@tscircuit/3d-viewer 0.0.13 → 0.0.14
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/dist/index.js +68 -138
- package/dist/index.js.map +1 -1
- package/package.json +7 -3
package/dist/index.js
CHANGED
|
@@ -5,9 +5,6 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
5
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
6
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __commonJS = (cb, mod) => function __require() {
|
|
9
|
-
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
10
|
-
};
|
|
11
8
|
var __export = (target, all) => {
|
|
12
9
|
for (var name in all)
|
|
13
10
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -30,113 +27,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
30
27
|
));
|
|
31
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
32
29
|
|
|
33
|
-
// node_modules/@tscircuit/soup-util/dist/index.cjs
|
|
34
|
-
var require_dist = __commonJS({
|
|
35
|
-
"node_modules/@tscircuit/soup-util/dist/index.cjs"(exports2, module2) {
|
|
36
|
-
"use strict";
|
|
37
|
-
var __defProp2 = Object.defineProperty;
|
|
38
|
-
var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
|
|
39
|
-
var __getOwnPropNames2 = Object.getOwnPropertyNames;
|
|
40
|
-
var __hasOwnProp2 = Object.prototype.hasOwnProperty;
|
|
41
|
-
var __export2 = (target, all) => {
|
|
42
|
-
for (var name in all)
|
|
43
|
-
__defProp2(target, name, { get: all[name], enumerable: true });
|
|
44
|
-
};
|
|
45
|
-
var __copyProps2 = (to, from, except, desc) => {
|
|
46
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
47
|
-
for (let key of __getOwnPropNames2(from))
|
|
48
|
-
if (!__hasOwnProp2.call(to, key) && key !== except)
|
|
49
|
-
__defProp2(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc2(from, key)) || desc.enumerable });
|
|
50
|
-
}
|
|
51
|
-
return to;
|
|
52
|
-
};
|
|
53
|
-
var __toCommonJS2 = (mod) => __copyProps2(__defProp2({}, "__esModule", { value: true }), mod);
|
|
54
|
-
var soup_util_exports = {};
|
|
55
|
-
__export2(soup_util_exports, {
|
|
56
|
-
default: () => soup_util_default,
|
|
57
|
-
su: () => su3
|
|
58
|
-
});
|
|
59
|
-
module2.exports = __toCommonJS2(soup_util_exports);
|
|
60
|
-
var su3 = (soup) => {
|
|
61
|
-
const su22 = new Proxy(
|
|
62
|
-
{},
|
|
63
|
-
{
|
|
64
|
-
get: (proxy_target, component_type) => {
|
|
65
|
-
return {
|
|
66
|
-
get: (id) => soup.find(
|
|
67
|
-
(e) => e.type === component_type && e[`${component_type}_id`] === id
|
|
68
|
-
),
|
|
69
|
-
getUsing: (using) => {
|
|
70
|
-
const keys = Object.keys(using);
|
|
71
|
-
if (keys.length !== 1) {
|
|
72
|
-
throw new Error(
|
|
73
|
-
"getUsing requires exactly one key, e.g. { pcb_component_id }"
|
|
74
|
-
);
|
|
75
|
-
}
|
|
76
|
-
const join_key = keys[0];
|
|
77
|
-
const join_type = join_key.replace("_id", "");
|
|
78
|
-
const joiner = soup.find(
|
|
79
|
-
(e) => e.type === join_type && e[join_key] === using[join_key]
|
|
80
|
-
);
|
|
81
|
-
if (!joiner)
|
|
82
|
-
return null;
|
|
83
|
-
return soup.find(
|
|
84
|
-
(e) => e.type === component_type && e[`${component_type}_id`] === joiner[`${component_type}_id`]
|
|
85
|
-
);
|
|
86
|
-
},
|
|
87
|
-
getWhere: (where) => {
|
|
88
|
-
const keys = Object.keys(where);
|
|
89
|
-
return soup.find(
|
|
90
|
-
(e) => e.type === component_type && keys.every((key) => e[key] === where[key])
|
|
91
|
-
);
|
|
92
|
-
},
|
|
93
|
-
list: (where) => {
|
|
94
|
-
const keys = !where ? [] : Object.keys(where);
|
|
95
|
-
return soup.filter(
|
|
96
|
-
(e) => e.type === component_type && keys.every((key) => e[key] === where[key])
|
|
97
|
-
);
|
|
98
|
-
},
|
|
99
|
-
select: (selector) => {
|
|
100
|
-
if (component_type === "source_component") {
|
|
101
|
-
return soup.find(
|
|
102
|
-
(e) => e.type === "source_component" && e.name === selector.replace(/\./g, "")
|
|
103
|
-
);
|
|
104
|
-
} else if (component_type === "pcb_port" || component_type === "source_port" || component_type === "schematic_port") {
|
|
105
|
-
const [component_name, port_selector] = selector.replace(/\./g, "").split(/[\s\>]+/);
|
|
106
|
-
const source_component = soup.find(
|
|
107
|
-
(e) => e.type === "source_component" && e.name === component_name
|
|
108
|
-
);
|
|
109
|
-
if (!source_component)
|
|
110
|
-
return null;
|
|
111
|
-
const source_port = soup.find(
|
|
112
|
-
(e) => e.type === "source_port" && e.source_component_id === source_component.source_component_id && (e.name === port_selector || (e.port_hints ?? []).includes(port_selector))
|
|
113
|
-
);
|
|
114
|
-
if (!source_port)
|
|
115
|
-
return null;
|
|
116
|
-
if (component_type === "source_port")
|
|
117
|
-
return source_port;
|
|
118
|
-
if (component_type === "pcb_port") {
|
|
119
|
-
return soup.find(
|
|
120
|
-
(e) => e.type === "pcb_port" && e.source_port_id === source_port.source_port_id
|
|
121
|
-
);
|
|
122
|
-
} else if (component_type === "schematic_port") {
|
|
123
|
-
return soup.find(
|
|
124
|
-
(e) => e.type === "schematic_port" && e.source_port_id === source_port.source_port_id
|
|
125
|
-
);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
);
|
|
133
|
-
return su22;
|
|
134
|
-
};
|
|
135
|
-
su3.unparsed = su3;
|
|
136
|
-
var soup_util_default = su3;
|
|
137
|
-
}
|
|
138
|
-
});
|
|
139
|
-
|
|
140
30
|
// src/index.tsx
|
|
141
31
|
var src_exports = {};
|
|
142
32
|
__export(src_exports, {
|
|
@@ -145,16 +35,18 @@ __export(src_exports, {
|
|
|
145
35
|
module.exports = __toCommonJS(src_exports);
|
|
146
36
|
|
|
147
37
|
// src/hooks/use-convert-children-to-soup.ts
|
|
38
|
+
var import_react_fiber = require("@tscircuit/react-fiber");
|
|
148
39
|
var useConvertChildrenToSoup = (children, defaultSoup) => {
|
|
149
|
-
|
|
40
|
+
const { elements } = (0, import_react_fiber.useRenderedElements)(children);
|
|
41
|
+
return elements ?? defaultSoup;
|
|
150
42
|
};
|
|
151
43
|
|
|
152
44
|
// src/CadViewer.tsx
|
|
153
|
-
var import_soup_util2 =
|
|
154
|
-
var
|
|
45
|
+
var import_soup_util2 = require("@tscircuit/soup-util");
|
|
46
|
+
var import_react6 = require("react");
|
|
155
47
|
|
|
156
48
|
// src/soup-to-3d/index.ts
|
|
157
|
-
var import_soup_util =
|
|
49
|
+
var import_soup_util = require("@tscircuit/soup-util");
|
|
158
50
|
var import_transforms = require("@jscad/modeling/src/operations/transforms");
|
|
159
51
|
var import_primitives2 = require("@jscad/modeling/src/primitives");
|
|
160
52
|
var import_colors2 = require("@jscad/modeling/src/colors");
|
|
@@ -507,7 +399,7 @@ var CubeWithLabeledSides = ({}) => {
|
|
|
507
399
|
// package.json
|
|
508
400
|
var package_default = {
|
|
509
401
|
name: "@tscircuit/3d-viewer",
|
|
510
|
-
version: "0.0.
|
|
402
|
+
version: "0.0.13",
|
|
511
403
|
main: "./dist/index.js",
|
|
512
404
|
files: [
|
|
513
405
|
"dist"
|
|
@@ -527,7 +419,13 @@ var package_default = {
|
|
|
527
419
|
"@jscad/stl-serializer": "^2.1.17",
|
|
528
420
|
"@react-three/drei": "^9.107.2",
|
|
529
421
|
"@react-three/fiber": "^8.16.8",
|
|
422
|
+
"@tscircuit/builder": "^1.9.0",
|
|
423
|
+
"@tscircuit/react-fiber": "^1.1.29",
|
|
424
|
+
"@tscircuit/soup": "^0.0.39",
|
|
425
|
+
"@tscircuit/soup-util": "^0.0.15",
|
|
530
426
|
"@types/three": "^0.165.0",
|
|
427
|
+
"jscad-fiber": "^0.0.38",
|
|
428
|
+
"jscad-planner": "^0.0.2",
|
|
531
429
|
react: "^18.3.1",
|
|
532
430
|
"react-dom": "^18.3.1",
|
|
533
431
|
"react-use-gesture": "^9.1.3",
|
|
@@ -546,8 +444,6 @@ var package_default = {
|
|
|
546
444
|
"@storybook/react": "^8.1.10",
|
|
547
445
|
"@storybook/react-vite": "^8.1.10",
|
|
548
446
|
"@storybook/test": "^8.1.10",
|
|
549
|
-
"@tscircuit/soup": "^0.0.39",
|
|
550
|
-
"@tscircuit/soup-util": "^0.0.11",
|
|
551
447
|
"@types/react": "^18.3.3",
|
|
552
448
|
"@types/react-dom": "^18.3.0",
|
|
553
449
|
"@vitejs/plugin-react": "^4.3.1",
|
|
@@ -730,17 +626,41 @@ function MixedStlModel({
|
|
|
730
626
|
|
|
731
627
|
// src/CadViewer.tsx
|
|
732
628
|
var import_three = require("three");
|
|
629
|
+
|
|
630
|
+
// src/three-components/JscadModel.tsx
|
|
631
|
+
var import_jscad_planner = require("jscad-planner");
|
|
632
|
+
var import_modeling = __toESM(require("@jscad/modeling"));
|
|
633
|
+
var import_jscad_fiber = require("jscad-fiber");
|
|
634
|
+
var THREE2 = __toESM(require("three"));
|
|
635
|
+
var import_react5 = require("react");
|
|
733
636
|
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
637
|
+
var JscadModel = ({ jscadPlan }) => {
|
|
638
|
+
const { threeGeom, material } = (0, import_react5.useMemo)(() => {
|
|
639
|
+
const jscadObject = (0, import_jscad_planner.executeJscadOperations)(import_modeling.default, jscadPlan);
|
|
640
|
+
const threeGeom2 = (0, import_jscad_fiber.convertCSGToThreeGeom)(jscadObject);
|
|
641
|
+
const material2 = new THREE2.MeshStandardMaterial({
|
|
642
|
+
vertexColors: true,
|
|
643
|
+
side: THREE2.DoubleSide
|
|
644
|
+
// Ensure both sides are visible
|
|
645
|
+
});
|
|
646
|
+
return { threeGeom: threeGeom2, material: material2 };
|
|
647
|
+
}, [jscadPlan]);
|
|
648
|
+
if (!threeGeom) return null;
|
|
649
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("mesh", { geometry: threeGeom, material });
|
|
650
|
+
};
|
|
651
|
+
|
|
652
|
+
// src/CadViewer.tsx
|
|
653
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
734
654
|
var CadViewer = ({ soup, children }) => {
|
|
735
655
|
soup ??= useConvertChildrenToSoup(children, soup);
|
|
736
|
-
const boardGeom = (0,
|
|
656
|
+
const boardGeom = (0, import_react6.useMemo)(() => {
|
|
737
657
|
if (!soup.some((e) => e.type === "pcb_board")) return null;
|
|
738
658
|
return createBoardGeomFromSoup(soup);
|
|
739
659
|
}, [soup]);
|
|
740
660
|
const { stls, loading } = useStlsFromGeom(boardGeom);
|
|
741
661
|
const cad_components = (0, import_soup_util2.su)(soup).cad_component.list();
|
|
742
|
-
return /* @__PURE__ */ (0,
|
|
743
|
-
stls.map(({ stlUrl, color }, index) => /* @__PURE__ */ (0,
|
|
662
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(CadViewerContainer, { children: [
|
|
663
|
+
stls.map(({ stlUrl, color }, index) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
744
664
|
STLModel,
|
|
745
665
|
{
|
|
746
666
|
stlUrl,
|
|
@@ -751,24 +671,34 @@ var CadViewer = ({ soup, children }) => {
|
|
|
751
671
|
)),
|
|
752
672
|
cad_components.map((cad_component) => {
|
|
753
673
|
const url = cad_component.model_obj_url ?? cad_component.model_stl_url;
|
|
754
|
-
if (
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
674
|
+
if (url) {
|
|
675
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
676
|
+
MixedStlModel,
|
|
677
|
+
{
|
|
678
|
+
url,
|
|
679
|
+
position: cad_component.position ? [
|
|
680
|
+
cad_component.position.x,
|
|
681
|
+
cad_component.position.y,
|
|
682
|
+
cad_component.position.z
|
|
683
|
+
] : void 0,
|
|
684
|
+
rotation: cad_component.rotation ? new import_three.Euler(
|
|
685
|
+
cad_component.rotation.x * Math.PI / 180,
|
|
686
|
+
cad_component.rotation.y * Math.PI / 180,
|
|
687
|
+
cad_component.rotation.z * Math.PI / 180
|
|
688
|
+
) : void 0
|
|
689
|
+
},
|
|
690
|
+
cad_component.cad_component_id
|
|
691
|
+
);
|
|
692
|
+
}
|
|
693
|
+
if (cad_component.model_jscad) {
|
|
694
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
695
|
+
JscadModel,
|
|
696
|
+
{
|
|
697
|
+
jscadPlan: cad_component.model_jscad
|
|
698
|
+
},
|
|
699
|
+
cad_component.cad_component_id
|
|
700
|
+
);
|
|
701
|
+
}
|
|
772
702
|
})
|
|
773
703
|
] });
|
|
774
704
|
};
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../node_modules/@tscircuit/soup-util/index.ts","../src/index.tsx","../src/hooks/use-convert-children-to-soup.ts","../src/CadViewer.tsx","../src/soup-to-3d/index.ts","../src/geoms/plated-hole.ts","../src/geoms/constants.ts","../src/hooks/use-stls-from-geom.ts","../src/three-components/STLModel.tsx","../src/CadViewerContainer.tsx","../src/three-components/cube-with-labeled-sides.tsx","../package.json","../src/hooks/use-global-obj-loader.ts","../src/three-components/MixedStlModel.tsx"],"sourcesContent":["import type {\n AnySoupElement,\n AnySoupElementInput,\n SourceComponentBase,\n SourcePort,\n} from \"@tscircuit/soup\"\n\ntype SoupOps<\n K extends AnySoupElement[\"type\"],\n T extends AnySoupElement | AnySoupElementInput\n> = {\n get: (id: string) => Extract<T, { type: K }> | null\n select: (selector: string) => Extract<T, { type: K }> | null\n getWhere: (where: any) => Extract<T, { type: K }> | null\n getUsing: (using: {\n [key: `${string}_id`]: string\n }) => Extract<T, { type: K }> | null\n list: (where?: any) => Extract<T, { type: K }>[]\n}\n\nexport type SoupUtilObject = {\n [K in AnySoupElement[\"type\"]]: SoupOps<K, AnySoupElement>\n}\nexport type SoupInputUtilObject = {\n [K in AnySoupElementInput[\"type\"]]: SoupOps<K, AnySoupElementInput>\n}\n\nexport type GetSoupUtilObject = ((soup: AnySoupElement[]) => SoupUtilObject) & {\n unparsed: (soup: AnySoupElementInput[]) => SoupInputUtilObject\n}\n\nexport const su: GetSoupUtilObject = ((soup: AnySoupElement[]) => {\n const su = new Proxy(\n {},\n {\n get: (proxy_target: any, component_type: string) => {\n return {\n get: (id: string) =>\n soup.find(\n (e: any) =>\n e.type === component_type && e[`${component_type}_id`] === id\n ),\n getUsing: (using: any) => {\n const keys = Object.keys(using)\n if (keys.length !== 1) {\n throw new Error(\n \"getUsing requires exactly one key, e.g. { pcb_component_id }\"\n )\n }\n const join_key = keys[0] as string\n const join_type = join_key.replace(\"_id\", \"\")\n const joiner: any = soup.find(\n (e: any) =>\n e.type === join_type && e[join_key] === using[join_key]\n )\n if (!joiner) return null\n return soup.find(\n (e: any) =>\n e.type === component_type &&\n e[`${component_type}_id`] === joiner[`${component_type}_id`]\n )\n },\n getWhere: (where: any) => {\n const keys = Object.keys(where)\n return soup.find(\n (e: any) =>\n e.type === component_type &&\n keys.every((key) => e[key] === where[key])\n )\n },\n list: (where?: any) => {\n const keys = !where ? [] : Object.keys(where)\n return soup.filter(\n (e: any) =>\n e.type === component_type &&\n keys.every((key) => e[key] === where[key])\n )\n },\n select: (selector: string) => {\n // TODO when applySelector is isolated we can use it, until then we\n // do a poor man's selector implementation for two common cases\n if (component_type === \"source_component\") {\n return soup.find(\n (e) =>\n e.type === \"source_component\" &&\n e.name === selector.replace(/\\./g, \"\")\n )\n } else if (\n component_type === \"pcb_port\" ||\n component_type === \"source_port\" ||\n component_type === \"schematic_port\"\n ) {\n const [component_name, port_selector] = selector\n .replace(/\\./g, \"\")\n .split(/[\\s\\>]+/)\n const source_component = soup.find(\n (e) =>\n e.type === \"source_component\" && e.name === component_name\n ) as SourceComponentBase\n if (!source_component) return null\n const source_port = soup.find(\n (e) =>\n e.type === \"source_port\" &&\n e.source_component_id ===\n source_component.source_component_id &&\n (e.name === port_selector ||\n (e.port_hints ?? []).includes(port_selector!))\n ) as SourcePort\n if (!source_port) return null\n if (component_type === \"source_port\") return source_port\n\n if (component_type === \"pcb_port\") {\n return soup.find(\n (e) =>\n e.type === \"pcb_port\" &&\n e.source_port_id === source_port.source_port_id\n )\n } else if (component_type === \"schematic_port\") {\n return soup.find(\n (e) =>\n e.type === \"schematic_port\" &&\n e.source_port_id === source_port.source_port_id\n )\n }\n }\n },\n }\n },\n }\n )\n\n return su\n}) as any\nsu.unparsed = su as any\n\nexport default su\n","export { CadViewer } from \"./CadViewer\"\n","import type { AnySoupElement } from \"@tscircuit/soup\"\n\nexport const useConvertChildrenToSoup = (\n children?: any,\n defaultSoup?: AnySoupElement[]\n) => {\n // TODO convert children if defined\n\n return defaultSoup!\n}\n","import type { AnySoupElement } from \"@tscircuit/soup\"\nimport { useConvertChildrenToSoup } from \"./hooks/use-convert-children-to-soup\"\nimport { su } from \"@tscircuit/soup-util\"\nimport { useMemo } from \"react\"\nimport { createBoardGeomFromSoup } from \"./soup-to-3d\"\nimport { useStlsFromGeom } from \"./hooks/use-stls-from-geom\"\nimport { STLModel } from \"./three-components/STLModel\"\nimport { CadViewerContainer } from \"./CadViewerContainer\"\nimport { MixedStlModel } from \"./three-components/MixedStlModel\"\nimport { Euler } from \"three\"\n\ninterface Props {\n soup?: AnySoupElement[]\n children?: any\n}\n\nexport const CadViewer = ({ soup, children }: Props) => {\n soup ??= useConvertChildrenToSoup(children, soup)\n\n const boardGeom = useMemo(() => {\n if (!soup.some((e) => e.type === \"pcb_board\")) return null\n return createBoardGeomFromSoup(soup)\n }, [soup])\n\n const { stls, loading } = useStlsFromGeom(boardGeom)\n\n const cad_components = su(soup).cad_component.list()\n\n // TODO canvas/camera etc.\n return (\n <CadViewerContainer>\n {stls.map(({ stlUrl, color }, index) => (\n <STLModel\n key={stlUrl}\n stlUrl={stlUrl}\n color={color}\n opacity={index === 0 ? 0.95 : 1}\n />\n ))}\n {cad_components.map((cad_component) => {\n const url = cad_component.model_obj_url ?? cad_component.model_stl_url\n if (!url) return null\n return (\n <MixedStlModel\n key={cad_component.cad_component_id}\n url={url}\n position={\n cad_component.position\n ? [\n cad_component.position.x,\n cad_component.position.y,\n cad_component.position.z,\n ]\n : undefined\n }\n rotation={\n cad_component.rotation\n ? new Euler(\n (cad_component.rotation.x * Math.PI) / 180,\n (cad_component.rotation.y * Math.PI) / 180,\n (cad_component.rotation.z * Math.PI) / 180\n )\n : undefined\n }\n />\n )\n })}\n </CadViewerContainer>\n )\n}\n","import type { Geom3 } from \"@jscad/modeling/src/geometries/types\"\nimport type { AnySoupElement, PCBPlatedHole } from \"@tscircuit/soup\"\nimport { su } from \"@tscircuit/soup-util\"\nimport { translate } from \"@jscad/modeling/src/operations/transforms\"\nimport { cuboid, cylinder, line } from \"@jscad/modeling/src/primitives\"\nimport { colorize } from \"@jscad/modeling/src/colors\"\nimport { subtract } from \"@jscad/modeling/src/operations/booleans\"\nimport { platedHole } from \"../geoms/plated-hole\"\nimport { M, colors } from \"../geoms/constants\"\nimport { extrudeLinear } from \"@jscad/modeling/src/operations/extrusions\"\nimport { expand } from \"@jscad/modeling/src/operations/expansions\"\n\nexport const createBoardGeomFromSoup = (soup: AnySoupElement[]): Geom3[] => {\n const board = su(soup).pcb_board.list()[0]\n if (!board) {\n throw new Error(\"No pcb_board found\")\n }\n\n const plated_holes = su(soup).pcb_plated_hole.list()\n const pads = su(soup).pcb_smtpad.list()\n const traces = su(soup).pcb_trace.list()\n const pcb_vias = su(soup).pcb_via.list()\n\n // PCB Board\n let boardGeom = cuboid({ size: [board.width, board.height, 1.2] })\n\n const platedHoleGeoms: Geom3[] = []\n const padGeoms: Geom3[] = []\n const traceGeoms: Geom3[] = []\n const ctx = {\n pcbThickness: 1.2,\n }\n\n const addPlatedHole = (plated_hole: PCBPlatedHole) => {\n if (!(plated_hole as any).shape) plated_hole.shape = \"circle\"\n if (plated_hole.shape === \"circle\") {\n const cyGeom = cylinder({\n center: [plated_hole.x, plated_hole.y, 0],\n radius: plated_hole.hole_diameter / 2 + M,\n })\n boardGeom = subtract(boardGeom, cyGeom)\n\n const platedHoleGeom = platedHole(plated_hole, ctx)\n platedHoleGeoms.push(platedHoleGeom)\n }\n }\n\n for (const plated_hole of plated_holes) {\n addPlatedHole(plated_hole)\n }\n\n for (const pad of pads) {\n if (pad.shape === \"rect\") {\n const padGeom = colorize(\n colors.copper,\n cuboid({\n center: [pad.x, pad.y, 1.2 / 2 + M],\n size: [pad.width, pad.height, M],\n })\n )\n padGeoms.push(padGeom)\n } else if (pad.shape === \"circle\") {\n const padGeom = colorize(\n colors.copper,\n cylinder({\n center: [pad.x, pad.y, 1.2 / 2 + M],\n radius: pad.radius,\n height: M,\n })\n )\n padGeoms.push(padGeom)\n }\n }\n\n for (const { route: mixedRoute } of traces) {\n if (mixedRoute.length < 2) continue\n const subRoutes = mixedRoute.reduce(\n (c, p) => {\n // @ts-ignore\n const lastLayer = c.current?.[c.current.length - 1]?.layer\n if (\n p.route_type === \"via\" ||\n (p.route_type === \"wire\" && p.layer !== lastLayer)\n ) {\n if (c.current.length > 2) {\n c.allPrev.push(c.current)\n }\n c.current = p.route_type === \"wire\" ? [p] : []\n return c\n }\n c.current.push(p)\n return c\n },\n {\n current: [] as typeof mixedRoute,\n allPrev: [] as Array<typeof mixedRoute>,\n }\n )\n for (const route of subRoutes.allPrev.concat([subRoutes.current])) {\n // TODO break into segments based on layers\n const linePath = line(route.map((p) => [p.x, p.y]))\n\n const layer = route[0]!.route_type === \"wire\" ? route[0]!.layer : \"top\"\n const layerSign = layer === \"top\" ? 1 : -1\n // traceGeoms.push(traceGeom)\n let traceGeom = translate(\n [0, 0, (layerSign * 1.2) / 2],\n extrudeLinear(\n { height: M * layerSign },\n expand({ delta: 0.1, corners: \"edge\" }, linePath)\n )\n )\n\n // HACK: Subtract all vias from every trace- this mostly is because the\n // vias aren't inside the route- we should probably pre-filter to make sure\n // that vias are only near the route\n for (const via of pcb_vias) {\n traceGeom = subtract(\n traceGeom,\n cylinder({\n center: [via.x, via.y, 0],\n radius: via.outer_diameter / 2,\n height: 5,\n })\n )\n }\n\n traceGeom = colorize(colors.fr4GreenSolderWithMask, traceGeom)\n\n traceGeoms.push(traceGeom)\n }\n for (const via of mixedRoute.filter((p) => p.route_type === \"via\")) {\n if (via.route_type !== \"via\") continue // TODO remove when ts is smart\n\n addPlatedHole({\n x: via.x,\n y: via.y,\n hole_diameter: 0.8,\n outer_diameter: 1.6,\n shape: \"circle\",\n layers: [\"top\", \"bottom\"],\n type: \"pcb_plated_hole\",\n })\n }\n }\n\n for (const via of pcb_vias) {\n addPlatedHole({\n x: via.x,\n y: via.y,\n hole_diameter: via.hole_diameter,\n outer_diameter: via.outer_diameter,\n shape: \"circle\",\n layers: [\"top\", \"bottom\"],\n type: \"pcb_plated_hole\",\n })\n }\n\n // Colorize to a PCB green color: #05A32E\n boardGeom = colorize(colors.fr4Green, boardGeom)\n\n return [boardGeom, ...platedHoleGeoms, ...padGeoms, ...traceGeoms]\n}\n","import type { PCBPlatedHole } from \"@tscircuit/soup\"\nimport type { Geom3 } from \"@jscad/modeling/src/geometries/types\"\nimport { cylinder } from \"@jscad/modeling/src/primitives\"\nimport { colorize } from \"@jscad/modeling/src/colors\"\nimport { subtract, union } from \"@jscad/modeling/src/operations/booleans\"\nimport { M, colors } from \"./constants\"\nimport { GeomContext } from \"../GeomContext\"\n\nexport const platedHole = (\n plated_hole: PCBPlatedHole,\n ctx: GeomContext\n): Geom3 => {\n if (!(plated_hole as any).shape) plated_hole.shape = \"circle\"\n if (plated_hole.shape === \"circle\") {\n return colorize(\n colors.copper,\n subtract(\n union(\n cylinder({\n center: [plated_hole.x, plated_hole.y, 0],\n radius: plated_hole.hole_diameter / 2,\n height: 1.2,\n }),\n cylinder({\n center: [plated_hole.x, plated_hole.y, 1.2 / 2],\n radius: plated_hole.outer_diameter / 2,\n height: M,\n }),\n cylinder({\n center: [plated_hole.x, plated_hole.y, -1.2 / 2],\n radius: plated_hole.outer_diameter / 2,\n height: M,\n })\n ),\n cylinder({\n center: [plated_hole.x, plated_hole.y, 0],\n radius: plated_hole.hole_diameter / 2 - M,\n height: 1.5,\n })\n )\n )\n } else {\n throw new Error(`Unsupported plated hole shape: ${plated_hole.shape}`)\n }\n}\n","import type { RGB } from \"@jscad/modeling/src/colors\"\n\nexport const M = 0.01\n\nexport const colors = {\n copper: [0.9, 0.6, 0.2],\n fr4Green: [0x05 / 255, 0xa3 / 255, 0x2e / 255],\n fr4GreenSolderWithMask: [0x00 / 255, 0x98 / 255, 0x13 / 255],\n} satisfies Record<string, RGB>\n","import { useState, useEffect } from \"react\"\nimport stlSerializer from \"@jscad/stl-serializer\"\nimport { Geom3 } from \"@jscad/modeling/src/geometries/types\"\n\nfunction blobToBase64Url(blob: Blob): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader()\n reader.onload = () => {\n resolve(reader.result as string)\n }\n reader.onerror = reject\n reader.readAsDataURL(blob)\n })\n}\n\ntype StlObj = { stlUrl: string; color: number[] }\n\nexport const useStlsFromGeom = (\n geom: Geom3[] | Geom3 | null\n): {\n stls: StlObj[]\n loading: boolean\n} => {\n const [stls, setStls] = useState<StlObj[]>([])\n const [loading, setLoading] = useState(true)\n\n useEffect(() => {\n if (!geom) return\n const generateStls = async () => {\n setLoading(true)\n const geometries = Array.isArray(geom) ? geom : [geom]\n\n const stlPromises = geometries.map(async (g) => {\n const rawData = stlSerializer.serialize({ binary: true }, [g])\n const blobData = new Blob(rawData)\n const stlUrl = await blobToBase64Url(blobData)\n return { stlUrl, color: g.color! }\n })\n\n try {\n const generatedStls = await Promise.all(stlPromises)\n setStls(generatedStls)\n } catch (error) {\n console.error(\"Error generating STLs:\", error)\n setStls([])\n } finally {\n setLoading(false)\n }\n }\n\n generateStls()\n }, [geom])\n\n return { stls, loading }\n}\n","import { useLoader } from \"@react-three/fiber\"\nimport { useRef } from \"react\"\nimport * as THREE from \"three\"\nimport { MTLLoader, OBJLoader, STLLoader } from \"three-stdlib\"\n\nexport function STLModel({\n stlUrl,\n mtlUrl,\n color,\n opacity = 1,\n}: {\n stlUrl: string\n color?: any\n mtlUrl?: string\n opacity?: number\n}) {\n const geom = useLoader(STLLoader, stlUrl)\n const mesh = useRef<THREE.Mesh>()\n\n // TODO handle mtl url\n\n return (\n <mesh ref={mesh as any}>\n <primitive object={geom} attach=\"geometry\" />\n <meshStandardMaterial\n color={color}\n transparent={opacity !== 1}\n opacity={opacity}\n />\n {/* <Outlines thickness={0.05} color=\"black\" opacity={0.25} /> */}\n </mesh>\n )\n}\n","import {\n Canvas,\n useFrame,\n extend,\n useThree,\n useLoader,\n} from \"@react-three/fiber\"\nimport { Suspense, useEffect, useMemo, useRef, useState } from \"react\"\nimport { OrbitControls, Grid, Outlines } from \"@react-three/drei\"\nimport * as THREE from \"three\"\nimport { CubeWithLabeledSides } from \"./three-components/cube-with-labeled-sides\"\nimport { createBoardGeomFromSoup } from \"./soup-to-3d\"\nimport soup from \"./bug-pads-and-traces.json\"\n// import soup from \"./plated-hole-board.json\"\nimport stlSerializer from \"@jscad/stl-serializer\"\n// import { STLLoader } from \"three/examples/jsm/loaders/STLLoader\"\nimport { MTLLoader, OBJLoader, STLLoader } from \"three-stdlib\"\nimport packageJson from \"../package.json\"\n\nexport const RotationTracker = () => {\n useFrame(({ camera }) => {\n window.TSCI_MAIN_CAMERA_ROTATION = camera.rotation\n })\n\n return <></>\n}\n\nexport const CadViewerContainer = ({ children }: { children: any }) => {\n return (\n <div style={{ position: \"relative\", width: \"100%\", height: \"100%\" }}>\n <div\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n width: 120,\n height: 120,\n }}\n >\n <Canvas\n camera={{\n up: [0, 0, 1],\n // rotation: [-Math.PI / 2, 0, 0],\n // lookAt: new THREE.Vector3(0, 0, 0),\n position: [1, 1, 1],\n }}\n >\n <ambientLight intensity={Math.PI / 2} />\n <CubeWithLabeledSides />\n </Canvas>\n </div>\n <Canvas\n scene={{ up: [0, 0, 1] }}\n camera={{ up: [0, 0, 1], position: [5, 5, 5] }}\n >\n <RotationTracker />\n <OrbitControls autoRotate autoRotateSpeed={1} />\n <ambientLight intensity={Math.PI / 2} />\n <pointLight\n position={[-10, -10, 10]}\n decay={0}\n intensity={Math.PI / 4}\n />\n <Grid\n rotation={[Math.PI / 2, 0, 0]}\n infiniteGrid={true}\n cellSize={1}\n sectionSize={10}\n />\n {children}\n </Canvas>\n <div\n style={{\n position: \"absolute\",\n right: 24,\n bottom: 24,\n fontFamily: \"sans-serif\",\n color: \"white\",\n WebkitTextStroke: \"0.5px rgba(0, 0, 0, 0.5)\",\n // color: \"rgba(255, 255, 255, 0.75)\",\n // textShadow:\n // \"0px 0px 1px rgba(0, 0, 0, 0.5), 0px 0px 2px rgba(0, 0, 0, 0.5)\",\n fontSize: 11,\n }}\n >\n @{packageJson.version}\n </div>\n </div>\n )\n}\n","import React, { useRef } from \"react\"\nimport { Canvas, useFrame } from \"@react-three/fiber\"\nimport { OrbitControls, Text } from \"@react-three/drei\"\nimport * as THREE from \"three\"\n\ndeclare global {\n interface Window {\n TSCI_MAIN_CAMERA_ROTATION: THREE.Euler\n }\n}\nif (typeof window !== \"undefined\") {\n window.TSCI_MAIN_CAMERA_ROTATION = new THREE.Euler(0, 0, 0)\n}\n\nfunction computePointInFront(rotationVector, distance) {\n // Create a quaternion from the rotation vector\n const quaternion = new THREE.Quaternion().setFromEuler(\n new THREE.Euler(rotationVector.x, rotationVector.y, rotationVector.z)\n )\n\n // Create a vector pointing forward (along the negative z-axis)\n const forwardVector = new THREE.Vector3(0, 0, 1)\n\n // Apply the rotation to the forward vector\n forwardVector.applyQuaternion(quaternion)\n\n // Scale the rotated vector by the distance\n const result = forwardVector.multiplyScalar(distance)\n\n return result\n}\n\nexport const CubeWithLabeledSides = ({}: any) => {\n const ref = useRef<THREE.Mesh>()\n const rotationTrackingRef = useRef({ lastRotation: new THREE.Euler() })\n useFrame((state, delta) => {\n if (!ref.current) return\n\n const mainRot = window.TSCI_MAIN_CAMERA_ROTATION\n\n // Use window.TSCI_CAMERA_ROTATION to compute the position of the camera\n const cameraPosition = computePointInFront(mainRot, 2)\n\n state.camera.position.copy(cameraPosition)\n state.camera.lookAt(0, 0, 0)\n })\n return (\n <mesh ref={ref as any} rotation={[Math.PI / 2, 0, 0]}>\n <boxGeometry args={[1, 1, 1]} />\n <meshStandardMaterial color=\"white\" />\n <Text position={[0, 0, 0.51]} fontSize={0.25} color=\"black\">\n Front\n </Text>\n <Text\n position={[0, 0, -0.51]}\n fontSize={0.25}\n color=\"black\"\n rotation={[0, Math.PI, 0]}\n >\n Back\n </Text>\n <Text\n position={[0.51, 0, 0]}\n fontSize={0.25}\n color=\"black\"\n rotation={[0, Math.PI / 2, 0]}\n >\n Right\n </Text>\n <Text\n position={[-0.51, 0, 0]}\n fontSize={0.25}\n color=\"black\"\n rotation={[0, -Math.PI / 2, 0]}\n >\n Left\n </Text>\n <Text\n position={[0, 0.51, 0]}\n fontSize={0.25}\n color=\"black\"\n rotation={[-Math.PI / 2, 0, 0]}\n >\n Top\n </Text>\n <Text\n position={[0, -0.51, 0]}\n fontSize={0.25}\n color=\"black\"\n rotation={[Math.PI / 2, 0, 0]}\n >\n Bottom\n </Text>\n <lineSegments\n args={[new THREE.EdgesGeometry(new THREE.BoxGeometry(1, 1, 1))]}\n material={\n new THREE.LineBasicMaterial({\n color: 0x000000,\n linewidth: 2,\n })\n }\n />\n </mesh>\n )\n}\n","{\n \"name\": \"@tscircuit/3d-viewer\",\n \"version\": \"0.0.12\",\n \"main\": \"./dist/index.js\",\n \"files\": [\n \"dist\"\n ],\n \"scripts\": {\n \"start\": \"bun run storybook\",\n \"dev:old\": \"bunx --bun vite\",\n \"build\": \"tsup ./src/index.tsx --dts --sourcemap\",\n \"prepublish\": \"npm run build\",\n \"preview\": \"vite preview\",\n \"storybook\": \"storybook dev -p 6006\",\n \"build-storybook\": \"storybook build\"\n },\n \"dependencies\": {\n \"@jscad/modeling\": \"^2.12.2\",\n \"@jscad/regl-renderer\": \"^2.6.9\",\n \"@jscad/stl-serializer\": \"^2.1.17\",\n \"@react-three/drei\": \"^9.107.2\",\n \"@react-three/fiber\": \"^8.16.8\",\n \"@types/three\": \"^0.165.0\",\n \"react\": \"^18.3.1\",\n \"react-dom\": \"^18.3.1\",\n \"react-use-gesture\": \"^9.1.3\",\n \"three\": \"^0.165.0\",\n \"three-stdlib\": \"^2.30.3\"\n },\n \"devDependencies\": {\n \"@biomejs/biome\": \"^1.8.3\",\n \"@chromatic-com/storybook\": \"^1.5.0\",\n \"@storybook/addon-essentials\": \"^8.1.10\",\n \"@storybook/addon-interactions\": \"^8.1.10\",\n \"@storybook/addon-links\": \"^8.1.10\",\n \"@storybook/addon-onboarding\": \"^8.1.10\",\n \"@storybook/blocks\": \"^8.1.10\",\n \"@storybook/builder-vite\": \"^8.1.10\",\n \"@storybook/react\": \"^8.1.10\",\n \"@storybook/react-vite\": \"^8.1.10\",\n \"@storybook/test\": \"^8.1.10\",\n \"@tscircuit/soup\": \"^0.0.39\",\n \"@tscircuit/soup-util\": \"^0.0.11\",\n \"@types/react\": \"^18.3.3\",\n \"@types/react-dom\": \"^18.3.0\",\n \"@vitejs/plugin-react\": \"^4.3.1\",\n \"storybook\": \"^8.1.10\",\n \"strip-ansi\": \"^7.1.0\",\n \"tsup\": \"^8.1.0\",\n \"typescript\": \"^5.5.3\",\n \"vite\": \"^5.3.1\",\n \"vite-tsconfig-paths\": \"^4.3.2\"\n }\n}\n","import { useState, useEffect } from \"react\"\nimport type { Group } from \"three\"\nimport { MTLLoader, OBJLoader } from \"three-stdlib\"\n\n// Define the type for our cache\ninterface CacheItem {\n promise: Promise<any>\n result: Group | null\n}\n\ndeclare global {\n interface Window {\n TSCIRCUIT_OBJ_LOADER_CACHE: Map<string, CacheItem>\n }\n}\n\n// Ensure the global cache exists\nif (typeof window !== \"undefined\" && !window.TSCIRCUIT_OBJ_LOADER_CACHE) {\n window.TSCIRCUIT_OBJ_LOADER_CACHE = new Map<string, CacheItem>()\n}\n\nexport function useGlobalObjLoader(url: string | null): Group | null {\n const [obj, setObj] = useState<Group | null>(null)\n\n useEffect(() => {\n if (!url) return\n\n const cache = window.TSCIRCUIT_OBJ_LOADER_CACHE\n let hasUrlChanged = false\n\n async function loadAndParseObj() {\n const response = await fetch(url!)\n const text = await response.text()\n\n const mtlContent = text\n .match(/newmtl[\\s\\S]*?endmtl/g)\n ?.join(\"\\n\")!\n .replace(/d 0\\./g, \"d 1.\")!\n const objContent = text.replace(/newmtl[\\s\\S]*?endmtl/g, \"\")\n\n const mtlLoader = new MTLLoader()\n mtlLoader.setMaterialOptions({\n invertTrProperty: true,\n })\n const materials = mtlLoader.parse(\n mtlContent.replace(\n /Kd\\s+([\\d.]+)\\s+([\\d.]+)\\s+([\\d.]+)/g,\n \"Kd $2 $2 $2\"\n ),\n \"test.mtl\"\n )\n\n const objLoader = new OBJLoader()\n objLoader.setMaterials(materials)\n return objLoader.parse(objContent)\n }\n\n function loadUrl() {\n if (cache.has(url!)) {\n const cacheItem = cache.get(url!)!\n if (cacheItem.result) {\n // If we have a result, clone it\n return Promise.resolve(cacheItem.result.clone())\n }\n // If we're still loading, return the existing promise\n return cacheItem.promise.then((result) => result.clone())\n }\n // If it's not in the cache, create a new promise and cache it\n const promise = loadAndParseObj().then((result) => {\n cache.set(url!, { ...cache.get(url!)!, result })\n return result\n })\n cache.set(url!, { promise, result: null })\n return promise\n }\n\n loadUrl()\n .then((result) => {\n if (hasUrlChanged) return\n setObj(result)\n })\n .catch((error) => {\n console.error(error)\n })\n\n return () => {\n hasUrlChanged = true\n }\n }, [url])\n\n return obj\n}\n","import { useEffect, useState } from \"react\"\nimport { useGlobalObjLoader } from \"src/hooks/use-global-obj-loader\"\nimport { Euler, Vector3 } from \"three\"\nimport { MTLLoader, OBJLoader } from \"three-stdlib\"\n\nexport function MixedStlModel({\n url,\n position,\n rotation,\n}: {\n url: string\n position?: Vector3 | [number, number, number]\n rotation?: Euler | [number, number, number]\n}) {\n const obj = useGlobalObjLoader(url)\n\n if (!obj) {\n return (\n <mesh position={position}>\n <boxGeometry args={[0.5, 0.5, 0.5]} />\n <meshStandardMaterial transparent color=\"red\" opacity={0.25} />\n </mesh>\n )\n }\n\n return <primitive rotation={rotation} position={position} object={obj} />\n}\n"],"mappings":"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","names":["__export","su","module","__toCommonJS","import_soup_util","import_react","import_primitives","import_colors","import_booleans","stlSerializer","import_react","import_fiber","import_drei","import_react","import_fiber","import_jsx_runtime","import_jsx_runtime","import_react","import_three_stdlib","import_jsx_runtime","import_jsx_runtime"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.tsx","../src/hooks/use-convert-children-to-soup.ts","../src/CadViewer.tsx","../src/soup-to-3d/index.ts","../src/geoms/plated-hole.ts","../src/geoms/constants.ts","../src/hooks/use-stls-from-geom.ts","../src/three-components/STLModel.tsx","../src/CadViewerContainer.tsx","../src/three-components/cube-with-labeled-sides.tsx","../package.json","../src/hooks/use-global-obj-loader.ts","../src/three-components/MixedStlModel.tsx","../src/three-components/JscadModel.tsx"],"sourcesContent":["export { CadViewer } from \"./CadViewer\"\n","import type { AnySoupElement } from \"@tscircuit/soup\"\nimport { useRenderedElements } from \"@tscircuit/react-fiber\"\n\nexport const useConvertChildrenToSoup = (\n children?: any,\n defaultSoup?: AnySoupElement[],\n): AnySoupElement[] => {\n const { elements } = useRenderedElements(children)\n\n return (elements as any) ?? defaultSoup!\n}\n","import type { AnySoupElement } from \"@tscircuit/soup\"\nimport { useConvertChildrenToSoup } from \"./hooks/use-convert-children-to-soup\"\nimport { su } from \"@tscircuit/soup-util\"\nimport { useMemo } from \"react\"\nimport { createBoardGeomFromSoup } from \"./soup-to-3d\"\nimport { useStlsFromGeom } from \"./hooks/use-stls-from-geom\"\nimport { STLModel } from \"./three-components/STLModel\"\nimport { CadViewerContainer } from \"./CadViewerContainer\"\nimport { MixedStlModel } from \"./three-components/MixedStlModel\"\nimport { Euler } from \"three\"\nimport { JscadModel } from \"./three-components/JscadModel\"\n\ninterface Props {\n soup?: AnySoupElement[]\n children?: any\n}\n\nexport const CadViewer = ({ soup, children }: Props) => {\n soup ??= useConvertChildrenToSoup(children, soup)\n\n const boardGeom = useMemo(() => {\n if (!soup.some((e) => e.type === \"pcb_board\")) return null\n return createBoardGeomFromSoup(soup)\n }, [soup])\n\n const { stls, loading } = useStlsFromGeom(boardGeom)\n\n const cad_components = su(soup).cad_component.list()\n\n // TODO canvas/camera etc.\n return (\n <CadViewerContainer>\n {stls.map(({ stlUrl, color }, index) => (\n <STLModel\n key={stlUrl}\n stlUrl={stlUrl}\n color={color}\n opacity={index === 0 ? 0.95 : 1}\n />\n ))}\n {cad_components.map((cad_component) => {\n const url = cad_component.model_obj_url ?? cad_component.model_stl_url\n if (url) {\n return (\n <MixedStlModel\n key={cad_component.cad_component_id}\n url={url}\n position={\n cad_component.position\n ? [\n cad_component.position.x,\n cad_component.position.y,\n cad_component.position.z,\n ]\n : undefined\n }\n rotation={\n cad_component.rotation\n ? new Euler(\n (cad_component.rotation.x * Math.PI) / 180,\n (cad_component.rotation.y * Math.PI) / 180,\n (cad_component.rotation.z * Math.PI) / 180,\n )\n : undefined\n }\n />\n )\n }\n\n if (cad_component.model_jscad) {\n return (\n <JscadModel\n key={cad_component.cad_component_id}\n jscadPlan={cad_component.model_jscad as any}\n />\n )\n }\n })}\n </CadViewerContainer>\n )\n}\n","import type { Geom3 } from \"@jscad/modeling/src/geometries/types\"\nimport type { AnySoupElement, PCBPlatedHole } from \"@tscircuit/soup\"\nimport { su } from \"@tscircuit/soup-util\"\nimport { translate } from \"@jscad/modeling/src/operations/transforms\"\nimport { cuboid, cylinder, line } from \"@jscad/modeling/src/primitives\"\nimport { colorize } from \"@jscad/modeling/src/colors\"\nimport { subtract } from \"@jscad/modeling/src/operations/booleans\"\nimport { platedHole } from \"../geoms/plated-hole\"\nimport { M, colors } from \"../geoms/constants\"\nimport { extrudeLinear } from \"@jscad/modeling/src/operations/extrusions\"\nimport { expand } from \"@jscad/modeling/src/operations/expansions\"\n\nexport const createBoardGeomFromSoup = (soup: AnySoupElement[]): Geom3[] => {\n const board = su(soup).pcb_board.list()[0]\n if (!board) {\n throw new Error(\"No pcb_board found\")\n }\n\n const plated_holes = su(soup).pcb_plated_hole.list()\n const pads = su(soup).pcb_smtpad.list()\n const traces = su(soup).pcb_trace.list()\n const pcb_vias = su(soup).pcb_via.list()\n\n // PCB Board\n let boardGeom = cuboid({ size: [board.width, board.height, 1.2] })\n\n const platedHoleGeoms: Geom3[] = []\n const padGeoms: Geom3[] = []\n const traceGeoms: Geom3[] = []\n const ctx = {\n pcbThickness: 1.2,\n }\n\n const addPlatedHole = (plated_hole: PCBPlatedHole) => {\n if (!(plated_hole as any).shape) plated_hole.shape = \"circle\"\n if (plated_hole.shape === \"circle\") {\n const cyGeom = cylinder({\n center: [plated_hole.x, plated_hole.y, 0],\n radius: plated_hole.hole_diameter / 2 + M,\n })\n boardGeom = subtract(boardGeom, cyGeom)\n\n const platedHoleGeom = platedHole(plated_hole, ctx)\n platedHoleGeoms.push(platedHoleGeom)\n }\n }\n\n for (const plated_hole of plated_holes) {\n addPlatedHole(plated_hole)\n }\n\n for (const pad of pads) {\n if (pad.shape === \"rect\") {\n const padGeom = colorize(\n colors.copper,\n cuboid({\n center: [pad.x, pad.y, 1.2 / 2 + M],\n size: [pad.width, pad.height, M],\n })\n )\n padGeoms.push(padGeom)\n } else if (pad.shape === \"circle\") {\n const padGeom = colorize(\n colors.copper,\n cylinder({\n center: [pad.x, pad.y, 1.2 / 2 + M],\n radius: pad.radius,\n height: M,\n })\n )\n padGeoms.push(padGeom)\n }\n }\n\n for (const { route: mixedRoute } of traces) {\n if (mixedRoute.length < 2) continue\n const subRoutes = mixedRoute.reduce(\n (c, p) => {\n // @ts-ignore\n const lastLayer = c.current?.[c.current.length - 1]?.layer\n if (\n p.route_type === \"via\" ||\n (p.route_type === \"wire\" && p.layer !== lastLayer)\n ) {\n if (c.current.length > 2) {\n c.allPrev.push(c.current)\n }\n c.current = p.route_type === \"wire\" ? [p] : []\n return c\n }\n c.current.push(p)\n return c\n },\n {\n current: [] as typeof mixedRoute,\n allPrev: [] as Array<typeof mixedRoute>,\n }\n )\n for (const route of subRoutes.allPrev.concat([subRoutes.current])) {\n // TODO break into segments based on layers\n const linePath = line(route.map((p) => [p.x, p.y]))\n\n const layer = route[0]!.route_type === \"wire\" ? route[0]!.layer : \"top\"\n const layerSign = layer === \"top\" ? 1 : -1\n // traceGeoms.push(traceGeom)\n let traceGeom = translate(\n [0, 0, (layerSign * 1.2) / 2],\n extrudeLinear(\n { height: M * layerSign },\n expand({ delta: 0.1, corners: \"edge\" }, linePath)\n )\n )\n\n // HACK: Subtract all vias from every trace- this mostly is because the\n // vias aren't inside the route- we should probably pre-filter to make sure\n // that vias are only near the route\n for (const via of pcb_vias) {\n traceGeom = subtract(\n traceGeom,\n cylinder({\n center: [via.x, via.y, 0],\n radius: via.outer_diameter / 2,\n height: 5,\n })\n )\n }\n\n traceGeom = colorize(colors.fr4GreenSolderWithMask, traceGeom)\n\n traceGeoms.push(traceGeom)\n }\n for (const via of mixedRoute.filter((p) => p.route_type === \"via\")) {\n if (via.route_type !== \"via\") continue // TODO remove when ts is smart\n\n addPlatedHole({\n x: via.x,\n y: via.y,\n hole_diameter: 0.8,\n outer_diameter: 1.6,\n shape: \"circle\",\n layers: [\"top\", \"bottom\"],\n type: \"pcb_plated_hole\",\n })\n }\n }\n\n for (const via of pcb_vias) {\n addPlatedHole({\n x: via.x,\n y: via.y,\n hole_diameter: via.hole_diameter,\n outer_diameter: via.outer_diameter,\n shape: \"circle\",\n layers: [\"top\", \"bottom\"],\n type: \"pcb_plated_hole\",\n })\n }\n\n // Colorize to a PCB green color: #05A32E\n boardGeom = colorize(colors.fr4Green, boardGeom)\n\n return [boardGeom, ...platedHoleGeoms, ...padGeoms, ...traceGeoms]\n}\n","import type { PCBPlatedHole } from \"@tscircuit/soup\"\nimport type { Geom3 } from \"@jscad/modeling/src/geometries/types\"\nimport { cylinder } from \"@jscad/modeling/src/primitives\"\nimport { colorize } from \"@jscad/modeling/src/colors\"\nimport { subtract, union } from \"@jscad/modeling/src/operations/booleans\"\nimport { M, colors } from \"./constants\"\nimport { GeomContext } from \"../GeomContext\"\n\nexport const platedHole = (\n plated_hole: PCBPlatedHole,\n ctx: GeomContext\n): Geom3 => {\n if (!(plated_hole as any).shape) plated_hole.shape = \"circle\"\n if (plated_hole.shape === \"circle\") {\n return colorize(\n colors.copper,\n subtract(\n union(\n cylinder({\n center: [plated_hole.x, plated_hole.y, 0],\n radius: plated_hole.hole_diameter / 2,\n height: 1.2,\n }),\n cylinder({\n center: [plated_hole.x, plated_hole.y, 1.2 / 2],\n radius: plated_hole.outer_diameter / 2,\n height: M,\n }),\n cylinder({\n center: [plated_hole.x, plated_hole.y, -1.2 / 2],\n radius: plated_hole.outer_diameter / 2,\n height: M,\n })\n ),\n cylinder({\n center: [plated_hole.x, plated_hole.y, 0],\n radius: plated_hole.hole_diameter / 2 - M,\n height: 1.5,\n })\n )\n )\n } else {\n throw new Error(`Unsupported plated hole shape: ${plated_hole.shape}`)\n }\n}\n","import type { RGB } from \"@jscad/modeling/src/colors\"\n\nexport const M = 0.01\n\nexport const colors = {\n copper: [0.9, 0.6, 0.2],\n fr4Green: [0x05 / 255, 0xa3 / 255, 0x2e / 255],\n fr4GreenSolderWithMask: [0x00 / 255, 0x98 / 255, 0x13 / 255],\n} satisfies Record<string, RGB>\n","import { useState, useEffect } from \"react\"\nimport stlSerializer from \"@jscad/stl-serializer\"\nimport { Geom3 } from \"@jscad/modeling/src/geometries/types\"\n\nfunction blobToBase64Url(blob: Blob): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader()\n reader.onload = () => {\n resolve(reader.result as string)\n }\n reader.onerror = reject\n reader.readAsDataURL(blob)\n })\n}\n\ntype StlObj = { stlUrl: string; color: number[] }\n\nexport const useStlsFromGeom = (\n geom: Geom3[] | Geom3 | null\n): {\n stls: StlObj[]\n loading: boolean\n} => {\n const [stls, setStls] = useState<StlObj[]>([])\n const [loading, setLoading] = useState(true)\n\n useEffect(() => {\n if (!geom) return\n const generateStls = async () => {\n setLoading(true)\n const geometries = Array.isArray(geom) ? geom : [geom]\n\n const stlPromises = geometries.map(async (g) => {\n const rawData = stlSerializer.serialize({ binary: true }, [g])\n const blobData = new Blob(rawData)\n const stlUrl = await blobToBase64Url(blobData)\n return { stlUrl, color: g.color! }\n })\n\n try {\n const generatedStls = await Promise.all(stlPromises)\n setStls(generatedStls)\n } catch (error) {\n console.error(\"Error generating STLs:\", error)\n setStls([])\n } finally {\n setLoading(false)\n }\n }\n\n generateStls()\n }, [geom])\n\n return { stls, loading }\n}\n","import { useLoader } from \"@react-three/fiber\"\nimport { useRef } from \"react\"\nimport * as THREE from \"three\"\nimport { MTLLoader, OBJLoader, STLLoader } from \"three-stdlib\"\n\nexport function STLModel({\n stlUrl,\n mtlUrl,\n color,\n opacity = 1,\n}: {\n stlUrl: string\n color?: any\n mtlUrl?: string\n opacity?: number\n}) {\n const geom = useLoader(STLLoader, stlUrl)\n const mesh = useRef<THREE.Mesh>()\n\n // TODO handle mtl url\n\n return (\n <mesh ref={mesh as any}>\n <primitive object={geom} attach=\"geometry\" />\n <meshStandardMaterial\n color={color}\n transparent={opacity !== 1}\n opacity={opacity}\n />\n {/* <Outlines thickness={0.05} color=\"black\" opacity={0.25} /> */}\n </mesh>\n )\n}\n","import {\n Canvas,\n useFrame,\n extend,\n useThree,\n useLoader,\n} from \"@react-three/fiber\"\nimport { Suspense, useEffect, useMemo, useRef, useState } from \"react\"\nimport { OrbitControls, Grid, Outlines } from \"@react-three/drei\"\nimport * as THREE from \"three\"\nimport { CubeWithLabeledSides } from \"./three-components/cube-with-labeled-sides\"\nimport { createBoardGeomFromSoup } from \"./soup-to-3d\"\nimport stlSerializer from \"@jscad/stl-serializer\"\n// import { STLLoader } from \"three/examples/jsm/loaders/STLLoader\"\nimport { MTLLoader, OBJLoader, STLLoader } from \"three-stdlib\"\nimport packageJson from \"../package.json\"\n\nexport const RotationTracker = () => {\n useFrame(({ camera }) => {\n window.TSCI_MAIN_CAMERA_ROTATION = camera.rotation\n })\n\n return <></>\n}\n\nexport const CadViewerContainer = ({ children }: { children: any }) => {\n return (\n <div style={{ position: \"relative\", width: \"100%\", height: \"100%\" }}>\n <div\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n width: 120,\n height: 120,\n }}\n >\n <Canvas\n camera={{\n up: [0, 0, 1],\n // rotation: [-Math.PI / 2, 0, 0],\n // lookAt: new THREE.Vector3(0, 0, 0),\n position: [1, 1, 1],\n }}\n >\n <ambientLight intensity={Math.PI / 2} />\n <CubeWithLabeledSides />\n </Canvas>\n </div>\n <Canvas\n scene={{ up: [0, 0, 1] }}\n camera={{ up: [0, 0, 1], position: [5, 5, 5] }}\n >\n <RotationTracker />\n <OrbitControls autoRotate autoRotateSpeed={1} />\n <ambientLight intensity={Math.PI / 2} />\n <pointLight\n position={[-10, -10, 10]}\n decay={0}\n intensity={Math.PI / 4}\n />\n <Grid\n rotation={[Math.PI / 2, 0, 0]}\n infiniteGrid={true}\n cellSize={1}\n sectionSize={10}\n />\n {children}\n </Canvas>\n <div\n style={{\n position: \"absolute\",\n right: 24,\n bottom: 24,\n fontFamily: \"sans-serif\",\n color: \"white\",\n WebkitTextStroke: \"0.5px rgba(0, 0, 0, 0.5)\",\n // color: \"rgba(255, 255, 255, 0.75)\",\n // textShadow:\n // \"0px 0px 1px rgba(0, 0, 0, 0.5), 0px 0px 2px rgba(0, 0, 0, 0.5)\",\n fontSize: 11,\n }}\n >\n @{packageJson.version}\n </div>\n </div>\n )\n}\n","import React, { useRef } from \"react\"\nimport { Canvas, useFrame } from \"@react-three/fiber\"\nimport { OrbitControls, Text } from \"@react-three/drei\"\nimport * as THREE from \"three\"\n\ndeclare global {\n interface Window {\n TSCI_MAIN_CAMERA_ROTATION: THREE.Euler\n }\n}\nif (typeof window !== \"undefined\") {\n window.TSCI_MAIN_CAMERA_ROTATION = new THREE.Euler(0, 0, 0)\n}\n\nfunction computePointInFront(rotationVector, distance) {\n // Create a quaternion from the rotation vector\n const quaternion = new THREE.Quaternion().setFromEuler(\n new THREE.Euler(rotationVector.x, rotationVector.y, rotationVector.z)\n )\n\n // Create a vector pointing forward (along the negative z-axis)\n const forwardVector = new THREE.Vector3(0, 0, 1)\n\n // Apply the rotation to the forward vector\n forwardVector.applyQuaternion(quaternion)\n\n // Scale the rotated vector by the distance\n const result = forwardVector.multiplyScalar(distance)\n\n return result\n}\n\nexport const CubeWithLabeledSides = ({}: any) => {\n const ref = useRef<THREE.Mesh>()\n const rotationTrackingRef = useRef({ lastRotation: new THREE.Euler() })\n useFrame((state, delta) => {\n if (!ref.current) return\n\n const mainRot = window.TSCI_MAIN_CAMERA_ROTATION\n\n // Use window.TSCI_CAMERA_ROTATION to compute the position of the camera\n const cameraPosition = computePointInFront(mainRot, 2)\n\n state.camera.position.copy(cameraPosition)\n state.camera.lookAt(0, 0, 0)\n })\n return (\n <mesh ref={ref as any} rotation={[Math.PI / 2, 0, 0]}>\n <boxGeometry args={[1, 1, 1]} />\n <meshStandardMaterial color=\"white\" />\n <Text position={[0, 0, 0.51]} fontSize={0.25} color=\"black\">\n Front\n </Text>\n <Text\n position={[0, 0, -0.51]}\n fontSize={0.25}\n color=\"black\"\n rotation={[0, Math.PI, 0]}\n >\n Back\n </Text>\n <Text\n position={[0.51, 0, 0]}\n fontSize={0.25}\n color=\"black\"\n rotation={[0, Math.PI / 2, 0]}\n >\n Right\n </Text>\n <Text\n position={[-0.51, 0, 0]}\n fontSize={0.25}\n color=\"black\"\n rotation={[0, -Math.PI / 2, 0]}\n >\n Left\n </Text>\n <Text\n position={[0, 0.51, 0]}\n fontSize={0.25}\n color=\"black\"\n rotation={[-Math.PI / 2, 0, 0]}\n >\n Top\n </Text>\n <Text\n position={[0, -0.51, 0]}\n fontSize={0.25}\n color=\"black\"\n rotation={[Math.PI / 2, 0, 0]}\n >\n Bottom\n </Text>\n <lineSegments\n args={[new THREE.EdgesGeometry(new THREE.BoxGeometry(1, 1, 1))]}\n material={\n new THREE.LineBasicMaterial({\n color: 0x000000,\n linewidth: 2,\n })\n }\n />\n </mesh>\n )\n}\n","{\n \"name\": \"@tscircuit/3d-viewer\",\n \"version\": \"0.0.13\",\n \"main\": \"./dist/index.js\",\n \"files\": [\n \"dist\"\n ],\n \"scripts\": {\n \"start\": \"bun run storybook\",\n \"dev:old\": \"bunx --bun vite\",\n \"build\": \"tsup ./src/index.tsx --dts --sourcemap\",\n \"prepublish\": \"npm run build\",\n \"preview\": \"vite preview\",\n \"storybook\": \"storybook dev -p 6006\",\n \"build-storybook\": \"storybook build\"\n },\n \"dependencies\": {\n \"@jscad/modeling\": \"^2.12.2\",\n \"@jscad/regl-renderer\": \"^2.6.9\",\n \"@jscad/stl-serializer\": \"^2.1.17\",\n \"@react-three/drei\": \"^9.107.2\",\n \"@react-three/fiber\": \"^8.16.8\",\n \"@tscircuit/builder\": \"^1.9.0\",\n \"@tscircuit/react-fiber\": \"^1.1.29\",\n \"@tscircuit/soup\": \"^0.0.39\",\n \"@tscircuit/soup-util\": \"^0.0.15\",\n \"@types/three\": \"^0.165.0\",\n \"jscad-fiber\": \"^0.0.38\",\n \"jscad-planner\": \"^0.0.2\",\n \"react\": \"^18.3.1\",\n \"react-dom\": \"^18.3.1\",\n \"react-use-gesture\": \"^9.1.3\",\n \"three\": \"^0.165.0\",\n \"three-stdlib\": \"^2.30.3\"\n },\n \"devDependencies\": {\n \"@biomejs/biome\": \"^1.8.3\",\n \"@chromatic-com/storybook\": \"^1.5.0\",\n \"@storybook/addon-essentials\": \"^8.1.10\",\n \"@storybook/addon-interactions\": \"^8.1.10\",\n \"@storybook/addon-links\": \"^8.1.10\",\n \"@storybook/addon-onboarding\": \"^8.1.10\",\n \"@storybook/blocks\": \"^8.1.10\",\n \"@storybook/builder-vite\": \"^8.1.10\",\n \"@storybook/react\": \"^8.1.10\",\n \"@storybook/react-vite\": \"^8.1.10\",\n \"@storybook/test\": \"^8.1.10\",\n \"@types/react\": \"^18.3.3\",\n \"@types/react-dom\": \"^18.3.0\",\n \"@vitejs/plugin-react\": \"^4.3.1\",\n \"storybook\": \"^8.1.10\",\n \"strip-ansi\": \"^7.1.0\",\n \"tsup\": \"^8.1.0\",\n \"typescript\": \"^5.5.3\",\n \"vite\": \"^5.3.1\",\n \"vite-tsconfig-paths\": \"^4.3.2\"\n }\n}\n","import { useState, useEffect } from \"react\"\nimport type { Group } from \"three\"\nimport { MTLLoader, OBJLoader } from \"three-stdlib\"\n\n// Define the type for our cache\ninterface CacheItem {\n promise: Promise<any>\n result: Group | null\n}\n\ndeclare global {\n interface Window {\n TSCIRCUIT_OBJ_LOADER_CACHE: Map<string, CacheItem>\n }\n}\n\n// Ensure the global cache exists\nif (typeof window !== \"undefined\" && !window.TSCIRCUIT_OBJ_LOADER_CACHE) {\n window.TSCIRCUIT_OBJ_LOADER_CACHE = new Map<string, CacheItem>()\n}\n\nexport function useGlobalObjLoader(url: string | null): Group | null {\n const [obj, setObj] = useState<Group | null>(null)\n\n useEffect(() => {\n if (!url) return\n\n const cache = window.TSCIRCUIT_OBJ_LOADER_CACHE\n let hasUrlChanged = false\n\n async function loadAndParseObj() {\n const response = await fetch(url!)\n const text = await response.text()\n\n const mtlContent = text\n .match(/newmtl[\\s\\S]*?endmtl/g)\n ?.join(\"\\n\")!\n .replace(/d 0\\./g, \"d 1.\")!\n const objContent = text.replace(/newmtl[\\s\\S]*?endmtl/g, \"\")\n\n const mtlLoader = new MTLLoader()\n mtlLoader.setMaterialOptions({\n invertTrProperty: true,\n })\n const materials = mtlLoader.parse(\n mtlContent.replace(\n /Kd\\s+([\\d.]+)\\s+([\\d.]+)\\s+([\\d.]+)/g,\n \"Kd $2 $2 $2\"\n ),\n \"test.mtl\"\n )\n\n const objLoader = new OBJLoader()\n objLoader.setMaterials(materials)\n return objLoader.parse(objContent)\n }\n\n function loadUrl() {\n if (cache.has(url!)) {\n const cacheItem = cache.get(url!)!\n if (cacheItem.result) {\n // If we have a result, clone it\n return Promise.resolve(cacheItem.result.clone())\n }\n // If we're still loading, return the existing promise\n return cacheItem.promise.then((result) => result.clone())\n }\n // If it's not in the cache, create a new promise and cache it\n const promise = loadAndParseObj().then((result) => {\n cache.set(url!, { ...cache.get(url!)!, result })\n return result\n })\n cache.set(url!, { promise, result: null })\n return promise\n }\n\n loadUrl()\n .then((result) => {\n if (hasUrlChanged) return\n setObj(result)\n })\n .catch((error) => {\n console.error(error)\n })\n\n return () => {\n hasUrlChanged = true\n }\n }, [url])\n\n return obj\n}\n","import { useEffect, useState } from \"react\"\nimport { useGlobalObjLoader } from \"src/hooks/use-global-obj-loader\"\nimport { Euler, Vector3 } from \"three\"\nimport { MTLLoader, OBJLoader } from \"three-stdlib\"\n\nexport function MixedStlModel({\n url,\n position,\n rotation,\n}: {\n url: string\n position?: Vector3 | [number, number, number]\n rotation?: Euler | [number, number, number]\n}) {\n const obj = useGlobalObjLoader(url)\n\n if (!obj) {\n return (\n <mesh position={position}>\n <boxGeometry args={[0.5, 0.5, 0.5]} />\n <meshStandardMaterial transparent color=\"red\" opacity={0.25} />\n </mesh>\n )\n }\n\n return <primitive rotation={rotation} position={position} object={obj} />\n}\n","import type { JscadOperation } from \"jscad-planner\"\nimport { executeJscadOperations } from \"jscad-planner\"\nimport jscad from \"@jscad/modeling\"\nimport { convertCSGToThreeGeom } from \"jscad-fiber\"\nimport * as THREE from \"three\"\nimport { useMemo } from \"react\"\n\nexport const JscadModel = ({ jscadPlan }: { jscadPlan: JscadOperation }) => {\n const { threeGeom, material } = useMemo(() => {\n const jscadObject = executeJscadOperations(jscad as any, jscadPlan)\n\n const threeGeom = convertCSGToThreeGeom(jscadObject)\n\n const material = new THREE.MeshStandardMaterial({\n vertexColors: true,\n side: THREE.DoubleSide, // Ensure both sides are visible\n })\n return { threeGeom, material }\n }, [jscadPlan])\n\n if (!threeGeom) return null\n\n return <mesh geometry={threeGeom} material={material} />\n}\n"],"mappings":"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","names":["import_soup_util","import_react","import_primitives","import_colors","import_booleans","stlSerializer","import_react","import_fiber","import_drei","import_react","import_fiber","import_jsx_runtime","import_jsx_runtime","import_react","import_three_stdlib","import_jsx_runtime","THREE","import_react","import_jsx_runtime","jscad","threeGeom","material","import_jsx_runtime"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tscircuit/3d-viewer",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.14",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist"
|
|
@@ -20,7 +20,13 @@
|
|
|
20
20
|
"@jscad/stl-serializer": "^2.1.17",
|
|
21
21
|
"@react-three/drei": "^9.107.2",
|
|
22
22
|
"@react-three/fiber": "^8.16.8",
|
|
23
|
+
"@tscircuit/builder": "^1.9.0",
|
|
24
|
+
"@tscircuit/react-fiber": "^1.1.29",
|
|
25
|
+
"@tscircuit/soup": "^0.0.39",
|
|
26
|
+
"@tscircuit/soup-util": "^0.0.15",
|
|
23
27
|
"@types/three": "^0.165.0",
|
|
28
|
+
"jscad-fiber": "^0.0.38",
|
|
29
|
+
"jscad-planner": "^0.0.2",
|
|
24
30
|
"react": "^18.3.1",
|
|
25
31
|
"react-dom": "^18.3.1",
|
|
26
32
|
"react-use-gesture": "^9.1.3",
|
|
@@ -39,8 +45,6 @@
|
|
|
39
45
|
"@storybook/react": "^8.1.10",
|
|
40
46
|
"@storybook/react-vite": "^8.1.10",
|
|
41
47
|
"@storybook/test": "^8.1.10",
|
|
42
|
-
"@tscircuit/soup": "^0.0.39",
|
|
43
|
-
"@tscircuit/soup-util": "^0.0.11",
|
|
44
48
|
"@types/react": "^18.3.3",
|
|
45
49
|
"@types/react-dom": "^18.3.0",
|
|
46
50
|
"@vitejs/plugin-react": "^4.3.1",
|