@tscircuit/core 0.0.1417 → 0.0.1418

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -2201,6 +2201,7 @@ declare class NormalComponent<ZodProps extends z.ZodType = any, PortNames extend
2201
2201
  pcb_missing_footprint_error_id?: string;
2202
2202
  _hasStartedFootprintUrlLoad: boolean;
2203
2203
  _hasStartedSupplierFootprintMismatchWarningCheck: boolean;
2204
+ _hasInflatedCircuitJsonSymbol: boolean;
2204
2205
  private _invalidFootprintPropMessages;
2205
2206
  _invalidPinLabelMessages: string[];
2206
2207
  _impliedFootprintPinLabels?: Record<string, string | string[]>;
@@ -2238,6 +2239,7 @@ declare class NormalComponent<ZodProps extends z.ZodType = any, PortNames extend
2238
2239
  _getImpliedFootprintString(): string | null;
2239
2240
  resolveFootprint(): any;
2240
2241
  _addChildrenFromStringFootprint(): void;
2242
+ _addChildrenFromCircuitJsonSymbol(): void;
2241
2243
  get portMap(): PortMap<PortNames>;
2242
2244
  getInstanceForReactElement(element: ReactElement): NormalComponent | null;
2243
2245
  doInitialSourceRender(): void;
@@ -61623,7 +61625,7 @@ declare class VoltageSource extends NormalComponent<typeof voltageSourceProps, "
61623
61625
  frequency?: number | undefined;
61624
61626
  voltage?: number | undefined;
61625
61627
  peakToPeakVoltage?: number | undefined;
61626
- waveShape?: "square" | "sinewave" | "triangle" | "sawtooth" | undefined;
61628
+ waveShape?: "square" | "triangle" | "sawtooth" | "sinewave" | undefined;
61627
61629
  phase?: number | undefined;
61628
61630
  dutyCycle?: number | undefined;
61629
61631
  pulseDelay?: number | undefined;
@@ -62215,7 +62217,7 @@ declare class VoltageSource extends NormalComponent<typeof voltageSourceProps, "
62215
62217
  frequency?: string | number | undefined;
62216
62218
  voltage?: string | number | undefined;
62217
62219
  peakToPeakVoltage?: string | number | undefined;
62218
- waveShape?: "square" | "sinewave" | "triangle" | "sawtooth" | undefined;
62220
+ waveShape?: "square" | "triangle" | "sawtooth" | "sinewave" | undefined;
62219
62221
  phase?: string | number | undefined;
62220
62222
  dutyCycle?: string | number | undefined;
62221
62223
  pulseDelay?: string | number | undefined;
@@ -66187,7 +66189,7 @@ declare class CurrentSource extends NormalComponent<typeof currentSourceProps, "
66187
66189
  schSheetName?: string | undefined;
66188
66190
  connections?: Partial<Record<"pin1" | "pin2" | "pos" | "neg", string | readonly string[] | string[]>> | undefined;
66189
66191
  frequency?: number | undefined;
66190
- waveShape?: "square" | "sinewave" | "triangle" | "sawtooth" | undefined;
66192
+ waveShape?: "square" | "triangle" | "sawtooth" | "sinewave" | undefined;
66191
66193
  phase?: number | undefined;
66192
66194
  dutyCycle?: number | undefined;
66193
66195
  current?: number | undefined;
@@ -66774,7 +66776,7 @@ declare class CurrentSource extends NormalComponent<typeof currentSourceProps, "
66774
66776
  schSheetName?: string | undefined;
66775
66777
  connections?: Partial<Record<"pin1" | "pin2" | "pos" | "neg", string | readonly string[] | string[]>> | undefined;
66776
66778
  frequency?: string | number | undefined;
66777
- waveShape?: "square" | "sinewave" | "triangle" | "sawtooth" | undefined;
66779
+ waveShape?: "square" | "triangle" | "sawtooth" | "sinewave" | undefined;
66778
66780
  phase?: string | number | undefined;
66779
66781
  dutyCycle?: string | number | undefined;
66780
66782
  current?: string | number | undefined;
@@ -76051,10 +76053,12 @@ declare class AutoroutingPhase extends PrimitiveComponent<typeof autoroutingPhas
76051
76053
  minViaHoleDiameter: zod.ZodOptional<zod.ZodEffects<zod.ZodUnion<[zod.ZodString, zod.ZodNumber]>, number, string | number>>;
76052
76054
  minViaPadDiameter: zod.ZodOptional<zod.ZodEffects<zod.ZodUnion<[zod.ZodString, zod.ZodNumber]>, number, string | number>>;
76053
76055
  key: zod.ZodOptional<zod.ZodAny>;
76056
+ name: zod.ZodOptional<zod.ZodString>;
76054
76057
  autorouter: zod.ZodOptional<zod.ZodType<_tscircuit_props.AutorouterProp, zod.ZodTypeDef, _tscircuit_props.AutorouterProp>>;
76055
76058
  phaseIndex: zod.ZodOptional<zod.ZodNumber>;
