@warlock.js/seal 5.10.0 → 5.11.0

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/CHANGELOG.md CHANGED
@@ -4,6 +4,12 @@ All notable changes to `@warlock.js/seal` are documented in this file.
4
4
 
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). `@warlock.js/*` packages are released in lockstep — every package shares the same version number, so a version below may list only the changes that affected this package.
6
6
 
7
+ ## 5.11.0 - 2026-09-14
8
+
9
+ ### Fixed
10
+
11
+ - `v.boolean().accepted()` / `.declined()` (and their conditional variants) rejected every string form they advertised — `"yes"`, `"on"`, `"1"` — because the boolean type rule ran first. They now parse those form values into a real boolean.
12
+
7
13
  ## 5.10.0 - 2026-09-14
8
14
 
9
15
  ### Added
package/cjs/index.cjs CHANGED
@@ -1127,6 +1127,238 @@ const removeEmptyArrayElementsMutator = async (value) => {
1127
1127
  return value.filter((item) => !isEmptyValue(item));
1128
1128
  };
1129
1129
 
1130
+ //#endregion
1131
+ //#region ../seal/src/rules/scalar/accepted-rule.ts
1132
+ /**
1133
+ * The full set of values treated as "accepted" by `acceptedRule` and its
1134
+ * conditional variants. Shared with `formBooleanMutator` (see
1135
+ * `../../mutators/boolean-mutators`) so `v.boolean().accepted()` recognizes
1136
+ * exactly this list — single source of truth, no duplicated literals.
1137
+ */
1138
+ const ACCEPTED_VALUES = [
1139
+ "1",
1140
+ "true",
1141
+ "yes",
1142
+ "y",
1143
+ "on",
1144
+ 1,
1145
+ true,
1146
+ "Yes",
1147
+ "Y",
1148
+ "On"
1149
+ ];
1150
+ const isAcceptedValue = (value) => {
1151
+ return ACCEPTED_VALUES.includes(value);
1152
+ };
1153
+ /**
1154
+ * Validate value as accepted if it equals:
1155
+ * 1 | "1" | true | "true" | "yes" | "y" | "on"
1156
+ */
1157
+ const acceptedRule = {
1158
+ name: "accepted",
1159
+ defaultErrorMessage: "The :input must be accepted",
1160
+ description: "The value must be accepted if it equals: 1 | '1' | true | 'true' | 'yes' | 'y' | 'on' | 1 | true | 'Yes' | 'Y' | 'On'",
1161
+ async validate(value, context) {
1162
+ if (isAcceptedValue(value)) return VALID_RULE;
1163
+ return invalidRule(this, context);
1164
+ }
1165
+ };
1166
+ /**
1167
+ * Accepted value if another field's value equals to a specific value
1168
+ */
1169
+ const acceptedIfRule = {
1170
+ name: "acceptedIf",
1171
+ description: "The field must be accepted if :field's value equals to :value",
1172
+ defaultErrorMessage: "The :input must be accepted",
1173
+ async validate(value, context) {
1174
+ const fieldValue = getFieldValue(this, context);
1175
+ const { value: expectedValue } = this.context.options;
1176
+ this.context.translatableParams.field = this.context.options.field;
1177
+ this.context.translatableParams.value = this.context.options.value;
1178
+ if (fieldValue !== expectedValue) return invalidRule(this, context);
1179
+ if (!isAcceptedValue(value)) return invalidRule(this, context);
1180
+ return VALID_RULE;
1181
+ }
1182
+ };
1183
+ /**
1184
+ * Accepted if another field is not equal to the given value
1185
+ */
1186
+ const acceptedUnlessRule = {
1187
+ name: "acceptedUnless",
1188
+ description: "The field must be accepted if :field's value is not equal to :value",
1189
+ defaultErrorMessage: "The :input must be accepted",
1190
+ async validate(value, context) {
1191
+ const fieldValue = getFieldValue(this, context);
1192
+ const { value: expectedValue } = this.context.options;
1193
+ this.context.translatableParams.field = this.context.options.field;
1194
+ this.context.translatableParams.value = this.context.options.value;
1195
+ if (fieldValue === expectedValue) return invalidRule(this, context);
1196
+ if (!isAcceptedValue(value)) return invalidRule(this, context);
1197
+ return VALID_RULE;
1198
+ }
1199
+ };
1200
+ /**
1201
+ * Accepted if another field is required
1202
+ */
1203
+ const acceptedIfRequiredRule = {
1204
+ name: "acceptedIfRequired",
1205
+ description: "The field must be accepted if :field is required",
1206
+ defaultErrorMessage: "The :input must be accepted",
1207
+ async validate(value, context) {
1208
+ const fieldValue = getFieldValue(this, context);
1209
+ this.context.translatableParams.field = this.context.options.field;
1210
+ if (isEmptyValue(fieldValue)) return invalidRule(this, context);
1211
+ if (!isAcceptedValue(value)) return invalidRule(this, context);
1212
+ return VALID_RULE;
1213
+ }
1214
+ };
1215
+ /**
1216
+ * Accepted if another field is present
1217
+ */
1218
+ const acceptedIfPresentRule = {
1219
+ name: "acceptedIfPresent",
1220
+ description: "The field must be accepted if :field is present",
1221
+ defaultErrorMessage: "The :input must be accepted",
1222
+ async validate(value, context) {
1223
+ const fieldValue = getFieldValue(this, context);
1224
+ this.context.translatableParams.field = this.context.options.field;
1225
+ if (fieldValue === void 0) return invalidRule(this, context);
1226
+ if (!isAcceptedValue(value)) return invalidRule(this, context);
1227
+ return VALID_RULE;
1228
+ }
1229
+ };
1230
+ /**
1231
+ * Accepted if another field is missing
1232
+ */
1233
+ const acceptedWithoutRule = {
1234
+ name: "acceptedWithout",
1235
+ description: "The field must be accepted if :field is missing",
1236
+ defaultErrorMessage: "The :input must be accepted",
1237
+ async validate(value, context) {
1238
+ const fieldValue = getFieldValue(this, context);
1239
+ this.context.translatableParams.field = this.context.options.field;
1240
+ if (fieldValue !== void 0) return invalidRule(this, context);
1241
+ if (!isAcceptedValue(value)) return invalidRule(this, context);
1242
+ return VALID_RULE;
1243
+ }
1244
+ };
1245
+
1246
+ //#endregion
1247
+ //#region ../seal/src/rules/scalar/declined-rule.ts
1248
+ /**
1249
+ * The full set of values treated as "declined" by `declinedRule` and its
1250
+ * conditional variants. Shared with `formBooleanMutator` (see
1251
+ * `../../mutators/boolean-mutators`) so `v.boolean().declined()` recognizes
1252
+ * exactly this list — single source of truth, no duplicated literals.
1253
+ */
1254
+ const DECLINED_VALUES = [
1255
+ "0",
1256
+ "false",
1257
+ "no",
1258
+ "n",
1259
+ "off",
1260
+ 0,
1261
+ false,
1262
+ "No",
1263
+ "N",
1264
+ "Off"
1265
+ ];
1266
+ const isDeclinedValue = (value) => {
1267
+ return DECLINED_VALUES.includes(value);
1268
+ };
1269
+ /**
1270
+ * Validate value as declined if it equals:
1271
+ * 0 | "0" | false | "false" | "no" | "n" | "off" | 0 | false | "No" | "N" | "Off"
1272
+ */
1273
+ const declinedRule = {
1274
+ name: "declined",
1275
+ defaultErrorMessage: "The :input must be declined",
1276
+ description: "The value must be declined if it equals: 0 | '0' | false | 'false' | 'no' | 'n' | 'off' | 0 | false | 'No' | 'N' | 'Off'",
1277
+ async validate(value, context) {
1278
+ if (isDeclinedValue(value)) return VALID_RULE;
1279
+ return invalidRule(this, context);
1280
+ }
1281
+ };
1282
+ /**
1283
+ * Declined value if another field's value equals to a specific value
1284
+ */
1285
+ const declinedIfRule = {
1286
+ name: "declinedIf",
1287
+ description: "The field must be declined if :field's value equals to :value",
1288
+ defaultErrorMessage: "The :input must be declined",
1289
+ async validate(value, context) {
1290
+ const fieldValue = getFieldValue(this, context);
1291
+ const { value: expectedValue } = this.context.options;
1292
+ this.context.translatableParams.field = this.context.options.field;
1293
+ this.context.translatableParams.value = this.context.options.value;
1294
+ if (fieldValue !== expectedValue) return invalidRule(this, context);
1295
+ if (!isDeclinedValue(value)) return invalidRule(this, context);
1296
+ return VALID_RULE;
1297
+ }
1298
+ };
1299
+ /**
1300
+ * Declined if another field is not equal to the given value
1301
+ */
1302
+ const declinedUnlessRule = {
1303
+ name: "declinedUnless",
1304
+ description: "The field must be declined if :field's value is not equal to :value",
1305
+ defaultErrorMessage: "The :input must be declined",
1306
+ async validate(value, context) {
1307
+ const fieldValue = getFieldValue(this, context);
1308
+ const { value: expectedValue } = this.context.options;
1309
+ this.context.translatableParams.field = this.context.options.field;
1310
+ this.context.translatableParams.value = this.context.options.value;
1311
+ if (fieldValue === expectedValue) return invalidRule(this, context);
1312
+ if (!isDeclinedValue(value)) return invalidRule(this, context);
1313
+ return VALID_RULE;
1314
+ }
1315
+ };
1316
+ /**
1317
+ * Declined if another field is required
1318
+ */
1319
+ const declinedIfRequiredRule = {
1320
+ name: "declinedIfRequired",
1321
+ description: "The field must be declined if :field is required",
1322
+ defaultErrorMessage: "The :input must be declined",
1323
+ async validate(value, context) {
1324
+ const fieldValue = getFieldValue(this, context);
1325
+ this.context.translatableParams.field = this.context.options.field;
1326
+ if (isEmptyValue(fieldValue)) return invalidRule(this, context);
1327
+ if (!isDeclinedValue(value)) return invalidRule(this, context);
1328
+ return VALID_RULE;
1329
+ }
1330
+ };
1331
+ /**
1332
+ * Declined if another field is present
1333
+ */
1334
+ const declinedIfPresentRule = {
1335
+ name: "declinedIfPresent",
1336
+ description: "The field must be declined if :field is present",
1337
+ defaultErrorMessage: "The :input must be declined",
1338
+ async validate(value, context) {
1339
+ const fieldValue = getFieldValue(this, context);
1340
+ this.context.translatableParams.field = this.context.options.field;
1341
+ if (fieldValue === void 0) return invalidRule(this, context);
1342
+ if (!isDeclinedValue(value)) return invalidRule(this, context);
1343
+ return VALID_RULE;
1344
+ }
1345
+ };
1346
+ /**
1347
+ * Declined if another field is missing
1348
+ */
1349
+ const declinedWithoutRule = {
1350
+ name: "declinedWithout",
1351
+ description: "The field must be declined if :field is missing",
1352
+ defaultErrorMessage: "The :input must be declined",
1353
+ async validate(value, context) {
1354
+ const fieldValue = getFieldValue(this, context);
1355
+ this.context.translatableParams.field = this.context.options.field;
1356
+ if (fieldValue !== void 0) return invalidRule(this, context);
1357
+ if (!isDeclinedValue(value)) return invalidRule(this, context);
1358
+ return VALID_RULE;
1359
+ }
1360
+ };
1361
+
1130
1362
  //#endregion
