@tscircuit/runframe 0.0.10 → 0.0.12

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 (45) hide show
  1. package/README.md +31 -1
  2. package/dist/standalone.min.js +11 -2
  3. package/package.json +11 -3
  4. package/.github/workflows/bun-formatcheck.yml +0 -26
  5. package/.github/workflows/bun-pver-release.yml +0 -25
  6. package/.github/workflows/bun-typecheck.yml +0 -26
  7. package/biome.json +0 -57
  8. package/bun.lockb +0 -0
  9. package/cosmos.config.json +0 -3
  10. package/cosmos.decorator.tsx +0 -3
  11. package/examples/resistor.fixture.tsx +0 -12
  12. package/examples/runframe-with-api-1.fixture.tsx +0 -41
  13. package/examples/runframe1-basic.fixture.tsx +0 -19
  14. package/index.html +0 -13
  15. package/lib/components/BomTable.tsx +0 -69
  16. package/lib/components/CircuitJsonPreview.tsx +0 -348
  17. package/lib/components/CircuitJsonTableViewer/CircuitJsonTableViewer.tsx +0 -315
  18. package/lib/components/CircuitJsonTableViewer/ClickableText.tsx +0 -20
  19. package/lib/components/CircuitJsonTableViewer/HeaderCell.tsx +0 -26
  20. package/lib/components/CircuitJsonTableViewer/Modal.tsx +0 -38
  21. package/lib/components/ErrorFallback.tsx +0 -25
  22. package/lib/components/ErrorTabContent.tsx +0 -86
  23. package/lib/components/PcbViewerWithContainerHeight.tsx +0 -47
  24. package/lib/components/PreviewEmptyState.tsx +0 -14
  25. package/lib/components/RunFrame.tsx +0 -68
  26. package/lib/components/RunFrameWithApi/index.tsx +0 -44
  27. package/lib/components/RunFrameWithApi/standalone.tsx +0 -6
  28. package/lib/components/RunFrameWithApi/store.ts +0 -122
  29. package/lib/components/RunFrameWithApi/types.ts +0 -43
  30. package/lib/components/ui/button.tsx +0 -57
  31. package/lib/components/ui/dropdown-menu.tsx +0 -203
  32. package/lib/components/ui/tabs.tsx +0 -53
  33. package/lib/dev/render-to-circuit-json.ts +0 -7
  34. package/lib/hooks/use-styles.ts +0 -17
  35. package/lib/preview.ts +0 -1
  36. package/lib/runner.ts +0 -2
  37. package/lib/utils/index.ts +0 -6
  38. package/lib/utils/pcbManualEditEventHandler.ts +0 -156
  39. package/postcss.config.js +0 -8
  40. package/renovate.json +0 -15
  41. package/scripts/build-css.ts +0 -26
  42. package/src/main.tsx +0 -13
  43. package/tailwind.config.js +0 -3
  44. package/tsconfig.json +0 -45
  45. package/vite.config.ts +0 -72