76056
76059
  }, "strip", zod.ZodTypeAny, {
76057
76060
  key?: any;
76061
+ name?: string | undefined;
76058
76062
  connections?: string[] | undefined;
76059
76063
  minTraceWidth?: number | undefined;
76060
76064
  minViaHoleEdgeToViaHoleEdgeClearance?: number | undefined;
@@ -76078,6 +76082,7 @@ declare class AutoroutingPhase extends PrimitiveComponent<typeof autoroutingPhas
76078
76082
  reroute?: boolean | undefined;
76079
76083
  }, {
76080
76084
  key?: any;
76085
+ name?: string | undefined;
76081
76086
  connections?: string[] | undefined;
76082
76087
  minTraceWidth?: string | number | undefined;
76083
76088
  minViaHoleEdgeToViaHoleEdgeClearance?: string | number | undefined;
@@ -76101,6 +76106,7 @@ declare class AutoroutingPhase extends PrimitiveComponent<typeof autoroutingPhas
76101
76106
  reroute?: boolean | undefined;
76102
76107
  }>, {
76103
76108
  key?: any;
76109
+ name?: string | undefined;
76104
76110
  connections?: string[] | undefined;
76105
76111
  minTraceWidth?: number | undefined;
76106
76112
  minViaHoleEdgeToViaHoleEdgeClearance?: number | undefined;
@@ -76124,6 +76130,7 @@ declare class AutoroutingPhase extends PrimitiveComponent<typeof autoroutingPhas
76124
76130
  reroute?: boolean | undefined;
76125
76131
  }, {
76126
76132
  key?: any;
76133
+ name?: string | undefined;
76127
76134
  connections?: string[] | undefined;
76128
76135
  minTraceWidth?: string | number | undefined;
76129
76136
  minViaHoleEdgeToViaHoleEdgeClearance?: string | number | undefined;
package/dist/index.js CHANGED
@@ -10401,8 +10401,8 @@ var createComponentsFromCircuitJson = ({
10401
10401
  schematicComponentsByImportedId.set(elm.schematic_component_id, elm);
10402
10402
  }
10403
10403
  const addSchematicPrimitive = (elm, primitive) => {
10404
- const schematicSymbolId = getSchematicSymbolId(elm);
10405
- const parentSymbol = schematicSymbolId ? schematicSymbolsByImportedId.get(schematicSymbolId) : void 0;
10404
+ const schematicSymbolId = getSchematicSymbolId(elm) ?? ("schematic_component_id" in elm && typeof elm.schematic_component_id === "string" ? schematicComponentsByImportedId.get(elm.schematic_component_id)?.schematic_symbol_id : void 0);
10405
+ const parentSymbol = typeof schematicSymbolId === "string" ? schematicSymbolsByImportedId.get(schematicSymbolId) : void 0;
10406
10406
  if (parentSymbol) {
10407
10407
  parentSymbol.add(primitive);
10408
10408
  } else {
@@ -11592,6 +11592,151 @@ var getNumericSchPinStyle = (pinStyles, pinLabels) => {
11592
11592
  return numericPinStyles;
11593
11593
  };
11594
11594
 
11595
+ // lib/utils/schematic/isCircuitJsonSymbol.ts
11596
+ var isSymbolElementType = (elementType) => elementType === "schematic_symbol" || elementType === "schematic_component" || elementType === "schematic_line" || elementType === "schematic_rect" || elementType === "schematic_circle" || elementType === "schematic_arc" || elementType === "schematic_text" || elementType === "schematic_path";
11597
+ var isCircuitJsonSymbol = (circuitJson) => {
11598
+ return Array.isArray(circuitJson) && circuitJson.length > 0 && circuitJson.some((element) => isSymbolElementType(element.type));
11599
+ };
11600
+
11601
+ // lib/utils/schematic/normalizeSchematicSymbolCircuitJson.ts
11602
+ var isFinitePoint = (point6) => typeof point6?.x === "number" && Number.isFinite(point6.x) && typeof point6.y === "number" && Number.isFinite(point6.y);
11603
+ var translatePoint = (point6, origin) => ({
11604
+ x: point6.x - origin.x,
11605
+ y: point6.y - origin.y
11606
+ });
11607
+ var isTranslatableSchematicElement = (element) => element.type === "schematic_component" || element.type === "schematic_port" || element.type === "schematic_line" || element.type === "schematic_rect" || element.type === "schematic_circle" || element.type === "schematic_arc" || element.type === "schematic_text" || element.type === "schematic_path";
11608
+ var getNormalizationOrigin = (symbolCircuitJson) => {
11609
+ const primarySchematicComponent = symbolCircuitJson.find(
11610
+ (element) => element.type === "schematic_component" && isFinitePoint(element.center)
11611
+ );
11612
+ if (primarySchematicComponent) {
11613
+ return primarySchematicComponent.center;
11614
+ }
11615
+ const schematicElements = symbolCircuitJson.filter(
11616
+ isTranslatableSchematicElement
11617
+ );
11618
+ if (schematicElements.length === 0) return null;
11619
+ const bounds = getBoundsForSchematic(schematicElements);
11620
+ if (!Number.isFinite(bounds.minX) || !Number.isFinite(bounds.maxX) || !Number.isFinite(bounds.minY) || !Number.isFinite(bounds.maxY)) {
11621
+ return null;
11622
+ }
11623
+ return {
11624
+ x: (bounds.minX + bounds.maxX) / 2,
11625
+ y: (bounds.minY + bounds.maxY) / 2
11626
+ };
11627
+ };
11628
+ var translateSchematicElement = (element, origin) => {
11629
+ switch (element.type) {
11630
+ case "schematic_component":
11631
+ case "schematic_port":
11632
+ case "schematic_rect":
11633
+ case "schematic_circle":
11634
+ case "schematic_arc":
11635
+ return isFinitePoint(element.center) ? {
11636
+ ...element,
11637
+ center: translatePoint(element.center, origin)
11638
+ } : element;
11639
+ case "schematic_line":
11640
+ return {
11641
+ ...element,
11642
+ x1: element.x1 - origin.x,
11643
+ y1: element.y1 - origin.y,
11644
+ x2: element.x2 - origin.x,
11645
+ y2: element.y2 - origin.y
11646
+ };
11647
+ case "schematic_text":
11648
+ return isFinitePoint(element.position) ? {
11649
+ ...element,
11650
+ position: translatePoint(element.position, origin)
11651
+ } : element;
11652
+ case "schematic_path":
11653
+ return {
11654
+ ...element,
11655
+ points: element.points.map((point6) => translatePoint(point6, origin))
11656
+ };
11657
+ default:
11658
+ return element;
11659
+ }
11660
+ };
11661
+ var normalizeSchematicSymbolCircuitJson = (symbolCircuitJson) => {
11662
+ const origin = getNormalizationOrigin(symbolCircuitJson);
11663
+ if (!origin) return [...symbolCircuitJson];
11664
+ if (origin.x === 0 && origin.y === 0) {
11665
+ return [...symbolCircuitJson];
11666
+ }
11667
+ return symbolCircuitJson.map(
11668
+ (element) => translateSchematicElement(element, origin)
11669
+ );
11670
+ };
11671
+
11672
+ // lib/utils/schematic/selectSymbolCircuitJson.ts
11673
+ var isImportedSymbolPrimitive = (elm) => elm.type === "schematic_line" || elm.type === "schematic_rect" || elm.type === "schematic_circle" || elm.type === "schematic_arc" || elm.type === "schematic_text" || elm.type === "schematic_path";
11674
+ var getStringProp = (elm, propName) => {
11675
+ if (!(propName in elm)) return void 0;
11676
+ const rawProp = elm[propName];
11677
+ return typeof rawProp === "string" ? rawProp : void 0;
11678
+ };
11679
+ var selectSymbolCircuitJson = (circuitJson) => {
11680
+ const schematicSymbols = circuitJson.filter(
11681
+ (elm) => elm.type === "schematic_symbol"
11682
+ );
11683
+ const schematicComponents = circuitJson.filter(
11684
+ (elm) => elm.type === "schematic_component"
11685
+ );
11686
+ const primarySymbolId = schematicComponents.find(
11687
+ (elm) => typeof elm.schematic_symbol_id === "string"
11688
+ )?.schematic_symbol_id ?? schematicSymbols[0]?.schematic_symbol_id;
11689
+ const primaryComponent = (primarySymbolId ? schematicComponents.find(
11690
+ (elm) => elm.schematic_symbol_id === primarySymbolId
11691
+ ) : void 0) ?? schematicComponents[0];
11692
+ const primaryComponentId = primaryComponent?.schematic_component_id;
11693
+ const primarySourceComponentId = typeof primaryComponent?.source_component_id === "string" ? primaryComponent.source_component_id : void 0;
11694
+ const primarySymbol = (primarySymbolId ? schematicSymbols.find(
11695
+ (elm) => elm.schematic_symbol_id === primarySymbolId
11696
+ ) : void 0) ?? schematicSymbols[0];
11697
+ const relatedSourcePortIds = /* @__PURE__ */ new Set();
11698
+ const selected = /* @__PURE__ */ new Set();
11699
+ const selectedElements = [];
11700
+ const add = (elm) => {
11701
+ if (!elm || selected.has(elm)) return;
11702
+ selected.add(elm);
11703
+ selectedElements.push(elm);
11704
+ };
11705
+ add(primarySymbol);
11706
+ add(primaryComponent);
11707
+ for (const elm of circuitJson) {
11708
+ if (elm.type !== "schematic_port") continue;
11709
+ if (!primaryComponentId || elm.schematic_component_id !== primaryComponentId) {
11710
+ continue;
11711
+ }
11712
+ add(elm);
11713
+ if (typeof elm.source_port_id === "string") {
11714
+ relatedSourcePortIds.add(elm.source_port_id);
11715
+ }
11716
+ }
11717
+ for (const elm of circuitJson) {
11718
+ if (!isImportedSymbolPrimitive(elm)) continue;
11719
+ const schematicSymbolId = getStringProp(elm, "schematic_symbol_id");
11720
+ const schematicComponentId = getStringProp(elm, "schematic_component_id");
11721
+ const isRelatedPrimitive = primarySymbolId && schematicSymbolId === primarySymbolId || primaryComponentId && schematicComponentId === primaryComponentId || !primarySymbolId && !primaryComponentId;
11722
+ if (isRelatedPrimitive) {
11723
+ add(elm);
11724
+ }
11725
+ }
11726
+ for (const elm of circuitJson) {
11727
+ if (elm.type !== "source_port") continue;
11728
+ if (relatedSourcePortIds.has(elm.source_port_id) || primarySourceComponentId && elm.source_component_id === primarySourceComponentId) {
11729
+ add(elm);
11730
+ }
11731
+ }
11732
+ if (selectedElements.length > 0) {
11733
+ return selectedElements;
11734
+ }
11735
+ return circuitJson.filter(
11736
+ (elm) => elm.type === "schematic_symbol" || elm.type === "schematic_component" || elm.type === "schematic_port" || isImportedSymbolPrimitive(elm)
11737
+ );
11738
+ };
11739
+
11595
11740
  // lib/components/base-components/NormalComponent/NormalComponent.ts
11596
11741
  import {
11597
11742
  isValidElement as isReactElement3,
@@ -11983,63 +12128,6 @@ var Footprint = class extends PrimitiveComponent2 {
11983
12128
  }
11984
12129
  };
11985
12130
 
11986
- // lib/components/base-components/NormalComponent/NormalComponent_doInitialCheckRefDesConvention.ts
11987
- var defaultExpectedPrefixesByFtype = {
11988
- simple_ammeter: ["A"],
11989
- simple_battery: ["B", "BT"],
11990
- simple_capacitor: ["C"],
11991
- simple_chip: ["U", "IC"],
11992
- simple_connector: ["J", "P", "CONN"],
11993
- simple_crystal: ["Y", "X"],
11994
- simple_current_source: ["I", "IS"],
11995
- simple_diode: ["D"],
11996
- simple_fuse: ["F"],
11997
- simple_inductor: ["L", "FB"],
11998
- simple_interconnect: ["ICN"],
11999
- simple_led: ["D", "LED"],
12000
- simple_mosfet: ["Q"],
12001
- simple_op_amp: ["U", "IC"],
12002
- simple_pin_header: ["J", "P", "JP"],
12003
- simple_pinout: ["J", "P"],
12004
- simple_potentiometer: ["RV", "RP"],
12005
- simple_power_source: ["B", "BT", "V", "VS"],
12006
- simple_push_button: ["SW", "S"],
12007
- simple_resistor: ["R"],
12008
- simple_resonator: ["Y", "X"],
12009
- simple_switch: ["SW", "S"],
12010
- simple_test_point: ["TP"],
12011
- simple_transistor: ["Q"],
12012
- simple_voltage_probe: ["VP"],
12013
- simple_voltage_source: ["V", "VS"]
12014
- };
12015
- var getDefaultExpectedRefDesPrefixesForFtype = (ftype) => {
12016
- if (!ftype) return void 0;
12017
- return defaultExpectedPrefixesByFtype[ftype];
12018
- };
12019
- var getRefDesPrefix = (refDes) => refDes.match(/^[A-Za-z]+/)?.[0]?.toUpperCase();
12020
- var NormalComponent_doInitialCheckRefDesConvention = (component) => {
12021
- const { db } = component.root;
12022
- if (!component.source_component_id) return;
12023
- const sourceComponent = db.source_component.get(component.source_component_id);
12024
- if (!sourceComponent?.name || !sourceComponent.ftype) return;
12025
- const expectedPrefixes = component.getRefDesPrefixes();
12026
- if (!expectedPrefixes || expectedPrefixes.length === 0) return;
12027
- const actualPrefix = getRefDesPrefix(sourceComponent.name);
12028
- if (actualPrefix && expectedPrefixes.includes(actualPrefix)) return;
12029
- const expectedPrefixMessage = expectedPrefixes.length === 1 ? expectedPrefixes[0] : `one of ${expectedPrefixes.join(", ")}`;
12030
- db.insert({
12031
- type: "source_refdes_convention_warning",
12032
- warning_type: "source_refdes_convention_warning",
12033
- message: `Component ${sourceComponent.name} has ftype="${sourceComponent.ftype}" but reference designator should start with ${expectedPrefixMessage}`,
12034
- source_component_id: sourceComponent.source_component_id,
12035
- refdes: sourceComponent.name,
12036
- source_component_ftype: sourceComponent.ftype,
12037
- expected_prefixes: expectedPrefixes,
12038
- actual_prefix: actualPrefix,
12039
- subcircuit_id: sourceComponent.subcircuit_id
12040
- });
12041
- };
12042
-
12043
12131
  // lib/components/base-components/NormalComponent/NormalComponent__getMinimumFlexContainerSize.ts
12044
12132
  import { getBoundsFromPoints as getBoundsFromPoints2 } from "@tscircuit/math-utils";
12045
12133
  var NormalComponent__getMinimumFlexContainerSize = (component) => {
@@ -12102,6 +12190,63 @@ var NormalComponent__repositionOnPcb = (component, position) => {
12102
12190
  );
12103
12191
  };
12104
12192
 
12193
+ // lib/components/base-components/NormalComponent/NormalComponent_doInitialCheckRefDesConvention.ts
12194
+ var defaultExpectedPrefixesByFtype = {
12195
+ simple_ammeter: ["A"],
12196
+ simple_battery: ["B", "BT"],
12197
+ simple_capacitor: ["C"],
12198
+ simple_chip: ["U", "IC"],
12199
+ simple_connector: ["J", "P", "CONN"],
12200
+ simple_crystal: ["Y", "X"],
12201
+ simple_current_source: ["I", "IS"],
12202
+ simple_diode: ["D"],
12203
+ simple_fuse: ["F"],
12204
+ simple_inductor: ["L", "FB"],
12205
+ simple_interconnect: ["ICN"],
12206
+ simple_led: ["D", "LED"],
12207
+ simple_mosfet: ["Q"],
12208
+ simple_op_amp: ["U", "IC"],
12209
+ simple_pin_header: ["J", "P", "JP"],
12210
+ simple_pinout: ["J", "P"],
12211
+ simple_potentiometer: ["RV", "RP"],
12212
+ simple_power_source: ["B", "BT", "V", "VS"],
12213
+ simple_push_button: ["SW", "S"],
12214
+ simple_resistor: ["R"],
12215
+ simple_resonator: ["Y", "X"],
12216
+ simple_switch: ["SW", "S"],
12217
+ simple_test_point: ["TP"],
12218
+ simple_transistor: ["Q"],
12219
+ simple_voltage_probe: ["VP"],
12220
+ simple_voltage_source: ["V", "VS"]
12221
+ };
12222
+ var getDefaultExpectedRefDesPrefixesForFtype = (ftype) => {
12223
+ if (!ftype) return void 0;
12224
+ return defaultExpectedPrefixesByFtype[ftype];
12225
+ };
12226
+ var getRefDesPrefix = (refDes) => refDes.match(/^[A-Za-z]+/)?.[0]?.toUpperCase();
12227
+ var NormalComponent_doInitialCheckRefDesConvention = (component) => {
12228
+ const { db } = component.root;
12229
+ if (!component.source_component_id) return;
12230
+ const sourceComponent = db.source_component.get(component.source_component_id);
12231
+ if (!sourceComponent?.name || !sourceComponent.ftype) return;
12232
+ const expectedPrefixes = component.getRefDesPrefixes();
12233
+ if (!expectedPrefixes || expectedPrefixes.length === 0) return;
12234
+ const actualPrefix = getRefDesPrefix(sourceComponent.name);
12235
+ if (actualPrefix && expectedPrefixes.includes(actualPrefix)) return;
12236
+ const expectedPrefixMessage = expectedPrefixes.length === 1 ? expectedPrefixes[0] : `one of ${expectedPrefixes.join(", ")}`;
12237
+ db.insert({
12238
+ type: "source_refdes_convention_warning",
12239
+ warning_type: "source_refdes_convention_warning",
12240
+ message: `Component ${sourceComponent.name} has ftype="${sourceComponent.ftype}" but reference designator should start with ${expectedPrefixMessage}`,
12241
+ source_component_id: sourceComponent.source_component_id,
12242
+ refdes: sourceComponent.name,
12243
+ source_component_ftype: sourceComponent.ftype,
12244
+ expected_prefixes: expectedPrefixes,
12245
+ actual_prefix: actualPrefix,
12246
+ subcircuit_id: sourceComponent.subcircuit_id
12247
+ });
12248
+ };
12249
+
12105
12250
  // lib/components/base-components/NormalComponent/NormalComponent_doInitialPcbComponentAnchorAlignment.ts
12106
12251
  function NormalComponent_doInitialPcbComponentAnchorAlignment(component) {
12107
12252
  if (component.root?.pcbDisabled) return;
@@ -12510,6 +12655,79 @@ function NormalComponent_doInitialResolveFootprintPinLabels(component) {
12510
12655
  }
12511
12656
  }
12512
12657
 
12658
+ // lib/components/base-components/NormalComponent/NormalComponent_doInitialSchematicComponentRender.ts
12659
+ import { schematic_manual_edit_conflict_warning } from "circuit-json";
12660
+ import { isValidElement as isReactElement2 } from "react";
12661
+ function NormalComponent_doInitialSchematicComponentRender(component) {
12662
+ if (component.root?.schematicDisabled) return;
12663
+ if (component.getCollapsedSchematicBoxAncestor()) return;
12664
+ const { db } = component.root;
12665
+ if (component._invalidPinLabelMessages?.length && component.root?.db) {
12666
+ for (const message of component._invalidPinLabelMessages) {
12667
+ let property_name = "pinLabels";
12668
+ const match = message.match(/^Invalid pin label:\s*([^=]+)=\s*'([^']+)'/);
12669
+ if (match) {
12670
+ const label = match[2];
12671
+ property_name = `pinLabels['${label}']`;
12672
+ }
12673
+ component.root.db.source_property_ignored_warning.insert({
12674
+ source_component_id: component.source_component_id,
12675
+ property_name,
12676
+ message,
12677
+ error_type: "source_property_ignored_warning"
12678
+ });
12679
+ }
12680
+ }
12681
+ if (component._parsedProps.schPinSpacing !== void 0 && component.root?.db) {
12682
+ component.root.db.source_property_ignored_warning.insert({
12683
+ source_component_id: component.source_component_id,
12684
+ property_name: "schPinSpacing",
12685
+ error_type: "source_property_ignored_warning",
12686
+ message: "schPinSpacing is deprecated and will be ignored. Pin spacing is always 0.2."
12687
+ });
12688
+ }
12689
+ const { schematicSymbolName } = component.config;
12690
+ const { _parsedProps: props } = component;
12691
+ const hasSymbolChild = component.children.some(
12692
+ (c) => c.componentName === "Symbol"
12693
+ );
12694
+ if (props.symbol && isReactElement2(props.symbol) || hasSymbolChild) {
12695
+ component._doInitialSchematicComponentRenderWithReactSymbol(props.symbol);
12696
+ } else if (schematicSymbolName) {
12697
+ component._doInitialSchematicComponentRenderWithSymbol();
12698
+ } else {
12699
+ const dimensions = component._getSchematicBoxDimensions();
12700
+ if (dimensions) {
12701
+ component._doInitialSchematicComponentRenderWithSchematicBoxDimensions();
12702
+ }
12703
+ }
12704
+ const manualPlacement = component.getSubcircuit()?._getSchematicManualPlacementForComponent(component);
12705
+ if (component.schematic_component_id && (component.props.schX !== void 0 || component.props.schY !== void 0) && !!manualPlacement) {
12706
+ if (!component.schematic_component_id) {
12707
+ return;
12708
+ }
12709
+ const warning = schematic_manual_edit_conflict_warning.parse({
12710
+ type: "schematic_manual_edit_conflict_warning",
12711
+ schematic_manual_edit_conflict_warning_id: `schematic_manual_edit_conflict_${component.source_component_id}`,
12712
+ message: `${component.getString()} has both manual placement and prop coordinates. schX and schY will be used. Remove schX/schY or clear the manual placement.`,
12713
+ schematic_component_id: component.schematic_component_id,
12714
+ source_component_id: component.source_component_id,
12715
+ subcircuit_id: component.getSubcircuit()?.subcircuit_id
12716
+ });
12717
+ db.schematic_manual_edit_conflict_warning.insert(warning);
12718
+ }
12719
+ const schSheetName = component._parsedProps?.schSheetName ?? component.props.schSheetName;
12720
+ if (schSheetName && component.source_component_id && !component._resolveSchematicSheetId()) {
12721
+ db.source_property_ignored_warning.insert({
12722
+ source_component_id: component.source_component_id,
12723
+ property_name: "schSheetName",
12724
+ error_type: "source_property_ignored_warning",
12725
+ subcircuit_id: component.getSubcircuit()?.subcircuit_id ?? void 0,
12726
+ message: `${component.getString()} references schSheetName "${schSheetName}", which does not match any schematic sheet and will be ignored.`
12727
+ });
12728
+ }
12729
+ }
12730
+
12513
12731
  // lib/components/base-components/NormalComponent/utils/getPcbTextBounds.ts
12514
12732
  function getPcbTextBounds(text) {
12515
12733
  const fontSize = text.font_size;
@@ -12822,79 +13040,6 @@ function NormalComponent_doInitialSupplierFootprintMismatchWarning(component) {
12822
13040
  });
12823
13041
  }
12824
13042
 
12825
- // lib/components/base-components/NormalComponent/NormalComponent_doInitialSchematicComponentRender.ts
12826
- import { schematic_manual_edit_conflict_warning } from "circuit-json";
12827
- import { isValidElement as isReactElement2 } from "react";
12828
- function NormalComponent_doInitialSchematicComponentRender(component) {
12829
- if (component.root?.schematicDisabled) return;
12830
- if (component.getCollapsedSchematicBoxAncestor()) return;
12831
- const { db } = component.root;
12832
- if (component._invalidPinLabelMessages?.length && component.root?.db) {
12833
- for (const message of component._invalidPinLabelMessages) {
12834
- let property_name = "pinLabels";
12835
- const match = message.match(/^Invalid pin label:\s*([^=]+)=\s*'([^']+)'/);
12836
- if (match) {
12837
- const label = match[2];
12838
- property_name = `pinLabels['${label}']`;
12839
- }
12840
- component.root.db.source_property_ignored_warning.insert({
12841
- source_component_id: component.source_component_id,
12842
- property_name,
12843
- message,
12844
- error_type: "source_property_ignored_warning"
12845
- });
12846
- }
12847
- }
12848
- if (component._parsedProps.schPinSpacing !== void 0 && component.root?.db) {
12849
- component.root.db.source_property_ignored_warning.insert({
12850
- source_component_id: component.source_component_id,
12851
- property_name: "schPinSpacing",
12852
- error_type: "source_property_ignored_warning",
12853
- message: "schPinSpacing is deprecated and will be ignored. Pin spacing is always 0.2."
12854
- });
12855
- }
12856
- const { schematicSymbolName } = component.config;
12857
- const { _parsedProps: props } = component;
12858
- const hasSymbolChild = component.children.some(
12859
- (c) => c.componentName === "Symbol"
12860
- );
12861
- if (props.symbol && isReactElement2(props.symbol) || hasSymbolChild) {
12862
- component._doInitialSchematicComponentRenderWithReactSymbol(props.symbol);
12863
- } else if (schematicSymbolName) {
12864
- component._doInitialSchematicComponentRenderWithSymbol();
12865
- } else {
12866
- const dimensions = component._getSchematicBoxDimensions();
12867
- if (dimensions) {
12868
- component._doInitialSchematicComponentRenderWithSchematicBoxDimensions();
12869
- }
12870
- }
12871
- const manualPlacement = component.getSubcircuit()?._getSchematicManualPlacementForComponent(component);
12872
- if (component.schematic_component_id && (component.props.schX !== void 0 || component.props.schY !== void 0) && !!manualPlacement) {
12873
- if (!component.schematic_component_id) {
12874
- return;
12875
- }
12876
- const warning = schematic_manual_edit_conflict_warning.parse({
12877
- type: "schematic_manual_edit_conflict_warning",
12878
- schematic_manual_edit_conflict_warning_id: `schematic_manual_edit_conflict_${component.source_component_id}`,
12879
- message: `${component.getString()} has both manual placement and prop coordinates. schX and schY will be used. Remove schX/schY or clear the manual placement.`,
12880
- schematic_component_id: component.schematic_component_id,
12881
- source_component_id: component.source_component_id,
12882
- subcircuit_id: component.getSubcircuit()?.subcircuit_id
12883
- });
12884
- db.schematic_manual_edit_conflict_warning.insert(warning);
12885
- }
12886
- const schSheetName = component._parsedProps?.schSheetName ?? component.props.schSheetName;
12887
- if (schSheetName && component.source_component_id && !component._resolveSchematicSheetId()) {
12888
- db.source_property_ignored_warning.insert({
12889
- source_component_id: component.source_component_id,
12890
- property_name: "schSheetName",
12891
- error_type: "source_property_ignored_warning",
12892
- subcircuit_id: component.getSubcircuit()?.subcircuit_id ?? void 0,
12893
- message: `${component.getString()} references schSheetName "${schSheetName}", which does not match any schematic sheet and will be ignored.`
12894
- });
12895
- }
12896
- }
12897
-
12898
13043
  // lib/components/base-components/NormalComponent/utils/canMergePortDefinitions.ts
12899
13044
  var canMergePortDefinitions = (a, b) => {
12900
13045
  const aPinNumber = a._parsedProps.pinNumber;
@@ -13084,6 +13229,7 @@ var NormalComponent3 = class extends PrimitiveComponent2 {
13084
13229
  pcb_missing_footprint_error_id;
13085
13230
  _hasStartedFootprintUrlLoad = false;
13086
13231
  _hasStartedSupplierFootprintMismatchWarningCheck = false;
13232
+ _hasInflatedCircuitJsonSymbol = false;
13087
13233
  _invalidFootprintPropMessages = [];
13088
13234
  _invalidPinLabelMessages = [];
13089
13235
  _impliedFootprintPinLabels;
@@ -13131,6 +13277,7 @@ var NormalComponent3 = class extends PrimitiveComponent2 {
13131
13277
  }
13132
13278
  this._invalidPinLabelMessages = invalidPinLabelsMessages;
13133
13279
  this._addChildrenFromStringFootprint();
13280
+ this._addChildrenFromCircuitJsonSymbol();
13134
13281
  this.initPorts();
13135
13282
  }
13136
13283
  doInitialSourceNameDuplicateComponentRemoval() {
@@ -13181,6 +13328,8 @@ var NormalComponent3 = class extends PrimitiveComponent2 {
13181
13328
  const pinLabelsFromProps = propsPinLabels && Array.isArray(propsPinLabels) ? Object.fromEntries(
13182
13329
  propsPinLabels.map((label, index) => [`pin${index + 1}`, label])
13183
13330
  ) : propsPinLabels;
13331
+ const existingChildPorts = this._getAllPortsFromChildren();
13332
+ const hasExistingOrQueuedPortWithPinNumber = (pinNumber) => existingChildPorts.some((p) => p._parsedProps.pinNumber === pinNumber) || portsToCreate.some((p) => p._parsedProps.pinNumber === pinNumber);
13184
13333
  const schPortArrangement = this._getSchematicPortArrangement();
13185
13334
  if (schPortArrangement && !pinLabels) {
13186
13335
  for (const side in schPortArrangement) {
@@ -13191,6 +13340,7 @@ var NormalComponent3 = class extends PrimitiveComponent2 {
13191
13340
  pinNumberOrLabel,
13192
13341
  pinLabels
13193
13342
  );
13343
+ if (hasExistingOrQueuedPortWithPinNumber(pinNumber)) continue;
13194
13344
  portsToCreate.push(
13195
13345
  new Port(
13196
13346
  {
@@ -13210,11 +13360,13 @@ var NormalComponent3 = class extends PrimitiveComponent2 {
13210
13360
  for (const side of sides) {
13211
13361
  const size = schPortArrangement[`${side}Size`];
13212
13362
  for (let i = 0; i < size; i++) {
13363
+ const nextPinNumber = pinNum++;
13364
+ if (hasExistingOrQueuedPortWithPinNumber(nextPinNumber)) continue;
13213
13365
  portsToCreate.push(
13214
13366
  new Port(
13215
13367
  {
13216
- pinNumber: pinNum++,
13217
- aliases: opts.additionalAliases?.[`pin${pinNum}`] ?? []
13368
+ pinNumber: nextPinNumber,
13369
+ aliases: opts.additionalAliases?.[`pin${nextPinNumber}`] ?? []
13218
13370
  },
13219
13371
  {
13220
13372
  originDescription: `schPortArrangement:${side}`
@@ -13232,9 +13384,9 @@ var NormalComponent3 = class extends PrimitiveComponent2 {
13232
13384
  `Invalid pinLabels key "${pinKey}". Expected "pin\${number}" (e.g. pin1, pin2).`
13233
13385
  );
13234
13386
  }
13235
- let existingPort = portsToCreate.find(
13387
+ let existingPort = existingChildPorts.find(
13236
13388
  (p) => p._parsedProps.pinNumber === pinNumber
13237
- );
13389
+ ) ?? portsToCreate.find((p) => p._parsedProps.pinNumber === pinNumber);
13238
13390
  const labelList = Array.isArray(label) ? label : [label];
13239
13391
  const propLabel = pinLabelsFromProps?.[pinKey];
13240
13392
  const hasPropLabel = propLabel !== void 0;
@@ -13291,10 +13443,8 @@ var NormalComponent3 = class extends PrimitiveComponent2 {
13291
13443
  }
13292
13444
  if (!this._getSchematicPortArrangement()) {
13293
13445
  const hasReactSymbol = isValidElement(this.props.symbol);
13294
- const symbolAlreadyAdded = this.children.some(
13295
- (c) => c.componentName === "Symbol"
13296
- );
13297
- if (hasReactSymbol && !symbolAlreadyAdded) {
13446
+ const hasCircuitJsonSymbolProp = isCircuitJsonSymbol(this.props.symbol);
13447
+ if (hasReactSymbol || hasCircuitJsonSymbolProp) {
13298
13448
  } else {
13299
13449
  const portsFromFootprint = this.getPortsFromFootprint({
13300
13450
  ...opts,
@@ -13321,7 +13471,7 @@ var NormalComponent3 = class extends PrimitiveComponent2 {
13321
13471
  }
13322
13472
  const requiredPinCount = opts.pinCount ?? this._getPrimaryPinCount() ?? 0;
13323
13473
  for (let pn = 1; pn <= requiredPinCount; pn++) {
13324
- if (portsToCreate.find((p) => p._parsedProps.pinNumber === pn)) continue;
13474
+ if (hasExistingOrQueuedPortWithPinNumber(pn)) continue;
13325
13475
  if (!schPortArrangement && pinLabelsFromProps && !Array.isArray(propsPinLabels) && !pinLabelsFromProps[`pin${pn}`]) {
13326
13476
  continue;
13327
13477
  }
@@ -13425,6 +13575,41 @@ var NormalComponent3 = class extends PrimitiveComponent2 {
13425
13575
  this.addAll(fpComponents);
13426
13576
  }
13427
13577
  }
13578
+ _addChildrenFromCircuitJsonSymbol() {
13579
+ if (this._hasInflatedCircuitJsonSymbol) return;
13580
+ const symbol = this._parsedProps.symbol;
13581
+ if (!isCircuitJsonSymbol(symbol)) return;
13582
+ if (this.children.some((component) => component.componentName === "Symbol")) {
13583
+ this._hasInflatedCircuitJsonSymbol = true;
13584
+ return;
13585
+ }
13586
+ const selectedSymbolCircuitJson = selectSymbolCircuitJson(symbol);
13587
+ if (selectedSymbolCircuitJson.length === 0) return;
13588
+ const symbolCircuitJson = normalizeSchematicSymbolCircuitJson(
13589
+ selectedSymbolCircuitJson
13590
+ );
13591
+ const importedSymbolComponents = createComponentsFromCircuitJson(
13592
+ {
13593
+ componentName: this.name ?? this.componentName,
13594
+ componentRotation: String(this.props.schRotation ?? 0)
13595
+ },
13596
+ symbolCircuitJson
13597
+ );
13598
+ if (importedSymbolComponents.length === 0) return;
13599
+ this._hasInflatedCircuitJsonSymbol = true;
13600
+ const hasImportedSymbolContainer = importedSymbolComponents.some(
13601
+ (component) => component.componentName === "Symbol"
13602
+ );
13603
+ if (!hasImportedSymbolContainer) {
13604
+ const symbolComponent = new SymbolComponent({
13605
+ name: this.name ?? this.componentName
13606
+ });
13607
+ symbolComponent.addAll(importedSymbolComponents);
13608
+ this.add(symbolComponent);
13609
+ return;
13610
+ }
13611
+ this.addAll(importedSymbolComponents);
13612
+ }
13428
13613
  get portMap() {
13429
13614
  return new Proxy(
13430
13615
  {},
@@ -25411,7 +25596,7 @@ import { identity as identity5 } from "transformation-matrix";
25411
25596
  var package_default = {
25412
25597
  name: "@tscircuit/core",
25413
25598
  type: "module",
25414
- version: "0.0.1416",
25599
+ version: "0.0.1417",
25415
25600
  types: "dist/index.d.ts",
25416
25601
  main: "dist/index.js",
25417
25602
  module: "dist/index.js",
@@ -25460,7 +25645,7 @@ var package_default = {
25460
25645
  "@tscircuit/math-utils": "^0.0.36",
25461
25646
  "@tscircuit/miniflex": "^0.0.4",
25462
25647
  "@tscircuit/ngspice-spice-engine": "^0.0.19",
25463
- "@tscircuit/props": "^0.0.567",
25648
+ "@tscircuit/props": "^0.0.569",
25464
25649
  "@tscircuit/schematic-match-adapt": "^0.0.18",
25465
25650
  "@tscircuit/schematic-trace-solver": "^0.0.95",
25466
25651
  "@tscircuit/solver-utils": "^0.0.16",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tscircuit/core",
3
3
  "type": "module",
4
- "version": "0.0.1417",
4
+ "version": "0.0.1418",
5
5
  "types": "dist/index.d.ts",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.js",
@@ -50,7 +50,7 @@
50
50
  "@tscircuit/math-utils": "^0.0.36",
51
51
  "@tscircuit/miniflex": "^0.0.4",
52
52
  "@tscircuit/ngspice-spice-engine": "^0.0.19",
53
- "@tscircuit/props": "^0.0.567",
53
+ "@tscircuit/props": "^0.0.569",
54
54
  "@tscircuit/schematic-match-adapt": "^0.0.18",
55
55
  "@tscircuit/schematic-trace-solver": "^0.0.95",
56
56
  "@tscircuit/solver-utils": "^0.0.16",