circuit-json-to-tscircuit 0.0.87 → 0.0.89

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (168) hide show
  1. package/dist/{chunk-DZP2ZWBQ.js → chunk-GVGY3ZZN.js} +256 -29
  2. package/dist/cli/main.js +5 -2
  3. package/dist/lib/index.js +1 -1
  4. package/lib/generate-board-cad-models-tsx/converter-types.ts +25 -0
  5. package/lib/generate-board-cad-models-tsx/format-point-prop.ts +7 -0
  6. package/lib/generate-board-cad-models-tsx/generate-cad-model-group-tsx.ts +43 -0
  7. package/lib/generate-board-cad-models-tsx/generate-cad-model-tsx.ts +56 -0
  8. package/lib/generate-board-cad-models-tsx/get-cad-model-groups.ts +54 -0
  9. package/lib/generate-board-cad-models-tsx/get-cad-model-origin-position.ts +13 -0
  10. package/lib/generate-board-cad-models-tsx/get-cad-model-placement.ts +46 -0
  11. package/lib/generate-board-cad-models-tsx/get-cad-model-url.ts +26 -0
  12. package/lib/generate-board-cad-models-tsx/get-model-url-with-format-hint.ts +10 -0
  13. package/lib/generate-board-cad-models-tsx.ts +22 -0
  14. package/lib/generate-footprint-tsx/convert-notes.ts +3 -0
  15. package/lib/get-board-using-template.ts +7 -1
  16. package/package.json +4 -1
  17. package/tests/__snapshots__/pcb-note-rounded-corners-comparison.snap.svg +8 -0
  18. package/tests/board-bottom-cad-model-rotation.test.ts +70 -0
  19. package/tests/fixtures/create-ti-evm-cad-model-loss-repro.ts +58 -0
  20. package/tests/fixtures/create-ti-evm-cad-model-visual-repro.ts +45 -0
  21. package/tests/fixtures/expect-ti-evm-3d-snapshot.ts +221 -0
  22. package/tests/fixtures/ti-evms/README.md +6 -0
  23. package/tests/fixtures/ti-evms/cad-models/dp83825evm/0.step.gz +0 -0
  24. package/tests/fixtures/ti-evms/cad-models/dp83825evm/1.step.gz +0 -0
  25. package/tests/fixtures/ti-evms/cad-models/dp83825evm/10.step.gz +0 -0
  26. package/tests/fixtures/ti-evms/cad-models/dp83825evm/11.step.gz +0 -0
  27. package/tests/fixtures/ti-evms/cad-models/dp83825evm/12.step.gz +0 -0
  28. package/tests/fixtures/ti-evms/cad-models/dp83825evm/13.step.gz +0 -0
  29. package/tests/fixtures/ti-evms/cad-models/dp83825evm/14.step.gz +0 -0
  30. package/tests/fixtures/ti-evms/cad-models/dp83825evm/15.step.gz +0 -0
  31. package/tests/fixtures/ti-evms/cad-models/dp83825evm/2.step.gz +0 -0
  32. package/tests/fixtures/ti-evms/cad-models/dp83825evm/3.step.gz +0 -0
  33. package/tests/fixtures/ti-evms/cad-models/dp83825evm/4.step.gz +0 -0
  34. package/tests/fixtures/ti-evms/cad-models/dp83825evm/5.step.gz +0 -0
  35. package/tests/fixtures/ti-evms/cad-models/dp83825evm/6.step.gz +0 -0
  36. package/tests/fixtures/ti-evms/cad-models/dp83825evm/7.step.gz +0 -0
  37. package/tests/fixtures/ti-evms/cad-models/dp83825evm/8.step.gz +0 -0
  38. package/tests/fixtures/ti-evms/cad-models/dp83825evm/9.step.gz +0 -0
  39. package/tests/fixtures/ti-evms/cad-models/drv8307evm/0.step.gz +0 -0
  40. package/tests/fixtures/ti-evms/cad-models/drv8307evm/1.step.gz +0 -0
  41. package/tests/fixtures/ti-evms/cad-models/drv8307evm/2.step.gz +0 -0
  42. package/tests/fixtures/ti-evms/cad-models/drv8307evm/3.step.gz +0 -0
  43. package/tests/fixtures/ti-evms/cad-models/drv8307evm/4.step.gz +0 -0
  44. package/tests/fixtures/ti-evms/cad-models/drv8307evm/5.step.gz +0 -0
  45. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/0.step.gz +0 -0
  46. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/1.step.gz +0 -0
  47. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/10.step.gz +0 -0
  48. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/11.step.gz +0 -0
  49. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/12.step.gz +0 -0
  50. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/13.step.gz +0 -0
  51. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/14.step.gz +0 -0
  52. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/15.step.gz +0 -0
  53. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/16.step.gz +0 -0
  54. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/17.step.gz +0 -0
  55. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/18.step.gz +0 -0
  56. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/19.step.gz +0 -0
  57. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/2.step.gz +0 -0
  58. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/20.step.gz +0 -0
  59. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/21.step.gz +0 -0
  60. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/22.step.gz +0 -0
  61. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/23.step.gz +0 -0
  62. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/24.step.gz +0 -0
  63. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/25.step.gz +0 -0
  64. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/26.step.gz +0 -0
  65. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/27.step.gz +0 -0
  66. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/28.step.gz +0 -0
  67. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/29.step.gz +0 -0
  68. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/3.step.gz +0 -0
  69. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/30.step.gz +0 -0
  70. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/31.step.gz +0 -0
  71. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/32.step.gz +0 -0
  72. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/33.step.gz +0 -0
  73. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/34.step.gz +0 -0
  74. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/35.step.gz +0 -0
  75. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/36.step.gz +0 -0
  76. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/37.step.gz +0 -0
  77. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/38.step.gz +0 -0
  78. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/39.step.gz +0 -0
  79. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/4.step.gz +0 -0
  80. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/40.step.gz +0 -0
  81. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/41.step.gz +0 -0
  82. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/42.step.gz +0 -0
  83. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/43.step.gz +0 -0
  84. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/44.step.gz +0 -0
  85. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/45.step.gz +0 -0
  86. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/5.step.gz +0 -0
  87. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/6.step.gz +0 -0
  88. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/7.step.gz +0 -0
  89. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/8.step.gz +0 -0
  90. package/tests/fixtures/ti-evms/cad-models/lm251772evm-pd/9.step.gz +0 -0
  91. package/tests/fixtures/ti-evms/cad-models/lm5155evm-fly/0.step.gz +0 -0
  92. package/tests/fixtures/ti-evms/cad-models/lm5155evm-fly/1.step.gz +0 -0
  93. package/tests/fixtures/ti-evms/cad-models/lm5155evm-fly/10.step.gz +0 -0
  94. package/tests/fixtures/ti-evms/cad-models/lm5155evm-fly/11.step.gz +0 -0
  95. package/tests/fixtures/ti-evms/cad-models/lm5155evm-fly/12.step.gz +0 -0
  96. package/tests/fixtures/ti-evms/cad-models/lm5155evm-fly/13.step.gz +0 -0
  97. package/tests/fixtures/ti-evms/cad-models/lm5155evm-fly/14.step.gz +0 -0
  98. package/tests/fixtures/ti-evms/cad-models/lm5155evm-fly/15.step.gz +0 -0
  99. package/tests/fixtures/ti-evms/cad-models/lm5155evm-fly/16.step.gz +0 -0
  100. package/tests/fixtures/ti-evms/cad-models/lm5155evm-fly/17.step.gz +0 -0
  101. package/tests/fixtures/ti-evms/cad-models/lm5155evm-fly/2.step.gz +0 -0
  102. package/tests/fixtures/ti-evms/cad-models/lm5155evm-fly/3.step.gz +0 -0
  103. package/tests/fixtures/ti-evms/cad-models/lm5155evm-fly/4.step.gz +0 -0
  104. package/tests/fixtures/ti-evms/cad-models/lm5155evm-fly/5.step.gz +0 -0
  105. package/tests/fixtures/ti-evms/cad-models/lm5155evm-fly/6.step.gz +0 -0
  106. package/tests/fixtures/ti-evms/cad-models/lm5155evm-fly/7.step.gz +0 -0
  107. package/tests/fixtures/ti-evms/cad-models/lm5155evm-fly/8.step.gz +0 -0
  108. package/tests/fixtures/ti-evms/cad-models/lm5155evm-fly/9.step.gz +0 -0
  109. package/tests/fixtures/ti-evms/cad-models/lmg342x-bb-evm/0.step.gz +0 -0
  110. package/tests/fixtures/ti-evms/cad-models/lmg342x-bb-evm/1.step.gz +0 -0
  111. package/tests/fixtures/ti-evms/cad-models/lmg342x-bb-evm/10.step.gz +0 -0
  112. package/tests/fixtures/ti-evms/cad-models/lmg342x-bb-evm/11.step.gz +0 -0
  113. package/tests/fixtures/ti-evms/cad-models/lmg342x-bb-evm/12.step.gz +0 -0
  114. package/tests/fixtures/ti-evms/cad-models/lmg342x-bb-evm/13.step.gz +0 -0
  115. package/tests/fixtures/ti-evms/cad-models/lmg342x-bb-evm/14.step.gz +0 -0
  116. package/tests/fixtures/ti-evms/cad-models/lmg342x-bb-evm/15.step.gz +0 -0
  117. package/tests/fixtures/ti-evms/cad-models/lmg342x-bb-evm/16.step.gz +0 -0
  118. package/tests/fixtures/ti-evms/cad-models/lmg342x-bb-evm/17.step.gz +0 -0
  119. package/tests/fixtures/ti-evms/cad-models/lmg342x-bb-evm/18.step.gz +0 -0
  120. package/tests/fixtures/ti-evms/cad-models/lmg342x-bb-evm/19.step.gz +0 -0
  121. package/tests/fixtures/ti-evms/cad-models/lmg342x-bb-evm/2.step.gz +0 -0
  122. package/tests/fixtures/ti-evms/cad-models/lmg342x-bb-evm/20.step.gz +0 -0
  123. package/tests/fixtures/ti-evms/cad-models/lmg342x-bb-evm/21.step.gz +0 -0
  124. package/tests/fixtures/ti-evms/cad-models/lmg342x-bb-evm/22.step.gz +0 -0
  125. package/tests/fixtures/ti-evms/cad-models/lmg342x-bb-evm/23.step.gz +0 -0
  126. package/tests/fixtures/ti-evms/cad-models/lmg342x-bb-evm/24.step.gz +0 -0
  127. package/tests/fixtures/ti-evms/cad-models/lmg342x-bb-evm/25.step.gz +0 -0
  128. package/tests/fixtures/ti-evms/cad-models/lmg342x-bb-evm/26.step.gz +0 -0
  129. package/tests/fixtures/ti-evms/cad-models/lmg342x-bb-evm/27.step.gz +0 -0
  130. package/tests/fixtures/ti-evms/cad-models/lmg342x-bb-evm/28.step.gz +0 -0
  131. package/tests/fixtures/ti-evms/cad-models/lmg342x-bb-evm/3.step.gz +0 -0
  132. package/tests/fixtures/ti-evms/cad-models/lmg342x-bb-evm/4.step.gz +0 -0
  133. package/tests/fixtures/ti-evms/cad-models/lmg342x-bb-evm/5.step.gz +0 -0
  134. package/tests/fixtures/ti-evms/cad-models/lmg342x-bb-evm/6.step.gz +0 -0
  135. package/tests/fixtures/ti-evms/cad-models/lmg342x-bb-evm/7.step.gz +0 -0
  136. package/tests/fixtures/ti-evms/cad-models/lmg342x-bb-evm/8.step.gz +0 -0
  137. package/tests/fixtures/ti-evms/cad-models/lmg342x-bb-evm/9.step.gz +0 -0
  138. package/tests/fixtures/ti-evms/dp83825evm-cad.circuit.json.gz +0 -0
  139. package/tests/fixtures/ti-evms/drv8307evm-cad.circuit.json.gz +0 -0
  140. package/tests/fixtures/ti-evms/lm251772evm-pd-cad.circuit.json.gz +0 -0
  141. package/tests/fixtures/ti-evms/lm5155evm-fly-cad.circuit.json.gz +0 -0
  142. package/tests/fixtures/ti-evms/lmg342x-bb-evm-cad.circuit.json.gz +0 -0
  143. package/tests/pcb-note-rounded-corners.test.tsx +63 -0
  144. package/tests/ti-evms/__snapshots__/ti-dp83825evm-cad-model-loss-generated-bottom-3d.snap.png +0 -0
  145. package/tests/ti-evms/__snapshots__/ti-dp83825evm-cad-model-loss-generated-top-3d.snap.png +0 -0
  146. package/tests/ti-evms/__snapshots__/ti-dp83825evm-cad-model-loss-source-bottom-3d.snap.png +0 -0
  147. package/tests/ti-evms/__snapshots__/ti-dp83825evm-cad-model-loss-source-top-3d.snap.png +0 -0
  148. package/tests/ti-evms/__snapshots__/ti-drv8307evm-cad-model-loss-generated-bottom-3d.snap.png +0 -0
  149. package/tests/ti-evms/__snapshots__/ti-drv8307evm-cad-model-loss-generated-top-3d.snap.png +0 -0
  150. package/tests/ti-evms/__snapshots__/ti-drv8307evm-cad-model-loss-source-bottom-3d.snap.png +0 -0
  151. package/tests/ti-evms/__snapshots__/ti-drv8307evm-cad-model-loss-source-top-3d.snap.png +0 -0
  152. package/tests/ti-evms/__snapshots__/ti-lm251772evm-pd-cad-model-loss-generated-bottom-3d.snap.png +0 -0
  153. package/tests/ti-evms/__snapshots__/ti-lm251772evm-pd-cad-model-loss-generated-top-3d.snap.png +0 -0
  154. package/tests/ti-evms/__snapshots__/ti-lm251772evm-pd-cad-model-loss-source-bottom-3d.snap.png +0 -0
  155. package/tests/ti-evms/__snapshots__/ti-lm251772evm-pd-cad-model-loss-source-top-3d.snap.png +0 -0
  156. package/tests/ti-evms/__snapshots__/ti-lm5155evm-fly-cad-model-loss-generated-bottom-3d.snap.png +0 -0
  157. package/tests/ti-evms/__snapshots__/ti-lm5155evm-fly-cad-model-loss-generated-top-3d.snap.png +0 -0
  158. package/tests/ti-evms/__snapshots__/ti-lm5155evm-fly-cad-model-loss-source-bottom-3d.snap.png +0 -0
  159. package/tests/ti-evms/__snapshots__/ti-lm5155evm-fly-cad-model-loss-source-top-3d.snap.png +0 -0
  160. package/tests/ti-evms/__snapshots__/ti-lmg342x-bb-evm-cad-model-loss-generated-bottom-3d.snap.png +0 -0
  161. package/tests/ti-evms/__snapshots__/ti-lmg342x-bb-evm-cad-model-loss-generated-top-3d.snap.png +0 -0
  162. package/tests/ti-evms/__snapshots__/ti-lmg342x-bb-evm-cad-model-loss-source-bottom-3d.snap.png +0 -0
  163. package/tests/ti-evms/__snapshots__/ti-lmg342x-bb-evm-cad-model-loss-source-top-3d.snap.png +0 -0
  164. package/tests/ti-evms/ti-dp83825evm-cad-model-loss.test.tsx +23 -0
  165. package/tests/ti-evms/ti-drv8307evm-cad-model-loss.test.tsx +23 -0
  166. package/tests/ti-evms/ti-lm251772evm-pd-cad-model-loss.test.tsx +23 -0
  167. package/tests/ti-evms/ti-lm5155evm-fly-cad-model-loss.test.tsx +23 -0
  168. package/tests/ti-evms/ti-lmg342x-bb-evm-cad-model-loss.test.tsx +23 -0