1131
1363
  //#region ../seal/src/mutators/boolean-mutators.ts
1132
1364
  /**
@@ -1141,6 +1373,26 @@ const booleanCoerceMutator = async (value) => {
1141
1373
  if (value === "false" || value === "0" || value === 0) return false;
1142
1374
  return value;
1143
1375
  };
1376
+ /**
1377
+ * Parse form-shaped boolean values into a real boolean, ahead of the type
1378
+ * rule.
1379
+ *
1380
+ * Opted into by calling any `accepted*`/`declined*` method on
1381
+ * `v.boolean()` (see `BooleanValidator`'s `withFormBooleanMutator`). Converts
1382
+ * every value in `ACCEPTED_VALUES` (`1`, `"1"`, `true`, `"true"`, `"yes"`,
1383
+ * `"y"`, `"on"`, `"Yes"`, `"Y"`, `"On"`) to `true`, and every value in
1384
+ * `DECLINED_VALUES` (`0`, `"0"`, `false`, `"false"`, `"no"`, `"n"`, `"off"`,
1385
+ * `"No"`, `"N"`, `"Off"`) to `false`. Any other value passes through
1386
+ * unchanged so the boolean type rule still rejects it.
1387
+ *
1388
+ * Named (not anonymous) so callers can detect whether it has already been
1389
+ * added — see the idempotence check in `BooleanValidator`.
1390
+ */
1391
+ const formBooleanMutator = async (value) => {
1392
+ if (ACCEPTED_VALUES.includes(value)) return true;
1393
+ if (DECLINED_VALUES.includes(value)) return false;
1394
+ return value;
1395
+ };
1144
1396
 
