@tscircuit/fake-snippets 0.0.44 → 0.0.45

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 (32) hide show
  1. package/bun.lock +43 -11
  2. package/dist/bundle.js +405 -335
  3. package/fake-snippets-api/routes/api/_fake/received_quotes.ts +66 -0
  4. package/fake-snippets-api/routes/api/package_releases/update.ts +25 -18
  5. package/package.json +2 -2
  6. package/src/components/CodeAndPreview.tsx +0 -1
  7. package/src/components/CodeEditor.tsx +0 -1
  8. package/src/components/CodeEditorHeader.tsx +0 -25
  9. package/src/components/EditorNav.tsx +10 -8
  10. package/src/components/ErrorOutline.tsx +35 -0
  11. package/src/components/FileSidebar.tsx +46 -16
  12. package/src/components/NotFound.tsx +37 -0
  13. package/src/components/PreviewContent.tsx +0 -6
  14. package/src/components/TrendingSnippetCarousel.tsx +1 -1
  15. package/src/components/ViewPackagePage/components/package-header.tsx +24 -3
  16. package/src/components/ViewPackagePage/utils/is-hidden-file.ts +0 -1
  17. package/src/components/dialogs/package-visibility-settings-dialog.tsx +10 -1
  18. package/src/components/dialogs/view-ts-files-dialog.tsx +0 -6
  19. package/src/components/package-port/CodeAndPreview.tsx +10 -8
  20. package/src/components/package-port/CodeEditor.tsx +26 -38
  21. package/src/components/package-port/CodeEditorHeader.tsx +117 -39
  22. package/src/components/package-port/EditorNav.tsx +10 -8
  23. package/src/components/ui/tree-view.tsx +5 -1
  24. package/src/{prettier.ts → lib/types.ts} +3 -1
  25. package/src/lib/utils/findTargetFile.ts +62 -0
  26. package/src/lib/utils/load-prettier.ts +3 -0
  27. package/src/pages/404.tsx +2 -33
  28. package/src/pages/package-editor.tsx +14 -3
  29. package/src/pages/user-profile.tsx +66 -27
  30. package/src/components/FootprintDialog.tsx +0 -339
  31. package/src/components/ParametersEditor.tsx +0 -140
  32. package/src/lib/utils/parseFootprintParams.ts +0 -52
@@ -0,0 +1,66 @@
1
+ import { withRouteSpec } from "fake-snippets-api/lib/middleware/with-winter-spec"
2
+ import { z } from "zod"
3
+ import { orderQuoteSchema } from "fake-snippets-api/lib/db/schema"
4
+
5
+ export default withRouteSpec({
6
+ methods: ["POST"],
7
+ auth: "session",
8
+ jsonBody: z.object({
9
+ order_quote_id: z.string(),
10
+ }),
11
+ jsonResponse: z.object({
12
+ order_quote: orderQuoteSchema.optional(),
13
+ error: z.string().optional(),
14
+ }),
15
+ })(async (req, ctx) => {
16
+ const { order_quote_id } = req.jsonBody
17
+
18
+ return ctx.json({
19
+ order_quote: {
20
+ order_quote_id,
21
+ account_id: "123",
22
+ package_release_id: "123",
23
+ is_completed: true,
24
+ is_processing: false,
25
+ vendor_name: "JLCPCB",
26
+ error: null,
27
+ has_error: false,
28
+ created_at: "2025-04-21",
29
+ updated_at: "2025-04-21",
30
+ completed_at: "2025-04-21",
31
+ quoted_components: [
32
+ {
33
+ manufacturer_part_number: "123",
34
+ supplier_part_number: "123",
35
+ quantity: 1,
36
+ unit_price: 100,
37
+ total_price: 100,
38
+ available: true,
39
+ },
40
+ {
41
+ manufacturer_part_number: "1234",
42
+ supplier_part_number: "1234",
43
+ quantity: 1,
44
+ unit_price: 200,
45
+ total_price: 200,
46
+ available: true,
47
+ },
48
+ ],
49
+ bare_pcb_cost: 300,
50
+ shipping_options: [
51
+ {
52
+ carrier: "DHL",
53
+ service: "Express",
54
+ cost: 100,
55
+ },
56
+ {
57
+ carrier: "FedEx",
58
+ service: "Express",
59
+ cost: 200,
60
+ },
61
+ ],
62
+ // TODO: shipping cost can vary so do the total cost calculation
63
+ total_cost: 100,
64
+ },
65
+ })
66
+ })
@@ -67,28 +67,35 @@ export default withRouteSpec({
67
67
  })
