@tscircuit/core 0.0.2146 → 0.0.2147

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
@@ -4615,6 +4615,8 @@ declare class Port extends PrimitiveComponent<typeof portProps> {
4615
4615
  * but everyone registers themselves as a match with their Port.
4616
4616
  */
4617
4617
  registerMatch(component: PrimitiveComponent): void;
4618
+ /** Physical package ball name; pinNumber remains a schematic layout ordinal. */
4619
+ physicalPinName?: string;
4618
4620
  getNameAndAliases(): string[];
4619
4621
  _getMatchingPinAttributes(): PinAttributeMap[];
4620
4622
  private _shouldIncludeInBoardPinout;
@@ -4737,6 +4739,9 @@ declare class NormalComponent<ZodProps extends z.ZodType = any, PortNames extend
4737
4739
  ignoreSymbolPorts?: boolean;
4738
4740
  }): void;
4739
4741
  _resolvePinLabels(): Record<string, string | string[]> | undefined;
4742
+ private _resolvedPackagePins?;
4743
+ /** Physical package name, separate from the internal schematic ordinal. */
4744
+ _getPhysicalPinName(pinNumber: number): string | undefined;
4740
4745
  _getImpliedFootprintString(): string | null;
4741
4746
  resolveFootprint(): any;
4742
4747
  _addChildrenFromStringFootprint(): void;
@@ -110865,7 +110870,6 @@ declare const pcbViaProps: z.ZodObject<{
110865
110870
  }>]>, "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6" | "inner7" | "inner8", "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6" | "inner7" | "inner8" | {
110866
110871
  name: "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6" | "inner7" | "inner8";
110867
110872
  }>>;
