@tscircuit/fake-snippets 0.0.89 → 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.
Files changed (39) hide show
  1. package/bun.lock +84 -108
  2. package/dist/bundle.js +493 -372
  3. package/fake-snippets-api/routes/api/autocomplete/create_autocomplete.ts +135 -0
  4. package/package.json +8 -10
  5. package/src/App.tsx +47 -2
  6. package/src/ContextProviders.tsx +0 -2
  7. package/src/components/CircuitJsonImportDialog.tsx +1 -1
  8. package/src/components/PackageBuildsPage/package-build-header.tsx +2 -12
  9. package/src/components/PageSearchComponent.tsx +2 -2
  10. package/src/components/SearchComponent.tsx +2 -2
  11. package/src/components/TrendingPackagesCarousel.tsx +2 -2
  12. package/src/components/dialogs/import-component-dialog.tsx +25 -0
  13. package/src/components/package-port/CodeAndPreview.tsx +1 -16
  14. package/src/components/package-port/CodeEditor.tsx +34 -8
  15. package/src/components/package-port/CodeEditorHeader.tsx +75 -13
  16. package/src/components/package-port/EditorNav.tsx +58 -65
  17. package/src/components/package-port/GlobalFindReplace.tsx +1 -1
  18. package/src/components/package-port/QuickOpen.tsx +1 -1
  19. package/src/hooks/use-axios.ts +2 -2
  20. package/src/hooks/use-code-completion-ai-api.ts +3 -3
  21. package/src/hooks/use-delete-package.ts +6 -2
  22. package/src/hooks/use-packages-base-api-url.ts +3 -0
  23. package/src/hooks/use-request-ai-review-mutation.ts +1 -1
  24. package/src/hooks/use-sign-in.ts +2 -2
  25. package/src/hooks/use-toast.tsx +1 -0
  26. package/src/hooks/useFileManagement.ts +10 -5
  27. package/src/lib/utils/findTargetFile.ts +1 -1
  28. package/src/lib/utils/package-utils.ts +10 -0
  29. package/src/main.tsx +0 -3
  30. package/src/pages/dashboard.tsx +12 -2
  31. package/src/pages/dev-login.tsx +2 -2
  32. package/src/pages/latest.tsx +2 -2
  33. package/src/pages/search.tsx +2 -2
  34. package/src/pages/trending.tsx +2 -2
  35. package/src/pages/user-profile.tsx +2 -2
  36. package/src/types/package.ts +4 -0
  37. package/vite.config.ts +0 -19
  38. package/src/build-watcher.ts +0 -52
  39. package/src/global.d.ts +0 -3
@@ -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 { useImportPackageDialog } from "@/components/dialogs/import-package-dialog"
4
+ import { useImportComponentDialog } from "@/components/dialogs/import-component-dialog"
5
5
  import { useToast } from "@/hooks/use-toast"