1145
1397
  //#endregion
1146
1398
  //#region ../seal/src/mutators/date-mutators.ts
@@ -5499,224 +5751,6 @@ var PrimitiveValidator = class extends BaseValidator {
5499
5751
  }
5500
5752
  };
5501
5753
 
5502
- //#endregion
5503
- //#region ../seal/src/rules/scalar/accepted-rule.ts
5504
- const isAcceptedValue = (value) => {
5505
- return [
5506
- "1",
5507
- "true",
5508
- "yes",
5509
- "y",
5510
- "on",
5511
- 1,
5512
- true,
5513
- "Yes",
5514
- "Y",
5515
- "On"
5516
- ].includes(value);
5517
- };
5518
- /**
5519
- * Validate value as accepted if it equals:
5520
- * 1 | "1" | true | "true" | "yes" | "y" | "on"
5521
- */
5522
- const acceptedRule = {
5523
- name: "accepted",
5524
- defaultErrorMessage: "The :input must be accepted",
5525
- description: "The value must be accepted if it equals: 1 | '1' | true | 'true' | 'yes' | 'y' | 'on' | 1 | true | 'Yes' | 'Y' | 'On'",
5526
- async validate(value, context) {
5527
- if (isAcceptedValue(value)) return VALID_RULE;
5528
- return invalidRule(this, context);
5529
- }
5530
- };
5531
- /**
5532
- * Accepted value if another field's value equals to a specific value
5533
- */
5534
- const acceptedIfRule = {
5535
- name: "acceptedIf",
5536
- description: "The field must be accepted if :field's value equals to :value",
5537
- defaultErrorMessage: "The :input must be accepted",
5538
- async validate(value, context) {
5539
- const fieldValue = getFieldValue(this, context);
5540
- const { value: expectedValue } = this.context.options;
5541
- this.context.translatableParams.field = this.context.options.field;
5542
- this.context.translatableParams.value = this.context.options.value;
5543
- if (fieldValue !== expectedValue) return invalidRule(this, context);
5544
- if (!isAcceptedValue(value)) return invalidRule(this, context);
5545
- return VALID_RULE;
5546
- }
5547
- };
5548
- /**
5549
- * Accepted if another field is not equal to the given value
5550
- */
5551
- const acceptedUnlessRule = {
5552
- name: "acceptedUnless",
5553
- description: "The field must be accepted if :field's value is not equal to :value",
5554
- defaultErrorMessage: "The :input must be accepted",
5555
- async validate(value, context) {
5556
- const fieldValue = getFieldValue(this, context);
5557
- const { value: expectedValue } = this.context.options;
5558
- this.context.translatableParams.field = this.context.options.field;
5559
- this.context.translatableParams.value = this.context.options.value;
5560
- if (fieldValue === expectedValue) return invalidRule(this, context);
5561
- if (!isAcceptedValue(value)) return invalidRule(this, context);
5562
- return VALID_RULE;
5563
- }
5564
- };
5565
- /**
5566
- * Accepted if another field is required
5567
- */
5568
- const acceptedIfRequiredRule = {
5569
- name: "acceptedIfRequired",
5570
- description: "The field must be accepted if :field is required",
5571
- defaultErrorMessage: "The :input must be accepted",
5572
- async validate(value, context) {
5573
- const fieldValue = getFieldValue(this, context);
5574
- this.context.translatableParams.field = this.context.options.field;
5575
- if (isEmptyValue(fieldValue)) return invalidRule(this, context);
5576
- if (!isAcceptedValue(value)) return invalidRule(this, context);
5577
- return VALID_RULE;
5578
- }
5579
- };
5580
- /**
5581
- * Accepted if another field is present
5582
- */
5583
- const acceptedIfPresentRule = {
5584
- name: "acceptedIfPresent",
5585
- description: "The field must be accepted if :field is present",
5586
- defaultErrorMessage: "The :input must be accepted",
5587
- async validate(value, context) {
5588
- const fieldValue = getFieldValue(this, context);
5589
- this.context.translatableParams.field = this.context.options.field;
5590
- if (fieldValue === void 0) return invalidRule(this, context);
5591
- if (!isAcceptedValue(value)) return invalidRule(this, context);
5592
- return VALID_RULE;
5593
- }
5594
- };
5595
- /**
5596
- * Accepted if another field is missing
5597
- */
5598
- const acceptedWithoutRule = {
5599
- name: "acceptedWithout",
5600
- description: "The field must be accepted if :field is missing",
5601
- defaultErrorMessage: "The :input must be accepted",
5602
- async validate(value, context) {
5603
- const fieldValue = getFieldValue(this, context);
5604
- this.context.translatableParams.field = this.context.options.field;
5605
- if (fieldValue !== void 0) return invalidRule(this, context);
5606
- if (!isAcceptedValue(value)) return invalidRule(this, context);
5607
- return VALID_RULE;
5608
- }
5609
- };
5610
-
5611
- //#endregion
5612
- //#region ../seal/src/rules/scalar/declined-rule.ts
5613
- const isDeclinedValue = (value) => {
5614
- return [
5615
- "0",
5616
- "false",
5617
- "no",
5618
- "n",
5619
- "off",
5620
- 0,
5621
- false,
5622
- "No",
5623
- "N",
5624
- "Off"
5625
- ].includes(value);
5626
- };
5627
- /**
5628
- * Validate value as declined if it equals:
5629
- * 0 | "0" | false | "false" | "no" | "n" | "off" | 0 | false | "No" | "N" | "Off"
5630
- */
5631
- const declinedRule = {
5632
- name: "declined",
5633
- defaultErrorMessage: "The :input must be declined",
5634
- description: "The value must be declined if it equals: 0 | '0' | false | 'false' | 'no' | 'n' | 'off' | 0 | false | 'No' | 'N' | 'Off'",
5635
- async validate(value, context) {
5636
- if (isDeclinedValue(value)) return VALID_RULE;
5637
- return invalidRule(this, context);
5638
- }
5639
- };
5640
- /**
5641
- * Declined value if another field's value equals to a specific value
5642
- */
5643
- const declinedIfRule = {
5644
- name: "declinedIf",
5645
- description: "The field must be declined if :field's value equals to :value",
5646
- defaultErrorMessage: "The :input must be declined",
5647
- async validate(value, context) {
5648
- const fieldValue = getFieldValue(this, context);
5649
- const { value: expectedValue } = this.context.options;
5650
- this.context.translatableParams.field = this.context.options.field;
5651
- this.context.translatableParams.value = this.context.options.value;
5652
- if (fieldValue !== expectedValue) return invalidRule(this, context);
5653
- if (!isDeclinedValue(value)) return invalidRule(this, context);
5654
- return VALID_RULE;
5655
- }
5656
- };
5657
- /**
5658
- * Declined if another field is not equal to the given value
5659
- */
5660
- const declinedUnlessRule = {
5661
- name: "declinedUnless",
5662
- description: "The field must be declined if :field's value is not equal to :value",
5663
- defaultErrorMessage: "The :input must be declined",
5664
- async validate(value, context) {
5665
- const fieldValue = getFieldValue(this, context);
5666
- const { value: expectedValue } = this.context.options;
5667
- this.context.translatableParams.field = this.context.options.field;
5668
- this.context.translatableParams.value = this.context.options.value;
5669
- if (fieldValue === expectedValue) return invalidRule(this, context);
5670
- if (!isDeclinedValue(value)) return invalidRule(this, context);
5671
- return VALID_RULE;
5672
- }
5673
- };
5674
- /**
5675
- * Declined if another field is required
5676
- */
5677
- const declinedIfRequiredRule = {
5678
- name: "declinedIfRequired",
5679
- description: "The field must be declined if :field is required",
5680
- defaultErrorMessage: "The :input must be declined",
5681
- async validate(value, context) {
5682
- const fieldValue = getFieldValue(this, context);
5683
- this.context.translatableParams.field = this.context.options.field;
5684
- if (isEmptyValue(fieldValue)) return invalidRule(this, context);
5685
- if (!isDeclinedValue(value)) return invalidRule(this, context);
5686
- return VALID_RULE;
5687
- }
5688
- };
5689
- /**
5690
- * Declined if another field is present
5691
- */
5692
- const declinedIfPresentRule = {
5693
- name: "declinedIfPresent",
5694
- description: "The field must be declined if :field is present",
5695
- defaultErrorMessage: "The :input must be declined",
5696
- async validate(value, context) {
5697
- const fieldValue = getFieldValue(this, context);
5698
- this.context.translatableParams.field = this.context.options.field;
5699
- if (fieldValue === void 0) return invalidRule(this, context);
5700
- if (!isDeclinedValue(value)) return invalidRule(this, context);
5701
- return VALID_RULE;
5702
- }
5703
- };
5704
- /**
5705
- * Declined if another field is missing
5706
- */
5707
- const declinedWithoutRule = {
5708
- name: "declinedWithout",
5709
- description: "The field must be declined if :field is missing",
5710
- defaultErrorMessage: "The :input must be declined",
5711
- async validate(value, context) {
5712
- const fieldValue = getFieldValue(this, context);
5713
- this.context.translatableParams.field = this.context.options.field;
5714
- if (fieldValue !== void 0) return invalidRule(this, context);
5715
- if (!isDeclinedValue(value)) return invalidRule(this, context);
5716
- return VALID_RULE;
5717
- }
5718
- };
5719
-
5720
5754
  //#endregion
