@tscircuit/core 0.0.2163 → 0.0.2165

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 (3) hide show
  1. package/dist/index.d.ts +34 -33
  2. package/dist/index.js +1013 -683
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -138,6 +138,629 @@ __export(components_exports, {
138
138
  VoltageSource: () => VoltageSource
139
139
  });
140
140
 
141
+ // lib/components/base-components/NormalComponent/NormalComponent_doInitialSourcePinSpecificationChecks.ts
142
+ import {
143
+ checkAllPinsInComponentAreUnderspecified,
144
+ checkNoGroundPinDefined,
145
+ checkNoPowerPinDefined
146
+ } from "@tscircuit/checks";
147
+
148
+ // lib/components/primitive-components/Port/apply-pin-attributes-to-source-port.ts
149
+ import { voltage } from "circuit-json";
150
+ var setSupportedCapability = (sourcePortProps, capability) => {
151
+ switch (capability) {
152
+ case "i2c_sda":
153
+ sourcePortProps.supports_i2c_sda = true;
154
+ return;
155
+ case "i2c_scl":
156
+ sourcePortProps.supports_i2c_scl = true;
157
+ return;
158
+ case "spi_cs":
159
+ sourcePortProps.supports_spi_cs = true;
160
+ return;
161
+ case "spi_sck":
162
+ sourcePortProps.supports_spi_sck = true;
163
+ return;
164
+ case "spi_mosi":
165
+ sourcePortProps.supports_spi_mosi = true;
166
+ return;
167
+ case "spi_miso":
168
+ sourcePortProps.supports_spi_miso = true;
169
+ return;
170
+ case "uart_tx":
171
+ sourcePortProps.supports_uart_tx = true;
172
+ return;
173
+ case "uart_rx":
174
+ sourcePortProps.supports_uart_rx = true;
175
+ return;
176
+ default: {
177
+ const unhandledCapability = capability;
178
+ throw new Error(`Unhandled pin capability: ${unhandledCapability}`);
179
+ }
180
+ }
181
+ };
182
+ var setConfiguredCapability = (sourcePortProps, capability) => {
183
+ switch (capability) {
184
+ case "i2c_sda":
185
+ sourcePortProps.is_configured_for_i2c_sda = true;
186
+ return;
187
+ case "i2c_scl":
188
+ sourcePortProps.is_configured_for_i2c_scl = true;
189
+ return;
190
+ case "spi_cs":
191
+ sourcePortProps.is_configured_for_spi_cs = true;
192
+ return;
193
+ case "spi_sck":
194
+ sourcePortProps.is_configured_for_spi_sck = true;
195
+ return;
196
+ case "spi_mosi":
197
+ sourcePortProps.is_configured_for_spi_mosi = true;
198
+ return;
199
+ case "spi_miso":
200
+ sourcePortProps.is_configured_for_spi_miso = true;
201
+ return;
202
+ case "uart_tx":
203
+ sourcePortProps.is_configured_for_uart_tx = true;
204
+ return;
205
+ case "uart_rx":
206
+ sourcePortProps.is_configured_for_uart_rx = true;
207
+ return;
208
+ default: {
209
+ const unhandledCapability = capability;
210
+ throw new Error(
211
+ `Unhandled configured pin capability: ${unhandledCapability}`
212
+ );
213
+ }
214
+ }
215
+ };
216
+ var applyPinAttributesToSourcePort = (sourcePortProps, attributes) => {
217
+ if (attributes.isInput !== void 0) {
218
+ sourcePortProps.is_input = attributes.isInput;
219
+ }
220
+ if (attributes.isOutput !== void 0) {
221
+ sourcePortProps.is_output = attributes.isOutput;
222
+ }
223
+ if (attributes.isBidirectional !== void 0) {
224
+ sourcePortProps.is_bidirectional = attributes.isBidirectional;
225
+ }
226
+ if (attributes.isPassive !== void 0) {
227
+ sourcePortProps.is_passive = attributes.isPassive;
228
+ }
229
+ if (attributes.canUseTriState !== void 0) {
230
+ sourcePortProps.can_use_tri_state = attributes.canUseTriState;
231
+ }
232
+ if (attributes.isUsingTriState !== void 0) {
233
+ sourcePortProps.is_using_tri_state = attributes.isUsingTriState;
234
+ }
235
+ if (attributes.canUseOpenCollector !== void 0) {
236
+ sourcePortProps.can_use_open_collector = attributes.canUseOpenCollector;
237
+ }
238
+ if (attributes.isUsingOpenCollector !== void 0) {
239
+ sourcePortProps.is_using_open_collector = attributes.isUsingOpenCollector;
240
+ }
241
+ if (attributes.canUseOpenEmitter !== void 0) {
242
+ sourcePortProps.can_use_open_emitter = attributes.canUseOpenEmitter;
243
+ }
244
+ if (attributes.isUsingOpenEmitter !== void 0) {
245
+ sourcePortProps.is_using_open_emitter = attributes.isUsingOpenEmitter;
246
+ }
247
+ if (attributes.isGpio !== void 0) {
248
+ sourcePortProps.is_gpio = attributes.isGpio;
249
+ }
250
+ if (attributes.highlightColor !== void 0) {
251
+ sourcePortProps.highlight_color = attributes.highlightColor;
252
+ }
253
+ for (const capability of attributes.capabilities ?? []) {
254
+ setSupportedCapability(sourcePortProps, capability);
255
+ }
256
+ const configuredCapabilities = /* @__PURE__ */ new Set([
257
+ ...attributes.activeCapabilities ?? [],
258
+ ...attributes.activeCapability ? [attributes.activeCapability] : []
259
+ ]);
260
+ for (const capability of configuredCapabilities) {
261
+ setConfiguredCapability(sourcePortProps, capability);
262
+ }
263
+ if (attributes.mustBeConnected !== void 0) {
264
+ sourcePortProps.must_be_connected = attributes.mustBeConnected;
265
+ }
266
+ if (attributes.providesPower !== void 0) {
267
+ sourcePortProps.provides_power = attributes.providesPower;
268
+ }
269
+ if (attributes.requiresPower !== void 0) {
270
+ sourcePortProps.requires_power = attributes.requiresPower;
271
+ }
272
+ if (attributes.providesGround !== void 0) {
273
+ sourcePortProps.provides_ground = attributes.providesGround;
274
+ }
275
+ if (attributes.requiresGround !== void 0) {
276
+ sourcePortProps.requires_ground = attributes.requiresGround;
277
+ }
278
+ if (attributes.providesVoltage !== void 0) {
279
+ sourcePortProps.provides_voltage = voltage.parse(attributes.providesVoltage);
280
+ }
281
+ if (attributes.requiresVoltage !== void 0) {
282
+ sourcePortProps.requires_voltage = voltage.parse(attributes.requiresVoltage);
283
+ }
284
+ if (attributes.doNotConnect !== void 0) {
285
+ sourcePortProps.do_not_connect = attributes.doNotConnect;
286
+ }
287
+ if (attributes.includeInBoardPinout !== void 0) {
288
+ sourcePortProps.include_in_board_pinout = attributes.includeInBoardPinout;
289
+ }
290
+ if (attributes.canUseInternalPullup !== void 0) {
291
+ sourcePortProps.can_use_internal_pullup = attributes.canUseInternalPullup;
292
+ }
293
+ if (attributes.isUsingInternalPullup !== void 0) {
294
+ sourcePortProps.is_using_internal_pullup = attributes.isUsingInternalPullup;
295
+ }
296
+ if (attributes.needsExternalPullup !== void 0) {
297
+ sourcePortProps.needs_external_pullup = attributes.needsExternalPullup;
298
+ }
299
+ if (attributes.canUseInternalPulldown !== void 0) {
300
+ sourcePortProps.can_use_internal_pulldown = attributes.canUseInternalPulldown;
301
+ }
302
+ if (attributes.isUsingInternalPulldown !== void 0) {
303
+ sourcePortProps.is_using_internal_pulldown = attributes.isUsingInternalPulldown;
304
+ }
305
+ if (attributes.needsExternalPulldown !== void 0) {
306
+ sourcePortProps.needs_external_pulldown = attributes.needsExternalPulldown;
307
+ }
308
+ if (attributes.canUseOpenDrain !== void 0) {
309
+ sourcePortProps.can_use_open_drain = attributes.canUseOpenDrain;
310
+ }
311
+ if (attributes.isUsingOpenDrain !== void 0) {
312
+ sourcePortProps.is_using_open_drain = attributes.isUsingOpenDrain;
313
+ }
314
+ if (attributes.canUsePushPull !== void 0) {
315
+ sourcePortProps.can_use_push_pull = attributes.canUsePushPull;
316
+ }
317
+ if (attributes.isUsingPushPull !== void 0) {
318
+ sourcePortProps.is_using_push_pull = attributes.isUsingPushPull;
319
+ }
320
+ if (attributes.shouldHaveDecouplingCapacitor !== void 0) {
321
+ sourcePortProps.should_have_decoupling_capacitor = attributes.shouldHaveDecouplingCapacitor;
322
+ }
323
+ if (attributes.recommendedDecouplingCapacitorCapacitance !== void 0) {
324
+ sourcePortProps.recommended_decoupling_capacitor_capacitance = attributes.recommendedDecouplingCapacitorCapacitance;
325
+ }
326
+ };
327
+
328
+ // lib/components/primitive-components/Port/get-pin-attribute-mismatches.ts
329
+ var getPinAttributeMismatches = (declared, imported) => {
330
+ const mismatches = [];
331
+ for (const propName of Object.keys(declared)) {
332
+ if (propName === "highlightColor" || propName === "includeInBoardPinout")
333
+ continue;
334
+ const normalized = {};
335
+ applyPinAttributesToSourcePort(normalized, {
336
+ [propName]: declared[propName]
337
+ });
338
+ if (propName === "capabilities") {
339
+ for (const attributeName of Object.keys(
340
+ imported
341
+ )) {
342
+ if (attributeName.startsWith("supports_"))
343
+ Object.assign(normalized, {
344
+ [attributeName]: normalized[attributeName] ?? false
345
+ });
346
+ }
347
+ }
348
+ for (const attributeName of Object.keys(
349
+ normalized
350
+ )) {
351
+ const declaredValue = normalized[attributeName];
352
+ const supportedAttributeName = attributeName.startsWith(
353
+ "is_configured_for_"
354
+ ) ? attributeName.replace("is_configured_for_", "supports_") : attributeName.startsWith("is_using_") ? attributeName.replace("is_using_", "can_use_") : void 0;
355
+ if (supportedAttributeName) {
356
+ if (declaredValue === true && imported[supportedAttributeName] === false)
357
+ mismatches.push(
358
+ `${propName}: ${JSON.stringify(declared[propName])}, fetched ${supportedAttributeName}: false`
359
+ );
360
+ continue;
361
+ }
362
+ const importedValue = imported[attributeName];
363
+ const valuesMatch = typeof importedValue === "number" && typeof declaredValue === "number" ? Math.abs(importedValue - declaredValue) <= Number.EPSILON * 8 * Math.max(1, Math.abs(importedValue), Math.abs(declaredValue)) : importedValue === declaredValue;
364
+ if (importedValue !== void 0 && declaredValue !== void 0 && !valuesMatch)
365
+ mismatches.push(
366
+ `${propName}: ${JSON.stringify(declared[propName])}, fetched ${attributeName}: ${JSON.stringify(importedValue)}`
367
+ );
368
+ }
369
+ }
370
+ return mismatches;
371
+ };
372
+
373
+ // lib/components/primitive-components/Port/resolve-port-source-pin-attributes.ts
374
+ import {
375
+ source_pin_attributes
376
+ } from "circuit-json";
377
+ var getImportedSourcePinAttributes = (port, importedSourcePorts) => {
378
+ if (new Set(
379
+ importedSourcePorts.map((sourcePort) => sourcePort.source_component_id)
380
+ ).size > 1)
381
+ return {};
382
+ const pinNumber = port.props.pinNumber;
383
+ const physicalMatches = pinNumber === void 0 ? [] : importedSourcePorts.filter(
384
+ (sourcePort) => sourcePort.pin_number === pinNumber
385
+ );
386
+ const aliases = port.getNameAndAliases();
387
+ const matches = physicalMatches.length > 0 ? physicalMatches : importedSourcePorts.filter(
388
+ (sourcePort) => [sourcePort.name, ...sourcePort.port_hints ?? []].some(
389
+ (alias) => aliases.includes(alias)
390
+ )
391
+ );
392
+ if (matches.length !== 1) return {};
393
+ const attributes = source_pin_attributes.parse(matches[0]);
394
+ for (const attributeName of Object.keys(
395
+ attributes
396
+ )) {
397
+ if (attributes[attributeName] === void 0)
398
+ delete attributes[attributeName];
399
+ }
400
+ return attributes;
401
+ };
402
+ var resolvePortSourcePinAttributes = (port) => {
403
+ const attributes = getImportedSourcePinAttributes(
404
+ port,
405
+ port.getParentNormalComponent()?._importedSourcePorts ?? []
406
+ );
407
+ for (const pinAttributes of port._getMatchingPinAttributes()) {
408
+ for (const attributeName of Object.keys(
409
+ attributes
410
+ )) {
411
+ if (pinAttributes.capabilities !== void 0 && attributeName.startsWith("supports_") || (pinAttributes.activeCapability !== void 0 || pinAttributes.activeCapabilities !== void 0) && attributeName.startsWith("is_configured_for_"))
412
+ delete attributes[attributeName];
413
+ }
414
+ applyPinAttributesToSourcePort(attributes, pinAttributes);
415
+ }
416
+ return attributes;
417
+ };
418
+
419
+ // lib/utils/get-datasheet-internal-connection-warnings.ts
420
+ var getDatasheetInternalConnectionWarnings = (component) => {
421
+ const reported = component._fetchedInternallyConnectedPinNames ?? component._importedInternallyConnectedPinNames ?? [];
422
+ const ports = component._getAllPortsFromChildren();
423
+ const resolvePort = (identifier) => {
424
+ const name = String(identifier);
425
+ const physical = ports.find(
426
+ (port) => port.physicalPinName === name || port.props.pinNumber !== void 0 && (String(port.props.pinNumber) === name || `pin${port.props.pinNumber}` === name)
427
+ );
428
+ if (physical) return physical;
429
+ const matches = ports.filter((port) => {
430
+ const aliases = port.getNameAndAliases();
431
+ return aliases.includes(name) || name.startsWith("pin") && aliases.includes(name.slice(3));
432
+ });
433
+ return matches.length === 1 ? matches[0] : void 0;
434
+ };
435
+ const declared = component._parsedProps.internallyConnectedPins;
436
+ const declaredGroups = (declared ?? []).map(
437
+ (group) => group.map(resolvePort).filter((port) => port !== void 0)
438
+ );
439
+ return reported.flatMap((group) => {
440
+ const resolved = group.map(resolvePort);
441
+ if (resolved.some((port) => !port)) return [];
442
+ const reportedPorts = [...new Set(resolved)];
443
+ if (reportedPorts.length < 2) return [];
444
+ const connected = /* @__PURE__ */ new Set([reportedPorts[0]]);
445
+ let changed = true;
446
+ while (changed) {
447
+ changed = false;
448
+ for (const group2 of declaredGroups) {
449
+ if (!group2.some((port) => connected.has(port))) continue;
450
+ for (const port of group2) {
451
+ if (!connected.has(port)) {
452
+ connected.add(port);
453
+ changed = true;
454
+ }
455
+ }
456
+ }
457
+ }
458
+ if (reportedPorts.every((port) => connected.has(port))) return [];
459
+ const pinNames = reportedPorts.map((port) => {
460
+ const aliases = port.getNameAndAliases();
461
+ return aliases.find((name) => !/^(?:pin)?\d+$/.test(name)) ?? aliases[0] ?? "unnamed pin";
462
+ });
463
+ const names = pinNames.length === 2 ? pinNames.join(" and ") : `${pinNames.slice(0, -1).join(", ")} and ${pinNames.at(-1)}`;
464
+ return [
465
+ {
466
+ message: `The datasheet reports pins ${names} are internally connected, but ${declared === void 0 ? `the internallyConnectedPins prop isn't set on ${component.getDisplayName()}` : `internallyConnectedPins on ${component.getDisplayName()} does not declare that connection`}.`,
467
+ sourcePortIds: reportedPorts.flatMap(
468
+ (port) => port.source_port_id ? [port.source_port_id] : []
469
+ )
470
+ }
471
+ ];
472
+ });
473
+ };
474
+
475
+ // lib/components/base-components/NormalComponent/NormalComponent_fetchDatasheetForValidation.ts
476
+ import {
477
+ resolveManufacturerPartNumber,
478
+ supplierProps
479
+ } from "@tscircuit/props";
480
+ import { source_pin_attributes as source_pin_attributes2 } from "circuit-json";
481
+
482
+ // lib/utils/fetch-part-circuit-json-with-datasheet.ts
483
+ import { ZodError } from "zod";
484
+ var chipDatasheetPartFetches = /* @__PURE__ */ new WeakMap();
485
+ var fetchDatasheetPart = async (fetchPartCircuitJson, request) => {
486
+ const { supplierPartNumber, manufacturerPartNumber, platformFetch } = request;
487
+ const legacyRequest = {
488
+ supplierPartNumber,
489
+ manufacturerPartNumber,
490
+ platformFetch
491
+ };
492
+ try {
493
+ return { circuitJson: await fetchPartCircuitJson(request) };
494
+ } catch (error) {
495
+ if (!request.includeDatasheetInformation && !(error instanceof ZodError && error.issues.some(
496
+ (issue) => issue.code === "unrecognized_keys" && issue.keys.includes("includeDatasheetInformation")
497
+ )))
498
+ throw error;
499
+ const fallbackRequest = {
500
+ ...request,
501
+ includeDatasheetInformation: false
502
+ };
503
+ let circuitJson;
504
+ let usedLegacyRequest = false;
505
+ try {
506
+ usedLegacyRequest = !request.includeDatasheetInformation;
507
+ circuitJson = await fetchPartCircuitJson(
508
+ usedLegacyRequest ? legacyRequest : fallbackRequest
509
+ );
510
+ } catch {
511
+ if (usedLegacyRequest) throw error;
512
+ circuitJson = await fetchPartCircuitJson(legacyRequest);
513
+ usedLegacyRequest = true;
514
+ }
515
+ if (!circuitJson?.length) throw error;
516
+ const manufacturerPartNumbers = circuitJson.flatMap(
517
+ (element) => element.type === "source_component" && element.manufacturer_part_number ? [element.manufacturer_part_number] : []
518
+ );
519
+ if (manufacturerPartNumber && manufacturerPartNumbers.some(
520
+ (importedManufacturerPartNumber) => importedManufacturerPartNumber.trim().toLowerCase() !== manufacturerPartNumber.trim().toLowerCase()
521
+ ))
522
+ throw error;
523
+ const reason = usedLegacyRequest ? "the parts engine only accepted a request without the datasheet option" : error instanceof Error ? error.message : String(error);
524
+ return { circuitJson, datasheetFailureReason: reason };
525
+ }
526
+ };
527
+ var fetchPartCircuitJsonWithoutDatasheet = async (fetchPartCircuitJson, request) => {
528
+ const { circuitJson } = await fetchDatasheetPart(fetchPartCircuitJson, {
529
+ ...request,
530
+ includeDatasheetInformation: false
531
+ });
532
+ return circuitJson;
533
+ };
534
+ var fetchPartCircuitJsonWithDatasheet = async ({
535
+ fetchPartCircuitJson,
536
+ supplierPartNumber,
537
+ manufacturerPartNumber
538
+ }, sourcePortOwner) => {
539
+ const includeDatasheetInformation = sourcePortOwner.config.componentName === "Chip" || sourcePortOwner.config.componentName === "OpAmp" || sourcePortOwner.config.componentName === "PushButton";
540
+ const request = {
541
+ supplierPartNumber,
542
+ manufacturerPartNumber,
543
+ platformFetch: sourcePortOwner.root?.platform?.platformFetch,
544
+ includeDatasheetInformation
545
+ };
546
+ let partFetch;
547
+ const circuit = sourcePortOwner.root;
548
+ if (sourcePortOwner.config.componentName === "Chip" && circuit) {
549
+ let partFetchesByEngine = chipDatasheetPartFetches.get(circuit);
550
+ if (!partFetchesByEngine) {
551
+ partFetchesByEngine = /* @__PURE__ */ new WeakMap();
552
+ chipDatasheetPartFetches.set(circuit, partFetchesByEngine);
553
+ }
554
+ let partFetches = partFetchesByEngine.get(fetchPartCircuitJson);
555
+ if (!partFetches) {
556
+ partFetches = /* @__PURE__ */ new Map();
557
+ partFetchesByEngine.set(fetchPartCircuitJson, partFetches);
558
+ }
559
+ const partCacheKey = `datasheet_part:${JSON.stringify(
560
+ [supplierPartNumber, manufacturerPartNumber]
561
+ )}`;
562
+ partFetch = partFetches.get(partCacheKey) ?? fetchDatasheetPart(fetchPartCircuitJson, request);
563
+ partFetches.set(partCacheKey, partFetch);
564
+ } else {
565
+ partFetch = fetchDatasheetPart(fetchPartCircuitJson, request);
566
+ }
567
+ const { circuitJson, datasheetFailureReason } = await partFetch;
568
+ if (includeDatasheetInformation && datasheetFailureReason !== void 0) {
569
+ const message = `Datasheet information for ${sourcePortOwner.getDisplayName()} could not be fetched: ${datasheetFailureReason}. Pin attributes may not be populated.`;
570
+ if (sourcePortOwner.source_component_id && sourcePortOwner.root) {
571
+ sourcePortOwner.root.db.source_property_ignored_warning.insert({
572
+ source_component_id: sourcePortOwner.source_component_id,
573
+ property_name: "pinAttributes",
574
+ message,
575
+ error_type: "source_property_ignored_warning"
576
+ });
577
+ } else {
578
+ console.warn(message);
579
+ }
580
+ }
581
+ return circuitJson;
582
+ };
583
+
584
+ // lib/utils/get-imported-internally-connected-pin-names.ts
585
+ var getImportedInternallyConnectedPinNames = (circuitJson) => {
586
+ const ports = circuitJson.filter((element) => element.type === "source_port");
587
+ const components = circuitJson.filter((element) => element.type === "source_component").filter(
588
+ (component) => component.internally_connected_source_port_ids !== void 0
589
+ );
590
+ if (!components.length) return void 0;
591
+ return components.flatMap(
592
+ (component) => (component.internally_connected_source_port_ids ?? []).flatMap((group) => {
593
+ const resolved = group.map(
594
+ (id) => ports.find(
595
+ (port) => port.source_port_id === id && port.source_component_id === component.source_component_id
596
+ )
597
+ );
598
+ if (resolved.some((port) => !port)) return [];
599
+ return [
600
+ resolved.map(
601
+ (port) => port.pin_number !== void 0 ? `pin${port.pin_number}` : port.name
602
+ )
603
+ ];
604
+ })
605
+ );
606
+ };
607
+
608
+ // lib/components/base-components/NormalComponent/NormalComponent_fetchDatasheetForValidation.ts
609
+ var NormalComponent_fetchDatasheetForValidation = (component) => {
610
+ if (!["Chip", "PushButton", "OpAmp"].includes(component.config.componentName))
611
+ return;
612
+ if (component._hasStartedPinAttributesFetch) return;
613
+ if (component.getInheritedProperty("partsEngineDisabled")) return;
614
+ if (component.getInheritedProperty("bomDisabled")) return;
615
+ if (component._importedInternallyConnectedPinNames !== void 0) return;
616
+ if (component._importedSourcePorts.some(
617
+ (port) => Object.values(source_pin_attributes2.parse(port)).some(
618
+ (value) => value !== void 0
619
+ )
620
+ ))
621
+ return;
622
+ const partsEngine = component.getInheritedProperty("partsEngine");
623
+ if (!partsEngine?.fetchPartCircuitJson) return;
624
+ const footprint = component.resolveFootprint();
625
+ const supplierPartNumbers = component._parsedProps.supplierPartNumbers;
626
+ if (supplierProps.shape.supplierPartNumbers.unwrap().keySchema.options.some(
627
+ (supplierName) => typeof component.root?.platform?.footprintLibraryMap?.[supplierName] !== "function" && supplierPartNumbers?.[supplierName]?.some(
628
+ (partNumber) => footprint === `${supplierName}:${partNumber}`
629
+ )
630
+ ))
631
+ return;
632
+ const supplierPartNumber = Object.values(supplierPartNumbers ?? {}).flat()[0];
633
+ const manufacturerPartNumber = resolveManufacturerPartNumber(
634
+ component._parsedProps
635
+ );
636
+ if (!supplierPartNumber && !manufacturerPartNumber) return;
637
+ component._hasStartedPinAttributesFetch = true;
638
+ component._queueAsyncEffect(
639
+ "fetch-datasheet-validation-metadata",
640
+ async () => {
641
+ try {
642
+ const partCircuitJson = await fetchPartCircuitJsonWithDatasheet(
643
+ {
644
+ fetchPartCircuitJson: partsEngine.fetchPartCircuitJson,
645
+ supplierPartNumber,
646
+ manufacturerPartNumber
647
+ },
648
+ component
649
+ );
650
+ component._fetchedSourcePortsForPinAttributes = partCircuitJson?.filter(
651
+ (element) => element.type === "source_port"
652
+ ) ?? [];
653
+ component._fetchedInternallyConnectedPinNames = getImportedInternallyConnectedPinNames(partCircuitJson ?? []);
654
+ component._markDirty("SourceDesignRuleChecks");
655
+ } catch {
656
+ }
657
+ }
658
+ );
659
+ };
660
+
661
+ // lib/components/base-components/NormalComponent/NormalComponent_doInitialSourcePinSpecificationChecks.ts
662
+ var NormalComponent_doInitialSourcePinSpecificationChecks = (component) => {
663
+ if (!["Chip", "PushButton", "OpAmp"].includes(component.config.componentName))
664
+ return;
665
+ const isChip = component.config.componentName === "Chip";
666
+ if (!component.source_component_id) return;
667
+ const { db: db2 } = component.root;
668
+ const existingWarning = db2.source_component_pins_underspecified_warning.getWhere({
669
+ source_component_id: component.source_component_id
670
+ });
671
+ const drcChecksDisabled = component.root?.platform?.drcChecksDisabled ?? component.getInheritedProperty("drcChecksDisabled");
672
+ const pinSpecificationDrcChecksDisabled = component.root?.platform?.pinSpecificationDrcChecksDisabled ?? component.getInheritedProperty("pinSpecificationDrcChecksDisabled");
673
+ const checksDisabled = drcChecksDisabled || pinSpecificationDrcChecksDisabled;
674
+ if (!checksDisabled) NormalComponent_fetchDatasheetForValidation(component);
675
+ const sourcePorts = checksDisabled ? [] : component.selectAll("port").flatMap((port) => {
676
+ if (!port.source_port_id) return [];
677
+ const sourcePort = db2.source_port.get(port.source_port_id);
678
+ return sourcePort?.source_component_id === component.source_component_id ? [sourcePort] : [];
679
+ });
680
+ const sourceComponent = checksDisabled ? null : db2.source_component.get(component.source_component_id);
681
+ const chipCircuitJson = sourceComponent ? [sourceComponent, ...sourcePorts] : [];
682
+ const issues = [];
683
+ if (!checksDisabled && isChip) {
684
+ for (const port of component.selectAll("port")) {
685
+ const sourcePort = sourcePorts.find(
686
+ (sourcePort2) => sourcePort2.source_port_id === port.source_port_id
687
+ );
688
+ if (!sourcePort) continue;
689
+ const declared = {};
690
+ for (const alias of port.getNameAndAliases()) {
691
+ Object.assign(declared, component._parsedProps.pinAttributes?.[alias]);
692
+ }
693
+ const imported = getImportedSourcePinAttributes(
694
+ port,
695
+ component._fetchedSourcePortsForPinAttributes.length ? component._fetchedSourcePortsForPinAttributes : component._importedSourcePorts
696
+ );
697
+ const reasons2 = getPinAttributeMismatches(declared, imported);
698
+ if (reasons2.length)
699
+ issues.push({
700
+ pinName: sourcePort.name || "unnamed pin",
701
+ reasons: reasons2,
702
+ sourcePort
703
+ });
704
+ }
705
+ }
706
+ for (const [warningTable, check] of [
707
+ [db2.source_no_power_pin_defined_warning, checkNoPowerPinDefined],
708
+ [db2.source_no_ground_pin_defined_warning, checkNoGroundPinDefined]
709
+ ]) {
710
+ const existing = warningTable.getWhere({
711
+ source_component_id: component.source_component_id
712
+ });
713
+ const existingId = existing?.type === "source_no_power_pin_defined_warning" ? existing.source_no_power_pin_defined_warning_id : existing?.source_no_ground_pin_defined_warning_id;
714
+ const [warning2] = checksDisabled || !isChip || issues.length ? [] : check(chipCircuitJson);
715
+ if (warning2) {
716
+ if (existingId) {
717
+ warningTable.update(existingId, {
718
+ message: warning2.message,
719
+ source_port_ids: warning2.source_port_ids,
720
+ subcircuit_id: warning2.subcircuit_id
721
+ });
722
+ } else {
723
+ db2.insertAll([warning2]);
724
+ }
725
+ } else if (existingId) {
726
+ warningTable.delete(existingId);
727
+ }
728
+ }
729
+ const [underspecifiedWarning] = checksDisabled || !isChip ? [] : checkAllPinsInComponentAreUnderspecified(chipCircuitJson);
730
+ const internalWarnings = checksDisabled ? [] : getDatasheetInternalConnectionWarnings(component);
731
+ if (!issues.length && !underspecifiedWarning && !internalWarnings.length) {
732
+ if (existingWarning) {
733
+ db2.source_component_pins_underspecified_warning.delete(
734
+ existingWarning.source_component_pins_underspecified_warning_id
735
+ );
736
+ }
737
+ return;
738
+ }
739
+ const examples = issues.slice(0, 3).map(({ pinName, reasons: reasons2 }) => `${pinName} (${reasons2.join("; ")})`).join(", ");
740
+ const remaining = issues.length > 3 ? `, and ${issues.length - 3} more` : "";
741
+ const pinMessage = issues.length ? `Chip ${component.name || "unnamed chip"} has pinAttributes that conflict with fetched pin metadata on ${issues.length} pin${issues.length === 1 ? "" : "s"}: ${examples}${remaining}. Check the chip configuration against the part datasheet.` : underspecifiedWarning?.message;
742
+ const warning = {
743
+ source_component_id: component.source_component_id,
744
+ source_port_ids: [
745
+ .../* @__PURE__ */ new Set([
746
+ ...issues.length ? issues.map(({ sourcePort }) => sourcePort.source_port_id) : underspecifiedWarning?.source_port_ids ?? [],
747
+ ...internalWarnings.flatMap((warning2) => warning2.sourcePortIds)
748
+ ])
749
+ ],
750
+ subcircuit_id: component.getSubcircuit().subcircuit_id ?? void 0,
751
+ warning_type: "source_component_pins_underspecified_warning",
752
+ message: [pinMessage, ...internalWarnings.map((warning2) => warning2.message)].filter(Boolean).join(" ")
753
+ };
754
+ if (existingWarning) {
755
+ db2.source_component_pins_underspecified_warning.update(
756
+ existingWarning.source_component_pins_underspecified_warning_id,
757
+ warning
758
+ );
759
+ } else {
760
+ db2.source_component_pins_underspecified_warning.insert(warning);
761
+ }
762
+ };
763
+
141
764
  // lib/utils/schematic/getPinNumberFromPinLabelsKey.ts
