@tscircuit/footprinter 0.0.298 → 0.0.300

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -24,6 +24,7 @@ __export(fn_exports, {
24
24
  micromelf: () => micromelf,
25
25
  minimelf: () => minimelf,
26
26
  mlp: () => mlp,
27
+ mountedpcbmodule: () => mountedpcbmodule,
27
28
  ms012: () => ms012,
28
29
  ms013: () => ms013,
29
30
  msop: () => msop,
@@ -794,7 +795,7 @@ var getArrayCount = (parameters) => {
794
795
  return Number.isNaN(parsed) ? void 0 : parsed;
795
796
  }
796
797
  if (typeof parameters.imperial === "string") {
797
- const match = parameters.imperial.match(/(?:array|x)(2|4)$/);
798
+ const match = parameters.imperial.match(/x(2|4)$/);
798
799
  const count = match?.[1];
799
800
  if (count) {
800
801
  return Number.parseInt(count, 10);
@@ -805,7 +806,7 @@ var getArrayCount = (parameters) => {
805
806
  var getImperialBase = (imperial) => {
806
807
  if (!imperial) return void 0;
807
808
  const imperialString = typeof imperial === "number" ? `${imperial}` : imperial;
808
- return imperialString.split("_")[0];
809
+ return imperialString.split(/[_x]/)[0];
809
810
  };
810
811
  var res = (rawParameters) => {
811
812
  const arrayCount = getArrayCount(rawParameters);
@@ -5086,14 +5087,14 @@ var sot89_3 = (parameters) => {
5086
5087
  const pads = [];
5087
5088
  const padGap = Number.parseFloat(parameters.p);
5088
5089
  const padWidth = Number.parseFloat(parameters.pw);
5089
- const length58 = Number.parseFloat(parameters.w);
5090
+ const length59 = Number.parseFloat(parameters.w);
5090
5091
  const padHeight = Number.parseFloat(parameters.pl);
5091
5092
  const centerExtra = 0.175;
5092
5093
  const outerPadXShift = (padHeight - (padHeight + centerExtra)) / 2;
5093
5094
  pads.push(
5094
- rectpad(1, -length58 / 2 + outerPadXShift, padGap, padHeight, padWidth),
5095
- rectpad(2, -length58 / 2, 0, padHeight + centerExtra, padWidth),
5096
- rectpad(3, -length58 / 2 + outerPadXShift, -padGap, padHeight, padWidth)
5095
+ rectpad(1, -length59 / 2 + outerPadXShift, padGap, padHeight, padWidth),
5096
+ rectpad(2, -length59 / 2, 0, padHeight + centerExtra, padWidth),
5097
+ rectpad(3, -length59 / 2 + outerPadXShift, -padGap, padHeight, padWidth)
5097
5098
  );
5098
5099
  const silkscreenRefText = silkscreenRef(0, 0, 0.3);
5099
5100
  const width = Number.parseFloat(parameters.w) / 2 - 1;
@@ -5133,7 +5134,7 @@ var sot89_5 = (parameters) => {
5133
5134
  const pads = [];
5134
5135
  const padGap = Number.parseFloat(parameters.p);
5135
5136
  const padWidth = Number.parseFloat(parameters.pw);
5136
- const length58 = Number.parseFloat(parameters.w);
5137
+ const length59 = Number.parseFloat(parameters.w);
5137
5138
  pads.push(
5138
5139
  rectpad(1, -1.85, -1.5, 1.5, 0.7),
5139
5140
  rectpad(2, -1.85, 1.5, 1.5, 0.7),
@@ -8308,17 +8309,261 @@ var m2host = (raw_params) => {
8308
8309
  };
8309
8310
  };
8310
8311
 
8311
- // src/fn/to92l.ts
8312
+ // src/fn/mountedpcbmodule.ts
8312
8313
  import { z as z76 } from "zod";
8313
- var to92l_def = base_def.extend({
8314
+ import { length as length58 } from "circuit-json";
8315
+ var mountedpcbmodule_def = base_def.extend({
8314
8316
  fn: z76.string(),
8315
- num_pins: z76.number().default(3),
8316
- inline: z76.boolean().default(false),
8317
- p: z76.string().default("1.27mm"),
8318
- id: z76.string().default("0.75mm"),
8319
- od: z76.string().default("1.3mm"),
8320
- w: z76.string().default("4.8mm"),
8321
- h: z76.string().default("4.0mm")
8317
+ numPins: z76.number().optional().default(0),
8318
+ rows: z76.union([z76.string(), z76.number()]).transform((val) => Number(val)).optional().default(1).describe("number of rows"),
8319
+ p: length58.default("2.54mm").describe("pitch"),
8320
+ id: length58.default("1.0mm").describe("inner diameter"),
8321
+ od: length58.default("1.5mm").describe("outer diameter"),
8322
+ male: z76.boolean().optional().describe("the module uses male headers"),
8323
+ female: z76.boolean().optional().describe("the module uses female headers"),
8324
+ smd: z76.boolean().optional().describe("surface mount device"),
8325
+ pinlabeltextalignleft: z76.boolean().optional().default(false),
8326
+ pinlabeltextaligncenter: z76.boolean().optional().default(false),
8327
+ pinlabeltextalignright: z76.boolean().optional().default(false),
8328
+ pinlabelverticallyinverted: z76.boolean().optional().default(false),
8329
+ pinlabelorthogonal: z76.boolean().optional().default(false),
8330
+ nopinlabels: z76.boolean().optional().default(false).describe("omit silkscreen pin labels"),
8331
+ doublesidedpinlabel: z76.boolean().optional().default(false).describe("add silkscreen pins in top and bottom layers"),
8332
+ bottomsidepinlabel: z76.boolean().optional().default(false).describe(
8333
+ "place the silkscreen reference text on the bottom layer instead of top"
8334
+ ),
8335
+ pinRowSide: z76.enum(["left", "right", "top", "bottom"]).optional().default("left"),
8336
+ pinrowleft: z76.boolean().optional().default(false),
8337
+ pinrowright: z76.boolean().optional().default(false),
8338
+ pinrowtop: z76.boolean().optional().default(false),
8339
+ pinrowbottom: z76.boolean().optional().default(false),
8340
+ width: length58.optional(),
8341
+ height: length58.optional(),
8342
+ pinRowHoleEdgeToEdgeDist: length58.default("2mm"),
8343
+ holes: z76.union([z76.string(), z76.array(z76.string())]).optional().transform((val) => {
8344
+ if (!val) return val;
8345
+ if (Array.isArray(val)) return val;
8346
+ if (val.startsWith("(") && val.endsWith(")")) {
8347
+ return val.slice(1, -1).split(",").map((s) => s.trim());
8348
+ }
8349
+ return [val];
8350
+ }),
8351
+ holeXDist: length58.optional(),
8352
+ holeYDist: length58.optional(),
8353
+ holeInset: length58.default("1mm"),
8354
+ pinrow: z76.union([z76.string(), z76.number()]).optional()
8355
+ }).transform((data) => {
8356
+ const pinlabelAnchorSide = determinePinlabelAnchorSide(data);
8357
+ let pinRowSide = data.pinRowSide;
8358
+ if (data.pinrowleft) pinRowSide = "left";
8359
+ if (data.pinrowright) pinRowSide = "right";
8360
+ if (data.pinrowtop) pinRowSide = "top";
8361
+ if (data.pinrowbottom) pinRowSide = "bottom";
8362
+ if (data.pinrow !== void 0) {
8363
+ data.numPins = Number(data.pinrow);
8364
+ }
8365
+ const numPinsPerRow = Math.ceil(data.numPins / data.rows);
8366
+ let calculatedWidth;
8367
+ let calculatedHeight;
8368
+ if (pinRowSide === "left" || pinRowSide === "right") {
8369
+ calculatedWidth = (data.rows - 1) * data.p + 2 * data.pinRowHoleEdgeToEdgeDist;
8370
+ calculatedHeight = (numPinsPerRow - 1) * data.p + 2 * data.pinRowHoleEdgeToEdgeDist;
8371
+ } else {
8372
+ calculatedHeight = (data.rows - 1) * data.p + 2 * data.pinRowHoleEdgeToEdgeDist;
8373
+ calculatedWidth = (numPinsPerRow - 1) * data.p + 2 * data.pinRowHoleEdgeToEdgeDist;
8374
+ }
8375
+ if (data.numPins === 0) {
8376
+ calculatedWidth = 10;
8377
+ calculatedHeight = 10;
8378
+ }
8379
+ return {
8380
+ ...data,
8381
+ pinlabelAnchorSide,
8382
+ pinRowSide,
8383
+ male: data.male ?? !data.female,
8384
+ female: data.female ?? false,
8385
+ width: data.width ?? calculatedWidth,
8386
+ height: data.height ?? calculatedHeight
8387
+ };
8388
+ }).superRefine((data, ctx) => {
8389
+ if (data.male && data.female) {
8390
+ ctx.addIssue({
8391
+ code: z76.ZodIssueCode.custom,
8392
+ message: "'male' and 'female' cannot both be true; it should be male or female.",
8393
+ path: ["male", "female"]
8394
+ });
8395
+ }
8396
+ });
8397
+ var mountedpcbmodule = (raw_params) => {
8398
+ const parameters = mountedpcbmodule_def.parse(raw_params);
8399
+ const {
8400
+ p,
8401
+ id,
8402
+ od,
8403
+ rows,
8404
+ numPins,
8405
+ pinlabelAnchorSide,
8406
+ pinlabelverticallyinverted,
8407
+ pinlabelorthogonal,
8408
+ pinlabeltextalignleft,
8409
+ pinlabeltextalignright,
8410
+ nopinlabels,
8411
+ doublesidedpinlabel,
8412
+ bottomsidepinlabel,
8413
+ pinRowSide,
8414
+ width,
8415
+ height,
8416
+ pinRowHoleEdgeToEdgeDist,
8417
+ holes,
8418
+ holeXDist,
8419
+ holeYDist,
8420
+ holeInset
8421
+ } = parameters;
8422
+ let pinlabelTextAlign = "center";
8423
+ if (pinlabeltextalignleft) pinlabelTextAlign = "left";
8424
+ else if (pinlabeltextalignright) pinlabelTextAlign = "right";
8425
+ const elements = [];
8426
+ const pinSpacing = p;
8427
+ let pinStartX = 0;
8428
+ let pinStartY = 0;
8429
+ let pinDirectionX = 0;
8430
+ let pinDirectionY = 0;
8431
+ let rowDirectionX = 0;
8432
+ let rowDirectionY = 0;
8433
+ const numPinsPerRow = Math.ceil(numPins / rows);
8434
+ if (pinRowSide === "left" || pinRowSide === "right") {
8435
+ pinStartX = pinRowSide === "left" ? -width / 2 + pinRowHoleEdgeToEdgeDist : width / 2 - pinRowHoleEdgeToEdgeDist;
8436
+ pinStartY = (numPinsPerRow - 1) / 2 * pinSpacing;
8437
+ pinDirectionX = 0;
8438
+ pinDirectionY = -pinSpacing;
8439
+ rowDirectionX = pinRowSide === "left" ? pinSpacing : -pinSpacing;
8440
+ rowDirectionY = 0;
8441
+ } else {
8442
+ pinStartX = -(numPinsPerRow - 1) / 2 * pinSpacing;
8443
+ pinStartY = pinRowSide === "top" ? height / 2 - pinRowHoleEdgeToEdgeDist : -height / 2 + pinRowHoleEdgeToEdgeDist;
8444
+ pinDirectionX = pinSpacing;
8445
+ pinDirectionY = 0;
8446
+ rowDirectionX = 0;
8447
+ rowDirectionY = pinRowSide === "top" ? -pinSpacing : pinSpacing;
8448
+ }
8449
+ let pinNumber = 1;
8450
+ for (let row = 0; row < rows && pinNumber <= numPins; row++) {
8451
+ for (let col = 0; col < numPinsPerRow && pinNumber <= numPins; col++) {
8452
+ const xoff = pinStartX + col * pinDirectionX + row * rowDirectionX;
8453
+ const yoff = pinStartY + col * pinDirectionY + row * rowDirectionY;
8454
+ if (parameters.smd) {
8455
+ elements.push(
8456
+ rectpad(pinNumber, xoff, yoff, parameters.od, parameters.od)
8457
+ );
8458
+ } else {
8459
+ if (pinNumber === 1) {
8460
+ elements.push(
8461
+ platedHoleWithRectPad({
8462
+ pn: pinNumber,
8463
+ x: xoff,
8464
+ y: yoff,
8465
+ holeDiameter: id,
8466
+ rectPadWidth: od,
8467
+ rectPadHeight: od
8468
+ })
8469
+ );
8470
+ } else {
8471
+ elements.push(platedhole(pinNumber, xoff, yoff, id, od));
8472
+ }
8473
+ }
8474
+ if (!nopinlabels) {
8475
+ const anchor_x = xoff + (pinRowSide === "left" ? -od : pinRowSide === "right" ? od : 0);
8476
+ const anchor_y = yoff + (pinRowSide === "top" ? od : pinRowSide === "bottom" ? -od : 0);
8477
+ if (!bottomsidepinlabel) {
8478
+ elements.push(
8479
+ silkscreenPin({
8480
+ fs: od / 5,
8481
+ pn: pinNumber,
8482
+ anchor_x,
8483
+ anchor_y,
8484
+ anchorplacement: pinlabelAnchorSide,
8485
+ textalign: pinlabelTextAlign,
8486
+ orthogonal: pinlabelorthogonal,
8487
+ verticallyinverted: pinlabelverticallyinverted,
8488
+ layer: "top"
8489
+ })
8490
+ );
8491
+ }
8492
+ if (doublesidedpinlabel || bottomsidepinlabel) {
8493
+ elements.push(
8494
+ silkscreenPin({
8495
+ fs: od / 5,
8496
+ pn: pinNumber,
8497
+ anchor_x,
8498
+ anchor_y,
8499
+ anchorplacement: pinlabelAnchorSide,
8500
+ textalign: pinlabelTextAlign,
8501
+ orthogonal: pinlabelorthogonal,
8502
+ verticallyinverted: pinlabelverticallyinverted,
8503
+ layer: "bottom"
8504
+ })
8505
+ );
8506
+ }
8507
+ }
8508
+ pinNumber++;
8509
+ }
8510
+ }
8511
+ if (holes) {
8512
+ for (const pos of holes) {
8513
+ let hx = 0;
8514
+ let hy = 0;
8515
+ if (pos === "topleft") {
8516
+ hx = -width / 2 + holeInset;
8517
+ hy = height / 2 - holeInset;
8518
+ } else if (pos === "topright") {
8519
+ hx = width / 2 - holeInset;
8520
+ hy = height / 2 - holeInset;
8521
+ } else if (pos === "bottomleft") {
8522
+ hx = -width / 2 + holeInset;
8523
+ hy = -height / 2 + holeInset;
8524
+ } else if (pos === "bottomright") {
8525
+ hx = width / 2 - holeInset;
8526
+ hy = -height / 2 + holeInset;
8527
+ } else if (pos === "center") {
8528
+ hx = 0;
8529
+ hy = 0;
8530
+ }
8531
+ if (holeXDist !== void 0) hx += holeXDist;
8532
+ if (holeYDist !== void 0) hy += holeYDist;
8533
+ elements.push(
8534
+ platedhole(numPins + holes.indexOf(pos) + 1, hx, hy, id, od)
8535
+ );
8536
+ }
8537
+ }
8538
+ if (!parameters.nosilkscreen) {
8539
+ const outline = [
8540
+ { x: -width / 2, y: -height / 2 },
8541
+ { x: width / 2, y: -height / 2 },
8542
+ { x: width / 2, y: height / 2 },
8543
+ { x: -width / 2, y: height / 2 },
8544
+ { x: -width / 2, y: -height / 2 }
8545
+ ];
8546
+ elements.push(silkscreenpath(outline, { stroke_width: 0.1, layer: "top" }));
8547
+ }
8548
+ const refText = silkscreenRef(0, height / 2 + 1, 0.5);
8549
+ elements.push(refText);
8550
+ return {
8551
+ circuitJson: elements,
8552
+ parameters
8553
+ };
8554
+ };
8555
+
8556
+ // src/fn/to92l.ts
8557
+ import { z as z77 } from "zod";
8558
+ var to92l_def = base_def.extend({
8559
+ fn: z77.string(),
8560
+ num_pins: z77.number().default(3),
8561
+ inline: z77.boolean().default(false),
8562
+ p: z77.string().default("1.27mm"),
8563
+ id: z77.string().default("0.75mm"),
8564
+ od: z77.string().default("1.3mm"),
8565
+ w: z77.string().default("4.8mm"),
8566
+ h: z77.string().default("4.0mm")
8322
8567
  });
8323
8568
  var to92l = (raw_params) => {
8324
8569
  const parameters = to92l_def.parse(raw_params);
@@ -8498,7 +8743,7 @@ var applyNoSilkscreen = (elements, parameters) => {
8498
8743
  // src/footprinter.ts
8499
8744
  var string2 = (def) => {
8500
8745
  let fp2 = footprinter();
8501
- const modifiedDef = def.replace(/^((?:\d{4}|\d{5}))(?=$|_)/, "res$1");
8746
+ const modifiedDef = def.replace(/^((?:\d{4}|\d{5}))(?=$|_|x)/, "res$1");
8502
8747
  const def_parts = modifiedDef.split(/_(?!metric)/).map((s) => {
8503
8748
  const m = s.match(/([a-zA-Z]+)([\(\d\.\+\?].*)?/);
8504
8749
  if (!m) return null;