@@ -1,26 +0,0 @@
1
- # Created using @tscircuit/plop (npm install -g @tscircuit/plop)
2
- name: Format Check
3
-
4
- on:
5
- push:
6
- branches: [main]
7
- pull_request:
8
- branches: [main]
9
-
10
- jobs:
11
- format-check:
12
- runs-on: ubuntu-latest
13
-
14
- steps:
15
- - uses: actions/checkout@v3
16
-
17
- - name: Setup bun
18
- uses: oven-sh/setup-bun@v1
19
- with:
20
- bun-version: latest
21
-
22
- - name: Install dependencies
23
- run: bun install
24
-
25
- - name: Run format check
26
- run: bun run format:check
@@ -1,25 +0,0 @@
1
- # Created using @tscircuit/plop (npm install -g @tscircuit/plop)
2
- name: Publish to npm
3
- on:
4
- push:
5
- branches:
6
- - main
7
- jobs:
8
- publish:
9
- runs-on: ubuntu-latest
10
- steps:
11
- - uses: actions/checkout@v3
12
- - name: Setup bun
13
- uses: oven-sh/setup-bun@v1
14
- with:
15
- bun-version: latest
16
- - uses: actions/setup-node@v3
17
- with:
18
- node-version: 20
19
- registry-url: https://registry.npmjs.org/
20
- - run: npm install -g pver
21
- - run: bun install --frozen-lockfile
22
- - run: bun run build
23
- - run: pver release
24
- env:
25
- NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
@@ -1,26 +0,0 @@
1
- # Created using @tscircuit/plop (npm install -g @tscircuit/plop)
2
- name: Type Check
3
-
4
- on:
5
- push:
6
- branches: [main]
7
- pull_request:
8
- branches: [main]
9
-
10
- jobs:
11
- type-check:
12
- runs-on: ubuntu-latest
13
-
14
- steps:
15
- - uses: actions/checkout@v3
16
-
17
- - name: Setup bun
18
- uses: oven-sh/setup-bun@v1
19
- with:
20
- bun-version: latest
21
-
22
- - name: Install dependencies
23
- run: bun i
24
-
25
- - name: Run type check
26
- run: bunx tsc --noEmit
package/biome.json DELETED
@@ -1,57 +0,0 @@
1
- {
2
- "$schema": "https://biomejs.dev/schemas/1.9.3/schema.json",
3
- "organizeImports": {
4
- "enabled": true
5
- },
6
- "formatter": {
7
- "enabled": true,
8
- "indentStyle": "space"
9
- },
10
- "files": {
11
- "ignore": ["cosmos-export", "dist", "package.json"]
12
- },
13
- "javascript": {
14
- "formatter": {
15
- "jsxQuoteStyle": "double",
16
- "quoteProperties": "asNeeded",
17
- "trailingCommas": "all",
18
- "semicolons": "asNeeded",
19
- "arrowParentheses": "always",
20
- "bracketSpacing": true,
21
- "bracketSameLine": false
22
- }
23
- },
24
- "linter": {
25
- "enabled": true,
26
- "rules": {
27
- "recommended": true,
28
- "suspicious": {
29
- "noExplicitAny": "off",
30
- "noArrayIndexKey": "off"
31
- },
32
- "complexity": {
33
- "noForEach": "info"
34
- },
35
- "correctness": {
36
- "useExhaustiveDependencies": "off"
37
- },
38
- "a11y": {
39
- "useKeyWithClickEvents": "off"
40
- },
41
- "style": {
42
- "noUselessElse": "off",
43
- "noNonNullAssertion": "off",
44
- "useNumberNamespace": "off",
45
- "noUnusedTemplateLiteral": "off",
46
- "useFilenamingConvention": {
47
- "level": "error",
48
- "options": {
49
- "strictCase": true,
50
- "requireAscii": true,
51
- "filenameCases": ["kebab-case", "export"]
52
- }
53
- }
54
- }
55
- }
56
- }
57
- }
package/bun.lockb DELETED
Binary file
@@ -1,3 +0,0 @@
1
- {
2
- "plugins": ["react-cosmos-plugin-vite"]
3
- }
@@ -1,3 +0,0 @@
1
- export default ({ children }: { children: React.ReactNode }) => {
2
- return <div style={{ width: "100vw", height: "100vh" }}>{children}</div>
3
- }
@@ -1,12 +0,0 @@
1
- import { CircuitJsonPreview } from "lib/components/CircuitJsonPreview"
2
- import { renderToCircuitJson } from "lib/dev/render-to-circuit-json"
3
-
4
- export default () => (
5
- <CircuitJsonPreview
6
- circuitJson={renderToCircuitJson(
7
- <board width="10mm" height="10mm">
8
- <resistor name="R1" resistance="1k" footprint="0402" />
9
- </board>,
10
- )}
11
- />
12
- )
@@ -1,41 +0,0 @@
1
- import { RunFrameWithApi } from "lib/components/RunFrameWithApi"
2
- import { useState, useEffect } from "react"
3
-
4
- export default () => {
5
- useEffect(() => {
6
- setTimeout(async () => {
7
- fetch("/api/files/upsert", {
8
- method: "POST",
9
- headers: { "Content-Type": "application/json" },
10
- body: JSON.stringify({
11
- file_path: "main.tsx",
12
- text_content: `
13
- circuit.add(
14
- <board width="10mm" height="10mm">
15
- <resistor name="R1" resistance="1k" footprint="0402" />
16
- <capacitor name="C1" capacitance="1uF" footprint="0603" pcbX={4} />
17
- <trace from=".R1 .pin1" to=".C1 .pin1" />
18
- </board>
19
- )`,
20
- }),
21
- })
22
- }, 500)
23
- }, [])
24
-
25
- if (
26
- typeof window !== "undefined" &&
27
- window.location.origin.includes("vercel.app")
28
- ) {
29
- return (
30
- <div>
31
- <h1>RunFrame with API</h1>
32
- <p>
33
- We don't currently deploy the API to vercel, try locally! The vite
34
- plugin will automatically load it.
35
- </p>
36
- </div>
37
- )
38
- }
39
-
40
- return <RunFrameWithApi />
41
- }
@@ -1,19 +0,0 @@
1
- import { RunFrame } from "lib/components/RunFrame"
2
- import React from "react"
3
-
4
- export default () => (
5
- <RunFrame
6
- fsMap={{
7
- "main.tsx": `
8
- circuit.add(
9
- <board width="10mm" height="10mm">
10
- <resistor name="R1" resistance="1k" footprint="0402" />
11
- <capacitor name="C1" capacitance="1uF" footprint="0603" pcbX={4} />
12
- <trace from=".R1 .pin1" to=".C1 .pin1" />
13
- </board>
14
- )
15
- `,
16
- }}
17
- entrypoint="main.tsx"
18
- />
19
- )
package/index.html DELETED
@@ -1,13 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>@tscircuit/runframe</title>
7
- </head>
8
- <body>
9
- <div id="root"></div>
10
- <script src="https://cdn.tailwindcss.com"></script>
11
- <script type="module" src="/src/main.tsx"></script>
12
- </body>
13
- </html>
@@ -1,69 +0,0 @@
1
- import type { SupplierName } from "@tscircuit/props"
2
- import type { AnyCircuitElement } from "circuit-json"
3
-
4
- interface BomTableProps {
5
- circuitJson: AnyCircuitElement[]
6
- }
7
-
8
- export const linkify = (supplier: string, partNumber: string) => {
9
- if (supplier === "jlcpcb") {
10
- return (
11
- <a
12
- className="underline text-blue-500"
13
- target="_blank"
14
- rel="noreferrer"
15
- href={`https://jlcpcb.com/partdetail/${partNumber}`}
16
- >
17
- {partNumber}
18
- </a>
19
- )
20
- }
21
- return partNumber
22
- }
23
-
24
- export const BomTable: React.FC<BomTableProps> = ({ circuitJson }) => {
25
- const sourceComponents = circuitJson.filter(
26
- (el) => el.type === "source_component",
27
- )
28
-
29
- const supplierColumns = new Set<SupplierName>()
30
- for (const comp of sourceComponents) {
31
- if (comp.supplier_part_numbers) {
32
- for (const supplier of Object.keys(comp.supplier_part_numbers)) {
33
- supplierColumns.add(supplier as SupplierName)
34
- }
35
- }
36
- }
37
-
38
- return (
39
- <div className="overflow-x-auto">
40
- <table className="w-full text-left text-sm">
41
- <thead>
42
- <tr className="border-b">
43
- <th className="p-2">Name</th>
44
- {Array.from(supplierColumns).map((supplier) => (
45
- <th key={supplier} className="p-2 capitalize">
46
- {supplier}
47
- </th>
48
- ))}
49
- </tr>
50
- </thead>
51
- <tbody>
52
- {sourceComponents.map((comp) => (
53
- <tr key={comp.source_component_id} className="border-b">
54
- <td className="p-2">{comp.name}</td>
55
- {Array.from(supplierColumns).map((supplier) => (
56
- <td key={supplier} className="p-2">
57
- {linkify(
58
- supplier,
59
- comp.supplier_part_numbers?.[supplier]?.[0] || "",
60
- )}
61
- </td>
62
- ))}
63
- </tr>
64
- ))}
65
- </tbody>
66
- </table>
67
- </div>
68
- )
69
- }
@@ -1,348 +0,0 @@
1
- import {
2
- Tabs,
3
- TabsContent,
4
- TabsList,
5
- TabsTrigger,
6
- } from "lib/components/ui/tabs"
7
- import { cn } from "lib/utils"
8
- import { applyPcbEditEvents } from "lib/utils/pcbManualEditEventHandler"
9
- import { CadViewer } from "@tscircuit/3d-viewer"
10
- import { PCBViewer } from "@tscircuit/pcb-viewer"
11
- import { useEffect, useState } from "react"
12
- import { ErrorFallback } from "./ErrorFallback"
13
- import { ErrorBoundary } from "react-error-boundary"
14
- import { ErrorTabContent } from "./ErrorTabContent"
15
- import { SchematicViewer } from "@tscircuit/schematic-viewer"
16
- import PreviewEmptyState from "./PreviewEmptyState"
17
- import { CircuitJsonTableViewer } from "./CircuitJsonTableViewer/CircuitJsonTableViewer"
18
- import { BomTable } from "./BomTable"
19
- import {
20
- CheckIcon,
21
- EllipsisIcon,
22
- EllipsisVerticalIcon,
23
- FullscreenIcon,
24
- MinimizeIcon,
25
- } from "lucide-react"
26
- import {
27
- DropdownMenu,
28
- DropdownMenuContent,
29
- DropdownMenuItem,
30
- DropdownMenuTrigger,
31
- } from "./ui/dropdown-menu"
32
- import { Button } from "./ui/button"
33
- import { PcbViewerWithContainerHeight } from "./PcbViewerWithContainerHeight"
34
- import { useStyles } from "lib/hooks/use-styles"
35
-
36
- export interface PreviewContentProps {
37
- code?: string
38
- readOnly?: boolean
39
- onRunClicked?: () => void
40
- tsxRunTriggerCount?: number
41
- errorMessage?: string | null
42
- circuitJson: any
43
- circuitJsonKey?: string
44
- className?: string
45
- showCodeTab?: boolean
46
- codeTabContent?: React.ReactNode
47
- showJsonTab?: boolean
48
- showImportAndFormatButtons?: boolean
49
- headerClassName?: string
50
- leftHeaderContent?: React.ReactNode
51
- isRunningCode?: boolean
52
- isStreaming?: boolean
53
- onToggleFullScreen?: () => void
54
- isFullScreen?: boolean
55
- onCodeChange?: (code: string) => void
56
- onDtsChange?: (dts: string) => void
57
- manualEditsFileContent?: string
58
- hasCodeChangedSinceLastRun?: boolean
59
- onManualEditsFileContentChange?: (newmanualEditsFileContent: string) => void
60
- }
61
-
62
- export const CircuitJsonPreview = ({
63
- code,
64
- onRunClicked = () => {},
65
- tsxRunTriggerCount,
66
- errorMessage,
67
- circuitJsonKey = "",
68
- circuitJson,
69
- showCodeTab = false,
70
- codeTabContent,
71
- showJsonTab = true,
72
- showImportAndFormatButtons = true,
73
- className,
74
- headerClassName,
75
- leftHeaderContent,
76
- readOnly,
77
- isStreaming,
78
- onToggleFullScreen,
79
- isFullScreen,
80
- isRunningCode,
81
- hasCodeChangedSinceLastRun,
82
- onCodeChange,
83
- onDtsChange,
84
- manualEditsFileContent,
85
- onManualEditsFileContentChange,
86
- }: PreviewContentProps) => {
87
- useStyles()
88
- const [activeTab, setActiveTab] = useState(showCodeTab ? "code" : "pcb")
89
-
90
- useEffect(() => {
91
- if (errorMessage) {
92
- setActiveTab("error")
93
- }
94
- }, [errorMessage])
95
-
96
- useEffect(() => {
97
- if (activeTab === "code" && circuitJson && !errorMessage) {
98
- setActiveTab("pcb")
99
- }
100
- }, [circuitJson])
101
-
102
- return (
103
- <div className={cn("flex flex-col relative", className)}>
104
- <div className="md:sticky md:top-2">
105
- <Tabs
106
- value={activeTab}
107
- onValueChange={setActiveTab}
108
- className="flex-grow flex flex-col p-2"
109
- >
110
- <div className={cn("flex items-center gap-2", headerClassName)}>
111
- {leftHeaderContent}
112
- {leftHeaderContent && <div className="flex-grow" />}
113
- {/* <RunButton
114
- onClick={() => triggerRunTsx()}
115
- disabled={!hasCodeChangedSinceLastRun && tsxRunTriggerCount !== 0}
116
- isRunningCode={isRunningCode}
117
- /> */}
118
- {!leftHeaderContent && <div className="flex-grow" />}
119
- <TabsList>
120
- {showCodeTab && <TabsTrigger value="code">Code</TabsTrigger>}
121
- <TabsTrigger value="pcb" className="whitespace-nowrap">
122
- {circuitJson && (
123
- <span
124
- className={cn(
125
- "inline-flex items-center justify-center w-2 h-2 mr-1 text-xs font-bold text-white rounded-full",
126
- !hasCodeChangedSinceLastRun
127
- ? "bg-blue-500"
128
- : "bg-gray-500",
129
- )}
130
- />
131
- )}
132
- PCB
133
- </TabsTrigger>
134
- <TabsTrigger value="schematic" className="whitespace-nowrap">
135
- {circuitJson && (
136
- <span
137
- className={cn(
138
- "inline-flex items-center justify-center w-2 h-2 mr-1 text-xs font-bold text-white rounded-full",
139
- !hasCodeChangedSinceLastRun
140
- ? "bg-blue-500"
141
- : "bg-gray-500",
142
- )}
143
- />
144
- )}
145
- Schematic
146
- </TabsTrigger>
147
- <TabsTrigger value="cad">
148
- {circuitJson && (
149
- <span
150
- className={cn(
151
- "inline-flex items-center justify-center w-2 h-2 mr-1 text-xs font-bold text-white rounded-full",
152
- !hasCodeChangedSinceLastRun
153
- ? "bg-blue-500"
154
- : "bg-gray-500",
155
- )}
156
- />
157
- )}
158
- 3D
159
- </TabsTrigger>
160
- <DropdownMenu>
161
- <DropdownMenuTrigger asChild>
162
- <div className="whitespace-nowrap p-2 mr-1 cursor-pointer relative">
163
- <EllipsisIcon className="w-4 h-4" />
164
- {errorMessage && (
165
- <span className="inline-flex absolute top-[6px] right-[4px] items-center justify-center w-1 h-1 ml-2 text-[8px] font-bold text-white bg-red-500 rounded-full" />
166
- )}
167
- </div>
168
- </DropdownMenuTrigger>
169
- <DropdownMenuContent className="*:text-xs">
170
- <DropdownMenuItem
171
- onSelect={() => setActiveTab("error")}
172
- className="flex"
173
- >
174
- <CheckIcon
175
- className={cn(
176
- "w-3 h-3 mr-2",
177
- activeTab !== "error" && "invisible",
178
- )}
179
- />
180
- <div className="flex-grow">Errors</div>
181
- {errorMessage && (
182
- <span className="inline-flex items-center justify-center w-3 h-3 ml-2 text-[8px] font-bold text-white bg-red-500 rounded-full">
183
- 1
184
- </span>
185
- )}
186
- </DropdownMenuItem>
187
- <DropdownMenuItem onSelect={() => setActiveTab("bom")}>
188
- <CheckIcon
189
- className={cn(
190
- "w-3 h-3 mr-2",
191
- activeTab !== "bom" && "invisible",
192
- )}
193
- />
194
- Bill of Materials
195
- </DropdownMenuItem>
196
- <DropdownMenuItem
197
- onSelect={() => setActiveTab("circuitjson")}
198
- >
199
- <CheckIcon
200
- className={cn(
201
- "w-3 h-3 mr-2",
202
- activeTab !== "circuitjson" && "invisible",
203
- )}
204
- />
205
- JSON
206
- </DropdownMenuItem>
207
- </DropdownMenuContent>
208
- </DropdownMenu>
209
- </TabsList>
210
- {onToggleFullScreen && (
211
- <Button onClick={onToggleFullScreen} variant="ghost">
212
- {isFullScreen ? (
213
- <MinimizeIcon size={16} />
214
- ) : (
215
- <FullscreenIcon size={16} />
216
- )}
217
- </Button>
218
- )}
219
- </div>
220
- {showCodeTab && (
221
- <TabsContent value="code" className="flex-grow overflow-hidden">
222
- <div className="h-full">{codeTabContent}</div>
223
- </TabsContent>
224
- )}
225
-
226
- <TabsContent value="pcb">
227
- <div
228
- className={cn(
229
- "overflow-hidden",
230
- isFullScreen ? "h-[calc(100vh-96px)]" : "h-[620px]",
231
- )}
232
- >
233
- <ErrorBoundary fallback={<div>Error loading PCB viewer</div>}>
234
- {circuitJson ? (
235
- <PcbViewerWithContainerHeight
236
- key={circuitJsonKey}
237
- soup={circuitJson}
238
- containerClassName={cn(
239
- "h-full w-full",
240
- isFullScreen
241
- ? "min-h-[calc(100vh-240px)]"
242
- : "min-h-[620px]",
243
- )}
244
- // onEditEventsChanged={(editEvents) => {
245
- // if (editEvents.some((editEvent) => editEvent.in_progress))
246
- // return
247
- // // Update state with new edit events
248
- // const newManualEditsFileContent = applyPcbEditEvents({
249
- // editEvents,
250
- // circuitJson,
251
- // manualEditsFileContent,
252
- // })
253
- // onManualEditsFileContentChange?.(
254
- // JSON.stringify(newManualEditsFileContent, null, 2),
255
- // )
256
- // }}
257
- />
258
- ) : (
259
- <PreviewEmptyState onRunClicked={onRunClicked} />
260
- )}
261
- </ErrorBoundary>
262
- </div>
263
- </TabsContent>
264
-
265
- <TabsContent value="schematic">
266
- <div
267
- className={cn(
268
- "overflow-auto",
269
- isFullScreen ? "h-[calc(100vh-96px)]" : "h-[620px]",
270
- )}
271
- >
272
- <ErrorBoundary fallback={<div>Error loading Schematic</div>}>
273
- {circuitJson ? (
274
- <SchematicViewer
275
- circuitJson={circuitJson}
276
- containerStyle={{
277
- height: "100%",
278
- }}
279
- />
280
- ) : (
281
- <PreviewEmptyState onRunClicked={onRunClicked} />
282
- )}
283
- </ErrorBoundary>
284
- </div>
285
- </TabsContent>
286
-
287
- <TabsContent value="cad">
288
- <div
289
- className={cn(
290
- "overflow-auto",
291
- isFullScreen ? "h-[calc(100vh-96px)]" : "h-[620px]",
292
- )}
293
- >
294
- <ErrorBoundary FallbackComponent={ErrorFallback}>
295
- {circuitJson ? (
296
- <CadViewer soup={circuitJson as any} />
297
- ) : (
298
- <PreviewEmptyState onRunClicked={onRunClicked} />
299
- )}
300
- </ErrorBoundary>
301
- </div>
302
- </TabsContent>
303
-
304
- <TabsContent value="bom">
305
- <div
306
- className={cn(
307
- "overflow-auto",
308
- isFullScreen ? "h-[calc(100vh-96px)]" : "h-[620px]",
309
- )}
310
- >
311
- <ErrorBoundary fallback={<div>Error loading BOM</div>}>
312
- {circuitJson ? (
313
- <BomTable circuitJson={circuitJson} />
314
- ) : (
315
- <PreviewEmptyState onRunClicked={onRunClicked} />
316
- )}
317
- </ErrorBoundary>
318
- </div>
319
- </TabsContent>
320
-
321
- <TabsContent value="circuitjson">
322
- <div
323
- className={cn(
324
- "overflow-auto",
325
- isFullScreen ? "h-[calc(100vh-96px)]" : "h-[620px]",
326
- )}
327
- >
328
- <ErrorBoundary fallback={<div>Error loading JSON viewer</div>}>
329
- {circuitJson ? (
330
- <CircuitJsonTableViewer elements={circuitJson as any} />
331
- ) : (
332
- <PreviewEmptyState onRunClicked={onRunClicked} />
333
- )}
334
- </ErrorBoundary>
335
- </div>
336
- </TabsContent>
337
- <TabsContent value="error">
338
- {circuitJson || errorMessage ? (
339
- <ErrorTabContent code={code} errorMessage={errorMessage} />
340
- ) : (
341
- <PreviewEmptyState onRunClicked={onRunClicked} />
342
- )}
343
- </TabsContent>
344
- </Tabs>
345
- </div>
346
- </div>
347
- )
348
- }