5721
5755
  //#region ../seal/src/validators/boolean-validator.ts
5722
5756
  /**
@@ -5737,65 +5771,89 @@ var BooleanValidator = class extends PrimitiveValidator {
5737
5771
  matchesType(value) {
5738
5772
  return typeof value === "boolean";
5739
5773
  }
5740
- /** Value must be accepted (true, "yes", 1, "on", etc.) */
5774
+ /**
5775
+ * Add a rule from the accepted/declined family, opting the validator into
5776
+ * form-boolean parsing.
5777
+ *
5778
+ * Calling ANY `accepted*`/`declined*` method on `v.boolean()` adds (once,
5779
+ * idempotently — checked by mutator identity so chaining several of these
5780
+ * methods never stacks duplicates) `formBooleanMutator`, which runs before
5781
+ * the type rule and converts the accepted set (`1`, `"1"`, `true`,
5782
+ * `"true"`, `"yes"`, `"y"`, `"on"`, `"Yes"`, `"Y"`, `"On"`) to `true` and
5783
+ * the declined set (`0`, `"0"`, `false`, `"false"`, `"no"`, `"n"`, `"off"`,
5784
+ * `"No"`, `"N"`, `"Off"`) to `false`; any other value passes through
5785
+ * unchanged and is rejected by the strict type rule as before.
5786
+ *
5787
+ * The mutator and the rule are added to the SAME resolved instance in one
5788
+ * pass — resolving `this.instance` twice (once per `addRule`/`addMutator`
5789
+ * call) would clone twice on an immutable validator and silently drop one
5790
+ * of the two additions.
5791
+ */
5792
+ addFormBooleanRule(rule, errorMessage, options = {}) {
5793
+ const instance = this.instance;
5794
+ if (!instance.mutators.some((mutator) => mutator.mutate === formBooleanMutator)) instance.addMutableMutator(formBooleanMutator);
5795
+ instance.addMutableRule(rule, errorMessage, options);
5796
+ return instance;
5797
+ }
5798
+ /** Value must be accepted (true, "yes", 1, "on", etc. — form strings are parsed into a real boolean first) */
5741
5799
  accepted(errorMessage) {
5742
- return this.addRule(acceptedRule, errorMessage);
5800
+ return this.addFormBooleanRule(acceptedRule, errorMessage);
5743
5801
  }
