@remoteoss/json-schema-form 0.8.2-dev.20240213105045 → 0.9.1-beta.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 +18 -0
- package/dist/index.cjs +44 -28
- package/dist/index.js +45 -29
- package/dist/standalone.js +44 -28
- package/package.json +1 -1
- package/src/tests/const.test.js +80 -3
- package/src/tests/createHeadlessForm.test.js +39 -0
- package/src/tests/helpers.js +4 -3
- package/src/tests/jsonLogic.fixtures.js +29 -0
- package/src/tests/jsonLogic.test.js +11 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,21 @@
|
|
|
1
|
+
#### 0.9.1-beta.0 (2024-03-26)
|
|
2
|
+
|
|
3
|
+
##### Bug Fixes
|
|
4
|
+
|
|
5
|
+
* **select/radio:** Allow numbers in oneOf ([#49](https://github.com/remoteoss/json-schema-form/pull/49)) ([04c2598a](https://github.com/remoteoss/json-schema-form/commit/04c2598a3f4e31d8a9495e0d69c0427b6b8c9f56))
|
|
6
|
+
|
|
7
|
+
#### 0.9.0-beta.0 (2024-03-11)
|
|
8
|
+
|
|
9
|
+
##### Breaking changes
|
|
10
|
+
|
|
11
|
+
* Rename `value` -> `forcedValue`. This is in regards to the `json-logic`, where a "forced value" will now be returned in each relevant field (i.e. fields where the schema `const` and `default` are the same) with `forcedValue` over `value`. ([#66](https://github.com/remoteoss/json-schema-form/pull/66)) ([77c445a9](https://github.com/remoteoss/json-schema-form/commit/77c445a9dce657a7648642312f22c18f972187c7))
|
|
12
|
+
|
|
13
|
+
#### 0.8.2-beta.0 (2024-02-13)
|
|
14
|
+
|
|
15
|
+
##### Bug Fixes
|
|
16
|
+
|
|
17
|
+
* **helpers:** getFieldOptions - return empty array if oneOf missing in radio ([#67](https://github.com/remoteoss/json-schema-form/pull/67)) ([6511330f](https://github.com/remoteoss/json-schema-form/commit/6511330f55a2accedb1c58a61ff915a3a0186dbb))
|
|
18
|
+
|
|
1
19
|
#### 0.8.1-beta.0 (2024-02-12)
|
|
2
20
|
|
|
3
21
|
##### Bug Fixes
|
package/dist/index.cjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
|
|
2
2
|
/*!
|
|
3
3
|
Copyright (c) 2024 Remote Technology, Inc.
|
|
4
|
-
NPM Package: @remoteoss/json-schema-form@0.
|
|
5
|
-
Generated: Tue,
|
|
4
|
+
NPM Package: @remoteoss/json-schema-form@0.9.1-beta.0
|
|
5
|
+
Generated: Tue, 26 Mar 2024 17:04:09 GMT
|
|
6
6
|
|
|
7
7
|
MIT License
|
|
8
8
|
|
|
@@ -457,9 +457,18 @@ var validateMaxDate = (value, minDate) => {
|
|
|
457
457
|
const compare = compareDates(value, minDate);
|
|
458
458
|
return compare === "LESSER" || compare === "EQUAL" ? true : false;
|
|
459
459
|
};
|
|
460
|
+
var validateRadioOrSelectOptions = (value, options) => {
|
|
461
|
+
if (value === void 0)
|
|
462
|
+
return true;
|
|
463
|
+
const exactMatch = options.some((option) => option.value === value);
|
|
464
|
+
if (exactMatch)
|
|
465
|
+
return true;
|
|
466
|
+
const patternMatch = options.some((option) => option.pattern?.test(value));
|
|
467
|
+
return !!patternMatch;
|
|
468
|
+
};
|
|
460
469
|
var yupSchemas = {
|
|
461
470
|
text: validateOnlyStrings,
|
|
462
|
-
|
|
471
|
+
radioOrSelectString: (options) => {
|
|
463
472
|
return (0, import_yup.string)().nullable().transform((value) => {
|
|
464
473
|
if (value === "") {
|
|
465
474
|
return void 0;
|
|
@@ -469,28 +478,9 @@ var yupSchemas = {
|
|
|
469
478
|
}
|
|
470
479
|
return value === null ? void 0 : value;
|
|
471
480
|
}).test(
|
|
472
|
-
/*
|
|
473
|
-
Custom test determines if the value either:
|
|
474
|
-
- Matches a specific option by value
|
|
475
|
-
- Matches a pattern
|
|
476
|
-
If the option is undefined do not test, to allow for optional fields.
|
|
477
|
-
*/
|
|
478
481
|
"matchesOptionOrPattern",
|
|
479
482
|
({ value }) => `The option ${JSON.stringify(value)} is not valid.`,
|
|
480
|
-
(value) =>
|
|
481
|
-
if (value === void 0) {
|
|
482
|
-
return true;
|
|
483
|
-
}
|
|
484
|
-
const exactMatch = options.some((option) => option.value === value);
|
|
485
|
-
if (exactMatch) {
|
|
486
|
-
return true;
|
|
487
|
-
}
|
|
488
|
-
const patternMatch = options.some((option) => option.pattern?.test(value));
|
|
489
|
-
if (patternMatch) {
|
|
490
|
-
return true;
|
|
491
|
-
}
|
|
492
|
-
return false;
|
|
493
|
-
}
|
|
483
|
+
(value) => validateRadioOrSelectOptions(value, options)
|
|
494
484
|
);
|
|
495
485
|
},
|
|
496
486
|
date: ({ minDate, maxDate }) => {
|
|
@@ -519,6 +509,22 @@ var yupSchemas = {
|
|
|
519
509
|
}
|
|
520
510
|
return dateString;
|
|
521
511
|
},
|
|
512
|
+
radioOrSelectNumber: (options) => (0, import_yup.mixed)().typeError("The value must be a number").transform((value) => {
|
|
513
|
+
if (options?.some((option) => option.value === null)) {
|
|
514
|
+
return value;
|
|
515
|
+
}
|
|
516
|
+
return value === null ? void 0 : value;
|
|
517
|
+
}).test(
|
|
518
|
+
"matchesOptionOrPattern",
|
|
519
|
+
({ value }) => {
|
|
520
|
+
return `The option ${JSON.stringify(value)} is not valid.`;
|
|
521
|
+
},
|
|
522
|
+
(value) => {
|
|
523
|
+
if (value !== void 0 && typeof value !== "number")
|
|
524
|
+
return false;
|
|
525
|
+
return validateRadioOrSelectOptions(value, options);
|
|
526
|
+
}
|
|
527
|
+
).nullable(),
|
|
522
528
|
number: (0, import_yup.number)().typeError("The value must be a number").nullable(),
|
|
523
529
|
file: (0, import_yup.array)().nullable(),
|
|
524
530
|
email: (0, import_yup.string)().trim().email("Please enter a valid email address").nullable(),
|
|
@@ -548,7 +554,9 @@ function getRequiredErrorMessage(inputType, { inlineError, configError }) {
|
|
|
548
554
|
return "Please acknowledge this field";
|
|
549
555
|
return "Required field";
|
|
550
556
|
}
|
|
551
|
-
var getJsonTypeInArray = (jsonType) =>
|
|
557
|
+
var getJsonTypeInArray = (jsonType) => {
|
|
558
|
+
return Array.isArray(jsonType) ? jsonType.find((val) => val !== "null") : jsonType;
|
|
559
|
+
};
|
|
552
560
|
var getOptions = (field) => {
|
|
553
561
|
const allValues = field.options?.map((option) => ({
|
|
554
562
|
value: option.value,
|
|
@@ -562,9 +570,16 @@ var getOptions = (field) => {
|
|
|
562
570
|
};
|
|
563
571
|
var getYupSchema = ({ inputType, ...field }) => {
|
|
564
572
|
const jsonType = getJsonTypeInArray(field.jsonType);
|
|
565
|
-
|
|
573
|
+
const hasOptions = field.options?.length > 0;
|
|
574
|
+
const generateOptionSchema = (type) => {
|
|
566
575
|
const optionValues = getOptions(field);
|
|
567
|
-
return yupSchemas.
|
|
576
|
+
return type === "number" ? yupSchemas.radioOrSelectNumber(optionValues) : yupSchemas.radioOrSelectString(optionValues);
|
|
577
|
+
};
|
|
578
|
+
if (hasOptions) {
|
|
579
|
+
if (Array.isArray(field.jsonType)) {
|
|
580
|
+
return field.jsonType.includes("number") ? generateOptionSchema("number") : generateOptionSchema("string");
|
|
581
|
+
}
|
|
582
|
+
return generateOptionSchema(field.jsonType);
|
|
568
583
|
}
|
|
569
584
|
if (field.format === "date") {
|
|
570
585
|
return yupSchemas.date({ minDate: field.minDate, maxDate: field.maxDate });
|
|
@@ -1381,7 +1396,7 @@ function extractParametersFromNode(schemaNode) {
|
|
|
1381
1396
|
const node = (0, import_omit.default)(schemaNode, ["x-jsf-presentation", "presentation"]);
|
|
1382
1397
|
const description = presentation?.description || node.description;
|
|
1383
1398
|
const statementDescription = presentation.statement?.description;
|
|
1384
|
-
const value = typeof node.const !== "undefined" && typeof node.default !== "undefined" ? {
|
|
1399
|
+
const value = typeof node.const !== "undefined" && typeof node.default !== "undefined" && node.const === node.default ? { forcedValue: node.const } : {};
|
|
1385
1400
|
return (0, import_omitBy.default)(
|
|
1386
1401
|
{
|
|
1387
1402
|
const: node.const,
|
|
@@ -1477,9 +1492,10 @@ var handleValuesChange = (fields, jsonSchema, config, logic) => (values) => {
|
|
|
1477
1492
|
};
|
|
1478
1493
|
};
|
|
1479
1494
|
function getDecoratedComputedAttributes(computedAttributes) {
|
|
1495
|
+
const isEqualConstAndDefault = computedAttributes?.const === computedAttributes?.default;
|
|
1480
1496
|
return {
|
|
1481
1497
|
...computedAttributes ?? {},
|
|
1482
|
-
...computedAttributes?.const && computedAttributes?.default ? {
|
|
1498
|
+
...computedAttributes?.const && computedAttributes?.default && isEqualConstAndDefault ? { forcedValue: computedAttributes.const } : {}
|
|
1483
1499
|
};
|
|
1484
1500
|
}
|
|
1485
1501
|
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
|
|
2
2
|
/*!
|
|
3
3
|
Copyright (c) 2024 Remote Technology, Inc.
|
|
4
|
-
NPM Package: @remoteoss/json-schema-form@0.
|
|
5
|
-
Generated: Tue,
|
|
4
|
+
NPM Package: @remoteoss/json-schema-form@0.9.1-beta.0
|
|
5
|
+
Generated: Tue, 26 Mar 2024 17:04:09 GMT
|
|
6
6
|
|
|
7
7
|
MIT License
|
|
8
8
|
|
|
@@ -386,7 +386,7 @@ import jsonLogic from "json-logic-js";
|
|
|
386
386
|
import flow from "lodash/flow";
|
|
387
387
|
import noop from "lodash/noop";
|
|
388
388
|
import { randexp } from "randexp";
|
|
389
|
-
import { string, number, boolean, object, array } from "yup";
|
|
389
|
+
import { string, number, boolean, object, array, mixed } from "yup";
|
|
390
390
|
var DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
|
|
391
391
|
var baseString = string().trim();
|
|
392
392
|
var todayDateHint = (/* @__PURE__ */ new Date()).toISOString().substring(0, 10);
|
|
@@ -421,9 +421,18 @@ var validateMaxDate = (value, minDate) => {
|
|
|
421
421
|
const compare = compareDates(value, minDate);
|
|
422
422
|
return compare === "LESSER" || compare === "EQUAL" ? true : false;
|
|
423
423
|
};
|
|
424
|
+
var validateRadioOrSelectOptions = (value, options) => {
|
|
425
|
+
if (value === void 0)
|
|
426
|
+
return true;
|
|
427
|
+
const exactMatch = options.some((option) => option.value === value);
|
|
428
|
+
if (exactMatch)
|
|
429
|
+
return true;
|
|
430
|
+
const patternMatch = options.some((option) => option.pattern?.test(value));
|
|
431
|
+
return !!patternMatch;
|
|
432
|
+
};
|
|
424
433
|
var yupSchemas = {
|
|
425
434
|
text: validateOnlyStrings,
|
|
426
|
-
|
|
435
|
+
radioOrSelectString: (options) => {
|
|
427
436
|
return string().nullable().transform((value) => {
|
|
428
437
|
if (value === "") {
|
|
429
438
|
return void 0;
|
|
@@ -433,28 +442,9 @@ var yupSchemas = {
|
|
|
433
442
|
}
|
|
434
443
|
return value === null ? void 0 : value;
|
|
435
444
|
}).test(
|
|
436
|
-
/*
|
|
437
|
-
Custom test determines if the value either:
|
|
438
|
-
- Matches a specific option by value
|
|
439
|
-
- Matches a pattern
|
|
440
|
-
If the option is undefined do not test, to allow for optional fields.
|
|
441
|
-
*/
|
|
442
445
|
"matchesOptionOrPattern",
|
|
443
446
|
({ value }) => `The option ${JSON.stringify(value)} is not valid.`,
|
|
444
|
-
(value) =>
|
|
445
|
-
if (value === void 0) {
|
|
446
|
-
return true;
|
|
447
|
-
}
|
|
448
|
-
const exactMatch = options.some((option) => option.value === value);
|
|
449
|
-
if (exactMatch) {
|
|
450
|
-
return true;
|
|
451
|
-
}
|
|
452
|
-
const patternMatch = options.some((option) => option.pattern?.test(value));
|
|
453
|
-
if (patternMatch) {
|
|
454
|
-
return true;
|
|
455
|
-
}
|
|
456
|
-
return false;
|
|
457
|
-
}
|
|
447
|
+
(value) => validateRadioOrSelectOptions(value, options)
|
|
458
448
|
);
|
|
459
449
|
},
|
|
460
450
|
date: ({ minDate, maxDate }) => {
|
|
@@ -483,6 +473,22 @@ var yupSchemas = {
|
|
|
483
473
|
}
|
|
484
474
|
return dateString;
|
|
485
475
|
},
|
|
476
|
+
radioOrSelectNumber: (options) => mixed().typeError("The value must be a number").transform((value) => {
|
|
477
|
+
if (options?.some((option) => option.value === null)) {
|
|
478
|
+
return value;
|
|
479
|
+
}
|
|
480
|
+
return value === null ? void 0 : value;
|
|
481
|
+
}).test(
|
|
482
|
+
"matchesOptionOrPattern",
|
|
483
|
+
({ value }) => {
|
|
484
|
+
return `The option ${JSON.stringify(value)} is not valid.`;
|
|
485
|
+
},
|
|
486
|
+
(value) => {
|
|
487
|
+
if (value !== void 0 && typeof value !== "number")
|
|
488
|
+
return false;
|
|
489
|
+
return validateRadioOrSelectOptions(value, options);
|
|
490
|
+
}
|
|
491
|
+
).nullable(),
|
|
486
492
|
number: number().typeError("The value must be a number").nullable(),
|
|
487
493
|
file: array().nullable(),
|
|
488
494
|
email: string().trim().email("Please enter a valid email address").nullable(),
|
|
@@ -512,7 +518,9 @@ function getRequiredErrorMessage(inputType, { inlineError, configError }) {
|
|
|
512
518
|
return "Please acknowledge this field";
|
|
513
519
|
return "Required field";
|
|
514
520
|
}
|
|
515
|
-
var getJsonTypeInArray = (jsonType) =>
|
|
521
|
+
var getJsonTypeInArray = (jsonType) => {
|
|
522
|
+
return Array.isArray(jsonType) ? jsonType.find((val) => val !== "null") : jsonType;
|
|
523
|
+
};
|
|
516
524
|
var getOptions = (field) => {
|
|
517
525
|
const allValues = field.options?.map((option) => ({
|
|
518
526
|
value: option.value,
|
|
@@ -526,9 +534,16 @@ var getOptions = (field) => {
|
|
|
526
534
|
};
|
|
527
535
|
var getYupSchema = ({ inputType, ...field }) => {
|
|
528
536
|
const jsonType = getJsonTypeInArray(field.jsonType);
|
|
529
|
-
|
|
537
|
+
const hasOptions = field.options?.length > 0;
|
|
538
|
+
const generateOptionSchema = (type) => {
|
|
530
539
|
const optionValues = getOptions(field);
|
|
531
|
-
return yupSchemas.
|
|
540
|
+
return type === "number" ? yupSchemas.radioOrSelectNumber(optionValues) : yupSchemas.radioOrSelectString(optionValues);
|
|
541
|
+
};
|
|
542
|
+
if (hasOptions) {
|
|
543
|
+
if (Array.isArray(field.jsonType)) {
|
|
544
|
+
return field.jsonType.includes("number") ? generateOptionSchema("number") : generateOptionSchema("string");
|
|
545
|
+
}
|
|
546
|
+
return generateOptionSchema(field.jsonType);
|
|
532
547
|
}
|
|
533
548
|
if (field.format === "date") {
|
|
534
549
|
return yupSchemas.date({ minDate: field.minDate, maxDate: field.maxDate });
|
|
@@ -1345,7 +1360,7 @@ function extractParametersFromNode(schemaNode) {
|
|
|
1345
1360
|
const node = omit(schemaNode, ["x-jsf-presentation", "presentation"]);
|
|
1346
1361
|
const description = presentation?.description || node.description;
|
|
1347
1362
|
const statementDescription = presentation.statement?.description;
|
|
1348
|
-
const value = typeof node.const !== "undefined" && typeof node.default !== "undefined" ? {
|
|
1363
|
+
const value = typeof node.const !== "undefined" && typeof node.default !== "undefined" && node.const === node.default ? { forcedValue: node.const } : {};
|
|
1349
1364
|
return omitBy(
|
|
1350
1365
|
{
|
|
1351
1366
|
const: node.const,
|
|
@@ -1441,9 +1456,10 @@ var handleValuesChange = (fields, jsonSchema, config, logic) => (values) => {
|
|
|
1441
1456
|
};
|
|
1442
1457
|
};
|
|
1443
1458
|
function getDecoratedComputedAttributes(computedAttributes) {
|
|
1459
|
+
const isEqualConstAndDefault = computedAttributes?.const === computedAttributes?.default;
|
|
1444
1460
|
return {
|
|
1445
1461
|
...computedAttributes ?? {},
|
|
1446
|
-
...computedAttributes?.const && computedAttributes?.default ? {
|
|
1462
|
+
...computedAttributes?.const && computedAttributes?.default && isEqualConstAndDefault ? { forcedValue: computedAttributes.const } : {}
|
|
1447
1463
|
};
|
|
1448
1464
|
}
|
|
1449
1465
|
|
package/dist/standalone.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
|
|
2
2
|
/*!
|
|
3
3
|
Copyright (c) 2024 Remote Technology, Inc.
|
|
4
|
-
NPM Package: @remoteoss/json-schema-form@0.
|
|
5
|
-
Generated: Tue,
|
|
4
|
+
NPM Package: @remoteoss/json-schema-form@0.9.1-beta.0
|
|
5
|
+
Generated: Tue, 26 Mar 2024 17:04:09 GMT
|
|
6
6
|
|
|
7
7
|
MIT License
|
|
8
8
|
|
|
@@ -11775,9 +11775,18 @@ var validateMaxDate = (value, minDate) => {
|
|
|
11775
11775
|
const compare = compareDates(value, minDate);
|
|
11776
11776
|
return compare === "LESSER" || compare === "EQUAL" ? true : false;
|
|
11777
11777
|
};
|
|
11778
|
+
var validateRadioOrSelectOptions = (value, options) => {
|
|
11779
|
+
if (value === void 0)
|
|
11780
|
+
return true;
|
|
11781
|
+
const exactMatch = options.some((option) => option.value === value);
|
|
11782
|
+
if (exactMatch)
|
|
11783
|
+
return true;
|
|
11784
|
+
const patternMatch = options.some((option) => option.pattern?.test(value));
|
|
11785
|
+
return !!patternMatch;
|
|
11786
|
+
};
|
|
11778
11787
|
var yupSchemas = {
|
|
11779
11788
|
text: validateOnlyStrings,
|
|
11780
|
-
|
|
11789
|
+
radioOrSelectString: (options) => {
|
|
11781
11790
|
return StringSchema().nullable().transform((value) => {
|
|
11782
11791
|
if (value === "") {
|
|
11783
11792
|
return void 0;
|
|
@@ -11787,28 +11796,9 @@ var yupSchemas = {
|
|
|
11787
11796
|
}
|
|
11788
11797
|
return value === null ? void 0 : value;
|
|
11789
11798
|
}).test(
|
|
11790
|
-
/*
|
|
11791
|
-
Custom test determines if the value either:
|
|
11792
|
-
- Matches a specific option by value
|
|
11793
|
-
- Matches a pattern
|
|
11794
|
-
If the option is undefined do not test, to allow for optional fields.
|
|
11795
|
-
*/
|
|
11796
11799
|
"matchesOptionOrPattern",
|
|
11797
11800
|
({ value }) => `The option ${JSON.stringify(value)} is not valid.`,
|
|
11798
|
-
(value) =>
|
|
11799
|
-
if (value === void 0) {
|
|
11800
|
-
return true;
|
|
11801
|
-
}
|
|
11802
|
-
const exactMatch = options.some((option) => option.value === value);
|
|
11803
|
-
if (exactMatch) {
|
|
11804
|
-
return true;
|
|
11805
|
-
}
|
|
11806
|
-
const patternMatch = options.some((option) => option.pattern?.test(value));
|
|
11807
|
-
if (patternMatch) {
|
|
11808
|
-
return true;
|
|
11809
|
-
}
|
|
11810
|
-
return false;
|
|
11811
|
-
}
|
|
11801
|
+
(value) => validateRadioOrSelectOptions(value, options)
|
|
11812
11802
|
);
|
|
11813
11803
|
},
|
|
11814
11804
|
date: ({ minDate, maxDate }) => {
|
|
@@ -11837,6 +11827,22 @@ var yupSchemas = {
|
|
|
11837
11827
|
}
|
|
11838
11828
|
return dateString;
|
|
11839
11829
|
},
|
|
11830
|
+
radioOrSelectNumber: (options) => SchemaType().typeError("The value must be a number").transform((value) => {
|
|
11831
|
+
if (options?.some((option) => option.value === null)) {
|
|
11832
|
+
return value;
|
|
11833
|
+
}
|
|
11834
|
+
return value === null ? void 0 : value;
|
|
11835
|
+
}).test(
|
|
11836
|
+
"matchesOptionOrPattern",
|
|
11837
|
+
({ value }) => {
|
|
11838
|
+
return `The option ${JSON.stringify(value)} is not valid.`;
|
|
11839
|
+
},
|
|
11840
|
+
(value) => {
|
|
11841
|
+
if (value !== void 0 && typeof value !== "number")
|
|
11842
|
+
return false;
|
|
11843
|
+
return validateRadioOrSelectOptions(value, options);
|
|
11844
|
+
}
|
|
11845
|
+
).nullable(),
|
|
11840
11846
|
number: NumberSchema().typeError("The value must be a number").nullable(),
|
|
11841
11847
|
file: array_default().nullable(),
|
|
11842
11848
|
email: StringSchema().trim().email("Please enter a valid email address").nullable(),
|
|
@@ -11866,7 +11872,9 @@ function getRequiredErrorMessage(inputType, { inlineError, configError }) {
|
|
|
11866
11872
|
return "Please acknowledge this field";
|
|
11867
11873
|
return "Required field";
|
|
11868
11874
|
}
|
|
11869
|
-
var getJsonTypeInArray = (jsonType) =>
|
|
11875
|
+
var getJsonTypeInArray = (jsonType) => {
|
|
11876
|
+
return Array.isArray(jsonType) ? jsonType.find((val) => val !== "null") : jsonType;
|
|
11877
|
+
};
|
|
11870
11878
|
var getOptions = (field) => {
|
|
11871
11879
|
const allValues = field.options?.map((option) => ({
|
|
11872
11880
|
value: option.value,
|
|
@@ -11880,9 +11888,16 @@ var getOptions = (field) => {
|
|
|
11880
11888
|
};
|
|
11881
11889
|
var getYupSchema = ({ inputType, ...field }) => {
|
|
11882
11890
|
const jsonType = getJsonTypeInArray(field.jsonType);
|
|
11883
|
-
|
|
11891
|
+
const hasOptions = field.options?.length > 0;
|
|
11892
|
+
const generateOptionSchema = (type) => {
|
|
11884
11893
|
const optionValues = getOptions(field);
|
|
11885
|
-
return yupSchemas.
|
|
11894
|
+
return type === "number" ? yupSchemas.radioOrSelectNumber(optionValues) : yupSchemas.radioOrSelectString(optionValues);
|
|
11895
|
+
};
|
|
11896
|
+
if (hasOptions) {
|
|
11897
|
+
if (Array.isArray(field.jsonType)) {
|
|
11898
|
+
return field.jsonType.includes("number") ? generateOptionSchema("number") : generateOptionSchema("string");
|
|
11899
|
+
}
|
|
11900
|
+
return generateOptionSchema(field.jsonType);
|
|
11886
11901
|
}
|
|
11887
11902
|
if (field.format === "date") {
|
|
11888
11903
|
return yupSchemas.date({ minDate: field.minDate, maxDate: field.maxDate });
|
|
@@ -12699,7 +12714,7 @@ function extractParametersFromNode(schemaNode) {
|
|
|
12699
12714
|
const node = (0, import_omit.default)(schemaNode, ["x-jsf-presentation", "presentation"]);
|
|
12700
12715
|
const description = presentation?.description || node.description;
|
|
12701
12716
|
const statementDescription = presentation.statement?.description;
|
|
12702
|
-
const value = typeof node.const !== "undefined" && typeof node.default !== "undefined" ? {
|
|
12717
|
+
const value = typeof node.const !== "undefined" && typeof node.default !== "undefined" && node.const === node.default ? { forcedValue: node.const } : {};
|
|
12703
12718
|
return (0, import_omitBy.default)(
|
|
12704
12719
|
{
|
|
12705
12720
|
const: node.const,
|
|
@@ -12795,9 +12810,10 @@ var handleValuesChange = (fields, jsonSchema, config, logic) => (values2) => {
|
|
|
12795
12810
|
};
|
|
12796
12811
|
};
|
|
12797
12812
|
function getDecoratedComputedAttributes(computedAttributes) {
|
|
12813
|
+
const isEqualConstAndDefault = computedAttributes?.const === computedAttributes?.default;
|
|
12798
12814
|
return {
|
|
12799
12815
|
...computedAttributes ?? {},
|
|
12800
|
-
...computedAttributes?.const && computedAttributes?.default ? {
|
|
12816
|
+
...computedAttributes?.const && computedAttributes?.default && isEqualConstAndDefault ? { forcedValue: computedAttributes.const } : {}
|
|
12801
12817
|
};
|
|
12802
12818
|
}
|
|
12803
12819
|
|
package/package.json
CHANGED
package/src/tests/const.test.js
CHANGED
|
@@ -112,7 +112,7 @@ describe('validations: const', () => {
|
|
|
112
112
|
},
|
|
113
113
|
{ strictInputType: false }
|
|
114
114
|
);
|
|
115
|
-
expect(fields[0]).toMatchObject({
|
|
115
|
+
expect(fields[0]).toMatchObject({ forcedValue: 10, const: 10, default: 10 });
|
|
116
116
|
});
|
|
117
117
|
});
|
|
118
118
|
|
|
@@ -130,7 +130,7 @@ describe('const/default with forced values', () => {
|
|
|
130
130
|
expect(handleValidation({ zero_only: 1 }).formErrors).toEqual({
|
|
131
131
|
zero_only: 'The only accepted value is 0.',
|
|
132
132
|
});
|
|
133
|
-
expect(fields[0]).toMatchObject({
|
|
133
|
+
expect(fields[0]).toMatchObject({ forcedValue: 0, const: 0, default: 0 });
|
|
134
134
|
expect(handleValidation({ zero_only: 0 }).formErrors).toBeUndefined();
|
|
135
135
|
// null is also considered valid until we fix @BUG RMT-518
|
|
136
136
|
// Expectation: To fail with error "The only accepted value is 0."
|
|
@@ -151,9 +151,86 @@ describe('const/default with forced values', () => {
|
|
|
151
151
|
ten_only: 'The only accepted value is 10.',
|
|
152
152
|
});
|
|
153
153
|
expect(handleValidation({ ten_only: 10 }).formErrors).toBeUndefined();
|
|
154
|
-
expect(fields[0]).toMatchObject({
|
|
154
|
+
expect(fields[0]).toMatchObject({ forcedValue: 10, const: 10, default: 10 });
|
|
155
155
|
// null is also considered valid until we fix @BUG RMT-518
|
|
156
156
|
// Expectation: To fail with error "The only accepted value is 10."
|
|
157
157
|
expect(handleValidation({ ten_only: null }).formErrors).toBeUndefined();
|
|
158
158
|
});
|
|
159
|
+
|
|
160
|
+
it('do not set a forced value if const and default do not equal', () => {
|
|
161
|
+
const { fields } = createHeadlessForm(
|
|
162
|
+
{
|
|
163
|
+
properties: {
|
|
164
|
+
bad_field_for_number: { type: 'number', const: 10, default: 20 },
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
{ strictInputType: false }
|
|
168
|
+
);
|
|
169
|
+
expect(fields[0]).not.toMatchObject({ forcedValue: expect.any(Number) });
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it('Should work numbers with non-standard input types', () => {
|
|
173
|
+
const { fields, handleValidation } = createHeadlessForm(
|
|
174
|
+
{
|
|
175
|
+
properties: {
|
|
176
|
+
number: {
|
|
177
|
+
type: 'integer',
|
|
178
|
+
const: 300,
|
|
179
|
+
default: 300,
|
|
180
|
+
'x-jsf-presentation': {
|
|
181
|
+
inputType: 'money',
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
required: ['number'],
|
|
186
|
+
},
|
|
187
|
+
{ strictInputType: true }
|
|
188
|
+
);
|
|
189
|
+
expect(handleValidation({ number: 0 }).formErrors).toEqual({
|
|
190
|
+
number: 'The only accepted value is 300.',
|
|
191
|
+
});
|
|
192
|
+
expect(handleValidation({ number: 300 }).formErrors).toBeUndefined();
|
|
193
|
+
expect(fields[0]).toMatchObject({ forcedValue: 300 });
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
describe('OneOf const', () => {
|
|
198
|
+
it('Validates numbers or strings correctly', () => {
|
|
199
|
+
const { handleValidation } = createHeadlessForm(
|
|
200
|
+
{
|
|
201
|
+
properties: {
|
|
202
|
+
number: { type: 'number', oneOf: [{ const: 0 }, { const: 1 }, { const: 2 }] },
|
|
203
|
+
},
|
|
204
|
+
},
|
|
205
|
+
{ strictInputType: false }
|
|
206
|
+
);
|
|
207
|
+
expect(handleValidation({}).formErrors).toEqual(undefined);
|
|
208
|
+
expect(handleValidation({ number: 3 }).formErrors).toEqual({
|
|
209
|
+
number: 'The option 3 is not valid.',
|
|
210
|
+
});
|
|
211
|
+
expect(handleValidation({ number: 2 }).formErrors).toBeUndefined();
|
|
212
|
+
expect(handleValidation({ number: '2' }).formErrors).toEqual({
|
|
213
|
+
number: 'The option "2" is not valid.',
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
it('Validates numbers or strings when type is an array with null', () => {
|
|
218
|
+
const { handleValidation } = createHeadlessForm(
|
|
219
|
+
{
|
|
220
|
+
properties: {
|
|
221
|
+
number: { type: ['number', 'null'], oneOf: [{ const: 0 }, { const: 1 }, { const: 2 }] },
|
|
222
|
+
},
|
|
223
|
+
},
|
|
224
|
+
{ strictInputType: false }
|
|
225
|
+
);
|
|
226
|
+
expect(handleValidation({}).formErrors).toEqual(undefined);
|
|
227
|
+
expect(handleValidation({ number: 3 }).formErrors).toEqual({
|
|
228
|
+
number: 'The option 3 is not valid.',
|
|
229
|
+
});
|
|
230
|
+
expect(handleValidation({ number: 2 }).formErrors).toBeUndefined();
|
|
231
|
+
expect(handleValidation({ number: '2' }).formErrors).toEqual({
|
|
232
|
+
number: 'The option "2" is not valid.',
|
|
233
|
+
});
|
|
234
|
+
expect(handleValidation({ number: null }).formErrors).toEqual(undefined);
|
|
235
|
+
});
|
|
159
236
|
});
|
|
@@ -2028,6 +2028,45 @@ describe('createHeadlessForm', () => {
|
|
|
2028
2028
|
});
|
|
2029
2029
|
});
|
|
2030
2030
|
|
|
2031
|
+
it('supports oneOf number const', () => {
|
|
2032
|
+
const result = createHeadlessForm({
|
|
2033
|
+
type: 'object',
|
|
2034
|
+
additionalProperties: false,
|
|
2035
|
+
properties: {
|
|
2036
|
+
pets: {
|
|
2037
|
+
title: 'How many pets?',
|
|
2038
|
+
oneOf: [
|
|
2039
|
+
{
|
|
2040
|
+
title: 'One',
|
|
2041
|
+
const: 0,
|
|
2042
|
+
},
|
|
2043
|
+
{
|
|
2044
|
+
title: 'Two',
|
|
2045
|
+
const: 2,
|
|
2046
|
+
},
|
|
2047
|
+
{
|
|
2048
|
+
title: 'null',
|
|
2049
|
+
const: 1,
|
|
2050
|
+
},
|
|
2051
|
+
],
|
|
2052
|
+
'x-jsf-presentation': {
|
|
2053
|
+
inputType: 'select',
|
|
2054
|
+
},
|
|
2055
|
+
type: ['number', 'null'],
|
|
2056
|
+
},
|
|
2057
|
+
},
|
|
2058
|
+
required: [],
|
|
2059
|
+
'x-jsf-order': ['pets'],
|
|
2060
|
+
});
|
|
2061
|
+
|
|
2062
|
+
const fieldValidator = result.fields[0].schema;
|
|
2063
|
+
|
|
2064
|
+
expect(fieldValidator.isValidSync(0)).toBe(true);
|
|
2065
|
+
expect(fieldValidator.isValidSync(1)).toBe(true);
|
|
2066
|
+
expect(() => fieldValidator.validateSync('2')).toThrowError('The option "2" is not valid.');
|
|
2067
|
+
expect(fieldValidator.isValidSync(null)).toBe(true);
|
|
2068
|
+
});
|
|
2069
|
+
|
|
2031
2070
|
describe('x-jsf-presentation attribute', () => {
|
|
2032
2071
|
it('support field with "x-jsf-presentation.statement"', () => {
|
|
2033
2072
|
const result = createHeadlessForm(schemaInputWithStatement);
|
package/src/tests/helpers.js
CHANGED
|
@@ -93,6 +93,7 @@ export const mockTextMaxLengthInput = {
|
|
|
93
93
|
export const mockRadioInputDeprecated = {
|
|
94
94
|
title: 'Has siblings',
|
|
95
95
|
description: 'Do you have any siblings?',
|
|
96
|
+
type: 'string',
|
|
96
97
|
enum: ['yes', 'no'],
|
|
97
98
|
'x-jsf-presentation': {
|
|
98
99
|
inputType: 'radio',
|
|
@@ -386,6 +387,7 @@ export const mockGroupArrayInput = {
|
|
|
386
387
|
],
|
|
387
388
|
},
|
|
388
389
|
title: 'Child Sex',
|
|
390
|
+
type: 'string',
|
|
389
391
|
},
|
|
390
392
|
},
|
|
391
393
|
'x-jsf-order': ['full_name', 'birthdate', 'sex'],
|
|
@@ -842,7 +844,7 @@ export const mockRadioInputOptionalNull = {
|
|
|
842
844
|
{ const: 'yes', title: 'Yes' },
|
|
843
845
|
{ const: 'no', title: 'No' },
|
|
844
846
|
// JSF excludes the null option from the field output
|
|
845
|
-
// But
|
|
847
|
+
// But keeps null as an accepted value
|
|
846
848
|
{ const: null, title: 'N/A' },
|
|
847
849
|
],
|
|
848
850
|
'x-jsf-presentation': { inputType: 'radio' },
|
|
@@ -1612,7 +1614,6 @@ export const schemaFieldsetScopedCondition = {
|
|
|
1612
1614
|
properties: {
|
|
1613
1615
|
has_child: {
|
|
1614
1616
|
description: 'If yes, it will show its age.',
|
|
1615
|
-
maximum: 100,
|
|
1616
1617
|
'x-jsf-presentation': {
|
|
1617
1618
|
inputType: 'radio',
|
|
1618
1619
|
options: [
|
|
@@ -1627,7 +1628,7 @@ export const schemaFieldsetScopedCondition = {
|
|
|
1627
1628
|
],
|
|
1628
1629
|
},
|
|
1629
1630
|
title: 'Do you have a child?',
|
|
1630
|
-
type: '
|
|
1631
|
+
type: 'string',
|
|
1631
1632
|
},
|
|
1632
1633
|
age: {
|
|
1633
1634
|
description: 'This age is required, but the "age" at the root level is still optional.',
|
|
@@ -227,6 +227,35 @@ export const schemaWithComputedAttributes = {
|
|
|
227
227
|
},
|
|
228
228
|
};
|
|
229
229
|
|
|
230
|
+
export const badSchemaThatWillNotSetAForcedValue = {
|
|
231
|
+
properties: {
|
|
232
|
+
field_a: {
|
|
233
|
+
type: 'number',
|
|
234
|
+
},
|
|
235
|
+
field_b: {
|
|
236
|
+
type: 'number',
|
|
237
|
+
'x-jsf-logic-computedAttrs': {
|
|
238
|
+
const: 'a_times_three',
|
|
239
|
+
default: 'a_times_two',
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
'x-jsf-logic': {
|
|
244
|
+
computedValues: {
|
|
245
|
+
a_times_two: {
|
|
246
|
+
rule: {
|
|
247
|
+
'*': [{ var: 'field_a' }, 2],
|
|
248
|
+
},
|
|
249
|
+
},
|
|
250
|
+
a_times_three: {
|
|
251
|
+
rule: {
|
|
252
|
+
'*': [{ var: 'field_a' }, 3],
|
|
253
|
+
},
|
|
254
|
+
},
|
|
255
|
+
},
|
|
256
|
+
},
|
|
257
|
+
};
|
|
258
|
+
|
|
230
259
|
export const schemaWithInlineRuleForComputedAttributeWithoutCopy = {
|
|
231
260
|
properties: {
|
|
232
261
|
field_a: {
|
|
@@ -35,6 +35,7 @@ import {
|
|
|
35
35
|
schemaWithUnknownVariableInComputedValues,
|
|
36
36
|
schemaWithUnknownVariableInValidations,
|
|
37
37
|
schemaWithValidationThatDoesNotExistOnProperty,
|
|
38
|
+
badSchemaThatWillNotSetAForcedValue,
|
|
38
39
|
} from './jsonLogic.fixtures';
|
|
39
40
|
import { mockConsole, restoreConsoleAndEnsureItWasNotCalled } from './testUtils';
|
|
40
41
|
|
|
@@ -335,12 +336,21 @@ describe('jsonLogic: cross-values validations', () => {
|
|
|
335
336
|
'This field is 2 times bigger than field_a with value of 4.'
|
|
336
337
|
);
|
|
337
338
|
expect(fieldB.default).toEqual(4);
|
|
338
|
-
expect(fieldB.
|
|
339
|
+
expect(fieldB.forcedValue).toEqual(4);
|
|
339
340
|
handleValidation({ field_a: 4 });
|
|
340
341
|
expect(fieldB.default).toEqual(8);
|
|
341
342
|
expect(fieldB.label).toEqual('This is 8!');
|
|
342
343
|
});
|
|
343
344
|
|
|
345
|
+
it('A forced value will not be set when const and default are not equal', () => {
|
|
346
|
+
const { fields } = createHeadlessForm(badSchemaThatWillNotSetAForcedValue, {
|
|
347
|
+
strictInputType: false,
|
|
348
|
+
initialValues: { field_a: 2 },
|
|
349
|
+
});
|
|
350
|
+
expect(fields[1]).toMatchObject({ const: 6, default: 4 });
|
|
351
|
+
expect(fields[1]).not.toMatchObject({ forcedValue: expect.any(Number) });
|
|
352
|
+
});
|
|
353
|
+
|
|
344
354
|
it('Derived errorMessages and statements work', () => {
|
|
345
355
|
const { fields, handleValidation } = createHeadlessForm(
|
|
346
356
|
schemaWithComputedAttributesAndErrorMessages,
|