@remoteoss/json-schema-form 0.5.0-dev.20230719162322 → 0.5.0-dev.20230810172154
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 +12 -0
- package/dist/index.cjs +61 -61
- package/dist/index.js +61 -61
- package/dist/standalone.js +61 -61
- package/package.json +1 -1
- package/src/tests/checkIfConditionMatches.test.js +51 -0
- package/src/tests/conditions.test.js +58 -0
- package/src/tests/createHeadlessForm.test.js +10 -19
- package/src/tests/helpers.js +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
#### 0.4.3-beta.0 (2023-08-09)
|
|
2
|
+
|
|
3
|
+
##### Bug fixes
|
|
4
|
+
|
|
5
|
+
* **conditions:** Validate a deeply nested if (e.g. checking an object with a number property) in an if property now doesn't break the form. ([#33](https://github.com/remoteoss/json-schema-form/pull/33)) ([e34cfcc](https://github.com/remoteoss/json-schema-form/commit/e34cfccaf45f1460b346f3cff0c797b3d11259e3))
|
|
6
|
+
|
|
7
|
+
#### 0.4.2-beta.0 (2023-07-20)
|
|
8
|
+
|
|
9
|
+
##### Bug Fixes
|
|
10
|
+
|
|
11
|
+
* **date:** Validate based on minDate and maxDate ([#30](https://github.com/remoteoss/json-schema-form/pull/30)) ([01c0143e](https://github.com/remoteoss/json-schema-form/commit/01c0143ea4a3775f9489ae6cb8fd99a90b3f1394))
|
|
12
|
+
|
|
1
13
|
#### 0.4.1-beta.0 (2023-07-03)
|
|
2
14
|
|
|
3
15
|
##### Bug Fixes
|
package/dist/index.cjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
|
|
2
2
|
/*!
|
|
3
3
|
Copyright (c) 2023 Remote Technology, Inc.
|
|
4
|
-
NPM Package: @remoteoss/json-schema-form@0.5.0-dev.
|
|
5
|
-
Generated:
|
|
4
|
+
NPM Package: @remoteoss/json-schema-form@0.5.0-dev.20230810172154
|
|
5
|
+
Generated: Thu, 10 Aug 2023 17:22:35 GMT
|
|
6
6
|
|
|
7
7
|
MIT License
|
|
8
8
|
|
|
@@ -84,6 +84,62 @@ var import_omitBy = __toESM(require("lodash/omitBy"));
|
|
|
84
84
|
var import_set = __toESM(require("lodash/set"));
|
|
85
85
|
var import_yup2 = require("yup");
|
|
86
86
|
|
|
87
|
+
// src/utils.js
|
|
88
|
+
function convertDiskSizeFromTo(from, to) {
|
|
89
|
+
const units = ["bytes", "kb", "mb"];
|
|
90
|
+
return function convert(value) {
|
|
91
|
+
return value * Math.pow(1024, units.indexOf(from.toLowerCase())) / Math.pow(1024, units.indexOf(to.toLowerCase()));
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
function hasProperty(object2, propertyName) {
|
|
95
|
+
return Object.prototype.hasOwnProperty.call(object2, propertyName);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// src/checkIfConditionMatches.js
|
|
99
|
+
function checkIfConditionMatches(node, formValues, formFields) {
|
|
100
|
+
return Object.keys(node.if.properties).every((name) => {
|
|
101
|
+
const currentProperty = node.if.properties[name];
|
|
102
|
+
const value = formValues[name];
|
|
103
|
+
const hasEmptyValue = typeof value === "undefined" || // NOTE: This is a "Remote API" dependency, as empty fields are sent as "null".
|
|
104
|
+
value === null;
|
|
105
|
+
const hasIfExplicit = node.if.required?.includes(name);
|
|
106
|
+
if (hasEmptyValue && !hasIfExplicit) {
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
if (hasProperty(currentProperty, "const")) {
|
|
110
|
+
return compareFormValueWithSchemaValue(value, currentProperty.const);
|
|
111
|
+
}
|
|
112
|
+
if (currentProperty.contains?.pattern) {
|
|
113
|
+
const formValue = value || [];
|
|
114
|
+
if (Array.isArray(formValue)) {
|
|
115
|
+
const pattern = new RegExp(currentProperty.contains.pattern);
|
|
116
|
+
return (value || []).some((item) => pattern.test(item));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (currentProperty.enum) {
|
|
120
|
+
return currentProperty.enum.includes(value);
|
|
121
|
+
}
|
|
122
|
+
if (currentProperty.properties) {
|
|
123
|
+
return checkIfConditionMatches(
|
|
124
|
+
{ if: currentProperty },
|
|
125
|
+
formValues[name],
|
|
126
|
+
getField(name, formFields).fields
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
const field = getField(name, formFields);
|
|
130
|
+
return validateFieldSchema(
|
|
131
|
+
{
|
|
132
|
+
options: field.options,
|
|
133
|
+
// @TODO/CODE SMELL. We are passing the property (raw field), but buildYupSchema() expected the output field.
|
|
134
|
+
...currentProperty,
|
|
135
|
+
inputType: field.inputType,
|
|
136
|
+
required: true
|
|
137
|
+
},
|
|
138
|
+
value
|
|
139
|
+
);
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
|
|
87
143
|
// src/internals/helpers.js
|
|
88
144
|
var import_merge = __toESM(require("lodash/fp/merge"));
|
|
89
145
|
var import_get = __toESM(require("lodash/get"));
|
|
@@ -343,24 +399,6 @@ function _composeFieldCustomClosure(defaultComposeFn) {
|
|
|
343
399
|
};
|
|
344
400
|
}
|
|
345
401
|
|
|
346
|
-
// src/utils.js
|
|
347
|
-
function convertDiskSizeFromTo(from, to) {
|
|
348
|
-
const units = ["bytes", "kb", "mb"];
|
|
349
|
-
return function convert(value) {
|
|
350
|
-
return value * Math.pow(1024, units.indexOf(from.toLowerCase())) / Math.pow(1024, units.indexOf(to.toLowerCase()));
|
|
351
|
-
};
|
|
352
|
-
}
|
|
353
|
-
function containsHTML(str = "") {
|
|
354
|
-
return /<[a-z][\s\S]*>/i.test(str);
|
|
355
|
-
}
|
|
356
|
-
function wrapWithSpan(html, properties = {}) {
|
|
357
|
-
const attributes = Object.entries(properties).reduce((acc, [key, value]) => `${acc}${key}="${value}" `, "").trim();
|
|
358
|
-
return `<span ${attributes}>${html}</span>`;
|
|
359
|
-
}
|
|
360
|
-
function hasProperty(object2, propertyName) {
|
|
361
|
-
return Object.prototype.hasOwnProperty.call(object2, propertyName);
|
|
362
|
-
}
|
|
363
|
-
|
|
364
402
|
// src/yupSchema.js
|
|
365
403
|
var import_flow = __toESM(require("lodash/flow"));
|
|
366
404
|
var import_noop = __toESM(require("lodash/noop"));
|
|
@@ -675,42 +713,6 @@ function compareFormValueWithSchemaValue(formValue, schemaValue) {
|
|
|
675
713
|
const currentPropertyValue = typeof schemaValue === "number" ? schemaValue : schemaValue || void 0;
|
|
676
714
|
return String(formValue) === String(currentPropertyValue);
|
|
677
715
|
}
|
|
678
|
-
function checkIfConditionMatches(node, formValues, formFields) {
|
|
679
|
-
return Object.keys(node.if.properties).every((name) => {
|
|
680
|
-
const currentProperty = node.if.properties[name];
|
|
681
|
-
const value = formValues[name];
|
|
682
|
-
const hasEmptyValue = typeof value === "undefined" || // NOTE: This is a "Remote API" dependency, as empty fields are sent as "null".
|
|
683
|
-
value === null;
|
|
684
|
-
const hasIfExplicit = node.if.required?.includes(name);
|
|
685
|
-
if (hasEmptyValue && !hasIfExplicit) {
|
|
686
|
-
return true;
|
|
687
|
-
}
|
|
688
|
-
if (hasProperty(currentProperty, "const")) {
|
|
689
|
-
return compareFormValueWithSchemaValue(value, currentProperty.const);
|
|
690
|
-
}
|
|
691
|
-
if (currentProperty.contains?.pattern) {
|
|
692
|
-
const formValue = value || [];
|
|
693
|
-
if (Array.isArray(formValue)) {
|
|
694
|
-
const pattern = new RegExp(currentProperty.contains.pattern);
|
|
695
|
-
return (value || []).some((item) => pattern.test(item));
|
|
696
|
-
}
|
|
697
|
-
}
|
|
698
|
-
if (currentProperty.enum) {
|
|
699
|
-
return currentProperty.enum.includes(value);
|
|
700
|
-
}
|
|
701
|
-
const field = getField(name, formFields);
|
|
702
|
-
return validateFieldSchema(
|
|
703
|
-
{
|
|
704
|
-
options: field.options,
|
|
705
|
-
// @TODO/CODE SMELL. We are passing the property (raw field), but buildYupSchema() expected the output field.
|
|
706
|
-
...currentProperty,
|
|
707
|
-
inputType: field.inputType,
|
|
708
|
-
required: true
|
|
709
|
-
},
|
|
710
|
-
value
|
|
711
|
-
);
|
|
712
|
-
});
|
|
713
|
-
}
|
|
714
716
|
function isFieldFilled(fieldValue) {
|
|
715
717
|
return Array.isArray(fieldValue) ? fieldValue.length > 0 : !!fieldValue;
|
|
716
718
|
}
|
|
@@ -922,7 +924,7 @@ function extractParametersFromNode(schemaNode) {
|
|
|
922
924
|
const errorMessage = pickXKey(schemaNode, "errorMessage") ?? {};
|
|
923
925
|
const node = (0, import_omit.default)(schemaNode, ["x-jsf-presentation", "presentation"]);
|
|
924
926
|
const description = presentation?.description || node.description;
|
|
925
|
-
const statementDescription =
|
|
927
|
+
const statementDescription = presentation.statement?.description;
|
|
926
928
|
return (0, import_omitBy.default)(
|
|
927
929
|
{
|
|
928
930
|
label: node.title,
|
|
@@ -959,10 +961,8 @@ function extractParametersFromNode(schemaNode) {
|
|
|
959
961
|
},
|
|
960
962
|
// Handle [name].presentation
|
|
961
963
|
...presentation,
|
|
962
|
-
description
|
|
963
|
-
|
|
964
|
-
}) : description,
|
|
965
|
-
extra: containsHTML(presentation.extra) ? wrapWithSpan(presentation.extra, { class: "jsf-extra" }) : presentation.extra,
|
|
964
|
+
description,
|
|
965
|
+
extra: presentation.extra,
|
|
966
966
|
statement: presentation.statement && {
|
|
967
967
|
...presentation.statement,
|
|
968
968
|
description: statementDescription
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
|
|
2
2
|
/*!
|
|
3
3
|
Copyright (c) 2023 Remote Technology, Inc.
|
|
4
|
-
NPM Package: @remoteoss/json-schema-form@0.5.0-dev.
|
|
5
|
-
Generated:
|
|
4
|
+
NPM Package: @remoteoss/json-schema-form@0.5.0-dev.20230810172154
|
|
5
|
+
Generated: Thu, 10 Aug 2023 17:22:35 GMT
|
|
6
6
|
|
|
7
7
|
MIT License
|
|
8
8
|
|
|
@@ -48,6 +48,62 @@ import omitBy from "lodash/omitBy";
|
|
|
48
48
|
import set from "lodash/set";
|
|
49
49
|
import { lazy } from "yup";
|
|
50
50
|
|
|
51
|
+
// src/utils.js
|
|
52
|
+
function convertDiskSizeFromTo(from, to) {
|
|
53
|
+
const units = ["bytes", "kb", "mb"];
|
|
54
|
+
return function convert(value) {
|
|
55
|
+
return value * Math.pow(1024, units.indexOf(from.toLowerCase())) / Math.pow(1024, units.indexOf(to.toLowerCase()));
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function hasProperty(object2, propertyName) {
|
|
59
|
+
return Object.prototype.hasOwnProperty.call(object2, propertyName);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// src/checkIfConditionMatches.js
|
|
63
|
+
function checkIfConditionMatches(node, formValues, formFields) {
|
|
64
|
+
return Object.keys(node.if.properties).every((name) => {
|
|
65
|
+
const currentProperty = node.if.properties[name];
|
|
66
|
+
const value = formValues[name];
|
|
67
|
+
const hasEmptyValue = typeof value === "undefined" || // NOTE: This is a "Remote API" dependency, as empty fields are sent as "null".
|
|
68
|
+
value === null;
|
|
69
|
+
const hasIfExplicit = node.if.required?.includes(name);
|
|
70
|
+
if (hasEmptyValue && !hasIfExplicit) {
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
if (hasProperty(currentProperty, "const")) {
|
|
74
|
+
return compareFormValueWithSchemaValue(value, currentProperty.const);
|
|
75
|
+
}
|
|
76
|
+
if (currentProperty.contains?.pattern) {
|
|
77
|
+
const formValue = value || [];
|
|
78
|
+
if (Array.isArray(formValue)) {
|
|
79
|
+
const pattern = new RegExp(currentProperty.contains.pattern);
|
|
80
|
+
return (value || []).some((item) => pattern.test(item));
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (currentProperty.enum) {
|
|
84
|
+
return currentProperty.enum.includes(value);
|
|
85
|
+
}
|
|
86
|
+
if (currentProperty.properties) {
|
|
87
|
+
return checkIfConditionMatches(
|
|
88
|
+
{ if: currentProperty },
|
|
89
|
+
formValues[name],
|
|
90
|
+
getField(name, formFields).fields
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
const field = getField(name, formFields);
|
|
94
|
+
return validateFieldSchema(
|
|
95
|
+
{
|
|
96
|
+
options: field.options,
|
|
97
|
+
// @TODO/CODE SMELL. We are passing the property (raw field), but buildYupSchema() expected the output field.
|
|
98
|
+
...currentProperty,
|
|
99
|
+
inputType: field.inputType,
|
|
100
|
+
required: true
|
|
101
|
+
},
|
|
102
|
+
value
|
|
103
|
+
);
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
51
107
|
// src/internals/helpers.js
|
|
52
108
|
import merge from "lodash/fp/merge";
|
|
53
109
|
import get from "lodash/get";
|
|
@@ -307,24 +363,6 @@ function _composeFieldCustomClosure(defaultComposeFn) {
|
|
|
307
363
|
};
|
|
308
364
|
}
|
|
309
365
|
|
|
310
|
-
// src/utils.js
|
|
311
|
-
function convertDiskSizeFromTo(from, to) {
|
|
312
|
-
const units = ["bytes", "kb", "mb"];
|
|
313
|
-
return function convert(value) {
|
|
314
|
-
return value * Math.pow(1024, units.indexOf(from.toLowerCase())) / Math.pow(1024, units.indexOf(to.toLowerCase()));
|
|
315
|
-
};
|
|
316
|
-
}
|
|
317
|
-
function containsHTML(str = "") {
|
|
318
|
-
return /<[a-z][\s\S]*>/i.test(str);
|
|
319
|
-
}
|
|
320
|
-
function wrapWithSpan(html, properties = {}) {
|
|
321
|
-
const attributes = Object.entries(properties).reduce((acc, [key, value]) => `${acc}${key}="${value}" `, "").trim();
|
|
322
|
-
return `<span ${attributes}>${html}</span>`;
|
|
323
|
-
}
|
|
324
|
-
function hasProperty(object2, propertyName) {
|
|
325
|
-
return Object.prototype.hasOwnProperty.call(object2, propertyName);
|
|
326
|
-
}
|
|
327
|
-
|
|
328
366
|
// src/yupSchema.js
|
|
329
367
|
import flow from "lodash/flow";
|
|
330
368
|
import noop from "lodash/noop";
|
|
@@ -639,42 +677,6 @@ function compareFormValueWithSchemaValue(formValue, schemaValue) {
|
|
|
639
677
|
const currentPropertyValue = typeof schemaValue === "number" ? schemaValue : schemaValue || void 0;
|
|
640
678
|
return String(formValue) === String(currentPropertyValue);
|
|
641
679
|
}
|
|
642
|
-
function checkIfConditionMatches(node, formValues, formFields) {
|
|
643
|
-
return Object.keys(node.if.properties).every((name) => {
|
|
644
|
-
const currentProperty = node.if.properties[name];
|
|
645
|
-
const value = formValues[name];
|
|
646
|
-
const hasEmptyValue = typeof value === "undefined" || // NOTE: This is a "Remote API" dependency, as empty fields are sent as "null".
|
|
647
|
-
value === null;
|
|
648
|
-
const hasIfExplicit = node.if.required?.includes(name);
|
|
649
|
-
if (hasEmptyValue && !hasIfExplicit) {
|
|
650
|
-
return true;
|
|
651
|
-
}
|
|
652
|
-
if (hasProperty(currentProperty, "const")) {
|
|
653
|
-
return compareFormValueWithSchemaValue(value, currentProperty.const);
|
|
654
|
-
}
|
|
655
|
-
if (currentProperty.contains?.pattern) {
|
|
656
|
-
const formValue = value || [];
|
|
657
|
-
if (Array.isArray(formValue)) {
|
|
658
|
-
const pattern = new RegExp(currentProperty.contains.pattern);
|
|
659
|
-
return (value || []).some((item) => pattern.test(item));
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
|
-
if (currentProperty.enum) {
|
|
663
|
-
return currentProperty.enum.includes(value);
|
|
664
|
-
}
|
|
665
|
-
const field = getField(name, formFields);
|
|
666
|
-
return validateFieldSchema(
|
|
667
|
-
{
|
|
668
|
-
options: field.options,
|
|
669
|
-
// @TODO/CODE SMELL. We are passing the property (raw field), but buildYupSchema() expected the output field.
|
|
670
|
-
...currentProperty,
|
|
671
|
-
inputType: field.inputType,
|
|
672
|
-
required: true
|
|
673
|
-
},
|
|
674
|
-
value
|
|
675
|
-
);
|
|
676
|
-
});
|
|
677
|
-
}
|
|
678
680
|
function isFieldFilled(fieldValue) {
|
|
679
681
|
return Array.isArray(fieldValue) ? fieldValue.length > 0 : !!fieldValue;
|
|
680
682
|
}
|
|
@@ -886,7 +888,7 @@ function extractParametersFromNode(schemaNode) {
|
|
|
886
888
|
const errorMessage = pickXKey(schemaNode, "errorMessage") ?? {};
|
|
887
889
|
const node = omit(schemaNode, ["x-jsf-presentation", "presentation"]);
|
|
888
890
|
const description = presentation?.description || node.description;
|
|
889
|
-
const statementDescription =
|
|
891
|
+
const statementDescription = presentation.statement?.description;
|
|
890
892
|
return omitBy(
|
|
891
893
|
{
|
|
892
894
|
label: node.title,
|
|
@@ -923,10 +925,8 @@ function extractParametersFromNode(schemaNode) {
|
|
|
923
925
|
},
|
|
924
926
|
// Handle [name].presentation
|
|
925
927
|
...presentation,
|
|
926
|
-
description
|
|
927
|
-
|
|
928
|
-
}) : description,
|
|
929
|
-
extra: containsHTML(presentation.extra) ? wrapWithSpan(presentation.extra, { class: "jsf-extra" }) : presentation.extra,
|
|
928
|
+
description,
|
|
929
|
+
extra: presentation.extra,
|
|
930
930
|
statement: presentation.statement && {
|
|
931
931
|
...presentation.statement,
|
|
932
932
|
description: statementDescription
|
package/dist/standalone.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
|
|
2
2
|
/*!
|
|
3
3
|
Copyright (c) 2023 Remote Technology, Inc.
|
|
4
|
-
NPM Package: @remoteoss/json-schema-form@0.5.0-dev.
|
|
5
|
-
Generated:
|
|
4
|
+
NPM Package: @remoteoss/json-schema-form@0.5.0-dev.20230810172154
|
|
5
|
+
Generated: Thu, 10 Aug 2023 17:22:35 GMT
|
|
6
6
|
|
|
7
7
|
MIT License
|
|
8
8
|
|
|
@@ -11025,6 +11025,62 @@ var lazy = function lazy2(fn) {
|
|
|
11025
11025
|
return new Lazy_default(fn);
|
|
11026
11026
|
};
|
|
11027
11027
|
|
|
11028
|
+
// src/utils.js
|
|
11029
|
+
function convertDiskSizeFromTo(from2, to) {
|
|
11030
|
+
const units = ["bytes", "kb", "mb"];
|
|
11031
|
+
return function convert(value) {
|
|
11032
|
+
return value * Math.pow(1024, units.indexOf(from2.toLowerCase())) / Math.pow(1024, units.indexOf(to.toLowerCase()));
|
|
11033
|
+
};
|
|
11034
|
+
}
|
|
11035
|
+
function hasProperty(object2, propertyName) {
|
|
11036
|
+
return Object.prototype.hasOwnProperty.call(object2, propertyName);
|
|
11037
|
+
}
|
|
11038
|
+
|
|
11039
|
+
// src/checkIfConditionMatches.js
|
|
11040
|
+
function checkIfConditionMatches(node, formValues, formFields) {
|
|
11041
|
+
return Object.keys(node.if.properties).every((name) => {
|
|
11042
|
+
const currentProperty = node.if.properties[name];
|
|
11043
|
+
const value = formValues[name];
|
|
11044
|
+
const hasEmptyValue = typeof value === "undefined" || // NOTE: This is a "Remote API" dependency, as empty fields are sent as "null".
|
|
11045
|
+
value === null;
|
|
11046
|
+
const hasIfExplicit = node.if.required?.includes(name);
|
|
11047
|
+
if (hasEmptyValue && !hasIfExplicit) {
|
|
11048
|
+
return true;
|
|
11049
|
+
}
|
|
11050
|
+
if (hasProperty(currentProperty, "const")) {
|
|
11051
|
+
return compareFormValueWithSchemaValue(value, currentProperty.const);
|
|
11052
|
+
}
|
|
11053
|
+
if (currentProperty.contains?.pattern) {
|
|
11054
|
+
const formValue = value || [];
|
|
11055
|
+
if (Array.isArray(formValue)) {
|
|
11056
|
+
const pattern = new RegExp(currentProperty.contains.pattern);
|
|
11057
|
+
return (value || []).some((item) => pattern.test(item));
|
|
11058
|
+
}
|
|
11059
|
+
}
|
|
11060
|
+
if (currentProperty.enum) {
|
|
11061
|
+
return currentProperty.enum.includes(value);
|
|
11062
|
+
}
|
|
11063
|
+
if (currentProperty.properties) {
|
|
11064
|
+
return checkIfConditionMatches(
|
|
11065
|
+
{ if: currentProperty },
|
|
11066
|
+
formValues[name],
|
|
11067
|
+
getField(name, formFields).fields
|
|
11068
|
+
);
|
|
11069
|
+
}
|
|
11070
|
+
const field = getField(name, formFields);
|
|
11071
|
+
return validateFieldSchema(
|
|
11072
|
+
{
|
|
11073
|
+
options: field.options,
|
|
11074
|
+
// @TODO/CODE SMELL. We are passing the property (raw field), but buildYupSchema() expected the output field.
|
|
11075
|
+
...currentProperty,
|
|
11076
|
+
inputType: field.inputType,
|
|
11077
|
+
required: true
|
|
11078
|
+
},
|
|
11079
|
+
value
|
|
11080
|
+
);
|
|
11081
|
+
});
|
|
11082
|
+
}
|
|
11083
|
+
|
|
11028
11084
|
// src/internals/helpers.js
|
|
11029
11085
|
var import_merge = __toESM(require_merge2());
|
|
11030
11086
|
var import_get2 = __toESM(require_get());
|
|
@@ -11284,24 +11340,6 @@ function _composeFieldCustomClosure(defaultComposeFn) {
|
|
|
11284
11340
|
};
|
|
11285
11341
|
}
|
|
11286
11342
|
|
|
11287
|
-
// src/utils.js
|
|
11288
|
-
function convertDiskSizeFromTo(from2, to) {
|
|
11289
|
-
const units = ["bytes", "kb", "mb"];
|
|
11290
|
-
return function convert(value) {
|
|
11291
|
-
return value * Math.pow(1024, units.indexOf(from2.toLowerCase())) / Math.pow(1024, units.indexOf(to.toLowerCase()));
|
|
11292
|
-
};
|
|
11293
|
-
}
|
|
11294
|
-
function containsHTML(str = "") {
|
|
11295
|
-
return /<[a-z][\s\S]*>/i.test(str);
|
|
11296
|
-
}
|
|
11297
|
-
function wrapWithSpan(html, properties = {}) {
|
|
11298
|
-
const attributes = Object.entries(properties).reduce((acc, [key, value]) => `${acc}${key}="${value}" `, "").trim();
|
|
11299
|
-
return `<span ${attributes}>${html}</span>`;
|
|
11300
|
-
}
|
|
11301
|
-
function hasProperty(object2, propertyName) {
|
|
11302
|
-
return Object.prototype.hasOwnProperty.call(object2, propertyName);
|
|
11303
|
-
}
|
|
11304
|
-
|
|
11305
11343
|
// src/yupSchema.js
|
|
11306
11344
|
var import_flow = __toESM(require_flow());
|
|
11307
11345
|
var import_noop = __toESM(require_noop());
|
|
@@ -11615,42 +11653,6 @@ function compareFormValueWithSchemaValue(formValue, schemaValue) {
|
|
|
11615
11653
|
const currentPropertyValue = typeof schemaValue === "number" ? schemaValue : schemaValue || void 0;
|
|
11616
11654
|
return String(formValue) === String(currentPropertyValue);
|
|
11617
11655
|
}
|
|
11618
|
-
function checkIfConditionMatches(node, formValues, formFields) {
|
|
11619
|
-
return Object.keys(node.if.properties).every((name) => {
|
|
11620
|
-
const currentProperty = node.if.properties[name];
|
|
11621
|
-
const value = formValues[name];
|
|
11622
|
-
const hasEmptyValue = typeof value === "undefined" || // NOTE: This is a "Remote API" dependency, as empty fields are sent as "null".
|
|
11623
|
-
value === null;
|
|
11624
|
-
const hasIfExplicit = node.if.required?.includes(name);
|
|
11625
|
-
if (hasEmptyValue && !hasIfExplicit) {
|
|
11626
|
-
return true;
|
|
11627
|
-
}
|
|
11628
|
-
if (hasProperty(currentProperty, "const")) {
|
|
11629
|
-
return compareFormValueWithSchemaValue(value, currentProperty.const);
|
|
11630
|
-
}
|
|
11631
|
-
if (currentProperty.contains?.pattern) {
|
|
11632
|
-
const formValue = value || [];
|
|
11633
|
-
if (Array.isArray(formValue)) {
|
|
11634
|
-
const pattern = new RegExp(currentProperty.contains.pattern);
|
|
11635
|
-
return (value || []).some((item) => pattern.test(item));
|
|
11636
|
-
}
|
|
11637
|
-
}
|
|
11638
|
-
if (currentProperty.enum) {
|
|
11639
|
-
return currentProperty.enum.includes(value);
|
|
11640
|
-
}
|
|
11641
|
-
const field = getField(name, formFields);
|
|
11642
|
-
return validateFieldSchema(
|
|
11643
|
-
{
|
|
11644
|
-
options: field.options,
|
|
11645
|
-
// @TODO/CODE SMELL. We are passing the property (raw field), but buildYupSchema() expected the output field.
|
|
11646
|
-
...currentProperty,
|
|
11647
|
-
inputType: field.inputType,
|
|
11648
|
-
required: true
|
|
11649
|
-
},
|
|
11650
|
-
value
|
|
11651
|
-
);
|
|
11652
|
-
});
|
|
11653
|
-
}
|
|
11654
11656
|
function isFieldFilled(fieldValue) {
|
|
11655
11657
|
return Array.isArray(fieldValue) ? fieldValue.length > 0 : !!fieldValue;
|
|
11656
11658
|
}
|
|
@@ -11862,7 +11864,7 @@ function extractParametersFromNode(schemaNode) {
|
|
|
11862
11864
|
const errorMessage = pickXKey(schemaNode, "errorMessage") ?? {};
|
|
11863
11865
|
const node = (0, import_omit.default)(schemaNode, ["x-jsf-presentation", "presentation"]);
|
|
11864
11866
|
const description = presentation?.description || node.description;
|
|
11865
|
-
const statementDescription =
|
|
11867
|
+
const statementDescription = presentation.statement?.description;
|
|
11866
11868
|
return (0, import_omitBy.default)(
|
|
11867
11869
|
{
|
|
11868
11870
|
label: node.title,
|
|
@@ -11899,10 +11901,8 @@ function extractParametersFromNode(schemaNode) {
|
|
|
11899
11901
|
},
|
|
11900
11902
|
// Handle [name].presentation
|
|
11901
11903
|
...presentation,
|
|
11902
|
-
description
|
|
11903
|
-
|
|
11904
|
-
}) : description,
|
|
11905
|
-
extra: containsHTML(presentation.extra) ? wrapWithSpan(presentation.extra, { class: "jsf-extra" }) : presentation.extra,
|
|
11904
|
+
description,
|
|
11905
|
+
extra: presentation.extra,
|
|
11906
11906
|
statement: presentation.statement && {
|
|
11907
11907
|
...presentation.statement,
|
|
11908
11908
|
description: statementDescription
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remoteoss/json-schema-form",
|
|
3
|
-
"version": "0.5.0-dev.
|
|
3
|
+
"version": "0.5.0-dev.20230810172154",
|
|
4
4
|
"description": "Headless UI form powered by JSON Schemas",
|
|
5
5
|
"author": "Remote.com <engineering@remote.com> (https://remote.com/)",
|
|
6
6
|
"license": "MIT",
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { checkIfConditionMatches } from '../checkIfConditionMatches';
|
|
2
|
+
|
|
3
|
+
it('Empty if is always going to be true', () => {
|
|
4
|
+
expect(checkIfConditionMatches({ if: { properties: {} } })).toBe(true);
|
|
5
|
+
});
|
|
6
|
+
|
|
7
|
+
it('Basic if check passes with correct value', () => {
|
|
8
|
+
expect(
|
|
9
|
+
checkIfConditionMatches(
|
|
10
|
+
{ if: { properties: { a: { const: 'hello' } } } },
|
|
11
|
+
{
|
|
12
|
+
a: 'hello',
|
|
13
|
+
}
|
|
14
|
+
)
|
|
15
|
+
).toBe(true);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('Basic if check fails with incorrect value', () => {
|
|
19
|
+
expect(
|
|
20
|
+
checkIfConditionMatches(
|
|
21
|
+
{ if: { properties: { a: { const: 'hello' } } } },
|
|
22
|
+
{
|
|
23
|
+
a: 'goodbye',
|
|
24
|
+
}
|
|
25
|
+
)
|
|
26
|
+
).toBe(false);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('Nested properties check passes with correct value', () => {
|
|
30
|
+
expect(
|
|
31
|
+
checkIfConditionMatches(
|
|
32
|
+
{ if: { properties: { parent: { properties: { child: { const: 'hello from child' } } } } } },
|
|
33
|
+
{
|
|
34
|
+
parent: { child: 'hello from child' },
|
|
35
|
+
},
|
|
36
|
+
[{ name: 'parent', fields: [] }]
|
|
37
|
+
)
|
|
38
|
+
).toBe(true);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('Nested properties check passes with correct value', () => {
|
|
42
|
+
expect(
|
|
43
|
+
checkIfConditionMatches(
|
|
44
|
+
{ if: { properties: { parent: { properties: { child: { const: 'hello from child' } } } } } },
|
|
45
|
+
{
|
|
46
|
+
parent: { child: 'goodbye from child' },
|
|
47
|
+
},
|
|
48
|
+
[{ name: 'parent', fields: [] }]
|
|
49
|
+
)
|
|
50
|
+
).toBe(false);
|
|
51
|
+
});
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { createHeadlessForm } from '../createHeadlessForm';
|
|
2
|
+
|
|
3
|
+
it('Should allow check of a nested property in a conditional', () => {
|
|
4
|
+
const { handleValidation } = createHeadlessForm(
|
|
5
|
+
{
|
|
6
|
+
additionalProperties: false,
|
|
7
|
+
allOf: [
|
|
8
|
+
{
|
|
9
|
+
if: {
|
|
10
|
+
properties: {
|
|
11
|
+
parent: {
|
|
12
|
+
properties: {
|
|
13
|
+
child: {
|
|
14
|
+
const: 'yes',
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
required: ['child'],
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
required: ['parent'],
|
|
21
|
+
},
|
|
22
|
+
then: { required: ['parent_sibling'] },
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
properties: {
|
|
26
|
+
parent: {
|
|
27
|
+
additionalProperties: false,
|
|
28
|
+
properties: {
|
|
29
|
+
child: {
|
|
30
|
+
oneOf: [
|
|
31
|
+
{
|
|
32
|
+
const: 'yes',
|
|
33
|
+
},
|
|
34
|
+
{ const: 'no' },
|
|
35
|
+
],
|
|
36
|
+
type: 'string',
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
required: ['child'],
|
|
40
|
+
type: 'object',
|
|
41
|
+
},
|
|
42
|
+
parent_sibling: {
|
|
43
|
+
type: 'integer',
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
required: ['parent'],
|
|
47
|
+
type: 'object',
|
|
48
|
+
},
|
|
49
|
+
{ strictInputType: false }
|
|
50
|
+
);
|
|
51
|
+
expect(handleValidation({ parent: { child: 'no' } }).formErrors).toEqual(undefined);
|
|
52
|
+
expect(handleValidation({ parent: { child: 'yes' } }).formErrors).toEqual({
|
|
53
|
+
parent_sibling: 'Required field',
|
|
54
|
+
});
|
|
55
|
+
expect(handleValidation({ parent: { child: 'yes' }, parent_sibling: 1 }).formErrors).toEqual(
|
|
56
|
+
undefined
|
|
57
|
+
);
|
|
58
|
+
});
|
|
@@ -1020,7 +1020,7 @@ describe('createHeadlessForm', () => {
|
|
|
1020
1020
|
schema: expect.any(Object),
|
|
1021
1021
|
type: 'date',
|
|
1022
1022
|
minDate: '1922-03-01',
|
|
1023
|
-
maxDate: '2022-03-
|
|
1023
|
+
maxDate: '2022-03-17',
|
|
1024
1024
|
});
|
|
1025
1025
|
|
|
1026
1026
|
const todayDateHint = new Date().toISOString().substring(0, 10);
|
|
@@ -1047,17 +1047,15 @@ describe('createHeadlessForm', () => {
|
|
|
1047
1047
|
schema: expect.any(Object),
|
|
1048
1048
|
type: 'date',
|
|
1049
1049
|
minDate: '1922-03-01',
|
|
1050
|
-
maxDate: '2022-03-
|
|
1050
|
+
maxDate: '2022-03-17',
|
|
1051
1051
|
});
|
|
1052
1052
|
|
|
1053
1053
|
expect(validateForm({})).toEqual({
|
|
1054
1054
|
birthdate: 'Required field',
|
|
1055
1055
|
});
|
|
1056
1056
|
|
|
1057
|
-
const todayDateHint = new Date().toISOString().substring(0, 10);
|
|
1058
|
-
|
|
1059
1057
|
expect(validateForm({ birthdate: '' })).toEqual({
|
|
1060
|
-
birthdate: `
|
|
1058
|
+
birthdate: `Required field`,
|
|
1061
1059
|
});
|
|
1062
1060
|
|
|
1063
1061
|
expect(validateForm({ birthdate: '1922-02-01' })).toEqual({
|
|
@@ -1081,19 +1079,17 @@ describe('createHeadlessForm', () => {
|
|
|
1081
1079
|
schema: expect.any(Object),
|
|
1082
1080
|
type: 'date',
|
|
1083
1081
|
minDate: '1922-03-01',
|
|
1084
|
-
maxDate: '2022-03-
|
|
1082
|
+
maxDate: '2022-03-17',
|
|
1085
1083
|
});
|
|
1086
1084
|
|
|
1087
|
-
const todayDateHint = new Date().toISOString().substring(0, 10);
|
|
1088
|
-
|
|
1089
1085
|
expect(validateForm({ birthdate: '' })).toEqual({
|
|
1090
|
-
birthdate: `
|
|
1086
|
+
birthdate: `Required field`,
|
|
1091
1087
|
});
|
|
1092
1088
|
|
|
1093
1089
|
expect(validateForm({ birthdate: '2022-02-01' })).toBeUndefined();
|
|
1094
1090
|
expect(validateForm({ birthdate: '2022-03-01' })).toBeUndefined();
|
|
1095
1091
|
expect(validateForm({ birthdate: '2022-04-01' })).toEqual({
|
|
1096
|
-
birthdate: 'The date must be 2022-03-
|
|
1092
|
+
birthdate: 'The date must be 2022-03-17 or before.',
|
|
1097
1093
|
});
|
|
1098
1094
|
});
|
|
1099
1095
|
|
|
@@ -2048,10 +2044,7 @@ describe('createHeadlessForm', () => {
|
|
|
2048
2044
|
});
|
|
2049
2045
|
|
|
2050
2046
|
expect(result).toMatchObject({
|
|
2051
|
-
fields: [
|
|
2052
|
-
{ description: 'I am regular' },
|
|
2053
|
-
{ description: '<span class="jsf-description">I am <b>bold</b>.</span>' },
|
|
2054
|
-
],
|
|
2047
|
+
fields: [{ description: 'I am regular' }, { description: 'I am <b>bold</b>.' }],
|
|
2055
2048
|
});
|
|
2056
2049
|
});
|
|
2057
2050
|
|
|
@@ -2510,7 +2503,7 @@ describe('createHeadlessForm', () => {
|
|
|
2510
2503
|
});
|
|
2511
2504
|
|
|
2512
2505
|
describe('when a field has conditional presentation properties', () => {
|
|
2513
|
-
it('adds
|
|
2506
|
+
it('adds the html to nested statement markup when visible', () => {
|
|
2514
2507
|
const { fields } = createHeadlessForm(schemaWithConditionalPresentationProperties, {
|
|
2515
2508
|
initialValues: {
|
|
2516
2509
|
// show the hidden statement
|
|
@@ -2518,9 +2511,7 @@ describe('createHeadlessForm', () => {
|
|
|
2518
2511
|
},
|
|
2519
2512
|
});
|
|
2520
2513
|
|
|
2521
|
-
expect(fields[0].statement.description).toBe(
|
|
2522
|
-
`<span class="jsf-statement"><a href="">conditional statement markup</a></span>`
|
|
2523
|
-
);
|
|
2514
|
+
expect(fields[0].statement.description).toBe(`<a href="">conditional statement markup</a>`);
|
|
2524
2515
|
});
|
|
2525
2516
|
});
|
|
2526
2517
|
|
|
@@ -3697,7 +3688,7 @@ describe('createHeadlessForm', () => {
|
|
|
3697
3688
|
expect(fields).toMatchObject([
|
|
3698
3689
|
{
|
|
3699
3690
|
name: 'time',
|
|
3700
|
-
description: '
|
|
3691
|
+
description: 'Write in <b>hh:ss</b> format', // from presentation
|
|
3701
3692
|
inputType: 'clock', // arbitrary type from presentation
|
|
3702
3693
|
deprecated: {
|
|
3703
3694
|
description: 'In favor of X', // from presentation
|
package/src/tests/helpers.js
CHANGED
|
@@ -991,7 +991,7 @@ export const schemaInputTypeDate = {
|
|
|
991
991
|
additionalProperties: false,
|
|
992
992
|
properties: {
|
|
993
993
|
birthdate: {
|
|
994
|
-
'x-jsf-presentation': { inputType: 'date', maxDate: '2022-03-
|
|
994
|
+
'x-jsf-presentation': { inputType: 'date', maxDate: '2022-03-17', minDate: '1922-03-01' },
|
|
995
995
|
title: 'Birthdate',
|
|
996
996
|
type: 'string',
|
|
997
997
|
format: 'date',
|