5744
5802
  /** Value must be accepted if another field equals a value */
5745
5803
  acceptedIf(field, value, errorMessage) {
5746
- return this.addRule(acceptedIfRule, errorMessage, {
5804
+ return this.addFormBooleanRule(acceptedIfRule, errorMessage, {
5747
5805
  field,
5748
5806
  value
5749
5807
  });
5750
5808
  }
5751
5809
  /** Value must be accepted unless another field equals a value */
5752
5810
  acceptedUnless(field, value, errorMessage) {
5753
- return this.addRule(acceptedUnlessRule, errorMessage, {
5811
+ return this.addFormBooleanRule(acceptedUnlessRule, errorMessage, {
5754
5812
  field,
5755
5813
  value
5756
5814
  });
5757
5815
  }
5758
5816
  /** Value must be accepted if another field is required */
5759
5817
  acceptedIfRequired(field, errorMessage) {
5760
- return this.addRule(acceptedIfRequiredRule, errorMessage, { field });
5818
+ return this.addFormBooleanRule(acceptedIfRequiredRule, errorMessage, { field });
5761
5819
  }
5762
5820
  /** Value must be accepted if another field is present */
5763
5821
  acceptedIfPresent(field, errorMessage) {
5764
- return this.addRule(acceptedIfPresentRule, errorMessage, { field });
5822
+ return this.addFormBooleanRule(acceptedIfPresentRule, errorMessage, { field });
5765
5823
  }
5766
5824
  /** Value must be accepted if another field is missing */
5767
5825
  acceptedWithout(field, errorMessage) {
5768
- return this.addRule(acceptedWithoutRule, errorMessage, { field });
5826
+ return this.addFormBooleanRule(acceptedWithoutRule, errorMessage, { field });
5769
5827
  }
5770
- /** Value must be declined (false, "no", 0, "off", etc.) */
5828
+ /** Value must be declined (false, "no", 0, "off", etc. — form strings are parsed into a real boolean first) */
5771
5829
  declined(errorMessage) {
5772
- return this.addRule(declinedRule, errorMessage);
5830
+ return this.addFormBooleanRule(declinedRule, errorMessage);
5773
5831
  }
5774
5832
  /** Value must be declined if another field equals a value */
5775
5833
  declinedIf(field, value, errorMessage) {
5776
- return this.addRule(declinedIfRule, errorMessage, {
5834
+ return this.addFormBooleanRule(declinedIfRule, errorMessage, {
5777
5835
  field,
5778
5836
  value
5779
5837
  });
5780
5838
  }
5781
5839
  /** Value must be declined unless another field equals a value */
5782
5840
  declinedUnless(field, value, errorMessage) {
5783
- return this.addRule(declinedUnlessRule, errorMessage, {
5841
+ return this.addFormBooleanRule(declinedUnlessRule, errorMessage, {
5784
5842
  field,
5785
5843
  value
5786
5844
  });
5787
5845
  }
5788
5846
  /** Value must be declined if another field is required */
5789
5847
  declinedIfRequired(field, errorMessage) {
5790
- return this.addRule(declinedIfRequiredRule, errorMessage, { field });
5848
+ return this.addFormBooleanRule(declinedIfRequiredRule, errorMessage, { field });
5791
5849
  }
5792
5850
  /** Value must be declined if another field is present */
5793
5851
  declinedIfPresent(field, errorMessage) {
5794
- return this.addRule(declinedIfPresentRule, errorMessage, { field });
5852
+ return this.addFormBooleanRule(declinedIfPresentRule, errorMessage, { field });
5795
5853
  }
5796
5854
  /** Value must be declined if another field is missing */
5797
5855
  declinedWithout(field, errorMessage) {
5798
- return this.addRule(declinedWithoutRule, errorMessage, { field });
5856
+ return this.addFormBooleanRule(declinedWithoutRule, errorMessage, { field });
5799
5857
  }
5800
5858
  /**
5801
5859
  * Opt in to coercion: an exact query-string-shaped boolean is converted to a
@@ -5807,7 +5865,9 @@ var BooleanValidator = class extends PrimitiveValidator {
5807
5865
  * `2` all pass through unchanged and fail the type rule. `v.boolean()` does
5808
5866
  * **not** coerce by default; this only takes effect when explicitly chained.
5809
5867
  * For form-style truthy strings like `"yes"` / `"on"`, use `.accepted()` /
5810
- * `.declined()` instead — those are separate pass/fail rules, not coercion.
5868
+ * `.declined()` instead — those methods opt into their own form-boolean
5869
+ * parsing (a wider value set, case-insensitive on a few forms) and then
5870
+ * apply the accepted/declined pass-fail rule on top of the parsed boolean.
5811
5871
  *
5812
5872
  * The output type is unchanged (`Infer<>` keys off the validator class), so
5813
5873
  * `v.boolean().coerce()` still infers `boolean`.
@@ -8876,6 +8936,7 @@ exports.forbiddenIfNotRule = forbiddenIfNotRule;
8876
8936
  exports.forbiddenIfRule = forbiddenIfRule;
8877
8937
  exports.forbiddenMethodsApplied = forbiddenMethodsApplied;
8878
8938
  exports.forbiddenRule = forbiddenRule;
8939
+ exports.formBooleanMutator = formBooleanMutator;
8879
8940
  exports.fromHourRule = fromHourRule;
8880
8941
  exports.fromMinuteRule = fromMinuteRule;
8881
8942
  exports.fromTodayRule = fromTodayRule;