6
6
  import {
7
7
  DropdownMenu,
@@ -19,13 +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"
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"
29
32
 
30
33
  export type FileName = string
31
34
 
@@ -36,21 +39,28 @@ interface CodeEditorHeaderProps {
36
39
  fileSidebarState: ReturnType<typeof useState<boolean>>
37
40
  handleFileChange: (filename: FileName) => void
38
41
  entrypointFileName?: string
42
+ appendNewFile: (path: string, content: string) => void
43
+ createFile: (props: ICreateFileProps) => ICreateFileResult
44
+ aiAutocompleteState: [boolean, React.Dispatch<React.SetStateAction<boolean>>]
39
45
  }
40
46
 
41
47
  export const CodeEditorHeader: React.FC<CodeEditorHeaderProps> = ({
42
48
  currentFile,
43
49
  files,
44
50
  updateFileContent,
51
+ appendNewFile,
45
52
  fileSidebarState,
46
53
  handleFileChange,
47
54
  entrypointFileName = "index.tsx",
55
+ createFile,
56
+ aiAutocompleteState,
48
57
  }) => {
49
- const { Dialog: ImportPackageDialog, openDialog: openImportDialog } =
50
- useImportPackageDialog()
51
- const { toast } = useToast()
58
+ const { Dialog: ImportComponentDialog, openDialog: openImportDialog } =
59
+ useImportComponentDialog()
60
+ const { toast, toastLibrary } = useToast()
52
61
  const [sidebarOpen, setSidebarOpen] = fileSidebarState
53
- const [aiAutocompleteEnabled, setAiAutocompleteEnabled] = useState(false)
62
+ const API_BASE = usePackagesBaseApiUrl()
63
+ const [aiAutocompleteEnabled, setAiAutocompleteEnabled] = aiAutocompleteState
54
64
 
55
65
  const handleFormatFile = useCallback(() => {
56
66
  if (!window.prettier || !window.prettierPlugins) return
@@ -141,6 +151,49 @@ export const CodeEditorHeader: React.FC<CodeEditorHeaderProps> = ({
141
151
  }
142
152
  }, [currentFile, files, toast, updateFileContent])
143
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
+
144
197
  return (
145
198
  <>
146
199
  <div className="flex items-center gap-2 px-2 border-b border-gray-200">
@@ -239,15 +292,16 @@ export const CodeEditorHeader: React.FC<CodeEditorHeaderProps> = ({
239
292
  </DropdownMenuContent>
240
293
  </DropdownMenu>
241
294
  )}
295
+
242
296
  <TooltipProvider>
243
297
  <Tooltip>
244
298
  <TooltipTrigger asChild>
245
299
  <Button
246
300
  size="sm"
247
301
  variant="ghost"
248
- onClick={() =>
249
- setAiAutocompleteEnabled(!aiAutocompleteEnabled)
250
- }
302
+ onClick={() => {
303
+ setAiAutocompleteEnabled((prev) => !prev)
304
+ }}
251
305
  className={`relative bg-transparent ${aiAutocompleteEnabled ? "text-gray-600 bg-gray-50" : "text-gray-400"}`}
252
306
  >
253
307
  <Bot className="h-4 w-4" />
@@ -263,6 +317,7 @@ export const CodeEditorHeader: React.FC<CodeEditorHeaderProps> = ({
263
317
  </TooltipContent>
264
318
  </Tooltip>
265
319
  </TooltipProvider>
320
+
266
321
  <Button size="sm" variant="ghost" onClick={() => openImportDialog()}>
267
322
  Import
268
323
  </Button>
@@ -270,10 +325,17 @@ export const CodeEditorHeader: React.FC<CodeEditorHeaderProps> = ({
270
325
  Format
271
326
  </Button>
272
327
  </div>
273
- <ImportPackageDialog
274
- onPackageSelected={(pkg: Package) => {
275
- const newContent = `import {} from "@tsci/${pkg.owner_github_username}.${pkg.unscoped_name}"\n${files[currentFile || ""]}`
276
- updateFileContent(currentFile, newContent)
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
+ })
277
339
  }}
278
340
  />
279
341
  </div>
@@ -18,19 +18,16 @@ import { Package } from "fake-snippets-api/lib/db/schema"
18
18
  import {
19
19
  ChevronDown,
20
20
  CodeIcon,
21
- Download,
22
21
  Edit2,
23
22
  Eye,
24
23
  EyeIcon,
25
24
  File,
26
25
  FilePenLine,
27
26
  MoreVertical,
28
- Package as PackageIcon,
29
27
  Pencil,
30
28
  Save,
31
29
  Share,
32
30
  Sidebar,
33
- Sparkles,
34
31
  Trash2,
35
32
  Undo2,
36
33
  } from "lucide-react"
@@ -41,7 +38,6 @@ import { useAxios } from "@/hooks/use-axios"
41
38
  import { useHotkeyCombo } from "@/hooks/use-hotkey"
42
39
  import { useToast } from "@/hooks/use-toast"
43
40
  import { useConfirmDeletePackageDialog } from "@/components/dialogs/confirm-delete-package-dialog"
44
- import { useFilesDialog } from "@/components/dialogs/files-dialog"
45
41
  import { useViewTsFilesDialog } from "@/components/dialogs/view-ts-files-dialog"
46
42
  import { DownloadButtonAndMenu } from "@/components/DownloadButtonAndMenu"
47
43
  import { TypeBadge } from "@/components/TypeBadge"
@@ -86,7 +82,6 @@ export default function EditorNav({
86
82
  } = useUpdatePackageDescriptionDialog()
87
83
  const { Dialog: DeleteDialog, openDialog: openDeleteDialog } =
88
84
  useConfirmDeletePackageDialog()
89
- const { Dialog: FilesDialog, openDialog: openFilesDialog } = useFilesDialog()
90
85
  const { Dialog: ViewTsFilesDialog, openDialog: openViewTsFilesDialog } =
91
86
  useViewTsFilesDialog()
92
87
 
@@ -376,13 +371,6 @@ export default function EditorNav({
376
371
  </Button>
377
372
  </DropdownMenuTrigger>
378
373
  <DropdownMenuContent>
379
- <DropdownMenuItem
380
- className="text-xs"
381
- onClick={() => openFilesDialog()}
382
- >
383
- <File className="mr-2 h-3 w-3" />
384
- View Files
385
- </DropdownMenuItem>
386
374
  <DropdownMenuItem
387
375
  className="text-xs"
388
376
  onClick={() => openupdateDescriptionDialog()}
@@ -395,62 +383,68 @@ export default function EditorNav({
395
383
  onClick={() => openViewTsFilesDialog()}
396
384
  >
397
385
  <File className="mr-2 h-3 w-3" />
398
- [Debug] View TS Files
386
+ View Files
399
387
  </DropdownMenuItem>
400
- <DropdownMenuSub>
401
- <DropdownMenuSubTrigger
402
- className="text-xs"
403
- disabled={isChangingType || hasUnsavedChanges}
404
- >
405
- <Edit2 className="mr-2 h-3 w-3" />
406
- {isChangingType ? "Changing..." : "Change Type"}
407
- </DropdownMenuSubTrigger>
408
- <DropdownMenuSubContent>
409
- <DropdownMenuItem
410
- className="text-xs"
411
- disabled={currentType === "board" || isChangingType}
412
- onClick={() => handleTypeChange("board")}
413
- >
414
- Board {currentType === "board" && "✓"}
415
- </DropdownMenuItem>
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>
416
439
  <DropdownMenuItem
417
- className="text-xs"
418
- disabled={currentType === "package" || isChangingType}
419
- onClick={() => handleTypeChange("package")}
440
+ className="text-xs text-red-600"
441
+ onClick={() => openDeleteDialog()}
420
442
  >
421
- Module {currentType === "package" && "✓"}
443
+ <Trash2 className="mr-2 h-3 w-3" />
444
+ Delete Package
422
445
  </DropdownMenuItem>
423
- </DropdownMenuSubContent>
424
- </DropdownMenuSub>
425
- <DropdownMenuSub>
426
- <DropdownMenuSubTrigger className="text-xs">
427
- <Edit2 className="mr-2 h-3 w-3" />
428
- Change Package Visibility
429
- </DropdownMenuSubTrigger>
430
- <DropdownMenuSubContent>
431
- <DropdownMenuItem
432
- className="text-xs"
433
- disabled={isPrivate}
434
- onClick={() => updatePackageVisibilityToPrivate(true)}
435
- >
436
- Private {isPrivate && "✓"}
437
- </DropdownMenuItem>
438
- <DropdownMenuItem
439
- className="text-xs"
440
- disabled={!isPrivate}
441
- onClick={() => updatePackageVisibilityToPrivate(false)}
442
- >
443
- Public {!isPrivate && "✓"}
444
- </DropdownMenuItem>
445
- </DropdownMenuSubContent>
446
- </DropdownMenuSub>
447
- <DropdownMenuItem
448
- className="text-xs text-red-600"
449
- onClick={() => openDeleteDialog()}
450
- >
451
- <Trash2 className="mr-2 h-3 w-3" />
452
- Delete Package
453
- </DropdownMenuItem>
446
+ </>
447
+ )}
454
448
  <DropdownMenuItem className="text-xs text-gray-500" disabled>
455
449
  @tscircuit/core@{tscircuitCorePkg.version}
456
450
  </DropdownMenuItem>
@@ -566,7 +560,6 @@ export default function EditorNav({
566
560
  packageName={pkg?.unscoped_name ?? ""}
567
561
  packageOwner={pkg?.owner_github_username ?? ""}
568
562
  />
569
- <FilesDialog snippetId={pkg?.package_id ?? ""} />
570
563
  <ViewTsFilesDialog />
571
564
  </nav>
572
565
  )
@@ -23,7 +23,7 @@ import {
23
23
  TooltipProvider,
24
24
  TooltipTrigger,
25
25
  } from "@/components/ui/tooltip"
26
- import type { PackageFile } from "./CodeAndPreview"
26
+ import type { PackageFile } from "@/types/package"
27
27
  import { isHiddenFile } from "../ViewPackagePage/utils/is-hidden-file"
28
28
 
29
29
  interface Match {
@@ -8,7 +8,7 @@ import {
8
8
  BookOpen,
9
9
  FileText,
10
10
  } from "lucide-react"
11
- import type { PackageFile } from "./CodeAndPreview"
11
+ import type { PackageFile } from "@/types/package"
12
12
  import { fuzzyMatch } from "../ViewPackagePage/utils/fuzz-search"
13
13
 
14
14
  interface ScoredFile extends PackageFile {
@@ -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 = useSnippetsBaseApiUrl()
7
+ const snippetsBaseApiUrl = usePackagesBaseApiUrl()
8
8
  const session = useGlobalStore((s) => s.session)
9
9
  return useMemo(() => {
10
10
  const instance = axios.create({
@@ -1,11 +1,11 @@
1
1
  import { useMemo } from "react"
2
2
 
3
3
  export const useCodeCompletionApi = () => {
4
- const codeiumApiKey = useMemo(() => {
4
+ const openrouterApiKey = useMemo(() => {
5
5
  return {
6
- apiKey: import.meta.env.VITE_CODIUM_API_KEY,
6
+ apiKey: import.meta.env.VITE_OPENROUTER_API_KEY,
7
7
  }
8
8
  }, [])
9
9
 
10
- return codeiumApiKey
10
+ return openrouterApiKey
11
11
  }
@@ -1,4 +1,4 @@
1
- import { useMutation } from "react-query"
1
+ import { useMutation, useQueryClient } from "react-query"
2
2
  import { useAxios } from "./use-axios"
3
3
  import { useToast } from "./use-toast"
4
4
 
@@ -7,6 +7,7 @@ export const useDeletePackage = ({
7
7
  }: { onSuccess?: () => void } = {}) => {
8
8
  const axios = useAxios()
9
9
  const { toast } = useToast()
10
+ const queryClient = useQueryClient()
10
11
 
11
12
  return useMutation(
12
13
  ["deletePackage"],
@@ -22,11 +23,14 @@ export const useDeletePackage = ({
22
23
  return response.data
23
24
  },
24
25
  {
25
- onSuccess: () => {
26
+ onSuccess: (_, variables) => {
26
27
  toast({
27
28
  title: "Package deleted",
28
29
  description: "Package deleted successfully",
29
30
  })
31
+ if (variables?.package_id) {
32
+ queryClient.invalidateQueries(["packages", variables.package_id])
33
+ }
30
34
  onSuccess?.()
31
35
  },
32
36
  onError: (error: any) => {
@@ -0,0 +1,3 @@
1
+ export const usePackagesBaseApiUrl = () => {
2
+ return import.meta.env.VITE_SNIPPETS_API_URL ?? "/api"
3
+ }
@@ -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 generated.",
37
+ description: "An AI review has been requested.",
38
38
  })
39
39
  queryClient.invalidateQueries(["packageRelease"])
40
40
  onSuccess?.(package_release, ai_review)
@@ -1,9 +1,9 @@
1
1
  import { useGlobalStore } from "./use-global-store"
2
2
  import { useIsUsingFakeApi } from "./use-is-using-fake-api"
3
- import { useSnippetsBaseApiUrl } from "./use-snippets-base-api-url"
3
+ import { usePackagesBaseApiUrl } from "./use-packages-base-api-url"
4
4
 
5
5
  export const useSignIn = () => {
6
- const snippetsBaseApiUrl = useSnippetsBaseApiUrl()
6
+ const snippetsBaseApiUrl = usePackagesBaseApiUrl()
7
7
  const isUsingFakeApi = useIsUsingFakeApi()
8
8
  const setSession = useGlobalStore((s) => s.setSession)
9
9
  return () => {
@@ -63,6 +63,7 @@ function useToast() {
63
63
  return {
64
64
  toast,
65
65
  dismiss: toastLibrary.dismiss,
66
+ toastLibrary,
66
67
  }
67
68
  }
68
69
 
@@ -1,10 +1,10 @@
1
1
  import { useEffect, useMemo, useState, useCallback, useRef } from "react"
2
2
  import { isValidFileName } from "@/lib/utils/isValidFileName"
3
+ import { PackageFile } from "@/types/package"
3
4
  import {
4
5
  DEFAULT_CODE,
5
6
  generateRandomPackageName,
6
- PackageFile,
7
- } from "../components/package-port/CodeAndPreview"
7
+ } from "@/lib/utils/package-utils"
8
8
  import { Package } from "fake-snippets-api/lib/db/schema"
9
9
  import { usePackageFiles } from "./use-package-files"
10
10
  import { decodeUrlHashToText } from "@/lib/decodeUrlHashToText"
@@ -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
- // immediately select the newly created file
213
- setCurrentFile(newFileName)
216
+ if (openFile) {
217
+ setCurrentFile(newFileName)
218
+ }
214
219
  return {
215
220
  newFileCreated: true,
216
221
  }
@@ -1,4 +1,4 @@
1
- import { PackageFile } from "@/components/package-port/CodeAndPreview"
1
+ import { PackageFile } from "@/types/package"
2
2
 
3
3
  export const findMainEntrypointFileFromTscircuitConfig = (
4
4
  files: PackageFile[],
@@ -0,0 +1,10 @@
1
+ export const DEFAULT_CODE = `
2
+ export default () => (
3
+ <board width="10mm" height="10mm">
4
+ {/* write your code here! */}
5
+ </board>
6
+ )
7
+ `.trim()
8
+
9
+ export const generateRandomPackageName = () =>
10
+ `untitled-package-${Math.floor(Math.random() * 900) + 100}`
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>
@@ -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 { useSnippetsBaseApiUrl } from "@/hooks/use-snippets-base-api-url"
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"
@@ -61,6 +61,11 @@ export const DashboardPage = () => {
61
61
  const response = await axios.get("/packages/list_trending")
62
62
  return response.data.packages
63
63
  },
64
+ {
65
+ refetchOnWindowFocus: false,
66
+ refetchOnMount: false,
67
+ refetchOnReconnect: false,
68
+ },
64
69
  )
65
70
 
66
71
  const { data: latestPackages } = useQuery<Package[]>(
@@ -69,9 +74,14 @@ export const DashboardPage = () => {
69
74
  const response = await axios.get("/packages/list_latest")
70
75
  return response.data.packages
71
76
  },
77
+ {
78
+ refetchOnWindowFocus: false,
79
+ refetchOnMount: false,
80
+ refetchOnReconnect: false,
81
+ },
72
82
  )
73
83
 
74
- const baseUrl = useSnippetsBaseApiUrl()
84
+ const baseUrl = usePackagesBaseApiUrl()
75
85
 
76
86
  const handleDeleteClick = (e: React.MouseEvent, pkg: Package) => {
77
87
  e.preventDefault() // Prevent navigation
@@ -1,10 +1,10 @@
1
1
  import { useGlobalStore } from "@/hooks/use-global-store"
2
- import { useSnippetsBaseApiUrl } from "@/hooks/use-snippets-base-api-url"
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 = useSnippetsBaseApiUrl()
7
+ const snippetsBaseApiUrl = usePackagesBaseApiUrl()
8
8
  const [username, setUsername] = useState("")
9
9
  const setSession = useGlobalStore((s) => s.setSession)
10
10
  const [, setLocation] = useLocation()
@@ -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 { useSnippetsBaseApiUrl } from "@/hooks/use-snippets-base-api-url"
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 = useSnippetsBaseApiUrl()
21
+ const apiBaseUrl = usePackagesBaseApiUrl()
22
22
  const [searchQuery, setSearchQuery] = useState("")
23
23
  const [category, setCategory] = useState("all")
24
24
 
@@ -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 { useSnippetsBaseApiUrl } from "@/hooks/use-snippets-base-api-url"
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 = useSnippetsBaseApiUrl()
22
+ const apiBaseUrl = usePackagesBaseApiUrl()
23
23
  const [searchParams, setSearchParams] = useSearchParams()
24
24
 
25
25
  const [searchQuery, setSearchQuery] = useState(searchParams.get("q") || "")
@@ -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 { useSnippetsBaseApiUrl } from "@/hooks/use-snippets-base-api-url"
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 = useSnippetsBaseApiUrl()
22
+ const apiBaseUrl = usePackagesBaseApiUrl()
23
23
  const [searchParams, setSearchParams] = useSearchParams()
24
24
 
25
25
  const [searchQuery, setSearchQuery] = useState(searchParams.get("q") || "")
@@ -8,7 +8,7 @@ import { Input } from "@/components/ui/input"
8
8
  import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs"
9
9
  import { useAxios } from "@/hooks/use-axios"
10
10
  import { useGlobalStore } from "@/hooks/use-global-store"
11
- import { useSnippetsBaseApiUrl } from "@/hooks/use-snippets-base-api-url"
11
+ import { usePackagesBaseApiUrl } from "@/hooks/use-packages-base-api-url"
12
12
  import { GitHubLogoIcon } from "@radix-ui/react-icons"
13
13
  import type { Package } from "fake-snippets-api/lib/db/schema"
14
14
  import type React from "react"
@@ -95,7 +95,7 @@ export const UserProfilePage = () => {
95
95
  },
96
96
  )
97
97
 
98
- const baseUrl = useSnippetsBaseApiUrl()
98
+ const baseUrl = usePackagesBaseApiUrl()
99
99
 
100
100
  if (accountError) {
101
101
  return <NotFoundPage heading="User Not Found" />