@tscircuit/fake-snippets 0.0.4 → 0.0.6

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.
@@ -0,0 +1,498 @@
1
+ export const exampleCircuitJson = [
2
+ {
3
+ type: "source_port",
4
+ source_port_id: "source_port_0",
5
+ name: "pin1",
6
+ pin_number: 1,
7
+ port_hints: ["anode", "pos", "left", "pin1", "1"],
8
+ source_component_id: "source_component_0",
9
+ },
10
+ {
11
+ type: "source_port",
12
+ source_port_id: "source_port_1",
13
+ name: "pin2",
14
+ pin_number: 2,
15
+ port_hints: ["cathode", "neg", "right", "pin2", "2"],
16
+ source_component_id: "source_component_0",
17
+ },
18
+ {
19
+ type: "source_component",
20
+ source_component_id: "source_component_0",
21
+ ftype: "simple_resistor",
22
+ name: "R1",
23
+ supplier_part_numbers: {
24
+ jlcpcb: ["C11702", "C25543", "C226166"],
25
+ },
26
+ resistance: 1000,
27
+ display_resistance: "1kΩ",
28
+ },
29
+ {
30
+ type: "source_port",
31
+ source_port_id: "source_port_2",
32
+ name: "pin1",
33
+ pin_number: 1,
34
+ port_hints: ["anode", "pos", "left", "pin1", "1"],
35
+ source_component_id: "source_component_1",
36
+ },
37
+ {
38
+ type: "source_port",
39
+ source_port_id: "source_port_3",
40
+ name: "pin2",
41
+ pin_number: 2,
42
+ port_hints: ["cathode", "neg", "right", "pin2", "2"],
43
+ source_component_id: "source_component_1",
44
+ },
45
+ {
46
+ type: "source_component",
47
+ source_component_id: "source_component_1",
48
+ ftype: "simple_capacitor",
49
+ name: "C1",
50
+ supplier_part_numbers: {
51
+ jlcpcb: ["C106205", "C1523", "C14442"],
52
+ },
53
+ capacitance: 1e-9,
54
+ display_capacitance: "1nF",
55
+ },
56
+ {
57
+ type: "source_group",
58
+ source_group_id: "source_group_0",
59
+ is_subcircuit: true,
60
+ subcircuit_id: "subcircuit_source_group_0",
61
+ },
62
+ {
63
+ type: "source_trace",
64
+ source_trace_id: "source_trace_0",
65
+ connected_source_port_ids: ["source_port_0", "source_port_2"],
66
+ connected_source_net_ids: [],
67
+ max_length: null,
68
+ display_name: ".R1 > .pin1 to .C1 > .pin1",
69
+ subcircuit_connectivity_map_key: "unnamedsubcircuit27_connectivity_net0",
70
+ },
71
+ {
72
+ type: "schematic_component",
73
+ schematic_component_id: "schematic_component_0",
74
+ center: {
75
+ x: 3,
76
+ y: 0,
77
+ },
78
+ rotation: 0,
79
+ size: {
80
+ width: 1.0583332999999997,
81
+ height: 0.388910699999999,
82
+ },
83
+ source_component_id: "source_component_0",
84
+ symbol_name: "boxresistor_right",
85
+ symbol_display_value: "1kΩ",
86
+ },
87
+ {
88
+ type: "schematic_component",
89
+ schematic_component_id: "schematic_component_1",
90
+ center: {
91
+ x: -3,
92
+ y: 0,
93
+ },
94
+ rotation: 0,
95
+ size: {
96
+ width: 1.0583333000000001,
97
+ height: 0.8400173000000031,
98
+ },
99
+ source_component_id: "source_component_1",
100
+ symbol_name: "capacitor_right",
101
+ symbol_display_value: "1nF",
102
+ },
103
+ {
104
+ type: "schematic_port",
105
+ schematic_port_id: "schematic_port_0",
106
+ schematic_component_id: "schematic_component_0",
107
+ center: {
108
+ x: 2.4662093,
109
+ y: 0.045805199999999324,
110
+ },
111
+ source_port_id: "source_port_0",
112
+ facing_direction: "left",
113
+ distance_from_component_edge: 0.4,
114
+ pin_number: 1,
115
+ display_pin_label: "left",
116
+ },
117
+ {
118
+ type: "schematic_port",
119
+ schematic_port_id: "schematic_port_1",
120
+ schematic_component_id: "schematic_component_0",
121
+ center: {
122
+ x: 3.5337907000000004,
123
+ y: 0.04525870000000065,
124
+ },
125
+ source_port_id: "source_port_1",
126
+ facing_direction: "right",
127
+ distance_from_component_edge: 0.4,
128
+ pin_number: 2,
129
+ display_pin_label: "right",
130
+ },
131
+ {
132
+ type: "schematic_port",
133
+ schematic_port_id: "schematic_port_2",
134
+ schematic_component_id: "schematic_component_1",
135
+ center: {
136
+ x: -3.5512093000000005,
137
+ y: 0.016380250000000984,
138
+ },
139
+ source_port_id: "source_port_2",
140
+ facing_direction: "left",
141
+ distance_from_component_edge: 0.4,
142
+ pin_number: 1,
143
+ display_pin_label: "left",
144
+ },
145
+ {
146
+ type: "schematic_port",
147
+ schematic_port_id: "schematic_port_3",
148
+ schematic_component_id: "schematic_component_1",
149
+ center: {
150
+ x: -2.4487907,
151
+ y: 0.016926950000000218,
152
+ },
153
+ source_port_id: "source_port_3",
154
+ facing_direction: "right",
155
+ distance_from_component_edge: 0.4,
156
+ pin_number: 2,
157
+ display_pin_label: "right",
158
+ },
159
+ {
160
+ type: "schematic_trace",
161
+ schematic_trace_id: "schematic_trace_0",
162
+ source_trace_id: "source_trace_0",
163
+ edges: [
164
+ {
165
+ from: {
166
+ route_type: "wire",
167
+ x: 2.4662093,
168
+ y: 0.045805199999999324,
169
+ width: 0.1,
170
+ layer: "top",
171
+ },
172
+ to: {
173
+ route_type: "wire",
174
+ x: -2.0487906999999996,
175
+ y: 0.045805199999999324,
176
+ width: 0.1,
177
+ layer: "top",
178
+ },
179
+ },
180
+ {
181
+ from: {
182
+ route_type: "wire",
183
+ x: -2.0487906999999996,
184
+ y: 0.045805199999999324,
185
+ width: 0.1,
186
+ layer: "top",
187
+ },
188
+ to: {
189
+ route_type: "wire",
190
+ x: -2.0487906999999996,
191
+ y: 0.7174736499999994,
192
+ width: 0.1,
193
+ layer: "top",
194
+ },
195
+ },
196
+ {
197
+ from: {
198
+ route_type: "wire",
199
+ x: -2.0487906999999996,
200
+ y: 0.7174736499999994,
201
+ width: 0.1,
202
+ layer: "top",
203
+ },
204
+ to: {
205
+ route_type: "wire",
206
+ x: -3.5512093000000005,
207
+ y: 0.7174736499999994,
208
+ width: 0.1,
209
+ layer: "top",
210
+ },
211
+ },
212
+ {
213
+ from: {
214
+ route_type: "wire",
215
+ x: -3.5512093000000005,
216
+ y: 0.7174736499999994,
217
+ width: 0.1,
218
+ layer: "top",
219
+ },
220
+ to: {
221
+ route_type: "wire",
222
+ x: -3.5512093000000005,
223
+ y: 0.016380250000000984,
224
+ width: 0.1,
225
+ layer: "top",
226
+ },
227
+ },
228
+ ],
229
+ junctions: [],
230
+ },
231
+ {
232
+ type: "pcb_component",
233
+ pcb_component_id: "pcb_component_0",
234
+ center: {
235
+ x: 3,
236
+ y: 0,
237
+ },
238
+ width: 1.5999999999999996,
239
+ height: 0.6000000000000001,
240
+ layer: "top",
241
+ rotation: 0,
242
+ source_component_id: "source_component_0",
243
+ subcircuit_id: "subcircuit_source_group_0",
244
+ },
245
+ {
246
+ type: "pcb_component",
247
+ pcb_component_id: "pcb_component_1",
248
+ center: {
249
+ x: -3,
250
+ y: 0,
251
+ },
252
+ width: 1.5999999999999996,
253
+ height: 0.6000000000000001,
254
+ layer: "top",
255
+ rotation: 0,
256
+ source_component_id: "source_component_1",
257
+ subcircuit_id: "subcircuit_source_group_0",
258
+ },
259
+ {
260
+ type: "pcb_board",
261
+ pcb_board_id: "pcb_board_0",
262
+ center: {
263
+ x: 0,
264
+ y: 0,
265
+ },
266
+ thickness: 1.4,
267
+ num_layers: 4,
268
+ width: 10,
269
+ height: 10,
270
+ },
271
+ {
272
+ type: "pcb_smtpad",
273
+ pcb_smtpad_id: "pcb_smtpad_0",
274
+ pcb_component_id: "pcb_component_0",
275
+ pcb_port_id: "pcb_port_0",
276
+ layer: "top",
277
+ shape: "rect",
278
+ width: 0.6000000000000001,
279
+ height: 0.6000000000000001,
280
+ port_hints: ["1", "left"],
281
+ x: 2.5,
282
+ y: 0,
283
+ subcircuit_id: "subcircuit_source_group_0",
284
+ },
285
+ {
286
+ type: "pcb_solder_paste",
287
+ pcb_solder_paste_id: "pcb_solder_paste_0",
288
+ layer: "top",
289
+ shape: "rect",
290
+ width: 0.42000000000000004,
291
+ height: 0.42000000000000004,
292
+ x: 2.5,
293
+ y: 0,
294
+ pcb_component_id: "pcb_component_0",
295
+ pcb_smtpad_id: "pcb_smtpad_0",
296
+ subcircuit_id: "subcircuit_source_group_0",
297
+ },
298
+ {
299
+ type: "pcb_smtpad",
300
+ pcb_smtpad_id: "pcb_smtpad_1",
301
+ pcb_component_id: "pcb_component_0",
302
+ pcb_port_id: "pcb_port_1",
303
+ layer: "top",
304
+ shape: "rect",
305
+ width: 0.6000000000000001,
306
+ height: 0.6000000000000001,
307
+ port_hints: ["2", "right"],
308
+ x: 3.5,
309
+ y: 0,
310
+ subcircuit_id: "subcircuit_source_group_0",
311
+ },
312
+ {
313
+ type: "pcb_solder_paste",
314
+ pcb_solder_paste_id: "pcb_solder_paste_1",
315
+ layer: "top",
316
+ shape: "rect",
317
+ width: 0.42000000000000004,
318
+ height: 0.42000000000000004,
319
+ x: 3.5,
320
+ y: 0,
321
+ pcb_component_id: "pcb_component_0",
322
+ pcb_smtpad_id: "pcb_smtpad_1",
323
+ subcircuit_id: "subcircuit_source_group_0",
324
+ },
325
+ {
326
+ type: "pcb_smtpad",
327
+ pcb_smtpad_id: "pcb_smtpad_2",
328
+ pcb_component_id: "pcb_component_1",
329
+ pcb_port_id: "pcb_port_2",
330
+ layer: "top",
331
+ shape: "rect",
332
+ width: 0.6000000000000001,
333
+ height: 0.6000000000000001,
334
+ port_hints: ["1", "left"],
335
+ x: -3.5,
336
+ y: 0,
337
+ subcircuit_id: "subcircuit_source_group_0",
338
+ },
339
+ {
340
+ type: "pcb_solder_paste",
341
+ pcb_solder_paste_id: "pcb_solder_paste_2",
342
+ layer: "top",
343
+ shape: "rect",
344
+ width: 0.42000000000000004,
345
+ height: 0.42000000000000004,
346
+ x: -3.5,
347
+ y: 0,
348
+ pcb_component_id: "pcb_component_1",
349
+ pcb_smtpad_id: "pcb_smtpad_2",
350
+ subcircuit_id: "subcircuit_source_group_0",
351
+ },
352
+ {
353
+ type: "pcb_smtpad",
354
+ pcb_smtpad_id: "pcb_smtpad_3",
355
+ pcb_component_id: "pcb_component_1",
356
+ pcb_port_id: "pcb_port_3",
357
+ layer: "top",
358
+ shape: "rect",
359
+ width: 0.6000000000000001,
360
+ height: 0.6000000000000001,
361
+ port_hints: ["2", "right"],
362
+ x: -2.5,
363
+ y: 0,
364
+ subcircuit_id: "subcircuit_source_group_0",
365
+ },
366
+ {
367
+ type: "pcb_solder_paste",
368
+ pcb_solder_paste_id: "pcb_solder_paste_3",
369
+ layer: "top",
370
+ shape: "rect",
371
+ width: 0.42000000000000004,
372
+ height: 0.42000000000000004,
373
+ x: -2.5,
374
+ y: 0,
375
+ pcb_component_id: "pcb_component_1",
376
+ pcb_smtpad_id: "pcb_smtpad_3",
377
+ subcircuit_id: "subcircuit_source_group_0",
378
+ },
379
+ {
380
+ type: "pcb_port",
381
+ pcb_port_id: "pcb_port_0",
382
+ pcb_component_id: "pcb_component_0",
383
+ layers: ["top"],
384
+ subcircuit_id: "subcircuit_source_group_0",
385
+ x: 2.5,
386
+ y: 0,
387
+ source_port_id: "source_port_0",
388
+ },
389
+ {
390
+ type: "pcb_port",
391
+ pcb_port_id: "pcb_port_1",
392
+ pcb_component_id: "pcb_component_0",
393
+ layers: ["top"],
394
+ subcircuit_id: "subcircuit_source_group_0",
395
+ x: 3.5,
396
+ y: 0,
397
+ source_port_id: "source_port_1",
398
+ },
399
+ {
400
+ type: "pcb_port",
401
+ pcb_port_id: "pcb_port_2",
402
+ pcb_component_id: "pcb_component_1",
403
+ layers: ["top"],
404
+ subcircuit_id: "subcircuit_source_group_0",
405
+ x: -3.5,
406
+ y: 0,
407
+ source_port_id: "source_port_2",
408
+ },
409
+ {
410
+ type: "pcb_port",
411
+ pcb_port_id: "pcb_port_3",
412
+ pcb_component_id: "pcb_component_1",
413
+ layers: ["top"],
414
+ subcircuit_id: "subcircuit_source_group_0",
415
+ x: -2.5,
416
+ y: 0,
417
+ source_port_id: "source_port_3",
418
+ },
419
+ {
420
+ type: "pcb_trace",
421
+ pcb_trace_id: "pcb_trace_0",
422
+ route: [
423
+ {
424
+ route_type: "wire",
425
+ x: 2.5,
426
+ y: 0,
427
+ width: 0.16,
428
+ layer: "top",
429
+ start_pcb_port_id: "pcb_port_0",
430
+ },
431
+ {
432
+ route_type: "wire",
433
+ x: -1.2000000000000002,
434
+ y: 0,
435
+ width: 0.16,
436
+ layer: "top",
437
+ },
438
+ {
439
+ route_type: "wire",
440
+ x: -1.2000000000000002,
441
+ y: 1.3,
442
+ width: 0.16,
443
+ layer: "top",
444
+ },
445
+ {
446
+ route_type: "wire",
447
+ x: -3.5,
448
+ y: 1.3,
449
+ width: 0.16,
450
+ layer: "top",
451
+ },
452
+ {
453
+ route_type: "wire",
454
+ x: -3.5,
455
+ y: 0,
456
+ width: 0.16,
457
+ layer: "top",
458
+ end_pcb_port_id: "pcb_port_2",
459
+ },
460
+ ],
461
+ source_trace_id: "source_trace_0",
462
+ trace_length: 8.6,
463
+ },
464
+ {
465
+ type: "cad_component",
466
+ cad_component_id: "cad_component_0",
467
+ position: {
468
+ x: 3,
469
+ y: 0,
470
+ z: 0.7,
471
+ },
472
+ rotation: {
473
+ x: 0,
474
+ y: 0,
475
+ z: 0,
476
+ },
477
+ pcb_component_id: "pcb_component_0",
478
+ source_component_id: "source_component_0",
479
+ footprinter_string: "0402",
480
+ },
481
+ {
482
+ type: "cad_component",
483
+ cad_component_id: "cad_component_1",
484
+ position: {
485
+ x: -3,
486
+ y: 0,
487
+ z: 0.7,
488
+ },
489
+ rotation: {
490
+ x: 0,
491
+ y: 0,
492
+ z: 0,
493
+ },
494
+ pcb_component_id: "pcb_component_1",
495
+ source_component_id: "source_component_1",
496
+ footprinter_string: "0402",
497
+ },
498
+ ]
package/src/App.tsx CHANGED
@@ -5,9 +5,20 @@ import "./components/CmdKMenu"
5
5
  import { ContextProviders } from "./ContextProviders"
