circuit-to-svg 0.0.23 → 0.0.24

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 CHANGED
@@ -1,10 +1,10 @@
1
1
  // src/lib/circuit-to-pcb-svg.ts
2
2
  import { stringify as stringify2 } from "svgson";
3
3
  import {
4
- applyToPoint as applyToPoint4,
5
- compose as compose2,
4
+ applyToPoint as applyToPoint7,
5
+ compose as compose3,
6
6
  scale,
7
- translate as translate2
7
+ translate as translate3
8
8
  } from "transformation-matrix";
9
9
 
10
10
  // src/utils/pairs.ts
@@ -86,20 +86,21 @@ function createSvgObjectsFromSmtPad(pad, transform) {
86
86
  return [];
87
87
  }
88
88
 
89
- // src/lib/svg-object-fns/create-svg-objects-from-pcb-slikscreen-text.ts
89
+ // src/lib/svg-object-fns/create-svg-objects-from-pcb-silkscreen-text.ts
90
90
  import {
91
91
  applyToPoint as applyToPoint3,
92
92
  compose,
93
93
  rotate,
94
- translate
94
+ translate,
95
+ toString as matrixToString
95
96
  } from "transformation-matrix";
96
- function createSvgObjectsFromPcbSilkscreenText(PcbSilkscreenText, transform) {
97
+ function createSvgObjectsFromPcbSilkscreenText(pcbSilkscreenText, transform) {
97
98
  const {
98
99
  anchor_position,
99
100
  text,
100
101
  font_size = 1,
101
102
  layer = "top"
102
- } = PcbSilkscreenText;
103
+ } = pcbSilkscreenText;
103
104
  if (!anchor_position || typeof anchor_position.x !== "number" || typeof anchor_position.y !== "number") {
104
105
  console.error("Invalid anchor_position:", anchor_position);
105
106
  return [];
@@ -128,9 +129,133 @@ function createSvgObjectsFromPcbSilkscreenText(PcbSilkscreenText, transform) {
128
129
  "font-size": transformedFontSize.toString(),
129
130
  "text-anchor": "middle",
130
131
  "dominant-baseline": "central",
131
- transform: `matrix(${textTransform.a} ${textTransform.b} ${textTransform.c} ${textTransform.d} ${textTransform.e} ${textTransform.f})`,
132
+ transform: matrixToString(textTransform),
132
133
  class: `pcb-silkscreen-text pcb-silkscreen-${layer}`,
133
- "data-pcb-silkscreen-text-id": PcbSilkscreenText.pcb_component_id
134
+ "data-pcb-silkscreen-text-id": pcbSilkscreenText.pcb_component_id
135
+ },
136
+ children: [
137
+ {
138
+ type: "text",
139
+ value: cleanedText,
140
+ name: "",
141
+ attributes: {},
142
+ children: []
143
+ }
144
+ ],
145
+ value: ""
146
+ };
147
+ return [svgObject];
148
+ }
149
+
150
+ // src/lib/svg-object-fns/create-svg-objects-from-pcb-fabrication-note-path.ts
151
+ import { applyToPoint as applyToPoint4 } from "transformation-matrix";
152
+ function createSvgObjectsFromPcbFabricationNotePath(fabNotePath, transform) {
153
+ if (!fabNotePath.route || !Array.isArray(fabNotePath.route)) return [];
154
+ let path = fabNotePath.route.map((point, index) => {
155
+ const [x, y] = applyToPoint4(transform, [point.x, point.y]);
156
+ return index === 0 ? `M ${x} ${y}` : `L ${x} ${y}`;
157
+ }).join(" ");
158
+ const firstPoint = fabNotePath.route[0];
159
+ const lastPoint = fabNotePath.route[fabNotePath.route.length - 1];
160
+ if (firstPoint.x !== lastPoint.x || firstPoint.y !== lastPoint.y) {
161
+ path += " Z";
162
+ }
163
+ return [
164
+ {
165
+ name: "path",
166
+ type: "element",
167
+ attributes: {
168
+ class: "pcb-fabrication-note-path",
169
+ stroke: "rgba(255,255,255,0.5)",
170
+ d: path,
171
+ "stroke-width": (fabNotePath.stroke_width * Math.abs(transform.a)).toString(),
172
+ "data-pcb-component-id": fabNotePath.pcb_component_id,
173
+ "data-pcb-fabrication-note-path-id": fabNotePath.fabrication_note_path_id
174
+ },
175
+ value: "",
176
+ children: []
177
+ }
178
+ ];
179
+ }
180
+
181
+ // src/lib/svg-object-fns/create-svg-objects-from-pcb-silkscreen-path.ts
182
+ import { applyToPoint as applyToPoint5 } from "transformation-matrix";
183
+ function createSvgObjectsFromPcbSilkscreenPath(silkscreenPath, transform) {
184
+ if (!silkscreenPath.route || !Array.isArray(silkscreenPath.route)) return [];
185
+ let path = silkscreenPath.route.map((point, index) => {
186
+ const [x, y] = applyToPoint5(transform, [point.x, point.y]);
187
+ return index === 0 ? `M ${x} ${y}` : `L ${x} ${y}`;
188
+ }).join(" ");
189
+ const firstPoint = silkscreenPath.route[0];
190
+ const lastPoint = silkscreenPath.route[silkscreenPath.route.length - 1];
191
+ if (firstPoint.x !== lastPoint.x || firstPoint.y !== lastPoint.y) {
192
+ path += " Z";
193
+ }
194
+ return [
195
+ {
196
+ name: "path",
197
+ type: "element",
198
+ attributes: {
199
+ class: `pcb-silkscreen pcb-silkscreen-${silkscreenPath.layer}`,
200
+ d: path,
201
+ "stroke-width": (silkscreenPath.stroke_width * Math.abs(transform.a)).toString(),
202
+ "data-pcb-component-id": silkscreenPath.pcb_component_id,
203
+ "data-pcb-silkscreen-path-id": silkscreenPath.pcb_silkscreen_path_id
204
+ },
205
+ value: "",
206
+ children: []
207
+ }
208
+ ];
209
+ }
210
+
211
+ // src/lib/svg-object-fns/create-svg-objects-from-pcb-fabrication-note-text.ts
212
+ import { toString as matrixToString2 } from "transformation-matrix";
213
+ import {
214
+ applyToPoint as applyToPoint6,
215
+ compose as compose2,
216
+ rotate as rotate2,
217
+ translate as translate2
218
+ } from "transformation-matrix";
219
+ function createSvgObjectsFromPcbFabricationNoteText(pcbFabNoteText, transform) {
220
+ const {
221
+ anchor_position,
222
+ anchor_alignment,
223
+ text,
224
+ font_size = 1,
225
+ layer = "top"
226
+ } = pcbFabNoteText;
227
+ if (!anchor_position || typeof anchor_position.x !== "number" || typeof anchor_position.y !== "number") {
228
+ console.error("Invalid anchor_position:", anchor_position);
229
+ return [];
230
+ }
231
+ const [transformedX, transformedY] = applyToPoint6(transform, [
232
+ anchor_position.x,
233
+ anchor_position.y
234
+ ]);
235
+ const transformedFontSize = font_size * Math.abs(transform.a);
236
+ const cleanedText = (text || "").replace(/\$\{|\}/g, "");
237
+ if (!cleanedText) {
238
+ return [];
239
+ }
240
+ const textTransform = compose2(
241
+ translate2(transformedX, transformedY),
242
+ // TODO do anchor_alignment
243
+ rotate2(Math.PI / 180)
244
+ // Convert degrees to radians
245
+ );
246
+ const svgObject = {
247
+ name: "text",
248
+ type: "element",
249
+ attributes: {
250
+ x: "0",
251
+ y: "0",
252
+ "font-family": "Arial, sans-serif",
253
+ "font-size": transformedFontSize.toString(),
254
+ "text-anchor": "middle",
255
+ "dominant-baseline": "central",
256
+ transform: matrixToString2(textTransform),
257
+ class: "pcb-fabrication-note-text",
258
+ fill: "rgba(255,255,255,0.5)"
134
259
  },
135
260
  children: [
136
261
  {
@@ -177,8 +302,8 @@ function circuitJsonToPcbSvg(soup) {
177
302
  const scaleFactor = Math.min(scaleX, scaleY);
178
303
  const offsetX = (svgWidth - circuitWidth * scaleFactor) / 2;
179
304
  const offsetY = (svgHeight - circuitHeight * scaleFactor) / 2;
180
- const transform = compose2(
181
- translate2(
305
+ const transform = compose3(
306
+ translate3(
182
307
  offsetX - minX * scaleFactor + padding * scaleFactor,
183
308
  svgHeight - offsetY + minY * scaleFactor - padding * scaleFactor
184
309
  ),
@@ -187,7 +312,7 @@ function circuitJsonToPcbSvg(soup) {
187
312
  );
188
313
  const traceElements = soup.filter((elm) => elm.type === "pcb_trace").flatMap((elm) => createSvgObjects(elm, transform));
189
314
  const holeElements = soup.filter((elm) => elm.type === "pcb_plated_hole").flatMap((elm) => createSvgObjects(elm, transform));
190
- const silkscreenElements = soup.filter((elm) => elm.type === "pcb_silkscreen_path").flatMap((elm) => createPcbSilkscreenPath(elm, transform));
315
+ const silkscreenElements = soup.filter((elm) => elm.type === "pcb_silkscreen_path").flatMap((elm) => createSvgObjectsFromPcbSilkscreenPath(elm, transform));
191
316
  const otherElements = soup.filter(
192
317
  (elm) => !["pcb_trace", "pcb_plated_hole", "pcb_silkscreen_path"].includes(
193
318
  elm.type
@@ -304,13 +429,17 @@ function createSvgObjects(elm, transform) {
304
429
  return createSvgObjectsFromSmtPad(elm, transform);
305
430
  case "pcb_silkscreen_text":
306
431
  return createSvgObjectsFromPcbSilkscreenText(elm, transform);
432
+ case "pcb_fabrication_note_path":
433
+ return createSvgObjectsFromPcbFabricationNotePath(elm, transform);
434
+ case "pcb_fabrication_note_text":
435
+ return createSvgObjectsFromPcbFabricationNoteText(elm, transform);
307
436
  default:
308
437
  return [];
309
438
  }
310
439
  }
311
440
  function createSvgObjectsFromPcbComponent(component, transform) {
312
441
  const { center, width, height, rotation = 0 } = component;
313
- const [x, y] = applyToPoint4(transform, [center.x, center.y]);
442
+ const [x, y] = applyToPoint7(transform, [center.x, center.y]);
314
443
  const scaledWidth = width * Math.abs(transform.a);
315
444
  const scaledHeight = height * Math.abs(transform.d);
316
445
  const transformStr = `translate(${x}, ${y}) rotate(${-rotation}) scale(1, -1)`;
@@ -345,7 +474,7 @@ function createSvgObjectsFromPcbComponent(component, transform) {
345
474
  };
346
475
  }
347
476
  function createSvgObjectsFromPcbHole(hole, transform) {
348
- const [x, y] = applyToPoint4(transform, [hole.x, hole.y]);
477
+ const [x, y] = applyToPoint7(transform, [hole.x, hole.y]);
349
478
  const scaledOuterRadius = hole.outer_diameter / 2 * Math.abs(transform.a);
350
479
  const scaledInnerRadius = hole.hole_diameter / 2 * Math.abs(transform.a);
351
480
  return {
@@ -375,32 +504,9 @@ function createSvgObjectsFromPcbHole(hole, transform) {
375
504
  ]
376
505
  };
377
506
  }
378
- function createPcbSilkscreenPath(silkscreenPath, transform) {
379
- if (!silkscreenPath.route || !Array.isArray(silkscreenPath.route)) return null;
380
- let path = silkscreenPath.route.map((point, index) => {
381
- const [x, y] = applyToPoint4(transform, [point.x, point.y]);
382
- return index === 0 ? `M ${x} ${y}` : `L ${x} ${y}`;
383
- }).join(" ");
384
- const firstPoint = silkscreenPath.route[0];
385
- const lastPoint = silkscreenPath.route[silkscreenPath.route.length - 1];
386
- if (firstPoint.x !== lastPoint.x || firstPoint.y !== lastPoint.y) {
387
- path += " Z";
388
- }
389
- return {
390
- name: "path",
391
- type: "element",
392
- attributes: {
393
- class: `pcb-silkscreen pcb-silkscreen-${silkscreenPath.layer}`,
394
- d: path,
395
- "stroke-width": (silkscreenPath.stroke_width * Math.abs(transform.a)).toString(),
396
- "data-pcb-component-id": silkscreenPath.pcb_component_id,
397
- "data-pcb-silkscreen-path-id": silkscreenPath.pcb_silkscreen_path_id
398
- }
399
- };
400
- }
401
507
  function createSvgObjectFromPcbBoundary(transform, minX, minY, maxX, maxY) {
402
- const [x1, y1] = applyToPoint4(transform, [minX, minY]);
403
- const [x2, y2] = applyToPoint4(transform, [maxX, maxY]);
508
+ const [x1, y1] = applyToPoint7(transform, [minX, minY]);
509
+ const [x2, y2] = applyToPoint7(transform, [maxX, maxY]);
404
510
  const width = Math.abs(x2 - x1);
405
511
  const height = Math.abs(y2 - y1);
406
512
  const x = Math.min(x1, x2);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/circuit-to-pcb-svg.ts","../src/utils/pairs.ts","../src/lib/svg-object-fns/create-svg-objects-from-pcb-trace.ts","../src/lib/layer-name-to-color.ts","../src/lib/svg-object-fns/create-svg-objects-from-smt-pads.ts","../src/lib/svg-object-fns/create-svg-objects-from-pcb-slikscreen-text.ts","../src/lib/circuit-to-schematic-svg.ts"],"sourcesContent":["import type { AnySoupElement, PCBTrace } from \"@tscircuit/soup\"\nimport { type INode as SvgObject, stringify } from \"svgson\"\nimport {\n applyToPoint,\n compose,\n scale,\n translate,\n type Matrix,\n} from \"transformation-matrix\"\nimport { createSvgObjectsFromPcbTrace } from \"./svg-object-fns/create-svg-objects-from-pcb-trace\"\nimport { createSvgObjectsFromSmtPad } from \"./svg-object-fns/create-svg-objects-from-smt-pads\"\nimport { createSvgObjectsFromPcbSilkscreenText } from \"./svg-object-fns/create-svg-objects-from-pcb-slikscreen-text\"\n\ninterface PointObjectNotation {\n x: number\n y: number\n}\n\nfunction circuitJsonToPcbSvg(soup: AnySoupElement[]): string {\n let minX = Number.POSITIVE_INFINITY\n let minY = Number.POSITIVE_INFINITY\n let maxX = Number.NEGATIVE_INFINITY\n let maxY = Number.NEGATIVE_INFINITY\n\n // Process all elements to determine bounds\n for (const item of soup) {\n if (\"center\" in item && \"width\" in item && \"height\" in item) {\n updateBounds(item.center, item.width, item.height)\n } else if (\"x\" in item && \"y\" in item) {\n updateBounds({ x: item.x, y: item.y }, 0, 0)\n } else if (\"route\" in item) {\n updateTraceBounds(item.route)\n }\n }\n\n const padding = 1 // Reduced padding for tighter boundary\n const circuitWidth = maxX - minX + 2 * padding\n const circuitHeight = maxY - minY + 2 * padding\n\n const svgWidth = 800\n const svgHeight = 600\n const paths: PointObjectNotation[][] = []\n for (const item of soup) {\n if (\"route\" in item && item.route !== undefined) {\n paths.push(item.route as PointObjectNotation[])\n }\n }\n\n // Calculate scale factor to fit the circuit within the SVG, maintaining aspect ratio\n const scaleX = svgWidth / circuitWidth\n const scaleY = svgHeight / circuitHeight\n const scaleFactor = Math.min(scaleX, scaleY)\n\n // Calculate centering offsets\n const offsetX = (svgWidth - circuitWidth * scaleFactor) / 2\n const offsetY = (svgHeight - circuitHeight * scaleFactor) / 2\n\n const transform = compose(\n translate(\n offsetX - minX * scaleFactor + padding * scaleFactor,\n svgHeight - offsetY + minY * scaleFactor - padding * scaleFactor,\n ),\n scale(scaleFactor, -scaleFactor), // Flip in y-direction\n )\n\n const traceElements = soup\n .filter((elm) => elm.type === \"pcb_trace\")\n .flatMap((elm) => createSvgObjects(elm, transform))\n\n const holeElements = soup\n .filter((elm) => elm.type === \"pcb_plated_hole\")\n .flatMap((elm) => createSvgObjects(elm, transform))\n\n const silkscreenElements = soup\n .filter((elm) => elm.type === \"pcb_silkscreen_path\")\n .flatMap((elm) => createPcbSilkscreenPath(elm, transform))\n\n const otherElements = soup\n .filter(\n (elm) =>\n ![\"pcb_trace\", \"pcb_plated_hole\", \"pcb_silkscreen_path\"].includes(\n elm.type,\n ),\n )\n .flatMap((item) => createSvgObjects(item, transform))\n\n let strokeWidth = String(0.05 * scaleFactor)\n\n for (const element of soup) {\n if (\"stroke_width\" in element) {\n strokeWidth = String(scaleFactor * element.stroke_width)\n break\n }\n }\n\n const svgObject: SvgObject = {\n name: \"svg\",\n type: \"element\",\n attributes: {\n xmlns: \"http://www.w3.org/2000/svg\",\n width: svgWidth.toString(),\n height: svgHeight.toString(),\n },\n value: \"\",\n children: [\n {\n name: \"style\",\n type: \"element\",\n children: [\n {\n type: \"text\",\n value: `\n .pcb-board { fill: #000; }\n .pcb-trace { fill: none; }\n .pcb-hole-outer { fill: rgb(200, 52, 52); }\n .pcb-hole-inner { fill: rgb(255, 38, 226); }\n .pcb-pad { }\n .pcb-boundary { fill: none; stroke: #fff; stroke-width: 0.3; }\n .pcb-silkscreen { fill: none; }\n .pcb-silkscreen-top { stroke: #f2eda1; }\n .pcb-silkscreen-bottom { stroke: #f2eda1; }\n .pcb-silkscreen-text { fill: #f2eda1; }\n `,\n },\n ],\n },\n {\n name: \"rect\",\n type: \"element\",\n attributes: {\n class: \"pcb-board\",\n x: \"0\",\n y: \"0\",\n width: svgWidth.toString(),\n height: svgHeight.toString(),\n },\n },\n createSvgObjectFromPcbBoundary(transform, minX, minY, maxX, maxY),\n {\n name: \"g\",\n type: \"element\",\n attributes: { id: \"other-elements\" },\n children: otherElements,\n },\n {\n name: \"g\",\n type: \"element\",\n attributes: { id: \"traces\" },\n children: traceElements,\n },\n {\n name: \"g\",\n type: \"element\",\n attributes: { id: \"holes\" },\n children: holeElements,\n },\n {\n name: \"g\",\n type: \"element\",\n attributes: { id: \"silkscreen\" },\n children: silkscreenElements,\n },\n ].filter((child): child is SvgObject => child !== null),\n }\n\n try {\n return stringify(svgObject as SvgObject)\n } catch (error) {\n console.error(\"Error stringifying SVG object:\", error)\n throw error\n }\n\n function updateBounds(center: any, width: any, height: any) {\n const halfWidth = width / 2\n const halfHeight = height / 2\n minX = Math.min(minX, center.x - halfWidth)\n minY = Math.min(minY, center.y - halfHeight)\n maxX = Math.max(maxX, center.x + halfWidth)\n maxY = Math.max(maxY, center.y + halfHeight)\n }\n\n function updateTraceBounds(route: any[]) {\n for (const point of route) {\n minX = Math.min(minX, point.x)\n minY = Math.min(minY, point.y)\n maxX = Math.max(maxX, point.x)\n maxY = Math.max(maxY, point.y)\n }\n }\n}\n\nfunction createSvgObjects(elm: AnySoupElement, transform: Matrix): SvgObject[] {\n switch (elm.type) {\n case \"pcb_component\":\n return [createSvgObjectsFromPcbComponent(elm, transform)].filter(Boolean)\n case \"pcb_trace\":\n return createSvgObjectsFromPcbTrace(elm, transform)\n case \"pcb_plated_hole\":\n return [createSvgObjectsFromPcbHole(elm, transform)].filter(Boolean)\n case \"pcb_smtpad\":\n return createSvgObjectsFromSmtPad(elm, transform)\n case \"pcb_silkscreen_text\":\n return createSvgObjectsFromPcbSilkscreenText(elm, transform)\n default:\n return []\n }\n}\n\nfunction createSvgObjectsFromPcbComponent(component: any, transform: any): any {\n const { center, width, height, rotation = 0 } = component\n const [x, y] = applyToPoint(transform, [center.x, center.y])\n const scaledWidth = width * Math.abs(transform.a)\n const scaledHeight = height * Math.abs(transform.d)\n const transformStr = `translate(${x}, ${y}) rotate(${-rotation}) scale(1, -1)`\n\n return {\n name: \"g\",\n type: \"element\",\n attributes: { transform: transformStr },\n children: [\n {\n name: \"rect\",\n type: \"element\",\n attributes: {\n class: \"pcb-component\",\n x: (-scaledWidth / 2).toString(),\n y: (-scaledHeight / 2).toString(),\n width: scaledWidth.toString(),\n height: scaledHeight.toString(),\n },\n },\n {\n name: \"rect\",\n type: \"element\",\n attributes: {\n class: \"pcb-component-outline\",\n x: (-scaledWidth / 2).toString(),\n y: (-scaledHeight / 2).toString(),\n width: scaledWidth.toString(),\n height: scaledHeight.toString(),\n },\n },\n ],\n }\n}\n\nfunction createSvgObjectsFromPcbHole(hole: any, transform: any): any {\n const [x, y] = applyToPoint(transform, [hole.x, hole.y])\n const scaledOuterRadius = (hole.outer_diameter / 2) * Math.abs(transform.a)\n const scaledInnerRadius = (hole.hole_diameter / 2) * Math.abs(transform.a)\n return {\n name: \"g\",\n type: \"element\",\n children: [\n {\n name: \"circle\",\n type: \"element\",\n attributes: {\n class: \"pcb-hole-outer\",\n cx: x.toString(),\n cy: y.toString(),\n r: scaledOuterRadius.toString(),\n },\n },\n {\n name: \"circle\",\n type: \"element\",\n attributes: {\n class: \"pcb-hole-inner\",\n cx: x.toString(),\n cy: y.toString(),\n r: scaledInnerRadius.toString(),\n },\n },\n ],\n }\n}\n\nfunction createPcbSilkscreenPath(silkscreenPath: any, transform: any): any {\n if (!silkscreenPath.route || !Array.isArray(silkscreenPath.route)) return null\n\n let path = silkscreenPath.route\n .map((point: any, index: number) => {\n const [x, y] = applyToPoint(transform, [point.x, point.y])\n return index === 0 ? `M ${x} ${y}` : `L ${x} ${y}`\n })\n .join(\" \")\n\n // Close the path if it's not already closed\n const firstPoint = silkscreenPath.route[0]\n const lastPoint = silkscreenPath.route[silkscreenPath.route.length - 1]\n if (firstPoint.x !== lastPoint.x || firstPoint.y !== lastPoint.y) {\n path += \" Z\"\n }\n\n return {\n name: \"path\",\n type: \"element\",\n attributes: {\n class: `pcb-silkscreen pcb-silkscreen-${silkscreenPath.layer}`,\n d: path,\n \"stroke-width\": (\n silkscreenPath.stroke_width * Math.abs(transform.a)\n ).toString(),\n \"data-pcb-component-id\": silkscreenPath.pcb_component_id,\n \"data-pcb-silkscreen-path-id\": silkscreenPath.pcb_silkscreen_path_id,\n },\n }\n}\n\nfunction createSvgObjectFromPcbBoundary(\n transform: any,\n minX: number,\n minY: number,\n maxX: number,\n maxY: number,\n): SvgObject {\n const [x1, y1] = applyToPoint(transform, [minX, minY])\n const [x2, y2] = applyToPoint(transform, [maxX, maxY])\n const width = Math.abs(x2 - x1)\n const height = Math.abs(y2 - y1)\n const x = Math.min(x1, x2)\n const y = Math.min(y1, y2)\n return {\n name: \"rect\",\n type: \"element\",\n value: \"\",\n children: [],\n attributes: {\n class: \"pcb-boundary\",\n x: x.toString(),\n y: y.toString(),\n width: width.toString(),\n height: height.toString(),\n },\n }\n}\n\nexport { circuitJsonToPcbSvg }\n","/**\n * Return pairs of adjacent elements in an array.\n */\nexport function pairs<T>(arr: Array<T>): Array<[T, T]> {\n const result: Array<[T, T]> = []\n for (let i = 0; i < arr.length - 1; i++) {\n result.push([arr[i]!, arr[i + 1]!])\n }\n return result\n}\n","import type { AnySoupElement, PCBTrace } from \"@tscircuit/soup\"\nimport { pairs } from \"src/utils/pairs\"\nimport { type INode as SvgObject, stringify } from \"svgson\"\nimport { applyToPoint } from \"transformation-matrix\"\nimport { LAYER_NAME_TO_COLOR } from \"../layer-name-to-color\"\n\nexport function createSvgObjectsFromPcbTrace(\n trace: PCBTrace,\n transform: any,\n): SvgObject[] {\n if (!trace.route || !Array.isArray(trace.route) || trace.route.length < 2)\n return []\n\n const segments = pairs(trace.route)\n const svgObjects: SvgObject[] = []\n\n for (const [start, end] of segments) {\n const startPoint = applyToPoint(transform, [start.x, start.y])\n const endPoint = applyToPoint(transform, [end.x, end.y])\n\n const layer =\n \"layer\" in start ? start.layer : \"layer\" in end ? end.layer : null\n if (!layer) continue\n\n const layerColor =\n LAYER_NAME_TO_COLOR[layer as keyof typeof LAYER_NAME_TO_COLOR] ?? \"white\"\n\n const traceWidth =\n \"width\" in start ? start.width : \"width\" in end ? end.width : null\n\n svgObjects.push({\n name: \"path\",\n type: \"element\",\n value: \"\",\n children: [],\n attributes: {\n class: \"pcb-trace\",\n stroke: layerColor,\n d: `M ${startPoint[0]} ${startPoint[1]} L ${endPoint[0]} ${endPoint[1]}`,\n \"stroke-width\": traceWidth\n ? (traceWidth * Math.abs(transform.a)).toString()\n : \"0.3\",\n \"stroke-linecap\": \"round\",\n \"stroke-linejoin\": \"round\",\n \"shape-rendering\": \"crispEdges\",\n },\n })\n }\n return svgObjects\n}\n","/**\n * TODO use @tscircuit/pcb-colors when it's published\n */\nexport const LAYER_NAME_TO_COLOR = {\n top: \"rgb(200, 52, 52)\",\n bottom: \"rgb(77, 127, 196)\",\n}\n\nexport function layerNameToColor(layerName: string) {\n return (\n LAYER_NAME_TO_COLOR[layerName as keyof typeof LAYER_NAME_TO_COLOR] ??\n \"white\"\n )\n}\n","import type { PCBSMTPad } from \"@tscircuit/soup\"\nimport { applyToPoint, type Matrix } from \"transformation-matrix\"\nimport { layerNameToColor } from \"../layer-name-to-color\"\n\nexport function createSvgObjectsFromSmtPad(\n pad: PCBSMTPad,\n transform: Matrix,\n): any {\n const [x, y] = applyToPoint(transform, [pad.x, pad.y])\n\n if (pad.shape === \"rect\") {\n const width = pad.width * Math.abs(transform.a)\n const height = pad.height * Math.abs(transform.d)\n return [\n {\n name: \"rect\",\n type: \"element\",\n attributes: {\n class: \"pcb-pad\",\n fill: layerNameToColor(pad.layer),\n x: (x - width / 2).toString(),\n y: (y - height / 2).toString(),\n width: width.toString(),\n height: height.toString(),\n },\n },\n ]\n }\n // TODO implement smtpad circles/ovals etc.\n return []\n}\n","import type { PcbSilkscreenText } from \"@tscircuit/soup\"\nimport type { INode as SvgObject } from \"svgson\"\nimport {\n type Matrix,\n applyToPoint,\n compose,\n rotate,\n translate,\n} from \"transformation-matrix\"\n\nexport function createSvgObjectsFromPcbSilkscreenText(\n PcbSilkscreenText: PcbSilkscreenText,\n transform: Matrix,\n): SvgObject[] {\n const {\n anchor_position,\n text,\n font_size = 1,\n layer = \"top\",\n } = PcbSilkscreenText\n\n if (\n !anchor_position ||\n typeof anchor_position.x !== \"number\" ||\n typeof anchor_position.y !== \"number\"\n ) {\n console.error(\"Invalid anchor_position:\", anchor_position)\n return []\n }\n\n const [transformedX, transformedY] = applyToPoint(transform, [\n anchor_position.x,\n anchor_position.y,\n ])\n const transformedFontSize = font_size * Math.abs(transform.a)\n\n // Remove ${} from text value and handle undefined text\n const cleanedText = (text || \"\").replace(/\\$\\{|\\}/g, \"\")\n if (!cleanedText) {\n return []\n }\n\n // Create a composite transformation\n const textTransform = compose(\n translate(transformedX, transformedY),\n rotate(Math.PI / 180), // Convert degrees to radians\n )\n\n const svgObject: SvgObject = {\n name: \"text\",\n type: \"element\",\n attributes: {\n x: \"0\",\n y: \"0\",\n \"font-family\": \"Arial, sans-serif\",\n \"font-size\": transformedFontSize.toString(),\n \"text-anchor\": \"middle\",\n \"dominant-baseline\": \"central\",\n transform: `matrix(${textTransform.a} ${textTransform.b} ${textTransform.c} ${textTransform.d} ${textTransform.e} ${textTransform.f})`,\n class: `pcb-silkscreen-text pcb-silkscreen-${layer}`,\n \"data-pcb-silkscreen-text-id\": PcbSilkscreenText.pcb_component_id,\n },\n children: [\n {\n type: \"text\",\n value: cleanedText,\n name: \"\",\n attributes: {},\n children: [],\n },\n ],\n value: \"\",\n }\n\n return [svgObject]\n}\n","import type { AnySoupElement } from \"@tscircuit/soup\"\nimport { getSvg, symbols } from \"schematic-symbols\"\nimport { parseSync, stringify } from \"svgson\"\n\nfunction circuitJsonToSchematicSvg(soup: AnySoupElement[]): string {\n let minX = Number.POSITIVE_INFINITY\n let minY = Number.POSITIVE_INFINITY\n let maxX = Number.NEGATIVE_INFINITY\n let maxY = Number.NEGATIVE_INFINITY\n\n const portSize = 0.2\n const portPositions = new Map()\n\n // First pass: find the bounds and collect port positions\n for (const item of soup) {\n if (item.type === \"schematic_component\") {\n updateBounds(item.center, item.size, item.rotation || 0)\n } else if (item.type === \"schematic_port\") {\n updateBounds(item.center, { width: portSize, height: portSize }, 0)\n portPositions.set(item.schematic_port_id, item.center)\n } else if (item.type === \"schematic_text\") {\n updateBounds(item.position, { width: 0, height: 0 }, 0)\n }\n }\n\n const height = maxY - minY\n const flipY = (y: number) => height - (y - minY) + minY\n\n const svgChildren: any[] = []\n\n // Process components\n const componentMap = new Map()\n for (const component of soup.filter(\n (item) => item.type === \"schematic_component\",\n )) {\n const flippedCenter = {\n x: component.center.x,\n y: flipY(component.center.y),\n }\n const svg = createSchematicComponent(\n flippedCenter,\n component.size,\n component.rotation || 0,\n (component as any).symbol_name,\n )\n svgChildren.push(svg)\n componentMap.set(component.schematic_component_id, component)\n }\n\n // Process ports and add lines to component edges\n for (const port of soup.filter((item) => item.type === \"schematic_port\")) {\n const flippedCenter = { x: port.center.x, y: flipY(port.center.y) }\n const svg = createSchematicPort(flippedCenter)\n svgChildren.push(svg)\n\n const component = componentMap.get(port.schematic_component_id)\n if (component) {\n const line = createPortToComponentLine(\n flippedCenter,\n component,\n port.facing_direction || \"right\",\n )\n svgChildren.push(line)\n }\n }\n\n // Process schematic traces\n for (const trace of soup.filter((item) => item.type === \"schematic_trace\")) {\n const svg = createSchematicTrace(trace, flipY, portPositions)\n if (svg) svgChildren.push(svg)\n }\n\n // Process text\n for (const text of soup.filter((item) => item.type === \"schematic_text\")) {\n const flippedPosition = { x: text.position.x, y: flipY(text.position.y) }\n const svg = createSchematicText(text, flippedPosition)\n svgChildren.push(svg)\n }\n\n const padding = 1\n const width = maxX - minX + 2 * padding\n const viewBox = `${minX - padding} ${minY - padding} ${width} ${height + 2 * padding}`\n\n const svgObject = {\n name: \"svg\",\n type: \"element\",\n attributes: {\n xmlns: \"http://www.w3.org/2000/svg\",\n viewBox,\n width: \"1200\",\n height: \"600\",\n style: \"background-color: #fff;\",\n },\n children: [\n {\n name: \"style\",\n type: \"element\",\n children: [\n {\n type: \"text\",\n value: `\n .component { fill: none; stroke: red; stroke-width: 0.03; }\n .component-pin { fill: none; stroke: red; stroke-width: 0.03; }\n .trace { stroke: green; stroke-width: 0.03; fill: none; }\n .text { font-family: Arial, sans-serif; font-size: 0.2px; }\n .port { fill: none; stroke: blue; stroke-width: 0.03; }\n `,\n },\n ],\n },\n ...svgChildren,\n ],\n }\n\n return stringify({ value: \"\", ...svgObject })\n\n function updateBounds(center: any, size: any, rotation: number) {\n const corners = [\n { x: -size.width / 2, y: -size.height / 2 },\n { x: size.width / 2, y: -size.height / 2 },\n { x: size.width / 2, y: size.height / 2 },\n { x: -size.width / 2, y: size.height / 2 },\n ]\n\n for (const corner of corners) {\n const rotatedX =\n corner.x * Math.cos(rotation) - corner.y * Math.sin(rotation) + center.x\n const rotatedY =\n corner.x * Math.sin(rotation) + corner.y * Math.cos(rotation) + center.y\n minX = Math.min(minX, rotatedX)\n minY = Math.min(minY, rotatedY)\n maxX = Math.max(maxX, rotatedX)\n maxY = Math.max(maxY, rotatedY)\n }\n }\n}\n\nfunction createSchematicComponent(\n center: { x: number; y: number },\n size: { width: number; height: number },\n rotation: number,\n symbolName?: string,\n): any {\n const transform = `translate(${center.x}, ${center.y}) rotate(${(rotation * 180) / Math.PI})`\n\n if (symbolName) {\n const symbol = (symbols as any)[symbolName]\n const paths = symbol.primitives.filter((p: any) => p.type === \"path\")\n const updatedSymbol = {\n ...symbol,\n primitives: paths,\n }\n const svg = parseSync(\n getSvg(updatedSymbol, {\n width: size.width,\n height: size.height,\n }),\n )\n\n // Filter out non-path elements and modify path colors\n const pathElements = svg.children\n .filter(\n (child: any) =>\n child.name === \"path\" && child.attributes.fill !== \"green\",\n )\n .map((path: any) => {\n const currentStrokeWidth = Number.parseFloat(\n path.attributes[\"stroke-width\"] || \"0.02\",\n )\n const newStrokeWidth = (currentStrokeWidth * 1.5).toString()\n\n return {\n ...path,\n attributes: {\n ...path.attributes,\n stroke:\n path.attributes.stroke === \"black\"\n ? \"red\"\n : path.attributes.stroke,\n \"stroke-width\": newStrokeWidth,\n },\n }\n })\n\n // Check if viewBox attribute exists\n const viewBoxAttr = svg.attributes.viewBox\n if (typeof viewBoxAttr === \"undefined\") {\n throw new Error(\"SVG does not have a viewBox attribute.\")\n }\n\n // Extract viewBox values\n const viewBox = viewBoxAttr.split(\" \").map(Number)\n if (viewBox.length < 4) {\n throw new Error(\"Invalid viewBox attribute.\")\n }\n const [minX, minY, width = 0, height = 0] = viewBox\n\n // Calculate scale factors\n const scaleX = size.width / (width || 1)\n const scaleY = size.height / (height || 1)\n\n const scale = Math.min(scaleX, scaleY)\n\n // Adjust transformation to include scaling and centering\n const adjustedTransform = `${transform} scale(${scale}) translate(${-(minX ?? 0) - width / 2}, ${-(minY ?? 0) - height / 2})`\n\n return {\n name: \"g\",\n type: \"element\",\n attributes: { transform: adjustedTransform },\n children: pathElements,\n }\n }\n\n return {\n name: \"g\",\n type: \"element\",\n attributes: { transform },\n children: [\n {\n name: \"rect\",\n type: \"element\",\n attributes: {\n class: \"component\",\n x: (-size.width / 2).toString(),\n y: (-size.height / 2).toString(),\n width: size.width.toString(),\n height: size.height.toString(),\n },\n },\n ],\n }\n}\n\nfunction createSchematicPort(center: { x: number; y: number }): any {\n const portSize = 0.2\n const x = center.x - portSize / 2\n const y = center.y - portSize / 2\n\n return {\n name: \"rect\",\n type: \"element\",\n attributes: {\n class: \"port\",\n x: x.toString(),\n y: y.toString(),\n width: portSize.toString(),\n height: portSize.toString(),\n },\n }\n}\n\nfunction createPortToComponentLine(\n portCenter: { x: number; y: number },\n component: any,\n facingDirection: string,\n): any {\n const componentCenter = { x: component.center.x, y: portCenter.y }\n const halfWidth = component.size.width / 2\n const halfHeight = component.size.height / 2\n\n let endX = portCenter.x\n let endY = portCenter.y\n\n switch (facingDirection) {\n case \"left\":\n endX = componentCenter.x - halfWidth\n break\n case \"right\":\n endX = componentCenter.x + halfWidth\n break\n case \"up\":\n endY = componentCenter.y - halfHeight\n break\n case \"down\":\n endY = componentCenter.y + halfHeight\n break\n }\n\n return {\n name: \"line\",\n type: \"element\",\n attributes: {\n class: \"component-pin\",\n x1: portCenter.x.toString(),\n y1: portCenter.y.toString(),\n x2: endX.toString(),\n y2: endY.toString(),\n },\n }\n}\n\nfunction createSchematicTrace(\n trace: any,\n flipY: (y: number) => number,\n portPositions: Map<string, { x: number; y: number }>,\n): any {\n const edges = trace.edges\n if (edges.length === 0) return null\n\n let path = \"\"\n\n // Process all edges\n edges.forEach((edge: any, index: number) => {\n const fromPoint =\n edge.from.ti !== undefined ? portPositions.get(edge.from.ti) : edge.from\n const toPoint =\n edge.to.ti !== undefined ? portPositions.get(edge.to.ti) : edge.to\n\n if (!fromPoint || !toPoint) {\n return\n }\n\n const fromCoord = `${fromPoint.x} ${flipY(fromPoint.y)}`\n const toCoord = `${toPoint.x} ${flipY(toPoint.y)}`\n\n if (index === 0) {\n path += `M ${fromCoord} L ${toCoord}`\n } else {\n path += ` L ${toCoord}`\n }\n })\n\n // Handle connection to final port if needed\n if (trace.to_schematic_port_id) {\n const finalPort = portPositions.get(trace.to_schematic_port_id)\n if (finalPort) {\n const lastFromPoint = path.split(\"M\")[1]?.split(\"L\")[0]\n const lastEdge = edges[edges.length - 1]\n const lastPoint =\n lastEdge.to.ti !== undefined\n ? portPositions.get(lastEdge.to.ti)\n : lastEdge.to\n if (lastPoint.x !== finalPort.x || lastPoint.y !== finalPort.y) {\n const finalCoord = `${finalPort.x} ${flipY(finalPort.y)}`\n path += ` M ${lastFromPoint} L ${finalCoord}`\n }\n }\n }\n\n return path\n ? {\n name: \"path\",\n type: \"element\",\n attributes: {\n class: \"trace\",\n d: path,\n },\n }\n : null\n}\n\nfunction createSchematicText(\n text: any,\n position: { x: number; y: number },\n): any {\n return {\n name: \"text\",\n type: \"element\",\n attributes: {\n class: \"text\",\n x: position.x.toString(),\n y: position.y.toString(),\n \"text-anchor\": getTextAnchor(text.anchor),\n \"dominant-baseline\": \"middle\",\n },\n children: [\n {\n type: \"text\",\n value: text.text ? text.text : \"\",\n },\n ],\n }\n}\n\nfunction getTextAnchor(anchor: string): string {\n switch (anchor) {\n case \"left\":\n return \"start\"\n case \"right\":\n return \"end\"\n default:\n return \"middle\"\n }\n}\n\nexport { circuitJsonToSchematicSvg }\n"],"mappings":"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","names":["stringify","applyToPoint","compose","translate","applyToPoint","applyToPoint","applyToPoint","compose","translate","stringify","applyToPoint","stringify","scale"]}
1
+ {"version":3,"sources":["../src/lib/circuit-to-pcb-svg.ts","../src/utils/pairs.ts","../src/lib/svg-object-fns/create-svg-objects-from-pcb-trace.ts","../src/lib/layer-name-to-color.ts","../src/lib/svg-object-fns/create-svg-objects-from-smt-pads.ts","../src/lib/svg-object-fns/create-svg-objects-from-pcb-silkscreen-text.ts","../src/lib/svg-object-fns/create-svg-objects-from-pcb-fabrication-note-path.ts","../src/lib/svg-object-fns/create-svg-objects-from-pcb-silkscreen-path.ts","../src/lib/svg-object-fns/create-svg-objects-from-pcb-fabrication-note-text.ts","../src/lib/circuit-to-schematic-svg.ts"],"sourcesContent":["import type { AnySoupElement, PCBTrace } from \"@tscircuit/soup\"\nimport { type INode as SvgObject, stringify } from \"svgson\"\nimport {\n applyToPoint,\n compose,\n scale,\n translate,\n type Matrix,\n} from \"transformation-matrix\"\nimport { createSvgObjectsFromPcbTrace } from \"./svg-object-fns/create-svg-objects-from-pcb-trace\"\nimport { createSvgObjectsFromSmtPad } from \"./svg-object-fns/create-svg-objects-from-smt-pads\"\nimport { createSvgObjectsFromPcbSilkscreenText } from \"./svg-object-fns/create-svg-objects-from-pcb-silkscreen-text\"\nimport { createSvgObjectsFromPcbFabricationNotePath } from \"./svg-object-fns/create-svg-objects-from-pcb-fabrication-note-path\"\nimport { createSvgObjectsFromPcbSilkscreenPath } from \"./svg-object-fns/create-svg-objects-from-pcb-silkscreen-path\"\nimport { createSvgObjectsFromPcbFabricationNoteText } from \"./svg-object-fns/create-svg-objects-from-pcb-fabrication-note-text\"\n\ninterface PointObjectNotation {\n x: number\n y: number\n}\n\nfunction circuitJsonToPcbSvg(soup: AnySoupElement[]): string {\n let minX = Number.POSITIVE_INFINITY\n let minY = Number.POSITIVE_INFINITY\n let maxX = Number.NEGATIVE_INFINITY\n let maxY = Number.NEGATIVE_INFINITY\n\n // Process all elements to determine bounds\n for (const item of soup) {\n if (\"center\" in item && \"width\" in item && \"height\" in item) {\n updateBounds(item.center, item.width, item.height)\n } else if (\"x\" in item && \"y\" in item) {\n updateBounds({ x: item.x, y: item.y }, 0, 0)\n } else if (\"route\" in item) {\n updateTraceBounds(item.route)\n }\n }\n\n const padding = 1 // Reduced padding for tighter boundary\n const circuitWidth = maxX - minX + 2 * padding\n const circuitHeight = maxY - minY + 2 * padding\n\n const svgWidth = 800\n const svgHeight = 600\n const paths: PointObjectNotation[][] = []\n for (const item of soup) {\n if (\"route\" in item && item.route !== undefined) {\n paths.push(item.route as PointObjectNotation[])\n }\n }\n\n // Calculate scale factor to fit the circuit within the SVG, maintaining aspect ratio\n const scaleX = svgWidth / circuitWidth\n const scaleY = svgHeight / circuitHeight\n const scaleFactor = Math.min(scaleX, scaleY)\n\n // Calculate centering offsets\n const offsetX = (svgWidth - circuitWidth * scaleFactor) / 2\n const offsetY = (svgHeight - circuitHeight * scaleFactor) / 2\n\n const transform = compose(\n translate(\n offsetX - minX * scaleFactor + padding * scaleFactor,\n svgHeight - offsetY + minY * scaleFactor - padding * scaleFactor,\n ),\n scale(scaleFactor, -scaleFactor), // Flip in y-direction\n )\n\n const traceElements = soup\n .filter((elm) => elm.type === \"pcb_trace\")\n .flatMap((elm) => createSvgObjects(elm, transform))\n\n const holeElements = soup\n .filter((elm) => elm.type === \"pcb_plated_hole\")\n .flatMap((elm) => createSvgObjects(elm, transform))\n\n const silkscreenElements = soup\n .filter((elm) => elm.type === \"pcb_silkscreen_path\")\n .flatMap((elm) => createSvgObjectsFromPcbSilkscreenPath(elm, transform))\n\n const otherElements = soup\n .filter(\n (elm) =>\n ![\"pcb_trace\", \"pcb_plated_hole\", \"pcb_silkscreen_path\"].includes(\n elm.type,\n ),\n )\n .flatMap((item) => createSvgObjects(item, transform))\n\n let strokeWidth = String(0.05 * scaleFactor)\n\n for (const element of soup) {\n if (\"stroke_width\" in element) {\n strokeWidth = String(scaleFactor * element.stroke_width)\n break\n }\n }\n\n const svgObject: SvgObject = {\n name: \"svg\",\n type: \"element\",\n attributes: {\n xmlns: \"http://www.w3.org/2000/svg\",\n width: svgWidth.toString(),\n height: svgHeight.toString(),\n },\n value: \"\",\n children: [\n {\n name: \"style\",\n type: \"element\",\n children: [\n {\n type: \"text\",\n value: `\n .pcb-board { fill: #000; }\n .pcb-trace { fill: none; }\n .pcb-hole-outer { fill: rgb(200, 52, 52); }\n .pcb-hole-inner { fill: rgb(255, 38, 226); }\n .pcb-pad { }\n .pcb-boundary { fill: none; stroke: #fff; stroke-width: 0.3; }\n .pcb-silkscreen { fill: none; }\n .pcb-silkscreen-top { stroke: #f2eda1; }\n .pcb-silkscreen-bottom { stroke: #f2eda1; }\n .pcb-silkscreen-text { fill: #f2eda1; }\n `,\n },\n ],\n },\n {\n name: \"rect\",\n type: \"element\",\n attributes: {\n class: \"pcb-board\",\n x: \"0\",\n y: \"0\",\n width: svgWidth.toString(),\n height: svgHeight.toString(),\n },\n },\n createSvgObjectFromPcbBoundary(transform, minX, minY, maxX, maxY),\n {\n name: \"g\",\n type: \"element\",\n attributes: { id: \"other-elements\" },\n children: otherElements,\n },\n {\n name: \"g\",\n type: \"element\",\n attributes: { id: \"traces\" },\n children: traceElements,\n },\n {\n name: \"g\",\n type: \"element\",\n attributes: { id: \"holes\" },\n children: holeElements,\n },\n {\n name: \"g\",\n type: \"element\",\n attributes: { id: \"silkscreen\" },\n children: silkscreenElements,\n },\n ].filter((child): child is SvgObject => child !== null),\n }\n\n try {\n return stringify(svgObject as SvgObject)\n } catch (error) {\n console.error(\"Error stringifying SVG object:\", error)\n throw error\n }\n\n function updateBounds(center: any, width: any, height: any) {\n const halfWidth = width / 2\n const halfHeight = height / 2\n minX = Math.min(minX, center.x - halfWidth)\n minY = Math.min(minY, center.y - halfHeight)\n maxX = Math.max(maxX, center.x + halfWidth)\n maxY = Math.max(maxY, center.y + halfHeight)\n }\n\n function updateTraceBounds(route: any[]) {\n for (const point of route) {\n minX = Math.min(minX, point.x)\n minY = Math.min(minY, point.y)\n maxX = Math.max(maxX, point.x)\n maxY = Math.max(maxY, point.y)\n }\n }\n}\n\nfunction createSvgObjects(elm: AnySoupElement, transform: Matrix): SvgObject[] {\n switch (elm.type) {\n case \"pcb_component\":\n return [createSvgObjectsFromPcbComponent(elm, transform)].filter(Boolean)\n case \"pcb_trace\":\n return createSvgObjectsFromPcbTrace(elm, transform)\n case \"pcb_plated_hole\":\n return [createSvgObjectsFromPcbHole(elm, transform)].filter(Boolean)\n case \"pcb_smtpad\":\n return createSvgObjectsFromSmtPad(elm, transform)\n case \"pcb_silkscreen_text\":\n return createSvgObjectsFromPcbSilkscreenText(elm, transform)\n case \"pcb_fabrication_note_path\":\n return createSvgObjectsFromPcbFabricationNotePath(elm, transform)\n case \"pcb_fabrication_note_text\":\n return createSvgObjectsFromPcbFabricationNoteText(elm, transform)\n default:\n return []\n }\n}\n\nfunction createSvgObjectsFromPcbComponent(component: any, transform: any): any {\n const { center, width, height, rotation = 0 } = component\n const [x, y] = applyToPoint(transform, [center.x, center.y])\n const scaledWidth = width * Math.abs(transform.a)\n const scaledHeight = height * Math.abs(transform.d)\n const transformStr = `translate(${x}, ${y}) rotate(${-rotation}) scale(1, -1)`\n\n return {\n name: \"g\",\n type: \"element\",\n attributes: { transform: transformStr },\n children: [\n {\n name: \"rect\",\n type: \"element\",\n attributes: {\n class: \"pcb-component\",\n x: (-scaledWidth / 2).toString(),\n y: (-scaledHeight / 2).toString(),\n width: scaledWidth.toString(),\n height: scaledHeight.toString(),\n },\n },\n {\n name: \"rect\",\n type: \"element\",\n attributes: {\n class: \"pcb-component-outline\",\n x: (-scaledWidth / 2).toString(),\n y: (-scaledHeight / 2).toString(),\n width: scaledWidth.toString(),\n height: scaledHeight.toString(),\n },\n },\n ],\n }\n}\n\nfunction createSvgObjectsFromPcbHole(hole: any, transform: any): any {\n const [x, y] = applyToPoint(transform, [hole.x, hole.y])\n const scaledOuterRadius = (hole.outer_diameter / 2) * Math.abs(transform.a)\n const scaledInnerRadius = (hole.hole_diameter / 2) * Math.abs(transform.a)\n return {\n name: \"g\",\n type: \"element\",\n children: [\n {\n name: \"circle\",\n type: \"element\",\n attributes: {\n class: \"pcb-hole-outer\",\n cx: x.toString(),\n cy: y.toString(),\n r: scaledOuterRadius.toString(),\n },\n },\n {\n name: \"circle\",\n type: \"element\",\n attributes: {\n class: \"pcb-hole-inner\",\n cx: x.toString(),\n cy: y.toString(),\n r: scaledInnerRadius.toString(),\n },\n },\n ],\n }\n}\n\nfunction createSvgObjectFromPcbBoundary(\n transform: any,\n minX: number,\n minY: number,\n maxX: number,\n maxY: number,\n): SvgObject {\n const [x1, y1] = applyToPoint(transform, [minX, minY])\n const [x2, y2] = applyToPoint(transform, [maxX, maxY])\n const width = Math.abs(x2 - x1)\n const height = Math.abs(y2 - y1)\n const x = Math.min(x1, x2)\n const y = Math.min(y1, y2)\n return {\n name: \"rect\",\n type: \"element\",\n value: \"\",\n children: [],\n attributes: {\n class: \"pcb-boundary\",\n x: x.toString(),\n y: y.toString(),\n width: width.toString(),\n height: height.toString(),\n },\n }\n}\n\nexport { circuitJsonToPcbSvg }\n","/**\n * Return pairs of adjacent elements in an array.\n */\nexport function pairs<T>(arr: Array<T>): Array<[T, T]> {\n const result: Array<[T, T]> = []\n for (let i = 0; i < arr.length - 1; i++) {\n result.push([arr[i]!, arr[i + 1]!])\n }\n return result\n}\n","import type { AnySoupElement, PCBTrace } from \"@tscircuit/soup\"\nimport { pairs } from \"src/utils/pairs\"\nimport { type INode as SvgObject, stringify } from \"svgson\"\nimport { applyToPoint } from \"transformation-matrix\"\nimport { LAYER_NAME_TO_COLOR } from \"../layer-name-to-color\"\n\nexport function createSvgObjectsFromPcbTrace(\n trace: PCBTrace,\n transform: any,\n): SvgObject[] {\n if (!trace.route || !Array.isArray(trace.route) || trace.route.length < 2)\n return []\n\n const segments = pairs(trace.route)\n const svgObjects: SvgObject[] = []\n\n for (const [start, end] of segments) {\n const startPoint = applyToPoint(transform, [start.x, start.y])\n const endPoint = applyToPoint(transform, [end.x, end.y])\n\n const layer =\n \"layer\" in start ? start.layer : \"layer\" in end ? end.layer : null\n if (!layer) continue\n\n const layerColor =\n LAYER_NAME_TO_COLOR[layer as keyof typeof LAYER_NAME_TO_COLOR] ?? \"white\"\n\n const traceWidth =\n \"width\" in start ? start.width : \"width\" in end ? end.width : null\n\n svgObjects.push({\n name: \"path\",\n type: \"element\",\n value: \"\",\n children: [],\n attributes: {\n class: \"pcb-trace\",\n stroke: layerColor,\n d: `M ${startPoint[0]} ${startPoint[1]} L ${endPoint[0]} ${endPoint[1]}`,\n \"stroke-width\": traceWidth\n ? (traceWidth * Math.abs(transform.a)).toString()\n : \"0.3\",\n \"stroke-linecap\": \"round\",\n \"stroke-linejoin\": \"round\",\n \"shape-rendering\": \"crispEdges\",\n },\n })\n }\n return svgObjects\n}\n","/**\n * TODO use @tscircuit/pcb-colors when it's published\n */\nexport const LAYER_NAME_TO_COLOR = {\n top: \"rgb(200, 52, 52)\",\n bottom: \"rgb(77, 127, 196)\",\n}\n\nexport function layerNameToColor(layerName: string) {\n return (\n LAYER_NAME_TO_COLOR[layerName as keyof typeof LAYER_NAME_TO_COLOR] ??\n \"white\"\n )\n}\n","import type { PCBSMTPad } from \"@tscircuit/soup\"\nimport { applyToPoint, type Matrix } from \"transformation-matrix\"\nimport { layerNameToColor } from \"../layer-name-to-color\"\n\nexport function createSvgObjectsFromSmtPad(\n pad: PCBSMTPad,\n transform: Matrix,\n): any {\n const [x, y] = applyToPoint(transform, [pad.x, pad.y])\n\n if (pad.shape === \"rect\") {\n const width = pad.width * Math.abs(transform.a)\n const height = pad.height * Math.abs(transform.d)\n return [\n {\n name: \"rect\",\n type: \"element\",\n attributes: {\n class: \"pcb-pad\",\n fill: layerNameToColor(pad.layer),\n x: (x - width / 2).toString(),\n y: (y - height / 2).toString(),\n width: width.toString(),\n height: height.toString(),\n },\n },\n ]\n }\n // TODO implement smtpad circles/ovals etc.\n return []\n}\n","import type { PcbSilkscreenText } from \"@tscircuit/soup\"\nimport type { INode as SvgObject } from \"svgson\"\nimport {\n type Matrix,\n applyToPoint,\n compose,\n rotate,\n translate,\n toString as matrixToString,\n} from \"transformation-matrix\"\n\nexport function createSvgObjectsFromPcbSilkscreenText(\n pcbSilkscreenText: PcbSilkscreenText,\n transform: Matrix,\n): SvgObject[] {\n const {\n anchor_position,\n text,\n font_size = 1,\n layer = \"top\",\n } = pcbSilkscreenText\n\n if (\n !anchor_position ||\n typeof anchor_position.x !== \"number\" ||\n typeof anchor_position.y !== \"number\"\n ) {\n console.error(\"Invalid anchor_position:\", anchor_position)\n return []\n }\n\n const [transformedX, transformedY] = applyToPoint(transform, [\n anchor_position.x,\n anchor_position.y,\n ])\n const transformedFontSize = font_size * Math.abs(transform.a)\n\n // Remove ${} from text value and handle undefined text\n const cleanedText = (text || \"\").replace(/\\$\\{|\\}/g, \"\")\n if (!cleanedText) {\n return []\n }\n\n // Create a composite transformation\n const textTransform = compose(\n translate(transformedX, transformedY),\n rotate(Math.PI / 180), // Convert degrees to radians\n )\n\n const svgObject: SvgObject = {\n name: \"text\",\n type: \"element\",\n attributes: {\n x: \"0\",\n y: \"0\",\n \"font-family\": \"Arial, sans-serif\",\n \"font-size\": transformedFontSize.toString(),\n \"text-anchor\": \"middle\",\n \"dominant-baseline\": \"central\",\n transform: matrixToString(textTransform),\n class: `pcb-silkscreen-text pcb-silkscreen-${layer}`,\n \"data-pcb-silkscreen-text-id\": pcbSilkscreenText.pcb_component_id,\n },\n children: [\n {\n type: \"text\",\n value: cleanedText,\n name: \"\",\n attributes: {},\n children: [],\n },\n ],\n value: \"\",\n }\n\n return [svgObject]\n}\n","import type { PcbSilkscreenPath, PcbFabricationNotePath } from \"@tscircuit/soup\"\nimport { applyToPoint, type Matrix } from \"transformation-matrix\"\nimport type { SvgObject } from \"../svg-object\"\n\nexport function createSvgObjectsFromPcbFabricationNotePath(\n fabNotePath: PcbFabricationNotePath,\n transform: Matrix,\n): SvgObject[] {\n if (!fabNotePath.route || !Array.isArray(fabNotePath.route)) return []\n\n let path = fabNotePath.route\n .map((point: any, index: number) => {\n const [x, y] = applyToPoint(transform, [point.x, point.y])\n return index === 0 ? `M ${x} ${y}` : `L ${x} ${y}`\n })\n .join(\" \")\n\n // Close the path if it's not already closed\n const firstPoint = fabNotePath.route[0]\n const lastPoint = fabNotePath.route[fabNotePath.route.length - 1]\n if (firstPoint!.x !== lastPoint!.x || firstPoint!.y !== lastPoint!.y) {\n path += \" Z\"\n }\n return [\n {\n name: \"path\",\n type: \"element\",\n attributes: {\n class: \"pcb-fabrication-note-path\",\n stroke: \"rgba(255,255,255,0.5)\",\n d: path,\n \"stroke-width\": (\n fabNotePath.stroke_width * Math.abs(transform.a)\n ).toString(),\n \"data-pcb-component-id\": fabNotePath.pcb_component_id,\n \"data-pcb-fabrication-note-path-id\":\n fabNotePath.fabrication_note_path_id,\n },\n value: \"\",\n children: [],\n },\n ]\n}\n","import type { PcbSilkscreenPath } from \"@tscircuit/soup\"\nimport { applyToPoint, type Matrix } from \"transformation-matrix\"\nimport type { SvgObject } from \"../svg-object\"\n\nexport function createSvgObjectsFromPcbSilkscreenPath(\n silkscreenPath: PcbSilkscreenPath,\n transform: Matrix,\n): SvgObject[] {\n if (!silkscreenPath.route || !Array.isArray(silkscreenPath.route)) return []\n\n let path = silkscreenPath.route\n .map((point: any, index: number) => {\n const [x, y] = applyToPoint(transform, [point.x, point.y])\n return index === 0 ? `M ${x} ${y}` : `L ${x} ${y}`\n })\n .join(\" \")\n\n // Close the path if it's not already closed\n const firstPoint = silkscreenPath.route[0]\n const lastPoint = silkscreenPath.route[silkscreenPath.route.length - 1]\n if (firstPoint!.x !== lastPoint!.x || firstPoint!.y !== lastPoint!.y) {\n path += \" Z\"\n }\n return [\n {\n name: \"path\",\n type: \"element\",\n attributes: {\n class: `pcb-silkscreen pcb-silkscreen-${silkscreenPath.layer}`,\n d: path,\n \"stroke-width\": (\n silkscreenPath.stroke_width * Math.abs(transform.a)\n ).toString(),\n \"data-pcb-component-id\": silkscreenPath.pcb_component_id,\n \"data-pcb-silkscreen-path-id\": silkscreenPath.pcb_silkscreen_path_id,\n },\n value: \"\",\n children: [],\n },\n ]\n}\n","import type { PcbFabricationNoteText } from \"@tscircuit/soup\"\nimport type { INode as SvgObject } from \"svgson\"\nimport { toString as matrixToString } from \"transformation-matrix\"\nimport {\n type Matrix,\n applyToPoint,\n compose,\n rotate,\n translate,\n} from \"transformation-matrix\"\n\nexport function createSvgObjectsFromPcbFabricationNoteText(\n pcbFabNoteText: PcbFabricationNoteText,\n transform: Matrix,\n): SvgObject[] {\n const {\n anchor_position,\n anchor_alignment,\n text,\n font_size = 1,\n layer = \"top\",\n } = pcbFabNoteText\n\n if (\n !anchor_position ||\n typeof anchor_position.x !== \"number\" ||\n typeof anchor_position.y !== \"number\"\n ) {\n console.error(\"Invalid anchor_position:\", anchor_position)\n return []\n }\n\n const [transformedX, transformedY] = applyToPoint(transform, [\n anchor_position.x,\n anchor_position.y,\n ])\n const transformedFontSize = font_size * Math.abs(transform.a)\n\n // Remove ${} from text value and handle undefined text\n const cleanedText = (text || \"\").replace(/\\$\\{|\\}/g, \"\")\n if (!cleanedText) {\n return []\n }\n\n // Create a composite transformation\n const textTransform = compose(\n translate(transformedX, transformedY), // TODO do anchor_alignment\n rotate(Math.PI / 180), // Convert degrees to radians\n )\n\n const svgObject: SvgObject = {\n name: \"text\",\n type: \"element\",\n attributes: {\n x: \"0\",\n y: \"0\",\n \"font-family\": \"Arial, sans-serif\",\n \"font-size\": transformedFontSize.toString(),\n \"text-anchor\": \"middle\",\n \"dominant-baseline\": \"central\",\n transform: matrixToString(textTransform),\n class: \"pcb-fabrication-note-text\",\n fill: \"rgba(255,255,255,0.5)\",\n },\n children: [\n {\n type: \"text\",\n value: cleanedText,\n name: \"\",\n attributes: {},\n children: [],\n },\n ],\n value: \"\",\n }\n\n return [svgObject]\n}\n","import type { AnySoupElement } from \"@tscircuit/soup\"\nimport { getSvg, symbols } from \"schematic-symbols\"\nimport { parseSync, stringify } from \"svgson\"\n\nfunction circuitJsonToSchematicSvg(soup: AnySoupElement[]): string {\n let minX = Number.POSITIVE_INFINITY\n let minY = Number.POSITIVE_INFINITY\n let maxX = Number.NEGATIVE_INFINITY\n let maxY = Number.NEGATIVE_INFINITY\n\n const portSize = 0.2\n const portPositions = new Map()\n\n // First pass: find the bounds and collect port positions\n for (const item of soup) {\n if (item.type === \"schematic_component\") {\n updateBounds(item.center, item.size, item.rotation || 0)\n } else if (item.type === \"schematic_port\") {\n updateBounds(item.center, { width: portSize, height: portSize }, 0)\n portPositions.set(item.schematic_port_id, item.center)\n } else if (item.type === \"schematic_text\") {\n updateBounds(item.position, { width: 0, height: 0 }, 0)\n }\n }\n\n const height = maxY - minY\n const flipY = (y: number) => height - (y - minY) + minY\n\n const svgChildren: any[] = []\n\n // Process components\n const componentMap = new Map()\n for (const component of soup.filter(\n (item) => item.type === \"schematic_component\",\n )) {\n const flippedCenter = {\n x: component.center.x,\n y: flipY(component.center.y),\n }\n const svg = createSchematicComponent(\n flippedCenter,\n component.size,\n component.rotation || 0,\n (component as any).symbol_name,\n )\n svgChildren.push(svg)\n componentMap.set(component.schematic_component_id, component)\n }\n\n // Process ports and add lines to component edges\n for (const port of soup.filter((item) => item.type === \"schematic_port\")) {\n const flippedCenter = { x: port.center.x, y: flipY(port.center.y) }\n const svg = createSchematicPort(flippedCenter)\n svgChildren.push(svg)\n\n const component = componentMap.get(port.schematic_component_id)\n if (component) {\n const line = createPortToComponentLine(\n flippedCenter,\n component,\n port.facing_direction || \"right\",\n )\n svgChildren.push(line)\n }\n }\n\n // Process schematic traces\n for (const trace of soup.filter((item) => item.type === \"schematic_trace\")) {\n const svg = createSchematicTrace(trace, flipY, portPositions)\n if (svg) svgChildren.push(svg)\n }\n\n // Process text\n for (const text of soup.filter((item) => item.type === \"schematic_text\")) {\n const flippedPosition = { x: text.position.x, y: flipY(text.position.y) }\n const svg = createSchematicText(text, flippedPosition)\n svgChildren.push(svg)\n }\n\n const padding = 1\n const width = maxX - minX + 2 * padding\n const viewBox = `${minX - padding} ${minY - padding} ${width} ${height + 2 * padding}`\n\n const svgObject = {\n name: \"svg\",\n type: \"element\",\n attributes: {\n xmlns: \"http://www.w3.org/2000/svg\",\n viewBox,\n width: \"1200\",\n height: \"600\",\n style: \"background-color: #fff;\",\n },\n children: [\n {\n name: \"style\",\n type: \"element\",\n children: [\n {\n type: \"text\",\n value: `\n .component { fill: none; stroke: red; stroke-width: 0.03; }\n .component-pin { fill: none; stroke: red; stroke-width: 0.03; }\n .trace { stroke: green; stroke-width: 0.03; fill: none; }\n .text { font-family: Arial, sans-serif; font-size: 0.2px; }\n .port { fill: none; stroke: blue; stroke-width: 0.03; }\n `,\n },\n ],\n },\n ...svgChildren,\n ],\n }\n\n return stringify({ value: \"\", ...svgObject })\n\n function updateBounds(center: any, size: any, rotation: number) {\n const corners = [\n { x: -size.width / 2, y: -size.height / 2 },\n { x: size.width / 2, y: -size.height / 2 },\n { x: size.width / 2, y: size.height / 2 },\n { x: -size.width / 2, y: size.height / 2 },\n ]\n\n for (const corner of corners) {\n const rotatedX =\n corner.x * Math.cos(rotation) - corner.y * Math.sin(rotation) + center.x\n const rotatedY =\n corner.x * Math.sin(rotation) + corner.y * Math.cos(rotation) + center.y\n minX = Math.min(minX, rotatedX)\n minY = Math.min(minY, rotatedY)\n maxX = Math.max(maxX, rotatedX)\n maxY = Math.max(maxY, rotatedY)\n }\n }\n}\n\nfunction createSchematicComponent(\n center: { x: number; y: number },\n size: { width: number; height: number },\n rotation: number,\n symbolName?: string,\n): any {\n const transform = `translate(${center.x}, ${center.y}) rotate(${(rotation * 180) / Math.PI})`\n\n if (symbolName) {\n const symbol = (symbols as any)[symbolName]\n const paths = symbol.primitives.filter((p: any) => p.type === \"path\")\n const updatedSymbol = {\n ...symbol,\n primitives: paths,\n }\n const svg = parseSync(\n getSvg(updatedSymbol, {\n width: size.width,\n height: size.height,\n }),\n )\n\n // Filter out non-path elements and modify path colors\n const pathElements = svg.children\n .filter(\n (child: any) =>\n child.name === \"path\" && child.attributes.fill !== \"green\",\n )\n .map((path: any) => {\n const currentStrokeWidth = Number.parseFloat(\n path.attributes[\"stroke-width\"] || \"0.02\",\n )\n const newStrokeWidth = (currentStrokeWidth * 1.5).toString()\n\n return {\n ...path,\n attributes: {\n ...path.attributes,\n stroke:\n path.attributes.stroke === \"black\"\n ? \"red\"\n : path.attributes.stroke,\n \"stroke-width\": newStrokeWidth,\n },\n }\n })\n\n // Check if viewBox attribute exists\n const viewBoxAttr = svg.attributes.viewBox\n if (typeof viewBoxAttr === \"undefined\") {\n throw new Error(\"SVG does not have a viewBox attribute.\")\n }\n\n // Extract viewBox values\n const viewBox = viewBoxAttr.split(\" \").map(Number)\n if (viewBox.length < 4) {\n throw new Error(\"Invalid viewBox attribute.\")\n }\n const [minX, minY, width = 0, height = 0] = viewBox\n\n // Calculate scale factors\n const scaleX = size.width / (width || 1)\n const scaleY = size.height / (height || 1)\n\n const scale = Math.min(scaleX, scaleY)\n\n // Adjust transformation to include scaling and centering\n const adjustedTransform = `${transform} scale(${scale}) translate(${-(minX ?? 0) - width / 2}, ${-(minY ?? 0) - height / 2})`\n\n return {\n name: \"g\",\n type: \"element\",\n attributes: { transform: adjustedTransform },\n children: pathElements,\n }\n }\n\n return {\n name: \"g\",\n type: \"element\",\n attributes: { transform },\n children: [\n {\n name: \"rect\",\n type: \"element\",\n attributes: {\n class: \"component\",\n x: (-size.width / 2).toString(),\n y: (-size.height / 2).toString(),\n width: size.width.toString(),\n height: size.height.toString(),\n },\n },\n ],\n }\n}\n\nfunction createSchematicPort(center: { x: number; y: number }): any {\n const portSize = 0.2\n const x = center.x - portSize / 2\n const y = center.y - portSize / 2\n\n return {\n name: \"rect\",\n type: \"element\",\n attributes: {\n class: \"port\",\n x: x.toString(),\n y: y.toString(),\n width: portSize.toString(),\n height: portSize.toString(),\n },\n }\n}\n\nfunction createPortToComponentLine(\n portCenter: { x: number; y: number },\n component: any,\n facingDirection: string,\n): any {\n const componentCenter = { x: component.center.x, y: portCenter.y }\n const halfWidth = component.size.width / 2\n const halfHeight = component.size.height / 2\n\n let endX = portCenter.x\n let endY = portCenter.y\n\n switch (facingDirection) {\n case \"left\":\n endX = componentCenter.x - halfWidth\n break\n case \"right\":\n endX = componentCenter.x + halfWidth\n break\n case \"up\":\n endY = componentCenter.y - halfHeight\n break\n case \"down\":\n endY = componentCenter.y + halfHeight\n break\n }\n\n return {\n name: \"line\",\n type: \"element\",\n attributes: {\n class: \"component-pin\",\n x1: portCenter.x.toString(),\n y1: portCenter.y.toString(),\n x2: endX.toString(),\n y2: endY.toString(),\n },\n }\n}\n\nfunction createSchematicTrace(\n trace: any,\n flipY: (y: number) => number,\n portPositions: Map<string, { x: number; y: number }>,\n): any {\n const edges = trace.edges\n if (edges.length === 0) return null\n\n let path = \"\"\n\n // Process all edges\n edges.forEach((edge: any, index: number) => {\n const fromPoint =\n edge.from.ti !== undefined ? portPositions.get(edge.from.ti) : edge.from\n const toPoint =\n edge.to.ti !== undefined ? portPositions.get(edge.to.ti) : edge.to\n\n if (!fromPoint || !toPoint) {\n return\n }\n\n const fromCoord = `${fromPoint.x} ${flipY(fromPoint.y)}`\n const toCoord = `${toPoint.x} ${flipY(toPoint.y)}`\n\n if (index === 0) {\n path += `M ${fromCoord} L ${toCoord}`\n } else {\n path += ` L ${toCoord}`\n }\n })\n\n // Handle connection to final port if needed\n if (trace.to_schematic_port_id) {\n const finalPort = portPositions.get(trace.to_schematic_port_id)\n if (finalPort) {\n const lastFromPoint = path.split(\"M\")[1]?.split(\"L\")[0]\n const lastEdge = edges[edges.length - 1]\n const lastPoint =\n lastEdge.to.ti !== undefined\n ? portPositions.get(lastEdge.to.ti)\n : lastEdge.to\n if (lastPoint.x !== finalPort.x || lastPoint.y !== finalPort.y) {\n const finalCoord = `${finalPort.x} ${flipY(finalPort.y)}`\n path += ` M ${lastFromPoint} L ${finalCoord}`\n }\n }\n }\n\n return path\n ? {\n name: \"path\",\n type: \"element\",\n attributes: {\n class: \"trace\",\n d: path,\n },\n }\n : null\n}\n\nfunction createSchematicText(\n text: any,\n position: { x: number; y: number },\n): any {\n return {\n name: \"text\",\n type: \"element\",\n attributes: {\n class: \"text\",\n x: position.x.toString(),\n y: position.y.toString(),\n \"text-anchor\": getTextAnchor(text.anchor),\n \"dominant-baseline\": \"middle\",\n },\n children: [\n {\n type: \"text\",\n value: text.text ? text.text : \"\",\n },\n ],\n }\n}\n\nfunction getTextAnchor(anchor: string): string {\n switch (anchor) {\n case \"left\":\n return \"start\"\n case \"right\":\n return \"end\"\n default:\n return \"middle\"\n }\n}\n\nexport { circuitJsonToSchematicSvg }\n"],"mappings":"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","names":["stringify","applyToPoint","compose","translate","applyToPoint","applyToPoint","applyToPoint","applyToPoint","applyToPoint","matrixToString","applyToPoint","compose","rotate","translate","compose","translate","stringify","applyToPoint","stringify","scale"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "circuit-to-svg",
3
3
  "type": "module",
4
- "version": "0.0.23",
4
+ "version": "0.0.24",
5
5
  "description": "Convert Circuit JSON to SVG",
6
6
  "main": "dist/index.js",
7
7
  "files": [
@@ -26,9 +26,11 @@
26
26
  "@storybook/react": "^8.2.5",
27
27
  "@storybook/react-vite": "^8.2.5",
28
28
  "@storybook/test": "^8.2.5",
29
+ "@tscircuit/core": "^0.0.55",
29
30
  "@tscircuit/plop": "^0.0.10",
30
31
  "bun-match-svg": "^0.0.3",
31
32
  "esbuild": "^0.20.2",
33
+ "react": "^18.3.1",
32
34
  "storybook": "^8.2.5",
33
35
  "tsup": "^8.0.2",
34
36
  "typescript": "^5.4.5",