jscad-electronics 0.0.236 → 0.0.237

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
@@ -748,7 +748,7 @@ var Crystal = ({
748
748
  ] });
749
749
  };
750
750
 
751
- // .model-contracts/generations/fa75ee0265d6d666dfb181dbec270fd94d15a3b5-v2/node_modules/zod/v3/external.js
751
+ // .model-contracts/generations/e80fbad5260b66fd00b4ab7513941eadd9b0b17b-v2/node_modules/zod/v3/external.js
752
752
  var external_exports = {};
753
753
  __export(external_exports, {
754
754
  BRAND: () => BRAND,
@@ -860,7 +860,7 @@ __export(external_exports, {
860
860
  void: () => voidType
861
861
  });
862
862
 
863
- // .model-contracts/generations/fa75ee0265d6d666dfb181dbec270fd94d15a3b5-v2/node_modules/zod/v3/helpers/util.js
863
+ // .model-contracts/generations/e80fbad5260b66fd00b4ab7513941eadd9b0b17b-v2/node_modules/zod/v3/helpers/util.js
864
864
  var util;
865
865
  (function(util2) {
866
866
  util2.assertEqual = (_) => {
@@ -994,7 +994,7 @@ var getParsedType = (data) => {
994
994
  }
995
995
  };
996
996
 
997
- // .model-contracts/generations/fa75ee0265d6d666dfb181dbec270fd94d15a3b5-v2/node_modules/zod/v3/ZodError.js
997
+ // .model-contracts/generations/e80fbad5260b66fd00b4ab7513941eadd9b0b17b-v2/node_modules/zod/v3/ZodError.js
998
998
  var ZodIssueCode = util.arrayToEnum([
999
999
  "invalid_type",
1000
1000
  "invalid_literal",
@@ -1112,7 +1112,7 @@ ZodError.create = (issues) => {
1112
1112
  return error;
1113
1113
  };
1114
1114
 
1115
- // .model-contracts/generations/fa75ee0265d6d666dfb181dbec270fd94d15a3b5-v2/node_modules/zod/v3/locales/en.js
1115
+ // .model-contracts/generations/e80fbad5260b66fd00b4ab7513941eadd9b0b17b-v2/node_modules/zod/v3/locales/en.js
1116
1116
  var errorMap = (issue, _ctx) => {
1117
1117
  let message;
1118
1118
  switch (issue.code) {
@@ -1215,7 +1215,7 @@ var errorMap = (issue, _ctx) => {
1215
1215
  };
1216
1216
  var en_default = errorMap;
1217
1217
 
1218
- // .model-contracts/generations/fa75ee0265d6d666dfb181dbec270fd94d15a3b5-v2/node_modules/zod/v3/errors.js
1218
+ // .model-contracts/generations/e80fbad5260b66fd00b4ab7513941eadd9b0b17b-v2/node_modules/zod/v3/errors.js
1219
1219
  var overrideErrorMap = en_default;
1220
1220
  function setErrorMap(map) {
1221
1221
  overrideErrorMap = map;
@@ -1224,7 +1224,7 @@ function getErrorMap() {
1224
1224
  return overrideErrorMap;
1225
1225
  }
1226
1226
 
1227
- // .model-contracts/generations/fa75ee0265d6d666dfb181dbec270fd94d15a3b5-v2/node_modules/zod/v3/helpers/parseUtil.js
1227
+ // .model-contracts/generations/e80fbad5260b66fd00b4ab7513941eadd9b0b17b-v2/node_modules/zod/v3/helpers/parseUtil.js
1228
1228
  var makeIssue = (params) => {
1229
1229
  const { data, path, errorMaps, issueData } = params;
1230
1230
  const fullPath = [...path, ...issueData.path || []];
@@ -1334,14 +1334,14 @@ var isDirty = (x) => x.status === "dirty";
1334
1334
  var isValid = (x) => x.status === "valid";
1335
1335
  var isAsync = (x) => typeof Promise !== "undefined" && x instanceof Promise;
1336
1336
 
1337
- // .model-contracts/generations/fa75ee0265d6d666dfb181dbec270fd94d15a3b5-v2/node_modules/zod/v3/helpers/errorUtil.js
1337
+ // .model-contracts/generations/e80fbad5260b66fd00b4ab7513941eadd9b0b17b-v2/node_modules/zod/v3/helpers/errorUtil.js
1338
1338
  var errorUtil;
1339
1339
  (function(errorUtil2) {
1340
1340
  errorUtil2.errToObj = (message) => typeof message === "string" ? { message } : message || {};
1341
1341
  errorUtil2.toString = (message) => typeof message === "string" ? message : message?.message;
1342
1342
  })(errorUtil || (errorUtil = {}));
1343
1343
 
1344
- // .model-contracts/generations/fa75ee0265d6d666dfb181dbec270fd94d15a3b5-v2/node_modules/zod/v3/types.js
1344
+ // .model-contracts/generations/e80fbad5260b66fd00b4ab7513941eadd9b0b17b-v2/node_modules/zod/v3/types.js
1345
1345
  var ParseInputLazyPath = class {
1346
1346
  constructor(parent, value, path, key) {
1347
1347
  this._cachedPath = [];
@@ -4789,7 +4789,7 @@ var coerce = {
4789
4789
  };
4790
4790
  var NEVER = INVALID;
4791
4791
 
4792
- // .model-contracts/generations/fa75ee0265d6d666dfb181dbec270fd94d15a3b5-v2/node_modules/@tscircuit/mm/dist/index.js
4792
+ // .model-contracts/generations/e80fbad5260b66fd00b4ab7513941eadd9b0b17b-v2/node_modules/@tscircuit/mm/dist/index.js
4793
4793
  var unitToMm = {
4794
4794
  in: 25.4,
4795
4795
  inch: 25.4,
@@ -4816,7 +4816,7 @@ var mm = (n) => {
4816
4816
  throw new Error(`Unsupported unit: ${unit}`);
4817
4817
  };
4818
4818
 
4819
- // .model-contracts/generations/fa75ee0265d6d666dfb181dbec270fd94d15a3b5-v2/index.js
4819
+ // .model-contracts/generations/e80fbad5260b66fd00b4ab7513941eadd9b0b17b-v2/index.js
4820
4820
  function normalizeNemaMotorModelString(value) {
4821
4821
  if (!/^nema(?:8|17|23|34)(?:_|$)/i.test(value)) return value;
4822
4822
  return value.replace(/(^|_)jst([0-9]+)_(ph|sh)(?=_|$)/gi, "$1jst$3$2").replace(/(^|_)jst[_-](ph|sh)[_-]([0-9]+)(?=_|$)/gi, "$1jst$2$3").replace(/(^|_)none(?=_|$)/gi, "$1nowires").replace(/(^|_)stubs(?=_|$)/gi, "$1wirestubs");
@@ -4872,36 +4872,6 @@ var parseModelStringParams = (definition) => {
4872
4872
  params.string = normalizedDefinition;
4873
4873
  return params;
4874
4874
  };
4875
- function expandModelStringFlags(value, flags10) {
4876
- return splitModelStringTokens(value).map(
4877
- (token, index) => index > 0 && Object.hasOwn(flags10, token.toLowerCase()) ? flags10[token.toLowerCase()] : token
4878
- ).join("_");
4879
- }
4880
- function normalizeModelStringFlags(value, flags10, parse, omittedFlags) {
4881
- const tokens = splitModelStringTokens(value);
4882
- if (!tokens.slice(1).some((token) => Object.hasOwn(flags10, token.toLowerCase())))
4883
- return value;
4884
- const expanded = expandModelStringFlags(value, flags10);
4885
- parse(parseModelStringParams(expanded));
4886
- const preferred = new Map(
4887
- Object.entries(flags10).map(([flag, selector]) => [selector, flag])
4888
- );
4889
- const omitted = new Set(omittedFlags.map((flag) => flags10[flag]));
4890
- return splitModelStringTokens(expanded).flatMap((token, index) => {
4891
- if (index === 0) return [token.toLowerCase()];
4892
- const lower = token.toLowerCase();
4893
- if (omitted.has(lower)) return [];
4894
- return [preferred.get(lower) ?? token];
4895
- }).join("_");
4896
- }
4897
- var stringFlags = {
4898
- hex: "drive(hex)",
4899
- fullthread: "thread(full)",
4900
- lefthanded: "threadhand(left)",
4901
- righthanded: "threadhand(right)",
4902
- male: "threadgender(male)"
4903
- };
4904
- var omittedStringFlags = ["righthanded", "male"];
4905
4875
  function defineModel(model552) {
4906
4876
  return model552;
4907
4877
  }
@@ -5048,11 +5018,11 @@ var hexBoltModelPropsShape = {
5048
5018
  iso4017: external_exports.literal(true).default(true),
5049
5019
  metricSize: hexBoltMetricSizeSchema,
5050
5020
  length: positiveModelLengthSchema2,
5051
- thread: external_exports.literal("full").default("full"),
5052
- drive: external_exports.literal("hex").default("hex"),
5053
- threadHand: external_exports.enum(["right", "left"]).default("right"),
5021
+ fullThread: external_exports.literal(true).default(true),
5022
+ hex: external_exports.literal(true).default(true),
5023
+ leftHanded: external_exports.boolean().default(false),
5054
5024
  threadClass: external_exports.literal("6g").default("6g"),
5055
- threadGender: external_exports.literal("male").default("male"),
5025
+ male: external_exports.literal(true).default(true),
5056
5026
  showThreads: external_exports.boolean().default(true),
5057
5027
  diameter: positiveModelLengthSchema2.optional(),
5058
5028
  threadPitch: positiveModelLengthSchema2.optional(),
@@ -5097,11 +5067,7 @@ var aliases = {
5097
5067
  metricsize: "metricSize",
5098
5068
  l: "length",
5099
5069
  length: "length",
5100
- thread: "thread",
5101
- drive: "drive",
5102
- threadhand: "threadHand",
5103
5070
  threadclass: "threadClass",
5104
- threadgender: "threadGender",
5105
5071
  diameter: "diameter",
5106
5072
  threadpitch: "threadPitch",
5107
5073
  headacrossflats: "headAcrossFlats",
@@ -5119,19 +5085,18 @@ var aliases = {
5119
5085
  headh: "headHeight",
5120
5086
  af: "headAcrossFlats"
5121
5087
  };
5122
- var selectors = /* @__PURE__ */ new Set([
5123
- "thread",
5124
- "drive",
5125
- "threadHand",
5126
- "threadClass",
5127
- "threadGender"
5128
- ]);
5088
+ var selectors = /* @__PURE__ */ new Set(["threadClass"]);
5089
+ var booleanFlags = {
5090
+ hex: { property: "hex", value: true },
5091
+ fullthread: { property: "fullThread", value: true },
5092
+ male: { property: "male", value: true },
5093
+ lefthanded: { property: "leftHanded", value: true },
5094
+ righthanded: { property: "leftHanded", value: false }
5095
+ };
5129
5096
  var parseHexBoltModelParams = (raw) => {
5130
5097
  if (raw.fn !== "hexbolt")
5131
5098
  throw new Error(`Expected hexbolt params, got "${raw.fn}"`);
5132
- const [root, ...tokens] = splitModelStringTokens(
5133
- expandModelStringFlags(raw.string, stringFlags)
5134
- );
5099
+ const [root, ...tokens] = splitModelStringTokens(raw.string);
5135
5100
  if (root?.toLowerCase() !== "hexbolt")
5136
5101
  throw new Error("The hexbolt function does not accept an inline value");
5137
5102
  const props = {};
@@ -5147,13 +5112,17 @@ var parseHexBoltModelParams = (raw) => {
5147
5112
  const value = match?.[2];
5148
5113
  let property;
5149
5114
  let parsed;
5150
- if (key === "threads" || key === "nothreads") {
5115
+ if (key && Object.hasOwn(booleanFlags, key)) {
5116
+ if (value !== "") throw new Error(`Flag "${key}" does not accept a value`);
5117
+ property = booleanFlags[key].property;
5118
+ parsed = booleanFlags[key].value;
5119
+ } else if (key === "threads" || key === "nothreads") {
5151
5120
  if (value !== "")
5152
5121
  throw new Error(`Token "${key}" does not accept a value`);
5153
5122
  property = "showThreads";
5154
5123
  parsed = key === "threads";
5155
5124
  } else {
5156
- property = key ? aliases[key] ?? "" : "";
5125
+ property = key && Object.hasOwn(aliases, key) ? aliases[key] : "";
5157
5126
  if (!property || !value)
5158
5127
  throw new Error(`Unknown or missing hexbolt token "${token}"`);
5159
5128
  if (selectors.has(property)) {
@@ -5185,13 +5154,7 @@ var parseHexBoltModelParams = (raw) => {
5185
5154
  var model = defineModel({
5186
5155
  name: "hexbolt",
5187
5156
  schema: hexBoltModelDefinitionSchema,
5188
- parse: parseHexBoltModelParams,
5189
- normalizeString: (value) => normalizeModelStringFlags(
5190
- value,
5191
- stringFlags,
5192
- parseHexBoltModelParams,
5193
- omittedStringFlags
5194
- )
5157
+ parse: parseHexBoltModelParams
5195
5158
  });
5196
5159
  function register(registry2) {
5197
5160
  registry2.register(model);
@@ -5298,11 +5261,11 @@ var shape2 = {
5298
5261
  /** Unsigned pitch-cylinder helix angle to +Z, in degrees. */
5299
5262
  helixAngle: external_exports.number().finite().min(0).lt(90).default(20),
5300
5263
  /** Right-hand teeth advance counterclockwise as Z increases. */
5301
- handedness: external_exports.enum(["right", "left"]).default("right"),
5264
+ leftHanded: external_exports.boolean().default(false),
5302
5265
  segmentsPerTurn: external_exports.number().int().min(12).max(128).default(32)
5303
5266
  };
5304
5267
  function dimensions2(props) {
5305
- const { helixAngle, handedness, segmentsPerTurn, ...spur } = props;
5268
+ const { helixAngle, leftHanded, segmentsPerTurn, ...spur } = props;
5306
5269
  const d = getSpurGearDimensions(spur);
5307
5270
  const beta = helixAngle * Math.PI / 180;
5308
5271
  return {
@@ -5313,18 +5276,18 @@ function dimensions2(props) {
5313
5276
  ) * 180 / Math.PI,
5314
5277
  normalPitch: d.circularPitch * Math.cos(beta),
5315
5278
  /** Signed angular advance between the lower and upper faces, in degrees. */
5316
- twistAngle: helixAngle === 0 ? 0 : (handedness === "right" ? 1 : -1) * (2 * props.faceWidth / d.pitchDiameter * Math.tan(beta) * 180) / Math.PI
5279
+ twistAngle: helixAngle === 0 ? 0 : (leftHanded ? -1 : 1) * (2 * props.faceWidth / d.pitchDiameter * Math.tan(beta) * 180) / Math.PI
5317
5280
  };
5318
5281
  }
5319
5282
  function validate2(props, context) {
5320
- const { fn, helixAngle, handedness, segmentsPerTurn, ...spur } = props;
5283
+ const { fn, helixAngle, leftHanded, segmentsPerTurn, ...spur } = props;
5321
5284
  const result = spurGearModelPropsSchema.safeParse(spur);
5322
5285
  if (!result.success) {
5323
5286
  for (const issue of result.error.issues) context.addIssue(issue);
5324
5287
  return;
5325
5288
  }
5326
5289
  if (Object.values(
5327
- dimensions2({ ...result.data, helixAngle, handedness, segmentsPerTurn })
5290
+ dimensions2({ ...result.data, helixAngle, leftHanded, segmentsPerTurn })
5328
5291
  ).some((value) => !Number.isFinite(value)))
5329
5292
  context.addIssue({
5330
5293
  code: "custom",
@@ -5358,7 +5321,7 @@ function parseHelicalGearModelParams(raw) {
5358
5321
  const [name, value] = parseGearToken(token);
5359
5322
  let property;
5360
5323
  let parsed;
5361
- if (name in lengths) {
5324
+ if (Object.hasOwn(lengths, name)) {
5362
5325
  property = lengths[name];
5363
5326
  parsed = value;
5364
5327
  } else if (name === "teeth" || name === "segments" || name === "turnsegments") {
@@ -5370,8 +5333,8 @@ function parseHelicalGearModelParams(raw) {
5370
5333
  } else if (name === "right" || name === "left") {
5371
5334
  if (value)
5372
5335
  throw new Error(`Helical flag "${name}" does not accept a value`);
5373
- property = "handedness";
5374
- parsed = name;
5336
+ property = "leftHanded";
5337
+ parsed = name === "left";
5375
5338
  } else throw new Error(`Unknown helical gear token "${token}"`);
5376
5339
  if (property in props)
5377
5340
  throw new Error(
@@ -5524,7 +5487,8 @@ var nemaMotorDimensions = {
5524
5487
  pilotLength: 1.5,
5525
5488
  shaftDiameter: 4,
5526
5489
  shaftLength: 15,
5527
- shaftShape: "round",
5490
+ roundShaft: true,
5491
+ dShaft: false,
5528
5492
  shaftFlatDepth: 0.5,
5529
5493
  shaftFlatLength: 10,
5530
5494
  shaftFlatAngle: 0,
@@ -5546,7 +5510,8 @@ var nemaMotorDimensions = {
5546
5510
  pilotLength: 2,
5547
5511
  shaftDiameter: 5,
5548
5512
  shaftLength: 24,
5549
- shaftShape: "d",
5513
+ roundShaft: false,
5514
+ dShaft: true,
5550
5515
  shaftFlatDepth: 0.5,
5551
5516
  shaftFlatLength: 15,
5552
5517
  shaftFlatAngle: 0,
@@ -5568,7 +5533,8 @@ var nemaMotorDimensions = {
5568
5533
  pilotLength: 1.6,
5569
5534
  shaftDiameter: 6.35,
5570
5535
  shaftLength: 20.6,
5571
- shaftShape: "d",
5536
+ roundShaft: false,
5537
+ dShaft: true,
5572
5538
  shaftFlatDepth: 0.5,
5573
5539
  shaftFlatLength: 15,
5574
5540
  shaftFlatAngle: 0,
@@ -5593,7 +5559,8 @@ var nemaMotorDimensions = {
5593
5559
  pilotLength: 1.6,
5594
5560
  shaftDiameter: 14,
5595
5561
  shaftLength: 32,
5596
- shaftShape: "round",
5562
+ roundShaft: true,
5563
+ dShaft: false,
5597
5564
  shaftFlatDepth: 0.5,
5598
5565
  shaftFlatLength: 15,
5599
5566
  shaftFlatAngle: 0,
@@ -5606,13 +5573,18 @@ var nemaMotorDimensions = {
5606
5573
  var shape3 = {
5607
5574
  nemaSize: nemaSizeSchema,
5608
5575
  /** Rear cap at Z=-bodyLength: bare, open bores or installed cap screws. */
5609
- backFace: external_exports.enum(["plain", "holes", "screws"]).optional(),
5576
+ backFacePlain: external_exports.boolean().optional(),
5577
+ backFaceHoles: external_exports.boolean().optional(),
5578
+ backFaceScrews: external_exports.boolean().optional(),
5610
5579
  backFaceHoleSpacing: positiveModelLengthSchema.optional(),
5611
5580
  backFaceHoleDiameter: positiveModelLengthSchema.optional(),
5612
5581
  backFaceHoleDepth: positiveModelLengthSchema.optional(),
5613
5582
  backFaceScrewSize: metricBoltSizeSchema.optional(),
5614
5583
  /** Visual termination; the wireside reference exists even when hidden. */
5615
- wireConnection: external_exports.union([external_exports.enum(["none", "stubs"]), jstMotorWireConnectionSchema]).optional(),
5584
+ noWires: external_exports.boolean().optional(),
5585
+ wireStubs: external_exports.boolean().optional(),
5586
+ /** JST catalog designation, mutually exclusive with the visible-wire flags. */
5587
+ wireConnection: jstMotorWireConnectionSchema.optional(),
5616
5588
  /** Counterclockwise angle about local +Z; 0 is the +X side. */
5617
5589
  wireSideAngle: external_exports.number().finite().optional(),
5618
5590
  wireLength: positiveModelLengthSchema.optional(),
@@ -5629,7 +5601,8 @@ var shape3 = {
5629
5601
  /** Distance from mounting face Z=0 to shaft tip, including pilot height. */
5630
5602
  shaftLength: positiveModelLengthSchema.optional(),
5631
5603
  shaftDiameter: positiveModelLengthSchema.optional(),
5632
- shaftShape: external_exports.enum(["round", "d"]).optional(),
5604
+ roundShaft: external_exports.boolean().optional(),
5605
+ dShaft: external_exports.boolean().optional(),
5633
5606
  /** Radial material removed from the +X side before rotation. */
5634
5607
  shaftFlatDepth: nonnegativeModelLengthSchema.optional(),
5635
5608
  /** Flat extends back from the tip; leaves a round shoulder above the pilot. */
@@ -5642,20 +5615,54 @@ var shape3 = {
5642
5615
  bodyCornerChamfer: nonnegativeModelLengthSchema.optional(),
5643
5616
  /** Rear outline is independent of the front mounting flange. */
5644
5617
  rearCornerChamfer: nonnegativeModelLengthSchema.optional(),
5645
- cornerProfile: external_exports.enum(["chamfered", "stepped"]).optional()
5618
+ chamfered: external_exports.boolean().optional(),
5619
+ stepped: external_exports.boolean().optional()
5646
5620
  };
5647
- var resolve = (p) => {
5621
+ var resolve = (p, ctx) => {
5622
+ const select = (flags11, fallback) => {
5623
+ const selected = flags11.filter((flag) => p[flag] === true);
5624
+ const specified = flags11.some((flag) => p[flag] !== void 0);
5625
+ if (selected.length > 1 || specified && selected.length === 0)
5626
+ ctx.addIssue({
5627
+ code: "custom",
5628
+ message: `Select exactly one of ${flags11.join(", ")}`
5629
+ });
5630
+ return selected[0] ?? fallback;
5631
+ };
5632
+ const back = select(
5633
+ ["backFacePlain", "backFaceHoles", "backFaceScrews"],
5634
+ p.nemaSize === 34 ? "backFacePlain" : "backFaceScrews"
5635
+ );
5636
+ const shaft = select(
5637
+ ["roundShaft", "dShaft"],
5638
+ nemaMotorDimensions[p.nemaSize].roundShaft ? "roundShaft" : "dShaft"
5639
+ );
5640
+ const corner = select(
5641
+ ["chamfered", "stepped"],
5642
+ p.nemaSize === 34 ? "stepped" : "chamfered"
5643
+ );
5644
+ const wireSpecified = p.noWires !== void 0 || p.wireStubs !== void 0 || p.wireConnection !== void 0;
5645
+ const wireSelections = Number(p.noWires === true) + Number(p.wireStubs === true) + Number(p.wireConnection !== void 0);
5646
+ if (wireSelections > 1 || wireSpecified && wireSelections === 0)
5647
+ ctx.addIssue({
5648
+ code: "custom",
5649
+ message: "Select exactly one of noWires, wireStubs or a JST wireConnection"
5650
+ });
5648
5651
  const d = nemaMotorDimensions[p.nemaSize];
5649
5652
  const backFaceScrewSize = p.backFaceScrewSize ?? d.backFaceScrewSize;
5650
5653
  const screw = hexSocketBoltDimensions[backFaceScrewSize];
5651
5654
  return {
5652
5655
  nemaSize: p.nemaSize,
5653
- wireConnection: p.wireConnection ?? "stubs",
5656
+ noWires: p.noWires === true,
5657
+ wireStubs: p.wireStubs === true || !wireSpecified,
5658
+ ...p.wireConnection !== void 0 ? { wireConnection: p.wireConnection } : {},
5654
5659
  wireSideAngle: ((p.wireSideAngle ?? (p.nemaSize === 34 ? 90 : 0)) % 360 + 360) % 360,
5655
5660
  wireLength: p.wireLength ?? (p.nemaSize === 34 ? 25 : 6),
5656
5661
  wireDiameter: p.wireDiameter ?? (p.nemaSize === 34 ? 2 : 1.2),
5657
5662
  wireCount: p.wireCount ?? 4,
5658
- backFace: p.backFace ?? (p.nemaSize === 34 ? "plain" : "screws"),
5663
+ backFacePlain: back === "backFacePlain",
5664
+ backFaceHoles: back === "backFaceHoles",
5665
+ backFaceScrews: back === "backFaceScrews",
5659
5666
  backFaceHoleSpacing: p.backFaceHoleSpacing ?? ("backFaceHoleSpacing" in d ? d.backFaceHoleSpacing : p.mountingHoleSpacing ?? d.mountingHoleSpacing),
5660
5667
  backFaceHoleDiameter: p.backFaceHoleDiameter ?? screw.diameter,
5661
5668
  backFaceHoleDepth: p.backFaceHoleDepth ?? d.backFaceHoleDepth,
@@ -5670,7 +5677,8 @@ var resolve = (p) => {
5670
5677
  pilotLength: p.pilotLength ?? d.pilotLength,
5671
5678
  shaftDiameter: p.shaftDiameter ?? d.shaftDiameter,
5672
5679
  shaftLength: p.shaftLength ?? d.shaftLength,
5673
- shaftShape: p.shaftShape ?? d.shaftShape,
5680
+ roundShaft: shaft === "roundShaft",
5681
+ dShaft: shaft === "dShaft",
5674
5682
  shaftFlatDepth: p.shaftFlatDepth ?? d.shaftFlatDepth,
5675
5683
  shaftFlatLength: p.shaftFlatLength ?? d.shaftFlatLength,
5676
5684
  shaftFlatAngle: p.shaftFlatAngle ?? d.shaftFlatAngle,
@@ -5678,7 +5686,8 @@ var resolve = (p) => {
5678
5686
  rearCapLength: p.rearCapLength ?? d.rearCapLength,
5679
5687
  faceCornerChamfer: p.faceCornerChamfer ?? d.faceCornerChamfer,
5680
5688
  bodyCornerChamfer: p.bodyCornerChamfer ?? d.bodyCornerChamfer,
5681
- ...p.nemaSize === 34 || p.cornerProfile !== void 0 ? { cornerProfile: p.cornerProfile ?? "stepped" } : {},
5689
+ chamfered: corner === "chamfered",
5690
+ stepped: corner === "stepped",
5682
5691
  ..."rearCornerChamfer" in d || p.rearCornerChamfer !== void 0 ? {
5683
5692
  rearCornerChamfer: p.rearCornerChamfer ?? ("rearCornerChamfer" in d ? d.rearCornerChamfer : p.faceCornerChamfer ?? d.faceCornerChamfer)
5684
5693
  } : {}
@@ -5686,27 +5695,27 @@ var resolve = (p) => {
5686
5695
  };
5687
5696
  var validate3 = (p, ctx) => {
5688
5697
  const issue = (message) => ctx.addIssue({ code: "custom", message });
5689
- const rearChamfer = p.rearCornerChamfer ?? (p.backFace === "plain" && p.mountingHoleThrough ? p.bodyCornerChamfer : p.faceCornerChamfer);
5690
- const rearEdge = p.cornerProfile === "stepped" ? rearChamfer / Math.SQRT2 : rearChamfer;
5691
- if (p.backFace !== "plain") {
5698
+ const rearChamfer = p.rearCornerChamfer ?? (p.backFacePlain && p.mountingHoleThrough ? p.bodyCornerChamfer : p.faceCornerChamfer);
5699
+ const rearEdge = p.stepped ? rearChamfer / Math.SQRT2 : rearChamfer;
5700
+ if (!p.backFacePlain) {
5692
5701
  const screw = hexSocketBoltDimensions[p.backFaceScrewSize];
5693
- const radius = (p.backFace === "screws" ? Math.max(p.backFaceHoleDiameter, screw.headDiameter) : p.backFaceHoleDiameter) / 2;
5702
+ const radius = (p.backFaceScrews ? Math.max(p.backFaceHoleDiameter, screw.headDiameter) : p.backFaceHoleDiameter) / 2;
5694
5703
  if (p.backFaceHoleSpacing <= 2 * radius)
5695
5704
  issue("Rear holes and screw heads must not overlap each other");
5696
- if (p.backFaceHoleSpacing + 2 * radius >= p.bodyWidth || (p.cornerProfile === "stepped" ? p.backFaceHoleSpacing + 2 * radius >= p.bodyWidth - 2 * rearEdge : p.bodyWidth - rearChamfer - p.backFaceHoleSpacing <= radius * Math.SQRT2))
5705
+ if (p.backFaceHoleSpacing + 2 * radius >= p.bodyWidth || (p.stepped ? p.backFaceHoleSpacing + 2 * radius >= p.bodyWidth - 2 * rearEdge : p.bodyWidth - rearChamfer - p.backFaceHoleSpacing <= radius * Math.SQRT2))
5697
5706
  issue("Rear holes and screw heads must fit entirely inside the rear face");
5698
5707
  if (p.backFaceHoleDepth >= p.rearCapLength)
5699
5708
  issue("Rear hole depth must be less than the rear cap length");
5700
- if (p.backFace === "screws" && p.backFaceHoleDiameter < screw.diameter)
5709
+ if (p.backFaceScrews && p.backFaceHoleDiameter < screw.diameter)
5701
5710
  issue("Rear holes must accommodate the screw diameter");
5702
5711
  }
5703
- if (p.wireConnection === "stubs") {
5712
+ if (p.wireStubs) {
5704
5713
  if (p.wireDiameter * p.wireCount * 1.5 > p.bodyWidth - 2 * rearEdge)
5705
5714
  issue("Wire bundle must fit on the cap side");
5706
5715
  if (p.wireDiameter >= p.rearCapLength)
5707
5716
  issue("Wire diameter must fit within the rear cap");
5708
5717
  }
5709
- const connector = getJstMotorConnector(p.wireConnection);
5718
+ const connector = p.wireConnection === void 0 ? void 0 : getJstMotorConnector(p.wireConnection);
5710
5719
  if (connector && p.bodyWidth - 2 * rearEdge < connector.bodyWidth)
5711
5720
  issue("JST header must fit on the motor side");
5712
5721
  const r = p.mountingHoleDiameter / 2;
@@ -5724,17 +5733,17 @@ var validate3 = (p, ctx) => {
5724
5733
  issue("Mounting holes must clear the pilot");
5725
5734
  if (!p.mountingHoleThrough && p.mountingHoleDepth >= p.frontCapLength)
5726
5735
  issue("Blind mounting hole depth must be less than the front cap length");
5727
- if (p.mountingHoleThrough && (p.cornerProfile === "stepped" ? p.bodyWidth / 2 - p.bodyCornerChamfer / Math.SQRT2 + Math.min(4, p.bodyCornerChamfer / Math.SQRT2 / 4) >= p.mountingHoleSpacing / 2 - r : p.bodyWidth - p.bodyCornerChamfer - p.mountingHoleSpacing >= -r * Math.SQRT2))
5736
+ if (p.mountingHoleThrough && (p.stepped ? p.bodyWidth / 2 - p.bodyCornerChamfer / Math.SQRT2 + Math.min(4, p.bodyCornerChamfer / Math.SQRT2 / 4) >= p.mountingHoleSpacing / 2 - r : p.bodyWidth - p.bodyCornerChamfer - p.mountingHoleSpacing >= -r * Math.SQRT2))
5728
5737
  issue("Body must clear through front mounting holes");
5729
5738
  if (p.shaftLength <= p.pilotLength)
5730
5739
  issue("Shaft tip must extend beyond the pilot");
5731
- if (p.shaftShape === "d" && (p.shaftFlatDepth <= 0 || p.shaftFlatDepth >= p.shaftDiameter / 2 || p.shaftFlatLength <= 0 || p.shaftFlatLength > p.shaftLength - p.pilotLength))
5740
+ if (p.dShaft && (p.shaftFlatDepth <= 0 || p.shaftFlatDepth >= p.shaftDiameter / 2 || p.shaftFlatLength <= 0 || p.shaftFlatLength > p.shaftLength - p.pilotLength))
5732
5741
  issue(
5733
5742
  "D flat must have positive depth less than the shaft radius and fit above the pilot"
5734
5743
  );
5735
5744
  };
5736
5745
  var nemaMotorModelPropsSchema = external_exports.object(shape3).strict().transform(resolve).superRefine(validate3);
5737
- var nemaMotorModelDefinitionSchema = external_exports.object({ fn: external_exports.literal("nema"), ...shape3 }).strict().transform(({ fn, ...props }) => ({ fn, ...resolve(props) })).superRefine(validate3);
5746
+ var nemaMotorModelDefinitionSchema = external_exports.object({ fn: external_exports.literal("nema"), ...shape3 }).strict().transform(({ fn, ...props }, ctx) => ({ fn, ...resolve(props, ctx) })).superRefine(validate3);
5738
5747
  var lengths2 = {
5739
5748
  wirelength: "wireLength",
5740
5749
  wirediameter: "wireDiameter",
@@ -5760,6 +5769,19 @@ var lengths2 = {
5760
5769
  bodychamfer: "bodyCornerChamfer",
5761
5770
  rearchamfer: "rearCornerChamfer"
5762
5771
  };
5772
+ var flags = {
5773
+ backfaceplain: "backFacePlain",
5774
+ plainbackface: "backFacePlain",
5775
+ backfaceholes: "backFaceHoles",
5776
+ backfacescrews: "backFaceScrews",
5777
+ round: "roundShaft",
5778
+ roundshaft: "roundShaft",
5779
+ dshaft: "dShaft",
5780
+ chamfered: "chamfered",
5781
+ stepped: "stepped",
5782
+ nowires: "noWires",
5783
+ wirestubs: "wireStubs"
5784
+ };
5763
5785
  function parseNemaMotorModelParams(raw) {
5764
5786
  const tokens = normalizeNemaMotorModelString(raw.string).split("_");
5765
5787
  const match = tokens[0]?.match(/^nema(8|17|23|34)$/i);
@@ -5776,20 +5798,15 @@ function parseNemaMotorModelParams(raw) {
5776
5798
  if (name in lengths2) {
5777
5799
  property = lengths2[name];
5778
5800
  parsed = value;
5779
- } else if (["backfaceholes", "backfacescrews", "plainbackface"].includes(name)) {
5801
+ } else if (name in flags) {
5780
5802
  if (value) throw new Error(`NEMA flag "${name}" does not accept a value`);
5781
- property = "backFace";
5782
- parsed = name === "backfaceholes" ? "holes" : name === "backfacescrews" ? "screws" : "plain";
5783
- } else if (["wirestubs", "nowires", "jstph", "jstsh"].includes(name)) {
5784
- const isJst = name === "jstph" || name === "jstsh";
5785
- if (isJst && !/^[1-9][0-9]*$/.test(value) || !isJst && value)
5803
+ property = flags[name];
5804
+ parsed = true;
5805
+ } else if (name === "jstph" || name === "jstsh") {
5806
+ if (!/^[1-9][0-9]*$/.test(value))
5786
5807
  throw new Error(`Invalid wire connection token "${token}"`);
5787
5808
  property = "wireConnection";
5788
- parsed = isJst ? `jst-${name.slice(3)}-${value}` : name === "nowires" ? "none" : "stubs";
5789
- } else if (name === "stepped" || name === "chamfered") {
5790
- if (value) throw new Error(`NEMA flag "${name}" does not accept a value`);
5791
- property = "cornerProfile";
5792
- parsed = name;
5809
+ parsed = `jst-${name.slice(3)}-${value}`;
5793
5810
  } else if (name === "wirecount") {
5794
5811
  property = "wireCount";
5795
5812
  if (!/^\d+$/.test(value)) throw new Error("wirecount requires an integer");
@@ -5802,10 +5819,10 @@ function parseNemaMotorModelParams(raw) {
5802
5819
  if (!/^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:deg)?$/i.test(value))
5803
5820
  throw new Error(`${name} requires a numeric angle in degrees`);
5804
5821
  parsed = Number(value.replace(/deg$/i, ""));
5805
- } else if (["round", "dshaft", "throughholes", "blindholes"].includes(name)) {
5822
+ } else if (name === "throughholes" || name === "blindholes") {
5806
5823
  if (value) throw new Error(`NEMA flag "${name}" does not accept a value`);
5807
- property = name === "round" || name === "dshaft" ? "shaftShape" : "mountingHoleThrough";
5808
- parsed = name === "round" ? "round" : name === "dshaft" ? "d" : name === "throughholes";
5824
+ property = "mountingHoleThrough";
5825
+ parsed = name === "throughholes";
5809
5826
  } else throw new Error(`Unknown NEMA motor token "${token}"`);
5810
5827
  if (property in props)
5811
5828
  throw new Error(`NEMA property "${property}" is set more than once`);
@@ -5828,22 +5845,26 @@ var holePosition = {
5828
5845
  u: modelLengthSchema,
5829
5846
  v: modelLengthSchema
5830
5847
  };
5831
- var sheetMetalHoleSchema = external_exports.discriminatedUnion("shape", [
5848
+ var sheetMetalHoleSchema = external_exports.union([
5832
5849
  external_exports.object({
5833
5850
  ...holePosition,
5834
- shape: external_exports.literal("round"),
5851
+ round: external_exports.literal(true),
5852
+ slot: external_exports.literal(false).default(false),
5835
5853
  diameter: positiveModelLengthSchema
5836
5854
  }).strict(),
5837
5855
  external_exports.object({
5838
5856
  ...holePosition,
5839
- shape: external_exports.literal("slot"),
5857
+ round: external_exports.literal(false).default(false),
5858
+ slot: external_exports.literal(true),
5840
5859
  length: positiveModelLengthSchema,
5841
5860
  width: positiveModelLengthSchema,
5842
5861
  axis: external_exports.enum(["u", "v"]).default("v")
5843
5862
  }).strict()
5844
5863
  ]);
5845
5864
  var sheetMetalShape = {
5846
- profile: external_exports.enum(["plate", "angle", "channel"]).default("plate"),
5865
+ plate: external_exports.boolean().default(false),
5866
+ angle: external_exports.boolean().default(false),
5867
+ channel: external_exports.boolean().default(false),
5847
5868
  width: positiveModelLengthSchema,
5848
5869
  /** Straight base length between bend tangencies, not overall width. */
5849
5870
  baseLength: positiveModelLengthSchema,
@@ -5853,9 +5874,19 @@ var sheetMetalShape = {
5853
5874
  insideBendRadius: positiveModelLengthSchema.default(1),
5854
5875
  holes: external_exports.array(sheetMetalHoleSchema).max(100).default([])
5855
5876
  };
5856
- var sheetMetalModelPropsSchema = external_exports.object(sheetMetalShape).strict();
5857
- var sheetMetalModelDefinitionSchema = external_exports.object({ fn: external_exports.literal("sheetmetal"), ...sheetMetalShape }).strict();
5858
- function parseSheetMetalFeature(feature, profile6) {
5877
+ function validateFlags(props, context) {
5878
+ if ([props.plate, props.angle, props.channel].filter(Boolean).length > 1)
5879
+ context.addIssue({
5880
+ code: "custom",
5881
+ message: "Specify at most one of plate, angle, or channel"
5882
+ });
5883
+ }
5884
+ function resolveFlags(props) {
5885
+ return { ...props, plate: props.plate || !(props.angle || props.channel) };
5886
+ }
5887
+ var sheetMetalModelPropsSchema = external_exports.object(sheetMetalShape).strict().superRefine(validateFlags).transform(resolveFlags);
5888
+ var sheetMetalModelDefinitionSchema = external_exports.object({ fn: external_exports.literal("sheetmetal"), ...sheetMetalShape }).strict().superRefine(validateFlags).transform((props) => ({ fn: props.fn, ...resolveFlags(props) }));
5889
+ function parseSheetMetalFeature(feature, flags11) {
5859
5890
  const match = feature.match(/^(hole|slot)[1-9]\d*\(([^()]+)\)$/);
5860
5891
  if (!match) throw new Error(`Invalid sheet metal feature "${feature}"`);
5861
5892
  const kind = match[1];
@@ -5888,8 +5919,8 @@ function parseSheetMetalFeature(feature, profile6) {
5888
5919
  if (faces.length !== 1)
5889
5920
  throw new Error(`Specify exactly one face in ${feature}`);
5890
5921
  const face2 = faces[0];
5891
- if (face2 === "angledface" && profile6 !== "angle" || ["leftface", "rightface"].includes(face2) && profile6 !== "channel")
5892
- throw new Error(`No ${face2} on ${profile6}`);
5922
+ if (face2 === "angledface" && !flags11.angle || ["leftface", "rightface"].includes(face2) && !flags11.channel)
5923
+ throw new Error(`No ${face2} on the selected sheet metal form`);
5893
5924
  for (const [a, b] of [
5894
5925
  ["leftofcenter", "rightofcenter"],
5895
5926
  ["abovecenter", "belowcenter"],
@@ -5913,7 +5944,7 @@ function parseSheetMetalFeature(feature, profile6) {
5913
5944
  throw new Error(`Hole requires r or d in ${feature}`);
5914
5945
  return sheetMetalHoleSchema.parse({
5915
5946
  ...position,
5916
- shape: "round",
5947
+ round: true,
5917
5948
  diameter: "r" in values ? 2 * distance2("r") : distance2("d")
5918
5949
  });
5919
5950
  }
@@ -5923,7 +5954,7 @@ function parseSheetMetalFeature(feature, profile6) {
5923
5954
  if (length32 < width10) throw new Error("Slot length must be at least its width");
5924
5955
  return sheetMetalHoleSchema.parse({
5925
5956
  ...position,
5926
- shape: "slot",
5957
+ slot: true,
5927
5958
  length: length32,
5928
5959
  width: width10,
5929
5960
  axis: panel === "base" === !("vertical" in values) ? "u" : "v"
@@ -5951,8 +5982,9 @@ function parseSheetMetalModelParams(raw) {
5951
5982
  continue;
5952
5983
  }
5953
5984
  if (["plate", "angle", "channel"].includes(token)) {
5954
- if (props.profile) throw new Error("Duplicate sheet metal profile");
5955
- props.profile = token;
5985
+ if (["plate", "angle", "channel"].some((flag) => flag in props))
5986
+ throw new Error("Duplicate sheet metal form flag");
5987
+ props[token] = true;
5956
5988
  continue;
5957
5989
  }
5958
5990
  const key = lengths3[token[0]];
@@ -5966,7 +5998,7 @@ function parseSheetMetalModelParams(raw) {
5966
5998
  ...props
5967
5999
  });
5968
6000
  definition.holes = features.map(
5969
- (feature) => parseSheetMetalFeature(feature, definition.profile)
6001
+ (feature) => parseSheetMetalFeature(feature, definition)
5970
6002
  );
5971
6003
  return definition;
5972
6004
  }
@@ -5978,14 +6010,6 @@ var model4 = defineModel({
5978
6010
  function register4(registry2) {
5979
6011
  registry2.register(model4);
5980
6012
  }
5981
- var flexScreenOrientationSchema = external_exports.enum([
5982
- "sitsFlat",
5983
- "sitsFlatBelowBoard",
5984
- "foldedToFaceAboveBoard",
5985
- "foldedToFaceBelowBoard",
5986
- "foldedToRightAngleAboveBoard",
5987
- "foldedToRightAngleBelowBoard"
5988
- ]);
5989
6013
  var positiveFiniteNumberSchema = external_exports.number().finite().positive();
5990
6014
  var aspectRatioStringSchema = external_exports.string().refine((value) => {
5991
6015
  const parts = value.split(":");
@@ -6027,7 +6051,6 @@ var flexScreenModelPropsShape = {
6027
6051
  aspectRatio: flexScreenAspectRatioSchema.optional(),
6028
6052
  ratio: flexScreenAspectRatioSchema.optional(),
6029
6053
  defaultDiagonal: positiveModelLengthSchema.optional(),
6030
- orientation: flexScreenOrientationSchema.optional(),
6031
6054
  sitsFlat: external_exports.boolean().optional(),
6032
6055
  sitsFlatBelowBoard: external_exports.boolean().optional(),
6033
6056
  foldedToFaceAboveBoard: external_exports.boolean().optional(),
@@ -6095,7 +6118,42 @@ var addOrientationShortcutIssue = (props, addIssue) => {
6095
6118
  const selectedShortcuts = orientationShortcutKeys.filter(
6096
6119
  (key) => props[key] === true
6097
6120
  );
6098
- if (selectedShortcuts.length > 1) addIssue(selectedShortcuts[1]);
6121
+ if (selectedShortcuts.length > 1) {
6122
+ addIssue(
6123
+ selectedShortcuts[1],
6124
+ "Only one FlexScreen orientation shortcut can be true"
6125
+ );
6126
+ } else if (selectedShortcuts.length === 0 && orientationShortcutKeys.some((key) => props[key] !== void 0)) {
6127
+ addIssue(
6128
+ "sitsFlat",
6129
+ "A FlexScreen orientation flag must be true when placement flags are supplied"
6130
+ );
6131
+ }
6132
+ };
6133
+ var normalizeOrientationFlags = (props) => {
6134
+ const {
6135
+ sitsFlat,
6136
+ sitsFlatBelowBoard,
6137
+ foldedToFaceAboveBoard,
6138
+ foldedToFaceBelowBoard,
6139
+ foldedToRightAngleAboveBoard,
6140
+ foldedToRightAngleBelowBoard,
6141
+ foldsAboveBoard,
6142
+ foldsBelowBoard,
6143
+ ...rest
6144
+ } = props;
6145
+ const above = foldedToFaceAboveBoard === true || foldsAboveBoard === true;
6146
+ const below = foldedToFaceBelowBoard === true || foldsBelowBoard === true;
6147
+ const selected = sitsFlatBelowBoard === true || above || below || foldedToRightAngleAboveBoard === true || foldedToRightAngleBelowBoard === true;
6148
+ return {
6149
+ ...rest,
6150
+ sitsFlat: sitsFlat === true || !selected,
6151
+ sitsFlatBelowBoard: sitsFlatBelowBoard === true,
6152
+ foldedToFaceAboveBoard: above,
6153
+ foldedToFaceBelowBoard: below,
6154
+ foldedToRightAngleAboveBoard: foldedToRightAngleAboveBoard === true,
6155
+ foldedToRightAngleBelowBoard: foldedToRightAngleBelowBoard === true
6156
+ };
6099
6157
  };
6100
6158
  var validateTailLengths = (props, context) => {
6101
6159
  if (props.flexCableLength === void 0) return;
@@ -6116,27 +6174,27 @@ var validateTailLengths = (props, context) => {
6116
6174
  };
6117
6175
  var flexScreenModelPropsSchema = external_exports.object(flexScreenModelPropsShape).strict().superRefine((props, context) => {
6118
6176
  validateTailLengths(props, context);
6119
- addOrientationShortcutIssue(props, (path) => {
6177
+ addOrientationShortcutIssue(props, (path, message) => {
6120
6178
  context.addIssue({
6121
6179
  code: "custom",
6122
- message: "Only one FlexScreen orientation shortcut can be true",
6180
+ message,
6123
6181
  path: [path]
6124
6182
  });
6125
6183
  });
6126
- });
6184
+ }).transform(normalizeOrientationFlags);
6127
6185
  var flexScreenModelDefinitionSchema = external_exports.object({
6128
6186
  fn: external_exports.literal("flexscreen"),
6129
6187
  ...flexScreenModelPropsShape
6130
6188
  }).strict().superRefine((model552, context) => {
6131
6189
  validateTailLengths(model552, context);
6132
- addOrientationShortcutIssue(model552, (path) => {
6190
+ addOrientationShortcutIssue(model552, (path, message) => {
6133
6191
  context.addIssue({
6134
6192
  code: "custom",
6135
- message: "Only one FlexScreen orientation shortcut can be true",
6193
+ message,
6136
6194
  path: [path]
6137
6195
  });
6138
6196
  });
6139
- });
6197
+ }).transform(normalizeOrientationFlags);
6140
6198
  var orientationTokens = {
6141
6199
  sitsflat: "sitsFlat",
6142
6200
  sitsflatbelow: "sitsFlatBelowBoard",
@@ -6262,6 +6320,23 @@ var parseFlexScreenModelParams = (rawParams) => {
6262
6320
  }
6263
6321
  const props = {};
6264
6322
  let orientation;
6323
+ for (const part of splitModelStringTokens(rawParams.string).slice(1)) {
6324
+ const match = part.match(/^([a-zA-Z]+)(.*)$/);
6325
+ if (!match) continue;
6326
+ const token = match[1].toLowerCase();
6327
+ const selected = orientationTokens[token];
6328
+ if (!selected) continue;
6329
+ if (match[2] !== "") {
6330
+ throw new Error(`FlexScreen token "${token}" does not accept a value`);
6331
+ }
6332
+ if (orientation !== void 0) {
6333
+ throw new Error(
6334
+ orientation === selected ? `Duplicate FlexScreen orientation flag "${token}"` : "A FlexScreen model string can only set one orientation"
6335
+ );
6336
+ }
6337
+ orientation = selected;
6338
+ props[selected] = true;
6339
+ }
6265
6340
  let relativeDistance;
6266
6341
  for (const [token, value] of Object.entries(rawParams)) {
6267
6342
  if (token === "fn" || token === "string" || token === "flexscreen") {
@@ -6270,13 +6345,6 @@ var parseFlexScreenModelParams = (rawParams) => {
6270
6345
  const tokenOrientation = orientationTokens[token];
6271
6346
  if (tokenOrientation) {
6272
6347
  assertBareToken(value, token);
6273
- if (orientation && orientation !== tokenOrientation) {
6274
- throw new Error(
6275
- "A FlexScreen model string can only set one orientation"
6276
- );
6277
- }
6278
- orientation = tokenOrientation;
6279
- props.orientation = tokenOrientation;
6280
6348
  continue;
6281
6349
  }
6282
6350
  if (token in booleanTokens) {
@@ -6452,7 +6520,7 @@ var shape4 = {
6452
6520
  /** Additional radial dedendum beyond one module, in millimeters. */
6453
6521
  clearance: nonnegativeGearLengthSchema.default(0.25),
6454
6522
  boreDiameter: nonnegativeGearLengthSchema.default(0),
6455
- handedness: external_exports.enum(["right", "left"]).default("right"),
6523
+ leftHanded: external_exports.boolean().default(false),
6456
6524
  /** Counterclockwise degrees about +Z, beginning at the Z=0 end. */
6457
6525
  phase: external_exports.number().finite().default(0),
6458
6526
  radialSegments: external_exports.number().int().min(24).max(256).refine(
@@ -6522,7 +6590,7 @@ function parseWormGearModelParams(raw) {
6522
6590
  const [name, value] = parseGearToken(token);
6523
6591
  let property;
6524
6592
  let parsed;
6525
- if (name in lengths5) {
6593
+ if (Object.hasOwn(lengths5, name)) {
6526
6594
  property = lengths5[name];
6527
6595
  parsed = value;
6528
6596
  } else if (["starts", "segments", "turnsegments"].includes(name)) {
@@ -6533,8 +6601,8 @@ function parseWormGearModelParams(raw) {
6533
6601
  parsed = parseGearAngle(value, property);
6534
6602
  } else if (name === "right" || name === "left") {
6535
6603
  if (value) throw new Error(`Worm flag "${name}" does not accept a value`);
6536
- property = "handedness";
6537
- parsed = name;
6604
+ property = "leftHanded";
6605
+ parsed = name === "left";
6538
6606
  } else throw new Error(`Unknown worm gear token "${token}"`);
6539
6607
  if (property in props)
6540
6608
  throw new Error(`Worm gear property "${property}" is set more than once`);
@@ -6853,7 +6921,7 @@ var lengths7 = {
6853
6921
  w: "width",
6854
6922
  width: "width"
6855
6923
  };
6856
- var flags = {
6924
+ var flags2 = {
6857
6925
  open: "bothSidesOpen",
6858
6926
  bothsidesopen: "bothSidesOpen",
6859
6927
  shielded: "bothSidesShielded",
@@ -6887,8 +6955,8 @@ function parseBallBearingModelParams(raw) {
6887
6955
  const scopes = /* @__PURE__ */ new Set();
6888
6956
  for (const token of tokens.slice(1)) {
6889
6957
  const lower = token.toLowerCase();
6890
- if (Object.hasOwn(flags, lower)) {
6891
- const property2 = flags[lower];
6958
+ if (Object.hasOwn(flags2, lower)) {
6959
+ const property2 = flags2[lower];
6892
6960
  const scope = property2.startsWith("both") ? "both" : property2.startsWith("top") ? "top" : "bottom";
6893
6961
  if (scopes.has(scope))
6894
6962
  throw new Error(
@@ -7082,7 +7150,7 @@ function parseBallTransferUnitModelParams(raw) {
7082
7150
  const lower = token.toLowerCase();
7083
7151
  let property;
7084
7152
  let value;
7085
- if (lower === "face3hole" || lower === "mount(face3hole)") {
7153
+ if (lower === "face3hole") {
7086
7154
  property = "faceThreeHole";
7087
7155
  value = true;
7088
7156
  } else {
@@ -7108,12 +7176,6 @@ var model12 = defineModel({
7108
7176
  function register12(registry2) {
7109
7177
  registry2.register(model12);
7110
7178
  }
7111
- var stringFlags2 = {
7112
- hexsocket: "drive(hexsocket)",
7113
- fullthread: "thread(full)",
7114
- righthanded: "threadhand(right)"
7115
- };
7116
- var omittedStringFlags2 = ["righthanded"];
7117
7179
  var buttonScrewDimensions = {
7118
7180
  M3: {
7119
7181
  diameter: 3,
@@ -7174,10 +7236,10 @@ var shape9 = {
7174
7236
  metricSize: buttonScrewMetricSizeSchema,
7175
7237
  /** Under-head length; this family supports short fully threaded screws only. */
7176
7238
  length: length4,
7177
- drive: external_exports.literal("hexsocket").default("hexsocket"),
7178
- thread: external_exports.literal("full").default("full"),
7239
+ hexSocket: external_exports.literal(true).default(true),
7240
+ fullThread: external_exports.literal(true).default(true),
7179
7241
  threadPitch: length4.optional(),
7180
- threadHand: external_exports.literal("right").default("right"),
7242
+ leftHanded: external_exports.literal(false).default(false),
7181
7243
  threadClass: external_exports.literal("6g").default("6g"),
7182
7244
  showThreads: external_exports.boolean().default(true)
7183
7245
  };
@@ -7233,9 +7295,7 @@ function getButtonScrewDimensions(input) {
7233
7295
  };
7234
7296
  }
7235
7297
  function parseButtonScrewModelParams(raw) {
7236
- const tokens = splitModelStringTokens(
7237
- expandModelStringFlags(raw.string, stringFlags2)
7238
- );
7298
+ const tokens = splitModelStringTokens(raw.string);
7239
7299
  if (raw.fn !== "buttonscrew" || tokens[0]?.toLowerCase() !== "buttonscrew")
7240
7300
  throw new Error("Expected buttonscrew without an inline argument");
7241
7301
  const props = { fn: "buttonscrew" };
@@ -7244,12 +7304,15 @@ function parseButtonScrewModelParams(raw) {
7244
7304
  length: "length",
7245
7305
  threadpitch: "threadPitch"
7246
7306
  };
7247
- const selectors7 = {
7248
- drive: "drive",
7249
- thread: "thread",
7250
- threadhand: "threadHand",
7307
+ const selectors5 = {
7251
7308
  threadclass: "threadClass"
7252
7309
  };
7310
+ const booleanFlags4 = {
7311
+ hexsocket: { property: "hexSocket", value: true },
7312
+ fullthread: { property: "fullThread", value: true },
7313
+ righthanded: { property: "leftHanded", value: false },
7314
+ lefthanded: { property: "leftHanded", value: true }
7315
+ };
7253
7316
  for (const token of tokens.slice(1)) {
7254
7317
  if (token.toLowerCase() === "iso7380-1") {
7255
7318
  if ("iso73801" in props)
@@ -7263,12 +7326,17 @@ function parseButtonScrewModelParams(raw) {
7263
7326
  const value = match[2];
7264
7327
  let property;
7265
7328
  let parsed = value;
7266
- if (name === "m") {
7329
+ if (Object.hasOwn(booleanFlags4, name)) {
7330
+ if (value) throw new Error(`Flag "${name}" does not accept a value`);
7331
+ property = booleanFlags4[name].property;
7332
+ parsed = booleanFlags4[name].value;
7333
+ } else if (name === "m") {
7267
7334
  property = "metricSize";
7268
7335
  parsed = `M${value}`;
7269
- } else if (name in lengths25) property = lengths25[name];
7270
- else if (name in selectors7) {
7271
- property = selectors7[name];
7336
+ } else if (Object.hasOwn(lengths25, name))
7337
+ property = lengths25[name];
7338
+ else if (Object.hasOwn(selectors5, name)) {
7339
+ property = selectors5[name];
7272
7340
  if (!/^\([^()]+\)$/.test(value))
7273
7341
  throw new Error(`Expected a parenthesized ${name}`);
7274
7342
  parsed = value.slice(1, -1).toLowerCase();
@@ -7286,21 +7354,11 @@ function parseButtonScrewModelParams(raw) {
7286
7354
  var model13 = defineModel({
7287
7355
  name: "buttonscrew",
7288
7356
  schema: buttonScrewModelDefinitionSchema,
7289
- parse: parseButtonScrewModelParams,
7290
- normalizeString: (value) => normalizeModelStringFlags(
7291
- value,
7292
- stringFlags2,
7293
- parseButtonScrewModelParams,
7294
- omittedStringFlags2
7295
- )
7357
+ parse: parseButtonScrewModelParams
7296
7358
  });
7297
7359
  function register13(registry2) {
7298
7360
  registry2.register(model13);
7299
7361
  }
7300
- var stringFlags3 = {
7301
- symmetricring: "shape(symmetricring)"
7302
- };
7303
- var omittedStringFlags3 = [];
7304
7362
  var length5 = external_exports.union([
7305
7363
  external_exports.number(),
7306
7364
  external_exports.string().regex(
@@ -7316,7 +7374,7 @@ var shape10 = {
7316
7374
  grooveWidth: length5,
7317
7375
  /** Radial recess from the flange outside diameter. */
7318
7376
  grooveDepth: length5,
7319
- shape: external_exports.literal("symmetricring").default("symmetricring")
7377
+ symmetricRing: external_exports.literal(true).default(true)
7320
7378
  };
7321
7379
  function validate9(props, context) {
7322
7380
  if (props.innerDiameter >= props.panelHoleDiameter || props.panelHoleDiameter >= props.outerDiameter)
@@ -7373,9 +7431,7 @@ var lengths9 = {
7373
7431
  groovedepth: "grooveDepth"
7374
7432
  };
7375
7433
  function parseCableGrommetModelParams(raw) {
7376
- const tokens = splitModelStringTokens(
7377
- expandModelStringFlags(raw.string, stringFlags3)
7378
- );
7434
+ const tokens = splitModelStringTokens(raw.string);
7379
7435
  if (raw.fn !== "cablegrommet" || !/^cablegrommet$/i.test(tokens[0]))
7380
7436
  throw new Error("Expected cablegrommet without an inline value");
7381
7437
  const props = { fn: "cablegrommet" };
@@ -7383,15 +7439,14 @@ function parseCableGrommetModelParams(raw) {
7383
7439
  const match = token.match(/^([a-z]+)(.*)$/i);
7384
7440
  const name = match?.[1]?.toLowerCase();
7385
7441
  const value = match?.[2];
7386
- if (!name || !value) throw new Error(`Invalid grommet token "${token}"`);
7442
+ if (!name) throw new Error(`Invalid grommet token "${token}"`);
7387
7443
  let property;
7388
7444
  let parsed = value;
7389
7445
  if (name in lengths9) property = lengths9[name];
7390
- else if (name === "shape") {
7391
- property = "shape";
7392
- const selector = value.match(/^\(([a-z]+)\)$/i);
7393
- if (!selector) throw new Error("Grommet shape requires parentheses");
7394
- parsed = selector[1].toLowerCase();
7446
+ else if (name === "symmetricring") {
7447
+ property = "symmetricRing";
7448
+ if (value !== "") throw new Error("symmetricring is a value-free flag");
7449
+ parsed = true;
7395
7450
  } else throw new Error(`Unknown grommet token "${token}"`);
7396
7451
  if (property in props)
7397
7452
  throw new Error(`Grommet property "${property}" is set more than once`);
@@ -7402,13 +7457,7 @@ function parseCableGrommetModelParams(raw) {
7402
7457
  var model14 = defineModel({
7403
7458
  name: "cablegrommet",
7404
7459
  schema: cableGrommetModelDefinitionSchema,
7405
- parse: parseCableGrommetModelParams,
7406
- normalizeString: (value) => normalizeModelStringFlags(
7407
- value,
7408
- stringFlags3,
7409
- parseCableGrommetModelParams,
7410
- omittedStringFlags3
7411
- )
7460
+ parse: parseCableGrommetModelParams
7412
7461
  });
7413
7462
  function register14(registry2) {
7414
7463
  registry2.register(model14);
@@ -7505,12 +7554,6 @@ var model15 = defineModel({
7505
7554
  function register15(registry2) {
7506
7555
  registry2.register(model15);
7507
7556
  }
7508
- var stringFlags4 = {
7509
- singleclamp: "mount(singleclamp)",
7510
- lefthanded: "threadhand(left)",
7511
- righthanded: "threadhand(right)"
7512
- };
7513
- var omittedStringFlags4 = ["righthanded"];
7514
7557
  var length7 = external_exports.union([
7515
7558
  external_exports.number().finite(),
7516
7559
  external_exports.string().regex(
@@ -7531,10 +7574,10 @@ var shape12 = {
7531
7574
  splitWidth: positive3,
7532
7575
  clampX: positive3.optional(),
7533
7576
  clearanceHoleDiameter: positive3.optional(),
7534
- mount: external_exports.literal("singleclamp").default("singleclamp"),
7577
+ singleClamp: external_exports.literal(true).default(true),
7535
7578
  metricSize: metricBoltSizeSchema,
7536
7579
  threadPitch: positive3.optional(),
7537
- threadHand: external_exports.enum(["right", "left"]).default("right"),
7580
+ leftHanded: external_exports.boolean().default(false),
7538
7581
  threadClass: external_exports.literal("6H").default("6H"),
7539
7582
  chamfer: nonnegative2.default(0)
7540
7583
  };
@@ -7610,7 +7653,7 @@ function getClampingShaftCollarDimensions(input) {
7610
7653
  diameter: threadDiameter,
7611
7654
  depth: threadedExtent - p.splitWidth / 2,
7612
7655
  threadPitch: p.threadPitch,
7613
- threadHand: p.threadHand,
7656
+ leftHanded: p.leftHanded,
7614
7657
  threadGender: "female",
7615
7658
  threadClass: p.threadClass
7616
7659
  }
@@ -7619,10 +7662,8 @@ function getClampingShaftCollarDimensions(input) {
7619
7662
  var tokenProperties = {
7620
7663
  bore: "boreDiameter",
7621
7664
  od: "outerDiameter",
7622
- mount: "mount",
7623
7665
  m: "metricSize",
7624
7666
  threadpitch: "threadPitch",
7625
- threadhand: "threadHand",
7626
7667
  threadclass: "threadClass",
7627
7668
  chamfer: "chamfer",
7628
7669
  w: "width",
@@ -7633,27 +7674,35 @@ var tokenProperties = {
7633
7674
  clearance: "clearanceHoleDiameter"
7634
7675
  };
7635
7676
  function parseClampingShaftCollarModelParams(raw) {
7636
- const tokens = splitModelStringTokens(
7637
- expandModelStringFlags(raw.string, stringFlags4)
7638
- );
7677
+ const tokens = splitModelStringTokens(raw.string);
7639
7678
  if (raw.fn !== "clampingshaftcollar" || tokens[0]?.toLowerCase() !== "clampingshaftcollar")
7640
7679
  throw new Error("Expected an unadorned clampingshaftcollar function");
7641
7680
  const props = {};
7642
7681
  for (const token of tokens.slice(1)) {
7643
7682
  const match = token.match(/^([a-z]+)(.*)$/i);
7644
7683
  const name = match?.[1]?.toLowerCase() ?? "";
7684
+ const value = match?.[2] ?? "";
7685
+ if (["singleclamp", "lefthanded", "righthanded"].includes(name)) {
7686
+ if (value) throw new Error(`Flag "${name}" does not take a value`);
7687
+ const property2 = name === "singleclamp" ? "singleClamp" : "leftHanded";
7688
+ if (property2 in props)
7689
+ throw new Error(
7690
+ `Duplicate or conflicting clampingshaftcollar flag "${property2}"`
7691
+ );
7692
+ props[property2] = name !== "righthanded";
7693
+ continue;
7694
+ }
7645
7695
  const property = tokenProperties[name];
7646
7696
  if (!property)
7647
7697
  throw new Error(`Unknown clampingshaftcollar token "${token}"`);
7648
7698
  if (property in props)
7649
7699
  throw new Error(`Duplicate clampingshaftcollar property "${property}"`);
7650
- const value = match[2];
7651
7700
  if (!value) throw new Error(`Token "${name}" requires a value`);
7652
- if (["mount", "threadHand", "threadClass"].includes(property)) {
7701
+ if (property === "threadClass") {
7653
7702
  const argument = value.match(/^\(([^()]+)\)$/);
7654
7703
  if (!argument)
7655
7704
  throw new Error(`Token "${name}" requires one parenthesized argument`);
7656
- props[property] = property === "threadClass" ? argument[1].toUpperCase() : argument[1].toLowerCase();
7705
+ props[property] = argument[1].toUpperCase();
7657
7706
  } else if (property === "metricSize") {
7658
7707
  if (!/^\d+(?:\.\d+)?$/.test(value))
7659
7708
  throw new Error("m requires a unitless metric designation");
@@ -7670,41 +7719,27 @@ function parseClampingShaftCollarModelParams(raw) {
7670
7719
  var model16 = defineModel({
7671
7720
  name: "clampingshaftcollar",
7672
7721
  schema: clampingShaftCollarModelDefinitionSchema,
7673
- parse: parseClampingShaftCollarModelParams,
7674
- normalizeString: (value) => normalizeModelStringFlags(
7675
- value,
7676
- stringFlags4,
7677
- parseClampingShaftCollarModelParams,
7678
- omittedStringFlags4
7679
- )
7722
+ parse: parseClampingShaftCollarModelParams
7680
7723
  });
7681
7724
  function register16(registry2) {
7682
7725
  registry2.register(model16);
7683
7726
  }
7684
- var stringFlags5 = {
7685
- closedground: "ends(closedground)",
7686
- lefthanded: "hand(left)",
7687
- righthanded: "hand(right)",
7688
- custom: "spec(custom)",
7689
- free: "state(free)"
7690
- };
7691
- var omittedStringFlags5 = ["righthanded", "custom", "free"];
7692
7727
  var length8 = external_exports.union([
7693
7728
  external_exports.number(),
7694
7729
  external_exports.string().regex(/^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:mm|cm|m|in|inch|mil|ft|feet)?$/i).transform((value) => value.toLowerCase())
7695
7730
  ]).pipe(modelLengthSchema).refine((value) => value > 0, "Length must be positive");
7696
7731
  var turnCount = external_exports.number().int().min(1).max(Number.MAX_SAFE_INTEGER);
7697
7732
  var shape13 = {
7698
- spec: external_exports.literal("custom").default("custom"),
7733
+ custom: external_exports.literal(true).default(true),
7699
7734
  outerDiameter: length8,
7700
7735
  wireDiameter: length8,
7701
7736
  freeLength: length8,
7702
7737
  totalTurns: turnCount.min(3),
7703
7738
  /** Closed-ground ends have exactly one inactive turn at each end. */
7704
7739
  activeTurns: turnCount.optional(),
7705
- ends: external_exports.literal("closedground").default("closedground"),
7706
- hand: external_exports.enum(["right", "left"]).default("right"),
7707
- state: external_exports.literal("free").default("free")
7740
+ closedGround: external_exports.literal(true).default(true),
7741
+ leftHanded: external_exports.boolean().default(false),
7742
+ free: external_exports.literal(true).default(true)
7708
7743
  };
7709
7744
  function validate12(props, context) {
7710
7745
  if (props.outerDiameter <= 2 * props.wireDiameter)
@@ -7757,14 +7792,12 @@ function getCompressionSpringCenterlinePoint(input, turn) {
7757
7792
  throw new Error("Turn coordinate must be finite and within [0,totalTurns]");
7758
7793
  const radius = (props.outerDiameter - props.wireDiameter) / 2;
7759
7794
  const pitch = (props.freeLength - 2 * props.wireDiameter) / props.activeTurns;
7760
- const phase = (props.hand === "right" ? 1 : -1) * 2 * Math.PI * (turn % 1);
7795
+ const phase = (props.leftHanded ? -1 : 1) * 2 * Math.PI * (turn % 1);
7761
7796
  const z59 = turn <= 1 ? props.wireDiameter * turn : turn >= props.totalTurns - 1 ? props.freeLength - props.wireDiameter * (props.totalTurns - turn) : props.wireDiameter + pitch * (turn - 1);
7762
7797
  return { x: radius * Math.cos(phase), y: radius * Math.sin(phase), z: z59 };
7763
7798
  }
7764
7799
  function parseCompressionSpringModelParams(raw) {
7765
- const tokens = splitModelStringTokens(
7766
- expandModelStringFlags(raw.string, stringFlags5)
7767
- );
7800
+ const tokens = splitModelStringTokens(raw.string);
7768
7801
  if (raw.fn !== "compressionspring" || tokens[0]?.toLowerCase() !== "compressionspring")
7769
7802
  throw new Error("Expected compressionspring without an inline argument");
7770
7803
  const props = { fn: "compressionspring" };
@@ -7775,11 +7808,12 @@ function parseCompressionSpringModelParams(raw) {
7775
7808
  length: "freeLength",
7776
7809
  freelength: "freeLength"
7777
7810
  };
7778
- const selectors7 = {
7779
- spec: "spec",
7780
- ends: "ends",
7781
- hand: "hand",
7782
- state: "state"
7811
+ const flags11 = {
7812
+ custom: "custom",
7813
+ closedground: "closedGround",
7814
+ free: "free",
7815
+ lefthanded: "leftHanded",
7816
+ righthanded: "leftHanded"
7783
7817
  };
7784
7818
  for (const token of tokens.slice(1)) {
7785
7819
  const match = token.match(/^([a-z]+)(.*)$/i);
@@ -7794,11 +7828,10 @@ function parseCompressionSpringModelParams(raw) {
7794
7828
  if (!/^\d+$/.test(value))
7795
7829
  throw new Error(`${name} requires a unitless integer`);
7796
7830
  parsed = Number(value);
7797
- } else if (name in selectors7) {
7798
- property = selectors7[name];
7799
- if (!/^\([^()]+\)$/.test(value))
7800
- throw new Error(`Expected a parenthesized ${name}`);
7801
- parsed = value.slice(1, -1).toLowerCase();
7831
+ } else if (Object.hasOwn(flags11, name)) {
7832
+ if (value) throw new Error(`Flag "${name}" does not take a value`);
7833
+ property = flags11[name];
7834
+ parsed = name !== "righthanded";
7802
7835
  } else throw new Error(`Unknown compression spring token "${token}"`);
7803
7836
  if (property in props)
7804
7837
  throw new Error(`Duplicate compression spring property "${property}"`);
@@ -7809,13 +7842,7 @@ function parseCompressionSpringModelParams(raw) {
7809
7842
  var model17 = defineModel({
7810
7843
  name: "compressionspring",
7811
7844
  schema: compressionSpringModelDefinitionSchema,
7812
- parse: parseCompressionSpringModelParams,
7813
- normalizeString: (value) => normalizeModelStringFlags(
7814
- value,
7815
- stringFlags5,
7816
- parseCompressionSpringModelParams,
7817
- omittedStringFlags5
7818
- )
7845
+ parse: parseCompressionSpringModelParams
7819
7846
  });
7820
7847
  function register17(registry2) {
7821
7848
  registry2.register(model17);
@@ -8268,7 +8295,7 @@ var aliases4 = {
8268
8295
  threadrootdiameter: "threadRootDiameter",
8269
8296
  threadpitchdiameter: "threadPitchDiameter"
8270
8297
  };
8271
- var flags2 = {
8298
+ var flags3 = {
8272
8299
  fullthread: "fullThread",
8273
8300
  plainface: "plainFace",
8274
8301
  lefthanded: "leftHand",
@@ -8294,9 +8321,9 @@ function parseFlangeBoltModelParams(raw) {
8294
8321
  const value = match?.[2] ?? "";
8295
8322
  let property;
8296
8323
  let parsed;
8297
- if (flags2[key]) {
8324
+ if (flags3[key]) {
8298
8325
  if (value) throw new Error(`Flag ${key} does not accept a value`);
8299
- property = flags2[key];
8326
+ property = flags3[key];
8300
8327
  parsed = !["righthanded", "nothreads"].includes(key);
8301
8328
  } else {
8302
8329
  if (key === "standard" || key === "headstandard")
@@ -8334,10 +8361,6 @@ var model20 = defineModel({
8334
8361
  function register20(registry2) {
8335
8362
  registry2.register(model20);
8336
8363
  }
8337
- var stringFlags6 = {
8338
- plainclosed: "style(plainclosed)"
8339
- };
8340
- var omittedStringFlags6 = ["plainclosed"];
8341
8364
  var positiveLength6 = external_exports.union([
8342
8365
  external_exports.number(),
8343
8366
  external_exports.string().regex(/^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:mm|cm|m|in|inch|mil|ft|feet)?$/i).transform((value) => value.toLowerCase())
@@ -8349,7 +8372,7 @@ var shape17 = {
8349
8372
  /** Overall end-plane distance including the integral flange. */
8350
8373
  length: positiveLength6,
8351
8374
  flangeThickness: positiveLength6,
8352
- style: external_exports.literal("plainclosed").default("plainclosed")
8375
+ plainClosed: external_exports.literal(true).default(true)
8353
8376
  };
8354
8377
  function validate16(props, context) {
8355
8378
  if (props.outerDiameter <= props.innerDiameter)
@@ -8399,9 +8422,7 @@ var lengths12 = {
8399
8422
  flangethickness: "flangeThickness"
8400
8423
  };
8401
8424
  function parseFlangedBushingModelParams(raw) {
8402
- const tokens = splitModelStringTokens(
8403
- expandModelStringFlags(raw.string, stringFlags6)
8404
- );
8425
+ const tokens = splitModelStringTokens(raw.string);
8405
8426
  if (raw.fn !== "flangedbushing" || tokens[0]?.toLowerCase() !== "flangedbushing")
8406
8427
  throw new Error("Expected flangedbushing without an inline value");
8407
8428
  const props = { fn: "flangedbushing" };
@@ -8415,11 +8436,10 @@ function parseFlangedBushingModelParams(raw) {
8415
8436
  if (Object.hasOwn(lengths12, name)) {
8416
8437
  property = lengths12[name];
8417
8438
  parsed = value;
8418
- } else if (name === "style") {
8419
- property = "style";
8420
- const style = value.match(/^\(([a-z]+)\)$/i);
8421
- if (!style) throw new Error("Style requires a parenthesized value");
8422
- parsed = style[1].toLowerCase();
8439
+ } else if (name === "plainclosed") {
8440
+ property = "plainClosed";
8441
+ if (value !== "") throw new Error("plainclosed is a value-free flag");
8442
+ parsed = true;
8423
8443
  } else throw new Error(`Unknown flanged bushing token "${token}"`);
8424
8444
  if (Object.hasOwn(props, property))
8425
8445
  throw new Error(
@@ -8432,13 +8452,7 @@ function parseFlangedBushingModelParams(raw) {
8432
8452
  var model21 = defineModel({
8433
8453
  name: "flangedbushing",
8434
8454
  schema: flangedBushingModelDefinitionSchema,
8435
- parse: parseFlangedBushingModelParams,
8436
- normalizeString: (value) => normalizeModelStringFlags(
8437
- value,
8438
- stringFlags6,
8439
- parseFlangedBushingModelParams,
8440
- omittedStringFlags6
8441
- )
8455
+ parse: parseFlangedBushingModelParams
8442
8456
  });
8443
8457
  function register21(registry2) {
8444
8458
  registry2.register(model21);
@@ -8796,10 +8810,7 @@ var lengths13 = {
8796
8810
  outerdiameter: "outerDiameter",
8797
8811
  thickness: "thickness"
8798
8812
  };
8799
- var flags3 = { flatannulus: "flatAnnulus" };
8800
- var selectors2 = {
8801
- profile: { value: "flatannulus", property: "flatAnnulus" }
8802
- };
8813
+ var flags4 = { flatannulus: "flatAnnulus" };
8803
8814
  var integers = {};
8804
8815
  var tuples = {};
8805
8816
  function parseFlatGasketModelParams(raw) {
@@ -8817,9 +8828,7 @@ function parseFlatGasketModelParams(raw) {
8817
8828
  if (!match) throw new Error(`Malformed flatgasket token "${token}"`);
8818
8829
  const key = match[1].toLowerCase(), value = match[2];
8819
8830
  if (Object.hasOwn(lengths13, key) && value) assign(lengths13[key], value);
8820
- else if (Object.hasOwn(flags3, key) && !value) assign(flags3[key], true);
8821
- else if (Object.hasOwn(selectors2, key) && value.toLowerCase() === `(${selectors2[key].value})`)
8822
- assign(selectors2[key].property, true);
8831
+ else if (Object.hasOwn(flags4, key) && !value) assign(flags4[key], true);
8823
8832
  else if (Object.hasOwn(integers, key) && /^\d+$/.test(value))
8824
8833
  assign(integers[key], Number(value));
8825
8834
  else if (Object.hasOwn(tuples, key)) {
@@ -8840,14 +8849,6 @@ var model24 = defineModel({
8840
8849
  function register24(registry2) {
8841
8850
  registry2.register(model24);
8842
8851
  }
8843
- var stringFlags7 = {
8844
- hexsocket: "drive(hexsocket)",
8845
- fullthread: "thread(full)",
8846
- lefthanded: "threadhand(left)",
8847
- righthanded: "threadhand(right)",
8848
- male: "threadgender(male)"
8849
- };
8850
- var omittedStringFlags7 = ["righthanded", "male"];
8851
8852
  var positiveModelLengthSchema3 = external_exports.union([
8852
8853
  external_exports.number(),
8853
8854
  external_exports.string().regex(/^(?:\d+(?:\.\d+)?|\.\d+)(?:mm|cm|m|in|inch)?$/i).transform((value) => value.toLowerCase())
@@ -8923,11 +8924,11 @@ var flatHeadScrewModelPropsShape = {
8923
8924
  iso10642: external_exports.literal(true).default(true),
8924
8925
  metricSize: flatHeadScrewMetricSizeSchema,
8925
8926
  length: positiveModelLengthSchema3,
8926
- thread: external_exports.literal("full").default("full"),
8927
- drive: external_exports.literal("hexsocket").default("hexsocket"),
8928
- threadHand: external_exports.enum(["right", "left"]).default("right"),
8927
+ fullThread: external_exports.literal(true).default(true),
8928
+ hexSocket: external_exports.literal(true).default(true),
8929
+ leftHanded: external_exports.boolean().default(false),
8929
8930
  threadClass: external_exports.literal("6g").default("6g"),
8930
- threadGender: external_exports.literal("male").default("male"),
8931
+ male: external_exports.literal(true).default(true),
8931
8932
  showThreads: external_exports.boolean().default(true),
8932
8933
  diameter: positiveModelLengthSchema3.optional(),
8933
8934
  threadPitch: positiveModelLengthSchema3.optional(),
@@ -8993,11 +8994,7 @@ var aliases5 = {
8993
8994
  metricsize: "metricSize",
8994
8995
  l: "length",
8995
8996
  length: "length",
8996
- thread: "thread",
8997
- drive: "drive",
8998
- threadhand: "threadHand",
8999
8997
  threadclass: "threadClass",
9000
- threadgender: "threadGender",
9001
8998
  diameter: "diameter",
9002
8999
  threadpitch: "threadPitch",
9003
9000
  headdiameter: "headDiameter",
@@ -9018,19 +9015,18 @@ var aliases5 = {
9018
9015
  socketaf: "socketAcrossFlats",
9019
9016
  socketh: "socketDepth"
9020
9017
  };
9021
- var selectors3 = /* @__PURE__ */ new Set([
9022
- "thread",
9023
- "drive",
9024
- "threadHand",
9025
- "threadClass",
9026
- "threadGender"
9027
- ]);
9018
+ var selectors2 = /* @__PURE__ */ new Set(["threadClass"]);
9019
+ var booleanFlags2 = {
9020
+ hexsocket: { property: "hexSocket", value: true },
9021
+ fullthread: { property: "fullThread", value: true },
9022
+ male: { property: "male", value: true },
9023
+ lefthanded: { property: "leftHanded", value: true },
9024
+ righthanded: { property: "leftHanded", value: false }
9025
+ };
9028
9026
  var parseFlatHeadScrewModelParams = (raw) => {
9029
9027
  if (raw.fn !== "flatheadscrew")
9030
9028
  throw new Error(`Expected flatheadscrew params, got "${raw.fn}"`);
9031
- const [root, ...tokens] = splitModelStringTokens(
9032
- expandModelStringFlags(raw.string, stringFlags7)
9033
- );
9029
+ const [root, ...tokens] = splitModelStringTokens(raw.string);
9034
9030
  if (root?.toLowerCase() !== "flatheadscrew")
9035
9031
  throw new Error(
9036
9032
  "The flatheadscrew function does not accept an inline value"
@@ -9048,16 +9044,20 @@ var parseFlatHeadScrewModelParams = (raw) => {
9048
9044
  const value = match?.[2];
9049
9045
  let property;
9050
9046
  let parsed;
9051
- if (key === "threads" || key === "nothreads") {
9047
+ if (key && Object.hasOwn(booleanFlags2, key)) {
9048
+ if (value !== "") throw new Error(`Flag "${key}" does not accept a value`);
9049
+ property = booleanFlags2[key].property;
9050
+ parsed = booleanFlags2[key].value;
9051
+ } else if (key === "threads" || key === "nothreads") {
9052
9052
  if (value !== "")
9053
9053
  throw new Error(`Token "${key}" does not accept a value`);
9054
9054
  property = "showThreads";
9055
9055
  parsed = key === "threads";
9056
9056
  } else {
9057
- property = key ? aliases5[key] ?? "" : "";
9057
+ property = key && Object.hasOwn(aliases5, key) ? aliases5[key] : "";
9058
9058
  if (!property || !value)
9059
9059
  throw new Error(`Unknown or missing flatheadscrew token "${token}"`);
9060
- if (selectors3.has(property)) {
9060
+ if (selectors2.has(property)) {
9061
9061
  const selector = value.match(/^\(([^()]+)\)$/)?.[1];
9062
9062
  if (!selector)
9063
9063
  throw new Error(`Token "${key}" requires a parenthesized selector`);
@@ -9087,13 +9087,7 @@ var parseFlatHeadScrewModelParams = (raw) => {
9087
9087
  var model25 = defineModel({
9088
9088
  name: "flatheadscrew",
9089
9089
  schema: flatHeadScrewModelDefinitionSchema,
9090
- parse: parseFlatHeadScrewModelParams,
9091
- normalizeString: (value) => normalizeModelStringFlags(
9092
- value,
9093
- stringFlags7,
9094
- parseFlatHeadScrewModelParams,
9095
- omittedStringFlags7
9096
- )
9090
+ parse: parseFlatHeadScrewModelParams
9097
9091
  });
9098
9092
  function register25(registry2) {
9099
9093
  registry2.register(model25);
@@ -9254,7 +9248,7 @@ var aliases7 = {
9254
9248
  threadpitchdiameter: "threadPitchDiameter",
9255
9249
  rootouterdiameter: "rootOuterDiameter"
9256
9250
  };
9257
- var flags4 = {
9251
+ var flags5 = {
9258
9252
  diamondknurl: "diamondKnurl",
9259
9253
  lefthanded: "leftHand",
9260
9254
  righthanded: "leftHand",
@@ -9271,9 +9265,9 @@ function parseHeatSetInsertModelParams(raw) {
9271
9265
  for (const token of tokens) {
9272
9266
  const match = token.match(/^([a-z]+)(.*)$/i), key = match?.[1]?.toLowerCase() ?? "", value = match?.[2] ?? "";
9273
9267
  let property, parsed;
9274
- if (flags4[key]) {
9268
+ if (flags5[key]) {
9275
9269
  if (value) throw new Error("Flags do not accept values");
9276
- property = flags4[key];
9270
+ property = flags5[key];
9277
9271
  parsed = !["righthanded", "nothreads"].includes(key);
9278
9272
  } else {
9279
9273
  property = aliases7[key] ?? "";
@@ -9310,10 +9304,6 @@ var model27 = defineModel({
9310
9304
  function register27(registry2) {
9311
9305
  registry2.register(model27);
9312
9306
  }
9313
- var stringFlags8 = {
9314
- righthanded: "threadhand(right)"
9315
- };
9316
- var omittedStringFlags8 = ["righthanded"];
9317
9307
  var hexNutDimensions = {
9318
9308
  M5: {
9319
9309
  diameter: 5,
@@ -9554,7 +9544,7 @@ var shape23 = {
9554
9544
  metricSize: hexNutMetricSizeSchema.optional(),
9555
9545
  imperialSize: hexNutImperialSizeSchema.optional(),
9556
9546
  threadPitch: length13.optional(),
9557
- threadHand: external_exports.literal("right").default("right"),
9547
+ rightHanded: external_exports.literal(true).default(true),
9558
9548
  threadClass: external_exports.enum(["6H", "2B"]).optional(),
9559
9549
  showThreads: external_exports.boolean().default(true)
9560
9550
  };
@@ -9580,11 +9570,11 @@ function validate22(props, context) {
9580
9570
  const issue = (path, message) => context.addIssue({ code: "custom", path: [path], message });
9581
9571
  if (!!props.metricSize === !!props.imperialSize)
9582
9572
  issue("metricSize", "Select exactly one metric or imperial size");
9583
- const flags10 = ["iso4032", "din934", "asmeb1822"];
9573
+ const flags11 = ["iso4032", "din934", "asmeb1822"];
9584
9574
  const family = selectedFamily(props);
9585
- if (flags10.filter((flag) => props[flag] === true).length > 1)
9575
+ if (flags11.filter((flag) => props[flag] === true).length > 1)
9586
9576
  issue("iso4032", "Select only one ISO, DIN or ASME family");
9587
- for (const flag of flags10)
9577
+ for (const flag of flags11)
9588
9578
  if (family[flag] && props[flag] === false)
9589
9579
  issue(
9590
9580
  flag,
@@ -9632,14 +9622,11 @@ function getHexNutDimensions(input) {
9632
9622
  };
9633
9623
  }
9634
9624
  function parseHexNutModelParams(raw) {
9635
- const tokens = splitModelStringTokens(
9636
- expandModelStringFlags(raw.string, stringFlags8)
9637
- );
9625
+ const tokens = splitModelStringTokens(raw.string);
9638
9626
  if (raw.fn !== "hexnut" || tokens[0]?.toLowerCase() !== "hexnut")
9639
9627
  throw new Error("Expected hexnut without an inline argument");
9640
9628
  const props = { fn: "hexnut" };
9641
- const selectors7 = {
9642
- threadhand: "threadHand",
9629
+ const selectors5 = {
9643
9630
  threadclass: "threadClass"
9644
9631
  };
9645
9632
  let explicitFamily = false;
@@ -9676,9 +9663,13 @@ function parseHexNutModelParams(raw) {
9676
9663
  throw new Error("Duplicate hex nut property threadPitch");
9677
9664
  props.threadPitch = 25.4 / Number(parts[1]);
9678
9665
  }
9666
+ } else if (name === "righthanded") {
9667
+ if (value) throw new Error("Handedness flags cannot have a value");
9668
+ property = "rightHanded";
9669
+ parsed = true;
9679
9670
  } else if (name === "threadpitch") property = "threadPitch";
9680
- else if (name in selectors7) {
9681
- property = selectors7[name];
9671
+ else if (name in selectors5) {
9672
+ property = selectors5[name];
9682
9673
  if (!/^\([^()]+\)$/.test(value))
9683
9674
  throw new Error(`Expected a parenthesized ${name}`);
9684
9675
  parsed = value.slice(1, -1).toLowerCase();
@@ -9697,13 +9688,7 @@ function parseHexNutModelParams(raw) {
9697
9688
  var model28 = defineModel({
9698
9689
  name: "hexnut",
9699
9690
  schema: hexNutModelDefinitionSchema,
9700
- parse: parseHexNutModelParams,
9701
- normalizeString: (value) => normalizeModelStringFlags(
9702
- value,
9703
- stringFlags8,
9704
- parseHexNutModelParams,
9705
- omittedStringFlags8
9706
- )
9691
+ parse: parseHexNutModelParams
9707
9692
  });
9708
9693
  function register28(registry2) {
9709
9694
  registry2.register(model28);
@@ -9965,7 +9950,7 @@ var lengths15 = {
9965
9950
  studchamfer: "studChamfer",
9966
9951
  mouthchamfer: "mouthChamfer"
9967
9952
  };
9968
- var flags5 = {
9953
+ var flags6 = {
9969
9954
  hex: ["hex", true],
9970
9955
  lefthanded: ["leftHand", true],
9971
9956
  righthanded: ["leftHand", false],
@@ -9981,8 +9966,8 @@ function parseMaleFemaleStandoffModelParams(raw) {
9981
9966
  const lower = token.toLowerCase();
9982
9967
  let property;
9983
9968
  let value;
9984
- if (Object.hasOwn(flags5, lower)) {
9985
- const entry = flags5[lower];
9969
+ if (Object.hasOwn(flags6, lower)) {
9970
+ const entry = flags6[lower];
9986
9971
  property = entry[0];
9987
9972
  value = entry[1];
9988
9973
  } else {
@@ -10167,14 +10152,6 @@ var model31 = defineModel({
10167
10152
  function register31(registry2) {
10168
10153
  registry2.register(model31);
10169
10154
  }
10170
- var stringFlags9 = {
10171
- phillips: "drive(phillips)",
10172
- fullthread: "thread(full)",
10173
- lefthanded: "threadhand(left)",
10174
- righthanded: "threadhand(right)",
10175
- male: "threadgender(male)"
10176
- };
10177
- var omittedStringFlags9 = ["righthanded", "male"];
10178
10155
  var positiveModelLengthSchema4 = external_exports.union([
10179
10156
  external_exports.number(),
10180
10157
  external_exports.string().regex(/^(?:\d+(?:\.\d+)?|\.\d+)(?:mm|cm|m|in|inch)?$/i).transform((value) => value.toLowerCase())
@@ -10298,11 +10275,11 @@ var panScrewModelPropsShape = {
10298
10275
  iso7045: external_exports.literal(true).default(true),
10299
10276
  metricSize: panScrewMetricSizeSchema,
10300
10277
  length: positiveModelLengthSchema4,
10301
- thread: external_exports.literal("full").default("full"),
10302
- drive: external_exports.literal("phillips").default("phillips"),
10303
- threadHand: external_exports.enum(["right", "left"]).default("right"),
10278
+ fullThread: external_exports.literal(true).default(true),
10279
+ phillips: external_exports.literal(true).default(true),
10280
+ leftHanded: external_exports.boolean().default(false),
10304
10281
  threadClass: external_exports.literal("6g").default("6g"),
10305
- threadGender: external_exports.literal("male").default("male"),
10282
+ male: external_exports.literal(true).default(true),
10306
10283
  showThreads: external_exports.boolean().default(true),
10307
10284
  iso4757: external_exports.literal(true).default(true),
10308
10285
  recessType: external_exports.literal("H").default("H"),
@@ -10369,11 +10346,7 @@ var aliases8 = {
10369
10346
  metricsize: "metricSize",
10370
10347
  l: "length",
10371
10348
  length: "length",
10372
- thread: "thread",
10373
- drive: "drive",
10374
- threadhand: "threadHand",
10375
10349
  threadclass: "threadClass",
10376
- threadgender: "threadGender",
10377
10350
  diameter: "diameter",
10378
10351
  threadpitch: "threadPitch",
10379
10352
  headdiameter: "headDiameter",
@@ -10404,19 +10377,18 @@ var aliases8 = {
10404
10377
  headh: "headHeight",
10405
10378
  headd: "headDiameter"
10406
10379
  };
10407
- var selectors4 = /* @__PURE__ */ new Set([
10408
- "thread",
10409
- "drive",
10410
- "threadHand",
10411
- "threadClass",
10412
- "threadGender"
10413
- ]);
10380
+ var selectors3 = /* @__PURE__ */ new Set(["threadClass"]);
10381
+ var booleanFlags3 = {
10382
+ phillips: { property: "phillips", value: true },
10383
+ fullthread: { property: "fullThread", value: true },
10384
+ male: { property: "male", value: true },
10385
+ lefthanded: { property: "leftHanded", value: true },
10386
+ righthanded: { property: "leftHanded", value: false }
10387
+ };
10414
10388
  var parsePanScrewModelParams = (raw) => {
10415
10389
  if (raw.fn !== "panscrew")
10416
10390
  throw new Error(`Expected panscrew params, got "${raw.fn}"`);
10417
- const [root, ...tokens] = splitModelStringTokens(
10418
- expandModelStringFlags(raw.string, stringFlags9)
10419
- );
10391
+ const [root, ...tokens] = splitModelStringTokens(raw.string);
10420
10392
  if (root?.toLowerCase() !== "panscrew")
10421
10393
  throw new Error("The panscrew function does not accept an inline value");
10422
10394
  const props = {};
@@ -10433,16 +10405,20 @@ var parsePanScrewModelParams = (raw) => {
10433
10405
  const value = match?.[2];
10434
10406
  let property;
10435
10407
  let parsed;
10436
- if (key === "threads" || key === "nothreads") {
10408
+ if (key && Object.hasOwn(booleanFlags3, key)) {
10409
+ if (value !== "") throw new Error(`Flag "${key}" does not accept a value`);
10410
+ property = booleanFlags3[key].property;
10411
+ parsed = booleanFlags3[key].value;
10412
+ } else if (key === "threads" || key === "nothreads") {
10437
10413
  if (value !== "")
10438
10414
  throw new Error(`Token "${key}" does not accept a value`);
10439
10415
  property = "showThreads";
10440
10416
  parsed = key === "threads";
10441
10417
  } else {
10442
- property = key ? aliases8[key] ?? "" : "";
10418
+ property = key && Object.hasOwn(aliases8, key) ? aliases8[key] : "";
10443
10419
  if (!property || !value)
10444
10420
  throw new Error(`Unknown or missing panscrew token "${token}"`);
10445
- if (selectors4.has(property)) {
10421
+ if (selectors3.has(property)) {
10446
10422
  const selector = value.match(/^\(([^()]+)\)$/)?.[1];
10447
10423
  if (!selector)
10448
10424
  throw new Error(`Token "${key}" requires a parenthesized selector`);
@@ -10475,13 +10451,7 @@ var parsePanScrewModelParams = (raw) => {
10475
10451
  var model32 = defineModel({
10476
10452
  name: "panscrew",
10477
10453
  schema: panScrewModelDefinitionSchema,
10478
- parse: parsePanScrewModelParams,
10479
- normalizeString: (value) => normalizeModelStringFlags(
10480
- value,
10481
- stringFlags9,
10482
- parsePanScrewModelParams,
10483
- omittedStringFlags9
10484
- )
10454
+ parse: parsePanScrewModelParams
10485
10455
  });
10486
10456
  function register32(registry2) {
10487
10457
  registry2.register(model32);
@@ -10667,10 +10637,6 @@ var model34 = defineModel({
10667
10637
  function register34(registry2) {
10668
10638
  registry2.register(model34);
10669
10639
  }
10670
- var stringFlags10 = {
10671
- plainclosed: "style(plainclosed)"
10672
- };
10673
- var omittedStringFlags10 = ["plainclosed"];
10674
10640
  var length18 = external_exports.union([
10675
10641
  external_exports.number(),
10676
10642
  external_exports.string().regex(/^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:mm|cm|m|in|inch|mil|ft|feet)?$/i).transform((value) => value.toLowerCase())
@@ -10681,7 +10647,7 @@ var shape29 = {
10681
10647
  outerDiameter: positiveLength12,
10682
10648
  /** Overall end-plane distance, including the chamfers. */
10683
10649
  length: positiveLength12,
10684
- style: external_exports.literal("plainclosed").default("plainclosed"),
10650
+ plainClosed: external_exports.literal(true).default(true),
10685
10651
  /** Equal axial/radial setbacks of all four 45-degree bore/outside rim chamfers. */
10686
10652
  edgeChamfer: length18.refine((value) => value >= 0).default(0)
10687
10653
  };
@@ -10729,9 +10695,7 @@ var lengths16 = {
10729
10695
  edgechamfer: "edgeChamfer"
10730
10696
  };
10731
10697
  function parsePlainBushingModelParams(raw) {
10732
- const tokens = splitModelStringTokens(
10733
- expandModelStringFlags(raw.string, stringFlags10)
10734
- );
10698
+ const tokens = splitModelStringTokens(raw.string);
10735
10699
  if (raw.fn !== "plainbushing" || tokens[0]?.toLowerCase() !== "plainbushing")
10736
10700
  throw new Error("Expected plainbushing without an inline value");
10737
10701
  const props = { fn: "plainbushing" };
@@ -10745,11 +10709,10 @@ function parsePlainBushingModelParams(raw) {
10745
10709
  if (Object.hasOwn(lengths16, name)) {
10746
10710
  property = lengths16[name];
10747
10711
  parsed = value;
10748
- } else if (name === "style") {
10749
- property = "style";
10750
- const style = value.match(/^\(([a-z]+)\)$/i);
10751
- if (!style) throw new Error("Style requires a parenthesized value");
10752
- parsed = style[1].toLowerCase();
10712
+ } else if (name === "plainclosed") {
10713
+ property = "plainClosed";
10714
+ if (value !== "") throw new Error("plainclosed is a value-free flag");
10715
+ parsed = true;
10753
10716
  } else throw new Error(`Unknown plain bushing token "${token}"`);
10754
10717
  if (Object.hasOwn(props, property))
10755
10718
  throw new Error(
@@ -10762,13 +10725,7 @@ function parsePlainBushingModelParams(raw) {
10762
10725
  var model35 = defineModel({
10763
10726
  name: "plainbushing",
10764
10727
  schema: plainBushingModelDefinitionSchema,
10765
- parse: parsePlainBushingModelParams,
10766
- normalizeString: (value) => normalizeModelStringFlags(
10767
- value,
10768
- stringFlags10,
10769
- parsePlainBushingModelParams,
10770
- omittedStringFlags10
10771
- )
10728
+ parse: parsePlainBushingModelParams
10772
10729
  });
10773
10730
  function register35(registry2) {
10774
10731
  registry2.register(model35);
@@ -10966,10 +10923,7 @@ var lengths17 = {
10966
10923
  thickness: "thickness",
10967
10924
  cornerradius: "cornerRadius"
10968
10925
  };
10969
- var flags6 = { flatframe: "flatFrame" };
10970
- var selectors5 = {
10971
- profile: { value: "flatframe", property: "flatFrame" }
10972
- };
10926
+ var flags7 = { flatframe: "flatFrame" };
10973
10927
  var integers2 = {};
10974
10928
  var tuples2 = {};
10975
10929
  function parseRectangularGasketModelParams(raw) {
@@ -10987,9 +10941,7 @@ function parseRectangularGasketModelParams(raw) {
10987
10941
  if (!match) throw new Error(`Malformed rectangulargasket token "${token}"`);
10988
10942
  const key = match[1].toLowerCase(), value = match[2];
10989
10943
  if (Object.hasOwn(lengths17, key) && value) assign(lengths17[key], value);
10990
- else if (Object.hasOwn(flags6, key) && !value) assign(flags6[key], true);
10991
- else if (Object.hasOwn(selectors5, key) && value.toLowerCase() === `(${selectors5[key].value})`)
10992
- assign(selectors5[key].property, true);
10944
+ else if (Object.hasOwn(flags7, key) && !value) assign(flags7[key], true);
10993
10945
  else if (Object.hasOwn(integers2, key) && /^\d+$/.test(value))
10994
10946
  assign(integers2[key], Number(value));
10995
10947
  else if (Object.hasOwn(tuples2, key)) {
@@ -11095,12 +11047,6 @@ var model39 = defineModel({
11095
11047
  function register39(registry2) {
11096
11048
  registry2.register(model39);
11097
11049
  }
11098
- var stringFlags11 = {
11099
- setscrew: "mount(setscrew)",
11100
- lefthanded: "threadhand(left)",
11101
- righthanded: "threadhand(right)"
11102
- };
11103
- var omittedStringFlags11 = ["righthanded"];
11104
11050
  var length23 = external_exports.union([
11105
11051
  external_exports.number().finite(),
11106
11052
  external_exports.string().regex(
@@ -11121,10 +11067,10 @@ var shape34 = {
11121
11067
  screwCount: external_exports.literal(4).default(4),
11122
11068
  screwEndOffset: positive6.optional(),
11123
11069
  screwAngle: external_exports.number().finite().default(0),
11124
- mount: external_exports.literal("setscrew").default("setscrew"),
11070
+ setScrew: external_exports.literal(true).default(true),
11125
11071
  metricSize: metricBoltSizeSchema,
11126
11072
  threadPitch: positive6.optional(),
11127
- threadHand: external_exports.enum(["right", "left"]).default("right"),
11073
+ leftHanded: external_exports.boolean().default(false),
11128
11074
  threadClass: external_exports.literal("6H").default("6H"),
11129
11075
  chamfer: nonnegative5.default(0)
11130
11076
  };
@@ -11193,7 +11139,7 @@ function getRigidCouplerDimensions(input) {
11193
11139
  diameter: threadDiameter,
11194
11140
  depth: radius - Math.sqrt((hole.bore / 2) ** 2 - (threadDiameter / 2) ** 2),
11195
11141
  threadPitch: p.threadPitch,
11196
- threadHand: p.threadHand,
11142
+ leftHanded: p.leftHanded,
11197
11143
  threadGender: "female",
11198
11144
  threadClass: p.threadClass
11199
11145
  };
@@ -11208,10 +11154,8 @@ function getRigidCouplerDimensions(input) {
11208
11154
  var tokenProperties2 = {
11209
11155
  bore: "boreDiameter",
11210
11156
  od: "outerDiameter",
11211
- mount: "mount",
11212
11157
  m: "metricSize",
11213
11158
  threadpitch: "threadPitch",
11214
- threadhand: "threadHand",
11215
11159
  threadclass: "threadClass",
11216
11160
  chamfer: "chamfer",
11217
11161
  boreb: "boreBDiameter",
@@ -11222,26 +11166,34 @@ var tokenProperties2 = {
11222
11166
  screwangle: "screwAngle"
11223
11167
  };
11224
11168
  function parseRigidCouplerModelParams(raw) {
11225
- const tokens = splitModelStringTokens(
11226
- expandModelStringFlags(raw.string, stringFlags11)
11227
- );
11169
+ const tokens = splitModelStringTokens(raw.string);
11228
11170
  if (raw.fn !== "rigidcoupler" || tokens[0]?.toLowerCase() !== "rigidcoupler")
11229
11171
  throw new Error("Expected an unadorned rigidcoupler function");
11230
11172
  const props = {};
11231
11173
  for (const token of tokens.slice(1)) {
11232
11174
  const match = token.match(/^([a-z]+)(.*)$/i);
11233
11175
  const name = match?.[1]?.toLowerCase() ?? "";
11176
+ const value = match?.[2] ?? "";
11177
+ if (["setscrew", "lefthanded", "righthanded"].includes(name)) {
11178
+ if (value) throw new Error(`Flag "${name}" does not take a value`);
11179
+ const property2 = name === "setscrew" ? "setScrew" : "leftHanded";
11180
+ if (property2 in props)
11181
+ throw new Error(
11182
+ `Duplicate or conflicting rigidcoupler flag "${property2}"`
11183
+ );
11184
+ props[property2] = name !== "righthanded";
11185
+ continue;
11186
+ }
11234
11187
  const property = tokenProperties2[name];
11235
11188
  if (!property) throw new Error(`Unknown rigidcoupler token "${token}"`);
11236
11189
  if (property in props)
11237
11190
  throw new Error(`Duplicate rigidcoupler property "${property}"`);
11238
- const value = match[2];
11239
11191
  if (!value) throw new Error(`Token "${name}" requires a value`);
11240
- if (["mount", "threadHand", "threadClass"].includes(property)) {
11192
+ if (property === "threadClass") {
11241
11193
  const argument = value.match(/^\(([^()]+)\)$/);
11242
11194
  if (!argument)
11243
11195
  throw new Error(`Token "${name}" requires one parenthesized argument`);
11244
- props[property] = property === "threadClass" ? argument[1].toUpperCase() : argument[1].toLowerCase();
11196
+ props[property] = argument[1].toUpperCase();
11245
11197
  } else if (property === "metricSize") {
11246
11198
  if (!/^\d+(?:\.\d+)?$/.test(value))
11247
11199
  throw new Error("m requires a unitless metric designation");
@@ -11266,13 +11218,7 @@ function parseRigidCouplerModelParams(raw) {
11266
11218
  var model40 = defineModel({
11267
11219
  name: "rigidcoupler",
11268
11220
  schema: rigidCouplerModelDefinitionSchema,
11269
- parse: parseRigidCouplerModelParams,
11270
- normalizeString: (value) => normalizeModelStringFlags(
11271
- value,
11272
- stringFlags11,
11273
- parseRigidCouplerModelParams,
11274
- omittedStringFlags11
11275
- )
11221
+ parse: parseRigidCouplerModelParams
11276
11222
  });
11277
11223
  function register40(registry2) {
11278
11224
  registry2.register(model40);
@@ -11388,7 +11334,7 @@ var aliases14 = {
11388
11334
  threadrootdiameter: "threadRootDiameter",
11389
11335
  threadpitchdiameter: "threadPitchDiameter"
11390
11336
  };
11391
- var flags7 = {
11337
+ var flags8 = {
11392
11338
  hexsocket: "hexSocket",
11393
11339
  cuppoint: "cupPoint",
11394
11340
  lefthanded: "leftHand",
@@ -11414,9 +11360,9 @@ function parseSetScrewModelParams(raw) {
11414
11360
  const value = match?.[2] ?? "";
11415
11361
  let property;
11416
11362
  let parsed;
11417
- if (flags7[key]) {
11363
+ if (flags8[key]) {
11418
11364
  if (value) throw new Error(`Flag ${key} does not accept a value`);
11419
- property = flags7[key];
11365
+ property = flags8[key];
11420
11366
  parsed = !["righthanded", "nothreads"].includes(key);
11421
11367
  } else {
11422
11368
  property = aliases14[key] ?? "";
@@ -11450,12 +11396,6 @@ var model41 = defineModel({
11450
11396
  function register41(registry2) {
11451
11397
  registry2.register(model41);
11452
11398
  }
11453
- var stringFlags12 = {
11454
- setscrew: "mount(setscrew)",
11455
- lefthanded: "threadhand(left)",
11456
- righthanded: "threadhand(right)"
11457
- };
11458
- var omittedStringFlags12 = ["righthanded"];
11459
11399
  var length24 = external_exports.union([
11460
11400
  external_exports.number().finite(),
11461
11401
  external_exports.string().regex(
@@ -11474,10 +11414,10 @@ var shape36 = {
11474
11414
  width: positive7,
11475
11415
  screwZ: positive7.optional(),
11476
11416
  screwAngle: external_exports.number().finite().default(0),
11477
- mount: external_exports.literal("setscrew").default("setscrew"),
11417
+ setScrew: external_exports.literal(true).default(true),
11478
11418
  metricSize: metricBoltSizeSchema,
11479
11419
  threadPitch: positive7.optional(),
11480
- threadHand: external_exports.enum(["right", "left"]).default("right"),
11420
+ leftHanded: external_exports.boolean().default(false),
11481
11421
  threadClass: external_exports.literal("6H").default("6H"),
11482
11422
  chamfer: nonnegative6.default(0)
11483
11423
  };
@@ -11527,7 +11467,7 @@ function getShaftCollarDimensions(input) {
11527
11467
  diameter: threadDiameter,
11528
11468
  depth: radius - Math.sqrt((p.boreDiameter / 2) ** 2 - (threadDiameter / 2) ** 2),
11529
11469
  threadPitch: p.threadPitch,
11530
- threadHand: p.threadHand,
11470
+ leftHanded: p.leftHanded,
11531
11471
  threadGender: "female",
11532
11472
  threadClass: p.threadClass
11533
11473
  }
@@ -11536,10 +11476,8 @@ function getShaftCollarDimensions(input) {
11536
11476
  var tokenProperties3 = {
11537
11477
  bore: "boreDiameter",
11538
11478
  od: "outerDiameter",
11539
- mount: "mount",
11540
11479
  m: "metricSize",
11541
11480
  threadpitch: "threadPitch",
11542
- threadhand: "threadHand",
11543
11481
  threadclass: "threadClass",
11544
11482
  chamfer: "chamfer",
11545
11483
  w: "width",
@@ -11548,26 +11486,34 @@ var tokenProperties3 = {
11548
11486
  screwangle: "screwAngle"
11549
11487
  };
11550
11488
  function parseShaftCollarModelParams(raw) {
11551
- const tokens = splitModelStringTokens(
11552
- expandModelStringFlags(raw.string, stringFlags12)
11553
- );
11489
+ const tokens = splitModelStringTokens(raw.string);
11554
11490
  if (raw.fn !== "shaftcollar" || tokens[0]?.toLowerCase() !== "shaftcollar")
11555
11491
  throw new Error("Expected an unadorned shaftcollar function");
11556
11492
  const props = {};
11557
11493
  for (const token of tokens.slice(1)) {
11558
11494
  const match = token.match(/^([a-z]+)(.*)$/i);
11559
11495
  const name = match?.[1]?.toLowerCase() ?? "";
11496
+ const value = match?.[2] ?? "";
11497
+ if (["setscrew", "lefthanded", "righthanded"].includes(name)) {
11498
+ if (value) throw new Error(`Flag "${name}" does not take a value`);
11499
+ const property2 = name === "setscrew" ? "setScrew" : "leftHanded";
11500
+ if (property2 in props)
11501
+ throw new Error(
11502
+ `Duplicate or conflicting shaftcollar flag "${property2}"`
11503
+ );
11504
+ props[property2] = name !== "righthanded";
11505
+ continue;
11506
+ }
11560
11507
  const property = tokenProperties3[name];
11561
11508
  if (!property) throw new Error(`Unknown shaftcollar token "${token}"`);
11562
11509
  if (property in props)
11563
11510
  throw new Error(`Duplicate shaftcollar property "${property}"`);
11564
- const value = match[2];
11565
11511
  if (!value) throw new Error(`Token "${name}" requires a value`);
11566
- if (["mount", "threadHand", "threadClass"].includes(property)) {
11512
+ if (property === "threadClass") {
11567
11513
  const argument = value.match(/^\(([^()]+)\)$/);
11568
11514
  if (!argument)
11569
11515
  throw new Error(`Token "${name}" requires one parenthesized argument`);
11570
- props[property] = property === "threadClass" ? argument[1].toUpperCase() : argument[1].toLowerCase();
11516
+ props[property] = argument[1].toUpperCase();
11571
11517
  } else if (property === "metricSize") {
11572
11518
  if (!/^\d+(?:\.\d+)?$/.test(value))
11573
11519
  throw new Error("m requires a unitless metric designation");
@@ -11585,13 +11531,7 @@ function parseShaftCollarModelParams(raw) {
11585
11531
  var model42 = defineModel({
11586
11532
  name: "shaftcollar",
11587
11533
  schema: shaftCollarModelDefinitionSchema,
11588
- parse: parseShaftCollarModelParams,
11589
- normalizeString: (value) => normalizeModelStringFlags(
11590
- value,
11591
- stringFlags12,
11592
- parseShaftCollarModelParams,
11593
- omittedStringFlags12
11594
- )
11534
+ parse: parseShaftCollarModelParams
11595
11535
  });
11596
11536
  function register42(registry2) {
11597
11537
  registry2.register(model42);
@@ -11861,8 +11801,8 @@ var lengths18 = {
11861
11801
  groovedepth: "grooveDepth",
11862
11802
  splitwidth: "splitWidth"
11863
11803
  };
11864
- var flags8 = {};
11865
- var selectors6 = {};
11804
+ var flags9 = {};
11805
+ var selectors4 = {};
11866
11806
  var integers3 = {};
11867
11807
  var tuples3 = {};
11868
11808
  function parseSplitGrommetModelParams(raw) {
@@ -11880,9 +11820,9 @@ function parseSplitGrommetModelParams(raw) {
11880
11820
  if (!match) throw new Error(`Malformed splitgrommet token "${token}"`);
11881
11821
  const key = match[1].toLowerCase(), value = match[2];
11882
11822
  if (Object.hasOwn(lengths18, key) && value) assign(lengths18[key], value);
11883
- else if (Object.hasOwn(flags8, key) && !value) assign(flags8[key], true);
11884
- else if (Object.hasOwn(selectors6, key) && value.toLowerCase() === `(${selectors6[key].value})`)
11885
- assign(selectors6[key].property, true);
11823
+ else if (Object.hasOwn(flags9, key) && !value) assign(flags9[key], true);
11824
+ else if (Object.hasOwn(selectors4, key) && value.toLowerCase() === `(${selectors4[key].value})`)
11825
+ assign(selectors4[key].property, true);
11886
11826
  else if (Object.hasOwn(integers3, key) && /^\d+$/.test(value))
11887
11827
  assign(integers3[key], Number(value));
11888
11828
  else if (Object.hasOwn(tuples3, key)) {
@@ -12331,12 +12271,9 @@ var aliases17 = {
12331
12271
  barbh: "barbHeight",
12332
12272
  barbheight: "barbHeight"
12333
12273
  };
12334
- var flags9 = {
12274
+ var flags10 = {
12335
12275
  tee: "tee"
12336
12276
  };
12337
- var literals = {
12338
- profile: ["tee", "tee"]
12339
- };
12340
12277
  function parseTSlotCoverStripModelParams(raw) {
12341
12278
  const [name, ...tokens] = splitModelStringTokens(raw.string);
12342
12279
  if (raw.fn !== "tslotcoverstrip" || name?.toLowerCase() !== "tslotcoverstrip")
@@ -12353,15 +12290,10 @@ function parseTSlotCoverStripModelParams(raw) {
12353
12290
  const value = match?.[2];
12354
12291
  if (!key || value === void 0)
12355
12292
  throw new Error(`Malformed tslotcoverstrip token "${token}"`);
12356
- if (Object.hasOwn(flags9, key)) {
12293
+ if (Object.hasOwn(flags10, key)) {
12357
12294
  if (value !== "")
12358
12295
  throw new Error(`tslotcoverstrip flag "${key}" takes no value`);
12359
- assign(flags9[key], true);
12360
- } else if (Object.hasOwn(literals, key)) {
12361
- const [literal, property] = literals[key];
12362
- if (value.toLowerCase() !== `(${literal})`)
12363
- throw new Error(`Expected tslotcoverstrip ${key}(${literal})`);
12364
- assign(property, true);
12296
+ assign(flags10[key], true);
12365
12297
  } else if (Object.hasOwn(aliases17, key) && value) {
12366
12298
  const property = aliases17[key];
12367
12299
  assign(property, property === "pinCount" ? Number(value) : value);
@@ -12378,15 +12310,11 @@ var model49 = defineModel({
12378
12310
  function register49(registry2) {
12379
12311
  registry2.register(model49);
12380
12312
  }
12381
- var stringFlags13 = {
12382
- fourtsolid: "profile(fourtsolid)"
12383
- };
12384
- var omittedStringFlags13 = [];
12385
12313
  var shape44 = {
12386
12314
  width: positiveGearLengthSchema.default(20),
12387
12315
  height: positiveGearLengthSchema.default(20),
12388
12316
  length: positiveGearLengthSchema.default(100),
12389
- profile: external_exports.literal("fourtsolid").default("fourtsolid"),
12317
+ fourTSolid: external_exports.literal(true).default(true),
12390
12318
  slotWidth: positiveGearLengthSchema.default(6),
12391
12319
  pocketWidth: positiveGearLengthSchema.default(10),
12392
12320
  pocketDepth: positiveGearLengthSchema.default(2),
@@ -12446,9 +12374,7 @@ var lengths22 = {
12446
12374
  cornerradius: "cornerRadius"
12447
12375
  };
12448
12376
  function parseTSlotExtrusionModelParams(raw) {
12449
- const tokens = splitModelStringTokens(
12450
- expandModelStringFlags(raw.string, stringFlags13)
12451
- );
12377
+ const tokens = splitModelStringTokens(raw.string);
12452
12378
  if (raw.fn !== "tslotextrusion" || tokens[0]?.toLowerCase() !== raw.fn)
12453
12379
  throw new Error("Expected tslotextrusion without an inline value");
12454
12380
  const props = { fn: "tslotextrusion" };
@@ -12457,11 +12383,10 @@ function parseTSlotExtrusionModelParams(raw) {
12457
12383
  let property;
12458
12384
  let parsed = value;
12459
12385
  if (name in lengths22) property = lengths22[name];
12460
- else if (name === "profile") {
12461
- property = "profile";
12462
- const match = value.match(/^\(([a-z]+)\)$/i);
12463
- if (!match) throw new Error("Profile requires one parenthesized identity");
12464
- parsed = match[1].toLowerCase();
12386
+ else if (name === "fourtsolid") {
12387
+ property = "fourTSolid";
12388
+ if (value !== "") throw new Error("fourtsolid is a value-free flag");
12389
+ parsed = true;
12465
12390
  } else throw new Error(`Unknown T-slot extrusion token "${token}"`);
12466
12391
  if (property in props)
12467
12392
  throw new Error(`T-slot extrusion property "${property}" is repeated`);
@@ -12472,26 +12397,16 @@ function parseTSlotExtrusionModelParams(raw) {
12472
12397
  var model50 = defineModel({
12473
12398
  name: "tslotextrusion",
12474
12399
  schema: tSlotExtrusionModelDefinitionSchema,
12475
- parse: parseTSlotExtrusionModelParams,
12476
- normalizeString: (value) => normalizeModelStringFlags(
12477
- value,
12478
- stringFlags13,
12479
- parseTSlotExtrusionModelParams,
12480
- omittedStringFlags13
12481
- )
12400
+ parse: parseTSlotExtrusionModelParams
12482
12401
  });
12483
12402
  function register50(registry2) {
12484
12403
  registry2.register(model50);
12485
12404
  }
12486
- var stringFlags14 = {
12487
- righttriangle: "shape(righttriangle)"
12488
- };
12489
- var omittedStringFlags14 = [];
12490
12405
  var shape45 = {
12491
12406
  width: positiveGearLengthSchema.default(40),
12492
12407
  height: positiveGearLengthSchema.default(40),
12493
12408
  thickness: positiveGearLengthSchema.default(4),
12494
- shape: external_exports.literal("righttriangle").default("righttriangle"),
12409
+ rightTriangle: external_exports.literal(true).default(true),
12495
12410
  slotCount: external_exports.literal(2).default(2),
12496
12411
  /** Capsule width and overall length, including both semicircular ends. */
12497
12412
  slot: external_exports.tuple([positiveGearLengthSchema, positiveGearLengthSchema]).default([5, 12]),
@@ -12566,9 +12481,7 @@ var lengths23 = {
12566
12481
  edgemargin: "edgeMargin"
12567
12482
  };
12568
12483
  function parseTSlotGussetModelParams(raw) {
12569
- const tokens = splitModelStringTokens(
12570
- expandModelStringFlags(raw.string, stringFlags14)
12571
- );
12484
+ const tokens = splitModelStringTokens(raw.string);
12572
12485
  if (raw.fn !== "tslotgusset" || tokens[0]?.toLowerCase() !== raw.fn)
12573
12486
  throw new Error("Expected tslotgusset without an inline value");
12574
12487
  const props = { fn: "tslotgusset" };
@@ -12580,11 +12493,10 @@ function parseTSlotGussetModelParams(raw) {
12580
12493
  else if (name === "slots" || name === "slotcount") {
12581
12494
  property = "slotCount";
12582
12495
  parsed = parseGearInteger(value, "slotCount");
12583
- } else if (name === "shape") {
12584
- property = "shape";
12585
- const match = value.match(/^\(([a-z]+)\)$/i);
12586
- if (!match) throw new Error("Shape requires one parenthesized identity");
12587
- parsed = match[1].toLowerCase();
12496
+ } else if (name === "righttriangle") {
12497
+ property = "rightTriangle";
12498
+ if (value !== "") throw new Error("righttriangle is a value-free flag");
12499
+ parsed = true;
12588
12500
  } else if (name === "slot" || name === "centers") {
12589
12501
  property = name;
12590
12502
  const match = value.match(/^\(([^(),]+),([^(),]+)\)$/);
@@ -12600,13 +12512,7 @@ function parseTSlotGussetModelParams(raw) {
12600
12512
  var model51 = defineModel({
12601
12513
  name: "tslotgusset",
12602
12514
  schema: tSlotGussetModelDefinitionSchema,
12603
- parse: parseTSlotGussetModelParams,
12604
- normalizeString: (value) => normalizeModelStringFlags(
12605
- value,
12606
- stringFlags14,
12607
- parseTSlotGussetModelParams,
12608
- omittedStringFlags14
12609
- )
12515
+ parse: parseTSlotGussetModelParams
12610
12516
  });
12611
12517
  function register51(registry2) {
12612
12518
  registry2.register(model51);
@@ -12862,7 +12768,7 @@ function getNemaMotorReferencePoints(input) {
12862
12768
  p.bodyWidth / 2 / Math.max(Math.abs(x), Math.abs(y)),
12863
12769
  (p.bodyWidth - p.faceCornerChamfer) / (Math.abs(x) + Math.abs(y))
12864
12770
  );
12865
- if (p.nemaSize === 34 && p.cornerProfile === "stepped") {
12771
+ if (p.nemaSize === 34 && p.stepped) {
12866
12772
  const h = p.bodyWidth / 2, c = p.bodyCornerChamfer / Math.SQRT2, r = Math.min(4, c / 4);
12867
12773
  const contains = (distance2) => {
12868
12774
  const a = Math.abs(distance2 * x), b = Math.abs(distance2 * y);
@@ -12906,7 +12812,7 @@ function getNemaMotorReferencePoints(input) {
12906
12812
  },
12907
12813
  direction: { x, y, z: 0 }
12908
12814
  },
12909
- shaftflat: p.shaftShape === "d" ? {
12815
+ shaftflat: p.dShaft ? {
12910
12816
  position: {
12911
12817
  x: (p.shaftDiameter / 2 - p.shaftFlatDepth) * Math.cos(flatRadians),
12912
12818
  y: (p.shaftDiameter / 2 - p.shaftFlatDepth) * Math.sin(flatRadians),
@@ -14486,7 +14392,11 @@ function finishShaftMountMesh(geometry) {
14486
14392
  function createClampingShaftCollarMesh(input) {
14487
14393
  const props = clampingShaftCollarModelPropsSchema.parse(input);
14488
14394
  const dimensions5 = getClampingShaftCollarDimensions(props);
14489
- assertShaftMountResolution([dimensions5.threadedHole]);
14395
+ const threadedHole = {
14396
+ ...dimensions5.threadedHole,
14397
+ threadHand: dimensions5.threadedHole.leftHanded ? "left" : "right"
14398
+ };
14399
+ assertShaftMountResolution([threadedHole]);
14490
14400
  const body = createAnnularSleeve({
14491
14401
  outerRadius: props.outerDiameter / 2,
14492
14402
  boreARadius: props.boreDiameter / 2,
@@ -14512,7 +14422,7 @@ function createClampingShaftCollarMesh(input) {
14512
14422
  body,
14513
14423
  slit,
14514
14424
  createMountingHoleCutter(dimensions5.clearanceHole),
14515
- createMountingHoleCutter(dimensions5.threadedHole)
14425
+ createMountingHoleCutter(threadedHole)
14516
14426
  )
14517
14427
  );
14518
14428
  }
@@ -14702,7 +14612,7 @@ function createCompressionSpringMesh(input, options = {}) {
14702
14612
  }
14703
14613
  }
14704
14614
  const triangle = (a, b, c) => {
14705
- if (props.hand === "left") indices.push(a, c, b);
14615
+ if (props.leftHanded) indices.push(a, c, b);
14706
14616
  else indices.push(a, b, c);
14707
14617
  };
14708
14618
  for (let step = 0; step < steps; step++)
@@ -15477,7 +15387,7 @@ function createFlatHeadScrewMesh(input, options = {}) {
15477
15387
  levels.add(-p.length + (shaftEnd + p.length) * i / steps);
15478
15388
  for (const z of [...levels].sort((a, b) => a - b)) {
15479
15389
  const r = add((theta) => {
15480
- const phase = (((z + p.length) / pitch - (p.threadHand === "right" ? 1 : -1) * theta / (2 * Math.PI)) % 1 + 1) % 1;
15390
+ const phase = (((z + p.length) / pitch - (p.leftHanded ? -1 : 1) * theta / (2 * Math.PI)) % 1 + 1) % 1;
15481
15391
  const d = Math.min(phase, 1 - phase);
15482
15392
  const groove = Math.min(
15483
15393
  major - minor,
@@ -15694,6 +15604,11 @@ var resolveFlexScreenSize = ({
15694
15604
  };
15695
15605
  };
15696
15606
  var resolveOrientation = (props) => {
15607
+ if ("orientation" in props) {
15608
+ throw new Error(
15609
+ "FlexScreen orientation is no longer supported; use a boolean placement flag"
15610
+ );
15611
+ }
15697
15612
  const shortcuts = [
15698
15613
  ["sitsFlat", props.sitsFlat],
15699
15614
  ["sitsFlatBelowBoard", props.sitsFlatBelowBoard],
@@ -15703,13 +15618,24 @@ var resolveOrientation = (props) => {
15703
15618
  ["foldedToFaceBelowBoard", props.foldsBelowBoard],
15704
15619
  ["foldedToRightAngleAboveBoard", props.foldedToRightAngleAboveBoard],
15705
15620
  ["foldedToRightAngleBelowBoard", props.foldedToRightAngleBelowBoard]
15706
- ].filter((entry) => entry[1]);
15707
- if (shortcuts.length > 1) {
15621
+ ];
15622
+ for (const [name, value] of shortcuts) {
15623
+ if (value !== void 0 && typeof value !== "boolean") {
15624
+ throw new Error(`FlexScreen placement flag "${name}" must be a boolean`);
15625
+ }
15626
+ }
15627
+ const selected = shortcuts.filter((entry) => entry[1] === true);
15628
+ if (selected.length > 1) {
15708
15629
  throw new Error(
15709
15630
  "Only one FlexScreen boolean orientation shortcut can be true"
15710
15631
  );
15711
15632
  }
15712
- return shortcuts[0]?.[0] ?? props.orientation ?? "sitsFlat";
15633
+ if (selected.length === 0 && shortcuts.some((entry) => entry[1] !== void 0)) {
15634
+ throw new Error(
15635
+ "A FlexScreen orientation flag must be true when placement flags are supplied"
15636
+ );
15637
+ }
15638
+ return selected[0]?.[0] ?? "sitsFlat";
15713
15639
  };
15714
15640
  var distance = (a, b) => Math.hypot(b[0] - a[0], b[1] - a[1], b[2] - a[2]);
15715
15641
  var interpolate = (a, b, progress) => [
@@ -16595,7 +16521,7 @@ function createTwistedSpurGearMesh(input, twist = 0, segmentsPerTurn = 32) {
16595
16521
  function createHelicalGearMesh(input) {
16596
16522
  const props = helicalGearModelPropsSchema.parse(input);
16597
16523
  const { twistAngle } = getHelicalGearDimensions(props);
16598
- const { helixAngle, handedness, segmentsPerTurn, ...spur } = props;
16524
+ const { helixAngle, leftHanded, segmentsPerTurn, ...spur } = props;
16599
16525
  return createTwistedSpurGearMesh(
16600
16526
  spur,
16601
16527
  twistAngle * Math.PI / 180,
@@ -16703,7 +16629,7 @@ function createHexBoltMesh(input, options = {}) {
16703
16629
  levels.add(-p.length + (shaftEnd + p.length) * i / steps);
16704
16630
  for (const z of [...levels].sort((a, b) => a - b)) {
16705
16631
  const r = add((theta) => {
16706
- const phase = (((z + p.length) / pitch - (p.threadHand === "right" ? 1 : -1) * theta / (2 * Math.PI)) % 1 + 1) % 1;
16632
+ const phase = (((z + p.length) / pitch - (p.leftHanded ? -1 : 1) * theta / (2 * Math.PI)) % 1 + 1) % 1;
16707
16633
  const d = Math.min(phase, 1 - phase);
16708
16634
  const groove = Math.min(
16709
16635
  major - minor,
@@ -17355,14 +17281,14 @@ var resolveNemaMotorProps = nemaMotorModelPropsSchema.parse.bind(nemaMotorModelP
17355
17281
  // lib/utils/nemaMotorWireGeometry.ts
17356
17282
  function createNemaMotorWireGeometry(input) {
17357
17283
  const p = resolveNemaMotorProps(input);
17358
- if (p.wireConnection === "none") return [];
17284
+ if (p.noWires) return [];
17359
17285
  const { position } = getNemaMotorReferencePoints(p).wireside;
17360
17286
  const angle = p.wireSideAngle * Math.PI / 180;
17361
17287
  const place = (geometry) => jscad8.transforms.translate(
17362
17288
  [position.x, position.y, position.z],
17363
17289
  jscad8.transforms.rotateZ(angle, geometry)
17364
17290
  );
17365
- if (p.wireConnection === "stubs") {
17291
+ if (p.wireStubs) {
17366
17292
  const colors = [
17367
17293
  "#d53f3f",
17368
17294
  "#2463af",
@@ -17508,11 +17434,11 @@ function createNemaMotorSections(input) {
17508
17434
  p.bodyWidth,
17509
17435
  p.faceCornerChamfer
17510
17436
  );
17511
- const profile6 = p.cornerProfile === "stepped" ? steppedFace : face;
17437
+ const profile6 = p.stepped ? steppedFace : face;
17512
17438
  const core = profile6(p.bodyWidth, p.bodyCornerChamfer);
17513
17439
  const rear = profile6(
17514
17440
  p.bodyWidth,
17515
- p.rearCornerChamfer ?? (p.backFace === "plain" && p.mountingHoleThrough ? p.bodyCornerChamfer : p.faceCornerChamfer)
17441
+ p.rearCornerChamfer ?? (p.backFacePlain && p.mountingHoleThrough ? p.bodyCornerChamfer : p.faceCornerChamfer)
17516
17442
  );
17517
17443
  const h = p.mountingHoleSpacing / 2;
17518
17444
  const centers = [
@@ -17528,7 +17454,7 @@ function createNemaMotorSections(input) {
17528
17454
  add("frontCap", front, -holeDepth, 0, holes);
17529
17455
  add("frontCap", front, -p.frontCapLength, -holeDepth);
17530
17456
  add("body", core, -p.bodyLength + p.rearCapLength, -p.frontCapLength);
17531
- if (p.backFace === "plain") {
17457
+ if (p.backFacePlain) {
17532
17458
  add("rearCap", rear, -p.bodyLength, -p.bodyLength + p.rearCapLength);
17533
17459
  } else {
17534
17460
  const halfPitch = p.backFaceHoleSpacing / 2;
@@ -17554,8 +17480,7 @@ function createNemaMotorSections(input) {
17554
17480
  add("pilot", circle(p.pilotDiameter / 2), 0, p.pilotLength);
17555
17481
  const r = p.shaftDiameter / 2;
17556
17482
  const round = circle(r);
17557
- if (p.shaftShape === "round")
17558
- add("shaft", round, p.pilotLength, p.shaftLength);
17483
+ if (p.roundShaft) add("shaft", round, p.pilotLength, p.shaftLength);
17559
17484
  else {
17560
17485
  const cut = r - p.shaftFlatDepth;
17561
17486
  const angle = Math.acos(cut / r);
@@ -17586,7 +17511,7 @@ function NemaMotor({
17586
17511
  ...props
17587
17512
  }) {
17588
17513
  const p = resolveNemaMotorProps(props);
17589
- const screw = p.backFace === "screws" ? jscad9.transforms.rotateX(
17514
+ const screw = p.backFaceScrews ? jscad9.transforms.rotateX(
17590
17515
  Math.PI,
17591
17516
  createHexSocketBoltGeom({
17592
17517
  metricSize: p.backFaceScrewSize,
@@ -17904,7 +17829,7 @@ function createPanScrewMesh(input, options = {}) {
17904
17829
  levels.add(-p.length + (shaftEnd + p.length) * i / steps);
17905
17830
  for (const z of [...levels].sort((a, b) => a - b)) {
17906
17831
  const r = add((theta) => {
17907
- const phase = (((z + p.length) / pitch - (p.threadHand === "right" ? 1 : -1) * theta / (2 * Math.PI)) % 1 + 1) % 1;
17832
+ const phase = (((z + p.length) / pitch - (p.leftHanded ? -1 : 1) * theta / (2 * Math.PI)) % 1 + 1) % 1;
17908
17833
  const d = Math.min(phase, 1 - phase);
17909
17834
  const groove = Math.min(
17910
17835
  major - minor,
@@ -18684,7 +18609,11 @@ import "@jscad/modeling";
18684
18609
  function createRigidCouplerMesh(input) {
18685
18610
  const props = rigidCouplerModelPropsSchema.parse(input);
18686
18611
  const dimensions5 = getRigidCouplerDimensions(props);
18687
- assertShaftMountResolution(dimensions5.screwHoles);
18612
+ const screwHoles = dimensions5.screwHoles.map((hole) => ({
18613
+ ...hole,
18614
+ threadHand: hole.leftHanded ? "left" : "right"
18615
+ }));
18616
+ assertShaftMountResolution(screwHoles);
18688
18617
  const body = createAnnularSleeve({
18689
18618
  outerRadius: props.outerDiameter / 2,
18690
18619
  boreARadius: props.boreDiameter / 2,
@@ -18694,10 +18623,7 @@ function createRigidCouplerMesh(input) {
18694
18623
  stepZ: dimensions5.boreADepth
18695
18624
  });
18696
18625
  return finishShaftMountMesh(
18697
- subtractShaftMountParts(
18698
- body,
18699
- ...dimensions5.screwHoles.map(createMountingHoleCutter)
18700
- )
18626
+ subtractShaftMountParts(body, ...screwHoles.map(createMountingHoleCutter))
18701
18627
  );
18702
18628
  }
18703
18629
 
@@ -18860,7 +18786,11 @@ import "@jscad/modeling";
18860
18786
  function createShaftCollarMesh(input) {
18861
18787
  const props = shaftCollarModelPropsSchema.parse(input);
18862
18788
  const dimensions5 = getShaftCollarDimensions(props);
18863
- assertShaftMountResolution([dimensions5.screwHole]);
18789
+ const screwHole = {
18790
+ ...dimensions5.screwHole,
18791
+ threadHand: dimensions5.screwHole.leftHanded ? "left" : "right"
18792
+ };
18793
+ assertShaftMountResolution([screwHole]);
18864
18794
  const body = createAnnularSleeve({
18865
18795
  outerRadius: props.outerDiameter / 2,
18866
18796
  boreARadius: props.boreDiameter / 2,
@@ -18868,10 +18798,7 @@ function createShaftCollarMesh(input) {
18868
18798
  chamfer: props.chamfer
18869
18799
  });
18870
18800
  return finishShaftMountMesh(
18871
- subtractShaftMountParts(
18872
- body,
18873
- createMountingHoleCutter(dimensions5.screwHole)
18874
- )
18801
+ subtractShaftMountParts(body, createMountingHoleCutter(screwHole))
18875
18802
  );
18876
18803
  }
18877
18804
 
@@ -18902,11 +18829,11 @@ import { Colorize as Colorize46, Custom as Custom38 } from "jscad-fiber";
18902
18829
  // lib/mechanical/sheet-metal-mesh.ts
18903
18830
  import earcut5 from "earcut";
18904
18831
  function holeOutline(hole) {
18905
- const radius = (hole.shape === "round" ? hole.diameter : hole.width) / 2;
18906
- const straight = hole.shape === "slot" ? (hole.length - hole.width) / 2 : 0;
18832
+ const radius = (hole.round ? hole.diameter : hole.width) / 2;
18833
+ const straight = hole.slot ? (hole.length - hole.width) / 2 : 0;
18907
18834
  if (straight < 0) throw new Error("Slot length must be at least its width");
18908
18835
  return Array.from({ length: 64 }, (_, i) => {
18909
- if (hole.shape === "round") {
18836
+ if (hole.round) {
18910
18837
  const angle2 = i * Math.PI / 32;
18911
18838
  return {
18912
18839
  u: hole.u + radius * Math.cos(angle2),
@@ -18917,12 +18844,13 @@ function holeOutline(hole) {
18917
18844
  const angle = -Math.PI / 2 + (i < 32 ? i : i - 32) * Math.PI / 31 + (i < 32 ? 0 : Math.PI);
18918
18845
  const along = half * straight + radius * Math.cos(angle);
18919
18846
  const across = radius * Math.sin(angle);
18920
- return hole.shape === "slot" && hole.axis === "v" ? { u: hole.u - across, v: hole.v + along } : { u: hole.u + along, v: hole.v + across };
18847
+ return hole.slot && hole.axis === "v" ? { u: hole.u - across, v: hole.v + along } : { u: hole.u + along, v: hole.v + across };
18921
18848
  });
18922
18849
  }
18923
18850
  function createSheetMetalMesh(input) {
18924
18851
  const props = sheetMetalModelPropsSchema.parse(input);
18925
- const { width: width10, baseLength, flangeHeight, thickness, profile: profile6 } = props;
18852
+ const { width: width10, baseLength, flangeHeight, thickness } = props;
18853
+ const profile6 = props.channel ? "channel" : props.angle ? "angle" : "plate";
18926
18854
  const radius = props.insideBendRadius + thickness / 2;
18927
18855
  const positions = [];
18928
18856
  const indices = [];
@@ -20128,7 +20056,7 @@ var createWormGearMesh = (input) => {
20128
20056
  const positions = [];
20129
20057
  const indices = [];
20130
20058
  const phase = props.phase % 360 * Math.PI / 180;
20131
- const direction = props.handedness === "right" ? 1 : -1;
20059
+ const direction = props.leftHanded ? -1 : 1;
20132
20060
  const ring = (z) => {
20133
20061
  const first = positions.length / 3;
20134
20062
  const rotation = phase + direction * (z / lead) * Math.PI * 2;