6
6
  import React from "react"
7
7
 
8
+ const FullPageLoader = () => (
9
+ <div className="fixed inset-0 flex items-center justify-center bg-white z-50">
10
+ <div className="w-48">
11
+ <div className="loading">
12
+ <div className="loading-bar"></div>
13
+ </div>
14
+ </div>
15
+ </div>
16
+ )
17
+
8
18
  const lazyImport = (importFn: () => Promise<any>) =>
9
19
  lazy<ComponentType<any>>(async () => {
10
20
  try {
21
+ await new Promise((resolve) => setTimeout(resolve, 500))
11
22
  const module = await importFn()
12
23
 
13
24
  if (module.default) {
@@ -85,7 +96,7 @@ function App() {
85
96
  return (
86
97
  <ContextProviders>
87
98
  <ErrorBoundary>
88
- <Suspense fallback={<div>Loading...</div>}>
99
+ <Suspense fallback={<FullPageLoader />}>
89
100
  <Switch>
90
101
  <Route path="/" component={LandingPage} />
91
102
  <Route path="/editor" component={EditorPage} />
@@ -0,0 +1,186 @@
1
+ import React, { useState } from "react"
2
+ import {
3
+ Dialog,
4
+ DialogContent,
5
+ DialogHeader,
6
+ DialogTitle,
7
+ DialogFooter,
8
+ } from "@/components/ui/dialog"
9
+ import { Button } from "@/components/ui/button"
10
+ import { Textarea } from "@/components/ui/textarea"
11
+ import { useAxios } from "@/hooks/use-axios"
12
+ import { useToast } from "@/hooks/use-toast"
13
+ import { useLocation } from "wouter"
14
+ import { useGlobalStore } from "@/hooks/use-global-store"
15
+ import { convertCircuitJsonToTscircuit } from "circuit-json-to-tscircuit"
16
+
17
+ interface CircuitJsonImportDialogProps {
18
+ open: boolean
19
+ onOpenChange: (open: boolean) => void
20
+ }
21
+
22
+ const isValidJSON = (code: string) => {
23
+ try {
24
+ JSON.parse(code)
25
+ return true
26
+ } catch {
27
+ return false
28
+ }
29
+ }
30
+
31
+ export function CircuitJsonImportDialog({
32
+ open,
33
+ onOpenChange,
34
+ }: CircuitJsonImportDialogProps) {
35
+ const [circuitJson, setcircuitJson] = useState("")
36
+ const [file, setFile] = useState<File | null>(null)
37
+ const [isLoading, setIsLoading] = useState(false)
38
+ const [error, setError] = useState<string | null>(null)
39
+ const axios = useAxios()
40
+ const { toast } = useToast()
41
+ const [, navigate] = useLocation()
42
+ const isLoggedIn = useGlobalStore((s) => Boolean(s.session))
43
+ const session = useGlobalStore((s) => s.session)
44
+
45
+ const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
46
+ const selectedFile = e.target.files?.[0]
47
+ if (selectedFile && selectedFile.type === "application/json") {
48
+ setFile(selectedFile)
49
+ } else {
50
+ setError("Please select a valid JSON file.")
51
+ }
52
+ }
53
+
54
+ const handleImport = async () => {
55
+ let importedCircuitJson
56
+
57
+ if (file) {
58
+ try {
59
+ const fileText = await file.text()
60
+ importedCircuitJson = JSON.parse(fileText)
61
+ } catch (err) {
62
+ setError("Error reading JSON file. Please ensure it is valid.")
63
+ return
64
+ }
65
+ } else if (isValidJSON(circuitJson)) {
66
+ setIsLoading(true)
67
+ setError(null)
68
+ importedCircuitJson = JSON.parse(circuitJson)
69
+ } else {
70
+ toast({
71
+ title: "Invalid Input",
72
+ description: "Please provide a valid JSON content or file.",
73
+ variant: "destructive",
74
+ })
75
+ return
76
+ }
77
+ let tscircuit
78
+ try {
79
+ tscircuit = convertCircuitJsonToTscircuit(importedCircuitJson as any, {
80
+ componentName: "circuit",
81
+ })
82
+ console.info(tscircuit)
83
+ } catch {
84
+ toast({
85
+ title: "Import Failed",
86
+ description: "Invalid Circuit JSON was provided.",
87
+ variant: "destructive",
88
+ })
89
+ setIsLoading(false)
90
+ return
91
+ }
92
+
93
+ try {
94
+ const newSnippetData = {
95
+ snippet_type: importedCircuitJson.type ?? "board",
96
+ circuit_json: importedCircuitJson,
97
+ code: tscircuit,
98
+ }
99
+ const response = await axios
100
+ .post("/snippets/create", newSnippetData)
101
+ .catch((e) => e)
102
+ const { snippet, message } = response.data
103
+ if (message) {
104
+ setError(message)
105
+ setIsLoading(false)
106
+ return
107
+ }
108
+ toast({
109
+ title: "Import Successful",
110
+ description: "Circuit Json has been imported successfully.",
111
+ })
112
+ onOpenChange(false)
113
+ navigate(`/editor?snippet_id=${snippet.snippet_id}`)
114
+ } catch (error) {
115
+ console.error("Error importing Circuit Json:", error)
116
+ toast({
117
+ title: "Import Failed",
118
+ description: "Failed to import the Circuit Json. Please try again.",
119
+ variant: "destructive",
120
+ })
121
+ } finally {
122
+ setIsLoading(false)
123
+ }
124
+ }
125
+
126
+ return (
127
+ <Dialog open={open} onOpenChange={onOpenChange}>
128
+ <DialogContent>
129
+ <DialogHeader>
130
+ <DialogTitle>Import Circuit JSON</DialogTitle>
131
+ </DialogHeader>
132
+ <div className="pb-4">
133
+ <Textarea
134
+ className="mt-3"
135
+ placeholder="Paste the Circuit JSON."
136
+ value={circuitJson}
137
+ onChange={(e) => setcircuitJson(e.target.value)}
138
+ disabled={!!file}
139
+ />
140
+ <div className="mt-4 flex flex-col gap-2">
141
+ <label
142
+ htmlFor="file-input"
143
+ className="block text-sm font-medium text-gray-700"
144
+ >
145
+ Upload JSON File
146
+ </label>
147
+ <div className="flex items-center gap-4">
148
+ <input
149
+ id="file-input"
150
+ type="file"
151
+ accept="application/json"
152
+ onChange={handleFileChange}
153
+ className="hidden" // Hide the default file input
154
+ />
155
+ <label
156
+ htmlFor="file-input"
157
+ className="px-4 py-2 bg-slate-900 text-slate-50 rounded-lg shadow cursor-pointer hover:bg-slate-900/90 dark:bg-slate-50 dark:text-slate-900 dark:hover:bg-slate-50/90 transition-all duration-200"
158
+ >
159
+ Choose File
160
+ </label>
161
+ </div>
162
+ {file && (
163
+ <p className="text-sm text-gray-600">
164
+ <span className="font-medium text-gray-900">
165
+ Selected file:
166
+ </span>{" "}
167
+ {file.name}
168
+ </p>
169
+ )}
170
+ </div>
171
+
172
+ {error && <p className="bg-red-100 p-2 mt-2 pre-wrap">{error}</p>}
173
+ </div>
174
+ <DialogFooter>
175
+ <Button onClick={handleImport} disabled={isLoading || !isLoggedIn}>
176
+ {!isLoggedIn
177
+ ? "Must be logged in for JSON import"
178
+ : isLoading
179
+ ? "Importing..."
180
+ : "Import"}
181
+ </Button>
182
+ </DialogFooter>
183
+ </DialogContent>
184
+ </Dialog>
185
+ )
186
+ }