@tscircuit/fake-snippets 0.0.66 → 0.0.67
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-tests/fake-snippets-api/fixtures/get-circuit-json.ts +5 -143
- package/bun-tests/fake-snippets-api/fixtures/get-test-server.ts +1 -4
- package/bun-tests/fake-snippets-api/fixtures/start-server.ts +7 -3
- package/bun-tests/fake-snippets-api/routes/order_quotes/create.test.ts +20 -56
- package/bun-tests/fake-snippets-api/routes/package_files/create_or_update.test.ts +2 -2
- package/bun-tests/fake-snippets-api/routes/package_releases/update.test.ts +1 -1
- package/bun-tests/fake-snippets-api/routes/packages/images.test.ts +0 -11
- package/bun.lock +15 -17
- package/dist/bundle.js +32 -39
- package/fake-snippets-api/routes/api/order_quotes/create.ts +30 -37
- package/fake-snippets-api/routes/api/order_quotes/get.ts +5 -8
- package/package.json +4 -3
- package/src/App.tsx +0 -7
- package/src/ContextProviders.tsx +2 -0
- package/src/components/DownloadButtonAndMenu.tsx +1 -4
- package/src/components/Footer.tsx +5 -2
- package/src/components/HeaderLogin.tsx +37 -54
- package/src/components/ImageWithFallback.tsx +37 -0
- package/src/components/JLCPCBImportDialog.tsx +43 -24
- package/src/components/PackageCard.tsx +2 -2
- package/src/components/{SnippetLink.tsx → PackageLink.tsx} +8 -16
- package/src/components/PackageSearchResults.tsx +87 -0
- package/src/components/PackagesList.tsx +3 -3
- package/src/components/PageSearchComponent.tsx +9 -9
- package/src/components/ViewPackagePage/components/ShikiCodeViewer.tsx +5 -28
- package/src/components/ViewPackagePage/components/main-content-header.tsx +8 -8
- package/src/components/ViewPackagePage/components/mobile-sidebar.tsx +24 -14
- package/src/components/ViewPackagePage/components/package-header.tsx +6 -1
- package/src/components/package-port/CodeEditor.tsx +13 -10
- package/src/components/package-port/CodeEditorHeader.tsx +1 -1
- package/src/components/package-port/EditorNav.tsx +2 -2
- package/src/hooks/use-global-store.ts +1 -0
- package/src/hooks/use-shiki-highlighter.ts +13 -6
- package/src/lib/download-fns/download-gltf.ts +3 -10
- package/src/lib/handleManualEditsImport.tsx +1 -1
- package/src/lib/types.ts +4 -2
- package/src/pages/dashboard.tsx +3 -4
- package/src/pages/editor.tsx +20 -14
- package/src/pages/latest.tsx +25 -26
- package/src/pages/search.tsx +120 -19
- package/src/pages/trending.tsx +14 -58
- package/src/pages/user-profile.tsx +13 -8
- package/bun-tests/fake-snippets-api/routes/snippets/add_star.test.ts +0 -84
- package/bun-tests/fake-snippets-api/routes/snippets/create.test.ts +0 -53
- package/bun-tests/fake-snippets-api/routes/snippets/delete.test.ts +0 -82
- package/bun-tests/fake-snippets-api/routes/snippets/download.test.ts +0 -90
- package/bun-tests/fake-snippets-api/routes/snippets/generate_from_jlcpcb.test.ts +0 -16
- package/bun-tests/fake-snippets-api/routes/snippets/get.test.ts +0 -163
- package/bun-tests/fake-snippets-api/routes/snippets/get_image.test.ts +0 -117
- package/bun-tests/fake-snippets-api/routes/snippets/images.test.ts +0 -114
- package/bun-tests/fake-snippets-api/routes/snippets/list.test.ts +0 -169
- package/bun-tests/fake-snippets-api/routes/snippets/list_newest.test.ts +0 -50
- package/bun-tests/fake-snippets-api/routes/snippets/list_trending.test.ts +0 -72
- package/bun-tests/fake-snippets-api/routes/snippets/remove_star.test.ts +0 -80
- package/bun-tests/fake-snippets-api/routes/snippets/search.test.ts +0 -75
- package/bun-tests/fake-snippets-api/routes/snippets/star-count.test.ts +0 -51
- package/bun-tests/fake-snippets-api/routes/snippets/update.test.ts +0 -175
- package/src/components/AiChatInterface.tsx +0 -229
- package/src/components/CodeAndPreview.tsx +0 -289
- package/src/components/CodeEditor.tsx +0 -539
- package/src/components/CodeEditorHeader.tsx +0 -135
- package/src/components/EditorNav.tsx +0 -502
- package/src/components/PreviewContent.tsx +0 -372
- package/src/components/SnippetCard.tsx +0 -159
- package/src/components/SnippetList.tsx +0 -71
- package/src/hooks/use-compiled-tsx.ts +0 -37
- package/src/hooks/use-run-tsx/construct-circuit.tsx +0 -62
- package/src/hooks/use-run-tsx/index.tsx +0 -256
- package/src/hooks/use-save-snippet.ts +0 -66
- package/src/hooks/use-typecheck.ts +0 -54
- package/src/lib/utils/getSyntaxError.ts +0 -13
- package/src/pages/ai.tsx +0 -92
- package/src/pages/view-snippet.tsx +0 -166
|
@@ -1,502 +0,0 @@
|
|
|
1
|
-
import { Button } from "@/components/ui/button"
|
|
2
|
-
import { GitFork } from "lucide-react"
|
|
3
|
-
import {
|
|
4
|
-
DropdownMenu,
|
|
5
|
-
DropdownMenuContent,
|
|
6
|
-
DropdownMenuItem,
|
|
7
|
-
DropdownMenuSub,
|
|
8
|
-
DropdownMenuSubContent,
|
|
9
|
-
DropdownMenuSubTrigger,
|
|
10
|
-
DropdownMenuTrigger,
|
|
11
|
-
} from "@/components/ui/dropdown-menu"
|
|
12
|
-
import { useGlobalStore } from "@/hooks/use-global-store"
|
|
13
|
-
import { encodeTextToUrlHash } from "@/lib/encodeTextToUrlHash"
|
|
14
|
-
import { cn } from "@/lib/utils"
|
|
15
|
-
import { OpenInNewWindowIcon, LockClosedIcon } from "@radix-ui/react-icons"
|
|
16
|
-
import { AnyCircuitElement } from "circuit-json"
|
|
17
|
-
import { Snippet } from "fake-snippets-api/lib/db/schema"
|
|
18
|
-
import {
|
|
19
|
-
ChevronDown,
|
|
20
|
-
CodeIcon,
|
|
21
|
-
Download,
|
|
22
|
-
Edit2,
|
|
23
|
-
Eye,
|
|
24
|
-
EyeIcon,
|
|
25
|
-
File,
|
|
26
|
-
FilePenLine,
|
|
27
|
-
MoreVertical,
|
|
28
|
-
Package,
|
|
29
|
-
Pencil,
|
|
30
|
-
Save,
|
|
31
|
-
Share,
|
|
32
|
-
Sidebar,
|
|
33
|
-
Sparkles,
|
|
34
|
-
Trash2,
|
|
35
|
-
} from "lucide-react"
|
|
36
|
-
import { useEffect, useState } from "react"
|
|
37
|
-
import { useMutation, useQueryClient } from "react-query"
|
|
38
|
-
import { Link, useLocation } from "wouter"
|
|
39
|
-
import { useAxios } from "../hooks/use-axios"
|
|
40
|
-
import { useToast } from "../hooks/use-toast"
|
|
41
|
-
import { useConfirmDeletePackageDialog } from "./dialogs/confirm-delete-package-dialog"
|
|
42
|
-
import { useCreateOrderDialog } from "./dialogs/create-order-dialog"
|
|
43
|
-
import { useFilesDialog } from "./dialogs/files-dialog"
|
|
44
|
-
import { useViewTsFilesDialog } from "./dialogs/view-ts-files-dialog"
|
|
45
|
-
import { useRenameSnippetDialog } from "./dialogs/rename-snippet-dialog"
|
|
46
|
-
import { DownloadButtonAndMenu } from "./DownloadButtonAndMenu"
|
|
47
|
-
import { SnippetLink } from "./SnippetLink"
|
|
48
|
-
import { TypeBadge } from "./TypeBadge"
|
|
49
|
-
import { useUpdateDescriptionDialog } from "./dialogs/edit-description-dialog"
|
|
50
|
-
import { useForkSnippetMutation } from "@/hooks/useForkSnippetMutation"
|
|
51
|
-
import tscircuitCorePkg from "@tscircuit/core/package.json"
|
|
52
|
-
|
|
53
|
-
export default function EditorNav({
|
|
54
|
-
circuitJson,
|
|
55
|
-
snippet,
|
|
56
|
-
code,
|
|
57
|
-
hasUnsavedChanges,
|
|
58
|
-
onTogglePreview,
|
|
59
|
-
previewOpen,
|
|
60
|
-
onSave,
|
|
61
|
-
snippetType,
|
|
62
|
-
isSaving,
|
|
63
|
-
canSave,
|
|
64
|
-
}: {
|
|
65
|
-
snippet?: Snippet | null
|
|
66
|
-
circuitJson?: AnyCircuitElement[] | null
|
|
67
|
-
code: string
|
|
68
|
-
snippetType?: string
|
|
69
|
-
hasUnsavedChanges: boolean
|
|
70
|
-
previewOpen: boolean
|
|
71
|
-
onTogglePreview: () => void
|
|
72
|
-
isSaving: boolean
|
|
73
|
-
onSave: () => void
|
|
74
|
-
canSave: boolean
|
|
75
|
-
}) {
|
|
76
|
-
const [, navigate] = useLocation()
|
|
77
|
-
const isLoggedIn = useGlobalStore((s) => Boolean(s.session))
|
|
78
|
-
const session = useGlobalStore((s) => s.session)
|
|
79
|
-
const { Dialog: RenameDialog, openDialog: openRenameDialog } =
|
|
80
|
-
useRenameSnippetDialog()
|
|
81
|
-
const {
|
|
82
|
-
Dialog: UpdateDescriptionDialog,
|
|
83
|
-
openDialog: openupdateDescriptionDialog,
|
|
84
|
-
} = useUpdateDescriptionDialog()
|
|
85
|
-
const { Dialog: DeleteDialog, openDialog: openDeleteDialog } =
|
|
86
|
-
useConfirmDeletePackageDialog()
|
|
87
|
-
const { Dialog: CreateOrderDialog, openDialog: openCreateOrderDialog } =
|
|
88
|
-
useCreateOrderDialog()
|
|
89
|
-
const { Dialog: FilesDialog, openDialog: openFilesDialog } = useFilesDialog()
|
|
90
|
-
const { Dialog: ViewTsFilesDialog, openDialog: openViewTsFilesDialog } =
|
|
91
|
-
useViewTsFilesDialog()
|
|
92
|
-
|
|
93
|
-
const [isChangingType, setIsChangingType] = useState(false)
|
|
94
|
-
const [currentType, setCurrentType] = useState(
|
|
95
|
-
snippetType ?? snippet?.snippet_type,
|
|
96
|
-
)
|
|
97
|
-
const [isPrivate, setIsPrivate] = useState(snippet?.is_private)
|
|
98
|
-
const axios = useAxios()
|
|
99
|
-
const { toast } = useToast()
|
|
100
|
-
const qc = useQueryClient()
|
|
101
|
-
|
|
102
|
-
const { mutate: forkSnippet, isLoading: isForking } = useForkSnippetMutation({
|
|
103
|
-
snippet: snippet!,
|
|
104
|
-
currentCode: code,
|
|
105
|
-
onSuccess: (forkedSnippet) => {
|
|
106
|
-
navigate("/editor?snippet_id=" + forkedSnippet.snippet_id)
|
|
107
|
-
setTimeout(() => {
|
|
108
|
-
window.location.reload() //reload the page
|
|
109
|
-
}, 2000)
|
|
110
|
-
},
|
|
111
|
-
})
|
|
112
|
-
|
|
113
|
-
// Update currentType when snippet or snippetType changes
|
|
114
|
-
useEffect(() => {
|
|
115
|
-
setCurrentType(snippetType ?? snippet?.snippet_type)
|
|
116
|
-
}, [snippetType, snippet?.snippet_type])
|
|
117
|
-
|
|
118
|
-
const handleTypeChange = async (newType: string) => {
|
|
119
|
-
if (!snippet || newType === currentType) return
|
|
120
|
-
|
|
121
|
-
try {
|
|
122
|
-
setIsChangingType(true)
|
|
123
|
-
|
|
124
|
-
const response = await axios.post("/snippets/update", {
|
|
125
|
-
snippet_id: snippet.snippet_id,
|
|
126
|
-
snippet_type: newType,
|
|
127
|
-
})
|
|
128
|
-
|
|
129
|
-
if (response.status === 200) {
|
|
130
|
-
setCurrentType(newType)
|
|
131
|
-
toast({
|
|
132
|
-
title: "Snippet type changed",
|
|
133
|
-
description: `Successfully changed type to "${newType}"`,
|
|
134
|
-
})
|
|
135
|
-
|
|
136
|
-
// Invalidate queries to refetch data
|
|
137
|
-
await Promise.all([
|
|
138
|
-
qc.invalidateQueries({ queryKey: ["snippets"] }),
|
|
139
|
-
qc.invalidateQueries({ queryKey: ["snippets", snippet.snippet_id] }),
|
|
140
|
-
])
|
|
141
|
-
|
|
142
|
-
// Reload the page to ensure all components reflect the new type
|
|
143
|
-
// window.location.reload()
|
|
144
|
-
} else {
|
|
145
|
-
throw new Error("Failed to update snippet type")
|
|
146
|
-
}
|
|
147
|
-
} catch (error: any) {
|
|
148
|
-
console.error("Error changing snippet type:", error)
|
|
149
|
-
toast({
|
|
150
|
-
title: "Error",
|
|
151
|
-
description:
|
|
152
|
-
error.response?.data?.error?.message ||
|
|
153
|
-
"Failed to change the snippet type. Please try again.",
|
|
154
|
-
variant: "destructive",
|
|
155
|
-
})
|
|
156
|
-
// Reset to previous type on error
|
|
157
|
-
setCurrentType(snippet.snippet_type)
|
|
158
|
-
} finally {
|
|
159
|
-
setIsChangingType(false)
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
const updatePackageVisibilityToPrivate = async (isPrivate: boolean) => {
|
|
164
|
-
if (!snippet) return
|
|
165
|
-
|
|
166
|
-
const response = await axios.post("/snippets/update", {
|
|
167
|
-
snippet_id: snippet.snippet_id,
|
|
168
|
-
is_private: isPrivate,
|
|
169
|
-
})
|
|
170
|
-
|
|
171
|
-
if (response.status === 200) {
|
|
172
|
-
setIsPrivate(isPrivate)
|
|
173
|
-
toast({
|
|
174
|
-
title: "Package visibility changed",
|
|
175
|
-
description: `Successfully changed visibility to ${isPrivate ? "private" : "public"}`,
|
|
176
|
-
})
|
|
177
|
-
} else {
|
|
178
|
-
setIsPrivate(snippet.is_private)
|
|
179
|
-
toast({
|
|
180
|
-
title: "Error",
|
|
181
|
-
description: "Failed to update package visibility",
|
|
182
|
-
variant: "destructive",
|
|
183
|
-
})
|
|
184
|
-
throw new Error("Failed to update package visibility")
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
const canSaveSnippet =
|
|
189
|
-
!snippet || snippet.owner_name === session?.github_username
|
|
190
|
-
|
|
191
|
-
return (
|
|
192
|
-
<nav className="lg:flex w-screen items-center justify-between px-2 py-3 border-b border-gray-200 bg-white text-sm border-t">
|
|
193
|
-
<div className="lg:flex items-center my-2 ">
|
|
194
|
-
<div className="flex items-center space-x-1">
|
|
195
|
-
{snippet && (
|
|
196
|
-
<>
|
|
197
|
-
<SnippetLink snippet={snippet} />
|
|
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
|
-
)}
|
|
208
|
-
{isPrivate && (
|
|
209
|
-
<div className="relative group">
|
|
210
|
-
<LockClosedIcon className="h-3 w-3 text-gray-700" />
|
|
211
|
-
<span className="absolute bottom-full left-1/2 transform -translate-x-1/2 mb-1 hidden group-hover:block bg-black text-white text-xs rounded py-1 px-2">
|
|
212
|
-
private
|
|
213
|
-
</span>
|
|
214
|
-
</div>
|
|
215
|
-
)}
|
|
216
|
-
<Link href={`/${snippet.name}`}>
|
|
217
|
-
<Button variant="ghost" size="icon" className="h-6 w-6">
|
|
218
|
-
<OpenInNewWindowIcon className="h-3 w-3 text-gray-700" />
|
|
219
|
-
</Button>
|
|
220
|
-
</Link>
|
|
221
|
-
</>
|
|
222
|
-
)}
|
|
223
|
-
</div>
|
|
224
|
-
<div className="flex items-center space-x-1">
|
|
225
|
-
{!isLoggedIn && (
|
|
226
|
-
<div className="bg-orange-100 text-orange-700 py-1 px-2 text-xs opacity-70">
|
|
227
|
-
Not logged in, can't save
|
|
228
|
-
</div>
|
|
229
|
-
)}
|
|
230
|
-
<Button
|
|
231
|
-
variant="outline"
|
|
232
|
-
size="sm"
|
|
233
|
-
className={"ml-1 h-6 px-2 text-xs save-button"}
|
|
234
|
-
disabled={!isLoggedIn}
|
|
235
|
-
onClick={canSaveSnippet ? onSave : () => forkSnippet()}
|
|
236
|
-
>
|
|
237
|
-
{canSaveSnippet ? (
|
|
238
|
-
<>
|
|
239
|
-
<Save className="mr-1 h-3 w-3" />
|
|
240
|
-
Save
|
|
241
|
-
</>
|
|
242
|
-
) : (
|
|
243
|
-
<>
|
|
244
|
-
<GitFork className="mr-1 h-3 w-3" />
|
|
245
|
-
Fork
|
|
246
|
-
</>
|
|
247
|
-
)}
|
|
248
|
-
</Button>
|
|
249
|
-
{isSaving && (
|
|
250
|
-
<div className="animate-fadeIn bg-blue-100 text-blue-800 text-xs font-medium px-2.5 py-0.5 rounded flex items-center">
|
|
251
|
-
<svg
|
|
252
|
-
className="animate-spin h-3 w-3 mr-2 text-blue-600"
|
|
253
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
254
|
-
fill="none"
|
|
255
|
-
viewBox="0 0 24 24"
|
|
256
|
-
>
|
|
257
|
-
<circle
|
|
258
|
-
className="opacity-25"
|
|
259
|
-
cx="12"
|
|
260
|
-
cy="12"
|
|
261
|
-
r="10"
|
|
262
|
-
stroke="currentColor"
|
|
263
|
-
strokeWidth="4"
|
|
264
|
-
></circle>
|
|
265
|
-
<path
|
|
266
|
-
className="opacity-75"
|
|
267
|
-
fill="currentColor"
|
|
268
|
-
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
|
269
|
-
></path>
|
|
270
|
-
</svg>
|
|
271
|
-
Saving...
|
|
272
|
-
</div>
|
|
273
|
-
)}
|
|
274
|
-
{hasUnsavedChanges && !isSaving && isLoggedIn && (
|
|
275
|
-
<div className="animate-fadeIn bg-yellow-100 text-yellow-800 text-xs font-medium px-2.5 py-0.5 rounded">
|
|
276
|
-
{snippet ? "unsaved changes" : "unsaved"}
|
|
277
|
-
</div>
|
|
278
|
-
)}
|
|
279
|
-
</div>
|
|
280
|
-
</div>
|
|
281
|
-
<div className="flex items-center justify-end -space-x-1">
|
|
282
|
-
<div className="flex mx-2 items-center space-x-1">
|
|
283
|
-
{snippet && <TypeBadge type={snippetType ?? snippet.snippet_type} />}
|
|
284
|
-
<Button
|
|
285
|
-
variant="ghost"
|
|
286
|
-
size="sm"
|
|
287
|
-
disabled={hasUnsavedChanges || isSaving || !snippet}
|
|
288
|
-
onClick={() => navigate(`/ai?snippet_id=${snippet!.snippet_id}`)}
|
|
289
|
-
>
|
|
290
|
-
<Sparkles className="mr-1 h-3 w-3" />
|
|
291
|
-
Edit with AI
|
|
292
|
-
</Button>
|
|
293
|
-
<DownloadButtonAndMenu
|
|
294
|
-
snippetUnscopedName={snippet?.unscoped_name}
|
|
295
|
-
circuitJson={circuitJson}
|
|
296
|
-
className="hidden md:flex"
|
|
297
|
-
/>
|
|
298
|
-
<Button
|
|
299
|
-
variant="ghost"
|
|
300
|
-
size="sm"
|
|
301
|
-
className="hidden md:flex px-2 text-xs"
|
|
302
|
-
onClick={() => {
|
|
303
|
-
const url = encodeTextToUrlHash(code, snippetType)
|
|
304
|
-
navigator.clipboard.writeText(url)
|
|
305
|
-
alert("URL copied to clipboard!")
|
|
306
|
-
}}
|
|
307
|
-
>
|
|
308
|
-
<Share className="mr-1 h-3 w-3" />
|
|
309
|
-
Copy URL
|
|
310
|
-
</Button>
|
|
311
|
-
{/* <Button
|
|
312
|
-
variant="ghost"
|
|
313
|
-
size="sm"
|
|
314
|
-
className="hidden md:flex px-2 text-xs"
|
|
315
|
-
>
|
|
316
|
-
<Eye className="mr-1 h-3 w-3" />
|
|
317
|
-
Public
|
|
318
|
-
</Button> */}
|
|
319
|
-
{snippet && (
|
|
320
|
-
<DropdownMenu>
|
|
321
|
-
<DropdownMenuTrigger asChild>
|
|
322
|
-
<Button variant="ghost" size="icon" className="hidden md:flex">
|
|
323
|
-
<MoreVertical className="h-3 w-3" />
|
|
324
|
-
</Button>
|
|
325
|
-
</DropdownMenuTrigger>
|
|
326
|
-
<DropdownMenuContent>
|
|
327
|
-
<DropdownMenuItem
|
|
328
|
-
className="text-xs"
|
|
329
|
-
onClick={() => openCreateOrderDialog()}
|
|
330
|
-
>
|
|
331
|
-
<Package className="mr-2 h-3 w-3" />
|
|
332
|
-
Submit Order
|
|
333
|
-
</DropdownMenuItem>
|
|
334
|
-
<DropdownMenuItem
|
|
335
|
-
className="text-xs"
|
|
336
|
-
onClick={() => openFilesDialog()}
|
|
337
|
-
>
|
|
338
|
-
<File className="mr-2 h-3 w-3" />
|
|
339
|
-
View Files
|
|
340
|
-
</DropdownMenuItem>
|
|
341
|
-
{snippet?.owner_name === session?.github_username && (
|
|
342
|
-
<DropdownMenuItem
|
|
343
|
-
className="text-xs"
|
|
344
|
-
onClick={() => openupdateDescriptionDialog()}
|
|
345
|
-
>
|
|
346
|
-
<FilePenLine className="mr-2 h-3 w-3" />
|
|
347
|
-
Edit Description
|
|
348
|
-
</DropdownMenuItem>
|
|
349
|
-
)}
|
|
350
|
-
|
|
351
|
-
<DropdownMenuItem
|
|
352
|
-
className="text-xs"
|
|
353
|
-
onClick={() => openViewTsFilesDialog()}
|
|
354
|
-
>
|
|
355
|
-
<File className="mr-2 h-3 w-3" />
|
|
356
|
-
[Debug] View TS Files
|
|
357
|
-
</DropdownMenuItem>
|
|
358
|
-
{snippet?.owner_name === session?.github_username && (
|
|
359
|
-
<>
|
|
360
|
-
<DropdownMenuSub>
|
|
361
|
-
<DropdownMenuSubTrigger
|
|
362
|
-
className="text-xs"
|
|
363
|
-
disabled={isChangingType || hasUnsavedChanges}
|
|
364
|
-
>
|
|
365
|
-
<Edit2 className="mr-2 h-3 w-3" />
|
|
366
|
-
{isChangingType ? "Changing..." : "Change Type"}
|
|
367
|
-
</DropdownMenuSubTrigger>
|
|
368
|
-
<DropdownMenuSubContent>
|
|
369
|
-
<DropdownMenuItem
|
|
370
|
-
className="text-xs"
|
|
371
|
-
disabled={currentType === "board" || isChangingType}
|
|
372
|
-
onClick={() => handleTypeChange("board")}
|
|
373
|
-
>
|
|
374
|
-
Board {currentType === "board" && "✓"}
|
|
375
|
-
</DropdownMenuItem>
|
|
376
|
-
<DropdownMenuItem
|
|
377
|
-
className="text-xs"
|
|
378
|
-
disabled={currentType === "package" || isChangingType}
|
|
379
|
-
onClick={() => handleTypeChange("package")}
|
|
380
|
-
>
|
|
381
|
-
Module {currentType === "package" && "✓"}
|
|
382
|
-
</DropdownMenuItem>
|
|
383
|
-
</DropdownMenuSubContent>
|
|
384
|
-
</DropdownMenuSub>
|
|
385
|
-
<DropdownMenuSub>
|
|
386
|
-
<DropdownMenuSubTrigger className="text-xs">
|
|
387
|
-
<Edit2 className="mr-2 h-3 w-3" />
|
|
388
|
-
Change Package Visibility
|
|
389
|
-
</DropdownMenuSubTrigger>
|
|
390
|
-
<DropdownMenuSubContent>
|
|
391
|
-
<DropdownMenuItem
|
|
392
|
-
className="text-xs"
|
|
393
|
-
disabled={isPrivate}
|
|
394
|
-
onClick={() => updatePackageVisibilityToPrivate(true)}
|
|
395
|
-
>
|
|
396
|
-
Private {isPrivate && "✓"}
|
|
397
|
-
</DropdownMenuItem>
|
|
398
|
-
<DropdownMenuItem
|
|
399
|
-
className="text-xs"
|
|
400
|
-
disabled={!isPrivate}
|
|
401
|
-
onClick={() =>
|
|
402
|
-
updatePackageVisibilityToPrivate(false)
|
|
403
|
-
}
|
|
404
|
-
>
|
|
405
|
-
Public {!isPrivate && "✓"}
|
|
406
|
-
</DropdownMenuItem>
|
|
407
|
-
</DropdownMenuSubContent>
|
|
408
|
-
</DropdownMenuSub>
|
|
409
|
-
<DropdownMenuItem
|
|
410
|
-
className="text-xs text-red-600"
|
|
411
|
-
onClick={() => openDeleteDialog()}
|
|
412
|
-
>
|
|
413
|
-
<Trash2 className="mr-2 h-3 w-3" />
|
|
414
|
-
Delete Snippet
|
|
415
|
-
</DropdownMenuItem>
|
|
416
|
-
</>
|
|
417
|
-
)}
|
|
418
|
-
|
|
419
|
-
<DropdownMenuItem className="text-xs text-gray-500" disabled>
|
|
420
|
-
@tscircuit/core@{tscircuitCorePkg.version}
|
|
421
|
-
</DropdownMenuItem>
|
|
422
|
-
</DropdownMenuContent>
|
|
423
|
-
</DropdownMenu>
|
|
424
|
-
)}
|
|
425
|
-
<Button
|
|
426
|
-
variant="ghost"
|
|
427
|
-
size="icon"
|
|
428
|
-
className={cn(
|
|
429
|
-
"hidden md:flex",
|
|
430
|
-
!previewOpen
|
|
431
|
-
? "bg-blue-600 text-white hover:bg-blue-700 hover:text-white"
|
|
432
|
-
: "",
|
|
433
|
-
)}
|
|
434
|
-
onClick={() => onTogglePreview()}
|
|
435
|
-
>
|
|
436
|
-
{previewOpen ? (
|
|
437
|
-
<Sidebar className="h-3 w-3" />
|
|
438
|
-
) : (
|
|
439
|
-
<EyeIcon className="h-3 w-3" />
|
|
440
|
-
)}
|
|
441
|
-
</Button>
|
|
442
|
-
</div>
|
|
443
|
-
<div className="flex items-center ">
|
|
444
|
-
<DropdownMenu>
|
|
445
|
-
<DropdownMenuTrigger asChild>
|
|
446
|
-
<button className="md:hidden inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 bg-secondary text-secondary-foreground hover:bg-secondary/80 h-9 px-4 py-2">
|
|
447
|
-
<ChevronDown className="h-4 w-4" />
|
|
448
|
-
</button>
|
|
449
|
-
</DropdownMenuTrigger>
|
|
450
|
-
<DropdownMenuContent>
|
|
451
|
-
<DropdownMenuItem className="text-xs">
|
|
452
|
-
<Download className="mr-1 h-3 w-3" />
|
|
453
|
-
Download
|
|
454
|
-
</DropdownMenuItem>
|
|
455
|
-
<DropdownMenuItem className="text-xs">
|
|
456
|
-
<Share className="mr-1 h-3 w-3" />
|
|
457
|
-
Copy URL
|
|
458
|
-
</DropdownMenuItem>
|
|
459
|
-
<DropdownMenuItem className="text-xs">
|
|
460
|
-
<Eye className="mr-1 h-3 w-3" />
|
|
461
|
-
Public
|
|
462
|
-
</DropdownMenuItem>
|
|
463
|
-
</DropdownMenuContent>
|
|
464
|
-
</DropdownMenu>
|
|
465
|
-
<Button
|
|
466
|
-
variant="ghost"
|
|
467
|
-
size="sm"
|
|
468
|
-
className="md:hidden"
|
|
469
|
-
onClick={() => onTogglePreview()}
|
|
470
|
-
>
|
|
471
|
-
{previewOpen ? (
|
|
472
|
-
<div className="flex items-center">
|
|
473
|
-
<CodeIcon className="h-3 w-3 mr-1" />
|
|
474
|
-
Show Code
|
|
475
|
-
</div>
|
|
476
|
-
) : (
|
|
477
|
-
<div className="flex items-center">
|
|
478
|
-
<EyeIcon className="h-3 w-3 mr-1" />
|
|
479
|
-
Show Preview
|
|
480
|
-
</div>
|
|
481
|
-
)}
|
|
482
|
-
</Button>
|
|
483
|
-
</div>
|
|
484
|
-
</div>
|
|
485
|
-
<UpdateDescriptionDialog
|
|
486
|
-
snippetId={snippet?.snippet_id ?? ""}
|
|
487
|
-
currentDescription={snippet?.description ?? ""}
|
|
488
|
-
/>
|
|
489
|
-
<RenameDialog
|
|
490
|
-
snippetId={snippet?.snippet_id ?? ""}
|
|
491
|
-
currentName={snippet?.unscoped_name ?? ""}
|
|
492
|
-
/>
|
|
493
|
-
<DeleteDialog
|
|
494
|
-
packageId={snippet?.snippet_id ?? ""}
|
|
495
|
-
packageName={snippet?.unscoped_name ?? ""}
|
|
496
|
-
/>
|
|
497
|
-
<CreateOrderDialog />
|
|
498
|
-
<FilesDialog snippetId={snippet?.snippet_id ?? ""} />
|
|
499
|
-
<ViewTsFilesDialog />
|
|
500
|
-
</nav>
|
|
501
|
-
)
|
|
502
|
-
}
|