@@ -140,6 +140,222 @@ var getRuntimeNetNamesBySourcePortId = ({
140
140
  return result;
141
141
  };
142
142
 
143
+ // lib/generate-board-cad-models-tsx/format-point-prop.ts
144
+ function formatPointProp(point) {
145
+ return `{ x: ${point.x}, y: ${point.y}, z: ${point.z} }`;
146
+ }
147
+
148
+ // lib/generate-board-cad-models-tsx/get-cad-model-origin-position.ts
149
+ function getCadModelOriginPosition(cadComponent) {
150
+ if (cadComponent.model_origin_position !== void 0) {
151
+ return cadComponent.model_origin_position;
152
+ }
153
+ if (cadComponent.model_origin_alignment === "unknown") {
154
+ return { x: 0, y: 0, z: 0 };
155
+ }
156
+ return void 0;
157
+ }
158
+
159
+ // lib/generate-board-cad-models-tsx/get-cad-model-placement.ts
160
+ function getCadModelPlacement({
161
+ cadComponent,
162
+ parentPlacement,
163
+ pcbBoard
164
+ }) {
165
+ const cadModelCcwRotationDegrees = cadComponent.rotation ?? {
166
+ x: 0,
167
+ y: 0,
168
+ z: 0
169
+ };
170
+ const boardSurfaceZ = pcbBoard.thickness / 2;
171
+ let positionOffsetZ = cadComponent.position.z - boardSurfaceZ;
172
+ let ccwRotationOffsetDegrees = {
173
+ x: cadModelCcwRotationDegrees.x,
174
+ y: cadModelCcwRotationDegrees.y,
175
+ z: cadModelCcwRotationDegrees.z - parentPlacement.ccwRotationDegrees
176
+ };
177
+ if (parentPlacement.layer === "bottom") {
178
+ positionOffsetZ = cadComponent.position.z + boardSurfaceZ;
179
+ ccwRotationOffsetDegrees = {
180
+ x: cadModelCcwRotationDegrees.x,
181
+ y: cadModelCcwRotationDegrees.y - 180,
182
+ z: cadModelCcwRotationDegrees.z + parentPlacement.ccwRotationDegrees
183
+ };
184
+ }
185
+ return {
186
+ positionOffset: {
187
+ x: cadComponent.position.x - parentPlacement.center.x,
188
+ y: cadComponent.position.y - parentPlacement.center.y,
189
+ z: positionOffsetZ
190
+ },
191
+ ccwRotationOffsetDegrees
192
+ };
193
+ }
194
+
195
+ // lib/generate-board-cad-models-tsx/get-cad-model-url.ts
196
+ function getCadModelUrl(cadComponent) {
197
+ if (cadComponent.model_glb_url) {
198
+ return { format: "glb", url: cadComponent.model_glb_url };
199
+ }
200
+ if (cadComponent.model_gltf_url) {
201
+ return { format: "gltf", url: cadComponent.model_gltf_url };
202
+ }
203
+ if (cadComponent.model_obj_url) {
204
+ return { format: "obj", url: cadComponent.model_obj_url };
205
+ }
206
+ if (cadComponent.model_step_url) {
207
+ return { format: "step", url: cadComponent.model_step_url };
208
+ }
209
+ if (cadComponent.model_stl_url) {
210
+ return { format: "stl", url: cadComponent.model_stl_url };
211
+ }
212
+ if (cadComponent.model_wrl_url) {
213
+ return { format: "wrl", url: cadComponent.model_wrl_url };
214
+ }
215
+ return void 0;
216
+ }
217
+
218
+ // lib/generate-board-cad-models-tsx/get-model-url-with-format-hint.ts
219
+ function getModelUrlWithFormatHint({
220
+ format,
221
+ url
222
+ }) {
223
+ const pathWithoutQuery = url.split(/[?#]/u)[0] ?? "";
224
+ if (pathWithoutQuery.toLowerCase().endsWith(`.${format}`)) return url;
225
+ return `${url}#ext=${format}`;
226
+ }
227
+
228
+ // lib/generate-board-cad-models-tsx/generate-cad-model-tsx.ts
229
+ function generateCadModelTsx({
230
+ cadComponent,
231
+ parentPlacement,
232
+ pcbBoard
233
+ }) {
234
+ const modelUrl = getCadModelUrl(cadComponent);
235
+ if (!modelUrl) return void 0;
236
+ const placement = getCadModelPlacement({
237
+ cadComponent,
238
+ parentPlacement,
239
+ pcbBoard
240
+ });
241
+ const attributes = [
242
+ `modelUrl={${JSON.stringify(getModelUrlWithFormatHint(modelUrl))}}`,
243
+ `positionOffset={${formatPointProp(placement.positionOffset)}}`,
244
+ `rotationOffset={${formatPointProp(placement.ccwRotationOffsetDegrees)}}`
245
+ ];
246
+ if (cadComponent.model_unit_to_mm_scale_factor !== void 0) {
247
+ attributes.push(
248
+ `modelUnitToMmScale={${cadComponent.model_unit_to_mm_scale_factor}}`
249
+ );
250
+ }
251
+ if (cadComponent.model_board_normal_direction !== void 0) {
252
+ attributes.push(
253
+ `modelBoardNormalDirection={${JSON.stringify(cadComponent.model_board_normal_direction)}}`
254
+ );
255
+ }
256
+ const modelOriginPosition = getCadModelOriginPosition(cadComponent);
257
+ if (modelOriginPosition !== void 0) {
258
+ attributes.push(
259
+ `modelOriginPosition={${formatPointProp(modelOriginPosition)}}`
260
+ );
261
+ }
262
+ if (cadComponent.size !== void 0) {
263
+ attributes.push(`size={${formatPointProp(cadComponent.size)}}`);
264
+ }
265
+ if (cadComponent.show_as_translucent_model === true) {
266
+ attributes.push("showAsTranslucentModel");
267
+ }
268
+ return `<cadmodel ${attributes.join(" ")} />`;
269
+ }
270
+
271
+ // lib/generate-board-cad-models-tsx/generate-cad-model-group-tsx.ts
272
+ function generateCadModelGroupTsx({
273
+ cadModelGroup,
274
+ groupIndex,
275
+ pcbBoard
276
+ }) {
277
+ const { cadComponents, parentPlacement } = cadModelGroup;
278
+ const modelElements = cadComponents.flatMap((cadComponent) => {
279
+ const modelElement = generateCadModelTsx({
280
+ cadComponent,
281
+ parentPlacement,
282
+ pcbBoard
283
+ });
284
+ return modelElement ? [modelElement] : [];
285
+ });
286
+ if (modelElements.length === 0) return void 0;
287
+ let cadModelTsx = modelElements[0];
288
+ if (modelElements.length > 1) {
289
+ cadModelTsx = `<cadassembly>${modelElements.join("\n")}</cadassembly>`;
290
+ }
291
+ if (!cadModelTsx) return void 0;
292
+ const attributes = [
293
+ `name={${JSON.stringify(`ImportedCadModel${groupIndex + 1}`)}}`,
294
+ `pcbX={${parentPlacement.center.x}}`,
295
+ `pcbY={${parentPlacement.center.y}}`,
296
+ `pcbRotation="${parentPlacement.ccwRotationDegrees}deg"`,
297
+ `layer="${parentPlacement.layer}"`,
298
+ "noSchematicRepresentation",
299
+ "obstructsWithinBounds={false}",
300
+ "footprint={<footprint />}",
301
+ `cadModel={${cadModelTsx}}`
302
+ ];
303
+ return `<chip ${attributes.join(" ")} />`;
304
+ }
305
+
306
+ // lib/generate-board-cad-models-tsx/get-cad-model-groups.ts
307
+ function getCadModelGroups(circuitJson) {
308
+ const pcbComponentById = /* @__PURE__ */ new Map();
309
+ for (const element of circuitJson) {
310
+ if (element.type === "pcb_component") {
311
+ pcbComponentById.set(element.pcb_component_id, element);
312
+ }
313
+ }
314
+ const cadModelGroupByKey = /* @__PURE__ */ new Map();
315
+ for (const element of circuitJson) {
316
+ if (element.type !== "cad_component" || !getCadModelUrl(element)) continue;
317
+ const pcbComponent = element.pcb_component_id ? pcbComponentById.get(element.pcb_component_id) : void 0;
318
+ const layer = (element.layer ?? pcbComponent?.layer) === "bottom" ? "bottom" : "top";
319
+ let parentPlacement = {
320
+ center: element.position,
321
+ ccwRotationDegrees: 0,
322
+ layer
323
+ };
324
+ let cadModelGroupKey = element.cad_component_id;
325
+ if (pcbComponent !== void 0) {
326
+ parentPlacement = {
327
+ center: pcbComponent.center,
328
+ ccwRotationDegrees: pcbComponent.rotation,
329
+ layer
330
+ };
331
+ cadModelGroupKey = `${pcbComponent.pcb_component_id}:${layer}`;
332
+ }
333
+ const cadModelGroup = cadModelGroupByKey.get(cadModelGroupKey) ?? {
334
+ cadComponents: [],
335
+ parentPlacement
336
+ };
337
+ cadModelGroup.cadComponents.push(element);
338
+ cadModelGroupByKey.set(cadModelGroupKey, cadModelGroup);
339
+ }
340
+ return [...cadModelGroupByKey.values()];
341
+ }
342
+
343
+ // lib/generate-board-cad-models-tsx.ts
344
+ function generateBoardCadModelsTsx({
345
+ circuitJson,
346
+ pcbBoard
347
+ }) {
348
+ if (!pcbBoard) return [];
349
+ return getCadModelGroups(circuitJson).flatMap((cadModelGroup, groupIndex) => {
350
+ const cadModelGroupTsx = generateCadModelGroupTsx({
351
+ cadModelGroup,
352
+ groupIndex,
353
+ pcbBoard
354
+ });
355
+ return cadModelGroupTsx ? [cadModelGroupTsx] : [];
356
+ });
357
+ }
358
+
143
359
  // lib/generate-board-nets-tsx.ts
144
360
  var generateBoardNetsTsx = (context) => {
145
361
  const runtimeNetNames = new Set(context.runtimeNetNameBySourceNetId.values());
@@ -150,6 +366,38 @@ var generateBoardNetsTsx = (context) => {
150
366
  });
151
367
  };
152
368
 
369
+ // lib/generate-board-schematic-sheet-tsx.ts
370
+ import { mmStr } from "@tscircuit/mm";
371
+ var DEFAULT_SHEET_DIMENSIONS_MM = {
372
+ a4: { width: 297, height: 210 },
373
+ ansi_b: { width: 431.8, height: 279.4 }
374
+ };
375
+ var generateBoardSchematicSheetTsx = ({
376
+ circuitJson,
377
+ schematicElements
378
+ }) => {
379
+ const sheet = circuitJson.find(
380
+ (element) => element.type === "schematic_sheet"
381
+ );
382
+ if (!sheet) return schematicElements.join("\n");
383
+ const attrs = [];
384
+ if (sheet.name) attrs.push(`name={${JSON.stringify(sheet.name)}}`);
385
+ if (sheet.sheet_index !== void 0) {
386
+ attrs.push(`sheetIndex={${sheet.sheet_index}}`);
387
+ }
388
+ if (sheet.sheet_size) {
389
+ attrs.push(`sheetSize="${sheet.sheet_size === "a4" ? "A4" : "ANSI_B"}"`);
390
+ }
391
+ const defaultDimensions = DEFAULT_SHEET_DIMENSIONS_MM[sheet.sheet_size ?? "a4"];
392
+ const sheetWidth = sheet.sheet_width ?? defaultDimensions.width;
393
+ const sheetHeight = sheet.sheet_height ?? defaultDimensions.height;
394
+ attrs.push(`sheetWidth="${mmStr(sheetWidth)}"`);
395
+ attrs.push(`sheetHeight="${mmStr(sheetHeight)}"`);
396
+ return `<schematicsheet ${attrs.join(" ")}>
397
+ ${schematicElements.join("\n")}
398
+ </schematicsheet>`;
399
+ };
400
+
153
401
  // lib/generate-board-schematic-tsx/convert-primitives.ts
154
402
  import { schematic_text } from "circuit-json";
155
403
 
@@ -1253,35 +1501,6 @@ var generateBoardSchematicElements = (circuitJson) => {
1253
1501
  ];
1254
1502
  };
1255
1503
 
1256
- // lib/generate-board-schematic-sheet-tsx.ts
1257
- import { mmStr } from "@tscircuit/mm";
1258
- var generateBoardSchematicSheetTsx = ({
1259
- circuitJson,
1260
- schematicElements
1261
- }) => {
1262
- const sheet = circuitJson.find(
1263
- (element) => element.type === "schematic_sheet"
1264
- );
1265
- if (!sheet) return schematicElements.join("\n");
1266
- const attrs = [];
1267
- if (sheet.name) attrs.push(`name={${JSON.stringify(sheet.name)}}`);
1268
- if (sheet.sheet_index !== void 0) {
1269
- attrs.push(`sheetIndex={${sheet.sheet_index}}`);
1270
- }
1271
- if (sheet.sheet_size) {
1272
- attrs.push(`sheetSize="${sheet.sheet_size === "a4" ? "A4" : "ANSI_B"}"`);
1273
- }
1274
- if (sheet.sheet_width !== void 0) {
1275
- attrs.push(`sheetWidth="${mmStr(sheet.sheet_width)}"`);
1276
- }
1277
- if (sheet.sheet_height !== void 0) {
1278
- attrs.push(`sheetHeight="${mmStr(sheet.sheet_height)}"`);
1279
- }
1280
- return `<schematicsheet ${attrs.join(" ")}>
1281
- ${schematicElements.join("\n")}
1282
- </schematicsheet>`;
1283
- };
1284
-
1285
1504
  // lib/generate-copper-pours-tsx.ts
1286
1505
  import { su as su6 } from "@tscircuit/soup-util";
1287
1506
 
@@ -1924,6 +2143,9 @@ var convertNotes = (circuitJson) => {
1924
2143
  if (noteRect.color !== void 0) {
1925
2144
  attrs.push(`color="${noteRect.color}"`);
1926
2145
  }
2146
+ if (noteRect.corner_radius !== void 0) {
2147
+ attrs.push(`cornerRadius={${noteRect.corner_radius}}`);
2148
+ }
1927
2149
  elementStrings.push(`<pcbnoterect ${attrs.join(" ")} />`);
1928
2150
  }
1929
2151
  for (const notePath of notePaths) {
@@ -2393,6 +2615,10 @@ var getBoardUsingTemplate = ({
2393
2615
  const footprintTsx = generateFootprintTsx(circuitJson, context);
2394
2616
  const copperPoursTsx = generateCopperPoursTsx(circuitJson, context);
2395
2617
  const boardNetsTsx = generateBoardNetsTsx(context);
2618
+ const boardCadModelsTsx = generateBoardCadModelsTsx({
2619
+ circuitJson,
2620
+ pcbBoard
2621
+ });
2396
2622
  const schematicElements = generateBoardSchematicElements(circuitJson);
2397
2623
  const schematicSheetTsx = generateBoardSchematicSheetTsx({
2398
2624
  circuitJson,
@@ -2402,6 +2628,7 @@ var getBoardUsingTemplate = ({
2402
2628
  ...boardNetsTsx,
2403
2629
  footprintTsx ? `<chip name="${context.pcbChipName}" noSchematicRepresentation footprint={${footprintTsx}} />` : "",
2404
2630
  ...copperPoursTsx,
2631
+ ...boardCadModelsTsx,
2405
2632
  schematicSheetTsx
2406
2633
  ].filter(Boolean).join("\n");
2407
2634
  return `
package/dist/cli/main.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  convertCircuitJsonToTscircuit
4
- } from "../chunk-DZP2ZWBQ.js";
4
+ } from "../chunk-GVGY3ZZN.js";
5
5
 
6
6
  // cli/main.ts
7
7
  import { Command } from "commander";
@@ -16,7 +16,7 @@ var package_default = {
16
16
  "./cli": "./dist/cli/main.js"
17
17
  },
18
18
  type: "module",
19
- version: "0.0.86",
19
+ version: "0.0.88",
20
20
  repository: {
21
21
  type: "git",
22
22
  url: "https://github.com/tscircuit/circuit-json-to-tscircuit.git"
@@ -38,9 +38,12 @@ var package_default = {
38
38
  "@types/react-dom": "18",
39
39
  "bun-match-svg": "^0.0.15",
40
40
  "circuit-json": "^0.0.521",
41
+ "circuit-json-to-gltf": "0.0.151",
41
42
  "circuit-to-svg": "https://pkg.pr.new/tscircuit/circuit-to-svg@738ef1d",
42
43
  commander: "^13.1.0",
44
+ "fast-png": "8.0.0",
43
45
  prettier: "^3.9.5",
46
+ poppygl: "0.0.34",
44
47
  "schematic-symbols": "0.0.248",
45
48
  shiki: "^4.3.1",
46
49
  "stack-svgs": "^0.0.1",
package/dist/lib/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  convertCircuitJsonToTscircuit
3
- } from "../chunk-DZP2ZWBQ.js";
3
+ } from "../chunk-GVGY3ZZN.js";
4
4
  export {
5
5
  convertCircuitJsonToTscircuit
6
6
  };
@@ -0,0 +1,25 @@
1
+ import type { CadComponent, PcbComponent } from "circuit-json"
2
+
3
+ export interface CadModelUrl {
4
+ format: "glb" | "gltf" | "obj" | "step" | "stl" | "wrl"
5
+ url: string
6
+ }
7
+
8
+ export interface CadModelParentPlacement {
9
+ center: { x: number; y: number }
10
+ ccwRotationDegrees: number
11
+ layer: "bottom" | "top"
12
+ }
13
+
14
+ export interface CadModelGroup {
15
+ cadComponents: CadComponent[]
16
+ parentPlacement: CadModelParentPlacement
17
+ }
18
+
19
+ export interface CadModelPlacement {
20
+ positionOffset: { x: number; y: number; z: number }
21
+ ccwRotationOffsetDegrees: { x: number; y: number; z: number }
22
+ }
23
+
24
+ export type CadModelGroupKey = string
25
+ export type PcbComponentId = PcbComponent["pcb_component_id"]
@@ -0,0 +1,7 @@
1
+ export function formatPointProp(point: {
2
+ x: number
3
+ y: number
4
+ z: number
5
+ }): string {
6
+ return `{ x: ${point.x}, y: ${point.y}, z: ${point.z} }`
7
+ }
@@ -0,0 +1,43 @@
1
+ import type { PcbBoard } from "circuit-json"
2
+ import type { CadModelGroup } from "./converter-types"
3
+ import { generateCadModelTsx } from "./generate-cad-model-tsx"
4
+
5
+ export function generateCadModelGroupTsx({
6
+ cadModelGroup,
7
+ groupIndex,
8
+ pcbBoard,
9
+ }: {
10
+ cadModelGroup: CadModelGroup
11
+ groupIndex: number
12
+ pcbBoard: PcbBoard
13
+ }): string | undefined {
14
+ const { cadComponents, parentPlacement } = cadModelGroup
15
+ const modelElements = cadComponents.flatMap((cadComponent) => {
16
+ const modelElement = generateCadModelTsx({
17
+ cadComponent,
18
+ parentPlacement,
19
+ pcbBoard,
20
+ })
21
+ return modelElement ? [modelElement] : []
22
+ })
23
+ if (modelElements.length === 0) return undefined
24
+
25
+ let cadModelTsx = modelElements[0]
26
+ if (modelElements.length > 1) {
27
+ cadModelTsx = `<cadassembly>${modelElements.join("\n")}</cadassembly>`
28
+ }
29
+ if (!cadModelTsx) return undefined
30
+
31
+ const attributes = [
32
+ `name={${JSON.stringify(`ImportedCadModel${groupIndex + 1}`)}}`,
33
+ `pcbX={${parentPlacement.center.x}}`,
34
+ `pcbY={${parentPlacement.center.y}}`,
35
+ `pcbRotation="${parentPlacement.ccwRotationDegrees}deg"`,
36
+ `layer="${parentPlacement.layer}"`,
37
+ "noSchematicRepresentation",
38
+ "obstructsWithinBounds={false}",
39
+ "footprint={<footprint />}",
40
+ `cadModel={${cadModelTsx}}`,
41
+ ]
42
+ return `<chip ${attributes.join(" ")} />`
43
+ }
@@ -0,0 +1,56 @@
1
+ import type { CadComponent, PcbBoard } from "circuit-json"
2
+ import type { CadModelParentPlacement } from "./converter-types"
3
+ import { formatPointProp } from "./format-point-prop"
4
+ import { getCadModelOriginPosition } from "./get-cad-model-origin-position"
5
+ import { getCadModelPlacement } from "./get-cad-model-placement"
6
+ import { getCadModelUrl } from "./get-cad-model-url"
7
+ import { getModelUrlWithFormatHint } from "./get-model-url-with-format-hint"
8
+
9
+ export function generateCadModelTsx({
10
+ cadComponent,
11
+ parentPlacement,
12
+ pcbBoard,
13
+ }: {
14
+ cadComponent: CadComponent
15
+ parentPlacement: CadModelParentPlacement
16
+ pcbBoard: PcbBoard
17
+ }): string | undefined {
18
+ const modelUrl = getCadModelUrl(cadComponent)
19
+ if (!modelUrl) return undefined
20
+
21
+ const placement = getCadModelPlacement({
22
+ cadComponent,
23
+ parentPlacement,
24
+ pcbBoard,
25
+ })
26
+ const attributes = [
27
+ `modelUrl={${JSON.stringify(getModelUrlWithFormatHint(modelUrl))}}`,
28
+ `positionOffset={${formatPointProp(placement.positionOffset)}}`,
29
+ `rotationOffset={${formatPointProp(placement.ccwRotationOffsetDegrees)}}`,
30
+ ]
31
+
32
+ if (cadComponent.model_unit_to_mm_scale_factor !== undefined) {
33
+ attributes.push(
34
+ `modelUnitToMmScale={${cadComponent.model_unit_to_mm_scale_factor}}`,
35
+ )
36
+ }
37
+ if (cadComponent.model_board_normal_direction !== undefined) {
38
+ attributes.push(
39
+ `modelBoardNormalDirection={${JSON.stringify(cadComponent.model_board_normal_direction)}}`,
40
+ )
41
+ }
42
+ const modelOriginPosition = getCadModelOriginPosition(cadComponent)
43
+ if (modelOriginPosition !== undefined) {
44
+ attributes.push(
45
+ `modelOriginPosition={${formatPointProp(modelOriginPosition)}}`,
46
+ )
47
+ }
48
+ if (cadComponent.size !== undefined) {
49
+ attributes.push(`size={${formatPointProp(cadComponent.size)}}`)
50
+ }
51
+ if (cadComponent.show_as_translucent_model === true) {
52
+ attributes.push("showAsTranslucentModel")
53
+ }
54
+
55
+ return `<cadmodel ${attributes.join(" ")} />`
56
+ }
@@ -0,0 +1,54 @@
1
+ import type { AnyCircuitElement, PcbComponent } from "circuit-json"
2
+ import type {
3
+ CadModelGroup,
4
+ CadModelGroupKey,
5
+ CadModelParentPlacement,
6
+ PcbComponentId,
7
+ } from "./converter-types"
8
+ import { getCadModelUrl } from "./get-cad-model-url"
9
+
10
+ export function getCadModelGroups(
11
+ circuitJson: AnyCircuitElement[],
12
+ ): CadModelGroup[] {
13
+ const pcbComponentById = new Map<PcbComponentId, PcbComponent>()
14
+ for (const element of circuitJson) {
15
+ if (element.type === "pcb_component") {
16
+ pcbComponentById.set(element.pcb_component_id, element)
17
+ }
18
+ }
19
+
20
+ const cadModelGroupByKey = new Map<CadModelGroupKey, CadModelGroup>()
21
+ for (const element of circuitJson) {
22
+ if (element.type !== "cad_component" || !getCadModelUrl(element)) continue
23
+
24
+ const pcbComponent = element.pcb_component_id
25
+ ? pcbComponentById.get(element.pcb_component_id)
26
+ : undefined
27
+ const layer =
28
+ (element.layer ?? pcbComponent?.layer) === "bottom" ? "bottom" : "top"
29
+ let parentPlacement: CadModelParentPlacement = {
30
+ center: element.position,
31
+ ccwRotationDegrees: 0,
32
+ layer,
33
+ }
34
+ let cadModelGroupKey: CadModelGroupKey = element.cad_component_id
35
+
36
+ if (pcbComponent !== undefined) {
37
+ parentPlacement = {
38
+ center: pcbComponent.center,
39
+ ccwRotationDegrees: pcbComponent.rotation,
40
+ layer,
41
+ }
42
+ cadModelGroupKey = `${pcbComponent.pcb_component_id}:${layer}`
43
+ }
44
+
45
+ const cadModelGroup = cadModelGroupByKey.get(cadModelGroupKey) ?? {
46
+ cadComponents: [],
47
+ parentPlacement,
48
+ }
49
+ cadModelGroup.cadComponents.push(element)
50
+ cadModelGroupByKey.set(cadModelGroupKey, cadModelGroup)
51
+ }
52
+
53
+ return [...cadModelGroupByKey.values()]
54
+ }
@@ -0,0 +1,13 @@
1
+ import type { CadComponent } from "circuit-json"
2
+
3
+ export function getCadModelOriginPosition(
4
+ cadComponent: CadComponent,
5
+ ): { x: number; y: number; z: number } | undefined {
6
+ if (cadComponent.model_origin_position !== undefined) {
7
+ return cadComponent.model_origin_position
8
+ }
9
+ if (cadComponent.model_origin_alignment === "unknown") {
10
+ return { x: 0, y: 0, z: 0 }
11
+ }
12
+ return undefined
13
+ }
@@ -0,0 +1,46 @@
1
+ import type { CadComponent, PcbBoard } from "circuit-json"
2
+ import type {
3
+ CadModelParentPlacement,
4
+ CadModelPlacement,
5
+ } from "./converter-types"
6
+
7
+ export function getCadModelPlacement({
8
+ cadComponent,
9
+ parentPlacement,
10
+ pcbBoard,
11
+ }: {
12
+ cadComponent: CadComponent
13
+ parentPlacement: CadModelParentPlacement
14
+ pcbBoard: PcbBoard
15
+ }): CadModelPlacement {
16
+ const cadModelCcwRotationDegrees = cadComponent.rotation ?? {
17
+ x: 0,
18
+ y: 0,
19
+ z: 0,
20
+ }
21
+ const boardSurfaceZ = pcbBoard.thickness / 2
22
+ let positionOffsetZ = cadComponent.position.z - boardSurfaceZ
23
+ let ccwRotationOffsetDegrees = {
24
+ x: cadModelCcwRotationDegrees.x,
25
+ y: cadModelCcwRotationDegrees.y,
26
+ z: cadModelCcwRotationDegrees.z - parentPlacement.ccwRotationDegrees,
27
+ }
28
+
29
+ if (parentPlacement.layer === "bottom") {
30
+ positionOffsetZ = cadComponent.position.z + boardSurfaceZ
31
+ ccwRotationOffsetDegrees = {
32
+ x: cadModelCcwRotationDegrees.x,
33
+ y: cadModelCcwRotationDegrees.y - 180,
34
+ z: cadModelCcwRotationDegrees.z + parentPlacement.ccwRotationDegrees,
35
+ }
36
+ }
37
+
38
+ return {
39
+ positionOffset: {
40
+ x: cadComponent.position.x - parentPlacement.center.x,
41
+ y: cadComponent.position.y - parentPlacement.center.y,
42
+ z: positionOffsetZ,
43
+ },
44
+ ccwRotationOffsetDegrees,
45
+ }
46
+ }
@@ -0,0 +1,26 @@
1
+ import type { CadComponent } from "circuit-json"
2
+ import type { CadModelUrl } from "./converter-types"
3
+
4
+ export function getCadModelUrl(
5
+ cadComponent: CadComponent,
6
+ ): CadModelUrl | undefined {
7
+ if (cadComponent.model_glb_url) {
8
+ return { format: "glb", url: cadComponent.model_glb_url }
9
+ }
10
+ if (cadComponent.model_gltf_url) {
11
+ return { format: "gltf", url: cadComponent.model_gltf_url }
12
+ }
13
+ if (cadComponent.model_obj_url) {
14
+ return { format: "obj", url: cadComponent.model_obj_url }
15
+ }
16
+ if (cadComponent.model_step_url) {
17
+ return { format: "step", url: cadComponent.model_step_url }
18
+ }
19
+ if (cadComponent.model_stl_url) {
20
+ return { format: "stl", url: cadComponent.model_stl_url }
21
+ }
22
+ if (cadComponent.model_wrl_url) {
23
+ return { format: "wrl", url: cadComponent.model_wrl_url }
24
+ }
25
+ return undefined
26
+ }
@@ -0,0 +1,10 @@
1
+ import type { CadModelUrl } from "./converter-types"
2
+
3
+ export function getModelUrlWithFormatHint({
4
+ format,
5
+ url,
6
+ }: CadModelUrl): string {
7
+ const pathWithoutQuery = url.split(/[?#]/u)[0] ?? ""
8
+ if (pathWithoutQuery.toLowerCase().endsWith(`.${format}`)) return url
9
+ return `${url}#ext=${format}`
10
+ }
@@ -0,0 +1,22 @@
1
+ import type { AnyCircuitElement, PcbBoard } from "circuit-json"
2
+ import { generateCadModelGroupTsx } from "./generate-board-cad-models-tsx/generate-cad-model-group-tsx"
3
+ import { getCadModelGroups } from "./generate-board-cad-models-tsx/get-cad-model-groups"
4
+
5
+ export function generateBoardCadModelsTsx({
6
+ circuitJson,
7
+ pcbBoard,
8
+ }: {
9
+ circuitJson: AnyCircuitElement[]
10
+ pcbBoard: PcbBoard | undefined
11
+ }): string[] {
12
+ if (!pcbBoard) return []
13
+
14
+ return getCadModelGroups(circuitJson).flatMap((cadModelGroup, groupIndex) => {
15
+ const cadModelGroupTsx = generateCadModelGroupTsx({
16
+ cadModelGroup,
17
+ groupIndex,
18
+ pcbBoard,
19
+ })
20
+ return cadModelGroupTsx ? [cadModelGroupTsx] : []
21
+ })
22
+ }
@@ -42,6 +42,9 @@ export const convertNotes: FootprintElementConverter = (circuitJson) => {
42
42
  if (noteRect.color !== undefined) {
43
43
  attrs.push(`color="${noteRect.color}"`)
44
44
  }
45
+ if (noteRect.corner_radius !== undefined) {
46
+ attrs.push(`cornerRadius={${noteRect.corner_radius}}`)
47
+ }
45
48
 
46
49
  elementStrings.push(`<pcbnoterect ${attrs.join(" ")} />`)
47
50
  }