142
765
  var PIN_LABELS_KEY_RE = /^(?:pin)?(\d+)$/;
143
766
  var getPinNumberFromPinLabelsKey = (pinKey) => {
@@ -201,7 +824,7 @@ function getNumericPinLabels(pinLabels) {
201
824
  }
202
825
 
203
826
  // lib/components/base-components/NormalComponent/NormalComponent.ts
204
- import { resolveManufacturerPartNumber as resolveManufacturerPartNumber2 } from "@tscircuit/props";
827
+ import { resolveManufacturerPartNumber as resolveManufacturerPartNumber3 } from "@tscircuit/props";
205
828
 
206
829
  // lib/utils/cad/compose-cad-model-rotation.ts
207
830
  import { normalizeDegrees } from "@tscircuit/math-utils";
@@ -4614,234 +5237,6 @@ var getCenterOfPcbPrimitives = (pcbPrimitives) => {
4614
5237
  // lib/components/primitive-components/Port/Port.ts
4615
5238
  import { portProps } from "@tscircuit/props";
4616
5239
 
4617
- // lib/components/primitive-components/Port/resolve-port-source-pin-attributes.ts
4618
- import {
4619
- source_pin_attributes
4620
- } from "circuit-json";
4621
-
4622
- // lib/components/primitive-components/Port/apply-pin-attributes-to-source-port.ts
4623
- import { voltage } from "circuit-json";
4624
- var setSupportedCapability = (sourcePortProps, capability) => {
4625
- switch (capability) {
4626
- case "i2c_sda":
4627
- sourcePortProps.supports_i2c_sda = true;
4628
- return;
4629
- case "i2c_scl":
4630
- sourcePortProps.supports_i2c_scl = true;
4631
- return;
4632
- case "spi_cs":
4633
- sourcePortProps.supports_spi_cs = true;
4634
- return;
4635
- case "spi_sck":
4636
- sourcePortProps.supports_spi_sck = true;
4637
- return;
4638
- case "spi_mosi":
4639
- sourcePortProps.supports_spi_mosi = true;
4640
- return;
4641
- case "spi_miso":
4642
- sourcePortProps.supports_spi_miso = true;
4643
- return;
4644
- case "uart_tx":
4645
- sourcePortProps.supports_uart_tx = true;
4646
- return;
4647
- case "uart_rx":
4648
- sourcePortProps.supports_uart_rx = true;
4649
- return;
4650
- default: {
4651
- const unhandledCapability = capability;
4652
- throw new Error(`Unhandled pin capability: ${unhandledCapability}`);
4653
- }
4654
- }
4655
- };
4656
- var setConfiguredCapability = (sourcePortProps, capability) => {
4657
- switch (capability) {
4658
- case "i2c_sda":
4659
- sourcePortProps.is_configured_for_i2c_sda = true;
4660
- return;
4661
- case "i2c_scl":
4662
- sourcePortProps.is_configured_for_i2c_scl = true;
4663
- return;
4664
- case "spi_cs":
4665
- sourcePortProps.is_configured_for_spi_cs = true;
4666
- return;
4667
- case "spi_sck":
4668
- sourcePortProps.is_configured_for_spi_sck = true;
4669
- return;
4670
- case "spi_mosi":
4671
- sourcePortProps.is_configured_for_spi_mosi = true;
4672
- return;
4673
- case "spi_miso":
4674
- sourcePortProps.is_configured_for_spi_miso = true;
4675
- return;
4676
- case "uart_tx":
4677
- sourcePortProps.is_configured_for_uart_tx = true;
4678
- return;
4679
- case "uart_rx":
4680
- sourcePortProps.is_configured_for_uart_rx = true;
4681
- return;
4682
- default: {
4683
- const unhandledCapability = capability;
4684
- throw new Error(
4685
- `Unhandled configured pin capability: ${unhandledCapability}`
4686
- );
4687
- }
4688
- }
4689
- };
4690
- var applyPinAttributesToSourcePort = (sourcePortProps, attributes) => {
4691
- if (attributes.isInput !== void 0) {
4692
- sourcePortProps.is_input = attributes.isInput;
4693
- }
4694
- if (attributes.isOutput !== void 0) {
4695
- sourcePortProps.is_output = attributes.isOutput;
4696
- }
4697
- if (attributes.isBidirectional !== void 0) {
4698
- sourcePortProps.is_bidirectional = attributes.isBidirectional;
4699
- }
4700
- if (attributes.isPassive !== void 0) {
4701
- sourcePortProps.is_passive = attributes.isPassive;
4702
- }
4703
- if (attributes.canUseTriState !== void 0) {
4704
- sourcePortProps.can_use_tri_state = attributes.canUseTriState;
4705
- }
4706
- if (attributes.isUsingTriState !== void 0) {
4707
- sourcePortProps.is_using_tri_state = attributes.isUsingTriState;
4708
- }
4709
- if (attributes.canUseOpenCollector !== void 0) {
4710
- sourcePortProps.can_use_open_collector = attributes.canUseOpenCollector;
4711
- }
4712
- if (attributes.isUsingOpenCollector !== void 0) {
4713
- sourcePortProps.is_using_open_collector = attributes.isUsingOpenCollector;
4714
- }
4715
- if (attributes.canUseOpenEmitter !== void 0) {
4716
- sourcePortProps.can_use_open_emitter = attributes.canUseOpenEmitter;
4717
- }
4718
- if (attributes.isUsingOpenEmitter !== void 0) {
4719
- sourcePortProps.is_using_open_emitter = attributes.isUsingOpenEmitter;
4720
- }
4721
- if (attributes.isGpio !== void 0) {
4722
- sourcePortProps.is_gpio = attributes.isGpio;
4723
- }
4724
- if (attributes.highlightColor !== void 0) {
4725
- sourcePortProps.highlight_color = attributes.highlightColor;
4726
- }
4727
- for (const capability of attributes.capabilities ?? []) {
4728
- setSupportedCapability(sourcePortProps, capability);
4729
- }
4730
- const configuredCapabilities = /* @__PURE__ */ new Set([
4731
- ...attributes.activeCapabilities ?? [],
4732
- ...attributes.activeCapability ? [attributes.activeCapability] : []
4733
- ]);
4734
- for (const capability of configuredCapabilities) {
4735
- setConfiguredCapability(sourcePortProps, capability);
4736
- }
4737
- if (attributes.mustBeConnected !== void 0) {
4738
- sourcePortProps.must_be_connected = attributes.mustBeConnected;
4739
- }
4740
- if (attributes.providesPower !== void 0) {
4741
- sourcePortProps.provides_power = attributes.providesPower;
4742
- }
4743
- if (attributes.requiresPower !== void 0) {
4744
- sourcePortProps.requires_power = attributes.requiresPower;
4745
- }
4746
- if (attributes.providesGround !== void 0) {
4747
- sourcePortProps.provides_ground = attributes.providesGround;
4748
- }
4749
- if (attributes.requiresGround !== void 0) {
4750
- sourcePortProps.requires_ground = attributes.requiresGround;
4751
- }
4752
- if (attributes.providesVoltage !== void 0) {
4753
- sourcePortProps.provides_voltage = voltage.parse(attributes.providesVoltage);
4754
- }
4755
- if (attributes.requiresVoltage !== void 0) {
4756
- sourcePortProps.requires_voltage = voltage.parse(attributes.requiresVoltage);
4757
- }
4758
- if (attributes.doNotConnect !== void 0) {
4759
- sourcePortProps.do_not_connect = attributes.doNotConnect;
4760
- }
4761
- if (attributes.includeInBoardPinout !== void 0) {
4762
- sourcePortProps.include_in_board_pinout = attributes.includeInBoardPinout;
4763
- }
4764
- if (attributes.canUseInternalPullup !== void 0) {
4765
- sourcePortProps.can_use_internal_pullup = attributes.canUseInternalPullup;
4766
- }
4767
- if (attributes.isUsingInternalPullup !== void 0) {
4768
- sourcePortProps.is_using_internal_pullup = attributes.isUsingInternalPullup;
4769
- }
4770
- if (attributes.needsExternalPullup !== void 0) {
4771
- sourcePortProps.needs_external_pullup = attributes.needsExternalPullup;
4772
- }
4773
- if (attributes.canUseInternalPulldown !== void 0) {
4774
- sourcePortProps.can_use_internal_pulldown = attributes.canUseInternalPulldown;
4775
- }
4776
- if (attributes.isUsingInternalPulldown !== void 0) {
4777
- sourcePortProps.is_using_internal_pulldown = attributes.isUsingInternalPulldown;
4778
- }
4779
- if (attributes.needsExternalPulldown !== void 0) {
4780
- sourcePortProps.needs_external_pulldown = attributes.needsExternalPulldown;
4781
- }
4782
- if (attributes.canUseOpenDrain !== void 0) {
4783
- sourcePortProps.can_use_open_drain = attributes.canUseOpenDrain;
4784
- }
4785
- if (attributes.isUsingOpenDrain !== void 0) {
4786
- sourcePortProps.is_using_open_drain = attributes.isUsingOpenDrain;
4787
- }
4788
- if (attributes.canUsePushPull !== void 0) {
4789
- sourcePortProps.can_use_push_pull = attributes.canUsePushPull;
4790
- }
4791
- if (attributes.isUsingPushPull !== void 0) {
4792
- sourcePortProps.is_using_push_pull = attributes.isUsingPushPull;
4793
- }
4794
- if (attributes.shouldHaveDecouplingCapacitor !== void 0) {
4795
- sourcePortProps.should_have_decoupling_capacitor = attributes.shouldHaveDecouplingCapacitor;
4796
- }
4797
- if (attributes.recommendedDecouplingCapacitorCapacitance !== void 0) {
4798
- sourcePortProps.recommended_decoupling_capacitor_capacitance = attributes.recommendedDecouplingCapacitorCapacitance;
4799
- }
4800
- };
4801
-
4802
- // lib/components/primitive-components/Port/resolve-port-source-pin-attributes.ts
4803
- var getImportedSourcePinAttributes = (port, importedSourcePorts) => {
4804
- if (new Set(
4805
- importedSourcePorts.map((sourcePort) => sourcePort.source_component_id)
4806
- ).size > 1)
4807
- return {};
4808
- const pinNumber = port.props.pinNumber;
4809
- const physicalMatches = pinNumber === void 0 ? [] : importedSourcePorts.filter(
4810
- (sourcePort) => sourcePort.pin_number === pinNumber
4811
- );
4812
- const aliases = port.getNameAndAliases();
4813
- const matches = physicalMatches.length > 0 ? physicalMatches : importedSourcePorts.filter(
4814
- (sourcePort) => [sourcePort.name, ...sourcePort.port_hints ?? []].some(
4815
- (alias) => aliases.includes(alias)
4816
- )
4817
- );
4818
- if (matches.length !== 1) return {};
4819
- const attributes = source_pin_attributes.parse(matches[0]);
4820
- for (const attributeName of Object.keys(
4821
- attributes
4822
- )) {
4823
- if (attributes[attributeName] === void 0)
4824
- delete attributes[attributeName];
4825
- }
4826
- return attributes;
4827
- };
4828
- var resolvePortSourcePinAttributes = (port) => {
4829
- const attributes = getImportedSourcePinAttributes(
4830
- port,
4831
- port.getParentNormalComponent()?._importedSourcePorts ?? []
4832
- );
4833
- for (const pinAttributes of port._getMatchingPinAttributes()) {
4834
- for (const attributeName of Object.keys(
4835
- attributes
4836
- )) {
4837
- if (pinAttributes.capabilities !== void 0 && attributeName.startsWith("supports_") || (pinAttributes.activeCapability !== void 0 || pinAttributes.activeCapabilities !== void 0) && attributeName.startsWith("is_configured_for_"))
4838
- delete attributes[attributeName];
4839
- }
4840
- applyPinAttributesToSourcePort(attributes, pinAttributes);
4841
- }
4842
- return attributes;
4843
- };
4844
-
4845
5240
  // lib/components/primitive-components/Port/Port_doInitialCreateTracesFromProps.ts
4846
5241
  var getConnectionTargets = (target) => {
4847
5242
  if (!target) return [];
@@ -4888,10 +5283,25 @@ function netIsGround(net) {
4888
5283
  return net._parsedProps.isGroundNet ?? GROUND_NET_REGEX.test(net._parsedProps.name);
4889
5284
  }
4890
5285
  function Port_isConnectedToGround(port) {
4891
- for (const connectedTrace of port._getDirectlyConnectedTraces()) {
5286
+ const internallyConnectedPorts = /* @__PURE__ */ new Set([
5287
+ port,
5288
+ ...port._getPortsInternallyConnectedToThisPort()
5289
+ ]);
5290
+ const traces = new Set(
5291
+ [...internallyConnectedPorts].flatMap(
5292
+ (connectedPort) => connectedPort._getDirectlyConnectedTraces()
5293
+ )
5294
+ );
5295
+ for (const connectedTrace of traces) {
4892
5296
  const connectedPorts = connectedTrace._findConnectedPorts().ports ?? [];
4893
- for (const connectedPort of connectedPorts) {
4894
- if (connectedPort === port) continue;
5297
+ const connectedPortGroup = new Set(
5298
+ connectedPorts.flatMap((connectedPort) => [
5299
+ connectedPort,
5300
+ ...connectedPort._getPortsInternallyConnectedToThisPort()
5301
+ ])
5302
+ );
5303
+ for (const connectedPort of connectedPortGroup) {
5304
+ if (internallyConnectedPorts.has(connectedPort)) continue;
4895
5305
  if (portIsGround(connectedPort)) return true;
4896
5306
  }
4897
5307
  for (const connectedNet of connectedTrace._findConnectedNets().nets) {
@@ -4912,16 +5322,35 @@ function portShouldHaveDecouplingCapacitor(port) {
4912
5322
  }
4913
5323
  if (attributes.requires_power !== void 0) return attributes.requires_power;
4914
5324
  if (attributes.provides_power === true) return false;
4915
- for (const portName of port.getNameAndAliases()) {
5325
+ const aliases = port.getNameAndAliases();
5326
+ if (attributes.requires_ground === true || attributes.provides_ground === true || aliases.some((alias) => GROUND_NET_REGEX.test(alias)))
5327
+ return false;
5328
+ for (const portName of aliases) {
5329
+ if (portName === port.physicalPinName) continue;
4916
5330
  if (POWER_NET_REGEX.test(portName)) return true;
4917
5331
  }
4918
5332
  return false;
4919
5333
  }
4920
5334
  function Port_isConnectedToPower(port) {
4921
- for (const connectedTrace of port._getDirectlyConnectedTraces()) {
5335
+ const internallyConnectedPorts = /* @__PURE__ */ new Set([
5336
+ port,
5337
+ ...port._getPortsInternallyConnectedToThisPort()
5338
+ ]);
5339
+ const traces = new Set(
5340
+ [...internallyConnectedPorts].flatMap(
5341
+ (connectedPort) => connectedPort._getDirectlyConnectedTraces()
5342
+ )
5343
+ );
5344
+ for (const connectedTrace of traces) {
4922
5345
  const connectedPorts = connectedTrace._findConnectedPorts().ports ?? [];
4923
- for (const connectedPort of connectedPorts) {
4924
- if (connectedPort === port) continue;
5346
+ const connectedPortGroup = new Set(
5347
+ connectedPorts.flatMap((connectedPort) => [
5348
+ connectedPort,
5349
+ ...connectedPort._getPortsInternallyConnectedToThisPort()
5350
+ ])
5351
+ );
5352
+ for (const connectedPort of connectedPortGroup) {
5353
+ if (internallyConnectedPorts.has(connectedPort)) continue;
4925
5354
  if (portShouldHaveDecouplingCapacitor(connectedPort)) return true;
4926
5355
  }
4927
5356
  }
@@ -5138,12 +5567,21 @@ var Port = class extends PrimitiveComponent2 {
5138
5567
  const parent = this.parent;
5139
5568
  if (!parent || !parent._getInternallyConnectedPins) return [];
5140
5569
  const internallyConnectedPorts = parent._getInternallyConnectedPins();
5141
- for (const ports of internallyConnectedPorts) {
5142
- if (ports.some((port) => port === this)) {
5143
- return ports;
5570
+ const connected = /* @__PURE__ */ new Set([this]);
5571
+ let changed = true;
5572
+ while (changed) {
5573
+ changed = false;
5574
+ for (const ports of internallyConnectedPorts) {
5575
+ if (!ports.some((port) => connected.has(port))) continue;
5576
+ for (const port of ports) {
5577
+ if (!connected.has(port)) {
5578
+ connected.add(port);
5579
+ changed = true;
5580
+ }
5581
+ }
5144
5582
  }
5145
5583
  }
5146
- return [];
5584
+ return connected.size > 1 ? [...connected] : [];
5147
5585
  }
5148
5586
  /**
5149
5587
  * Return true if this port has a schematic representation and can be rendered
@@ -7063,10 +7501,10 @@ function addTraceTeardrops(route, contacts) {
7063
7501
  result.push(start);
7064
7502
  continue;
7065
7503
  }
7066
- const atDistance = (distance27) => ({
7504
+ const atDistance = (distance28) => ({
7067
7505
  route_type: "wire",
7068
- x: start.x + (end.x - start.x) * distance27 / length8,
7069
- y: start.y + (end.y - start.y) * distance27 / length8,
7506
+ x: start.x + (end.x - start.x) * distance28 / length8,
7507
+ y: start.y + (end.y - start.y) * distance28 / length8,
7070
7508
  width: start.width,
7071
7509
  layer: start.layer
7072
7510
  });
@@ -7772,11 +8210,11 @@ function Trace_doInitialPcbTraceRender(trace) {
7772
8210
  const closestNetBPort = getClosest(netAPort, netBPorts);
7773
8211
  const netAPortPosition = netAPort._getGlobalPcbPositionBeforeLayout();
7774
8212
  const netBPortPosition = closestNetBPort._getGlobalPcbPositionBeforeLayout();
7775
- const distance27 = Math.sqrt(
8213
+ const distance28 = Math.sqrt(
7776
8214
  (netAPortPosition.x - netBPortPosition.x) ** 2 + (netAPortPosition.y - netBPortPosition.y) ** 2
7777
8215
  );
7778
- if (distance27 < closestDistance) {
7779
- closestDistance = distance27;
8216
+ if (distance28 < closestDistance) {
8217
+ closestDistance = distance28;
7780
8218
  closestPortPair = [netAPort, closestNetBPort];
7781
8219
  }
7782
8220
  }
@@ -13780,6 +14218,12 @@ var createComponentsFromCircuitJson = ({
13780
14218
  const importedSourcePorts = circuitJson.filter(
13781
14219
  (elm) => elm.type === "source_port"
13782
14220
  );
14221
+ if (sourcePortOwner) {
14222
+ const internalGroups = getImportedInternallyConnectedPinNames(circuitJson);
14223
+ if (internalGroups !== void 0) {
14224
+ sourcePortOwner._importedInternallyConnectedPinNames = internalGroups;
14225
+ }
14226
+ }
13783
14227
  if (sourcePortOwner && importedSourcePorts.length > 0) {
13784
14228
  sourcePortOwner._importedSourcePorts = importedSourcePorts;
13785
14229
  for (const port of sourcePortOwner._getAllPortsFromChildren()) {
@@ -14534,7 +14978,7 @@ var createComponentsFromCircuitJson = ({
14534
14978
  parentSymbol = schematicSymbolsByImportedId.get(schematicSymbolId);
14535
14979
  }
14536
14980
  if (parentSymbol && schematicComponent?.is_box_with_pins === true && elm.center && elm.side_of_component) {
14537
- const distance27 = elm.distance_from_component_edge;
14981
+ const distance28 = elm.distance_from_component_edge;
14538
14982
  const facingDirection = getFacingDirectionFromSide(
14539
14983
  elm.side_of_component
14540
14984
  );
@@ -14545,8 +14989,8 @@ var createComponentsFromCircuitJson = ({
14545
14989
  stemDirection = 1;
14546
14990
  }
14547
14991
  const portCenter = {
14548
- x: elm.center.x + directionVector.x * distance27 * stemDirection,
14549
- y: elm.center.y + directionVector.y * distance27 * stemDirection
14992
+ x: elm.center.x + directionVector.x * distance28 * stemDirection,
14993
+ y: elm.center.y + directionVector.y * distance28 * stemDirection
14550
14994
  };
14551
14995
  const sourcePort = sourcePortsByImportedId.get(elm.source_port_id);
14552
14996
  const aliases = Array.from(
@@ -16545,110 +16989,6 @@ import {
16545
16989
  pcb_pin1_location,
16546
16990
  source_component_misconfigured_error
16547
16991
  } from "circuit-json";
16548
-
16549
- // lib/utils/fetch-part-circuit-json-with-datasheet.ts
16550
- import { ZodError } from "zod";
16551
- var chipDatasheetPartFetches = /* @__PURE__ */ new WeakMap();
16552
- var fetchDatasheetPart = async (fetchPartCircuitJson, request) => {
16553
- const { supplierPartNumber, manufacturerPartNumber, platformFetch } = request;
16554
- const legacyRequest = {
16555
- supplierPartNumber,
16556
- manufacturerPartNumber,
16557
- platformFetch
16558
- };
16559
- try {
16560
- return { circuitJson: await fetchPartCircuitJson(request) };
16561
- } catch (error) {
16562
- if (!request.includeDatasheetInformation && !(error instanceof ZodError && error.issues.some(
16563
- (issue) => issue.code === "unrecognized_keys" && issue.keys.includes("includeDatasheetInformation")
16564
- )))
16565
- throw error;
16566
- const fallbackRequest = {
16567
- ...request,
16568
- includeDatasheetInformation: false
16569
- };
16570
- let circuitJson;
16571
- let usedLegacyRequest = false;
16572
- try {
16573
- usedLegacyRequest = !request.includeDatasheetInformation;
16574
- circuitJson = await fetchPartCircuitJson(
16575
- usedLegacyRequest ? legacyRequest : fallbackRequest
16576
- );
16577
- } catch {
16578
- if (usedLegacyRequest) throw error;
16579
- circuitJson = await fetchPartCircuitJson(legacyRequest);
16580
- usedLegacyRequest = true;
16581
- }
16582
- if (!circuitJson?.length) throw error;
16583
- const manufacturerPartNumbers = circuitJson.flatMap(
16584
- (element) => element.type === "source_component" && element.manufacturer_part_number ? [element.manufacturer_part_number] : []
16585
- );
16586
- if (manufacturerPartNumber && manufacturerPartNumbers.some(
16587
- (importedManufacturerPartNumber) => importedManufacturerPartNumber.trim().toLowerCase() !== manufacturerPartNumber.trim().toLowerCase()
16588
- ))
16589
- throw error;
16590
- const reason = usedLegacyRequest ? "the parts engine only accepted a request without the datasheet option" : error instanceof Error ? error.message : String(error);
16591
- return { circuitJson, datasheetFailureReason: reason };
16592
- }
16593
- };
16594
- var fetchPartCircuitJsonWithoutDatasheet = async (fetchPartCircuitJson, request) => {
16595
- const { circuitJson } = await fetchDatasheetPart(fetchPartCircuitJson, {
16596
- ...request,
16597
- includeDatasheetInformation: false
16598
- });
16599
- return circuitJson;
16600
- };
16601
- var fetchPartCircuitJsonWithDatasheet = async ({
16602
- fetchPartCircuitJson,
16603
- supplierPartNumber,
16604
- manufacturerPartNumber
16605
- }, sourcePortOwner) => {
16606
- const includeDatasheetInformation = sourcePortOwner.config.componentName === "Chip" || sourcePortOwner.config.componentName === "OpAmp";
16607
- const request = {
16608
- supplierPartNumber,
16609
- manufacturerPartNumber,
16610
- platformFetch: sourcePortOwner.root?.platform?.platformFetch,
16611
- includeDatasheetInformation
16612
- };
16613
- let partFetch;
16614
- const circuit = sourcePortOwner.root;
16615
- if (sourcePortOwner.config.componentName === "Chip" && circuit) {
16616
- let partFetchesByEngine = chipDatasheetPartFetches.get(circuit);
16617
- if (!partFetchesByEngine) {
16618
- partFetchesByEngine = /* @__PURE__ */ new WeakMap();
16619
- chipDatasheetPartFetches.set(circuit, partFetchesByEngine);
16620
- }
16621
- let partFetches = partFetchesByEngine.get(fetchPartCircuitJson);
16622
- if (!partFetches) {
16623
- partFetches = /* @__PURE__ */ new Map();
16624
- partFetchesByEngine.set(fetchPartCircuitJson, partFetches);
16625
- }
16626
- const partCacheKey = `datasheet_part:${JSON.stringify(
16627
- [supplierPartNumber, manufacturerPartNumber]
16628
- )}`;
16629
- partFetch = partFetches.get(partCacheKey) ?? fetchDatasheetPart(fetchPartCircuitJson, request);
16630
- partFetches.set(partCacheKey, partFetch);
16631
- } else {
16632
- partFetch = fetchDatasheetPart(fetchPartCircuitJson, request);
16633
- }
16634
- const { circuitJson, datasheetFailureReason } = await partFetch;
16635
- if (includeDatasheetInformation && datasheetFailureReason !== void 0) {
16636
- const message = `Datasheet information for ${sourcePortOwner.getDisplayName()} could not be fetched: ${datasheetFailureReason}. Pin attributes may not be populated.`;
16637
- if (sourcePortOwner.source_component_id && sourcePortOwner.root) {
16638
- sourcePortOwner.root.db.source_property_ignored_warning.insert({
16639
- source_component_id: sourcePortOwner.source_component_id,
16640
- property_name: "pinAttributes",
16641
- message,
16642
- error_type: "source_property_ignored_warning"
16643
- });
16644
- } else {
16645
- console.warn(message);
16646
- }
16647
- }
16648
- return circuitJson;
16649
- };
16650
-
16651
- // lib/components/base-components/NormalComponent/NormalComponent_doInitialPartOrientationAnalysis.ts
16652
16992
  var pendingSupplierPartOrientationAnalyses = /* @__PURE__ */ new WeakMap();
16653
16993
  var getPendingSupplierPartOrientationAnalyses = (partsEngine) => {
16654
16994
  const existing = pendingSupplierPartOrientationAnalyses.get(partsEngine);
@@ -16980,8 +17320,8 @@ function NormalComponent_doInitialPcbComponentAnchorAlignment(component) {
16980
17320
 
16981
17321
  // lib/components/base-components/NormalComponent/NormalComponent_doInitialPcbFootprintStringRender.ts
16982
17322
  import {
16983
- supplierProps,
16984
- resolveManufacturerPartNumber
17323
+ supplierProps as supplierProps2,
17324
+ resolveManufacturerPartNumber as resolveManufacturerPartNumber2
16985
17325
  } from "@tscircuit/props";
16986
17326
  import {
16987
17327
  circuit_json_footprint_load_error,
@@ -17067,7 +17407,7 @@ var parseLibraryFootprintRef = (s2) => {
17067
17407
  };
17068
17408
 
17069
17409
  // lib/components/base-components/NormalComponent/NormalComponent_doInitialPcbFootprintStringRender.ts
17070
- var supplierNames = supplierProps.shape.supplierPartNumbers.unwrap().keySchema.options;
17410
+ var supplierNames = supplierProps2.shape.supplierPartNumbers.unwrap().keySchema.options;
17071
17411
  var shouldAddOutsideFootprintWrapper = (component) => component.componentName === "Symbol" || component.isSchematicPrimitive;
17072
17412
  var getSupplierPartCircuitJsonResolver = (component, footprintLibrary, footprintName) => {
17073
17413
  if (component.getInheritedProperty("partsEngineDisabled")) return;
@@ -17086,7 +17426,7 @@ var getSupplierPartCircuitJsonResolver = (component, footprintLibrary, footprint
17086
17426
  {
17087
17427
  fetchPartCircuitJson,
17088
17428
  supplierPartNumber,
17089
- manufacturerPartNumber: resolveManufacturerPartNumber(component.props)
17429
+ manufacturerPartNumber: resolveManufacturerPartNumber2(component.props)
17090
17430
  },
17091
17431
  component
17092
17432
  );
@@ -17662,7 +18002,7 @@ var NormalComponent_doInitialMissingManufacturerPartNumberWarning = (component)
17662
18002
 
17663
18003
  // lib/components/base-components/NormalComponent/NormalComponent_doInitialComponentAvailabilityWarning.ts
17664
18004
  import {
17665
- supplierProps as supplierProps2
18005
+ supplierProps as supplierProps3
17666
18006
  } from "@tscircuit/props";
17667
18007
  import { source_component_availability_warning } from "circuit-json";
17668
18008
 
@@ -17720,7 +18060,7 @@ var checkPartAvailability = (circuit, {
17720
18060
 
17721
18061
  // lib/components/base-components/NormalComponent/NormalComponent_doInitialComponentAvailabilityWarning.ts
17722
18062
  var availabilityChecks = /* @__PURE__ */ new WeakMap();
17723
- var supplierNames2 = supplierProps2.shape.supplierPartNumbers.unwrap().keySchema.options;
18063
+ var supplierNames2 = supplierProps3.shape.supplierPartNumbers.unwrap().keySchema.options;
17724
18064
  function NormalComponent_doInitialComponentAvailabilityWarning(component, { refresh = false } = {}) {
17725
18065
  const root = component.root;
17726
18066
  const sourceComponentId = component.source_component_id;
@@ -17796,14 +18136,14 @@ function NormalComponent_doInitialComponentAvailabilityWarning(component, { refr
17796
18136
  // lib/components/base-components/NormalComponent/NormalComponent_doInitialSupplierFootprintMismatchWarning.ts
17797
18137
  import { getBoundsOfPcbElements } from "@tscircuit/circuit-json-util";
17798
18138
  import {
17799
- supplierProps as supplierProps3
18139
+ supplierProps as supplierProps4
17800
18140
  } from "@tscircuit/props";
17801
18141
  import {
17802
18142
  source_part_not_found_warning,
17803
18143
  supplier_footprint_mismatch_warning
17804
18144
  } from "circuit-json";
17805
18145
  var SUPPLIER_FOOTPRINT_IOU_WARNING_THRESHOLD = 0.8;
17806
- var supplierNames3 = supplierProps3.shape.supplierPartNumbers.unwrap().keySchema.options;
18146
+ var supplierNames3 = supplierProps4.shape.supplierPartNumbers.unwrap().keySchema.options;
17807
18147
  var isCopperElement = (elm) => elm.type === "pcb_smtpad" || elm.type === "pcb_plated_hole";
17808
18148
  var isValidBounds = (bounds) => Number.isFinite(bounds.minX) && Number.isFinite(bounds.minY) && Number.isFinite(bounds.maxX) && Number.isFinite(bounds.maxY) && bounds.maxX > bounds.minX && bounds.maxY > bounds.minY;
17809
18149
  var getCopperBounds = (elements) => {
@@ -18127,6 +18467,11 @@ var NormalComponent = class extends PrimitiveComponent2 {
18127
18467
  _asyncFootprintCadModel;
18128
18468
  /** Electrical attributes from imported ports; user props remain authoritative. */
18129
18469
  _importedSourcePorts = [];
18470
+ _importedInternallyConnectedPinNames;
18471
+ /** Optional datasheet facts fetched solely for source-level validation. */
18472
+ _fetchedSourcePortsForPinAttributes = [];
18473
+ _fetchedInternallyConnectedPinNames;
18474
+ _hasStartedPinAttributesFetch = false;
18130
18475
  _isCadModelChild;
18131
18476
  _inferredInternallyConnectedPinNames = [];
18132
18477
  pcb_missing_footprint_error_id;
@@ -18149,7 +18494,7 @@ var NormalComponent = class extends PrimitiveComponent2 {
18149
18494
  return [];
18150
18495
  }
18151
18496
  get internallyConnectedPinNames() {
18152
- const rawPins = this._parsedProps.internallyConnectedPins ?? this.defaultInternallyConnectedPinNames;
18497
+ const rawPins = this._parsedProps.internallyConnectedPins ?? this._importedInternallyConnectedPinNames ?? this.defaultInternallyConnectedPinNames;
18153
18498
  return [...rawPins, ...this._inferredInternallyConnectedPinNames].map(
18154
18499
  (pinGroup) => pinGroup.map(
18155
18500
  (pin) => typeof pin === "number" ? `pin${pin}` : pin
@@ -18596,7 +18941,7 @@ var NormalComponent = class extends PrimitiveComponent2 {
18596
18941
  const source_component = db2.source_component.insert({
18597
18942
  ftype,
18598
18943
  name: this.name,
18599
- manufacturer_part_number: resolveManufacturerPartNumber2(props),
18944
+ manufacturer_part_number: resolveManufacturerPartNumber3(props),
18600
18945
  supplier_part_numbers: props.supplierPartNumbers,
18601
18946
  display_name: props.displayName
18602
18947
  });
@@ -18663,7 +19008,8 @@ var NormalComponent = class extends PrimitiveComponent2 {
18663
19008
  for (const netPortNames of this.internallyConnectedPinNames) {
18664
19009
  const ports = [];
18665
19010
  for (const portName of netPortNames) {
18666
- ports.push(this.portMap[portName]);
19011
+ const port = this.portMap[portName] ?? this.portMap[`pin${portName}`];
19012
+ if (port) ports.push(port);
18667
19013
  }
18668
19014
  internallyConnectedPorts.push(ports);
18669
19015
  }
@@ -18742,7 +19088,7 @@ var NormalComponent = class extends PrimitiveComponent2 {
18742
19088
  const schematic_box_width = dimensions?.getSize().width;
18743
19089
  const schematic_box_height = dimensions?.getSize().height;
18744
19090
  const manufacturer_part_number_schematic_text = db2.schematic_text.insert({
18745
- text: resolveManufacturerPartNumber2(props) ?? "",
19091
+ text: resolveManufacturerPartNumber3(props) ?? "",
18746
19092
  schematic_component_id: schematic_component2.schematic_component_id,
18747
19093
  anchor: "left",
18748
19094
  rotation: 0,
@@ -19764,6 +20110,10 @@ var NormalComponent = class extends PrimitiveComponent2 {
19764
20110
  }
19765
20111
  doInitialSourceDesignRuleChecks() {
19766
20112
  NormalComponent_doInitialSourceDesignRuleChecks(this);
20113
+ NormalComponent_doInitialSourcePinSpecificationChecks(this);
20114
+ }
20115
+ updateSourceDesignRuleChecks() {
20116
+ NormalComponent_doInitialSourcePinSpecificationChecks(this);
19767
20117
  }
19768
20118
  doInitialSourceComponentPropertyValidation() {
19769
20119
  this._insertInvalidFootprintPropErrors();
@@ -19990,7 +20340,7 @@ function inflatePcbBoard(pcbBoard, inflatorContext) {
19990
20340
  }
19991
20341
 
19992
20342
  // lib/components/normal-components/Capacitor.ts
19993
- import { capacitorProps, resolveManufacturerPartNumber as resolveManufacturerPartNumber3 } from "@tscircuit/props";
20343
+ import { capacitorProps, resolveManufacturerPartNumber as resolveManufacturerPartNumber4 } from "@tscircuit/props";
19994
20344
  import { formatSiUnit } from "format-si-unit";
19995
20345
  import { symbols as symbols3 } from "schematic-symbols";
19996
20346
 
@@ -20035,15 +20385,15 @@ var Capacitor_addPolarityFabricationSymbols = (capacitor) => {
20035
20385
  source_port_id: negatives[0].source_port_id
20036
20386
  });
20037
20387
  if (!positive || !negative) return;
20038
- const distance27 = Math.hypot(negative.x - positive.x, negative.y - positive.y);
20039
- if (distance27 < 1e-6) return;
20388
+ const distance28 = Math.hypot(negative.x - positive.x, negative.y - positive.y);
20389
+ if (distance28 < 1e-6) return;
20040
20390
  const frame = compose9(
20041
20391
  translate7((positive.x + negative.x) / 2, (positive.y + negative.y) / 2),
20042
20392
  rotate4(Math.atan2(negative.y - positive.y, negative.x - positive.x))
20043
20393
  );
20044
20394
  const point6 = (x2, y2) => applyToPoint31(frame, { x: x2, y: y2 });
20045
- const offset = distance27 / 4;
20046
- const halfSize = Math.min(distance27 * 0.12, 0.3);
20395
+ const offset = distance28 / 4;
20396
+ const halfSize = Math.min(distance28 * 0.12, 0.3);
20047
20397
  const routes = [
20048
20398
  [point6(-offset - halfSize, 0), point6(-offset + halfSize, 0)],
20049
20399
  [point6(-offset, -halfSize), point6(-offset, halfSize)],
@@ -20176,7 +20526,7 @@ var Capacitor = class extends NormalComponent {
20176
20526
  const source_component = db2.source_component.insert({
20177
20527
  ftype: "simple_capacitor",
20178
20528
  name: this.name,
20179
- manufacturer_part_number: resolveManufacturerPartNumber3(props),
20529
+ manufacturer_part_number: resolveManufacturerPartNumber4(props),
20180
20530
  supplier_part_numbers: props.supplierPartNumbers,
20181
20531
  capacitance: props.capacitance,
20182
20532
  max_voltage_rating: props.maxVoltageRating,
@@ -20309,9 +20659,7 @@ function inflateSourceCapacitor(sourceElm, inflatorContext) {
20309
20659
  // lib/components/normal-components/Chip.ts
20310
20660
  import { normalizeDegrees as normalizeDegrees6 } from "@tscircuit/math-utils";
20311
20661
  import { chipProps, resolveManufacturerPartNumber as resolveManufacturerPartNumber5 } from "@tscircuit/props";
20312
- import {
20313
- pcb_component_invalid_layer_error as pcb_component_invalid_layer_error2
20314
- } from "circuit-json";
20662
+ import { pcb_component_invalid_layer_error as pcb_component_invalid_layer_error2 } from "circuit-json";
20315
20663
 
20316
20664
  // lib/components/normal-components/Chip_doInitialPcbPlacementDesignRuleChecks.ts
20317
20665
  import { checkConnectorAccessibleOrientation } from "@tscircuit/checks";
@@ -20375,209 +20723,8 @@ var Chip_doInitialPcbPlacementDesignRuleChecks = (chip) => {
20375
20723
  db2.insertAll([orientationWarning]);
20376
20724
  };
20377
20725
 
20378
- // lib/components/normal-components/Chip_doInitialSourcePinSpecificationChecks.ts
20379
- import {
20380
- checkAllPinsInComponentAreUnderspecified,
20381
- checkNoGroundPinDefined,
20382
- checkNoPowerPinDefined
20383
- } from "@tscircuit/checks";
20384
-
20385
- // lib/components/primitive-components/Port/get-pin-attribute-mismatches.ts
20386
- var getPinAttributeMismatches = (declared, imported) => {
20387
- const mismatches = [];
20388
- for (const propName of Object.keys(declared)) {
20389
- if (propName === "highlightColor" || propName === "includeInBoardPinout")
20390
- continue;
20391
- const normalized = {};
20392
- applyPinAttributesToSourcePort(normalized, {
20393
- [propName]: declared[propName]
20394
- });
20395
- if (propName === "capabilities") {
20396
- for (const attributeName of Object.keys(
20397
- imported
20398
- )) {
20399
- if (attributeName.startsWith("supports_"))
20400
- Object.assign(normalized, {
20401
- [attributeName]: normalized[attributeName] ?? false
20402
- });
20403
- }
20404
- }
20405
- for (const attributeName of Object.keys(
20406
- normalized
20407
- )) {
20408
- const declaredValue = normalized[attributeName];
20409
- const supportedAttributeName = attributeName.startsWith(
20410
- "is_configured_for_"
20411
- ) ? attributeName.replace("is_configured_for_", "supports_") : attributeName.startsWith("is_using_") ? attributeName.replace("is_using_", "can_use_") : void 0;
20412
- if (supportedAttributeName) {
20413
- if (declaredValue === true && imported[supportedAttributeName] === false)
20414
- mismatches.push(
20415
- `${propName}: ${JSON.stringify(declared[propName])}, fetched ${supportedAttributeName}: false`
20416
- );
20417
- continue;
20418
- }
20419
- const importedValue = imported[attributeName];
20420
- const valuesMatch = typeof importedValue === "number" && typeof declaredValue === "number" ? Math.abs(importedValue - declaredValue) <= Number.EPSILON * 8 * Math.max(1, Math.abs(importedValue), Math.abs(declaredValue)) : importedValue === declaredValue;
20421
- if (importedValue !== void 0 && declaredValue !== void 0 && !valuesMatch)
20422
- mismatches.push(
20423
- `${propName}: ${JSON.stringify(declared[propName])}, fetched ${attributeName}: ${JSON.stringify(importedValue)}`
20424
- );
20425
- }
20426
- }
20427
- return mismatches;
20428
- };
20429
-
20430
- // lib/components/normal-components/Chip_fetchPinAttributesForValidation.ts
20431
- import {
20432
- resolveManufacturerPartNumber as resolveManufacturerPartNumber4,
20433
- supplierProps as supplierProps4
20434
- } from "@tscircuit/props";
20435
- import { source_pin_attributes as source_pin_attributes2 } from "circuit-json";
20436
- var Chip_fetchPinAttributesForValidation = (chip) => {
20437
- if (chip.config.componentName !== "Chip") return;
20438
- if (chip._hasStartedPinAttributesFetch) return;
20439
- if (!Object.keys(chip._parsedProps.pinAttributes ?? {}).length) return;
20440
- if (chip.getInheritedProperty("partsEngineDisabled")) return;
20441
- if (chip.getInheritedProperty("bomDisabled")) return;
20442
- if (chip._importedSourcePorts.some(
20443
- (port) => Object.values(source_pin_attributes2.parse(port)).some(
20444
- (value) => value !== void 0
20445
- )
20446
- ))
20447
- return;
20448
- const partsEngine = chip.getInheritedProperty("partsEngine");
20449
- if (!partsEngine?.fetchPartCircuitJson) return;
20450
- const footprint = chip.resolveFootprint();
20451
- if (supplierProps4.shape.supplierPartNumbers.unwrap().keySchema.options.some(
20452
- (supplierName) => typeof chip.root?.platform?.footprintLibraryMap?.[supplierName] !== "function" && chip._parsedProps.supplierPartNumbers?.[supplierName]?.some(
20453
- (partNumber) => footprint === `${supplierName}:${partNumber}`
20454
- )
20455
- ))
20456
- return;
20457
- const supplierPartNumber = Object.values(
20458
- chip._parsedProps.supplierPartNumbers ?? {}
20459
- ).flat()[0];
20460
- const manufacturerPartNumber = resolveManufacturerPartNumber4(
20461
- chip._parsedProps
20462
- );
20463
- if (!supplierPartNumber && !manufacturerPartNumber) return;
20464
- chip._hasStartedPinAttributesFetch = true;
20465
- chip._queueAsyncEffect("fetch-chip-pin-metadata", async () => {
20466
- try {
20467
- const partCircuitJson = await fetchPartCircuitJsonWithDatasheet(
20468
- {
20469
- fetchPartCircuitJson: partsEngine.fetchPartCircuitJson,
20470
- supplierPartNumber,
20471
- manufacturerPartNumber
20472
- },
20473
- chip
20474
- );
20475
- chip._fetchedSourcePortsForPinAttributes = partCircuitJson?.filter((element) => element.type === "source_port") ?? [];
20476
- chip._markDirty("SourceDesignRuleChecks");
20477
- } catch {
20478
- }
20479
- });
20480
- };
20481
-
20482
- // lib/components/normal-components/Chip_doInitialSourcePinSpecificationChecks.ts
20483
- var Chip_doInitialSourcePinSpecificationChecks = (chip) => {
20484
- if (chip.config.componentName !== "Chip") return;
20485
- if (!chip.source_component_id) return;
20486
- const { db: db2 } = chip.root;
20487
- const existingWarning = db2.source_component_pins_underspecified_warning.getWhere({
20488
- source_component_id: chip.source_component_id
20489
- });
20490
- const drcChecksDisabled = chip.root?.platform?.drcChecksDisabled ?? chip.getInheritedProperty("drcChecksDisabled");
20491
- const pinSpecificationDrcChecksDisabled = chip.root?.platform?.pinSpecificationDrcChecksDisabled ?? chip.getInheritedProperty("pinSpecificationDrcChecksDisabled");
20492
- const checksDisabled = drcChecksDisabled || pinSpecificationDrcChecksDisabled;
20493
- if (!checksDisabled) Chip_fetchPinAttributesForValidation(chip);
20494
- const sourcePorts = checksDisabled ? [] : chip.selectAll("port").flatMap((port) => {
20495
- if (!port.source_port_id) return [];
20496
- const sourcePort = db2.source_port.get(port.source_port_id);
20497
- return sourcePort?.source_component_id === chip.source_component_id ? [sourcePort] : [];
20498
- });
20499
- const sourceComponent = checksDisabled ? null : db2.source_component.get(chip.source_component_id);
20500
- const chipCircuitJson = sourceComponent ? [sourceComponent, ...sourcePorts] : [];
20501
- const issues = [];
20502
- if (!checksDisabled) {
20503
- for (const port of chip.selectAll("port")) {
20504
- const sourcePort = sourcePorts.find(
20505
- (sourcePort2) => sourcePort2.source_port_id === port.source_port_id
20506
- );
20507
- if (!sourcePort) continue;
20508
- const declared = {};
20509
- for (const alias of port.getNameAndAliases()) {
20510
- Object.assign(declared, chip._parsedProps.pinAttributes?.[alias]);
20511
- }
20512
- const imported = getImportedSourcePinAttributes(
20513
- port,
20514
- chip._fetchedSourcePortsForPinAttributes.length ? chip._fetchedSourcePortsForPinAttributes : chip._importedSourcePorts
20515
- );
20516
- const reasons2 = getPinAttributeMismatches(declared, imported);
20517
- if (reasons2.length)
20518
- issues.push({
20519
- pinName: sourcePort.name || "unnamed pin",
20520
- reasons: reasons2,
20521
- sourcePort
20522
- });
20523
- }
20524
- }
20525
- for (const [warningTable, check] of [
20526
- [db2.source_no_power_pin_defined_warning, checkNoPowerPinDefined],
20527
- [db2.source_no_ground_pin_defined_warning, checkNoGroundPinDefined]
20528
- ]) {
20529
- const existing = warningTable.getWhere({
20530
- source_component_id: chip.source_component_id
20531
- });
20532
- const existingId = existing?.type === "source_no_power_pin_defined_warning" ? existing.source_no_power_pin_defined_warning_id : existing?.source_no_ground_pin_defined_warning_id;
20533
- const [warning2] = checksDisabled || issues.length ? [] : check(chipCircuitJson);
20534
- if (warning2) {
20535
- if (existingId) {
20536
- warningTable.update(existingId, {
20537
- message: warning2.message,
20538
- source_port_ids: warning2.source_port_ids,
20539
- subcircuit_id: warning2.subcircuit_id
20540
- });
20541
- } else {
20542
- db2.insertAll([warning2]);
20543
- }
20544
- } else if (existingId) {
20545
- warningTable.delete(existingId);
20546
- }
20547
- }
20548
- const [underspecifiedWarning] = checksDisabled ? [] : checkAllPinsInComponentAreUnderspecified(chipCircuitJson);
20549
- if (!issues.length && !underspecifiedWarning) {
20550
- if (existingWarning) {
20551
- db2.source_component_pins_underspecified_warning.delete(
20552
- existingWarning.source_component_pins_underspecified_warning_id
20553
- );
20554
- }
20555
- return;
20556
- }
20557
- const examples = issues.slice(0, 3).map(({ pinName, reasons: reasons2 }) => `${pinName} (${reasons2.join("; ")})`).join(", ");
20558
- const remaining = issues.length > 3 ? `, and ${issues.length - 3} more` : "";
20559
- const warning = {
20560
- source_component_id: chip.source_component_id,
20561
- source_port_ids: issues.length ? issues.map(({ sourcePort }) => sourcePort.source_port_id) : underspecifiedWarning.source_port_ids,
20562
- subcircuit_id: chip.getSubcircuit().subcircuit_id ?? void 0,
20563
- warning_type: "source_component_pins_underspecified_warning",
20564
- message: issues.length ? `Chip ${chip.name || "unnamed chip"} has pinAttributes that conflict with fetched pin metadata on ${issues.length} pin${issues.length === 1 ? "" : "s"}: ${examples}${remaining}. Check the chip configuration against the part datasheet.` : underspecifiedWarning.message
20565
- };
20566
- if (existingWarning) {
20567
- db2.source_component_pins_underspecified_warning.update(
20568
- existingWarning.source_component_pins_underspecified_warning_id,
20569
- warning
20570
- );
20571
- } else {
20572
- db2.source_component_pins_underspecified_warning.insert(warning);
20573
- }
20574
- };
20575
-
20576
20726
  // lib/components/normal-components/Chip.ts
20577
20727
  var Chip = class extends NormalComponent {
20578
- /** Fetched facts used only for comparison when the user supplies a custom footprint. */
20579
- _fetchedSourcePortsForPinAttributes = [];
20580
- _hasStartedPinAttributesFetch = false;
20581
20728
  get config() {
20582
20729
  return {
20583
20730
  componentName: "Chip",
@@ -20632,13 +20779,6 @@ var Chip = class extends NormalComponent {
20632
20779
  });
20633
20780
  this.source_component_id = source_component.source_component_id;
20634
20781
  }
20635
- doInitialSourceDesignRuleChecks() {
20636
- super.doInitialSourceDesignRuleChecks();
20637
- Chip_doInitialSourcePinSpecificationChecks(this);
20638
- }
20639
- updateSourceDesignRuleChecks() {
20640
- Chip_doInitialSourcePinSpecificationChecks(this);
20641
- }
20642
20782
  doInitialPcbComponentRender() {
20643
20783
  if (this.root?.pcbDisabled) return;
20644
20784
  const { db: db2 } = this.root;
@@ -22079,7 +22219,7 @@ import {
22079
22219
  groupProps
22080
22220
  } from "@tscircuit/props";
22081
22221
  import {
22082
- distance as distance19
22222
+ distance as distance20
22083
22223
  } from "circuit-json";
22084
22224
  import Debug15 from "debug";
22085
22225
 
@@ -41323,9 +41463,9 @@ function getFreeBoundaryTracks(params) {
41323
41463
  for (const via of vias) {
41324
41464
  if (!via.spanLayers.includes(targetLayer2)) continue;
41325
41465
  const radius = via.diameter / 2 + traceWidth / 2 + clearance;
41326
- const distance27 = Math.abs(via.center[across] - edge);
41327
- if (distance27 >= radius) continue;
41328
- const extent = Math.sqrt(radius * radius - distance27 * distance27);
41466
+ const distance28 = Math.abs(via.center[across] - edge);
41467
+ if (distance28 >= radius) continue;
41468
+ const extent = Math.sqrt(radius * radius - distance28 * distance28);
41329
41469
  blocked.push([via.center[along2] - extent, via.center[along2] + extent]);
41330
41470
  }
41331
41471
  const gaps = [];
@@ -115553,9 +115693,8 @@ function computeCrossings(traces, opts = {}) {
115553
115693
  }
115554
115694
  }
115555
115695
  }
115556
- const out = traces.map((t48) => ({
115557
- source_trace_id: t48.source_trace_id,
115558
- connectivity_key: t48.connectivity_key,
115696
+ const out = traces.map((trace) => ({
115697
+ ...trace,
115559
115698
  edges: []
115560
115699
  }));
115561
115700
  for (let ti = 0; ti < traces.length; ti++) {
@@ -115856,6 +115995,147 @@ function removeOverlappingSameNetCrossingSegments(traces) {
115856
115995
  }));
115857
115996
  }
115858
115997
 
115998
+ // lib/components/primitive-components/Group/Group_doInitialSchematicTraceRender/remove-redundant-traces-to-net-labels.ts
115999
+ import { distance as distance18, pointToSegmentDistance as pointToSegmentDistance4 } from "@tscircuit/math-utils";
116000
+ var GEOMETRY_TOLERANCE = 1e-6;
116001
+ function removeRedundantTracesToNetLabels({
116002
+ traces,
116003
+ existingTraces,
116004
+ netLabelTerminals,
116005
+ terminals,
116006
+ inlineNetLabelTraces = /* @__PURE__ */ new Set()
116007
+ }) {
116008
+ const retainedEdgesByOriginalEdge = /* @__PURE__ */ new Map();
116009
+ for (const connectivityKey of new Set(
116010
+ netLabelTerminals.map((terminal) => terminal.connectivityKey)
116011
+ )) {
116012
+ const routingNodes = [];
116013
+ const getOrCreateRoutingNode = (position) => {
116014
+ let node = routingNodes.find(
116015
+ (node2) => distance18(node2.position, position) <= GEOMETRY_TOLERANCE
116016
+ );
116017
+ if (!node) {
116018
+ node = { position, segments: [], distanceToLabel: Infinity };
116019
+ routingNodes.push(node);
116020
+ }
116021
+ return node;
116022
+ };
116023
+ const netEdges = [
116024
+ ...existingTraces.filter(
116025
+ (trace) => trace.subcircuit_connectivity_map_key === connectivityKey
116026
+ ).flatMap(
116027
+ (trace) => trace.edges.map((edge) => ({ edge, isPreserved: true }))
116028
+ ),
116029
+ ...traces.filter(
116030
+ (trace) => trace.subcircuit_connectivity_map_key === connectivityKey
116031
+ ).flatMap(
116032
+ (trace) => trace.edges.map((edge) => ({
116033
+ edge,
116034
+ isPreserved: inlineNetLabelTraces.has(trace)
116035
+ }))
116036
+ )
116037
+ ];
116038
+ for (const { edge } of netEdges) {
116039
+ getOrCreateRoutingNode(edge.from);
116040
+ getOrCreateRoutingNode(edge.to);
116041
+ }
116042
+ for (let edgeIndex = 0; edgeIndex < netEdges.length; edgeIndex++) {
116043
+ for (let otherEdgeIndex = edgeIndex + 1; otherEdgeIndex < netEdges.length; otherEdgeIndex++) {
116044
+ const firstEdge = netEdges[edgeIndex].edge;
116045
+ const secondEdge = netEdges[otherEdgeIndex].edge;
116046
+ const contactPoint = segmentIntersection(
116047
+ firstEdge.from,
116048
+ firstEdge.to,
116049
+ secondEdge.from,
116050
+ secondEdge.to,
116051
+ GEOMETRY_TOLERANCE
116052
+ );
116053
+ if (contactPoint) getOrCreateRoutingNode(contactPoint);
116054
+ }
116055
+ }
116056
+ const terminalNodes = terminals.filter((terminal) => terminal.connectivityKey === connectivityKey).map((terminal) => getOrCreateRoutingNode(terminal.position));
116057
+ for (const terminal of netLabelTerminals) {
116058
+ if (terminal.connectivityKey === connectivityKey) {
116059
+ getOrCreateRoutingNode(terminal.position).distanceToLabel = 0;
116060
+ }
116061
+ }
116062
+ const routingSegmentsByOriginalEdge = /* @__PURE__ */ new Map();
116063
+ for (const { edge, isPreserved } of netEdges) {
116064
+ const edgeNodes = routingNodes.filter(
116065
+ (node) => pointToSegmentDistance4(node.position, edge.from, edge.to) <= GEOMETRY_TOLERANCE
116066
+ ).sort(
116067
+ (firstNode, secondNode) => distance18(edge.from, firstNode.position) - distance18(edge.from, secondNode.position)
116068
+ );
116069
+ const segments = [];
116070
+ for (let nodeIndex = 1; nodeIndex < edgeNodes.length; nodeIndex++) {
116071
+ const from = edgeNodes[nodeIndex - 1];
116072
+ const to = edgeNodes[nodeIndex];
116073
+ const segment2 = {
116074
+ from,
116075
+ to,
116076
+ cost: isPreserved ? 0 : distance18(from.position, to.position)
116077
+ };
116078
+ from.segments.push(segment2);
116079
+ to.segments.push(segment2);
116080
+ segments.push(segment2);
116081
+ }
116082
+ if (!isPreserved) routingSegmentsByOriginalEdge.set(edge, segments);
116083
+ }
116084
+ const unvisitedNodes = new Set(routingNodes);
116085
+ while (unvisitedNodes.size > 0) {
116086
+ let nearestNode;
116087
+ for (const node of unvisitedNodes) {
116088
+ if (node.distanceToLabel < (nearestNode?.distanceToLabel ?? Infinity)) {
116089
+ nearestNode = node;
116090
+ }
116091
+ }
116092
+ if (!nearestNode) break;
116093
+ unvisitedNodes.delete(nearestNode);
116094
+ for (const segment2 of nearestNode.segments) {
116095
+ const neighborNode = segment2.from === nearestNode ? segment2.to : segment2.from;
116096
+ const candidateDistance = nearestNode.distanceToLabel + segment2.cost;
116097
+ if (unvisitedNodes.has(neighborNode) && candidateDistance < neighborNode.distanceToLabel) {
116098
+ neighborNode.distanceToLabel = candidateDistance;
116099
+ neighborNode.pathToLabel = { node: nearestNode, segment: segment2 };
116100
+ }
116101
+ }
116102
+ }
116103
+ const retainedSegments = /* @__PURE__ */ new Set();
116104
+ for (let node of terminalNodes) {
116105
+ while (node.pathToLabel) {
116106
+ const { segment: segment2, node: nextNodeOnPath } = node.pathToLabel;
116107
+ if (retainedSegments.has(segment2)) break;
116108
+ retainedSegments.add(segment2);
116109
+ node = nextNodeOnPath;
116110
+ }
116111
+ }
116112
+ for (const [edge, segments] of routingSegmentsByOriginalEdge) {
116113
+ const retainedEdgeSegments = [];
116114
+ for (const segment2 of segments) {
116115
+ if (!retainedSegments.has(segment2) && Number.isFinite(segment2.from.distanceToLabel))
116116
+ continue;
116117
+ const previousRetainedEdge = retainedEdgeSegments.at(-1);
116118
+ if (previousRetainedEdge && distance18(previousRetainedEdge.to, segment2.from.position) <= GEOMETRY_TOLERANCE) {
116119
+ previousRetainedEdge.to = segment2.to.position;
116120
+ } else {
116121
+ retainedEdgeSegments.push({
116122
+ ...edge,
116123
+ from: segment2.from.position,
116124
+ to: segment2.to.position
116125
+ });
116126
+ }
116127
+ }
116128
+ retainedEdgesByOriginalEdge.set(edge, retainedEdgeSegments);
116129
+ }
116130
+ }
116131
+ return traces.map((trace) => ({
116132
+ ...trace,
116133
+ edges: trace.edges.flatMap(
116134
+ (edge) => retainedEdgesByOriginalEdge.get(edge) ?? [edge]
116135
+ )
116136
+ })).filter((trace) => trace.edges.length > 0);
116137
+ }
116138
+
115859
116139
  // lib/components/primitive-components/Group/Group_doInitialSchematicTraceRender/applyTracesFromSolverOutput.ts
115860
116140
  var debug10 = Debug12("Group_doInitialSchematicTraceRender");
115861
116141
  var MAX_PIN_SNAP_GAP = 1.5;
@@ -115914,9 +116194,15 @@ function applyTracesFromSolverOutput(args) {
115914
116194
  group,
115915
116195
  solver,
115916
116196
  userNetIdToConnKey,
115917
- schematicPortIdsWithPreExistingNetLabels
116197
+ schematicPortIdsWithPreExistingNetLabels,
116198
+ schematicSheetId
115918
116199
  } = args;
115919
116200
  const { db: db2 } = group.root;
116201
+ const routedPinBySchematicPortId = new Map(
116202
+ solver.inputProblem.chips.flatMap(
116203
+ (chip) => chip.pins.map((pin) => [asSchematicPortId(pin.pinId), pin])
116204
+ )
116205
+ );
115920
116206
  const customSymbolPortIds = new Set(
115921
116207
  group.selectAll("port").filter((port) => {
115922
116208
  if (!port._getSymbolAncestor()) return false;
@@ -115954,19 +116240,12 @@ function applyTracesFromSolverOutput(args) {
115954
116240
  }
115955
116241
  const traces = solver.inlineNetLabelSolver?.getOutput().traces ?? solver.sameNetJunctionAlignmentSolver?.getOutput().traces ?? solver.netLabelTraceCollisionSolver?.getOutput().traces ?? solver.traceCleanupSolver?.getOutput().traces ?? solver.traceLabelOverlapAvoidanceSolver?.getOutput().traces ?? solver.schematicTraceLinesSolver?.solvedTracePaths;
115956
116242
  const pendingTraces = [];
116243
+ const terminals = [];
116244
+ const netLabelTerminals = [];
115957
116245
  debug10(`Traces inside SchematicTraceSolver output: ${(traces ?? []).length}`);
115958
116246
  for (const solvedTracePath of traces ?? []) {
115959
116247
  const uniquePinIds = Array.from(new Set(solvedTracePath.pinIds ?? []));
115960
116248
  const solvedTraceSchematicPortIds = uniquePinIds.map(asSchematicPortId);
115961
- const isNetLabelCoveredTrace = solvedTraceSchematicPortIds.length > 0 && solvedTraceSchematicPortIds.every(
115962
- (id) => schematicPortIdsWithPreExistingNetLabels.has(id)
115963
- );
115964
- if (isNetLabelCoveredTrace) {
115965
- debug10(
115966
- `Skipping solver netlabel-covered trace ${solvedTracePath?.mspPairId} because all schematic ports already have netlabels`
115967
- );
115968
- continue;
115969
- }
115970
116249
  const points = solvedTracePath?.tracePath;
115971
116250
  if (!Array.isArray(points) || points.length < 2) {
115972
116251
  debug10(
@@ -116025,6 +116304,27 @@ function applyTracesFromSolverOutput(args) {
116025
116304
  subcircuit_connectivity_map_key = sourcePortConnKeys[0];
116026
116305
  }
116027
116306
  }
116307
+ if (subcircuit_connectivity_map_key) {
116308
+ for (const schematicPortId of solvedTraceSchematicPortIds) {
116309
+ const schematicPort = db2.schematic_port.get(schematicPortId);
116310
+ if (!schematicPort) continue;
116311
+ const portTerminal = {
116312
+ position: schematicPort.center,
116313
+ connectivityKey: subcircuit_connectivity_map_key
116314
+ };
116315
+ terminals.push(portTerminal);
116316
+ const routedPin = routedPinBySchematicPortId.get(schematicPortId);
116317
+ if (routedPin) {
116318
+ terminals.push({
116319
+ position: { x: routedPin.x, y: routedPin.y },
116320
+ connectivityKey: subcircuit_connectivity_map_key
116321
+ });
116322
+ }
116323
+ if (schematicPortIdsWithPreExistingNetLabels.has(schematicPortId)) {
116324
+ netLabelTerminals.push(portTerminal);
116325
+ }
116326
+ }
116327
+ }
116028
116328
  const endpointSchematicSheetIds = new Set(
116029
116329
  solvedTraceSchematicPortIds.map(
116030
116330
  (schematicPortId) => db2.schematic_port.get(schematicPortId)?.schematic_sheet_id
@@ -116046,18 +116346,39 @@ function applyTracesFromSolverOutput(args) {
116046
116346
  debug10(
116047
116347
  `Applying ${pendingTraces.length} traces from SchematicTraceSolver output`
116048
116348
  );
116049
- const withCrossings = computeCrossings(
116050
- pendingTraces.map((t48) => ({
116051
- source_trace_id: t48.source_trace_id,
116052
- edges: t48.edges,
116053
- connectivity_key: t48.subcircuit_connectivity_map_key
116054
- }))
116349
+ const existingTraces = db2.schematic_trace.list().filter((trace) => trace.schematic_sheet_id === schematicSheetId);
116350
+ const netLabelPlacements = solver.inlineNetLabelSolver?.getOutput().netLabelPlacements ?? solver.netLabelNetLabelCollisionSolver?.getOutput().netLabelPlacements ?? solver.netLabelTraceCollisionSolver?.getOutput().netLabelPlacements ?? solver.netLabelPlacementSolver?.netLabelPlacements ?? solver.traceLabelOverlapAvoidanceSolver?.getOutput().netLabelPlacements ?? [];
116351
+ for (const placement of netLabelPlacements) {
116352
+ if (placement.pinIds.some(
116353
+ (pinId) => schematicPortIdsWithPreExistingNetLabels.has(asSchematicPortId(pinId))
116354
+ ))
116355
+ continue;
116356
+ const userNetId = solver.mspConnectionPairSolver.globalConnMap.getIdsConnectedToNet(
116357
+ placement.globalConnNetId
116358
+ ).find((netId) => userNetIdToConnKey.has(netId));
116359
+ const connectivityKey = userNetId ? userNetIdToConnKey.get(userNetId) : void 0;
116360
+ if (connectivityKey)
116361
+ terminals.push({ position: placement.anchorPoint, connectivityKey });
116362
+ }
116363
+ const inlineNetLabelTraceIds = new Set(
116364
+ (solver.inlineNetLabelSolver?.getOutput().inlineNetLabelPlacements ?? []).flatMap(
116365
+ (placement) => placement.mspPairId ? [placement.mspPairId] : []
116366
+ )
116055
116367
  );
116368
+ const retainedTraces = removeRedundantTracesToNetLabels({
116369
+ traces: pendingTraces,
116370
+ existingTraces,
116371
+ netLabelTerminals,
116372
+ terminals,
116373
+ inlineNetLabelTraces: new Set(
116374
+ pendingTraces.filter(
116375
+ (trace) => inlineNetLabelTraceIds.has(trace.source_trace_id)
116376
+ )
116377
+ )
116378
+ });
116056
116379
  const existingTracesForJunctions = [];
116057
- const schematicSheetId = group._resolveSchematicSheetId();
116058
- for (const t48 of db2.schematic_trace.list()) {
116380
+ for (const t48 of existingTraces) {
116059
116381
  if (t48.edges.length === 0) continue;
116060
- if (t48.schematic_sheet_id !== schematicSheetId) continue;
116061
116382
  const sourceTrace = t48.source_trace_id ? db2.source_trace.get(t48.source_trace_id) : void 0;
116062
116383
  existingTracesForJunctions.push({
116063
116384
  schematic_trace_id: t48.schematic_trace_id,
@@ -116066,16 +116387,21 @@ function applyTracesFromSolverOutput(args) {
116066
116387
  connectivity_key: t48.subcircuit_connectivity_map_key ?? sourceTrace?.subcircuit_connectivity_map_key
116067
116388
  });
116068
116389
  }
116069
- const tracesWithTrimmedCrossingOverlaps = removeOverlappingSameNetCrossingSegments([
116070
- ...withCrossings,
116390
+ const withCrossings = computeCrossings([
116391
+ ...retainedTraces.map((trace) => ({
116392
+ source_trace_id: trace.source_trace_id,
116393
+ edges: trace.edges,
116394
+ connectivity_key: trace.subcircuit_connectivity_map_key
116395
+ })),
116071
116396
  ...existingTracesForJunctions
116072
116397
  ]);
116398
+ const tracesWithTrimmedCrossingOverlaps = removeOverlappingSameNetCrossingSegments(withCrossings);
116073
116399
  const visibleTraces = tracesWithTrimmedCrossingOverlaps.slice(
116074
116400
  0,
116075
- withCrossings.length
116401
+ retainedTraces.length
116076
116402
  );
116077
116403
  const visibleExistingTraces = tracesWithTrimmedCrossingOverlaps.slice(
116078
- withCrossings.length
116404
+ retainedTraces.length
116079
116405
  );
116080
116406
  for (const trace of visibleExistingTraces) {
116081
116407
  if (!trace.schematic_trace_id) continue;
@@ -117467,7 +117793,8 @@ var renderSchematicTracesForSheet = ({
117467
117793
  group,
117468
117794
  solver,
117469
117795
  userNetIdToConnKey,
117470
- schematicPortIdsWithPreExistingNetLabels
117796
+ schematicPortIdsWithPreExistingNetLabels,
117797
+ schematicSheetId
117471
117798
  });
117472
117799
  applyNetLabelPlacements({
117473
117800
  group,
@@ -119121,7 +119448,7 @@ var RoutingPhasePreparationError = class extends Error {
119121
119448
  var package_default = {
119122
119449
  name: "@tscircuit/core",
119123
119450
  type: "module",
119124
- version: "0.0.2162",
119451
+ version: "0.0.2164",
119125
119452
  types: "dist/index.d.ts",
119126
119453
  main: "dist/index.js",
119127
119454
  module: "dist/index.js",
@@ -119886,7 +120213,7 @@ function getAccumulatedPcbTracesWithStageOutputReplacements({
119886
120213
  }
119887
120214
 
119888
120215
  // lib/components/primitive-components/Group/get-source-trace-id-for-routed-trace.ts
119889
- import { distance as distance18, pointToSegmentDistance as pointToSegmentDistance4 } from "@tscircuit/math-utils";
120216
+ import { distance as distance19, pointToSegmentDistance as pointToSegmentDistance5 } from "@tscircuit/math-utils";
119890
120217
  import { ConnectivityMap as ConnectivityMap6 } from "circuit-json-to-connectivity-map";
119891
120218
  import { applyToPoint as applyToPoint39, rotateDEG as rotateDEG4 } from "transformation-matrix";
119892
120219
  var POINT_EPSILON3 = 1e-6;
@@ -119898,7 +120225,7 @@ function isPointOnWireSegment({
119898
120225
  if (point6.layer && (segmentStart.layer !== point6.layer || segmentEnd.layer !== point6.layer)) {
119899
120226
  return false;
119900
120227
  }
119901
- return pointToSegmentDistance4(point6, segmentStart, segmentEnd) <= POINT_EPSILON3;
120228
+ return pointToSegmentDistance5(point6, segmentStart, segmentEnd) <= POINT_EPSILON3;
119902
120229
  }
119903
120230
  function isPointInSmtPad({
119904
120231
  point: point6,
@@ -119910,7 +120237,7 @@ function isPointInSmtPad({
119910
120237
  return Math.abs(unrotatedPoint.x - pad.x) <= pad.width / 2 + traceWidth / 2 && Math.abs(unrotatedPoint.y - pad.y) <= pad.height / 2 + traceWidth / 2;
119911
120238
  }
119912
120239
  if (pad.shape === "circle") {
119913
- return distance18(point6, pad) <= pad.radius + traceWidth / 2;
120240
+ return distance19(point6, pad) <= pad.radius + traceWidth / 2;
119914
120241
  }
119915
120242
  return false;
119916
120243
  }
@@ -119919,7 +120246,7 @@ function isPointInPlatedHole({
119919
120246
  hole,
119920
120247
  traceWidth = 0
119921
120248
  }) {
119922
- return distance18(point6, hole) <= (hole.outer_diameter ?? hole.hole_diameter ?? 0) / 2 + traceWidth / 2;
120249
+ return distance19(point6, hole) <= (hole.outer_diameter ?? hole.hole_diameter ?? 0) / 2 + traceWidth / 2;
119923
120250
  }
119924
120251
  function getEndpointSourcePortIdsFromGeometry(db2, trace) {
119925
120252
  const sourcePortIds = /* @__PURE__ */ new Set();
@@ -119933,7 +120260,7 @@ function getEndpointSourcePortIdsFromGeometry(db2, trace) {
119933
120260
  if (!pcbPort.source_port_id) continue;
119934
120261
  if (endpoint.layer && pcbPort.layers && !pcbPort.layers.includes(endpoint.layer))
119935
120262
  continue;
119936
- if (distance18(endpoint, pcbPort) <= 0.01) {
120263
+ if (distance19(endpoint, pcbPort) <= 0.01) {
119937
120264
  exactEndpointSourcePortIds.add(pcbPort.source_port_id);
119938
120265
  }
119939
120266
  }
@@ -120622,8 +120949,8 @@ var Group5 = class extends NormalComponent {
120622
120949
  const groupProps2 = props;
120623
120950
  const hasOutline = groupProps2.outline && groupProps2.outline.length > 0;
120624
120951
  const numericOutline = hasOutline ? groupProps2.outline.map((point6) => ({
120625
- x: distance19.parse(point6.x),
120626
- y: distance19.parse(point6.y)
120952
+ x: distance20.parse(point6.x),
120953
+ y: distance20.parse(point6.y)
120627
120954
  })) : void 0;
120628
120955
  const ctx = this.props;
120629
120956
  const anchorPosition = this._getGlobalPcbPositionBeforeLayout();
@@ -120661,8 +120988,8 @@ var Group5 = class extends NormalComponent {
120661
120988
  const hasExplicitPositioning = this._parsedProps.pcbX !== void 0 || this._parsedProps.pcbY !== void 0;
120662
120989
  if (hasOutline) {
120663
120990
  const numericOutline = props.outline.map((point6) => ({
120664
- x: distance19.parse(point6.x),
120665
- y: distance19.parse(point6.y)
120991
+ x: distance20.parse(point6.x),
120992
+ y: distance20.parse(point6.y)
120666
120993
  }));
120667
120994
  const outlineBounds = getBoundsFromPoints12(numericOutline);
120668
120995
  if (!outlineBounds) return;
@@ -121814,6 +122141,9 @@ var Group5 = class extends NormalComponent {
121814
122141
  const debug13 = Debug15("tscircuit:core:updatePcbTraceRender");
121815
122142
  debug13(`[${this.getString()}] updating...`);
121816
122143
  if (!this.isSubcircuit) return;
122144
+ if (this.root?.pcbDisabled) return;
122145
+ if (this.root?.pcbRoutingDisabled || this.getInheritedProperty("routingDisabled"))
122146
+ return;
121817
122147
  if (this._isInflatedFromCircuitJson) return;
121818
122148
  if (this._isLegacyAutorouterDisabled()) return;
121819
122149
  if (this._shouldRouteAsync() && this._hasTracesToRoute() && !this._hasStartedAsyncAutorouting) {
@@ -122577,8 +122907,8 @@ var Led_addPolarityFabricationSymbol = (led) => {
122577
122907
  const a2 = db2.pcb_port.getWhere({ source_port_id: anode.source_port_id });
122578
122908
  const k2 = db2.pcb_port.getWhere({ source_port_id: cathode.source_port_id });
122579
122909
  if (!a2 || !k2) return;
122580
- const distance27 = Math.hypot(k2.x - a2.x, k2.y - a2.y);
122581
- if (distance27 < 1e-6) return;
122910
+ const distance28 = Math.hypot(k2.x - a2.x, k2.y - a2.y);
122911
+ if (distance28 < 1e-6) return;
122582
122912
  const angle = Math.atan2(k2.y - a2.y, k2.x - a2.x);
122583
122913
  const frame = compose17(
122584
122914
  translate17((a2.x + k2.x) / 2, (a2.y + k2.y) / 2),
@@ -122592,10 +122922,10 @@ var Led_addPolarityFabricationSymbol = (led) => {
122592
122922
  };
122593
122923
  const notes = [];
122594
122924
  generatedNotes.set(led, notes);
122595
- const halfLength = Math.min(distance27 * 0.2, 0.4);
122925
+ const halfLength = Math.min(distance28 * 0.2, 0.4);
122596
122926
  const halfHeight = halfLength * 0.75;
122597
122927
  const routes = [
122598
- [point6(-distance27 / 2, 0), point6(-halfLength, 0)],
122928
+ [point6(-distance28 / 2, 0), point6(-halfLength, 0)],
122599
122929
  [
122600
122930
  point6(-halfLength, -halfHeight),
122601
122931
  point6(halfLength, 0),
@@ -122603,7 +122933,7 @@ var Led_addPolarityFabricationSymbol = (led) => {
122603
122933
  point6(-halfLength, -halfHeight)
122604
122934
  ],
122605
122935
  [point6(halfLength, -halfHeight), point6(halfLength, halfHeight)],
122606
- [point6(halfLength, 0), point6(distance27 / 2, 0)]
122936
+ [point6(halfLength, 0), point6(distance28 / 2, 0)]
122607
122937
  ];
122608
122938
  for (const route of routes) {
122609
122939
  notes.push(
@@ -124616,7 +124946,7 @@ var Board_doInitialPcbPlacementDesignRuleChecks = (board) => {
124616
124946
 
124617
124947
  // lib/components/normal-components/Board/board-castellated-hole.ts
124618
124948
  import {
124619
- distance as distance20
124949
+ distance as distance21
124620
124950
  } from "circuit-json";
124621
124951
  var CASTELLATED_HOLE_ENDPOINT_TOLERANCE_MM = 1e-6;
124622
124952
  var getConnectionTargets2 = (connectsTo) => {
@@ -124637,8 +124967,8 @@ var BoardCastellatedHole = class _BoardCastellatedHole extends PlatedHole {
124637
124967
  constructor(outlinePoint, outlinePointIndex) {
124638
124968
  const name = `castellated_hole_${outlinePointIndex + 1}`;
124639
124969
  const connectionTargets = getConnectionTargets2(outlinePoint.connectsTo);
124640
- const holeDiameter = distance20.parse(outlinePoint.holeDiameter);
124641
- const padDiameter = distance20.parse(outlinePoint.padDiameter);
124970
+ const holeDiameter = distance21.parse(outlinePoint.holeDiameter);
124971
+ const padDiameter = distance21.parse(outlinePoint.padDiameter);
124642
124972
  super({
124643
124973
  shape: "circle",
124644
124974
  holeDiameter,
@@ -125420,11 +125750,11 @@ var MountedBoard = class extends Subcircuit {
125420
125750
 
125421
125751
  // lib/components/normal-components/Panel.ts
125422
125752
  import { panelProps } from "@tscircuit/props";
125423
- import { distance as distance25 } from "circuit-json";
125753
+ import { distance as distance26 } from "circuit-json";
125424
125754
 
125425
125755
  // lib/components/normal-components/Subpanel.ts
125426
125756
  import { subpanelProps } from "@tscircuit/props";
125427
- import { distance as distance24 } from "circuit-json";
125757
+ import { distance as distance25 } from "circuit-json";
125428
125758
  import { compose as compose19, identity as identity11, translate as translate19 } from "transformation-matrix";
125429
125759
 
125430
125760
  // lib/utils/panels/generate-panel-tabs-and-mouse-bites.ts
@@ -125688,15 +126018,15 @@ function generatePanelOutlineRoutingCutouts(boards, options) {
125688
126018
  }
125689
126019
 
125690
126020
  // lib/utils/panels/pack-into-grid.ts
125691
- import { distance as distance23 } from "circuit-json";
126021
+ import { distance as distance24 } from "circuit-json";
125692
126022
 
125693
126023
  // lib/utils/panels/get-board-dimensions-from-props.ts
125694
126024
  import { getBoundsFromPoints as getBoundsFromPoints14 } from "@tscircuit/math-utils";
125695
- import { distance as distance21 } from "circuit-json";
126025
+ import { distance as distance23 } from "circuit-json";
125696
126026
  var getBoardDimensionsFromProps = (board) => {
125697
126027
  const props = board._parsedProps;
125698
- let width = props.width != null ? distance21.parse(props.width) : void 0;
125699
- let height = props.height != null ? distance21.parse(props.height) : void 0;
126028
+ let width = props.width != null ? distance23.parse(props.width) : void 0;
126029
+ let height = props.height != null ? distance23.parse(props.height) : void 0;
125700
126030
  if ((width === void 0 || height === void 0) && props.outline?.length) {
125701
126031
  const outlineBounds = getBoundsFromPoints14(props.outline);
125702
126032
  if (outlineBounds) {
@@ -125740,8 +126070,8 @@ function packIntoGrid({
125740
126070
  }
125741
126071
  let cols;
125742
126072
  let rows;
125743
- const minCellWidth = cellWidth ? distance23.parse(cellWidth) : 0;
125744
- const minCellHeight = cellHeight ? distance23.parse(cellHeight) : 0;
126073
+ const minCellWidth = cellWidth ? distance24.parse(cellWidth) : 0;
126074
+ const minCellHeight = cellHeight ? distance24.parse(cellHeight) : 0;
125745
126075
  if (col !== void 0) {
125746
126076
  cols = col;
125747
126077
  rows = row ?? Math.ceil(itemsWithDims.length / cols);
@@ -125840,8 +126170,8 @@ function getItemDimensions(item, db2) {
125840
126170
  const props = subpanel._parsedProps;
125841
126171
  if (props.width !== void 0 && props.height !== void 0) {
125842
126172
  return {
125843
- width: distance23.parse(props.width),
125844
- height: distance23.parse(props.height)
126173
+ width: distance24.parse(props.width),
126174
+ height: distance24.parse(props.height)
125845
126175
  };
125846
126176
  }
125847
126177
  const directBoards = subpanel._getDirectBoardChildren();
@@ -125868,7 +126198,7 @@ function getItemDimensions(item, db2) {
125868
126198
  return getBoardDimensionsFromProps(directBoards[0]);
125869
126199
  }
125870
126200
  if (subpanel._cachedGridWidth > 0 && subpanel._cachedGridHeight > 0) {
125871
- const edgePadding = distance23.parse(props.edgePadding ?? 5);
126201
+ const edgePadding = distance24.parse(props.edgePadding ?? 5);
125872
126202
  return {
125873
126203
  width: subpanel._cachedGridWidth + edgePadding * 2,
125874
126204
  height: subpanel._cachedGridHeight + edgePadding * 2
@@ -126026,17 +126356,17 @@ var Subpanel = class _Subpanel extends Group5 {
126026
126356
  edgePaddingTop: edgePaddingTopProp,
126027
126357
  edgePaddingBottom: edgePaddingBottomProp
126028
126358
  } = this._parsedProps;
126029
- const edgePadding = distance24.parse(edgePaddingProp ?? 5);
126030
- const edgePaddingLeft = distance24.parse(edgePaddingLeftProp ?? edgePadding);
126031
- const edgePaddingRight = distance24.parse(
126359
+ const edgePadding = distance25.parse(edgePaddingProp ?? 5);
126360
+ const edgePaddingLeft = distance25.parse(edgePaddingLeftProp ?? edgePadding);
126361
+ const edgePaddingRight = distance25.parse(
126032
126362
  edgePaddingRightProp ?? edgePadding
126033
126363
  );
126034
- const edgePaddingTop = distance24.parse(edgePaddingTopProp ?? edgePadding);
126035
- const edgePaddingBottom = distance24.parse(
126364
+ const edgePaddingTop = distance25.parse(edgePaddingTopProp ?? edgePadding);
126365
+ const edgePaddingBottom = distance25.parse(
126036
126366
  edgePaddingBottomProp ?? edgePadding
126037
126367
  );
126038
- const panelWidth = distance24.parse(this._parsedProps.width);
126039
- const panelHeight = distance24.parse(this._parsedProps.height);
126368
+ const panelWidth = distance25.parse(this._parsedProps.width);
126369
+ const panelHeight = distance25.parse(this._parsedProps.height);
126040
126370
  availablePanelWidth = panelWidth - edgePaddingLeft - edgePaddingRight;
126041
126371
  availablePanelHeight = panelHeight - edgePaddingTop - edgePaddingBottom;
126042
126372
  }
@@ -126111,8 +126441,8 @@ var Subpanel = class _Subpanel extends Group5 {
126111
126441
  if (!this.pcb_group_id) return;
126112
126442
  if (hasExplicitWidth && hasExplicitHeight) {
126113
126443
  db2.pcb_group.update(this.pcb_group_id, {
126114
- width: distance24.parse(this._parsedProps.width),
126115
- height: distance24.parse(this._parsedProps.height)
126444
+ width: distance25.parse(this._parsedProps.width),
126445
+ height: distance25.parse(this._parsedProps.height)
126116
126446
  });
126117
126447
  } else if (gridWidth > 0 || gridHeight > 0) {
126118
126448
  const {
@@ -126122,18 +126452,18 @@ var Subpanel = class _Subpanel extends Group5 {
126122
126452
  edgePaddingTop: edgePaddingTopProp,
126123
126453
  edgePaddingBottom: edgePaddingBottomProp
126124
126454
  } = this._parsedProps;
126125
- const edgePadding = distance24.parse(edgePaddingProp ?? 5);
126126
- const edgePaddingLeft = distance24.parse(edgePaddingLeftProp ?? edgePadding);
126127
- const edgePaddingRight = distance24.parse(
126455
+ const edgePadding = distance25.parse(edgePaddingProp ?? 5);
126456
+ const edgePaddingLeft = distance25.parse(edgePaddingLeftProp ?? edgePadding);
126457
+ const edgePaddingRight = distance25.parse(
126128
126458
  edgePaddingRightProp ?? edgePadding
126129
126459
  );
126130
- const edgePaddingTop = distance24.parse(edgePaddingTopProp ?? edgePadding);
126131
- const edgePaddingBottom = distance24.parse(
126460
+ const edgePaddingTop = distance25.parse(edgePaddingTopProp ?? edgePadding);
126461
+ const edgePaddingBottom = distance25.parse(
126132
126462
  edgePaddingBottomProp ?? edgePadding
126133
126463
  );
126134
126464
  db2.pcb_group.update(this.pcb_group_id, {
126135
- width: hasExplicitWidth ? distance24.parse(this._parsedProps.width) : gridWidth + edgePaddingLeft + edgePaddingRight,
126136
- height: hasExplicitHeight ? distance24.parse(this._parsedProps.height) : gridHeight + edgePaddingTop + edgePaddingBottom
126465
+ width: hasExplicitWidth ? distance25.parse(this._parsedProps.width) : gridWidth + edgePaddingLeft + edgePaddingRight,
126466
+ height: hasExplicitHeight ? distance25.parse(this._parsedProps.height) : gridHeight + edgePaddingTop + edgePaddingBottom
126137
126467
  });
126138
126468
  }
126139
126469
  }
@@ -126221,8 +126551,8 @@ var Panel = class extends Subpanel {
126221
126551
  const { db: db2 } = this.root;
126222
126552
  const props = this._parsedProps;
126223
126553
  const inserted = db2.pcb_panel.insert({
126224
- width: props.width !== void 0 ? distance25.parse(props.width) : 0,
126225
- height: props.height !== void 0 ? distance25.parse(props.height) : 0,
126554
+ width: props.width !== void 0 ? distance26.parse(props.width) : 0,
126555
+ height: props.height !== void 0 ? distance26.parse(props.height) : 0,
126226
126556
  thickness: 1.6,
126227
126557
  center: this._getGlobalPcbPositionBeforeLayout(),
126228
126558
  covered_with_solder_mask: !(props.noSolderMask ?? false)
@@ -126241,8 +126571,8 @@ var Panel = class extends Subpanel {
126241
126571
  if (!this.pcb_panel_id) return;
126242
126572
  if (hasExplicitWidth && hasExplicitHeight) {
126243
126573
  db2.pcb_panel.update(this.pcb_panel_id, {
126244
- width: distance25.parse(this._parsedProps.width),
126245
- height: distance25.parse(this._parsedProps.height)
126574
+ width: distance26.parse(this._parsedProps.width),
126575
+ height: distance26.parse(this._parsedProps.height)
126246
126576
  });
126247
126577
  } else if (gridWidth > 0 || gridHeight > 0) {
126248
126578
  const {
@@ -126252,18 +126582,18 @@ var Panel = class extends Subpanel {
126252
126582
  edgePaddingTop: edgePaddingTopProp,
126253
126583
  edgePaddingBottom: edgePaddingBottomProp
126254
126584
  } = this._parsedProps;
126255
- const edgePadding = distance25.parse(edgePaddingProp ?? 5);
126256
- const edgePaddingLeft = distance25.parse(edgePaddingLeftProp ?? edgePadding);
126257
- const edgePaddingRight = distance25.parse(
126585
+ const edgePadding = distance26.parse(edgePaddingProp ?? 5);
126586
+ const edgePaddingLeft = distance26.parse(edgePaddingLeftProp ?? edgePadding);
126587
+ const edgePaddingRight = distance26.parse(
126258
126588
  edgePaddingRightProp ?? edgePadding
126259
126589
  );
126260
- const edgePaddingTop = distance25.parse(edgePaddingTopProp ?? edgePadding);
126261
- const edgePaddingBottom = distance25.parse(
126590
+ const edgePaddingTop = distance26.parse(edgePaddingTopProp ?? edgePadding);
126591
+ const edgePaddingBottom = distance26.parse(
126262
126592
  edgePaddingBottomProp ?? edgePadding
126263
126593
  );
126264
126594
  db2.pcb_panel.update(this.pcb_panel_id, {
126265
- width: hasExplicitWidth ? distance25.parse(this._parsedProps.width) : gridWidth + edgePaddingLeft + edgePaddingRight,
126266
- height: hasExplicitHeight ? distance25.parse(this._parsedProps.height) : gridHeight + edgePaddingTop + edgePaddingBottom
126595
+ width: hasExplicitWidth ? distance26.parse(this._parsedProps.width) : gridWidth + edgePaddingLeft + edgePaddingRight,
126596
+ height: hasExplicitHeight ? distance26.parse(this._parsedProps.height) : gridHeight + edgePaddingTop + edgePaddingBottom
126267
126597
  });
126268
126598
  }
126269
126599
  }
@@ -126274,8 +126604,8 @@ var Panel = class extends Subpanel {
126274
126604
  const props = this._parsedProps;
126275
126605
  const currentPanel = db2.pcb_panel.get(this.pcb_panel_id);
126276
126606
  db2.pcb_panel.update(this.pcb_panel_id, {
126277
- width: props.width !== void 0 ? distance25.parse(props.width) : currentPanel?.width,
126278
- height: props.height !== void 0 ? distance25.parse(props.height) : currentPanel?.height,
126607
+ width: props.width !== void 0 ? distance26.parse(props.width) : currentPanel?.width,
126608
+ height: props.height !== void 0 ? distance26.parse(props.height) : currentPanel?.height,
126279
126609
  center: this._getGlobalPcbPositionBeforeLayout(),
126280
126610
  covered_with_solder_mask: !(props.noSolderMask ?? false)
126281
126611
  });
@@ -127881,9 +128211,9 @@ var resolvePcbDimensionOffsetDirection = ({
127881
128211
  }
127882
128212
  const dx2 = to.x - from.x;
127883
128213
  const dy2 = to.y - from.y;
127884
- const distance27 = Math.hypot(dx2, dy2);
127885
- if (offset === void 0 || distance27 === 0) return;
127886
- return { x: -dy2 / distance27, y: dx2 / distance27 };
128214
+ const distance28 = Math.hypot(dx2, dy2);
128215
+ if (offset === void 0 || distance28 === 0) return;
128216
+ return { x: -dy2 / distance28, y: dx2 / distance28 };
127887
128217
  };
127888
128218
 
127889
128219
  // lib/components/primitive-components/FabricationNoteDimension.ts
@@ -130978,7 +131308,7 @@ var SilkscreenGraphic = class extends PrimitiveComponent2 {
130978
131308
 
130979
131309
  // lib/components/primitive-components/Fiducial.ts
130980
131310
  import "zod";
130981
- import { distance as distance26 } from "circuit-json";
131311
+ import { distance as distance27 } from "circuit-json";
130982
131312
  import { fiducialProps as fiducialProps2 } from "@tscircuit/props";
130983
131313
  var Fiducial = class extends PrimitiveComponent2 {
130984
131314
  pcb_smtpad_id = null;
@@ -131003,15 +131333,15 @@ var Fiducial = class extends PrimitiveComponent2 {
131003
131333
  shape: "circle",
131004
131334
  x: position.x,
131005
131335
  y: position.y,
131006
- radius: distance26.parse(props.padDiameter) / 2,
131007
- soldermask_margin: props.soldermaskPullback ? distance26.parse(props.soldermaskPullback) : distance26.parse(props.padDiameter) / 2,
131336
+ radius: distance27.parse(props.padDiameter) / 2,
131337
+ soldermask_margin: props.soldermaskPullback ? distance27.parse(props.soldermaskPullback) : distance27.parse(props.padDiameter) / 2,
131008
131338
  is_covered_with_solder_mask: true
131009
131339
  });
131010
131340
  this.pcb_smtpad_id = pcb_smtpad.pcb_smtpad_id;
131011
131341
  }
131012
131342
  getPcbSize() {
131013
131343
  const { _parsedProps: props } = this;
131014
- const d2 = distance26.parse(props.padDiameter);
131344
+ const d2 = distance27.parse(props.padDiameter);
131015
131345
  return { width: d2, height: d2 };
131016
131346
  }
131017
131347
  _setPositionFromLayout(newCenter) {
@@ -135455,8 +135785,8 @@ function inferAssemblyCablePath({
135455
135785
  fromDirection,
135456
135786
  toDirection
135457
135787
  }) {
135458
- const distance27 = Math.hypot(to.x - from.x, to.y - from.y, to.z - from.z);
135459
- if (distance27 < 1e-6)
135788
+ const distance28 = Math.hypot(to.x - from.x, to.y - from.y, to.z - from.z);
135789
+ if (distance28 < 1e-6)
135460
135790
  throw new Error("Cable wire exits must be at different positions");
135461
135791
  const chord = vec37.fromValues(to.x - from.x, to.y - from.y, to.z - from.z);
135462
135792
  const routeNormal = vec37.cross(vec37.create(), chord, [
@@ -135468,7 +135798,7 @@ function inferAssemblyCablePath({
135468
135798
  vec37.cross(
135469
135799
  routeNormal,
135470
135800
  chord,
135471
- Math.abs(chord[2]) / distance27 > 0.95 ? [0, 1, 0] : [0, 0, 1]
135801
+ Math.abs(chord[2]) / distance28 > 0.95 ? [0, 1, 0] : [0, 0, 1]
135472
135802
  );
135473
135803
  }
135474
135804
  const archDirection = vec37.normalize(
@@ -135478,7 +135808,7 @@ function inferAssemblyCablePath({
135478
135808
  const archSide = from.z < 0 && to.z < 0 ? -1 : 1;
135479
135809
  if (archDirection[2] * archSide < 0)
135480
135810
  vec37.scale(archDirection, archDirection, -1);
135481
- const clearance = Math.min(25, Math.max(8, distance27 / 3));
135811
+ const clearance = Math.min(25, Math.max(8, distance28 / 3));
135482
135812
  const controlA = {
135483
135813
  x: from.x + fromDirection.x * clearance,
135484
135814
  y: from.y + fromDirection.y * clearance,
@@ -135499,7 +135829,7 @@ function inferAssemblyCablePath({
135499
135829
  ];
135500
135830
  for (let i2 = 1; i2 < 48; i2++) {
135501
135831
  const t48 = i2 / 48, u2 = 1 - t48;
135502
- const arch = Math.sin(Math.PI * t48) ** 2 * Math.min(12, distance27 * 0.15);
135832
+ const arch = Math.sin(Math.PI * t48) ** 2 * Math.min(12, distance28 * 0.15);
135503
135833
  path.push({
135504
135834
  x: u2 ** 3 * from.x + 3 * u2 ** 2 * t48 * controlA.x + 3 * u2 * t48 ** 2 * controlB.x + t48 ** 3 * to.x + archDirection[0] * arch,
135505
135835
  y: u2 ** 3 * from.y + 3 * u2 ** 2 * t48 * controlA.y + 3 * u2 * t48 ** 2 * controlB.y + t48 ** 3 * to.y + archDirection[1] * arch,