110868
- name: z.ZodOptional<z.ZodString>;
110869
110873
  fromLayer: z.ZodOptional<z.ZodOptional<z.ZodEffects<z.ZodUnion<[z.ZodEnum<["top", "bottom", "inner1", "inner2", "inner3", "inner4", "inner5", "inner6", "inner7", "inner8"]>, z.ZodObject<{
110870
110874
  name: z.ZodEnum<["top", "bottom", "inner1", "inner2", "inner3", "inner4", "inner5", "inner6", "inner7", "inner8"]>;
110871
110875
  }, "strip", z.ZodTypeAny, {
@@ -110894,6 +110898,7 @@ declare const pcbViaProps: z.ZodObject<{
110894
110898
  name: "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6" | "inner7" | "inner8";
110895
110899
  }>, "many">>;
110896
110900
  connectsTo: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
110901
+ name: z.ZodOptional<z.ZodString>;
110897
110902
  holeDiameter: z.ZodOptional<z.ZodEffects<z.ZodUnion<[z.ZodString, z.ZodNumber]>, number, string | number>>;
110898
110903
  netIsAssignable: z.ZodOptional<z.ZodBoolean>;
110899
110904
  footprint: z.ZodOptional<z.ZodType<_tscircuit_props.FootprintProp, z.ZodTypeDef, _tscircuit_props.FootprintProp>>;
@@ -110980,11 +110985,11 @@ declare const pcbViaProps: z.ZodObject<{
110980
110985
  }, "strip", z.ZodTypeAny, {
110981
110986
  symbol?: _tscircuit_props.SymbolProp | undefined;
110982
110987
  layer?: "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6" | "inner7" | "inner8" | undefined;
110983
- name?: string | undefined;
110984
110988
  fromLayer?: "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6" | "inner7" | "inner8" | undefined;
110985
110989
  toLayer?: "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6" | "inner7" | "inner8" | undefined;
110986
110990
  layers?: ("top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6" | "inner7" | "inner8")[] | undefined;
110987
110991
  connectsTo?: string | string[] | undefined;
110992
+ name?: string | undefined;
110988
110993
  holeDiameter?: number | undefined;
110989
110994
  netIsAssignable?: boolean | undefined;
110990
110995
  footprint?: _tscircuit_props.FootprintProp | undefined;
@@ -111043,7 +111048,6 @@ declare const pcbViaProps: z.ZodObject<{
111043
111048
  layer?: "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6" | "inner7" | "inner8" | {
111044
111049
  name: "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6" | "inner7" | "inner8";
111045
111050
  } | undefined;
111046
- name?: string | undefined;
111047
111051
  fromLayer?: "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6" | "inner7" | "inner8" | {
111048
111052
  name: "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6" | "inner7" | "inner8";
111049
111053
  } | undefined;
@@ -111054,6 +111058,7 @@ declare const pcbViaProps: z.ZodObject<{
111054
111058
  name: "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6" | "inner7" | "inner8";
111055
111059
  })[] | undefined;
111056
111060
  connectsTo?: string | string[] | undefined;
111061
+ name?: string | undefined;
111057
111062
  holeDiameter?: string | number | undefined;
111058
111063
  netIsAssignable?: boolean | undefined;
111059
111064
  footprint?: _tscircuit_props.FootprintProp | undefined;
@@ -111125,7 +111130,6 @@ declare class PcbVia extends PrimitiveComponent<typeof pcbViaProps> {
111125
111130
  }>]>, "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6" | "inner7" | "inner8", "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6" | "inner7" | "inner8" | {
111126
111131
  name: "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6" | "inner7" | "inner8";
111127
111132
  }>>;
111128
- name: z.ZodOptional<z.ZodString>;
111129
111133
  fromLayer: z.ZodOptional<z.ZodOptional<z.ZodEffects<z.ZodUnion<[z.ZodEnum<["top", "bottom", "inner1", "inner2", "inner3", "inner4", "inner5", "inner6", "inner7", "inner8"]>, z.ZodObject<{
111130
111134
  name: z.ZodEnum<["top", "bottom", "inner1", "inner2", "inner3", "inner4", "inner5", "inner6", "inner7", "inner8"]>;
111131
111135
  }, "strip", z.ZodTypeAny, {
@@ -111154,6 +111158,7 @@ declare class PcbVia extends PrimitiveComponent<typeof pcbViaProps> {
111154
111158
  name: "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6" | "inner7" | "inner8";
111155
111159
  }>, "many">>;
111156
111160
  connectsTo: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
111161
+ name: z.ZodOptional<z.ZodString>;
111157
111162
  holeDiameter: z.ZodOptional<z.ZodEffects<z.ZodUnion<[z.ZodString, z.ZodNumber]>, number, string | number>>;
111158
111163
  netIsAssignable: z.ZodOptional<z.ZodBoolean>;
111159
111164
  footprint: z.ZodOptional<z.ZodType<_tscircuit_props.FootprintProp, z.ZodTypeDef, _tscircuit_props.FootprintProp>>;
@@ -111240,11 +111245,11 @@ declare class PcbVia extends PrimitiveComponent<typeof pcbViaProps> {
111240
111245
  }, "strip", z.ZodTypeAny, {
111241
111246
  symbol?: _tscircuit_props.SymbolProp | undefined;
111242
111247
  layer?: "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6" | "inner7" | "inner8" | undefined;
111243
- name?: string | undefined;
111244
111248
  fromLayer?: "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6" | "inner7" | "inner8" | undefined;
111245
111249
  toLayer?: "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6" | "inner7" | "inner8" | undefined;
111246
111250
  layers?: ("top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6" | "inner7" | "inner8")[] | undefined;
111247
111251
  connectsTo?: string | string[] | undefined;
111252
+ name?: string | undefined;
111248
111253
  holeDiameter?: number | undefined;
111249
111254
  netIsAssignable?: boolean | undefined;
111250
111255
  footprint?: _tscircuit_props.FootprintProp | undefined;
@@ -111303,7 +111308,6 @@ declare class PcbVia extends PrimitiveComponent<typeof pcbViaProps> {
111303
111308
  layer?: "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6" | "inner7" | "inner8" | {
111304
111309
  name: "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6" | "inner7" | "inner8";
111305
111310
  } | undefined;
111306
- name?: string | undefined;
111307
111311
  fromLayer?: "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6" | "inner7" | "inner8" | {
111308
111312
  name: "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6" | "inner7" | "inner8";
111309
111313
  } | undefined;
@@ -111314,6 +111318,7 @@ declare class PcbVia extends PrimitiveComponent<typeof pcbViaProps> {
111314
111318
  name: "top" | "bottom" | "inner1" | "inner2" | "inner3" | "inner4" | "inner5" | "inner6" | "inner7" | "inner8";
111315
111319
  })[] | undefined;
111316
111320
  connectsTo?: string | string[] | undefined;
111321
+ name?: string | undefined;
111317
111322
  holeDiameter?: string | number | undefined;
111318
111323
  netIsAssignable?: boolean | undefined;
111319
111324
  footprint?: _tscircuit_props.FootprintProp | undefined;
package/dist/index.js CHANGED
@@ -137,6 +137,68 @@ __export(components_exports, {
137
137
  VoltageSource: () => VoltageSource
138
138
  });
139
139
 
140
+ // lib/utils/schematic/getPinNumberFromPinLabelsKey.ts
141
+ var PIN_LABELS_KEY_RE = /^(?:pin)?(\d+)$/;
142
+ var getPinNumberFromPinLabelsKey = (pinKey) => {
143
+ const match = pinKey.match(PIN_LABELS_KEY_RE);
144
+ if (!match) return null;
145
+ return Number.parseInt(match[1], 10);
146
+ };
147
+
148
+ // lib/utils/schematic/resolvePinLabels.ts
149
+ var isPhysicalPinName = (name) => /^[A-Z]+[1-9]\d*$/.test(name);
150
+ function resolvePinLabels(pinLabels) {
151
+ const usedPinNumbers = new Set(
152
+ Object.keys(pinLabels).flatMap((key) => {
153
+ const pinNumber = getPinNumberFromPinLabelsKey(key);
154
+ return pinNumber === null ? [] : [pinNumber];
155
+ })
156
+ );
157
+ const physicalNames = Object.keys(pinLabels).filter(isPhysicalPinName).sort((a2, b2) => {
158
+ const [, rowA, columnA] = a2.match(/^([A-Z]+)(\d+)$/);
159
+ const [, rowB, columnB] = b2.match(/^([A-Z]+)(\d+)$/);
160
+ return rowA.length - rowB.length || (rowA < rowB ? -1 : rowA > rowB ? 1 : 0) || Number(columnA) - Number(columnB);
161
+ });
162
+ const physicalPins = [];
163
+ let nextPinNumber = 1;
164
+ for (const name of physicalNames) {
165
+ while (usedPinNumbers.has(nextPinNumber)) nextPinNumber++;
166
+ physicalPins.push({ physicalPinName: name, pinNumber: nextPinNumber++ });
167
+ }
168
+ return Object.entries(pinLabels).map(([key, labels]) => {
169
+ const numericPinNumber = getPinNumberFromPinLabelsKey(key);
170
+ const pinNumber = numericPinNumber ?? physicalPins.find((pin) => pin.physicalPinName === key)?.pinNumber;
171
+ if (pinNumber === void 0) {
172
+ throw new Error(
173
+ `Invalid pinLabels key "${key}". Expected a numeric pin (e.g. pin1) or physical ball name (e.g. A1).`
174
+ );
175
+ }
176
+ return {
177
+ pinNumber,
178
+ physicalPinName: numericPinNumber === null ? key : void 0,
179
+ labels: typeof labels === "string" ? [labels] : [...labels]
180
+ };
181
+ });
182
+ }
183
+ function getNumericPinLabels(pinLabels) {
184
+ if (!Object.keys(pinLabels).some(isPhysicalPinName)) {
185
+ return Object.fromEntries(
186
+ Object.entries(pinLabels).map(([key, labels]) => [
187
+ key,
188
+ typeof labels === "string" ? labels : [...labels]
189
+ ])
190
+ );
191
+ }
192
+ return Object.fromEntries(
193
+ resolvePinLabels(pinLabels).map(
194
+ ({ pinNumber, physicalPinName, labels }) => [
195
+ `pin${pinNumber}`,
196
+ physicalPinName ? [...labels, physicalPinName] : labels
197
+ ]
198
+ )
199
+ );
200
+ }
201
+
140
202
  // lib/components/base-components/NormalComponent/NormalComponent.ts
141
203
  import { resolveManufacturerPartNumber as resolveManufacturerPartNumber2 } from "@tscircuit/props";
142
204
 
@@ -937,6 +999,18 @@ var mergeRoutes = (routes) => {
937
999
  // lib/components/primitive-components/Net.ts
938
1000
  import { netProps } from "@tscircuit/props";
939
1001
 
1002
+ // lib/components/primitive-components/Port/assertUnambiguousPhysicalPortSelection.ts
1003
+ function assertUnambiguousPhysicalPortSelection(ports, selector) {
1004
+ if (ports.length < 2 || !ports.some((port) => port.physicalPinName)) return;
1005
+ const names = ports.map((port) => {
1006
+ const componentName = port.getParentNormalComponent()?.name ?? "unnamed component";
1007
+ return `${componentName}.${port.physicalPinName ?? port.name}`;
1008
+ });
1009
+ throw new Error(
1010
+ `Ambiguous port "${selector}"; use a physical ball name: ${names.join(", ")}.`
1011
+ );
1012
+ }
1013
+
940
1014
  // lib/components/base-components/PrimitiveComponent/get-construction-props-schema.ts
941
1015
  var constructionSchemas = /* @__PURE__ */ new WeakMap();
942
1016
  var getConstructionPropsSchema = (schema) => {
@@ -3004,9 +3078,16 @@ var PrimitiveComponent2 = class extends Renderable {
3004
3078
  this,
3005
3079
  cssSelectOptionsInsideSubcircuit
3006
3080
  );
3007
- result = allMatching.find(
3081
+ const matchingComponents = allMatching.filter(
3008
3082
  (n2) => n2.lowercaseComponentName === options.type
3009
3083
  );
3084
+ if (options.type === "port") {
3085
+ assertUnambiguousPhysicalPortSelection(
3086
+ matchingComponents,
3087
+ selectorRaw
3088
+ );
3089
+ }
3090
+ result = matchingComponents[0] ?? null;
3010
3091
  }
3011
3092
  if (!options?.type) {
3012
3093
  result ??= selectOne(
@@ -3016,6 +3097,14 @@ var PrimitiveComponent2 = class extends Renderable {
3016
3097
  );
3017
3098
  }
3018
3099
  if (result) {
3100
+ if (!options?.type && result.componentName === "Port") {
3101
+ assertUnambiguousPhysicalPortSelection(
3102
+ this.selectAll(selectorRaw).filter(
3103
+ (component) => component.componentName === "Port"
3104
+ ),
3105
+ selectorRaw
3106
+ );
3107
+ }
3019
3108
  this._cachedSelectOneQueries.set(selectorRaw, result);
3020
3109
  return result;
3021
3110
  }
@@ -5216,10 +5305,13 @@ var Port = class extends PrimitiveComponent2 {
5216
5305
  registerMatch(component) {
5217
5306
  this.matchedComponents.push(component);
5218
5307
  }
5308
+ /** Physical package ball name; pinNumber remains a schematic layout ordinal. */
5309
+ physicalPinName;
5219
5310
  getNameAndAliases() {
5220
5311
  const { _parsedProps: props } = this;
5221
5312
  return Array.from(
5222
5313
  /* @__PURE__ */ new Set([
5314
+ ...this.physicalPinName ? [this.physicalPinName] : [],
5223
5315
  ...props.name ? [props.name] : [],
5224
5316
  ...props.aliases ?? [],
5225
5317
  ...typeof props.pinNumber === "number" ? [`pin${props.pinNumber}`, props.pinNumber.toString()] : [],
@@ -5313,8 +5405,10 @@ var Port = class extends PrimitiveComponent2 {
5313
5405
  const source_component_id = parentWithSourceId?.source_component_id ?? null;
5314
5406
  const portAttributesFromParent = resolvePortSourcePinAttributes(this);
5315
5407
  const source_port = db2.source_port.insert({
5316
- name: props.name,
5317
- pin_number: props.pinNumber,
5408
+ name: this.physicalPinName ?? props.name,
5409
+ // Physical balls have a string package identity. Keep their numeric
5410
+ // layout ordinal on schematic_port, not the physical source pin number.
5411
+ pin_number: this.physicalPinName ? void 0 : props.pinNumber,
5318
5412
  port_hints,
5319
5413
  source_component_id,
5320
5414
  subcircuit_id: this.getSubcircuit()?.subcircuit_id,
@@ -9247,14 +9341,6 @@ var createInstanceFromReactElement = (reactElm) => {
9247
9341
  import "circuit-json";
9248
9342
  import "zod";
9249
9343
 
9250
- // lib/utils/schematic/getPinNumberFromPinLabelsKey.ts
9251
- var PIN_LABELS_KEY_RE = /^(?:pin)?(\d+)$/;
9252
- var getPinNumberFromPinLabelsKey = (pinKey) => {
9253
- const match = pinKey.match(PIN_LABELS_KEY_RE);
9254
- if (!match) return null;
9255
- return Number.parseInt(match[1], 10);
9256
- };
9257
-
9258
9344
  // lib/utils/filterPinLabels.ts
9259
9345
  function filterPinLabels(pinLabels) {
9260
9346
  if (!pinLabels)
@@ -9328,18 +9414,20 @@ var parsePinNumberFromLabelsOrThrow = (pinNumberOrLabel, pinLabels) => {
9328
9414
  if (!pinLabels) {
9329
9415
  throw new Error(getInvalidPinLabelMessage(pinNumberOrLabel));
9330
9416
  }
9331
- for (const pinNumberKey in pinLabels) {
9332
- const aliases = Array.isArray(pinLabels[pinNumberKey]) ? pinLabels[pinNumberKey] : [pinLabels[pinNumberKey]];
9333
- if (aliases.includes(pinNumberOrLabel)) {
9334
- const pinNumber = getPinNumberFromPinLabelsKey(pinNumberKey);
9335
- if (pinNumber === null) {
9336
- throw new Error(
9337
- `Invalid pinLabels key "${pinNumberKey}". Expected "pin\${number}" (e.g. pin1, pin2).`
9338
- );
9339
- }
9340
- return pinNumber;
9341
- }
9417
+ const resolvedPins = resolvePinLabels(pinLabels);
9418
+ const physicalPin = resolvedPins.find(
9419
+ (pin) => pin.physicalPinName === pinNumberOrLabel
9420
+ );
9421
+ if (physicalPin) return physicalPin.pinNumber;
9422
+ const matches = resolvedPins.filter(
9423
+ (pin) => pin.labels.includes(pinNumberOrLabel)
9424
+ );
9425
+ if (matches.length > 1 && matches.some((pin) => pin.physicalPinName)) {
9426
+ throw new Error(
9427
+ `Ambiguous pin label "${pinNumberOrLabel}"; use a physical ball name: ${matches.map((pin) => pin.physicalPinName ?? `pin${pin.pinNumber}`).join(", ")}.`
9428
+ );
9342
9429
  }
9430
+ if (matches.length > 0) return matches[0].pinNumber;
9343
9431
  throw new Error(getInvalidPinLabelMessage(pinNumberOrLabel));
9344
9432
  };
9345
9433
 
@@ -11083,10 +11171,15 @@ function selectPortForPcbPrimitive(ports, primitive, hints) {
11083
11171
  const pinNumber = getPinNumberFromHints(hints);
11084
11172
  const matchingPorts = ports.filter((port) => port.isMatchingAnyOf(hints));
11085
11173
  if (matchingPorts.length === 0) return null;
11174
+ const physicalCandidates = matchingPorts.filter(
11175
+ (port) => port.physicalPinName && hints.includes(port.physicalPinName)
11176
+ );
11177
+ if (physicalCandidates.length === 1) return physicalCandidates[0];
11086
11178
  const pinMatchedPorts = pinNumber === null ? matchingPorts : matchingPorts.filter(
11087
11179
  (port) => port._parsedProps.pinNumber === pinNumber || port._primaryPinNumber === pinNumber
11088
11180
  );
11089
11181
  const candidates = pinMatchedPorts.length > 0 ? pinMatchedPorts : matchingPorts;
11182
+ assertUnambiguousPhysicalPortSelection(candidates, hints.join(", "));
11090
11183
  const overlappingPort = candidates.find(
11091
11184
  (port) => port.matchedComponents.some(
11092
11185
  (component) => component.isPcbPrimitive && doPcbPrimitivesOverlapBeforeRender(component, primitive)
@@ -17507,6 +17600,15 @@ function getPrimaryPortsFromPortHintGroups(portHintGroups, opts) {
17507
17600
  );
17508
17601
  if (filteredPortHints.length === 0) continue;
17509
17602
  let portHintsList = filteredPortHints;
17603
+ const physicalPinNumber = portHintsList.map((hint) => opts?.implicitPinNumberByHint?.get(hint)).find(
17604
+ (pinNumber2) => pinNumber2 !== void 0 && portHintsList.includes(opts?.getPhysicalPinName?.(pinNumber2) ?? "")
17605
+ );
17606
+ if (physicalPinNumber !== void 0) {
17607
+ portHintsList = [
17608
+ ...portHintsList.filter((hint) => !/^(?:pin)?\d+$/.test(hint)),
17609
+ `pin${physicalPinNumber}`
17610
+ ];
17611
+ }
17510
17612
  const hasPinIdentifier = portHintsList.some(
17511
17613
  (hint) => hint.startsWith("pin") || /^(?:pin)?\d+$/.test(hint)
17512
17614
  );
@@ -17526,6 +17628,7 @@ function getPrimaryPortsFromPortHintGroups(portHintGroups, opts) {
17526
17628
  newPort.originDescription = portHintGroup.originDescription;
17527
17629
  const pinNumber = newPort._parsedProps.pinNumber;
17528
17630
  if (pinNumber === void 0) continue;
17631
+ newPort.physicalPinName = opts?.getPhysicalPinName?.(pinNumber);
17529
17632
  if (!entriesByPinNumber.has(pinNumber))
17530
17633
  entriesByPinNumber.set(pinNumber, []);
17531
17634
  entriesByPinNumber.get(pinNumber).push({
@@ -17587,7 +17690,7 @@ function getPrimaryPortsFromPortHintGroups(portHintGroups, opts) {
17587
17690
  }
17588
17691
  opts?.inferredInternallyConnectedPinNames?.push(internallyConnectedPinNames);
17589
17692
  }
17590
- if (opts?.inferredInternallyConnectedPinNames) {
17693
+ if (opts?.inferredInternallyConnectedPinNames && opts.inferSharedAliases !== false) {
17591
17694
  inferInternallyConnectedPinNamesFromPorts(
17592
17695
  ports,
17593
17696
  opts.inferredInternallyConnectedPinNames
@@ -17667,14 +17770,14 @@ var NormalComponent = class extends PrimitiveComponent2 {
17667
17770
  super(filteredProps);
17668
17771
  if (filteredProps.pinLabels && !Array.isArray(filteredProps.pinLabels)) {
17669
17772
  const invalidPinKey = Object.keys(filteredProps.pinLabels).find(
17670
- (pinKey) => getPinNumberFromPinLabelsKey(pinKey) === null
17773
+ (pinKey) => getPinNumberFromPinLabelsKey(pinKey) === null && !isPhysicalPinName(pinKey)
17671
17774
  );
17672
17775
  if (invalidPinKey) {
17673
17776
  throw new InvalidProps(this.lowercaseComponentName, this.props, {
17674
17777
  _errors: [],
17675
17778
  pinLabels: {
17676
17779
  _errors: [
17677
- `Invalid pinLabels key "${invalidPinKey}". Expected "pin\${number}" (e.g. pin1, pin2).`
17780
+ `Invalid pinLabels key "${invalidPinKey}". Expected "pin\${number}" (e.g. pin1, pin2) or a physical ball name (e.g. A1).`
17678
17781
  ]
17679
17782
  }
17680
17783
  });
@@ -17734,7 +17837,7 @@ var NormalComponent = class extends PrimitiveComponent2 {
17734
17837
  const propsPinLabels = this._parsedProps.pinLabels;
17735
17838
  const pinLabelsFromProps = propsPinLabels && Array.isArray(propsPinLabels) ? Object.fromEntries(
17736
17839
  propsPinLabels.map((label, index2) => [`pin${index2 + 1}`, label])
17737
- ) : propsPinLabels;
17840
+ ) : propsPinLabels ? getNumericPinLabels(propsPinLabels) : void 0;
17738
17841
  const existingChildPorts = this._getAllPortsFromChildren();
17739
17842
  const hasExistingOrQueuedPortWithPinNumber = (pinNumber) => existingChildPorts.some((p2) => p2._parsedProps.pinNumber === pinNumber) || portsToCreate.some((p2) => p2._parsedProps.pinNumber === pinNumber);
17740
17843
  const schPortArrangement = this._getSchematicPortArrangement();
@@ -17788,7 +17891,7 @@ var NormalComponent = class extends PrimitiveComponent2 {
17788
17891
  const pinNumber = getPinNumberFromPinLabelsKey(pinKey);
17789
17892
  if (pinNumber === null) {
17790
17893
  throw new Error(
17791
- `Invalid pinLabels key "${pinKey}". Expected "pin\${number}" (e.g. pin1, pin2).`
17894
+ `Invalid pinLabels key "${pinKey}". Expected "pin\${number}" (e.g. pin1, pin2) or a physical ball name (e.g. A1).`
17792
17895
  );
17793
17896
  }
17794
17897
  let existingPort = existingChildPorts.find(
@@ -17797,8 +17900,9 @@ var NormalComponent = class extends PrimitiveComponent2 {
17797
17900
  const labelList = Array.isArray(label) ? label : [label];
17798
17901
  const propLabel = pinLabelsFromProps?.[pinKey];
17799
17902
  const hasPropLabel = propLabel !== void 0;
17800
- const primaryLabel = hasPropLabel ? labelList[0] : `pin${pinNumber}`;
17801
- const otherLabels = hasPropLabel ? labelList.slice(1) : labelList;
17903
+ const physicalPinName = this._getPhysicalPinName(pinNumber);
17904
+ const primaryLabel = physicalPinName ?? (hasPropLabel ? labelList[0] : `pin${pinNumber}`);
17905
+ const otherLabels = physicalPinName ? labelList : hasPropLabel ? labelList.slice(1) : labelList;
17802
17906
  if (!existingPort) {
17803
17907
  existingPort = new Port(
17804
17908
  {
@@ -17818,6 +17922,7 @@ var NormalComponent = class extends PrimitiveComponent2 {
17818
17922
  } else {
17819
17923
  existingPort.externallyAddedAliases.push(primaryLabel, ...otherLabels);
17820
17924
  }
17925
+ existingPort.physicalPinName = physicalPinName;
17821
17926
  }
17822
17927
  }
17823
17928
  if (config.schematicSymbolName && !opts.ignoreSymbolPorts) {
@@ -17949,7 +18054,11 @@ var NormalComponent = class extends PrimitiveComponent2 {
17949
18054
  }
17950
18055
  inferInternallyConnectedPinNamesFromPorts(
17951
18056
  Array.from(
17952
- /* @__PURE__ */ new Set([...this._getAllPortsFromChildren(), ...portsToCreate])
18057
+ new Set(
18058
+ [...this._getAllPortsFromChildren(), ...portsToCreate].filter(
18059
+ (port) => !port.physicalPinName
18060
+ )
18061
+ )
17953
18062
  ),
17954
18063
  this._inferredInternallyConnectedPinNames
17955
18064
  );
@@ -17961,7 +18070,7 @@ var NormalComponent = class extends PrimitiveComponent2 {
17961
18070
  const pinLabels = this._parsedProps.pinLabels;
17962
18071
  const parsedPinLabels = pinLabels && Array.isArray(pinLabels) ? Object.fromEntries(
17963
18072
  pinLabels.map((label, index2) => [`pin${index2 + 1}`, label])
17964
- ) : pinLabels;
18073
+ ) : pinLabels ? getNumericPinLabels(pinLabels) : void 0;
17965
18074
  const resolvedPinLabels = {
17966
18075
  ...this._impliedFootprintPinLabels ?? {},
17967
18076
  ...parsedPinLabels ?? {}
@@ -17969,6 +18078,14 @@ var NormalComponent = class extends PrimitiveComponent2 {
17969
18078
  if (Object.keys(resolvedPinLabels).length === 0) return void 0;
17970
18079
  return resolvedPinLabels;
17971
18080
  }
18081
+ _resolvedPackagePins;
18082
+ /** Physical package name, separate from the internal schematic ordinal. */
18083
+ _getPhysicalPinName(pinNumber) {
18084
+ const pinLabels = this._parsedProps?.pinLabels ?? this.props.pinLabels;
18085
+ if (!pinLabels || Array.isArray(pinLabels)) return void 0;
18086
+ this._resolvedPackagePins ??= resolvePinLabels(pinLabels);
18087
+ return this._resolvedPackagePins.find((pin) => pin.pinNumber === pinNumber)?.physicalPinName;
18088
+ }
17972
18089
  _getImpliedFootprintString() {
17973
18090
  return null;
17974
18091
  }
@@ -18648,8 +18765,12 @@ var NormalComponent = class extends PrimitiveComponent2 {
18648
18765
  if (opts?.collectInferredInternallyConnectedPins) {
18649
18766
  inferredInternallyConnectedPinNames = this._inferredInternallyConnectedPinNames;
18650
18767
  }
18768
+ const physicalPinLabels = this._parsedProps?.pinLabels ?? this.props.pinLabels;
18769
+ const hasPhysicalPins = physicalPinLabels && !Array.isArray(physicalPinLabels) && Object.keys(physicalPinLabels).some(isPhysicalPinName);
18651
18770
  const implicitPinNumberByHint = /* @__PURE__ */ new Map();
18652
- const explicitPinLabels = this._parsedProps?.pinLabels ?? this.props.pinLabels;
18771
+ const ambiguousHints = /* @__PURE__ */ new Set();
18772
+ const rawExplicitPinLabels = this._parsedProps?.pinLabels ?? this.props.pinLabels;
18773
+ const explicitPinLabels = rawExplicitPinLabels && !Array.isArray(rawExplicitPinLabels) ? getNumericPinLabels(rawExplicitPinLabels) : rawExplicitPinLabels;
18653
18774
  if (explicitPinLabels) {
18654
18775
  const pinLabelEntries = Array.isArray(explicitPinLabels) ? explicitPinLabels.map((label, index2) => [`pin${index2 + 1}`, label]) : Object.entries(explicitPinLabels);
18655
18776
  for (const [pinKey, labelOrLabels] of pinLabelEntries) {
@@ -18658,13 +18779,20 @@ var NormalComponent = class extends PrimitiveComponent2 {
18658
18779
  const labels = Array.isArray(labelOrLabels) ? labelOrLabels : [labelOrLabels];
18659
18780
  for (const label of labels) {
18660
18781
  if (typeof label === "string" && label.length > 0) {
18782
+ const previousPinNumber = implicitPinNumberByHint.get(label);
18783
+ if (hasPhysicalPins && previousPinNumber !== void 0 && previousPinNumber !== pinNumber) {
18784
+ ambiguousHints.add(label);
18785
+ }
18661
18786
  implicitPinNumberByHint.set(label, pinNumber);
18662
18787
  }
18663
18788
  }
18664
18789
  }
18665
18790
  }
18791
+ for (const hint of ambiguousHints) implicitPinNumberByHint.delete(hint);
18666
18792
  const primaryPortOpts = {
18667
18793
  ...opts,
18794
+ inferSharedAliases: !hasPhysicalPins,
18795
+ getPhysicalPinName: (pinNumber) => this._getPhysicalPinName(pinNumber),
18668
18796
  inferredInternallyConnectedPinNames,
18669
18797
  implicitPinNumberByHint
18670
18798
  };
@@ -18910,19 +19038,24 @@ var NormalComponent = class extends PrimitiveComponent2 {
18910
19038
  `pin${pinIndex + 1}`,
18911
19039
  label
18912
19040
  ])
18913
- ) : props.pinLabels;
19041
+ ) : props.pinLabels ? getNumericPinLabels(props.pinLabels) : void 0;
18914
19042
  const allPinLabels = {
18915
19043
  ...pinLabelsFromPorts,
18916
19044
  ...pinLabelsFromProps
18917
19045
  };
18918
19046
  const schPortArrangement = this._getSchematicPortArrangement() ?? this._getImplicitSparseSchematicPortArrangement(pinCount);
19047
+ if (props.pinLabels && !Array.isArray(props.pinLabels) && Object.keys(props.pinLabels).some(isPhysicalPinName) && schPortArrangement) {
19048
+ for (const pin of getPinsFromPortArrangement(schPortArrangement)) {
19049
+ parsePinNumberFromLabelsOrThrow(pin, props.pinLabels);
19050
+ }
19051
+ }
18919
19052
  return getAllDimensionsForSchematicBox({
18920
19053
  schWidth: props.schWidth,
18921
19054
  schHeight: props.schHeight,
18922
19055
  schPinSpacing: pinSpacing,
18923
19056
  numericSchPinStyle: getNumericSchPinStyle(
18924
19057
  props.schPinStyle,
18925
- allPinLabels
19058
+ !Array.isArray(props.pinLabels) ? props.pinLabels ?? allPinLabels : allPinLabels
18926
19059
  ),
18927
19060
  pinCount,
18928
19061
  schPortArrangement,
@@ -110256,20 +110389,22 @@ function getTitleAnchorAndPosition({
110256
110389
  // lib/components/primitive-components/SchematicBox/SchematicBox_doInitialSchematicComponentRender.ts
110257
110390
  var getSchematicBoxPinLabels = (pinLabels) => {
110258
110391
  if (!pinLabels) return [];
110259
- return Object.entries(pinLabels).map(([pinKey, pinLabel]) => {
110260
- const pinNumber = getPinNumberFromPinLabelsKey(pinKey);
110261
- if (pinNumber === null) {
110262
- throw new Error(
110263
- `Invalid schematicbox pinLabels key "${pinKey}". Expected pin<number>.`
110264
- );
110392
+ return Object.entries(getNumericPinLabels(pinLabels)).map(
110393
+ ([pinKey, pinLabel]) => {
110394
+ const pinNumber = getPinNumberFromPinLabelsKey(pinKey);
110395
+ if (pinNumber === null) {
110396
+ throw new Error(
110397
+ `Invalid schematicbox pinLabels key "${pinKey}". Expected pin<number>.`
110398
+ );
110399
+ }
110400
+ const pinAliases = typeof pinLabel === "string" ? [pinLabel] : [...pinLabel];
110401
+ return {
110402
+ pinNumber,
110403
+ displayPinLabel: pinAliases[0] ?? pinKey,
110404
+ pinAliases
110405
+ };
110265
110406
  }
110266
- const pinAliases = typeof pinLabel === "string" ? [pinLabel] : [...pinLabel];
110267
- return {
110268
- pinNumber,
110269
- displayPinLabel: pinAliases[0] ?? pinKey,
110270
- pinAliases
110271
- };
110272
- });
110407
+ );
110273
110408
  };
110274
110409
  var getSchematicBoxPinStyleFromReferencedChip = ({
110275
110410
  referencedChip,
@@ -118557,7 +118692,7 @@ var RoutingPhasePreparationError = class extends Error {
118557
118692
  var package_default = {
118558
118693
  name: "@tscircuit/core",
118559
118694
  type: "module",
118560
- version: "0.0.2145",
118695
+ version: "0.0.2146",
118561
118696
  types: "dist/index.d.ts",
118562
118697
  main: "dist/index.js",
118563
118698
  module: "dist/index.js",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tscircuit/core",
3
3
  "type": "module",
4
- "version": "0.0.2146",
4
+ "version": "0.0.2147",
5
5
  "types": "dist/index.d.ts",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.js",