68
68
  }
69
69
 
70
- // Handle is_latest updates
71
- if (is_latest !== undefined && is_latest) {
72
- ctx.db.packageReleases
73
- .filter(
74
- (pr) =>
75
- pr.package_id === release.package_id &&
76
- pr.package_release_id !== releaseId &&
77
- pr.is_latest,
78
- )
79
- .forEach((pr) => {
80
- pr.is_latest = false
81
- })
82
- }
83
-
84
- // Update the release
85
- Object.assign(release, {
70
+ // Create updated release object
71
+ const updatedRelease = {
72
+ ...release,
86
73
  ...(is_locked !== undefined && { is_locked }),
87
74
  ...(is_latest !== undefined && { is_latest }),
88
75
  ...(license !== undefined && { license }),
89
- })
76
+ }
77
+
78
+ // Handle is_latest updates atomically
79
+ if (is_latest !== undefined && is_latest) {
80
+ // Get all releases for this package that are currently marked as latest
81
+ const otherLatestReleases = ctx.db.packageReleases.filter(
82
+ (pr) =>
83
+ pr.package_id === release.package_id &&
84
+ pr.package_release_id !== releaseId &&
85
+ pr.is_latest,
86
+ )
87
+
88
+ // Update all releases in a single operation
89
+ for (const latestRelease of otherLatestReleases) {
90
+ ctx.db.updatePackageRelease({
91
+ ...latestRelease,
92
+ is_latest: false,
93
+ })
94
+ }
95
+ }
90
96
 
91
- ctx.db.updatePackageRelease(release)
97
+ // Update the target release
98
+ ctx.db.updatePackageRelease(updatedRelease)
92
99
 
93
100
  return ctx.json({
94
101
  ok: true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tscircuit/fake-snippets",
3
- "version": "0.0.44",
3
+ "version": "0.0.45",
4
4
  "type": "module",
5
5
  "repository": {
6
6
  "type": "git",
@@ -136,7 +136,7 @@
136
136
  "@playwright/test": "^1.48.0",
137
137
  "@tscircuit/core": "^0.0.370",
138
138
  "@tscircuit/prompt-benchmarks": "^0.0.28",
139
- "@tscircuit/runframe": "^0.0.330",
139
+ "@tscircuit/runframe": "^0.0.357",
140
140
  "@types/babel__standalone": "^7.1.7",
141
141
  "@types/bun": "^1.1.10",
142
142
  "@types/country-list": "^2.1.4",
@@ -10,7 +10,6 @@ import { decodeUrlHashToText } from "@/lib/decodeUrlHashToText"
10
10
  import { getSnippetTemplate } from "@/lib/get-snippet-template"
11
11
  import { cn } from "@/lib/utils"
12
12
  import { parseJsonOrNull } from "@/lib/utils/parseJsonOrNull"
13
- import "@/prettier"
14
13
  import type { Snippet } from "fake-snippets-api/lib/db/schema"
15
14
  import { Loader2 } from "lucide-react"
16
15
  import { useEffect, useMemo, useState } from "react"
@@ -456,7 +456,6 @@ export const CodeEditor = ({
456
456
  ...(args as Parameters<typeof updateFileContent>),
457
457
  )
458
458
  }}
459
- cursorPosition={cursorPosition}
460
459
  />
461
460
  )}
462
461
  <div ref={editorRef} className="flex-1 overflow-auto" />
@@ -8,8 +8,6 @@ import {
8
8
  } from "@/components/ui/select"
9
9
  import { useImportSnippetDialog } from "./dialogs/import-snippet-dialog"
10
10
  import { useToast } from "@/hooks/use-toast"
