Skip to content

Commit

Permalink
refactor previewcontent
Browse files Browse the repository at this point in the history
  • Loading branch information
seveibar committed Oct 10, 2024
1 parent 9a5cab7 commit a5f30b8
Show file tree
Hide file tree
Showing 7 changed files with 171 additions and 59 deletions.
60 changes: 19 additions & 41 deletions src/components/CodeAndPreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@ import { useAxios } from "@/hooks/use-axios"
import { TypeBadge } from "./TypeBadge"
import { useToast } from "@/hooks/use-toast"
import { useMutation, useQueryClient } from "react-query"
import { ClipboardIcon, Share, Eye, EyeOff } from "lucide-react"
import { ClipboardIcon, Share, Eye, EyeOff, PlayIcon } from "lucide-react"
import { MagicWandIcon } from "@radix-ui/react-icons"
import { ErrorBoundary } from "react-error-boundary"
import { ErrorTabContent } from "./ErrorTabContent"
import { cn } from "@/lib/utils"
import { PreviewContent } from "./PreviewContent"

interface Props {
snippet?: Snippet | null
Expand All @@ -41,10 +42,16 @@ export function CodeAndPreview({ snippet }: Props) {
}, [snippet?.code])
const { toast } = useToast()

const { message, circuitJson, compiledJs } = useRunTsx(
const {
message,
circuitJson,
compiledJs,
triggerRunTsx,
tsxRunTriggerCount,
} = useRunTsx({
code,
snippet?.snippet_type,
)
type: snippet?.snippet_type,
})
const qc = useQueryClient()

