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/vanilla.js CHANGED
@@ -24,7 +24,7 @@ function h(type, props, ...restChildren) {
24
24
  };
25
25
  }
26
26
 
27
- // .model-contracts/generations/fa75ee0265d6d666dfb181dbec270fd94d15a3b5-v2/node_modules/zod/v3/external.js
27
+ // .model-contracts/generations/e80fbad5260b66fd00b4ab7513941eadd9b0b17b-v2/node_modules/zod/v3/external.js
28
28
  var external_exports = {};
29
29
  __export(external_exports, {
30
30
  BRAND: () => BRAND,
@@ -136,7 +136,7 @@ __export(external_exports, {
136
136
  void: () => voidType
137
137
  });
138
138
 
139
- // .model-contracts/generations/fa75ee0265d6d666dfb181dbec270fd94d15a3b5-v2/node_modules/zod/v3/helpers/util.js
139
+ // .model-contracts/generations/e80fbad5260b66fd00b4ab7513941eadd9b0b17b-v2/node_modules/zod/v3/helpers/util.js
140
140
  var util;
141
141
  (function(util2) {
142
142
  util2.assertEqual = (_) => {
@@ -270,7 +270,7 @@ var getParsedType = (data) => {
270
270
  }
271
271
  };
272
272
 
273
- // .model-contracts/generations/fa75ee0265d6d666dfb181dbec270fd94d15a3b5-v2/node_modules/zod/v3/ZodError.js
273
+ // .model-contracts/generations/e80fbad5260b66fd00b4ab7513941eadd9b0b17b-v2/node_modules/zod/v3/ZodError.js
274
274
  var ZodIssueCode = util.arrayToEnum([
275
275
  "invalid_type",
276
276
  "invalid_literal",
@@ -388,7 +388,7 @@ ZodError.create = (issues) => {
388
388
  return error;
389
389
  };
390
390
 
391
- // .model-contracts/generations/fa75ee0265d6d666dfb181dbec270fd94d15a3b5-v2/node_modules/zod/v3/locales/en.js
391
+ // .model-contracts/generations/e80fbad5260b66fd00b4ab7513941eadd9b0b17b-v2/node_modules/zod/v3/locales/en.js
392
392
  var errorMap = (issue, _ctx) => {
393
393
  let message;
394
394
  switch (issue.code) {
@@ -491,7 +491,7 @@ var errorMap = (issue, _ctx) => {
491
491
  };
492
492
  var en_default = errorMap;
493
493
 
494
- // .model-contracts/generations/fa75ee0265d6d666dfb181dbec270fd94d15a3b5-v2/node_modules/zod/v3/errors.js
494
+ // .model-contracts/generations/e80fbad5260b66fd00b4ab7513941eadd9b0b17b-v2/node_modules/zod/v3/errors.js
495
495
  var overrideErrorMap = en_default;
496
496
  function setErrorMap(map) {
497
497
  overrideErrorMap = map;
@@ -500,7 +500,7 @@ function getErrorMap() {
500
500
  return overrideErrorMap;
501
501
  }
502
502
 
503
- // .model-contracts/generations/fa75ee0265d6d666dfb181dbec270fd94d15a3b5-v2/node_modules/zod/v3/helpers/parseUtil.js
503
+ // .model-contracts/generations/e80fbad5260b66fd00b4ab7513941eadd9b0b17b-v2/node_modules/zod/v3/helpers/parseUtil.js
504
504
  var makeIssue = (params) => {
505
505
  const { data, path, errorMaps, issueData } = params;
506
506
  const fullPath = [...path, ...issueData.path || []];
@@ -610,14 +610,14 @@ var isDirty = (x) => x.status === "dirty";
610
610
  var isValid = (x) => x.status === "valid";
611
611
  var isAsync = (x) => typeof Promise !== "undefined" && x instanceof Promise;
612
612
 
613
- // .model-contracts/generations/fa75ee0265d6d666dfb181dbec270fd94d15a3b5-v2/node_modules/zod/v3/helpers/errorUtil.js
613
+ // .model-contracts/generations/e80fbad5260b66fd00b4ab7513941eadd9b0b17b-v2/node_modules/zod/v3/helpers/errorUtil.js
614
614
  var errorUtil;
615
615
  (function(errorUtil2) {
616
616
  errorUtil2.errToObj = (message) => typeof message === "string" ? { message } : message || {};
617
617
  errorUtil2.toString = (message) => typeof message === "string" ? message : message?.message;
618
618
  })(errorUtil || (errorUtil = {}));
619
619
 
620
- // .model-contracts/generations/fa75ee0265d6d666dfb181dbec270fd94d15a3b5-v2/node_modules/zod/v3/types.js
620
+ // .model-contracts/generations/e80fbad5260b66fd00b4ab7513941eadd9b0b17b-v2/node_modules/zod/v3/types.js
621
621
  var ParseInputLazyPath = class {
622
622
  constructor(parent, value, path, key) {
623
623
  this._cachedPath = [];
@@ -4065,7 +4065,7 @@ var coerce = {
4065
4065
  };
4066
4066
  var NEVER = INVALID;
4067
4067
 
4068
- // .model-contracts/generations/fa75ee0265d6d666dfb181dbec270fd94d15a3b5-v2/node_modules/@tscircuit/mm/dist/index.js
4068
+ // .model-contracts/generations/e80fbad5260b66fd00b4ab7513941eadd9b0b17b-v2/node_modules/@tscircuit/mm/dist/index.js
4069
4069
  var unitToMm = {
4070
4070
  in: 25.4,
4071
4071
  inch: 25.4,
@@ -4092,7 +4092,7 @@ var mm = (n) => {
4092
4092
  throw new Error(`Unsupported unit: ${unit}`);
4093
4093
  };
4094
4094
 
4095
- // .model-contracts/generations/fa75ee0265d6d666dfb181dbec270fd94d15a3b5-v2/index.js
4095
+ // .model-contracts/generations/e80fbad5260b66fd00b4ab7513941eadd9b0b17b-v2/index.js
4096
4096
  function normalizeNemaMotorModelString(value) {
4097
4097
  if (!/^nema(?:8|17|23|34)(?:_|$)/i.test(value)) return value;
4098
4098
  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");
@@ -4148,36 +4148,6 @@ var parseModelStringParams = (definition) => {
4148
4148
  params.string = normalizedDefinition;
4149
4149
  return params;
4150
4150
  };
4151
- function expandModelStringFlags(value, flags10) {
4152
- return splitModelStringTokens(value).map(
4153
- (token, index) => index > 0 && Object.hasOwn(flags10, token.toLowerCase()) ? flags10[token.toLowerCase()] : token
4154
- ).join("_");
4155
- }
4156
- function normalizeModelStringFlags(value, flags10, parse, omittedFlags) {
4157
- const tokens = splitModelStringTokens(value);
4158
- if (!tokens.slice(1).some((token) => Object.hasOwn(flags10, token.toLowerCase())))
4159
- return value;
4160
- const expanded = expandModelStringFlags(value, flags10);
4161
- parse(parseModelStringParams(expanded));
4162
- const preferred = new Map(
4163
- Object.entries(flags10).map(([flag, selector]) => [selector, flag])
4164
- );
4165
- const omitted = new Set(omittedFlags.map((flag) => flags10[flag]));
4166
- return splitModelStringTokens(expanded).flatMap((token, index) => {
4167
- if (index === 0) return [token.toLowerCase()];
4168
- const lower = token.toLowerCase();
4169
- if (omitted.has(lower)) return [];
4170
- return [preferred.get(lower) ?? token];
4171
- }).join("_");
4172
- }
4173
- var stringFlags = {
4174
- hex: "drive(hex)",
4175
- fullthread: "thread(full)",
4176
- lefthanded: "threadhand(left)",
4177
- righthanded: "threadhand(right)",
4178
- male: "threadgender(male)"
4179
- };
4180
- var omittedStringFlags = ["righthanded", "male"];
4181
4151
  function defineModel(model552) {
4182
4152
  return model552;
4183
4153
  }
@@ -4324,11 +4294,11 @@ var hexBoltModelPropsShape = {
4324
4294
  iso4017: external_exports.literal(true).default(true),
4325
4295
  metricSize: hexBoltMetricSizeSchema,
4326
4296
  length: positiveModelLengthSchema2,
4327
- thread: external_exports.literal("full").default("full"),
4328
- drive: external_exports.literal("hex").default("hex"),
4329
- threadHand: external_exports.enum(["right", "left"]).default("right"),
4297
+ fullThread: external_exports.literal(true).default(true),
4298
+ hex: external_exports.literal(true).default(true),
4299
+ leftHanded: external_exports.boolean().default(false),
4330
4300
  threadClass: external_exports.literal("6g").default("6g"),
4331
- threadGender: external_exports.literal("male").default("male"),
4301
+ male: external_exports.literal(true).default(true),
4332
4302
  showThreads: external_exports.boolean().default(true),
4333
4303
  diameter: positiveModelLengthSchema2.optional(),
4334
4304
  threadPitch: positiveModelLengthSchema2.optional(),
@@ -4373,11 +4343,7 @@ var aliases = {
4373
4343
  metricsize: "metricSize",
4374
4344
  l: "length",
4375
4345
  length: "length",
4376
- thread: "thread",
4377
- drive: "drive",
4378
- threadhand: "threadHand",
4379
4346
  threadclass: "threadClass",
4380
- threadgender: "threadGender",
4381
4347
  diameter: "diameter",
4382
4348
  threadpitch: "threadPitch",
4383
4349
  headacrossflats: "headAcrossFlats",
@@ -4395,19 +4361,18 @@ var aliases = {
4395
4361
  headh: "headHeight",
4396
4362
  af: "headAcrossFlats"
4397
4363
  };
4398
- var selectors = /* @__PURE__ */ new Set([
4399
- "thread",
4400
- "drive",
4401
- "threadHand",
4402
- "threadClass",
4403
- "threadGender"
4404
- ]);
4364
+ var selectors = /* @__PURE__ */ new Set(["threadClass"]);
4365
+ var booleanFlags = {
4366
+ hex: { property: "hex", value: true },
4367
+ fullthread: { property: "fullThread", value: true },
4368
+ male: { property: "male", value: true },
4369
+ lefthanded: { property: "leftHanded", value: true },
4370
+ righthanded: { property: "leftHanded", value: false }
4371
+ };
4405
4372
  var parseHexBoltModelParams = (raw) => {
4406
4373
  if (raw.fn !== "hexbolt")
4407
4374
  throw new Error(`Expected hexbolt params, got "${raw.fn}"`);
4408
- const [root, ...tokens] = splitModelStringTokens(
4409
- expandModelStringFlags(raw.string, stringFlags)
4410
- );
4375
+ const [root, ...tokens] = splitModelStringTokens(raw.string);
4411
4376
  if (root?.toLowerCase() !== "hexbolt")
4412
4377
  throw new Error("The hexbolt function does not accept an inline value");
4413
4378
  const props = {};
@@ -4423,13 +4388,17 @@ var parseHexBoltModelParams = (raw) => {
4423
4388
  const value = match?.[2];
4424
4389
  let property;
4425
4390
  let parsed;
4426
- if (key === "threads" || key === "nothreads") {
4391
+ if (key && Object.hasOwn(booleanFlags, key)) {
4392
+ if (value !== "") throw new Error(`Flag "${key}" does not accept a value`);
4393
+ property = booleanFlags[key].property;
4394
+ parsed = booleanFlags[key].value;
4395
+ } else if (key === "threads" || key === "nothreads") {
4427
4396
  if (value !== "")
4428
4397
  throw new Error(`Token "${key}" does not accept a value`);
4429
4398
  property = "showThreads";
4430
4399
  parsed = key === "threads";
4431
4400
  } else {
4432
- property = key ? aliases[key] ?? "" : "";
4401
+ property = key && Object.hasOwn(aliases, key) ? aliases[key] : "";
4433
4402
  if (!property || !value)
4434
4403
  throw new Error(`Unknown or missing hexbolt token "${token}"`);
4435
4404
  if (selectors.has(property)) {
@@ -4461,13 +4430,7 @@ var parseHexBoltModelParams = (raw) => {
4461
4430
  var model = defineModel({
4462
4431
  name: "hexbolt",
4463
4432
  schema: hexBoltModelDefinitionSchema,
4464
- parse: parseHexBoltModelParams,
4465
- normalizeString: (value) => normalizeModelStringFlags(
4466
- value,
4467
- stringFlags,
4468
- parseHexBoltModelParams,
4469
- omittedStringFlags
4470
- )
4433
+ parse: parseHexBoltModelParams
4471
4434
  });
4472
4435
  function register(registry2) {
4473
4436
  registry2.register(model);
@@ -4574,11 +4537,11 @@ var shape2 = {
4574
4537
  /** Unsigned pitch-cylinder helix angle to +Z, in degrees. */
4575
4538
  helixAngle: external_exports.number().finite().min(0).lt(90).default(20),
4576
4539
  /** Right-hand teeth advance counterclockwise as Z increases. */
4577
- handedness: external_exports.enum(["right", "left"]).default("right"),
4540
+ leftHanded: external_exports.boolean().default(false),
4578
4541
  segmentsPerTurn: external_exports.number().int().min(12).max(128).default(32)
4579
4542
  };
4580
4543
  function dimensions2(props) {
4581
- const { helixAngle, handedness, segmentsPerTurn, ...spur } = props;
4544
+ const { helixAngle, leftHanded, segmentsPerTurn, ...spur } = props;
4582
4545
  const d = getSpurGearDimensions(spur);
4583
4546
  const beta = helixAngle * Math.PI / 180;
4584
4547
  return {
@@ -4589,18 +4552,18 @@ function dimensions2(props) {
4589
4552
  ) * 180 / Math.PI,
4590
4553
  normalPitch: d.circularPitch * Math.cos(beta),
4591
4554
  /** Signed angular advance between the lower and upper faces, in degrees. */
4592
- twistAngle: helixAngle === 0 ? 0 : (handedness === "right" ? 1 : -1) * (2 * props.faceWidth / d.pitchDiameter * Math.tan(beta) * 180) / Math.PI
4555
+ twistAngle: helixAngle === 0 ? 0 : (leftHanded ? -1 : 1) * (2 * props.faceWidth / d.pitchDiameter * Math.tan(beta) * 180) / Math.PI
4593
4556
  };
4594
4557
  }
4595
4558
  function validate2(props, context) {
4596
- const { fn, helixAngle, handedness, segmentsPerTurn, ...spur } = props;
4559
+ const { fn, helixAngle, leftHanded, segmentsPerTurn, ...spur } = props;
4597
4560
  const result = spurGearModelPropsSchema.safeParse(spur);
4598
4561
  if (!result.success) {
4599
4562
  for (const issue of result.error.issues) context.addIssue(issue);
4600
4563
  return;
4601
4564
  }
4602
4565
  if (Object.values(
4603
- dimensions2({ ...result.data, helixAngle, handedness, segmentsPerTurn })
4566
+ dimensions2({ ...result.data, helixAngle, leftHanded, segmentsPerTurn })
4604
4567
  ).some((value) => !Number.isFinite(value)))
4605
4568
  context.addIssue({
4606
4569
  code: "custom",
@@ -4634,7 +4597,7 @@ function parseHelicalGearModelParams(raw) {
4634
4597
  const [name, value] = parseGearToken(token);
4635
4598
  let property;
4636
4599
  let parsed;
4637
- if (name in lengths) {
4600
+ if (Object.hasOwn(lengths, name)) {
4638
4601
  property = lengths[name];
4639
4602
  parsed = value;
4640
4603
  } else if (name === "teeth" || name === "segments" || name === "turnsegments") {
@@ -4646,8 +4609,8 @@ function parseHelicalGearModelParams(raw) {
4646
4609
  } else if (name === "right" || name === "left") {
4647
4610
  if (value)
4648
4611
  throw new Error(`Helical flag "${name}" does not accept a value`);
4649
- property = "handedness";
4650
- parsed = name;
4612
+ property = "leftHanded";
4613
+ parsed = name === "left";
4651
4614
  } else throw new Error(`Unknown helical gear token "${token}"`);
4652
4615
  if (property in props)
4653
4616
  throw new Error(
@@ -4800,7 +4763,8 @@ var nemaMotorDimensions = {
4800
4763
  pilotLength: 1.5,
4801
4764
  shaftDiameter: 4,
4802
4765
  shaftLength: 15,
4803
- shaftShape: "round",
4766
+ roundShaft: true,
4767
+ dShaft: false,
4804
4768
  shaftFlatDepth: 0.5,
4805
4769
  shaftFlatLength: 10,
4806
4770
  shaftFlatAngle: 0,
@@ -4822,7 +4786,8 @@ var nemaMotorDimensions = {
4822
4786
  pilotLength: 2,
4823
4787
  shaftDiameter: 5,
4824
4788
  shaftLength: 24,
4825
- shaftShape: "d",
4789
+ roundShaft: false,
4790
+ dShaft: true,
4826
4791
  shaftFlatDepth: 0.5,
4827
4792
  shaftFlatLength: 15,
4828
4793
  shaftFlatAngle: 0,
@@ -4844,7 +4809,8 @@ var nemaMotorDimensions = {
4844
4809
  pilotLength: 1.6,
4845
4810
  shaftDiameter: 6.35,
4846
4811
  shaftLength: 20.6,
4847
- shaftShape: "d",
4812
+ roundShaft: false,
4813
+ dShaft: true,
4848
4814
  shaftFlatDepth: 0.5,
4849
4815
  shaftFlatLength: 15,
4850
4816
  shaftFlatAngle: 0,
@@ -4869,7 +4835,8 @@ var nemaMotorDimensions = {
4869
4835
  pilotLength: 1.6,
4870
4836
  shaftDiameter: 14,
4871
4837
  shaftLength: 32,
4872
- shaftShape: "round",
4838
+ roundShaft: true,
4839
+ dShaft: false,
4873
4840
  shaftFlatDepth: 0.5,
4874
4841
  shaftFlatLength: 15,
4875
4842
  shaftFlatAngle: 0,
@@ -4882,13 +4849,18 @@ var nemaMotorDimensions = {
4882
4849
  var shape3 = {
4883
4850
  nemaSize: nemaSizeSchema,
4884
4851
  /** Rear cap at Z=-bodyLength: bare, open bores or installed cap screws. */
4885
- backFace: external_exports.enum(["plain", "holes", "screws"]).optional(),
4852
+ backFacePlain: external_exports.boolean().optional(),
4853
+ backFaceHoles: external_exports.boolean().optional(),
4854
+ backFaceScrews: external_exports.boolean().optional(),
4886
4855
  backFaceHoleSpacing: positiveModelLengthSchema.optional(),
4887
4856
  backFaceHoleDiameter: positiveModelLengthSchema.optional(),
4888
4857
  backFaceHoleDepth: positiveModelLengthSchema.optional(),
4889
4858
  backFaceScrewSize: metricBoltSizeSchema.optional(),
4890
4859
  /** Visual termination; the wireside reference exists even when hidden. */
4891
- wireConnection: external_exports.union([external_exports.enum(["none", "stubs"]), jstMotorWireConnectionSchema]).optional(),
4860
+ noWires: external_exports.boolean().optional(),
4861
+ wireStubs: external_exports.boolean().optional(),
4862
+ /** JST catalog designation, mutually exclusive with the visible-wire flags. */
4863
+ wireConnection: jstMotorWireConnectionSchema.optional(),
4892
4864
  /** Counterclockwise angle about local +Z; 0 is the +X side. */
4893
4865
  wireSideAngle: external_exports.number().finite().optional(),
4894
4866
  wireLength: positiveModelLengthSchema.optional(),
@@ -4905,7 +4877,8 @@ var shape3 = {
4905
4877
  /** Distance from mounting face Z=0 to shaft tip, including pilot height. */
4906
4878
  shaftLength: positiveModelLengthSchema.optional(),
4907
4879
  shaftDiameter: positiveModelLengthSchema.optional(),
4908
- shaftShape: external_exports.enum(["round", "d"]).optional(),
4880
+ roundShaft: external_exports.boolean().optional(),
4881
+ dShaft: external_exports.boolean().optional(),
4909
4882
  /** Radial material removed from the +X side before rotation. */
4910
4883
  shaftFlatDepth: nonnegativeModelLengthSchema.optional(),
4911
4884
  /** Flat extends back from the tip; leaves a round shoulder above the pilot. */
@@ -4918,20 +4891,54 @@ var shape3 = {
4918
4891
  bodyCornerChamfer: nonnegativeModelLengthSchema.optional(),
4919
4892
  /** Rear outline is independent of the front mounting flange. */
4920
4893
  rearCornerChamfer: nonnegativeModelLengthSchema.optional(),
4921
- cornerProfile: external_exports.enum(["chamfered", "stepped"]).optional()
4894
+ chamfered: external_exports.boolean().optional(),
4895
+ stepped: external_exports.boolean().optional()
4922
4896
  };
4923
- var resolve = (p) => {
4897
+ var resolve = (p, ctx) => {
4898
+ const select = (flags11, fallback) => {
4899
+ const selected = flags11.filter((flag) => p[flag] === true);
4900
+ const specified = flags11.some((flag) => p[flag] !== void 0);
4901
+ if (selected.length > 1 || specified && selected.length === 0)
4902
+ ctx.addIssue({
4903
+ code: "custom",
4904
+ message: `Select exactly one of ${flags11.join(", ")}`
4905
+ });
4906
+ return selected[0] ?? fallback;
4907
+ };
4908
+ const back = select(
4909
+ ["backFacePlain", "backFaceHoles", "backFaceScrews"],
4910
+ p.nemaSize === 34 ? "backFacePlain" : "backFaceScrews"
4911
+ );
4912
+ const shaft = select(
4913
+ ["roundShaft", "dShaft"],
4914
+ nemaMotorDimensions[p.nemaSize].roundShaft ? "roundShaft" : "dShaft"
4915
+ );
4916
+ const corner = select(
4917
+ ["chamfered", "stepped"],
4918
+ p.nemaSize === 34 ? "stepped" : "chamfered"
4919
+ );
4920
+ const wireSpecified = p.noWires !== void 0 || p.wireStubs !== void 0 || p.wireConnection !== void 0;
4921
+ const wireSelections = Number(p.noWires === true) + Number(p.wireStubs === true) + Number(p.wireConnection !== void 0);
4922
+ if (wireSelections > 1 || wireSpecified && wireSelections === 0)
4923
+ ctx.addIssue({
4924
+ code: "custom",
4925
+ message: "Select exactly one of noWires, wireStubs or a JST wireConnection"
4926
+ });
4924
4927
  const d = nemaMotorDimensions[p.nemaSize];
4925
4928
  const backFaceScrewSize = p.backFaceScrewSize ?? d.backFaceScrewSize;
4926
4929
  const screw = hexSocketBoltDimensions[backFaceScrewSize];
4927
4930
  return {
4928
4931
  nemaSize: p.nemaSize,
4929
- wireConnection: p.wireConnection ?? "stubs",
4932
+ noWires: p.noWires === true,
4933
+ wireStubs: p.wireStubs === true || !wireSpecified,
4934
+ ...p.wireConnection !== void 0 ? { wireConnection: p.wireConnection } : {},
4930
4935
  wireSideAngle: ((p.wireSideAngle ?? (p.nemaSize === 34 ? 90 : 0)) % 360 + 360) % 360,
4931
4936
  wireLength: p.wireLength ?? (p.nemaSize === 34 ? 25 : 6),
4932
4937
  wireDiameter: p.wireDiameter ?? (p.nemaSize === 34 ? 2 : 1.2),
4933
4938
  wireCount: p.wireCount ?? 4,
4934
- backFace: p.backFace ?? (p.nemaSize === 34 ? "plain" : "screws"),
4939
+ backFacePlain: back === "backFacePlain",
4940
+ backFaceHoles: back === "backFaceHoles",
4941
+ backFaceScrews: back === "backFaceScrews",
4935
4942
  backFaceHoleSpacing: p.backFaceHoleSpacing ?? ("backFaceHoleSpacing" in d ? d.backFaceHoleSpacing : p.mountingHoleSpacing ?? d.mountingHoleSpacing),
4936
4943
  backFaceHoleDiameter: p.backFaceHoleDiameter ?? screw.diameter,
4937
4944
  backFaceHoleDepth: p.backFaceHoleDepth ?? d.backFaceHoleDepth,
@@ -4946,7 +4953,8 @@ var resolve = (p) => {
4946
4953
  pilotLength: p.pilotLength ?? d.pilotLength,
4947
4954
  shaftDiameter: p.shaftDiameter ?? d.shaftDiameter,
4948
4955
  shaftLength: p.shaftLength ?? d.shaftLength,
4949
- shaftShape: p.shaftShape ?? d.shaftShape,
4956
+ roundShaft: shaft === "roundShaft",
4957
+ dShaft: shaft === "dShaft",
4950
4958
  shaftFlatDepth: p.shaftFlatDepth ?? d.shaftFlatDepth,
4951
4959
  shaftFlatLength: p.shaftFlatLength ?? d.shaftFlatLength,
4952
4960
  shaftFlatAngle: p.shaftFlatAngle ?? d.shaftFlatAngle,
@@ -4954,7 +4962,8 @@ var resolve = (p) => {
4954
4962
  rearCapLength: p.rearCapLength ?? d.rearCapLength,
4955
4963
  faceCornerChamfer: p.faceCornerChamfer ?? d.faceCornerChamfer,
4956
4964
  bodyCornerChamfer: p.bodyCornerChamfer ?? d.bodyCornerChamfer,
4957
- ...p.nemaSize === 34 || p.cornerProfile !== void 0 ? { cornerProfile: p.cornerProfile ?? "stepped" } : {},
4965
+ chamfered: corner === "chamfered",
4966
+ stepped: corner === "stepped",
4958
4967
  ..."rearCornerChamfer" in d || p.rearCornerChamfer !== void 0 ? {
4959
4968
  rearCornerChamfer: p.rearCornerChamfer ?? ("rearCornerChamfer" in d ? d.rearCornerChamfer : p.faceCornerChamfer ?? d.faceCornerChamfer)
4960
4969
  } : {}
@@ -4962,27 +4971,27 @@ var resolve = (p) => {
4962
4971
  };
4963
4972
  var validate3 = (p, ctx) => {
4964
4973
  const issue = (message) => ctx.addIssue({ code: "custom", message });
4965
- const rearChamfer = p.rearCornerChamfer ?? (p.backFace === "plain" && p.mountingHoleThrough ? p.bodyCornerChamfer : p.faceCornerChamfer);
4966
- const rearEdge = p.cornerProfile === "stepped" ? rearChamfer / Math.SQRT2 : rearChamfer;
4967
- if (p.backFace !== "plain") {
4974
+ const rearChamfer = p.rearCornerChamfer ?? (p.backFacePlain && p.mountingHoleThrough ? p.bodyCornerChamfer : p.faceCornerChamfer);
4975
+ const rearEdge = p.stepped ? rearChamfer / Math.SQRT2 : rearChamfer;
4976
+ if (!p.backFacePlain) {
4968
4977
  const screw = hexSocketBoltDimensions[p.backFaceScrewSize];
4969
- const radius = (p.backFace === "screws" ? Math.max(p.backFaceHoleDiameter, screw.headDiameter) : p.backFaceHoleDiameter) / 2;
4978
+ const radius = (p.backFaceScrews ? Math.max(p.backFaceHoleDiameter, screw.headDiameter) : p.backFaceHoleDiameter) / 2;
4970
4979
  if (p.backFaceHoleSpacing <= 2 * radius)
4971
4980
  issue("Rear holes and screw heads must not overlap each other");
4972
- 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))
4981
+ 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))
4973
4982
  issue("Rear holes and screw heads must fit entirely inside the rear face");
4974
4983
  if (p.backFaceHoleDepth >= p.rearCapLength)
4975
4984
  issue("Rear hole depth must be less than the rear cap length");
4976
- if (p.backFace === "screws" && p.backFaceHoleDiameter < screw.diameter)
4985
+ if (p.backFaceScrews && p.backFaceHoleDiameter < screw.diameter)
4977
4986
  issue("Rear holes must accommodate the screw diameter");
4978
4987
  }
4979
- if (p.wireConnection === "stubs") {
4988
+ if (p.wireStubs) {
4980
4989
  if (p.wireDiameter * p.wireCount * 1.5 > p.bodyWidth - 2 * rearEdge)
4981
4990
  issue("Wire bundle must fit on the cap side");
4982
4991
  if (p.wireDiameter >= p.rearCapLength)
4983
4992
  issue("Wire diameter must fit within the rear cap");
4984
4993
  }
4985
- const connector = getJstMotorConnector(p.wireConnection);
4994
+ const connector = p.wireConnection === void 0 ? void 0 : getJstMotorConnector(p.wireConnection);
4986
4995
  if (connector && p.bodyWidth - 2 * rearEdge < connector.bodyWidth)
4987
4996
  issue("JST header must fit on the motor side");
4988
4997
  const r = p.mountingHoleDiameter / 2;
@@ -5000,17 +5009,17 @@ var validate3 = (p, ctx) => {
5000
5009
  issue("Mounting holes must clear the pilot");
5001
5010
  if (!p.mountingHoleThrough && p.mountingHoleDepth >= p.frontCapLength)
5002
5011
  issue("Blind mounting hole depth must be less than the front cap length");
5003
- 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))
5012
+ 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))
5004
5013
  issue("Body must clear through front mounting holes");
5005
5014
  if (p.shaftLength <= p.pilotLength)
5006
5015
  issue("Shaft tip must extend beyond the pilot");
5007
- if (p.shaftShape === "d" && (p.shaftFlatDepth <= 0 || p.shaftFlatDepth >= p.shaftDiameter / 2 || p.shaftFlatLength <= 0 || p.shaftFlatLength > p.shaftLength - p.pilotLength))
5016
+ if (p.dShaft && (p.shaftFlatDepth <= 0 || p.shaftFlatDepth >= p.shaftDiameter / 2 || p.shaftFlatLength <= 0 || p.shaftFlatLength > p.shaftLength - p.pilotLength))
5008
5017
  issue(
5009
5018
  "D flat must have positive depth less than the shaft radius and fit above the pilot"
5010
5019
  );
5011
5020
  };
5012
5021
  var nemaMotorModelPropsSchema = external_exports.object(shape3).strict().transform(resolve).superRefine(validate3);
5013
- var nemaMotorModelDefinitionSchema = external_exports.object({ fn: external_exports.literal("nema"), ...shape3 }).strict().transform(({ fn, ...props }) => ({ fn, ...resolve(props) })).superRefine(validate3);
5022
+ var nemaMotorModelDefinitionSchema = external_exports.object({ fn: external_exports.literal("nema"), ...shape3 }).strict().transform(({ fn, ...props }, ctx) => ({ fn, ...resolve(props, ctx) })).superRefine(validate3);
5014
5023
  var lengths2 = {
5015
5024
  wirelength: "wireLength",
5016
5025
  wirediameter: "wireDiameter",
@@ -5036,6 +5045,19 @@ var lengths2 = {
5036
5045
  bodychamfer: "bodyCornerChamfer",
5037
5046
  rearchamfer: "rearCornerChamfer"
5038
5047
  };
5048
+ var flags = {
5049
+ backfaceplain: "backFacePlain",
5050
+ plainbackface: "backFacePlain",
5051
+ backfaceholes: "backFaceHoles",
5052
+ backfacescrews: "backFaceScrews",
5053
+ round: "roundShaft",
5054
+ roundshaft: "roundShaft",
5055
+ dshaft: "dShaft",
5056
+ chamfered: "chamfered",
5057
+ stepped: "stepped",
5058
+ nowires: "noWires",
5059
+ wirestubs: "wireStubs"
5060
+ };
5039
5061
  function parseNemaMotorModelParams(raw) {
5040
5062
  const tokens = normalizeNemaMotorModelString(raw.string).split("_");
5041
5063
  const match = tokens[0]?.match(/^nema(8|17|23|34)$/i);
@@ -5052,20 +5074,15 @@ function parseNemaMotorModelParams(raw) {
5052
5074
  if (name in lengths2) {
5053
5075
  property = lengths2[name];
5054
5076
  parsed = value;
5055
- } else if (["backfaceholes", "backfacescrews", "plainbackface"].includes(name)) {
5077
+ } else if (name in flags) {
5056
5078
  if (value) throw new Error(`NEMA flag "${name}" does not accept a value`);
5057
- property = "backFace";
5058
- parsed = name === "backfaceholes" ? "holes" : name === "backfacescrews" ? "screws" : "plain";
5059
- } else if (["wirestubs", "nowires", "jstph", "jstsh"].includes(name)) {
5060
- const isJst = name === "jstph" || name === "jstsh";
5061
- if (isJst && !/^[1-9][0-9]*$/.test(value) || !isJst && value)
5079
+ property = flags[name];
5080
+ parsed = true;
5081
+ } else if (name === "jstph" || name === "jstsh") {
5082
+ if (!/^[1-9][0-9]*$/.test(value))
5062
5083
  throw new Error(`Invalid wire connection token "${token}"`);
5063
5084
  property = "wireConnection";
5064
- parsed = isJst ? `jst-${name.slice(3)}-${value}` : name === "nowires" ? "none" : "stubs";
5065
- } else if (name === "stepped" || name === "chamfered") {
5066
- if (value) throw new Error(`NEMA flag "${name}" does not accept a value`);
5067
- property = "cornerProfile";
5068
- parsed = name;
5085
+ parsed = `jst-${name.slice(3)}-${value}`;
5069
5086
  } else if (name === "wirecount") {
5070
5087
  property = "wireCount";
5071
5088
  if (!/^\d+$/.test(value)) throw new Error("wirecount requires an integer");
@@ -5078,10 +5095,10 @@ function parseNemaMotorModelParams(raw) {
5078
5095
  if (!/^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:deg)?$/i.test(value))
5079
5096
  throw new Error(`${name} requires a numeric angle in degrees`);
5080
5097
  parsed = Number(value.replace(/deg$/i, ""));
5081
- } else if (["round", "dshaft", "throughholes", "blindholes"].includes(name)) {
5098
+ } else if (name === "throughholes" || name === "blindholes") {
5082
5099
  if (value) throw new Error(`NEMA flag "${name}" does not accept a value`);
5083
- property = name === "round" || name === "dshaft" ? "shaftShape" : "mountingHoleThrough";
5084
- parsed = name === "round" ? "round" : name === "dshaft" ? "d" : name === "throughholes";
5100
+ property = "mountingHoleThrough";
5101
+ parsed = name === "throughholes";
5085
5102
  } else throw new Error(`Unknown NEMA motor token "${token}"`);
5086
5103
  if (property in props)
5087
5104
  throw new Error(`NEMA property "${property}" is set more than once`);
@@ -5104,22 +5121,26 @@ var holePosition = {
5104
5121
  u: modelLengthSchema,
5105
5122
  v: modelLengthSchema
5106
5123
  };
5107
- var sheetMetalHoleSchema = external_exports.discriminatedUnion("shape", [
5124
+ var sheetMetalHoleSchema = external_exports.union([
5108
5125
  external_exports.object({
5109
5126
  ...holePosition,
5110
- shape: external_exports.literal("round"),
5127
+ round: external_exports.literal(true),
5128
+ slot: external_exports.literal(false).default(false),
5111
5129
  diameter: positiveModelLengthSchema
5112
5130
  }).strict(),
5113
5131
  external_exports.object({
5114
5132
  ...holePosition,
5115
- shape: external_exports.literal("slot"),
5133
+ round: external_exports.literal(false).default(false),
5134
+ slot: external_exports.literal(true),
5116
5135
  length: positiveModelLengthSchema,
5117
5136
  width: positiveModelLengthSchema,
5118
5137
  axis: external_exports.enum(["u", "v"]).default("v")
5119
5138
  }).strict()
5120
5139
  ]);
5121
5140
  var sheetMetalShape = {
5122
- profile: external_exports.enum(["plate", "angle", "channel"]).default("plate"),
5141
+ plate: external_exports.boolean().default(false),
5142
+ angle: external_exports.boolean().default(false),
5143
+ channel: external_exports.boolean().default(false),
5123
5144
  width: positiveModelLengthSchema,
5124
5145
  /** Straight base length between bend tangencies, not overall width. */
5125
5146
  baseLength: positiveModelLengthSchema,
@@ -5129,9 +5150,19 @@ var sheetMetalShape = {
5129
5150
  insideBendRadius: positiveModelLengthSchema.default(1),
5130
5151
  holes: external_exports.array(sheetMetalHoleSchema).max(100).default([])
5131
5152
  };
5132
- var sheetMetalModelPropsSchema = external_exports.object(sheetMetalShape).strict();
5133
- var sheetMetalModelDefinitionSchema = external_exports.object({ fn: external_exports.literal("sheetmetal"), ...sheetMetalShape }).strict();
5134
- function parseSheetMetalFeature(feature, profile6) {
5153
+ function validateFlags(props, context) {
5154
+ if ([props.plate, props.angle, props.channel].filter(Boolean).length > 1)
5155
+ context.addIssue({
5156
+ code: "custom",
5157
+ message: "Specify at most one of plate, angle, or channel"
5158
+ });
5159
+ }
5160
+ function resolveFlags(props) {
5161
+ return { ...props, plate: props.plate || !(props.angle || props.channel) };
5162
+ }
5163
+ var sheetMetalModelPropsSchema = external_exports.object(sheetMetalShape).strict().superRefine(validateFlags).transform(resolveFlags);
5164
+ var sheetMetalModelDefinitionSchema = external_exports.object({ fn: external_exports.literal("sheetmetal"), ...sheetMetalShape }).strict().superRefine(validateFlags).transform((props) => ({ fn: props.fn, ...resolveFlags(props) }));
5165
+ function parseSheetMetalFeature(feature, flags11) {
5135
5166
  const match = feature.match(/^(hole|slot)[1-9]\d*\(([^()]+)\)$/);
5136
5167
  if (!match) throw new Error(`Invalid sheet metal feature "${feature}"`);
5137
5168
  const kind = match[1];
@@ -5164,8 +5195,8 @@ function parseSheetMetalFeature(feature, profile6) {
5164
5195
  if (faces.length !== 1)
5165
5196
  throw new Error(`Specify exactly one face in ${feature}`);
5166
5197
  const face2 = faces[0];
5167
- if (face2 === "angledface" && profile6 !== "angle" || ["leftface", "rightface"].includes(face2) && profile6 !== "channel")
5168
- throw new Error(`No ${face2} on ${profile6}`);
5198
+ if (face2 === "angledface" && !flags11.angle || ["leftface", "rightface"].includes(face2) && !flags11.channel)
5199
+ throw new Error(`No ${face2} on the selected sheet metal form`);
5169
5200
  for (const [a, b] of [
5170
5201
  ["leftofcenter", "rightofcenter"],
5171
5202
  ["abovecenter", "belowcenter"],
@@ -5189,7 +5220,7 @@ function parseSheetMetalFeature(feature, profile6) {
5189
5220
  throw new Error(`Hole requires r or d in ${feature}`);
5190
5221
  return sheetMetalHoleSchema.parse({
5191
5222
  ...position,
5192
- shape: "round",
5223
+ round: true,
5193
5224
  diameter: "r" in values ? 2 * distance2("r") : distance2("d")
5194
5225
  });
5195
5226
  }
@@ -5199,7 +5230,7 @@ function parseSheetMetalFeature(feature, profile6) {
5199
5230
  if (length32 < width10) throw new Error("Slot length must be at least its width");
5200
5231
  return sheetMetalHoleSchema.parse({
5201
5232
  ...position,
5202
- shape: "slot",
5233
+ slot: true,
5203
5234
  length: length32,
5204
5235
  width: width10,
5205
5236
  axis: panel === "base" === !("vertical" in values) ? "u" : "v"
@@ -5227,8 +5258,9 @@ function parseSheetMetalModelParams(raw) {
5227
5258
  continue;
5228
5259
  }
5229
5260
  if (["plate", "angle", "channel"].includes(token)) {
5230
- if (props.profile) throw new Error("Duplicate sheet metal profile");
5231
- props.profile = token;
5261
+ if (["plate", "angle", "channel"].some((flag) => flag in props))
5262
+ throw new Error("Duplicate sheet metal form flag");
5263
+ props[token] = true;
5232
5264
  continue;
5233
5265
  }
5234
5266
  const key = lengths3[token[0]];
@@ -5242,7 +5274,7 @@ function parseSheetMetalModelParams(raw) {
5242
5274
  ...props
5243
5275
  });
5244
5276
  definition.holes = features.map(
5245
- (feature) => parseSheetMetalFeature(feature, definition.profile)
5277
+ (feature) => parseSheetMetalFeature(feature, definition)
5246
5278
  );
5247
5279
  return definition;
5248
5280
  }
@@ -5254,14 +5286,6 @@ var model4 = defineModel({
5254
5286
  function register4(registry2) {
5255
5287
  registry2.register(model4);
5256
5288
  }
5257
- var flexScreenOrientationSchema = external_exports.enum([
5258
- "sitsFlat",
5259
- "sitsFlatBelowBoard",
5260
- "foldedToFaceAboveBoard",
5261
- "foldedToFaceBelowBoard",
5262
- "foldedToRightAngleAboveBoard",
5263
- "foldedToRightAngleBelowBoard"
5264
- ]);
5265
5289
  var positiveFiniteNumberSchema = external_exports.number().finite().positive();
5266
5290
  var aspectRatioStringSchema = external_exports.string().refine((value) => {
5267
5291
  const parts = value.split(":");
@@ -5303,7 +5327,6 @@ var flexScreenModelPropsShape = {
5303
5327
  aspectRatio: flexScreenAspectRatioSchema.optional(),
5304
5328
  ratio: flexScreenAspectRatioSchema.optional(),
5305
5329
  defaultDiagonal: positiveModelLengthSchema.optional(),
5306
- orientation: flexScreenOrientationSchema.optional(),
5307
5330
  sitsFlat: external_exports.boolean().optional(),
5308
5331
  sitsFlatBelowBoard: external_exports.boolean().optional(),
5309
5332
  foldedToFaceAboveBoard: external_exports.boolean().optional(),
@@ -5371,7 +5394,42 @@ var addOrientationShortcutIssue = (props, addIssue) => {
5371
5394
  const selectedShortcuts = orientationShortcutKeys.filter(
5372
5395
  (key) => props[key] === true
5373
5396
  );
5374
- if (selectedShortcuts.length > 1) addIssue(selectedShortcuts[1]);
5397
+ if (selectedShortcuts.length > 1) {
5398
+ addIssue(
5399
+ selectedShortcuts[1],
5400
+ "Only one FlexScreen orientation shortcut can be true"
5401
+ );
5402
+ } else if (selectedShortcuts.length === 0 && orientationShortcutKeys.some((key) => props[key] !== void 0)) {
5403
+ addIssue(
5404
+ "sitsFlat",
5405
+ "A FlexScreen orientation flag must be true when placement flags are supplied"
5406
+ );
5407
+ }
5408
+ };
5409
+ var normalizeOrientationFlags = (props) => {
5410
+ const {
5411
+ sitsFlat,
5412
+ sitsFlatBelowBoard,
5413
+ foldedToFaceAboveBoard,
5414
+ foldedToFaceBelowBoard,
5415
+ foldedToRightAngleAboveBoard,
5416
+ foldedToRightAngleBelowBoard,
5417
+ foldsAboveBoard,
5418
+ foldsBelowBoard,
5419
+ ...rest
5420
+ } = props;
5421
+ const above = foldedToFaceAboveBoard === true || foldsAboveBoard === true;
5422
+ const below = foldedToFaceBelowBoard === true || foldsBelowBoard === true;
5423
+ const selected = sitsFlatBelowBoard === true || above || below || foldedToRightAngleAboveBoard === true || foldedToRightAngleBelowBoard === true;
5424
+ return {
5425
+ ...rest,
5426
+ sitsFlat: sitsFlat === true || !selected,
5427
+ sitsFlatBelowBoard: sitsFlatBelowBoard === true,
5428
+ foldedToFaceAboveBoard: above,
5429
+ foldedToFaceBelowBoard: below,
5430
+ foldedToRightAngleAboveBoard: foldedToRightAngleAboveBoard === true,
5431
+ foldedToRightAngleBelowBoard: foldedToRightAngleBelowBoard === true
5432
+ };
5375
5433
  };
5376
5434
  var validateTailLengths = (props, context) => {
5377
5435
  if (props.flexCableLength === void 0) return;
@@ -5392,27 +5450,27 @@ var validateTailLengths = (props, context) => {
5392
5450
  };
5393
5451
  var flexScreenModelPropsSchema = external_exports.object(flexScreenModelPropsShape).strict().superRefine((props, context) => {
5394
5452
  validateTailLengths(props, context);
5395
- addOrientationShortcutIssue(props, (path) => {
5453
+ addOrientationShortcutIssue(props, (path, message) => {
5396
5454
  context.addIssue({
5397
5455
  code: "custom",
5398
- message: "Only one FlexScreen orientation shortcut can be true",
5456
+ message,
5399
5457
  path: [path]
5400
5458
  });
5401
5459
  });
5402
- });
5460
+ }).transform(normalizeOrientationFlags);
5403
5461
  var flexScreenModelDefinitionSchema = external_exports.object({
5404
5462
  fn: external_exports.literal("flexscreen"),
5405
5463
  ...flexScreenModelPropsShape
5406
5464
  }).strict().superRefine((model552, context) => {
5407
5465
  validateTailLengths(model552, context);
5408
- addOrientationShortcutIssue(model552, (path) => {
5466
+ addOrientationShortcutIssue(model552, (path, message) => {
5409
5467
  context.addIssue({
5410
5468
  code: "custom",
5411
- message: "Only one FlexScreen orientation shortcut can be true",
5469
+ message,
5412
5470
  path: [path]
5413
5471
  });
5414
5472
  });
5415
- });
5473
+ }).transform(normalizeOrientationFlags);
5416
5474
  var orientationTokens = {
5417
5475
  sitsflat: "sitsFlat",
5418
5476
  sitsflatbelow: "sitsFlatBelowBoard",
@@ -5538,6 +5596,23 @@ var parseFlexScreenModelParams = (rawParams) => {
5538
5596
  }
5539
5597
  const props = {};
5540
5598
  let orientation;
5599
+ for (const part of splitModelStringTokens(rawParams.string).slice(1)) {
5600
+ const match = part.match(/^([a-zA-Z]+)(.*)$/);
5601
+ if (!match) continue;
5602
+ const token = match[1].toLowerCase();
5603
+ const selected = orientationTokens[token];
5604
+ if (!selected) continue;
5605
+ if (match[2] !== "") {
5606
+ throw new Error(`FlexScreen token "${token}" does not accept a value`);
5607
+ }
5608
+ if (orientation !== void 0) {
5609
+ throw new Error(
5610
+ orientation === selected ? `Duplicate FlexScreen orientation flag "${token}"` : "A FlexScreen model string can only set one orientation"
5611
+ );
5612
+ }
5613
+ orientation = selected;
5614
+ props[selected] = true;
5615
+ }
5541
5616
  let relativeDistance;
5542
5617
  for (const [token, value] of Object.entries(rawParams)) {
5543
5618
  if (token === "fn" || token === "string" || token === "flexscreen") {
@@ -5546,13 +5621,6 @@ var parseFlexScreenModelParams = (rawParams) => {
5546
5621
  const tokenOrientation = orientationTokens[token];
5547
5622
  if (tokenOrientation) {
5548
5623
  assertBareToken(value, token);
5549
- if (orientation && orientation !== tokenOrientation) {
5550
- throw new Error(
5551
- "A FlexScreen model string can only set one orientation"
5552
- );
5553
- }
5554
- orientation = tokenOrientation;
5555
- props.orientation = tokenOrientation;
5556
5624
  continue;
5557
5625
  }
5558
5626
  if (token in booleanTokens) {
@@ -5728,7 +5796,7 @@ var shape4 = {
5728
5796
  /** Additional radial dedendum beyond one module, in millimeters. */
5729
5797
  clearance: nonnegativeGearLengthSchema.default(0.25),
5730
5798
  boreDiameter: nonnegativeGearLengthSchema.default(0),
5731
- handedness: external_exports.enum(["right", "left"]).default("right"),
5799
+ leftHanded: external_exports.boolean().default(false),
5732
5800
  /** Counterclockwise degrees about +Z, beginning at the Z=0 end. */
5733
5801
  phase: external_exports.number().finite().default(0),
5734
5802
  radialSegments: external_exports.number().int().min(24).max(256).refine(
@@ -5798,7 +5866,7 @@ function parseWormGearModelParams(raw) {
5798
5866
  const [name, value] = parseGearToken(token);
5799
5867
  let property;
5800
5868
  let parsed;
5801
- if (name in lengths5) {
5869
+ if (Object.hasOwn(lengths5, name)) {
5802
5870
  property = lengths5[name];
5803
5871
  parsed = value;
5804
5872
  } else if (["starts", "segments", "turnsegments"].includes(name)) {
@@ -5809,8 +5877,8 @@ function parseWormGearModelParams(raw) {
5809
5877
  parsed = parseGearAngle(value, property);
5810
5878
  } else if (name === "right" || name === "left") {
5811
5879
  if (value) throw new Error(`Worm flag "${name}" does not accept a value`);
5812
- property = "handedness";
5813
- parsed = name;
5880
+ property = "leftHanded";
5881
+ parsed = name === "left";
5814
5882
  } else throw new Error(`Unknown worm gear token "${token}"`);
5815
5883
  if (property in props)
5816
5884
  throw new Error(`Worm gear property "${property}" is set more than once`);
@@ -6129,7 +6197,7 @@ var lengths7 = {
6129
6197
  w: "width",
6130
6198
  width: "width"
6131
6199
  };
6132
- var flags = {
6200
+ var flags2 = {
6133
6201
  open: "bothSidesOpen",
6134
6202
  bothsidesopen: "bothSidesOpen",
6135
6203
  shielded: "bothSidesShielded",
@@ -6163,8 +6231,8 @@ function parseBallBearingModelParams(raw) {
6163
6231
  const scopes = /* @__PURE__ */ new Set();
6164
6232
  for (const token of tokens.slice(1)) {
6165
6233
  const lower = token.toLowerCase();
6166
- if (Object.hasOwn(flags, lower)) {
6167
- const property2 = flags[lower];
6234
+ if (Object.hasOwn(flags2, lower)) {
6235
+ const property2 = flags2[lower];
6168
6236
  const scope = property2.startsWith("both") ? "both" : property2.startsWith("top") ? "top" : "bottom";
6169
6237
  if (scopes.has(scope))
6170
6238
  throw new Error(
@@ -6358,7 +6426,7 @@ function parseBallTransferUnitModelParams(raw) {
6358
6426
  const lower = token.toLowerCase();
6359
6427
  let property;
6360
6428
  let value;
6361
- if (lower === "face3hole" || lower === "mount(face3hole)") {
6429
+ if (lower === "face3hole") {
6362
6430
  property = "faceThreeHole";
6363
6431
  value = true;
6364
6432
  } else {
@@ -6384,12 +6452,6 @@ var model12 = defineModel({
6384
6452
  function register12(registry2) {
6385
6453
  registry2.register(model12);
6386
6454
  }
6387
- var stringFlags2 = {
6388
- hexsocket: "drive(hexsocket)",
6389
- fullthread: "thread(full)",
6390
- righthanded: "threadhand(right)"
6391
- };
6392
- var omittedStringFlags2 = ["righthanded"];
6393
6455
  var buttonScrewDimensions = {
6394
6456
  M3: {
6395
6457
  diameter: 3,
@@ -6450,10 +6512,10 @@ var shape9 = {
6450
6512
  metricSize: buttonScrewMetricSizeSchema,
6451
6513
  /** Under-head length; this family supports short fully threaded screws only. */
6452
6514
  length: length4,
6453
- drive: external_exports.literal("hexsocket").default("hexsocket"),
6454
- thread: external_exports.literal("full").default("full"),
6515
+ hexSocket: external_exports.literal(true).default(true),
6516
+ fullThread: external_exports.literal(true).default(true),
6455
6517
  threadPitch: length4.optional(),
6456
- threadHand: external_exports.literal("right").default("right"),
6518
+ leftHanded: external_exports.literal(false).default(false),
6457
6519
  threadClass: external_exports.literal("6g").default("6g"),
6458
6520
  showThreads: external_exports.boolean().default(true)
6459
6521
  };
@@ -6509,9 +6571,7 @@ function getButtonScrewDimensions(input) {
6509
6571
  };
6510
6572
  }
6511
6573
  function parseButtonScrewModelParams(raw) {
6512
- const tokens = splitModelStringTokens(
6513
- expandModelStringFlags(raw.string, stringFlags2)
6514
- );
6574
+ const tokens = splitModelStringTokens(raw.string);
6515
6575
  if (raw.fn !== "buttonscrew" || tokens[0]?.toLowerCase() !== "buttonscrew")
6516
6576
  throw new Error("Expected buttonscrew without an inline argument");
6517
6577
  const props = { fn: "buttonscrew" };
@@ -6520,12 +6580,15 @@ function parseButtonScrewModelParams(raw) {
6520
6580
  length: "length",
6521
6581
  threadpitch: "threadPitch"
6522
6582
  };
6523
- const selectors7 = {
6524
- drive: "drive",
6525
- thread: "thread",
6526
- threadhand: "threadHand",
6583
+ const selectors5 = {
6527
6584
  threadclass: "threadClass"
6528
6585
  };
6586
+ const booleanFlags4 = {
6587
+ hexsocket: { property: "hexSocket", value: true },
6588
+ fullthread: { property: "fullThread", value: true },
6589
+ righthanded: { property: "leftHanded", value: false },
6590
+ lefthanded: { property: "leftHanded", value: true }
6591
+ };
6529
6592
  for (const token of tokens.slice(1)) {
6530
6593
  if (token.toLowerCase() === "iso7380-1") {
6531
6594
  if ("iso73801" in props)
@@ -6539,12 +6602,17 @@ function parseButtonScrewModelParams(raw) {
6539
6602
  const value = match[2];
6540
6603
  let property;
6541
6604
  let parsed = value;
6542
- if (name === "m") {
6605
+ if (Object.hasOwn(booleanFlags4, name)) {
6606
+ if (value) throw new Error(`Flag "${name}" does not accept a value`);
6607
+ property = booleanFlags4[name].property;
6608
+ parsed = booleanFlags4[name].value;
6609
+ } else if (name === "m") {
6543
6610
  property = "metricSize";
6544
6611
  parsed = `M${value}`;
6545
- } else if (name in lengths25) property = lengths25[name];
6546
- else if (name in selectors7) {
6547
- property = selectors7[name];
6612
+ } else if (Object.hasOwn(lengths25, name))
6613
+ property = lengths25[name];
6614
+ else if (Object.hasOwn(selectors5, name)) {
6615
+ property = selectors5[name];
6548
6616
  if (!/^\([^()]+\)$/.test(value))
6549
6617
  throw new Error(`Expected a parenthesized ${name}`);
6550
6618
  parsed = value.slice(1, -1).toLowerCase();
@@ -6562,21 +6630,11 @@ function parseButtonScrewModelParams(raw) {
6562
6630
  var model13 = defineModel({
6563
6631
  name: "buttonscrew",
6564
6632
  schema: buttonScrewModelDefinitionSchema,
6565
- parse: parseButtonScrewModelParams,
6566
- normalizeString: (value) => normalizeModelStringFlags(
6567
- value,
6568
- stringFlags2,
6569
- parseButtonScrewModelParams,
6570
- omittedStringFlags2
6571
- )
6633
+ parse: parseButtonScrewModelParams
6572
6634
  });
6573
6635
  function register13(registry2) {
6574
6636
  registry2.register(model13);
6575
6637
  }
6576
- var stringFlags3 = {
6577
- symmetricring: "shape(symmetricring)"
6578
- };
6579
- var omittedStringFlags3 = [];
6580
6638
  var length5 = external_exports.union([
6581
6639
  external_exports.number(),
6582
6640
  external_exports.string().regex(
@@ -6592,7 +6650,7 @@ var shape10 = {
6592
6650
  grooveWidth: length5,
6593
6651
  /** Radial recess from the flange outside diameter. */
6594
6652
  grooveDepth: length5,
6595
- shape: external_exports.literal("symmetricring").default("symmetricring")
6653
+ symmetricRing: external_exports.literal(true).default(true)
6596
6654
  };
6597
6655
  function validate9(props, context) {
6598
6656
  if (props.innerDiameter >= props.panelHoleDiameter || props.panelHoleDiameter >= props.outerDiameter)
@@ -6649,9 +6707,7 @@ var lengths9 = {
6649
6707
  groovedepth: "grooveDepth"
6650
6708
  };
6651
6709
  function parseCableGrommetModelParams(raw) {
6652
- const tokens = splitModelStringTokens(
6653
- expandModelStringFlags(raw.string, stringFlags3)
6654
- );
6710
+ const tokens = splitModelStringTokens(raw.string);
6655
6711
  if (raw.fn !== "cablegrommet" || !/^cablegrommet$/i.test(tokens[0]))
6656
6712
  throw new Error("Expected cablegrommet without an inline value");
6657
6713
  const props = { fn: "cablegrommet" };
@@ -6659,15 +6715,14 @@ function parseCableGrommetModelParams(raw) {
6659
6715
  const match = token.match(/^([a-z]+)(.*)$/i);
6660
6716
  const name = match?.[1]?.toLowerCase();
6661
6717
  const value = match?.[2];
6662
- if (!name || !value) throw new Error(`Invalid grommet token "${token}"`);
6718
+ if (!name) throw new Error(`Invalid grommet token "${token}"`);
6663
6719
  let property;
6664
6720
  let parsed = value;
6665
6721
  if (name in lengths9) property = lengths9[name];
6666
- else if (name === "shape") {
6667
- property = "shape";
6668
- const selector = value.match(/^\(([a-z]+)\)$/i);
6669
- if (!selector) throw new Error("Grommet shape requires parentheses");
6670
- parsed = selector[1].toLowerCase();
6722
+ else if (name === "symmetricring") {
6723
+ property = "symmetricRing";
6724
+ if (value !== "") throw new Error("symmetricring is a value-free flag");
6725
+ parsed = true;
6671
6726
  } else throw new Error(`Unknown grommet token "${token}"`);
6672
6727
  if (property in props)
6673
6728
  throw new Error(`Grommet property "${property}" is set more than once`);
@@ -6678,13 +6733,7 @@ function parseCableGrommetModelParams(raw) {
6678
6733
  var model14 = defineModel({
6679
6734
  name: "cablegrommet",
6680
6735
  schema: cableGrommetModelDefinitionSchema,
6681
- parse: parseCableGrommetModelParams,
6682
- normalizeString: (value) => normalizeModelStringFlags(
6683
- value,
6684
- stringFlags3,
6685
- parseCableGrommetModelParams,
6686
- omittedStringFlags3
6687
- )
6736
+ parse: parseCableGrommetModelParams
6688
6737
  });
6689
6738
  function register14(registry2) {
6690
6739
  registry2.register(model14);
@@ -6781,12 +6830,6 @@ var model15 = defineModel({
6781
6830
  function register15(registry2) {
6782
6831
  registry2.register(model15);
6783
6832
  }
6784
- var stringFlags4 = {
6785
- singleclamp: "mount(singleclamp)",
6786
- lefthanded: "threadhand(left)",
6787
- righthanded: "threadhand(right)"
6788
- };
6789
- var omittedStringFlags4 = ["righthanded"];
6790
6833
  var length7 = external_exports.union([
6791
6834
  external_exports.number().finite(),
6792
6835
  external_exports.string().regex(
@@ -6807,10 +6850,10 @@ var shape12 = {
6807
6850
  splitWidth: positive3,
6808
6851
  clampX: positive3.optional(),
6809
6852
  clearanceHoleDiameter: positive3.optional(),
6810
- mount: external_exports.literal("singleclamp").default("singleclamp"),
6853
+ singleClamp: external_exports.literal(true).default(true),
6811
6854
  metricSize: metricBoltSizeSchema,
6812
6855
  threadPitch: positive3.optional(),
6813
- threadHand: external_exports.enum(["right", "left"]).default("right"),
6856
+ leftHanded: external_exports.boolean().default(false),
6814
6857
  threadClass: external_exports.literal("6H").default("6H"),
6815
6858
  chamfer: nonnegative2.default(0)
6816
6859
  };
@@ -6886,7 +6929,7 @@ function getClampingShaftCollarDimensions(input) {
6886
6929
  diameter: threadDiameter,
6887
6930
  depth: threadedExtent - p.splitWidth / 2,
6888
6931
  threadPitch: p.threadPitch,
6889
- threadHand: p.threadHand,
6932
+ leftHanded: p.leftHanded,
6890
6933
  threadGender: "female",
6891
6934
  threadClass: p.threadClass
6892
6935
  }
@@ -6895,10 +6938,8 @@ function getClampingShaftCollarDimensions(input) {
6895
6938
  var tokenProperties = {
6896
6939
  bore: "boreDiameter",
6897
6940
  od: "outerDiameter",
6898
- mount: "mount",
6899
6941
  m: "metricSize",
6900
6942
  threadpitch: "threadPitch",
6901
- threadhand: "threadHand",
6902
6943
  threadclass: "threadClass",
6903
6944
  chamfer: "chamfer",
6904
6945
  w: "width",
@@ -6909,27 +6950,35 @@ var tokenProperties = {
6909
6950
  clearance: "clearanceHoleDiameter"
6910
6951
  };
6911
6952
  function parseClampingShaftCollarModelParams(raw) {
6912
- const tokens = splitModelStringTokens(
6913
- expandModelStringFlags(raw.string, stringFlags4)
6914
- );
6953
+ const tokens = splitModelStringTokens(raw.string);
6915
6954
  if (raw.fn !== "clampingshaftcollar" || tokens[0]?.toLowerCase() !== "clampingshaftcollar")
6916
6955
  throw new Error("Expected an unadorned clampingshaftcollar function");
6917
6956
  const props = {};
6918
6957
  for (const token of tokens.slice(1)) {
6919
6958
  const match = token.match(/^([a-z]+)(.*)$/i);
6920
6959
  const name = match?.[1]?.toLowerCase() ?? "";
6960
+ const value = match?.[2] ?? "";
6961
+ if (["singleclamp", "lefthanded", "righthanded"].includes(name)) {
6962
+ if (value) throw new Error(`Flag "${name}" does not take a value`);
6963
+ const property2 = name === "singleclamp" ? "singleClamp" : "leftHanded";
6964
+ if (property2 in props)
6965
+ throw new Error(
6966
+ `Duplicate or conflicting clampingshaftcollar flag "${property2}"`
6967
+ );
6968
+ props[property2] = name !== "righthanded";
6969
+ continue;
6970
+ }
6921
6971
  const property = tokenProperties[name];
6922
6972
  if (!property)
6923
6973
  throw new Error(`Unknown clampingshaftcollar token "${token}"`);
6924
6974
  if (property in props)
6925
6975
  throw new Error(`Duplicate clampingshaftcollar property "${property}"`);
6926
- const value = match[2];
6927
6976
  if (!value) throw new Error(`Token "${name}" requires a value`);
6928
- if (["mount", "threadHand", "threadClass"].includes(property)) {
6977
+ if (property === "threadClass") {
6929
6978
  const argument = value.match(/^\(([^()]+)\)$/);
6930
6979
  if (!argument)
6931
6980
  throw new Error(`Token "${name}" requires one parenthesized argument`);
6932
- props[property] = property === "threadClass" ? argument[1].toUpperCase() : argument[1].toLowerCase();
6981
+ props[property] = argument[1].toUpperCase();
6933
6982
  } else if (property === "metricSize") {
6934
6983
  if (!/^\d+(?:\.\d+)?$/.test(value))
6935
6984
  throw new Error("m requires a unitless metric designation");
@@ -6946,41 +6995,27 @@ function parseClampingShaftCollarModelParams(raw) {
6946
6995
  var model16 = defineModel({
6947
6996
  name: "clampingshaftcollar",
6948
6997
  schema: clampingShaftCollarModelDefinitionSchema,
6949
- parse: parseClampingShaftCollarModelParams,
6950
- normalizeString: (value) => normalizeModelStringFlags(
6951
- value,
6952
- stringFlags4,
6953
- parseClampingShaftCollarModelParams,
6954
- omittedStringFlags4
6955
- )
6998
+ parse: parseClampingShaftCollarModelParams
6956
6999
  });
6957
7000
  function register16(registry2) {
6958
7001
  registry2.register(model16);
6959
7002
  }
6960
- var stringFlags5 = {
6961
- closedground: "ends(closedground)",
6962
- lefthanded: "hand(left)",
6963
- righthanded: "hand(right)",
6964
- custom: "spec(custom)",
6965
- free: "state(free)"
6966
- };
6967
- var omittedStringFlags5 = ["righthanded", "custom", "free"];
6968
7003
  var length8 = external_exports.union([
6969
7004
  external_exports.number(),
6970
7005
  external_exports.string().regex(/^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:mm|cm|m|in|inch|mil|ft|feet)?$/i).transform((value) => value.toLowerCase())
6971
7006
  ]).pipe(modelLengthSchema).refine((value) => value > 0, "Length must be positive");
6972
7007
  var turnCount = external_exports.number().int().min(1).max(Number.MAX_SAFE_INTEGER);
6973
7008
  var shape13 = {
6974
- spec: external_exports.literal("custom").default("custom"),
7009
+ custom: external_exports.literal(true).default(true),
6975
7010
  outerDiameter: length8,
6976
7011
  wireDiameter: length8,
6977
7012
  freeLength: length8,
6978
7013
  totalTurns: turnCount.min(3),
6979
7014
  /** Closed-ground ends have exactly one inactive turn at each end. */
6980
7015
  activeTurns: turnCount.optional(),
6981
- ends: external_exports.literal("closedground").default("closedground"),
6982
- hand: external_exports.enum(["right", "left"]).default("right"),
6983
- state: external_exports.literal("free").default("free")
7016
+ closedGround: external_exports.literal(true).default(true),
7017
+ leftHanded: external_exports.boolean().default(false),
7018
+ free: external_exports.literal(true).default(true)
6984
7019
  };
6985
7020
  function validate12(props, context) {
6986
7021
  if (props.outerDiameter <= 2 * props.wireDiameter)
@@ -7033,14 +7068,12 @@ function getCompressionSpringCenterlinePoint(input, turn) {
7033
7068
  throw new Error("Turn coordinate must be finite and within [0,totalTurns]");
7034
7069
  const radius = (props.outerDiameter - props.wireDiameter) / 2;
7035
7070
  const pitch = (props.freeLength - 2 * props.wireDiameter) / props.activeTurns;
7036
- const phase = (props.hand === "right" ? 1 : -1) * 2 * Math.PI * (turn % 1);
7071
+ const phase = (props.leftHanded ? -1 : 1) * 2 * Math.PI * (turn % 1);
7037
7072
  const z59 = turn <= 1 ? props.wireDiameter * turn : turn >= props.totalTurns - 1 ? props.freeLength - props.wireDiameter * (props.totalTurns - turn) : props.wireDiameter + pitch * (turn - 1);
7038
7073
  return { x: radius * Math.cos(phase), y: radius * Math.sin(phase), z: z59 };
7039
7074
  }
7040
7075
  function parseCompressionSpringModelParams(raw) {
7041
- const tokens = splitModelStringTokens(
7042
- expandModelStringFlags(raw.string, stringFlags5)
7043
- );
7076
+ const tokens = splitModelStringTokens(raw.string);
7044
7077
  if (raw.fn !== "compressionspring" || tokens[0]?.toLowerCase() !== "compressionspring")
7045
7078
  throw new Error("Expected compressionspring without an inline argument");
7046
7079
  const props = { fn: "compressionspring" };
@@ -7051,11 +7084,12 @@ function parseCompressionSpringModelParams(raw) {
7051
7084
  length: "freeLength",
7052
7085
  freelength: "freeLength"
7053
7086
  };
7054
- const selectors7 = {
7055
- spec: "spec",
7056
- ends: "ends",
7057
- hand: "hand",
7058
- state: "state"
7087
+ const flags11 = {
7088
+ custom: "custom",
7089
+ closedground: "closedGround",
7090
+ free: "free",
7091
+ lefthanded: "leftHanded",
7092
+ righthanded: "leftHanded"
7059
7093
  };
7060
7094
  for (const token of tokens.slice(1)) {
7061
7095
  const match = token.match(/^([a-z]+)(.*)$/i);
@@ -7070,11 +7104,10 @@ function parseCompressionSpringModelParams(raw) {
7070
7104
  if (!/^\d+$/.test(value))
7071
7105
  throw new Error(`${name} requires a unitless integer`);
7072
7106
  parsed = Number(value);
7073
- } else if (name in selectors7) {
7074
- property = selectors7[name];
7075
- if (!/^\([^()]+\)$/.test(value))
7076
- throw new Error(`Expected a parenthesized ${name}`);
7077
- parsed = value.slice(1, -1).toLowerCase();
7107
+ } else if (Object.hasOwn(flags11, name)) {
7108
+ if (value) throw new Error(`Flag "${name}" does not take a value`);
7109
+ property = flags11[name];
7110
+ parsed = name !== "righthanded";
7078
7111
  } else throw new Error(`Unknown compression spring token "${token}"`);
7079
7112
  if (property in props)
7080
7113
  throw new Error(`Duplicate compression spring property "${property}"`);
@@ -7085,13 +7118,7 @@ function parseCompressionSpringModelParams(raw) {
7085
7118
  var model17 = defineModel({
7086
7119
  name: "compressionspring",
7087
7120
  schema: compressionSpringModelDefinitionSchema,
7088
- parse: parseCompressionSpringModelParams,
7089
- normalizeString: (value) => normalizeModelStringFlags(
7090
- value,
7091
- stringFlags5,
7092
- parseCompressionSpringModelParams,
7093
- omittedStringFlags5
7094
- )
7121
+ parse: parseCompressionSpringModelParams
7095
7122
  });
7096
7123
  function register17(registry2) {
7097
7124
  registry2.register(model17);
@@ -7544,7 +7571,7 @@ var aliases4 = {
7544
7571
  threadrootdiameter: "threadRootDiameter",
7545
7572
  threadpitchdiameter: "threadPitchDiameter"
7546
7573
  };
7547
- var flags2 = {
7574
+ var flags3 = {
7548
7575
  fullthread: "fullThread",
7549
7576
  plainface: "plainFace",
7550
7577
  lefthanded: "leftHand",
@@ -7570,9 +7597,9 @@ function parseFlangeBoltModelParams(raw) {
7570
7597
  const value = match?.[2] ?? "";
7571
7598
  let property;
7572
7599
  let parsed;
7573
- if (flags2[key]) {
7600
+ if (flags3[key]) {
7574
7601
  if (value) throw new Error(`Flag ${key} does not accept a value`);
7575
- property = flags2[key];
7602
+ property = flags3[key];
7576
7603
  parsed = !["righthanded", "nothreads"].includes(key);
7577
7604
  } else {
7578
7605
  if (key === "standard" || key === "headstandard")
@@ -7610,10 +7637,6 @@ var model20 = defineModel({
7610
7637
  function register20(registry2) {
7611
7638
  registry2.register(model20);
7612
7639
  }
7613
- var stringFlags6 = {
7614
- plainclosed: "style(plainclosed)"
7615
- };
7616
- var omittedStringFlags6 = ["plainclosed"];
7617
7640
  var positiveLength6 = external_exports.union([
7618
7641
  external_exports.number(),
7619
7642
  external_exports.string().regex(/^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:mm|cm|m|in|inch|mil|ft|feet)?$/i).transform((value) => value.toLowerCase())
@@ -7625,7 +7648,7 @@ var shape17 = {
7625
7648
  /** Overall end-plane distance including the integral flange. */
7626
7649
  length: positiveLength6,
7627
7650
  flangeThickness: positiveLength6,
7628
- style: external_exports.literal("plainclosed").default("plainclosed")
7651
+ plainClosed: external_exports.literal(true).default(true)
7629
7652
  };
7630
7653
  function validate16(props, context) {
7631
7654
  if (props.outerDiameter <= props.innerDiameter)
@@ -7675,9 +7698,7 @@ var lengths12 = {
7675
7698
  flangethickness: "flangeThickness"
7676
7699
  };
7677
7700
  function parseFlangedBushingModelParams(raw) {
7678
- const tokens = splitModelStringTokens(
7679
- expandModelStringFlags(raw.string, stringFlags6)
7680
- );
7701
+ const tokens = splitModelStringTokens(raw.string);
7681
7702
  if (raw.fn !== "flangedbushing" || tokens[0]?.toLowerCase() !== "flangedbushing")
7682
7703
  throw new Error("Expected flangedbushing without an inline value");
7683
7704
  const props = { fn: "flangedbushing" };
@@ -7691,11 +7712,10 @@ function parseFlangedBushingModelParams(raw) {
7691
7712
  if (Object.hasOwn(lengths12, name)) {
7692
7713
  property = lengths12[name];
7693
7714
  parsed = value;
7694
- } else if (name === "style") {
7695
- property = "style";
7696
- const style = value.match(/^\(([a-z]+)\)$/i);
7697
- if (!style) throw new Error("Style requires a parenthesized value");
7698
- parsed = style[1].toLowerCase();
7715
+ } else if (name === "plainclosed") {
7716
+ property = "plainClosed";
7717
+ if (value !== "") throw new Error("plainclosed is a value-free flag");
7718
+ parsed = true;
7699
7719
  } else throw new Error(`Unknown flanged bushing token "${token}"`);
7700
7720
  if (Object.hasOwn(props, property))
7701
7721
  throw new Error(
@@ -7708,13 +7728,7 @@ function parseFlangedBushingModelParams(raw) {
7708
7728
  var model21 = defineModel({
7709
7729
  name: "flangedbushing",
7710
7730
  schema: flangedBushingModelDefinitionSchema,
7711
- parse: parseFlangedBushingModelParams,
7712
- normalizeString: (value) => normalizeModelStringFlags(
7713
- value,
7714
- stringFlags6,
7715
- parseFlangedBushingModelParams,
7716
- omittedStringFlags6
7717
- )
7731
+ parse: parseFlangedBushingModelParams
7718
7732
  });
7719
7733
  function register21(registry2) {
7720
7734
  registry2.register(model21);
@@ -8072,10 +8086,7 @@ var lengths13 = {
8072
8086
  outerdiameter: "outerDiameter",
8073
8087
  thickness: "thickness"
8074
8088
  };
8075
- var flags3 = { flatannulus: "flatAnnulus" };
8076
- var selectors2 = {
8077
- profile: { value: "flatannulus", property: "flatAnnulus" }
8078
- };
8089
+ var flags4 = { flatannulus: "flatAnnulus" };
8079
8090
  var integers = {};
8080
8091
  var tuples = {};
8081
8092
  function parseFlatGasketModelParams(raw) {
@@ -8093,9 +8104,7 @@ function parseFlatGasketModelParams(raw) {
8093
8104
  if (!match) throw new Error(`Malformed flatgasket token "${token}"`);
8094
8105
  const key = match[1].toLowerCase(), value = match[2];
8095
8106
  if (Object.hasOwn(lengths13, key) && value) assign(lengths13[key], value);
8096
- else if (Object.hasOwn(flags3, key) && !value) assign(flags3[key], true);
8097
- else if (Object.hasOwn(selectors2, key) && value.toLowerCase() === `(${selectors2[key].value})`)
8098
- assign(selectors2[key].property, true);
8107
+ else if (Object.hasOwn(flags4, key) && !value) assign(flags4[key], true);
8099
8108
  else if (Object.hasOwn(integers, key) && /^\d+$/.test(value))
8100
8109
  assign(integers[key], Number(value));
8101
8110
  else if (Object.hasOwn(tuples, key)) {
@@ -8116,14 +8125,6 @@ var model24 = defineModel({
8116
8125
  function register24(registry2) {
8117
8126
  registry2.register(model24);
8118
8127
  }
8119
- var stringFlags7 = {
8120
- hexsocket: "drive(hexsocket)",
8121
- fullthread: "thread(full)",
8122
- lefthanded: "threadhand(left)",
8123
- righthanded: "threadhand(right)",
8124
- male: "threadgender(male)"
8125
- };
8126
- var omittedStringFlags7 = ["righthanded", "male"];
8127
8128
  var positiveModelLengthSchema3 = external_exports.union([
8128
8129
  external_exports.number(),
8129
8130
  external_exports.string().regex(/^(?:\d+(?:\.\d+)?|\.\d+)(?:mm|cm|m|in|inch)?$/i).transform((value) => value.toLowerCase())
@@ -8199,11 +8200,11 @@ var flatHeadScrewModelPropsShape = {
8199
8200
  iso10642: external_exports.literal(true).default(true),
8200
8201
  metricSize: flatHeadScrewMetricSizeSchema,
8201
8202
  length: positiveModelLengthSchema3,
8202
- thread: external_exports.literal("full").default("full"),
8203
- drive: external_exports.literal("hexsocket").default("hexsocket"),
8204
- threadHand: external_exports.enum(["right", "left"]).default("right"),
8203
+ fullThread: external_exports.literal(true).default(true),
8204
+ hexSocket: external_exports.literal(true).default(true),
8205
+ leftHanded: external_exports.boolean().default(false),
8205
8206
  threadClass: external_exports.literal("6g").default("6g"),
8206
- threadGender: external_exports.literal("male").default("male"),
8207
+ male: external_exports.literal(true).default(true),
8207
8208
  showThreads: external_exports.boolean().default(true),
8208
8209
  diameter: positiveModelLengthSchema3.optional(),
8209
8210
  threadPitch: positiveModelLengthSchema3.optional(),
@@ -8269,11 +8270,7 @@ var aliases5 = {
8269
8270
  metricsize: "metricSize",
8270
8271
  l: "length",
8271
8272
  length: "length",
8272
- thread: "thread",
8273
- drive: "drive",
8274
- threadhand: "threadHand",
8275
8273
  threadclass: "threadClass",
8276
- threadgender: "threadGender",
8277
8274
  diameter: "diameter",
8278
8275
  threadpitch: "threadPitch",
8279
8276
  headdiameter: "headDiameter",
@@ -8294,19 +8291,18 @@ var aliases5 = {
8294
8291
  socketaf: "socketAcrossFlats",
8295
8292
  socketh: "socketDepth"
8296
8293
  };
8297
- var selectors3 = /* @__PURE__ */ new Set([
8298
- "thread",
8299
- "drive",
8300
- "threadHand",
8301
- "threadClass",
8302
- "threadGender"
8303
- ]);
8294
+ var selectors2 = /* @__PURE__ */ new Set(["threadClass"]);
8295
+ var booleanFlags2 = {
8296
+ hexsocket: { property: "hexSocket", value: true },
8297
+ fullthread: { property: "fullThread", value: true },
8298
+ male: { property: "male", value: true },
8299
+ lefthanded: { property: "leftHanded", value: true },
8300
+ righthanded: { property: "leftHanded", value: false }
8301
+ };
8304
8302
  var parseFlatHeadScrewModelParams = (raw) => {
8305
8303
  if (raw.fn !== "flatheadscrew")
8306
8304
  throw new Error(`Expected flatheadscrew params, got "${raw.fn}"`);
8307
- const [root, ...tokens] = splitModelStringTokens(
8308
- expandModelStringFlags(raw.string, stringFlags7)
8309
- );
8305
+ const [root, ...tokens] = splitModelStringTokens(raw.string);
8310
8306
  if (root?.toLowerCase() !== "flatheadscrew")
8311
8307
  throw new Error(
8312
8308
  "The flatheadscrew function does not accept an inline value"
@@ -8324,16 +8320,20 @@ var parseFlatHeadScrewModelParams = (raw) => {
8324
8320
  const value = match?.[2];
8325
8321
  let property;
8326
8322
  let parsed;
8327
- if (key === "threads" || key === "nothreads") {
8323
+ if (key && Object.hasOwn(booleanFlags2, key)) {
8324
+ if (value !== "") throw new Error(`Flag "${key}" does not accept a value`);
8325
+ property = booleanFlags2[key].property;
8326
+ parsed = booleanFlags2[key].value;
8327
+ } else if (key === "threads" || key === "nothreads") {
8328
8328
  if (value !== "")
8329
8329
  throw new Error(`Token "${key}" does not accept a value`);
8330
8330
  property = "showThreads";
8331
8331
  parsed = key === "threads";
8332
8332
  } else {
8333
- property = key ? aliases5[key] ?? "" : "";
8333
+ property = key && Object.hasOwn(aliases5, key) ? aliases5[key] : "";
8334
8334
  if (!property || !value)
8335
8335
  throw new Error(`Unknown or missing flatheadscrew token "${token}"`);
8336
- if (selectors3.has(property)) {
8336
+ if (selectors2.has(property)) {
8337
8337
  const selector = value.match(/^\(([^()]+)\)$/)?.[1];
8338
8338
  if (!selector)
8339
8339
  throw new Error(`Token "${key}" requires a parenthesized selector`);
@@ -8363,13 +8363,7 @@ var parseFlatHeadScrewModelParams = (raw) => {
8363
8363
  var model25 = defineModel({
8364
8364
  name: "flatheadscrew",
8365
8365
  schema: flatHeadScrewModelDefinitionSchema,
8366
- parse: parseFlatHeadScrewModelParams,
8367
- normalizeString: (value) => normalizeModelStringFlags(
8368
- value,
8369
- stringFlags7,
8370
- parseFlatHeadScrewModelParams,
8371
- omittedStringFlags7
8372
- )
8366
+ parse: parseFlatHeadScrewModelParams
8373
8367
  });
8374
8368
  function register25(registry2) {
8375
8369
  registry2.register(model25);
@@ -8530,7 +8524,7 @@ var aliases7 = {
8530
8524
  threadpitchdiameter: "threadPitchDiameter",
8531
8525
  rootouterdiameter: "rootOuterDiameter"
8532
8526
  };
8533
- var flags4 = {
8527
+ var flags5 = {
8534
8528
  diamondknurl: "diamondKnurl",
8535
8529
  lefthanded: "leftHand",
8536
8530
  righthanded: "leftHand",
@@ -8547,9 +8541,9 @@ function parseHeatSetInsertModelParams(raw) {
8547
8541
  for (const token of tokens) {
8548
8542
  const match = token.match(/^([a-z]+)(.*)$/i), key = match?.[1]?.toLowerCase() ?? "", value = match?.[2] ?? "";
8549
8543
  let property, parsed;
8550
- if (flags4[key]) {
8544
+ if (flags5[key]) {
8551
8545
  if (value) throw new Error("Flags do not accept values");
8552
- property = flags4[key];
8546
+ property = flags5[key];
8553
8547
  parsed = !["righthanded", "nothreads"].includes(key);
8554
8548
  } else {
8555
8549
  property = aliases7[key] ?? "";
@@ -8586,10 +8580,6 @@ var model27 = defineModel({
8586
8580
  function register27(registry2) {
8587
8581
  registry2.register(model27);
8588
8582
  }
8589
- var stringFlags8 = {
8590
- righthanded: "threadhand(right)"
8591
- };
8592
- var omittedStringFlags8 = ["righthanded"];
8593
8583
  var hexNutDimensions = {
8594
8584
  M5: {
8595
8585
  diameter: 5,
@@ -8830,7 +8820,7 @@ var shape23 = {
8830
8820
  metricSize: hexNutMetricSizeSchema.optional(),
8831
8821
  imperialSize: hexNutImperialSizeSchema.optional(),
8832
8822
  threadPitch: length13.optional(),
8833
- threadHand: external_exports.literal("right").default("right"),
8823
+ rightHanded: external_exports.literal(true).default(true),
8834
8824
  threadClass: external_exports.enum(["6H", "2B"]).optional(),
8835
8825
  showThreads: external_exports.boolean().default(true)
8836
8826
  };
@@ -8856,11 +8846,11 @@ function validate22(props, context) {
8856
8846
  const issue = (path, message) => context.addIssue({ code: "custom", path: [path], message });
8857
8847
  if (!!props.metricSize === !!props.imperialSize)
8858
8848
  issue("metricSize", "Select exactly one metric or imperial size");
8859
- const flags10 = ["iso4032", "din934", "asmeb1822"];
8849
+ const flags11 = ["iso4032", "din934", "asmeb1822"];
8860
8850
  const family = selectedFamily(props);
8861
- if (flags10.filter((flag) => props[flag] === true).length > 1)
8851
+ if (flags11.filter((flag) => props[flag] === true).length > 1)
8862
8852
  issue("iso4032", "Select only one ISO, DIN or ASME family");
8863
- for (const flag of flags10)
8853
+ for (const flag of flags11)
8864
8854
  if (family[flag] && props[flag] === false)
8865
8855
  issue(
8866
8856
  flag,
@@ -8908,14 +8898,11 @@ function getHexNutDimensions(input) {
8908
8898
  };
8909
8899
  }
8910
8900
  function parseHexNutModelParams(raw) {
8911
- const tokens = splitModelStringTokens(
8912
- expandModelStringFlags(raw.string, stringFlags8)
8913
- );
8901
+ const tokens = splitModelStringTokens(raw.string);
8914
8902
  if (raw.fn !== "hexnut" || tokens[0]?.toLowerCase() !== "hexnut")
8915
8903
  throw new Error("Expected hexnut without an inline argument");
8916
8904
  const props = { fn: "hexnut" };
8917
- const selectors7 = {
8918
- threadhand: "threadHand",
8905
+ const selectors5 = {
8919
8906
  threadclass: "threadClass"
8920
8907
  };
8921
8908
  let explicitFamily = false;
@@ -8952,9 +8939,13 @@ function parseHexNutModelParams(raw) {
8952
8939
  throw new Error("Duplicate hex nut property threadPitch");
8953
8940
  props.threadPitch = 25.4 / Number(parts[1]);
8954
8941
  }
8942
+ } else if (name === "righthanded") {
8943
+ if (value) throw new Error("Handedness flags cannot have a value");
8944
+ property = "rightHanded";
8945
+ parsed = true;
8955
8946
  } else if (name === "threadpitch") property = "threadPitch";
8956
- else if (name in selectors7) {
8957
- property = selectors7[name];
8947
+ else if (name in selectors5) {
8948
+ property = selectors5[name];
8958
8949
  if (!/^\([^()]+\)$/.test(value))
8959
8950
  throw new Error(`Expected a parenthesized ${name}`);
8960
8951
  parsed = value.slice(1, -1).toLowerCase();
@@ -8973,13 +8964,7 @@ function parseHexNutModelParams(raw) {
8973
8964
  var model28 = defineModel({
8974
8965
  name: "hexnut",
8975
8966
  schema: hexNutModelDefinitionSchema,
8976
- parse: parseHexNutModelParams,
8977
- normalizeString: (value) => normalizeModelStringFlags(
8978
- value,
8979
- stringFlags8,
8980
- parseHexNutModelParams,
8981
- omittedStringFlags8
8982
- )
8967
+ parse: parseHexNutModelParams
8983
8968
  });
8984
8969
  function register28(registry2) {
8985
8970
  registry2.register(model28);
@@ -9241,7 +9226,7 @@ var lengths15 = {
9241
9226
  studchamfer: "studChamfer",
9242
9227
  mouthchamfer: "mouthChamfer"
9243
9228
  };
9244
- var flags5 = {
9229
+ var flags6 = {
9245
9230
  hex: ["hex", true],
9246
9231
  lefthanded: ["leftHand", true],
9247
9232
  righthanded: ["leftHand", false],
@@ -9257,8 +9242,8 @@ function parseMaleFemaleStandoffModelParams(raw) {
9257
9242
  const lower = token.toLowerCase();
9258
9243
  let property;
9259
9244
  let value;
9260
- if (Object.hasOwn(flags5, lower)) {
9261
- const entry = flags5[lower];
9245
+ if (Object.hasOwn(flags6, lower)) {
9246
+ const entry = flags6[lower];
9262
9247
  property = entry[0];
9263
9248
  value = entry[1];
9264
9249
  } else {
@@ -9443,14 +9428,6 @@ var model31 = defineModel({
9443
9428
  function register31(registry2) {
9444
9429
  registry2.register(model31);
9445
9430
  }
9446
- var stringFlags9 = {
9447
- phillips: "drive(phillips)",
9448
- fullthread: "thread(full)",
9449
- lefthanded: "threadhand(left)",
9450
- righthanded: "threadhand(right)",
9451
- male: "threadgender(male)"
9452
- };
9453
- var omittedStringFlags9 = ["righthanded", "male"];
9454
9431
  var positiveModelLengthSchema4 = external_exports.union([
9455
9432
  external_exports.number(),
9456
9433
  external_exports.string().regex(/^(?:\d+(?:\.\d+)?|\.\d+)(?:mm|cm|m|in|inch)?$/i).transform((value) => value.toLowerCase())
@@ -9574,11 +9551,11 @@ var panScrewModelPropsShape = {
9574
9551
  iso7045: external_exports.literal(true).default(true),
9575
9552
  metricSize: panScrewMetricSizeSchema,
9576
9553
  length: positiveModelLengthSchema4,
9577
- thread: external_exports.literal("full").default("full"),
9578
- drive: external_exports.literal("phillips").default("phillips"),
9579
- threadHand: external_exports.enum(["right", "left"]).default("right"),
9554
+ fullThread: external_exports.literal(true).default(true),
9555
+ phillips: external_exports.literal(true).default(true),
9556
+ leftHanded: external_exports.boolean().default(false),
9580
9557
  threadClass: external_exports.literal("6g").default("6g"),
9581
- threadGender: external_exports.literal("male").default("male"),
9558
+ male: external_exports.literal(true).default(true),
9582
9559
  showThreads: external_exports.boolean().default(true),
9583
9560
  iso4757: external_exports.literal(true).default(true),
9584
9561
  recessType: external_exports.literal("H").default("H"),
@@ -9645,11 +9622,7 @@ var aliases8 = {
9645
9622
  metricsize: "metricSize",
9646
9623
  l: "length",
9647
9624
  length: "length",
9648
- thread: "thread",
9649
- drive: "drive",
9650
- threadhand: "threadHand",
9651
9625
  threadclass: "threadClass",
9652
- threadgender: "threadGender",
9653
9626
  diameter: "diameter",
9654
9627
  threadpitch: "threadPitch",
9655
9628
  headdiameter: "headDiameter",
@@ -9680,19 +9653,18 @@ var aliases8 = {
9680
9653
  headh: "headHeight",
9681
9654
  headd: "headDiameter"
9682
9655
  };
9683
- var selectors4 = /* @__PURE__ */ new Set([
9684
- "thread",
9685
- "drive",
9686
- "threadHand",
9687
- "threadClass",
9688
- "threadGender"
9689
- ]);
9656
+ var selectors3 = /* @__PURE__ */ new Set(["threadClass"]);
9657
+ var booleanFlags3 = {
9658
+ phillips: { property: "phillips", value: true },
9659
+ fullthread: { property: "fullThread", value: true },
9660
+ male: { property: "male", value: true },
9661
+ lefthanded: { property: "leftHanded", value: true },
9662
+ righthanded: { property: "leftHanded", value: false }
9663
+ };
9690
9664
  var parsePanScrewModelParams = (raw) => {
9691
9665
  if (raw.fn !== "panscrew")
9692
9666
  throw new Error(`Expected panscrew params, got "${raw.fn}"`);
9693
- const [root, ...tokens] = splitModelStringTokens(
9694
- expandModelStringFlags(raw.string, stringFlags9)
9695
- );
9667
+ const [root, ...tokens] = splitModelStringTokens(raw.string);
9696
9668
  if (root?.toLowerCase() !== "panscrew")
9697
9669
  throw new Error("The panscrew function does not accept an inline value");
9698
9670
  const props = {};
@@ -9709,16 +9681,20 @@ var parsePanScrewModelParams = (raw) => {
9709
9681
  const value = match?.[2];
9710
9682
  let property;
9711
9683
  let parsed;
9712
- if (key === "threads" || key === "nothreads") {
9684
+ if (key && Object.hasOwn(booleanFlags3, key)) {
9685
+ if (value !== "") throw new Error(`Flag "${key}" does not accept a value`);
9686
+ property = booleanFlags3[key].property;
9687
+ parsed = booleanFlags3[key].value;
9688
+ } else if (key === "threads" || key === "nothreads") {
9713
9689
  if (value !== "")
9714
9690
  throw new Error(`Token "${key}" does not accept a value`);
9715
9691
  property = "showThreads";
9716
9692
  parsed = key === "threads";
9717
9693
  } else {
9718
- property = key ? aliases8[key] ?? "" : "";
9694
+ property = key && Object.hasOwn(aliases8, key) ? aliases8[key] : "";
9719
9695
  if (!property || !value)
9720
9696
  throw new Error(`Unknown or missing panscrew token "${token}"`);
9721
- if (selectors4.has(property)) {
9697
+ if (selectors3.has(property)) {
9722
9698
  const selector = value.match(/^\(([^()]+)\)$/)?.[1];
9723
9699
  if (!selector)
9724
9700
  throw new Error(`Token "${key}" requires a parenthesized selector`);
@@ -9751,13 +9727,7 @@ var parsePanScrewModelParams = (raw) => {
9751
9727
  var model32 = defineModel({
9752
9728
  name: "panscrew",
9753
9729
  schema: panScrewModelDefinitionSchema,
9754
- parse: parsePanScrewModelParams,
9755
- normalizeString: (value) => normalizeModelStringFlags(
9756
- value,
9757
- stringFlags9,
9758
- parsePanScrewModelParams,
9759
- omittedStringFlags9
9760
- )
9730
+ parse: parsePanScrewModelParams
9761
9731
  });
9762
9732
  function register32(registry2) {
9763
9733
  registry2.register(model32);
@@ -9943,10 +9913,6 @@ var model34 = defineModel({
9943
9913
  function register34(registry2) {
9944
9914
  registry2.register(model34);
9945
9915
  }
9946
- var stringFlags10 = {
9947
- plainclosed: "style(plainclosed)"
9948
- };
9949
- var omittedStringFlags10 = ["plainclosed"];
9950
9916
  var length18 = external_exports.union([
9951
9917
  external_exports.number(),
9952
9918
  external_exports.string().regex(/^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:mm|cm|m|in|inch|mil|ft|feet)?$/i).transform((value) => value.toLowerCase())
@@ -9957,7 +9923,7 @@ var shape29 = {
9957
9923
  outerDiameter: positiveLength12,
9958
9924
  /** Overall end-plane distance, including the chamfers. */
9959
9925
  length: positiveLength12,
9960
- style: external_exports.literal("plainclosed").default("plainclosed"),
9926
+ plainClosed: external_exports.literal(true).default(true),
9961
9927
  /** Equal axial/radial setbacks of all four 45-degree bore/outside rim chamfers. */
9962
9928
  edgeChamfer: length18.refine((value) => value >= 0).default(0)
9963
9929
  };
@@ -10005,9 +9971,7 @@ var lengths16 = {
10005
9971
  edgechamfer: "edgeChamfer"
10006
9972
  };
10007
9973
  function parsePlainBushingModelParams(raw) {
10008
- const tokens = splitModelStringTokens(
10009
- expandModelStringFlags(raw.string, stringFlags10)
10010
- );
9974
+ const tokens = splitModelStringTokens(raw.string);
10011
9975
  if (raw.fn !== "plainbushing" || tokens[0]?.toLowerCase() !== "plainbushing")
10012
9976
  throw new Error("Expected plainbushing without an inline value");
10013
9977
  const props = { fn: "plainbushing" };
@@ -10021,11 +9985,10 @@ function parsePlainBushingModelParams(raw) {
10021
9985
  if (Object.hasOwn(lengths16, name)) {
10022
9986
  property = lengths16[name];
10023
9987
  parsed = value;
10024
- } else if (name === "style") {
10025
- property = "style";
10026
- const style = value.match(/^\(([a-z]+)\)$/i);
10027
- if (!style) throw new Error("Style requires a parenthesized value");
10028
- parsed = style[1].toLowerCase();
9988
+ } else if (name === "plainclosed") {
9989
+ property = "plainClosed";
9990
+ if (value !== "") throw new Error("plainclosed is a value-free flag");
9991
+ parsed = true;
10029
9992
  } else throw new Error(`Unknown plain bushing token "${token}"`);
10030
9993
  if (Object.hasOwn(props, property))
10031
9994
  throw new Error(
@@ -10038,13 +10001,7 @@ function parsePlainBushingModelParams(raw) {
10038
10001
  var model35 = defineModel({
10039
10002
  name: "plainbushing",
10040
10003
  schema: plainBushingModelDefinitionSchema,
10041
- parse: parsePlainBushingModelParams,
10042
- normalizeString: (value) => normalizeModelStringFlags(
10043
- value,
10044
- stringFlags10,
10045
- parsePlainBushingModelParams,
10046
- omittedStringFlags10
10047
- )
10004
+ parse: parsePlainBushingModelParams
10048
10005
  });
10049
10006
  function register35(registry2) {
10050
10007
  registry2.register(model35);
@@ -10242,10 +10199,7 @@ var lengths17 = {
10242
10199
  thickness: "thickness",
10243
10200
  cornerradius: "cornerRadius"
10244
10201
  };
10245
- var flags6 = { flatframe: "flatFrame" };
10246
- var selectors5 = {
10247
- profile: { value: "flatframe", property: "flatFrame" }
10248
- };
10202
+ var flags7 = { flatframe: "flatFrame" };
10249
10203
  var integers2 = {};
10250
10204
  var tuples2 = {};
10251
10205
  function parseRectangularGasketModelParams(raw) {
@@ -10263,9 +10217,7 @@ function parseRectangularGasketModelParams(raw) {
10263
10217
  if (!match) throw new Error(`Malformed rectangulargasket token "${token}"`);
10264
10218
  const key = match[1].toLowerCase(), value = match[2];
10265
10219
  if (Object.hasOwn(lengths17, key) && value) assign(lengths17[key], value);
10266
- else if (Object.hasOwn(flags6, key) && !value) assign(flags6[key], true);
10267
- else if (Object.hasOwn(selectors5, key) && value.toLowerCase() === `(${selectors5[key].value})`)
10268
- assign(selectors5[key].property, true);
10220
+ else if (Object.hasOwn(flags7, key) && !value) assign(flags7[key], true);
10269
10221
  else if (Object.hasOwn(integers2, key) && /^\d+$/.test(value))
10270
10222
  assign(integers2[key], Number(value));
10271
10223
  else if (Object.hasOwn(tuples2, key)) {
@@ -10371,12 +10323,6 @@ var model39 = defineModel({
10371
10323
  function register39(registry2) {
10372
10324
  registry2.register(model39);
10373
10325
  }
10374
- var stringFlags11 = {
10375
- setscrew: "mount(setscrew)",
10376
- lefthanded: "threadhand(left)",
10377
- righthanded: "threadhand(right)"
10378
- };
10379
- var omittedStringFlags11 = ["righthanded"];
10380
10326
  var length23 = external_exports.union([
10381
10327
  external_exports.number().finite(),
10382
10328
  external_exports.string().regex(
@@ -10397,10 +10343,10 @@ var shape34 = {
10397
10343
  screwCount: external_exports.literal(4).default(4),
10398
10344
  screwEndOffset: positive6.optional(),
10399
10345
  screwAngle: external_exports.number().finite().default(0),
10400
- mount: external_exports.literal("setscrew").default("setscrew"),
10346
+ setScrew: external_exports.literal(true).default(true),
10401
10347
  metricSize: metricBoltSizeSchema,
10402
10348
  threadPitch: positive6.optional(),
10403
- threadHand: external_exports.enum(["right", "left"]).default("right"),
10349
+ leftHanded: external_exports.boolean().default(false),
10404
10350
  threadClass: external_exports.literal("6H").default("6H"),
10405
10351
  chamfer: nonnegative5.default(0)
10406
10352
  };
@@ -10469,7 +10415,7 @@ function getRigidCouplerDimensions(input) {
10469
10415
  diameter: threadDiameter,
10470
10416
  depth: radius - Math.sqrt((hole.bore / 2) ** 2 - (threadDiameter / 2) ** 2),
10471
10417
  threadPitch: p.threadPitch,
10472
- threadHand: p.threadHand,
10418
+ leftHanded: p.leftHanded,
10473
10419
  threadGender: "female",
10474
10420
  threadClass: p.threadClass
10475
10421
  };
@@ -10484,10 +10430,8 @@ function getRigidCouplerDimensions(input) {
10484
10430
  var tokenProperties2 = {
10485
10431
  bore: "boreDiameter",
10486
10432
  od: "outerDiameter",
10487
- mount: "mount",
10488
10433
  m: "metricSize",
10489
10434
  threadpitch: "threadPitch",
10490
- threadhand: "threadHand",
10491
10435
  threadclass: "threadClass",
10492
10436
  chamfer: "chamfer",
10493
10437
  boreb: "boreBDiameter",
@@ -10498,26 +10442,34 @@ var tokenProperties2 = {
10498
10442
  screwangle: "screwAngle"
10499
10443
  };
10500
10444
  function parseRigidCouplerModelParams(raw) {
10501
- const tokens = splitModelStringTokens(
10502
- expandModelStringFlags(raw.string, stringFlags11)
10503
- );
10445
+ const tokens = splitModelStringTokens(raw.string);
10504
10446
  if (raw.fn !== "rigidcoupler" || tokens[0]?.toLowerCase() !== "rigidcoupler")
10505
10447
  throw new Error("Expected an unadorned rigidcoupler function");
10506
10448
  const props = {};
10507
10449
  for (const token of tokens.slice(1)) {
10508
10450
  const match = token.match(/^([a-z]+)(.*)$/i);
10509
10451
  const name = match?.[1]?.toLowerCase() ?? "";
10452
+ const value = match?.[2] ?? "";
10453
+ if (["setscrew", "lefthanded", "righthanded"].includes(name)) {
10454
+ if (value) throw new Error(`Flag "${name}" does not take a value`);
10455
+ const property2 = name === "setscrew" ? "setScrew" : "leftHanded";
10456
+ if (property2 in props)
10457
+ throw new Error(
10458
+ `Duplicate or conflicting rigidcoupler flag "${property2}"`
10459
+ );
10460
+ props[property2] = name !== "righthanded";
10461
+ continue;
10462
+ }
10510
10463
  const property = tokenProperties2[name];
10511
10464
  if (!property) throw new Error(`Unknown rigidcoupler token "${token}"`);
10512
10465
  if (property in props)
10513
10466
  throw new Error(`Duplicate rigidcoupler property "${property}"`);
10514
- const value = match[2];
10515
10467
  if (!value) throw new Error(`Token "${name}" requires a value`);
10516
- if (["mount", "threadHand", "threadClass"].includes(property)) {
10468
+ if (property === "threadClass") {
10517
10469
  const argument = value.match(/^\(([^()]+)\)$/);
10518
10470
  if (!argument)
10519
10471
  throw new Error(`Token "${name}" requires one parenthesized argument`);
10520
- props[property] = property === "threadClass" ? argument[1].toUpperCase() : argument[1].toLowerCase();
10472
+ props[property] = argument[1].toUpperCase();
10521
10473
  } else if (property === "metricSize") {
10522
10474
  if (!/^\d+(?:\.\d+)?$/.test(value))
10523
10475
  throw new Error("m requires a unitless metric designation");
@@ -10542,13 +10494,7 @@ function parseRigidCouplerModelParams(raw) {
10542
10494
  var model40 = defineModel({
10543
10495
  name: "rigidcoupler",
10544
10496
  schema: rigidCouplerModelDefinitionSchema,
10545
- parse: parseRigidCouplerModelParams,
10546
- normalizeString: (value) => normalizeModelStringFlags(
10547
- value,
10548
- stringFlags11,
10549
- parseRigidCouplerModelParams,
10550
- omittedStringFlags11
10551
- )
10497
+ parse: parseRigidCouplerModelParams
10552
10498
  });
10553
10499
  function register40(registry2) {
10554
10500
  registry2.register(model40);
@@ -10664,7 +10610,7 @@ var aliases14 = {
10664
10610
  threadrootdiameter: "threadRootDiameter",
10665
10611
  threadpitchdiameter: "threadPitchDiameter"
10666
10612
  };
10667
- var flags7 = {
10613
+ var flags8 = {
10668
10614
  hexsocket: "hexSocket",
10669
10615
  cuppoint: "cupPoint",
10670
10616
  lefthanded: "leftHand",
@@ -10690,9 +10636,9 @@ function parseSetScrewModelParams(raw) {
10690
10636
  const value = match?.[2] ?? "";
10691
10637
  let property;
10692
10638
  let parsed;
10693
- if (flags7[key]) {
10639
+ if (flags8[key]) {
10694
10640
  if (value) throw new Error(`Flag ${key} does not accept a value`);
10695
- property = flags7[key];
10641
+ property = flags8[key];
10696
10642
  parsed = !["righthanded", "nothreads"].includes(key);
10697
10643
  } else {
10698
10644
  property = aliases14[key] ?? "";
@@ -10726,12 +10672,6 @@ var model41 = defineModel({
10726
10672
  function register41(registry2) {
10727
10673
  registry2.register(model41);
10728
10674
  }
10729
- var stringFlags12 = {
10730
- setscrew: "mount(setscrew)",
10731
- lefthanded: "threadhand(left)",
10732
- righthanded: "threadhand(right)"
10733
- };
10734
- var omittedStringFlags12 = ["righthanded"];
10735
10675
  var length24 = external_exports.union([
10736
10676
  external_exports.number().finite(),
10737
10677
  external_exports.string().regex(
@@ -10750,10 +10690,10 @@ var shape36 = {
10750
10690
  width: positive7,
10751
10691
  screwZ: positive7.optional(),
10752
10692
  screwAngle: external_exports.number().finite().default(0),
10753
- mount: external_exports.literal("setscrew").default("setscrew"),
10693
+ setScrew: external_exports.literal(true).default(true),
10754
10694
  metricSize: metricBoltSizeSchema,
10755
10695
  threadPitch: positive7.optional(),
10756
- threadHand: external_exports.enum(["right", "left"]).default("right"),
10696
+ leftHanded: external_exports.boolean().default(false),
10757
10697
  threadClass: external_exports.literal("6H").default("6H"),
10758
10698
  chamfer: nonnegative6.default(0)
10759
10699
  };
@@ -10803,7 +10743,7 @@ function getShaftCollarDimensions(input) {
10803
10743
  diameter: threadDiameter,
10804
10744
  depth: radius - Math.sqrt((p.boreDiameter / 2) ** 2 - (threadDiameter / 2) ** 2),
10805
10745
  threadPitch: p.threadPitch,
10806
- threadHand: p.threadHand,
10746
+ leftHanded: p.leftHanded,
10807
10747
  threadGender: "female",
10808
10748
  threadClass: p.threadClass
10809
10749
  }
@@ -10812,10 +10752,8 @@ function getShaftCollarDimensions(input) {
10812
10752
  var tokenProperties3 = {
10813
10753
  bore: "boreDiameter",
10814
10754
  od: "outerDiameter",
10815
- mount: "mount",
10816
10755
  m: "metricSize",
10817
10756
  threadpitch: "threadPitch",
10818
- threadhand: "threadHand",
10819
10757
  threadclass: "threadClass",
10820
10758
  chamfer: "chamfer",
10821
10759
  w: "width",
@@ -10824,26 +10762,34 @@ var tokenProperties3 = {
10824
10762
  screwangle: "screwAngle"
10825
10763
  };
10826
10764
  function parseShaftCollarModelParams(raw) {
10827
- const tokens = splitModelStringTokens(
10828
- expandModelStringFlags(raw.string, stringFlags12)
10829
- );
10765
+ const tokens = splitModelStringTokens(raw.string);
10830
10766
  if (raw.fn !== "shaftcollar" || tokens[0]?.toLowerCase() !== "shaftcollar")
10831
10767
  throw new Error("Expected an unadorned shaftcollar function");
10832
10768
  const props = {};
10833
10769
  for (const token of tokens.slice(1)) {
10834
10770
  const match = token.match(/^([a-z]+)(.*)$/i);
10835
10771
  const name = match?.[1]?.toLowerCase() ?? "";
10772
+ const value = match?.[2] ?? "";
10773
+ if (["setscrew", "lefthanded", "righthanded"].includes(name)) {
10774
+ if (value) throw new Error(`Flag "${name}" does not take a value`);
10775
+ const property2 = name === "setscrew" ? "setScrew" : "leftHanded";
10776
+ if (property2 in props)
10777
+ throw new Error(
10778
+ `Duplicate or conflicting shaftcollar flag "${property2}"`
10779
+ );
10780
+ props[property2] = name !== "righthanded";
10781
+ continue;
10782
+ }
10836
10783
  const property = tokenProperties3[name];
10837
10784
  if (!property) throw new Error(`Unknown shaftcollar token "${token}"`);
10838
10785
  if (property in props)
10839
10786
  throw new Error(`Duplicate shaftcollar property "${property}"`);
10840
- const value = match[2];
10841
10787
  if (!value) throw new Error(`Token "${name}" requires a value`);
10842
- if (["mount", "threadHand", "threadClass"].includes(property)) {
10788
+ if (property === "threadClass") {
10843
10789
  const argument = value.match(/^\(([^()]+)\)$/);
10844
10790
  if (!argument)
10845
10791
  throw new Error(`Token "${name}" requires one parenthesized argument`);
10846
- props[property] = property === "threadClass" ? argument[1].toUpperCase() : argument[1].toLowerCase();
10792
+ props[property] = argument[1].toUpperCase();
10847
10793
  } else if (property === "metricSize") {
10848
10794
  if (!/^\d+(?:\.\d+)?$/.test(value))
10849
10795
  throw new Error("m requires a unitless metric designation");
@@ -10861,13 +10807,7 @@ function parseShaftCollarModelParams(raw) {
10861
10807
  var model42 = defineModel({
10862
10808
  name: "shaftcollar",
10863
10809
  schema: shaftCollarModelDefinitionSchema,
10864
- parse: parseShaftCollarModelParams,
10865
- normalizeString: (value) => normalizeModelStringFlags(
10866
- value,
10867
- stringFlags12,
10868
- parseShaftCollarModelParams,
10869
- omittedStringFlags12
10870
- )
10810
+ parse: parseShaftCollarModelParams
10871
10811
  });
10872
10812
  function register42(registry2) {
10873
10813
  registry2.register(model42);
@@ -11137,8 +11077,8 @@ var lengths18 = {
11137
11077
  groovedepth: "grooveDepth",
11138
11078
  splitwidth: "splitWidth"
11139
11079
  };
11140
- var flags8 = {};
11141
- var selectors6 = {};
11080
+ var flags9 = {};
11081
+ var selectors4 = {};
11142
11082
  var integers3 = {};
11143
11083
  var tuples3 = {};
11144
11084
  function parseSplitGrommetModelParams(raw) {
@@ -11156,9 +11096,9 @@ function parseSplitGrommetModelParams(raw) {
11156
11096
  if (!match) throw new Error(`Malformed splitgrommet token "${token}"`);
11157
11097
  const key = match[1].toLowerCase(), value = match[2];
11158
11098
  if (Object.hasOwn(lengths18, key) && value) assign(lengths18[key], value);
11159
- else if (Object.hasOwn(flags8, key) && !value) assign(flags8[key], true);
11160
- else if (Object.hasOwn(selectors6, key) && value.toLowerCase() === `(${selectors6[key].value})`)
11161
- assign(selectors6[key].property, true);
11099
+ else if (Object.hasOwn(flags9, key) && !value) assign(flags9[key], true);
11100
+ else if (Object.hasOwn(selectors4, key) && value.toLowerCase() === `(${selectors4[key].value})`)
11101
+ assign(selectors4[key].property, true);
11162
11102
  else if (Object.hasOwn(integers3, key) && /^\d+$/.test(value))
11163
11103
  assign(integers3[key], Number(value));
11164
11104
  else if (Object.hasOwn(tuples3, key)) {
@@ -11607,12 +11547,9 @@ var aliases17 = {
11607
11547
  barbh: "barbHeight",
11608
11548
  barbheight: "barbHeight"
11609
11549
  };
11610
- var flags9 = {
11550
+ var flags10 = {
11611
11551
  tee: "tee"
11612
11552
  };
11613
- var literals = {
11614
- profile: ["tee", "tee"]
11615
- };
11616
11553
  function parseTSlotCoverStripModelParams(raw) {
11617
11554
  const [name, ...tokens] = splitModelStringTokens(raw.string);
11618
11555
  if (raw.fn !== "tslotcoverstrip" || name?.toLowerCase() !== "tslotcoverstrip")
@@ -11629,15 +11566,10 @@ function parseTSlotCoverStripModelParams(raw) {
11629
11566
  const value = match?.[2];
11630
11567
  if (!key || value === void 0)
11631
11568
  throw new Error(`Malformed tslotcoverstrip token "${token}"`);
11632
- if (Object.hasOwn(flags9, key)) {
11569
+ if (Object.hasOwn(flags10, key)) {
11633
11570
  if (value !== "")
11634
11571
  throw new Error(`tslotcoverstrip flag "${key}" takes no value`);
11635
- assign(flags9[key], true);
11636
- } else if (Object.hasOwn(literals, key)) {
11637
- const [literal, property] = literals[key];
11638
- if (value.toLowerCase() !== `(${literal})`)
11639
- throw new Error(`Expected tslotcoverstrip ${key}(${literal})`);
11640
- assign(property, true);
11572
+ assign(flags10[key], true);
11641
11573
  } else if (Object.hasOwn(aliases17, key) && value) {
11642
11574
  const property = aliases17[key];
11643
11575
  assign(property, property === "pinCount" ? Number(value) : value);
@@ -11654,15 +11586,11 @@ var model49 = defineModel({
11654
11586
  function register49(registry2) {
11655
11587
  registry2.register(model49);
11656
11588
  }
11657
- var stringFlags13 = {
11658
- fourtsolid: "profile(fourtsolid)"
11659
- };
11660
- var omittedStringFlags13 = [];
11661
11589
  var shape44 = {
11662
11590
  width: positiveGearLengthSchema.default(20),
11663
11591
  height: positiveGearLengthSchema.default(20),
11664
11592
  length: positiveGearLengthSchema.default(100),
11665
- profile: external_exports.literal("fourtsolid").default("fourtsolid"),
11593
+ fourTSolid: external_exports.literal(true).default(true),
11666
11594
  slotWidth: positiveGearLengthSchema.default(6),
11667
11595
  pocketWidth: positiveGearLengthSchema.default(10),
11668
11596
  pocketDepth: positiveGearLengthSchema.default(2),
@@ -11722,9 +11650,7 @@ var lengths22 = {
11722
11650
  cornerradius: "cornerRadius"
11723
11651
  };
11724
11652
  function parseTSlotExtrusionModelParams(raw) {
11725
- const tokens = splitModelStringTokens(
11726
- expandModelStringFlags(raw.string, stringFlags13)
11727
- );
11653
+ const tokens = splitModelStringTokens(raw.string);
11728
11654
  if (raw.fn !== "tslotextrusion" || tokens[0]?.toLowerCase() !== raw.fn)
11729
11655
  throw new Error("Expected tslotextrusion without an inline value");
11730
11656
  const props = { fn: "tslotextrusion" };
@@ -11733,11 +11659,10 @@ function parseTSlotExtrusionModelParams(raw) {
11733
11659
  let property;
11734
11660
  let parsed = value;
11735
11661
  if (name in lengths22) property = lengths22[name];
11736
- else if (name === "profile") {
11737
- property = "profile";
11738
- const match = value.match(/^\(([a-z]+)\)$/i);
11739
- if (!match) throw new Error("Profile requires one parenthesized identity");
11740
- parsed = match[1].toLowerCase();
11662
+ else if (name === "fourtsolid") {
11663
+ property = "fourTSolid";
11664
+ if (value !== "") throw new Error("fourtsolid is a value-free flag");
11665
+ parsed = true;
11741
11666
  } else throw new Error(`Unknown T-slot extrusion token "${token}"`);
11742
11667
  if (property in props)
11743
11668
  throw new Error(`T-slot extrusion property "${property}" is repeated`);
@@ -11748,26 +11673,16 @@ function parseTSlotExtrusionModelParams(raw) {
11748
11673
  var model50 = defineModel({
11749
11674
  name: "tslotextrusion",
11750
11675
  schema: tSlotExtrusionModelDefinitionSchema,
11751
- parse: parseTSlotExtrusionModelParams,
11752
- normalizeString: (value) => normalizeModelStringFlags(
11753
- value,
11754
- stringFlags13,
11755
- parseTSlotExtrusionModelParams,
11756
- omittedStringFlags13
11757
- )
11676
+ parse: parseTSlotExtrusionModelParams
11758
11677
  });
11759
11678
  function register50(registry2) {
11760
11679
  registry2.register(model50);
11761
11680
  }
11762
- var stringFlags14 = {
11763
- righttriangle: "shape(righttriangle)"
11764
- };
11765
- var omittedStringFlags14 = [];
11766
11681
  var shape45 = {
11767
11682
  width: positiveGearLengthSchema.default(40),
11768
11683
  height: positiveGearLengthSchema.default(40),
11769
11684
  thickness: positiveGearLengthSchema.default(4),
11770
- shape: external_exports.literal("righttriangle").default("righttriangle"),
11685
+ rightTriangle: external_exports.literal(true).default(true),
11771
11686
  slotCount: external_exports.literal(2).default(2),
11772
11687
  /** Capsule width and overall length, including both semicircular ends. */
11773
11688
  slot: external_exports.tuple([positiveGearLengthSchema, positiveGearLengthSchema]).default([5, 12]),
@@ -11842,9 +11757,7 @@ var lengths23 = {
11842
11757
  edgemargin: "edgeMargin"
11843
11758
  };
11844
11759
  function parseTSlotGussetModelParams(raw) {
11845
- const tokens = splitModelStringTokens(
11846
- expandModelStringFlags(raw.string, stringFlags14)
11847
- );
11760
+ const tokens = splitModelStringTokens(raw.string);
11848
11761
  if (raw.fn !== "tslotgusset" || tokens[0]?.toLowerCase() !== raw.fn)
11849
11762
  throw new Error("Expected tslotgusset without an inline value");
11850
11763
  const props = { fn: "tslotgusset" };
@@ -11856,11 +11769,10 @@ function parseTSlotGussetModelParams(raw) {
11856
11769
  else if (name === "slots" || name === "slotcount") {
11857
11770
  property = "slotCount";
11858
11771
  parsed = parseGearInteger(value, "slotCount");
11859
- } else if (name === "shape") {
11860
- property = "shape";
11861
- const match = value.match(/^\(([a-z]+)\)$/i);
11862
- if (!match) throw new Error("Shape requires one parenthesized identity");
11863
- parsed = match[1].toLowerCase();
11772
+ } else if (name === "righttriangle") {
11773
+ property = "rightTriangle";
11774
+ if (value !== "") throw new Error("righttriangle is a value-free flag");
11775
+ parsed = true;
11864
11776
  } else if (name === "slot" || name === "centers") {
11865
11777
  property = name;
11866
11778
  const match = value.match(/^\(([^(),]+),([^(),]+)\)$/);
@@ -11876,13 +11788,7 @@ function parseTSlotGussetModelParams(raw) {
11876
11788
  var model51 = defineModel({
11877
11789
  name: "tslotgusset",
11878
11790
  schema: tSlotGussetModelDefinitionSchema,
11879
- parse: parseTSlotGussetModelParams,
11880
- normalizeString: (value) => normalizeModelStringFlags(
11881
- value,
11882
- stringFlags14,
11883
- parseTSlotGussetModelParams,
11884
- omittedStringFlags14
11885
- )
11791
+ parse: parseTSlotGussetModelParams
11886
11792
  });
11887
11793
  function register51(registry2) {
11888
11794
  registry2.register(model51);
@@ -12138,7 +12044,7 @@ function getNemaMotorReferencePoints(input) {
12138
12044
  p.bodyWidth / 2 / Math.max(Math.abs(x), Math.abs(y)),
12139
12045
  (p.bodyWidth - p.faceCornerChamfer) / (Math.abs(x) + Math.abs(y))
12140
12046
  );
12141
- if (p.nemaSize === 34 && p.cornerProfile === "stepped") {
12047
+ if (p.nemaSize === 34 && p.stepped) {
12142
12048
  const h2 = p.bodyWidth / 2, c = p.bodyCornerChamfer / Math.SQRT2, r = Math.min(4, c / 4);
12143
12049
  const contains = (distance2) => {
12144
12050
  const a = Math.abs(distance2 * x), b = Math.abs(distance2 * y);
@@ -12182,7 +12088,7 @@ function getNemaMotorReferencePoints(input) {
12182
12088
  },
12183
12089
  direction: { x, y, z: 0 }
12184
12090
  },
12185
- shaftflat: p.shaftShape === "d" ? {
12091
+ shaftflat: p.dShaft ? {
12186
12092
  position: {
12187
12093
  x: (p.shaftDiameter / 2 - p.shaftFlatDepth) * Math.cos(flatRadians),
12188
12094
  y: (p.shaftDiameter / 2 - p.shaftFlatDepth) * Math.sin(flatRadians),
@@ -13744,7 +13650,11 @@ function finishShaftMountMesh(geometry) {
13744
13650
  function createClampingShaftCollarMesh(input) {
13745
13651
  const props = clampingShaftCollarModelPropsSchema.parse(input);
13746
13652
  const dimensions5 = getClampingShaftCollarDimensions(props);
13747
- assertShaftMountResolution([dimensions5.threadedHole]);
13653
+ const threadedHole = {
13654
+ ...dimensions5.threadedHole,
13655
+ threadHand: dimensions5.threadedHole.leftHanded ? "left" : "right"
13656
+ };
13657
+ assertShaftMountResolution([threadedHole]);
13748
13658
  const body = createAnnularSleeve({
13749
13659
  outerRadius: props.outerDiameter / 2,
13750
13660
  boreARadius: props.boreDiameter / 2,
@@ -13770,7 +13680,7 @@ function createClampingShaftCollarMesh(input) {
13770
13680
  body,
13771
13681
  slit,
13772
13682
  createMountingHoleCutter(dimensions5.clearanceHole),
13773
- createMountingHoleCutter(dimensions5.threadedHole)
13683
+ createMountingHoleCutter(threadedHole)
13774
13684
  )
13775
13685
  );
13776
13686
  }
@@ -13955,7 +13865,7 @@ function createCompressionSpringMesh(input, options = {}) {
13955
13865
  }
13956
13866
  }
13957
13867
  const triangle = (a, b, c) => {
13958
- if (props.hand === "left") indices.push(a, c, b);
13868
+ if (props.leftHanded) indices.push(a, c, b);
13959
13869
  else indices.push(a, b, c);
13960
13870
  };
13961
13871
  for (let step = 0; step < steps; step++)
@@ -14690,7 +14600,7 @@ function createFlatHeadScrewMesh(input, options = {}) {
14690
14600
  levels.add(-p.length + (shaftEnd + p.length) * i / steps);
14691
14601
  for (const z of [...levels].sort((a, b) => a - b)) {
14692
14602
  const r = add((theta) => {
14693
- const phase = (((z + p.length) / pitch - (p.threadHand === "right" ? 1 : -1) * theta / (2 * Math.PI)) % 1 + 1) % 1;
14603
+ const phase = (((z + p.length) / pitch - (p.leftHanded ? -1 : 1) * theta / (2 * Math.PI)) % 1 + 1) % 1;
14694
14604
  const d = Math.min(phase, 1 - phase);
14695
14605
  const groove = Math.min(
14696
14606
  major - minor,
@@ -14890,6 +14800,11 @@ var resolveFlexScreenSize = ({
14890
14800
  };
14891
14801
  };
14892
14802
  var resolveOrientation = (props) => {
14803
+ if ("orientation" in props) {
14804
+ throw new Error(
14805
+ "FlexScreen orientation is no longer supported; use a boolean placement flag"
14806
+ );
14807
+ }
14893
14808
  const shortcuts = [
14894
14809
  ["sitsFlat", props.sitsFlat],
14895
14810
  ["sitsFlatBelowBoard", props.sitsFlatBelowBoard],
@@ -14899,13 +14814,24 @@ var resolveOrientation = (props) => {
14899
14814
  ["foldedToFaceBelowBoard", props.foldsBelowBoard],
14900
14815
  ["foldedToRightAngleAboveBoard", props.foldedToRightAngleAboveBoard],
14901
14816
  ["foldedToRightAngleBelowBoard", props.foldedToRightAngleBelowBoard]
14902
- ].filter((entry) => entry[1]);
14903
- if (shortcuts.length > 1) {
14817
+ ];
14818
+ for (const [name, value] of shortcuts) {
14819
+ if (value !== void 0 && typeof value !== "boolean") {
14820
+ throw new Error(`FlexScreen placement flag "${name}" must be a boolean`);
14821
+ }
14822
+ }
14823
+ const selected = shortcuts.filter((entry) => entry[1] === true);
14824
+ if (selected.length > 1) {
14904
14825
  throw new Error(
14905
14826
  "Only one FlexScreen boolean orientation shortcut can be true"
14906
14827
  );
14907
14828
  }
14908
- return shortcuts[0]?.[0] ?? props.orientation ?? "sitsFlat";
14829
+ if (selected.length === 0 && shortcuts.some((entry) => entry[1] !== void 0)) {
14830
+ throw new Error(
14831
+ "A FlexScreen orientation flag must be true when placement flags are supplied"
14832
+ );
14833
+ }
14834
+ return selected[0]?.[0] ?? "sitsFlat";
14909
14835
  };
14910
14836
  var distance = (a, b) => Math.hypot(b[0] - a[0], b[1] - a[1], b[2] - a[2]);
14911
14837
  var interpolate = (a, b, progress) => [
@@ -15777,7 +15703,7 @@ function createTwistedSpurGearMesh(input, twist = 0, segmentsPerTurn = 32) {
15777
15703
  function createHelicalGearMesh(input) {
15778
15704
  const props = helicalGearModelPropsSchema.parse(input);
15779
15705
  const { twistAngle } = getHelicalGearDimensions(props);
15780
- const { helixAngle, handedness, segmentsPerTurn, ...spur } = props;
15706
+ const { helixAngle, leftHanded, segmentsPerTurn, ...spur } = props;
15781
15707
  return createTwistedSpurGearMesh(
15782
15708
  spur,
15783
15709
  twistAngle * Math.PI / 180,
@@ -15880,7 +15806,7 @@ function createHexBoltMesh(input, options = {}) {
15880
15806
  levels.add(-p.length + (shaftEnd + p.length) * i / steps);
15881
15807
  for (const z of [...levels].sort((a, b) => a - b)) {
15882
15808
  const r = add((theta) => {
15883
- const phase = (((z + p.length) / pitch - (p.threadHand === "right" ? 1 : -1) * theta / (2 * Math.PI)) % 1 + 1) % 1;
15809
+ const phase = (((z + p.length) / pitch - (p.leftHanded ? -1 : 1) * theta / (2 * Math.PI)) % 1 + 1) % 1;
15884
15810
  const d = Math.min(phase, 1 - phase);
15885
15811
  const groove = Math.min(
15886
15812
  major - minor,
@@ -16510,14 +16436,14 @@ var resolveNemaMotorProps = nemaMotorModelPropsSchema.parse.bind(nemaMotorModelP
16510
16436
  // lib/utils/nemaMotorWireGeometry.ts
16511
16437
  function createNemaMotorWireGeometry(input) {
16512
16438
  const p = resolveNemaMotorProps(input);
16513
- if (p.wireConnection === "none") return [];
16439
+ if (p.noWires) return [];
16514
16440
  const { position } = getNemaMotorReferencePoints(p).wireside;
16515
16441
  const angle = p.wireSideAngle * Math.PI / 180;
16516
16442
  const place = (geometry) => jscad8.transforms.translate(
16517
16443
  [position.x, position.y, position.z],
16518
16444
  jscad8.transforms.rotateZ(angle, geometry)
16519
16445
  );
16520
- if (p.wireConnection === "stubs") {
16446
+ if (p.wireStubs) {
16521
16447
  const colors = [
16522
16448
  "#d53f3f",
16523
16449
  "#2463af",
@@ -16663,11 +16589,11 @@ function createNemaMotorSections(input) {
16663
16589
  p.bodyWidth,
16664
16590
  p.faceCornerChamfer
16665
16591
  );
16666
- const profile6 = p.cornerProfile === "stepped" ? steppedFace : face;
16592
+ const profile6 = p.stepped ? steppedFace : face;
16667
16593
  const core = profile6(p.bodyWidth, p.bodyCornerChamfer);
16668
16594
  const rear = profile6(
16669
16595
  p.bodyWidth,
16670
- p.rearCornerChamfer ?? (p.backFace === "plain" && p.mountingHoleThrough ? p.bodyCornerChamfer : p.faceCornerChamfer)
16596
+ p.rearCornerChamfer ?? (p.backFacePlain && p.mountingHoleThrough ? p.bodyCornerChamfer : p.faceCornerChamfer)
16671
16597
  );
16672
16598
  const h2 = p.mountingHoleSpacing / 2;
16673
16599
  const centers = [
@@ -16683,7 +16609,7 @@ function createNemaMotorSections(input) {
16683
16609
  add("frontCap", front, -holeDepth, 0, holes);
16684
16610
  add("frontCap", front, -p.frontCapLength, -holeDepth);
16685
16611
  add("body", core, -p.bodyLength + p.rearCapLength, -p.frontCapLength);
16686
- if (p.backFace === "plain") {
16612
+ if (p.backFacePlain) {
16687
16613
  add("rearCap", rear, -p.bodyLength, -p.bodyLength + p.rearCapLength);
16688
16614
  } else {
16689
16615
  const halfPitch = p.backFaceHoleSpacing / 2;
@@ -16709,8 +16635,7 @@ function createNemaMotorSections(input) {
16709
16635
  add("pilot", circle(p.pilotDiameter / 2), 0, p.pilotLength);
16710
16636
  const r = p.shaftDiameter / 2;
16711
16637
  const round = circle(r);
16712
- if (p.shaftShape === "round")
16713
- add("shaft", round, p.pilotLength, p.shaftLength);
16638
+ if (p.roundShaft) add("shaft", round, p.pilotLength, p.shaftLength);
16714
16639
  else {
16715
16640
  const cut = r - p.shaftFlatDepth;
16716
16641
  const angle = Math.acos(cut / r);
@@ -16739,7 +16664,7 @@ function NemaMotor({
16739
16664
  ...props
16740
16665
  }) {
16741
16666
  const p = resolveNemaMotorProps(props);
16742
- const screw = p.backFace === "screws" ? jscad9.transforms.rotateX(
16667
+ const screw = p.backFaceScrews ? jscad9.transforms.rotateX(
16743
16668
  Math.PI,
16744
16669
  createHexSocketBoltGeom({
16745
16670
  metricSize: p.backFaceScrewSize,
@@ -17048,7 +16973,7 @@ function createPanScrewMesh(input, options = {}) {
17048
16973
  levels.add(-p.length + (shaftEnd + p.length) * i / steps);
17049
16974
  for (const z of [...levels].sort((a, b) => a - b)) {
17050
16975
  const r = add((theta) => {
17051
- const phase = (((z + p.length) / pitch - (p.threadHand === "right" ? 1 : -1) * theta / (2 * Math.PI)) % 1 + 1) % 1;
16976
+ const phase = (((z + p.length) / pitch - (p.leftHanded ? -1 : 1) * theta / (2 * Math.PI)) % 1 + 1) % 1;
17052
16977
  const d = Math.min(phase, 1 - phase);
17053
16978
  const groove = Math.min(
17054
16979
  major - minor,
@@ -17788,7 +17713,11 @@ import "@jscad/modeling";
17788
17713
  function createRigidCouplerMesh(input) {
17789
17714
  const props = rigidCouplerModelPropsSchema.parse(input);
17790
17715
  const dimensions5 = getRigidCouplerDimensions(props);
17791
- assertShaftMountResolution(dimensions5.screwHoles);
17716
+ const screwHoles = dimensions5.screwHoles.map((hole) => ({
17717
+ ...hole,
17718
+ threadHand: hole.leftHanded ? "left" : "right"
17719
+ }));
17720
+ assertShaftMountResolution(screwHoles);
17792
17721
  const body = createAnnularSleeve({
17793
17722
  outerRadius: props.outerDiameter / 2,
17794
17723
  boreARadius: props.boreDiameter / 2,
@@ -17798,10 +17727,7 @@ function createRigidCouplerMesh(input) {
17798
17727
  stepZ: dimensions5.boreADepth
17799
17728
  });
17800
17729
  return finishShaftMountMesh(
17801
- subtractShaftMountParts(
17802
- body,
17803
- ...dimensions5.screwHoles.map(createMountingHoleCutter)
17804
- )
17730
+ subtractShaftMountParts(body, ...screwHoles.map(createMountingHoleCutter))
17805
17731
  );
17806
17732
  }
17807
17733
 
@@ -17954,7 +17880,11 @@ import "@jscad/modeling";
17954
17880
  function createShaftCollarMesh(input) {
17955
17881
  const props = shaftCollarModelPropsSchema.parse(input);
17956
17882
  const dimensions5 = getShaftCollarDimensions(props);
17957
- assertShaftMountResolution([dimensions5.screwHole]);
17883
+ const screwHole = {
17884
+ ...dimensions5.screwHole,
17885
+ threadHand: dimensions5.screwHole.leftHanded ? "left" : "right"
17886
+ };
17887
+ assertShaftMountResolution([screwHole]);
17958
17888
  const body = createAnnularSleeve({
17959
17889
  outerRadius: props.outerDiameter / 2,
17960
17890
  boreARadius: props.boreDiameter / 2,
@@ -17962,10 +17892,7 @@ function createShaftCollarMesh(input) {
17962
17892
  chamfer: props.chamfer
17963
17893
  });
17964
17894
  return finishShaftMountMesh(
17965
- subtractShaftMountParts(
17966
- body,
17967
- createMountingHoleCutter(dimensions5.screwHole)
17968
- )
17895
+ subtractShaftMountParts(body, createMountingHoleCutter(screwHole))
17969
17896
  );
17970
17897
  }
17971
17898
 
@@ -17991,11 +17918,11 @@ function register92(registry2) {
17991
17918
  // lib/mechanical/sheet-metal-mesh.ts
17992
17919
  import earcut5 from "earcut";
17993
17920
  function holeOutline(hole) {
17994
- const radius = (hole.shape === "round" ? hole.diameter : hole.width) / 2;
17995
- const straight = hole.shape === "slot" ? (hole.length - hole.width) / 2 : 0;
17921
+ const radius = (hole.round ? hole.diameter : hole.width) / 2;
17922
+ const straight = hole.slot ? (hole.length - hole.width) / 2 : 0;
17996
17923
  if (straight < 0) throw new Error("Slot length must be at least its width");
17997
17924
  return Array.from({ length: 64 }, (_, i) => {
17998
- if (hole.shape === "round") {
17925
+ if (hole.round) {
17999
17926
  const angle2 = i * Math.PI / 32;
18000
17927
  return {
18001
17928
  u: hole.u + radius * Math.cos(angle2),
@@ -18006,12 +17933,13 @@ function holeOutline(hole) {
18006
17933
  const angle = -Math.PI / 2 + (i < 32 ? i : i - 32) * Math.PI / 31 + (i < 32 ? 0 : Math.PI);
18007
17934
  const along = half * straight + radius * Math.cos(angle);
18008
17935
  const across = radius * Math.sin(angle);
18009
- return hole.shape === "slot" && hole.axis === "v" ? { u: hole.u - across, v: hole.v + along } : { u: hole.u + along, v: hole.v + across };
17936
+ return hole.slot && hole.axis === "v" ? { u: hole.u - across, v: hole.v + along } : { u: hole.u + along, v: hole.v + across };
18010
17937
  });
18011
17938
  }
18012
17939
  function createSheetMetalMesh(input) {
18013
17940
  const props = sheetMetalModelPropsSchema.parse(input);
18014
- const { width: width10, baseLength, flangeHeight, thickness, profile: profile6 } = props;
17941
+ const { width: width10, baseLength, flangeHeight, thickness } = props;
17942
+ const profile6 = props.channel ? "channel" : props.angle ? "angle" : "plate";
18015
17943
  const radius = props.insideBendRadius + thickness / 2;
18016
17944
  const positions = [];
18017
17945
  const indices = [];
@@ -19154,7 +19082,7 @@ var createWormGearMesh = (input) => {
19154
19082
  const positions = [];
19155
19083
  const indices = [];
19156
19084
  const phase = props.phase % 360 * Math.PI / 180;
19157
- const direction = props.handedness === "right" ? 1 : -1;
19085
+ const direction = props.leftHanded ? -1 : 1;
19158
19086
  const ring = (z) => {
19159
19087
  const first = positions.length / 3;
19160
19088
  const rotation = phase + direction * (z / lead) * Math.PI * 2;