11
- import { FootprintDialog } from "./FootprintDialog"
12
- import { useState } from "react"
13
11
  import {
14
12
  DropdownMenu,
15
13
  DropdownMenuContent,
@@ -27,7 +25,6 @@ interface CodeEditorHeaderProps {
27
25
  files: Record<FileName, string>
28
26
  handleFileChange: (filename: FileName) => void
29
27
  updateFileContent: (filename: FileName, content: string) => void
30
- cursorPosition: number | null
31
28
  }
32
29
 
33
30
  export const CodeEditorHeader = ({
@@ -35,11 +32,9 @@ export const CodeEditorHeader = ({
35
32
  files,
36
33
  handleFileChange,
37
34
  updateFileContent,
38
- cursorPosition,
39
35
  }: CodeEditorHeaderProps) => {
40
36
  const { Dialog: ImportSnippetDialog, openDialog: openImportDialog } =
41
37
  useImportSnippetDialog()
42
- const [footprintDialogOpen, setFootprintDialogOpen] = useState(false)
43
38
  const { toast } = useToast()
44
39
 
45
40
  const formatCurrentFile = () => {
@@ -120,18 +115,6 @@ export const CodeEditorHeader = ({
120
115
  </DropdownMenuContent>
121
116
  </DropdownMenu>
122
117
  )}
123
- <DropdownMenu>
124
- <DropdownMenuTrigger asChild>
125
- <Button size="sm" variant="ghost">
126
- Insert
127
- </Button>
128
- </DropdownMenuTrigger>
129
- <DropdownMenuContent>
130
- <DropdownMenuItem onClick={() => setFootprintDialogOpen(true)}>
131
- Chip
132
- </DropdownMenuItem>
133
- </DropdownMenuContent>
134
- </DropdownMenu>
135
118
  <Button size="sm" variant="ghost" onClick={() => openImportDialog()}>
136
119
  Import
137
120
  </Button>
@@ -145,14 +128,6 @@ export const CodeEditorHeader = ({
145
128
  updateFileContent(currentFile, newContent)
146
129
  }}
147
130
  />
148
- <FootprintDialog
149
- currentFile={currentFile}
150
- open={footprintDialogOpen}
151
- onOpenChange={setFootprintDialogOpen}
152
- updateFileContent={updateFileContent}
153
- files={files}
154
- cursorPosition={cursorPosition}
155
- />
156
131
  </div>
157
132
  )
158
133
  }
@@ -195,14 +195,16 @@ export default function EditorNav({
195
195
  {snippet && (
196
196
  <>
197
197
  <SnippetLink snippet={snippet} />
198
- <Button
199
- variant="ghost"
200
- size="icon"
201
- className="h-6 w-6 ml-2"
202
- onClick={() => openRenameDialog()}
203
- >
204
- <Pencil className="h-3 w-3 text-gray-700" />
205
- </Button>
198
+ {snippet?.owner_name === session?.github_username && (
199
+ <Button
200
+ variant="ghost"
201
+ size="icon"
202
+ className="h-6 w-6 ml-2"
203
+ onClick={() => openRenameDialog()}
204
+ >
205
+ <Pencil className="h-3 w-3 text-gray-700" />
206
+ </Button>
207
+ )}
206
208
  {isPrivate && (
207
209
  <div className="relative group">
208
210
  <LockClosedIcon className="h-3 w-3 text-gray-700" />
@@ -0,0 +1,35 @@
1
+ import { AlertCircle } from "lucide-react"
2
+
3
+ export function ErrorOutline({
4
+ error,
5
+ description,
6
+ }: { error?: Error; description?: string; children?: React.ReactNode }) {
7
+ return (
8
+ <div className="flex items-center justify-center p-4">
9
+ <div className="max-w-lg w-full mx-auto p-6 sm:p-8 bg-red-100/80 rounded-xl shadow-lg border border-red-500">
10
+ <div className="flex flex-col items-center text-center">
11
+ <AlertCircle className="h-10 w-10 text-red-700 mb-4" />
12
+ <h2 className="text-xl sm:text-2xl font-bold text-red-700 mb-3">
13
+ Something strange happened
14
+ </h2>
15
+ <p className="text-red-600 font-medium mb-6 text-sm sm:text-base">
16
+ {description ||
17
+ "An unexpected error occurred while processing your request."}{" "}
18
+ <br />
19
+ Please try again or contact support if the problem persists.
20
+ </p>
21
+ {error?.message && (
22
+ <details className="w-full text-left bg-red-50 p-3 rounded-md border border-red-200">
23
+ <summary className="text-sm font-medium text-red-800 cursor-pointer hover:text-red-900">
24
+ Show Error Details
25
+ </summary>
26
+ <pre className="mt-2 text-xs text-red-700 bg-transparent p-0 rounded overflow-auto whitespace-pre-wrap break-words">
27
+ {error.message}
28
+ </pre>
29
+ </details>
30
+ )}
31
+ </div>
32
+ </div>
33
+ </div>
34
+ )
35
+ }
@@ -2,6 +2,7 @@ import React, { useState } from "react"
2
2
  import { cn } from "@/lib/utils"
3
3
  import { File, Folder, PanelRightOpen } from "lucide-react"
4
4
  import { TreeView, TreeDataItem } from "@/components/ui/tree-view"
5
+ import { isHiddenFile } from "./ViewPackagePage/utils/is-hidden-file"
5
6
 
6
7
  type FileName = string
7
8
 
@@ -24,35 +25,63 @@ const FileSidebar: React.FC<FileSidebarProps> = ({
24
25
  const transformFilesToTreeData = (
25
26
  files: Record<FileName, string>,
26
27
  ): TreeDataItem[] => {
27
- const root: { [key: string]: TreeDataItem } = {}
28
+ type TreeNode = Omit<TreeDataItem, "children"> & {
29
+ children?: Record<string, TreeNode>
30
+ }
31
+ const root: Record<string, TreeNode> = {}
28
32
 
29
33
  Object.keys(files).forEach((path) => {
30
- const parts = path.split("/")
34
+ const startsWithSlash = path.startsWith("/")
35
+ const parts = (startsWithSlash ? path.slice(1) : path).trim().split("/")
31
36
  let current = root
32
37
 
33
- let currentPath = ""
34
38
  parts.forEach((part, index) => {
35
- const id = currentPath ? `${currentPath}/${part}` : part
36
- currentPath = id
37
-
38
- if (!current[part]) {
39
- const isFile = index === parts.length - 1
39
+ const isFile = index === parts.length - 1
40
+ const parentPath = parts.slice(0, index).join("/")
41
+ const currentPath = parentPath ? `${parentPath}/${part}` : part
42
+ const evaluatedFilePath = startsWithSlash
43
+ ? `/${currentPath}`
44
+ : currentPath
45
+ if (
46
+ !current[part] &&
47
+ (!isHiddenFile(currentPath) ||
48
+ isHiddenFile(
49
+ currentFile.startsWith("/") ? currentFile.slice(1) : currentFile,
50
+ ))
51
+ ) {
40
52
  current[part] = {
41
- id: id,
42
- name: part,
53
+ id: currentPath,
54
+ name: isFile ? part : part,
43
55
  icon: isFile ? File : Folder,
44
- onClick: isFile ? () => onFileSelect(id) : undefined,
56
+ onClick: isFile ? () => onFileSelect(evaluatedFilePath) : undefined,
57
+ draggable: isFile,
58
+ droppable: !isFile,
59
+ children: isFile ? undefined : {},
45
60
  }
46
61
  }
47
- current = (current[part] as any).children || (current[part] as any)
62
+
63
+ if (!isFile && current[part].children) {
64
+ current = current[part].children
65
+ }
48
66
  })
49
67
  })
50
68
 
51
- return Object.values(root)
69
+ // Convert the nested object structure to array structure
70
+ const convertToArray = (
71
+ items: Record<string, TreeNode>,
72
+ ): TreeDataItem[] => {
73
+ return Object.values(items).map((item) => ({
74
+ ...item,
75
+ children: item.children ? convertToArray(item.children) : undefined,
76
+ }))
77
+ }
78
+ return convertToArray(root).filter((x) => {
79
+ if (x.children?.length === 0) return false
80
+ return true
81
+ })
52
82
  }
53
83
 
54
84
  const treeData = transformFilesToTreeData(files)
55
-
56
85
  return (
57
86
  <div
58
87
  className={cn(
@@ -63,11 +92,12 @@ const FileSidebar: React.FC<FileSidebarProps> = ({
63
92
  >
64
93
  <button
65
94
  onClick={() => setSidebarOpen(!sidebarOpen)}
66
- className={`z-[99] mt-2 ml-2 text-black/60 scale-90 transition-opacity duration-200 ${!sidebarOpen ? "opacity-0 pointer-events-none" : "opacity-100"}`}
95
+ className={`z-[99] mt-2 ml-2 text-gray-400 scale-90 transition-opacity duration-200 ${
96
+ !sidebarOpen ? "opacity-0 pointer-events-none" : "opacity-100"
97
+ }`}
67
98
  >
68
99
  <PanelRightOpen />
69
100
  </button>
70
-
71
101
  <TreeView
72
102
  data={treeData}
73
103
  initialSelectedItemId={currentFile}
@@ -0,0 +1,37 @@
1
+ import { Button } from "@/components/ui/button"
2
+ import { PrefetchPageLink } from "@/components/PrefetchPageLink"
3
+
4
+ export function NotFound({ heading = "Page not found" }: { heading?: string }) {
5
+ return (
6
+ <section className="flex-1 flex items-center justify-center min-h-[90vh]">
7
+ <div className="container px-4 md:px-6 py-12 flex flex-col items-center text-center max-w-3xl">
8
+ <div className="mb-8 flex flex-col items-center justify-center">
9
+ <div className="mb-2">
10
+ <span className="text-3xl font-bold text-white bg-blue-500 px-4 py-2 rounded-md shadow-md inline-block">
11
+ 404
12
+ </span>
13
+ </div>
14
+ </div>
15
+ <h1 className="text-4xl font-extrabold tracking-tight lg:text-5xl mb-4">
16
+ {heading}
17
+ </h1>
18
+ <p className="text-xl text-muted-foreground mb-8">
19
+ The page you're looking for doesn't exist or has been moved to another
20
+ address.
21
+ </p>
22
+ <div className="flex flex-col sm:flex-row gap-4">
23
+ <PrefetchPageLink href="/">
24
+ <Button size="lg" className="bg-blue-500 hover:bg-blue-600">
25
+ Return Home
26
+ </Button>
27
+ </PrefetchPageLink>
28
+ <PrefetchPageLink href="/search">
29
+ <Button size="lg" variant="outline">
30
+ Search Packages
31
+ </Button>
32
+ </PrefetchPageLink>
33
+ </div>
34
+ </div>
35
+ </section>
36
+ )
37
+ }
@@ -55,12 +55,6 @@ export interface PreviewContentProps {
55
55
  onManualEditsFileContentChange?: (newmanualEditsFileContent: string) => void
56
56
  }
57
57
 
58
- declare global {
59
- interface Window {
60
- TSCIRCUIT_3D_OBJECT_REF: any
61
- }
62
- }
63
-
64
58
  export const PreviewContent = ({
65
59
  code,
66
60
  triggerRunTsx,
@@ -32,7 +32,7 @@ export const TrendingSnippetCarousel = () => {
32
32
  {trendingSnippets?.length ? (
33
33
  <>
34
34
  <div className="container mx-auto px-4">
35
- <h2 className="text-2xl font-semibold mb-6">Trending Snippets</h2>
35
+ <h2 className="text-2xl font-semibold mb-6">Trending Packages</h2>
36
36
  </div>
37
37
  <div
38
38
  className="flex gap-6 overflow-x-hidden relative"
@@ -8,8 +8,9 @@ import {
8
8
  } from "@/hooks/use-package-stars"
9
9
  import { LockClosedIcon } from "@radix-ui/react-icons"
10
10
  import { GitFork, Star } from "lucide-react"
11
- import { useToast } from "@/hooks/use-toast"
12
11
  import { Link } from "wouter"
12
+ import { useOrderDialog } from "@tscircuit/runframe"
13
+ import { useEffect } from "react"
13
14
 
14
15
  interface PackageInfo {
15
16
  name: string
@@ -37,8 +38,7 @@ export default function PackageHeader({
37
38
  const author = packageInfo?.owner_github_username
38
39
  const packageName = packageInfo?.unscoped_name
39
40
 
40
- const { toast } = useToast()
41
-
41
+ const { OrderDialog, isOpen, open, close, stage, setStage } = useOrderDialog()
42
42
  const { data: starData, isLoading: isStarDataLoading } =
43
43
  usePackageStarsByName(packageInfo?.name ?? null)
44
44
  const { addStar, removeStar } = usePackageStarMutationByName(
@@ -66,6 +66,12 @@ export default function PackageHeader({
66
66
  const isStarLoading =
67
67
  isStarDataLoading || addStar.isLoading || removeStar.isLoading
68
68
 
69
+ useEffect(() => {
70
+ window.TSCIRCUIT_REGISTRY_API_BASE_URL =
71
+ import.meta.env.VITE_TSCIRCUIT_REGISTRY_API_URL ??
72
+ `${window.location.origin}/api`
73
+ }, [])
74
+
69
75
  return (
70
76
  <header className="bg-white border-b border-gray-200 py-4">
71
77
  <div className="max-w-[1200px] mx-auto px-4">
@@ -103,6 +109,15 @@ export default function PackageHeader({
103
109
  )}
104
110
  </div>
105
111
  <div className="items-center space-x-2 hidden md:flex">
112
+ {/* WIP: add order button */}
113
+ {/* <Button
114
+ size="sm"
115
+ variant="default"
116
+ className="bg-blue-600 hover:bg-blue-700"
117
+ onClick={open}
118
+ >
119
+ Place Order
120
+ </Button> */}
106
121
  <Button
107
122
  variant="outline"
108
123
  size="sm"
@@ -165,6 +180,12 @@ export default function PackageHeader({
165
180
  </div>
166
181
  </div>
167
182
  </div>
183
+ <OrderDialog
184
+ isOpen={isOpen}
185
+ onClose={close}
186
+ stage={stage}
187
+ setStage={setStage}
188
+ />
168
189
  </header>
169
190
  )
170
191
  }
@@ -25,7 +25,6 @@ export const isHiddenFile = (filePath: string): boolean => {
25
25
  /\.eslintrc(\.[^/]*)?$/,
26
26
  /\.prettierrc(\.[^/]*)?$/,
27
27
  /\.babelrc$/,
28
- /tscircuit\.config\.json/,
29
28
  /tsconfig\.json$/,
30
29
  /jest\.config\.[^/]*$/,
31
30
  /vite\.config\.[^/]*$/,
@@ -1,6 +1,12 @@
1
1
  import { useState } from "react"
2
2
  import { Button } from "../ui/button"
3
- import { Dialog, DialogContent, DialogHeader, DialogTitle } from "../ui/dialog"
3
+ import {
4
+ Dialog,
5
+ DialogContent,
6
+ DialogHeader,
7
+ DialogTitle,
8
+ DialogDescription,
9
+ } from "../ui/dialog"
4
10
  import { Label } from "../ui/label"
5
11
  import { RadioGroup, RadioGroupItem } from "../ui/radio-group"
6
12
  import { createUseDialog } from "./create-use-dialog"
@@ -23,6 +29,9 @@ export const PackageVisibilitySettingsDialog = ({
23
29
  <DialogContent>
24
30
  <DialogHeader>
25
31
  <DialogTitle>Package Privacy Settings</DialogTitle>
32
+ <DialogDescription>
33
+ Control whether your package is publicly visible or private.
34
+ </DialogDescription>
26
35
  </DialogHeader>
27
36
  <div className="py-1">
28
37
  <RadioGroup
@@ -13,12 +13,6 @@ interface ViewTsFilesDialogProps {
13
13
  onOpenChange: (open: boolean) => void
14
14
  }
15
15
 
16
- declare global {
17
- interface Window {
18
- __DEBUG_CODE_EDITOR_FS_MAP: Map<string, string>
19
- }
20
- }
21
-
22
16
  export const ViewTsFilesDialog: React.FC<ViewTsFilesDialogProps> = ({
23
17
  open,
24
18
  onOpenChange,
@@ -9,7 +9,6 @@ import { decodeUrlHashToText } from "@/lib/decodeUrlHashToText"
9
9
  import { getSnippetTemplate } from "@/lib/get-snippet-template"
10
10
  import { cn } from "@/lib/utils"
11
11
  import { parseJsonOrNull } from "@/lib/utils/parseJsonOrNull"
12
- import "@/prettier"
13
12
  import type { Package } from "fake-snippets-api/lib/db/schema"
14
13
  import { Loader2 } from "lucide-react"
15
14
  import { useEffect, useMemo, useState } from "react"
@@ -23,12 +22,13 @@ import { useCreatePackageReleaseMutation } from "@/hooks/use-create-package-rele
23
22
  import { useUpdatePackageFilesMutation } from "@/hooks/useUpdatePackageFilesMutation"
24
23
  import { useUpdatePackageMutation } from "@/hooks/useUpdatePackageMutation"
25
24
  import { usePackageFilesLoader } from "@/hooks/usePackageFilesLoader"
25
+ import { findTargetFile } from "@/lib/utils/findTargetFile"
26
26
 
27
27
  interface Props {
28
28
  pkg?: Package
29
29
  }
30
30
 
31
- interface PackageFile {
31
+ export interface PackageFile {
32
32
  path: string
33
33
  content: string
34
34
  }
@@ -94,6 +94,8 @@ export function CodeAndPreview({ pkg }: Props) {
94
94
  const [isPrivate, setIsPrivate] = useState(false)
95
95
 
96
96
  const entryPointCode = useMemo(() => {
97
+ const entryPointFile = findTargetFile(pkgFilesWithContent, null)
98
+ if (entryPointFile && entryPointFile.content) return entryPointFile.content
97
99
  return (
98
100
  pkgFilesWithContent.find((x) => x.path === "index.tsx")?.content ??
99
101
  defaultCode
@@ -147,6 +149,10 @@ export function CodeAndPreview({ pkg }: Props) {
147
149
  const { data: loadedFiles, isLoading: isLoadingFiles } =
148
150
  usePackageFilesLoader(pkg)
149
151
 
152
+ const [pkgFilesLoaded, setPkgFilesLoaded] = useState<boolean>(
153
+ urlParams.package_id ? false : true,
154
+ )
155
+
150
156
  useEffect(() => {
151
157
  if (!pkgFiles.data?.length) {
152
158
  if (pkg && pkgFilesWithContent.length === 0) {
@@ -171,6 +177,7 @@ export function CodeAndPreview({ pkg }: Props) {
171
177
  }
172
178
 
173
179
  setPkgFilesWithContent(processedResults)
180
+ setPkgFilesLoaded(true)
174
181
  setInitialFilesLoad(processedResults)
175
182
  setLastRunCode(
176
183
  processedResults.find((x) => x.path === "index.tsx")?.content ??
@@ -185,12 +192,6 @@ export function CodeAndPreview({ pkg }: Props) {
185
192
  defaultCode,
186
193
  ])
187
194
 
188
- // useEffect(() => {
189
- // if (pkg && pkgFiles.data) {
190
- // loadPkgFiles()
191
- // }
192
- // }, [pkg, pkgFiles.data])
193
-
194
195
  const createPackageMutation = useCreatePackageMutation()
195
196
 
196
197
  const { mutate: createRelease, isLoading: isCreatingRelease } =
@@ -355,6 +356,7 @@ export function CodeAndPreview({ pkg }: Props) {
355
356
  )
356
357
  }}
357
358
  onDtsChange={setDts}
359
+ pkgFilesLoaded={pkgFilesLoaded}
358
360
  />
359
361
  </div>
360
362
  {showPreview && (