const updateSnippetMutation = useMutation({
Expand Down Expand Up @@ -113,43 +120,14 @@ export function CodeAndPreview({ snippet }: Props) {
/>
</div>
{showPreview && (
<div className="w-full md:w-1/2 p-2 min-h-[640px]">
<Tabs defaultValue="pcb">
<TabsList>
<TabsTrigger value="pcb">PCB</TabsTrigger>
<TabsTrigger value="cad">3D</TabsTrigger>
<TabsTrigger value="table">JSON</TabsTrigger>
<TabsTrigger value="error">
Errors
{message && (
<span className="inline-flex items-center justify-center w-5 h-5 ml-2 text-xs font-bold text-white bg-red-500 rounded-full">
1
</span>
)}
</TabsTrigger>
</TabsList>
<TabsContent value="pcb">
<div className="mt-4 h-[500px]">
<PCBViewer soup={circuitJson} />
</div>
</TabsContent>
<TabsContent value="cad">
<div className="mt-4 h-[500px]">
<ErrorBoundary fallback={<div>Error loading 3D viewer</div>}>
<CadViewer soup={circuitJson as any} />
</ErrorBoundary>
</div>
</TabsContent>
<TabsContent value="table">
<div className="mt-4 h-[500px]">
<CircuitJsonTableViewer elements={circuitJson as any} />
</div>
</TabsContent>
<TabsContent value="error">
<ErrorTabContent code={code} errorMessage={message} />
</TabsContent>
</Tabs>
</div>
<PreviewContent
code={code}
triggerRunTsx={triggerRunTsx}
hasUnsavedChanges={hasUnsavedChanges}
tsxRunTriggerCount={tsxRunTriggerCount}
errorMessage={message}
circuitJson={circuitJson}
/>
)}
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/components/ErrorTabContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const ErrorTabContent = ({
}: {
code?: string
isStreaming?: boolean
errorMessage?: string
errorMessage?: string | null
}) => {
const anthropic = useAiApi()
const simplifiedErrorMessage = useAsyncMemo(async () => {
Expand Down
119 changes: 119 additions & 0 deletions src/components/PreviewContent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import { useEffect, useMemo, useState } from "react"
import { CodeEditor } from "@/components/CodeEditor"
import { PCBViewer } from "@tscircuit/pcb-viewer"
import { CadViewer } from "@tscircuit/3d-viewer"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import { defaultCodeForBlankPage } from "@/lib/defaultCodeForBlankCode"
import { decodeUrlHashToText } from "@/lib/decodeUrlHashToText"
import { encodeTextToUrlHash } from "@/lib/encodeTextToUrlHash"
import { Button } from "@/components/ui/button"
import { useRunTsx } from "@/hooks/use-run-tsx"
import EditorNav from "./EditorNav"
import { CircuitJsonTableViewer } from "./TableViewer/CircuitJsonTableViewer"
import { Snippet } from "fake-snippets-api/lib/db/schema"
import { useAxios } from "@/hooks/use-axios"
import { TypeBadge } from "./TypeBadge"
import { useToast } from "@/hooks/use-toast"
import { useMutation, useQueryClient } from "react-query"
import { ClipboardIcon, Share, Eye, EyeOff, PlayIcon } from "lucide-react"
import { MagicWandIcon } from "@radix-ui/react-icons"
import { ErrorBoundary } from "react-error-boundary"
import { ErrorTabContent } from "./ErrorTabContent"
import { cn } from "@/lib/utils"

export interface PreviewContentProps {
code: string
triggerRunTsx: () => void
hasUnsavedChanges: boolean
tsxRunTriggerCount: number
errorMessage: string | null
circuitJson: any
}

const PreviewEmptyState = ({
triggerRunTsx,
}: { triggerRunTsx: () => void }) => (
<div className="flex items-center gap-3 bg-gray-200 text-center justify-center py-10">
No circuit json loaded
<Button className="bg-blue-600 hover:bg-blue-500" onClick={triggerRunTsx}>
Run Code
<PlayIcon className="w-3 h-3 ml-2" />
</Button>
</div>
)

export const PreviewContent = ({
code,
triggerRunTsx,
hasUnsavedChanges,
tsxRunTriggerCount,
errorMessage,
circuitJson,
}: PreviewContentProps) => {
return (
<div className="w-full md:w-1/2 p-2 min-h-[640px]">
<Tabs defaultValue="pcb">
<div className="flex items-center gap-2">
<Button
className="bg-blue-600 hover:bg-blue-500"
onClick={() => triggerRunTsx()}
disabled={hasUnsavedChanges && tsxRunTriggerCount !== 0}
>
Run
<PlayIcon className="w-3 h-3 ml-2" />
</Button>
<div className="flex-grow" />
<TabsList>
<TabsTrigger value="pcb">PCB</TabsTrigger>
<TabsTrigger value="cad">3D</TabsTrigger>
<TabsTrigger value="table">JSON</TabsTrigger>
<TabsTrigger value="error">
Errors
{errorMessage && (
<span className="inline-flex items-center justify-center w-5 h-5 ml-2 text-xs font-bold text-white bg-red-500 rounded-full">
1
</span>
)}
</TabsTrigger>
</TabsList>
</div>
<TabsContent value="pcb">
<div className="mt-4 h-[500px]">
<ErrorBoundary fallback={<div>Error loading PCB viewer</div>}>
{circuitJson ? (
<PCBViewer soup={circuitJson} />
) : (
<PreviewEmptyState triggerRunTsx={triggerRunTsx} />
)}
</ErrorBoundary>
</div>
</TabsContent>
<TabsContent value="cad">
<div className="mt-4 h-[500px]">
<ErrorBoundary fallback={<div>Error loading 3D viewer</div>}>
{circuitJson ? (
<CadViewer soup={circuitJson as any} />
) : (
<PreviewEmptyState triggerRunTsx={triggerRunTsx} />
)}
</ErrorBoundary>
</div>
</TabsContent>
<TabsContent value="table">
<div className="mt-4 h-[500px]">
<ErrorBoundary fallback={<div>Error loading 3D viewer</div>}>
{circuitJson ? (
<CircuitJsonTableViewer elements={circuitJson as any} />
) : (
<PreviewEmptyState triggerRunTsx={triggerRunTsx} />
)}
</ErrorBoundary>
</div>
</TabsContent>
<TabsContent value="error">
<ErrorTabContent code={code} errorMessage={errorMessage} />
</TabsContent>
</Tabs>
</div>
)
}
1 change: 0 additions & 1 deletion src/hooks/use-run-tsx/construct-circuit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import * as React from "react"
import { useCompiledTsx } from "../use-compiled-tsx"
import { createJSCADRenderer } from "jscad-fiber"
import { jscadPlanner } from "jscad-planner"
import { getImportsFromCode } from "@tscircuit/prompt-benchmarks/code-runner-utils"

export const constructCircuit = (
UserElm: any,
Expand Down
36 changes: 25 additions & 11 deletions src/hooks/use-run-tsx/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect, useMemo, useState } from "react"
import { useEffect, useMemo, useReducer, useState } from "react"
import * as React from "react"
import { useCompiledTsx } from "../use-compiled-tsx"
import { Circuit } from "@tscircuit/core"
Expand All @@ -17,13 +17,24 @@ type RunTsxResult = {
isLoading: boolean
}

export const useRunTsx = (
code?: string,
type?: "board" | "footprint" | "package" | "model",
{ isStreaming = false }: { isStreaming?: boolean } = {},
): RunTsxResult => {
export const useRunTsx = ({
code,
type,
isStreaming = false,
}: {
code?: string
type?: "board" | "footprint" | "package" | "model"
isStreaming?: boolean
} = {}): RunTsxResult & {
triggerRunTsx: () => void
tsxRunTriggerCount: number
} => {
type ??= "board"
const compiledJs = useCompiledTsx(code, { isStreaming })
const [tsxRunTriggerCount, incTsxRunTriggerCount] = useReducer(
(c) => c + 1,
0,
)
const [tsxResult, setTsxResult] = useState<RunTsxResult>({
compiledModule: null,
message: "",
Expand All @@ -33,6 +44,7 @@ export const useRunTsx = (
const apiBaseUrl = useSnippetsBaseApiUrl()

useEffect(() => {
if (tsxRunTriggerCount === 0) return
async function run() {
if (isStreaming || !compiledJs || !code) {
setTsxResult({
Expand Down Expand Up @@ -61,11 +73,9 @@ export const useRunTsx = (
).then((res) => res.json())

try {
console.log("importedSnippet", importedSnippet)
// eval the imported snippet compiled_js
preSuppliedImports[importName] = evalCompiledJs(
importedSnippet.compiled_js,
)
).default.exports
} catch (e) {
console.error("Error importing snippet", e)
}
Expand Down Expand Up @@ -127,7 +137,11 @@ export const useRunTsx = (
}
}
run()
}, [compiledJs, isStreaming])
}, [tsxRunTriggerCount, compiledJs, isStreaming])

return tsxResult
return {
...tsxResult,
triggerRunTsx: incTsxRunTriggerCount,
tsxRunTriggerCount,
}
}
4 changes: 3 additions & 1 deletion src/pages/ai.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ export const AiPage = () => {
const [code, setCode] = useState("")
const [dts, setDts] = useState("")
const [isStreaming, setIsStreaming] = useState(false)
const { message: errorMessage, circuitJson } = useRunTsx(code, "board", {
const { message: errorMessage, circuitJson } = useRunTsx({
code,
type: "board",
isStreaming,
})
const { saveSnippet, isLoading: isSaving } = useSaveSnippet()
Expand Down
8 changes: 4 additions & 4 deletions src/pages/view-snippet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ export const ViewSnippetPage = () => {
const { author, snippetName } = useParams()
const { snippet } = useCurrentSnippet()

const { circuitJson, message } = useRunTsx(
snippet?.code ?? "",
snippet?.snippet_type,
)
const { circuitJson, message } = useRunTsx({
code: snippet?.code ?? "",
type: snippet?.snippet_type,
})

return (
<div>
Expand Down

0 comments on commit a5f30b8

Please sign in to comment.