@remoteoss/json-schema-form 0.11.12-dev.20250310202108 → 0.11.12-dev.20250313084704
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +75 -73
- package/dist/index.js +75 -73
- package/dist/standalone.js +75 -73
- package/package.json +1 -1
- package/src/tests/conditions.test.js +0 -68
- package/src/tests/createHeadlessForm.test.js +22 -0
- package/src/tests/helpers.js +21 -0
package/dist/index.cjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
|
|
2
2
|
/*!
|
|
3
3
|
Copyright (c) 2025 Remote Technology, Inc.
|
|
4
|
-
NPM Package: @remoteoss/json-schema-form@0.11.12-dev.
|
|
5
|
-
Generated:
|
|
4
|
+
NPM Package: @remoteoss/json-schema-form@0.11.12-dev.20250313084704
|
|
5
|
+
Generated: Thu, 13 Mar 2025 08:47:14 GMT
|
|
6
6
|
|
|
7
7
|
MIT License
|
|
8
8
|
|
|
@@ -96,6 +96,75 @@ function hasProperty(object2, propertyName) {
|
|
|
96
96
|
return Object.prototype.hasOwnProperty.call(object2, propertyName);
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
+
// src/internals/checkIfConditionMatches.js
|
|
100
|
+
function checkIfConditionMatchesProperties(node, formValues, formFields, logic) {
|
|
101
|
+
if (typeof node.if === "boolean") {
|
|
102
|
+
return node.if;
|
|
103
|
+
}
|
|
104
|
+
if (node.if.anyOf) {
|
|
105
|
+
return node.if.anyOf.some(
|
|
106
|
+
(property) => checkIfConditionMatchesProperties({ if: property }, formValues, formFields, logic)
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
return Object.keys(node.if.properties ?? {}).every((name) => {
|
|
110
|
+
const currentProperty = node.if.properties[name];
|
|
111
|
+
const value = formValues[name];
|
|
112
|
+
const hasEmptyValue = typeof value === "undefined" || // NOTE: This is a "Remote API" dependency, as empty fields are sent as "null".
|
|
113
|
+
value === null;
|
|
114
|
+
const hasIfExplicit = node.if.required?.includes(name);
|
|
115
|
+
if (hasEmptyValue && !hasIfExplicit) {
|
|
116
|
+
return true;
|
|
117
|
+
}
|
|
118
|
+
if (hasProperty(currentProperty, "const")) {
|
|
119
|
+
return compareFormValueWithSchemaValue(value, currentProperty.const);
|
|
120
|
+
}
|
|
121
|
+
if (currentProperty.contains?.pattern) {
|
|
122
|
+
const formValue = value || [];
|
|
123
|
+
if (Array.isArray(formValue)) {
|
|
124
|
+
const pattern = new RegExp(currentProperty.contains.pattern);
|
|
125
|
+
return (value || []).some((item) => pattern.test(item));
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
if (currentProperty.enum) {
|
|
129
|
+
return currentProperty.enum.includes(value);
|
|
130
|
+
}
|
|
131
|
+
if (currentProperty.properties) {
|
|
132
|
+
return checkIfConditionMatchesProperties(
|
|
133
|
+
{ if: currentProperty },
|
|
134
|
+
formValues[name],
|
|
135
|
+
getField(name, formFields).fields,
|
|
136
|
+
logic
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
const field = getField(name, formFields);
|
|
140
|
+
return validateFieldSchema(
|
|
141
|
+
{
|
|
142
|
+
...field,
|
|
143
|
+
...currentProperty,
|
|
144
|
+
required: true
|
|
145
|
+
},
|
|
146
|
+
value
|
|
147
|
+
);
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
function checkIfMatchesValidationsAndComputedValues(node, formValues, logic, parentID) {
|
|
151
|
+
const validationsMatch = Object.entries(node.if.validations ?? {}).every(([name, property]) => {
|
|
152
|
+
const currentValue = logic.getScope(parentID).applyValidationRuleInCondition(name, formValues);
|
|
153
|
+
if (Object.hasOwn(property, "const") && currentValue === property.const)
|
|
154
|
+
return true;
|
|
155
|
+
return false;
|
|
156
|
+
});
|
|
157
|
+
const computedValuesMatch = Object.entries(node.if.computedValues ?? {}).every(
|
|
158
|
+
([name, property]) => {
|
|
159
|
+
const currentValue = logic.getScope(parentID).applyComputedValueRuleInCondition(name, formValues);
|
|
160
|
+
if (Object.hasOwn(property, "const") && currentValue === property.const)
|
|
161
|
+
return true;
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
);
|
|
165
|
+
return computedValuesMatch && validationsMatch;
|
|
166
|
+
}
|
|
167
|
+
|
|
99
168
|
// src/internals/helpers.js
|
|
100
169
|
var import_merge = __toESM(require("lodash/fp/merge"));
|
|
101
170
|
var import_get = __toESM(require("lodash/get"));
|
|
@@ -355,76 +424,6 @@ function _composeFieldCustomClosure(defaultComposeFn) {
|
|
|
355
424
|
};
|
|
356
425
|
}
|
|
357
426
|
|
|
358
|
-
// src/internals/checkIfConditionMatches.js
|
|
359
|
-
function checkIfConditionMatchesProperties(node, formValues, formFields, logic) {
|
|
360
|
-
if (typeof node.if === "boolean") {
|
|
361
|
-
return node.if;
|
|
362
|
-
}
|
|
363
|
-
if (node.if.anyOf) {
|
|
364
|
-
return node.if.anyOf.some(
|
|
365
|
-
(property) => checkIfConditionMatchesProperties({ if: property }, formValues, formFields, logic)
|
|
366
|
-
);
|
|
367
|
-
}
|
|
368
|
-
return Object.keys(node.if.properties ?? {}).every((name) => {
|
|
369
|
-
const currentProperty = node.if.properties[name];
|
|
370
|
-
const field = getField(name, formFields ?? []);
|
|
371
|
-
const isFieldsetField = field?.inputType === supportedTypes.FIELDSET;
|
|
372
|
-
const value = formValues?.[name] ?? (isFieldsetField ? {} : void 0);
|
|
373
|
-
const hasEmptyValue = typeof value === "undefined" || // NOTE: This is a "Remote API" dependency, as empty fields are sent as "null".
|
|
374
|
-
value === null;
|
|
375
|
-
const hasIfExplicit = node.if.required?.includes(name);
|
|
376
|
-
if (hasEmptyValue && !hasIfExplicit) {
|
|
377
|
-
return true;
|
|
378
|
-
}
|
|
379
|
-
if (hasProperty(currentProperty, "const")) {
|
|
380
|
-
return compareFormValueWithSchemaValue(value, currentProperty.const);
|
|
381
|
-
}
|
|
382
|
-
if (currentProperty.contains?.pattern) {
|
|
383
|
-
const formValue = value || [];
|
|
384
|
-
if (Array.isArray(formValue)) {
|
|
385
|
-
const pattern = new RegExp(currentProperty.contains.pattern);
|
|
386
|
-
return (value || []).some((item) => pattern.test(item));
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
if (currentProperty.enum) {
|
|
390
|
-
return currentProperty.enum.includes(value);
|
|
391
|
-
}
|
|
392
|
-
if (currentProperty.properties) {
|
|
393
|
-
return checkIfConditionMatchesProperties(
|
|
394
|
-
{ if: currentProperty },
|
|
395
|
-
formValues[name],
|
|
396
|
-
getField(name, formFields).fields,
|
|
397
|
-
logic
|
|
398
|
-
);
|
|
399
|
-
}
|
|
400
|
-
return validateFieldSchema(
|
|
401
|
-
{
|
|
402
|
-
...field,
|
|
403
|
-
...currentProperty,
|
|
404
|
-
required: true
|
|
405
|
-
},
|
|
406
|
-
value
|
|
407
|
-
);
|
|
408
|
-
});
|
|
409
|
-
}
|
|
410
|
-
function checkIfMatchesValidationsAndComputedValues(node, formValues, logic, parentID) {
|
|
411
|
-
const validationsMatch = Object.entries(node.if.validations ?? {}).every(([name, property]) => {
|
|
412
|
-
const currentValue = logic.getScope(parentID).applyValidationRuleInCondition(name, formValues);
|
|
413
|
-
if (Object.hasOwn(property, "const") && currentValue === property.const)
|
|
414
|
-
return true;
|
|
415
|
-
return false;
|
|
416
|
-
});
|
|
417
|
-
const computedValuesMatch = Object.entries(node.if.computedValues ?? {}).every(
|
|
418
|
-
([name, property]) => {
|
|
419
|
-
const currentValue = logic.getScope(parentID).applyComputedValueRuleInCondition(name, formValues);
|
|
420
|
-
if (Object.hasOwn(property, "const") && currentValue === property.const)
|
|
421
|
-
return true;
|
|
422
|
-
return false;
|
|
423
|
-
}
|
|
424
|
-
);
|
|
425
|
-
return computedValuesMatch && validationsMatch;
|
|
426
|
-
}
|
|
427
|
-
|
|
428
427
|
// src/jsonLogic.js
|
|
429
428
|
var import_json_logic_js = __toESM(require("json-logic-js"));
|
|
430
429
|
|
|
@@ -614,6 +613,8 @@ var getYupSchema = ({ inputType, ...field }) => {
|
|
|
614
613
|
switch (type) {
|
|
615
614
|
case "number":
|
|
616
615
|
return yupSchemas.radioOrSelectNumber(optionValues);
|
|
616
|
+
case "integer":
|
|
617
|
+
return yupSchemas.radioOrSelectNumber(optionValues);
|
|
617
618
|
case "boolean":
|
|
618
619
|
return yupSchemas.radioOrSelectBoolean(optionValues);
|
|
619
620
|
default:
|
|
@@ -774,7 +775,8 @@ function buildYupSchema(field, config, logic) {
|
|
|
774
775
|
if (inputType === supportedTypes.FILE) {
|
|
775
776
|
validators.push(withFile);
|
|
776
777
|
}
|
|
777
|
-
|
|
778
|
+
const hasOptions = field.options?.length > 0;
|
|
779
|
+
if (jsonType === "integer" && !hasOptions) {
|
|
778
780
|
validators.push(withInteger);
|
|
779
781
|
}
|
|
780
782
|
if (typeof propertyFields.minimum !== "undefined") {
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
|
|
2
2
|
/*!
|
|
3
3
|
Copyright (c) 2025 Remote Technology, Inc.
|
|
4
|
-
NPM Package: @remoteoss/json-schema-form@0.11.12-dev.
|
|
5
|
-
Generated:
|
|
4
|
+
NPM Package: @remoteoss/json-schema-form@0.11.12-dev.20250313084704
|
|
5
|
+
Generated: Thu, 13 Mar 2025 08:47:14 GMT
|
|
6
6
|
|
|
7
7
|
MIT License
|
|
8
8
|
|
|
@@ -59,6 +59,75 @@ function hasProperty(object2, propertyName) {
|
|
|
59
59
|
return Object.prototype.hasOwnProperty.call(object2, propertyName);
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
+
// src/internals/checkIfConditionMatches.js
|
|
63
|
+
function checkIfConditionMatchesProperties(node, formValues, formFields, logic) {
|
|
64
|
+
if (typeof node.if === "boolean") {
|
|
65
|
+
return node.if;
|
|
66
|
+
}
|
|
67
|
+
if (node.if.anyOf) {
|
|
68
|
+
return node.if.anyOf.some(
|
|
69
|
+
(property) => checkIfConditionMatchesProperties({ if: property }, formValues, formFields, logic)
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
return Object.keys(node.if.properties ?? {}).every((name) => {
|
|
73
|
+
const currentProperty = node.if.properties[name];
|
|
74
|
+
const value = formValues[name];
|
|
75
|
+
const hasEmptyValue = typeof value === "undefined" || // NOTE: This is a "Remote API" dependency, as empty fields are sent as "null".
|
|
76
|
+
value === null;
|
|
77
|
+
const hasIfExplicit = node.if.required?.includes(name);
|
|
78
|
+
if (hasEmptyValue && !hasIfExplicit) {
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
if (hasProperty(currentProperty, "const")) {
|
|
82
|
+
return compareFormValueWithSchemaValue(value, currentProperty.const);
|
|
83
|
+
}
|
|
84
|
+
if (currentProperty.contains?.pattern) {
|
|
85
|
+
const formValue = value || [];
|
|
86
|
+
if (Array.isArray(formValue)) {
|
|
87
|
+
const pattern = new RegExp(currentProperty.contains.pattern);
|
|
88
|
+
return (value || []).some((item) => pattern.test(item));
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (currentProperty.enum) {
|
|
92
|
+
return currentProperty.enum.includes(value);
|
|
93
|
+
}
|
|
94
|
+
if (currentProperty.properties) {
|
|
95
|
+
return checkIfConditionMatchesProperties(
|
|
96
|
+
{ if: currentProperty },
|
|
97
|
+
formValues[name],
|
|
98
|
+
getField(name, formFields).fields,
|
|
99
|
+
logic
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
const field = getField(name, formFields);
|
|
103
|
+
return validateFieldSchema(
|
|
104
|
+
{
|
|
105
|
+
...field,
|
|
106
|
+
...currentProperty,
|
|
107
|
+
required: true
|
|
108
|
+
},
|
|
109
|
+
value
|
|
110
|
+
);
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
function checkIfMatchesValidationsAndComputedValues(node, formValues, logic, parentID) {
|
|
114
|
+
const validationsMatch = Object.entries(node.if.validations ?? {}).every(([name, property]) => {
|
|
115
|
+
const currentValue = logic.getScope(parentID).applyValidationRuleInCondition(name, formValues);
|
|
116
|
+
if (Object.hasOwn(property, "const") && currentValue === property.const)
|
|
117
|
+
return true;
|
|
118
|
+
return false;
|
|
119
|
+
});
|
|
120
|
+
const computedValuesMatch = Object.entries(node.if.computedValues ?? {}).every(
|
|
121
|
+
([name, property]) => {
|
|
122
|
+
const currentValue = logic.getScope(parentID).applyComputedValueRuleInCondition(name, formValues);
|
|
123
|
+
if (Object.hasOwn(property, "const") && currentValue === property.const)
|
|
124
|
+
return true;
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
);
|
|
128
|
+
return computedValuesMatch && validationsMatch;
|
|
129
|
+
}
|
|
130
|
+
|
|
62
131
|
// src/internals/helpers.js
|
|
63
132
|
import merge from "lodash/fp/merge";
|
|
64
133
|
import get from "lodash/get";
|
|
@@ -318,76 +387,6 @@ function _composeFieldCustomClosure(defaultComposeFn) {
|
|
|
318
387
|
};
|
|
319
388
|
}
|
|
320
389
|
|
|
321
|
-
// src/internals/checkIfConditionMatches.js
|
|
322
|
-
function checkIfConditionMatchesProperties(node, formValues, formFields, logic) {
|
|
323
|
-
if (typeof node.if === "boolean") {
|
|
324
|
-
return node.if;
|
|
325
|
-
}
|
|
326
|
-
if (node.if.anyOf) {
|
|
327
|
-
return node.if.anyOf.some(
|
|
328
|
-
(property) => checkIfConditionMatchesProperties({ if: property }, formValues, formFields, logic)
|
|
329
|
-
);
|
|
330
|
-
}
|
|
331
|
-
return Object.keys(node.if.properties ?? {}).every((name) => {
|
|
332
|
-
const currentProperty = node.if.properties[name];
|
|
333
|
-
const field = getField(name, formFields ?? []);
|
|
334
|
-
const isFieldsetField = field?.inputType === supportedTypes.FIELDSET;
|
|
335
|
-
const value = formValues?.[name] ?? (isFieldsetField ? {} : void 0);
|
|
336
|
-
const hasEmptyValue = typeof value === "undefined" || // NOTE: This is a "Remote API" dependency, as empty fields are sent as "null".
|
|
337
|
-
value === null;
|
|
338
|
-
const hasIfExplicit = node.if.required?.includes(name);
|
|
339
|
-
if (hasEmptyValue && !hasIfExplicit) {
|
|
340
|
-
return true;
|
|
341
|
-
}
|
|
342
|
-
if (hasProperty(currentProperty, "const")) {
|
|
343
|
-
return compareFormValueWithSchemaValue(value, currentProperty.const);
|
|
344
|
-
}
|
|
345
|
-
if (currentProperty.contains?.pattern) {
|
|
346
|
-
const formValue = value || [];
|
|
347
|
-
if (Array.isArray(formValue)) {
|
|
348
|
-
const pattern = new RegExp(currentProperty.contains.pattern);
|
|
349
|
-
return (value || []).some((item) => pattern.test(item));
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
if (currentProperty.enum) {
|
|
353
|
-
return currentProperty.enum.includes(value);
|
|
354
|
-
}
|
|
355
|
-
if (currentProperty.properties) {
|
|
356
|
-
return checkIfConditionMatchesProperties(
|
|
357
|
-
{ if: currentProperty },
|
|
358
|
-
formValues[name],
|
|
359
|
-
getField(name, formFields).fields,
|
|
360
|
-
logic
|
|
361
|
-
);
|
|
362
|
-
}
|
|
363
|
-
return validateFieldSchema(
|
|
364
|
-
{
|
|
365
|
-
...field,
|
|
366
|
-
...currentProperty,
|
|
367
|
-
required: true
|
|
368
|
-
},
|
|
369
|
-
value
|
|
370
|
-
);
|
|
371
|
-
});
|
|
372
|
-
}
|
|
373
|
-
function checkIfMatchesValidationsAndComputedValues(node, formValues, logic, parentID) {
|
|
374
|
-
const validationsMatch = Object.entries(node.if.validations ?? {}).every(([name, property]) => {
|
|
375
|
-
const currentValue = logic.getScope(parentID).applyValidationRuleInCondition(name, formValues);
|
|
376
|
-
if (Object.hasOwn(property, "const") && currentValue === property.const)
|
|
377
|
-
return true;
|
|
378
|
-
return false;
|
|
379
|
-
});
|
|
380
|
-
const computedValuesMatch = Object.entries(node.if.computedValues ?? {}).every(
|
|
381
|
-
([name, property]) => {
|
|
382
|
-
const currentValue = logic.getScope(parentID).applyComputedValueRuleInCondition(name, formValues);
|
|
383
|
-
if (Object.hasOwn(property, "const") && currentValue === property.const)
|
|
384
|
-
return true;
|
|
385
|
-
return false;
|
|
386
|
-
}
|
|
387
|
-
);
|
|
388
|
-
return computedValuesMatch && validationsMatch;
|
|
389
|
-
}
|
|
390
|
-
|
|
391
390
|
// src/jsonLogic.js
|
|
392
391
|
import jsonLogic from "json-logic-js";
|
|
393
392
|
|
|
@@ -577,6 +576,8 @@ var getYupSchema = ({ inputType, ...field }) => {
|
|
|
577
576
|
switch (type) {
|
|
578
577
|
case "number":
|
|
579
578
|
return yupSchemas.radioOrSelectNumber(optionValues);
|
|
579
|
+
case "integer":
|
|
580
|
+
return yupSchemas.radioOrSelectNumber(optionValues);
|
|
580
581
|
case "boolean":
|
|
581
582
|
return yupSchemas.radioOrSelectBoolean(optionValues);
|
|
582
583
|
default:
|
|
@@ -737,7 +738,8 @@ function buildYupSchema(field, config, logic) {
|
|
|
737
738
|
if (inputType === supportedTypes.FILE) {
|
|
738
739
|
validators.push(withFile);
|
|
739
740
|
}
|
|
740
|
-
|
|
741
|
+
const hasOptions = field.options?.length > 0;
|
|
742
|
+
if (jsonType === "integer" && !hasOptions) {
|
|
741
743
|
validators.push(withInteger);
|
|
742
744
|
}
|
|
743
745
|
if (typeof propertyFields.minimum !== "undefined") {
|
package/dist/standalone.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
|
|
2
2
|
/*!
|
|
3
3
|
Copyright (c) 2025 Remote Technology, Inc.
|
|
4
|
-
NPM Package: @remoteoss/json-schema-form@0.11.12-dev.
|
|
5
|
-
Generated:
|
|
4
|
+
NPM Package: @remoteoss/json-schema-form@0.11.12-dev.20250313084704
|
|
5
|
+
Generated: Thu, 13 Mar 2025 08:47:14 GMT
|
|
6
6
|
|
|
7
7
|
MIT License
|
|
8
8
|
|
|
@@ -11576,6 +11576,75 @@ function hasProperty(object2, propertyName) {
|
|
|
11576
11576
|
return Object.prototype.hasOwnProperty.call(object2, propertyName);
|
|
11577
11577
|
}
|
|
11578
11578
|
|
|
11579
|
+
// src/internals/checkIfConditionMatches.js
|
|
11580
|
+
function checkIfConditionMatchesProperties(node, formValues, formFields, logic) {
|
|
11581
|
+
if (typeof node.if === "boolean") {
|
|
11582
|
+
return node.if;
|
|
11583
|
+
}
|
|
11584
|
+
if (node.if.anyOf) {
|
|
11585
|
+
return node.if.anyOf.some(
|
|
11586
|
+
(property2) => checkIfConditionMatchesProperties({ if: property2 }, formValues, formFields, logic)
|
|
11587
|
+
);
|
|
11588
|
+
}
|
|
11589
|
+
return Object.keys(node.if.properties ?? {}).every((name) => {
|
|
11590
|
+
const currentProperty = node.if.properties[name];
|
|
11591
|
+
const value = formValues[name];
|
|
11592
|
+
const hasEmptyValue = typeof value === "undefined" || // NOTE: This is a "Remote API" dependency, as empty fields are sent as "null".
|
|
11593
|
+
value === null;
|
|
11594
|
+
const hasIfExplicit = node.if.required?.includes(name);
|
|
11595
|
+
if (hasEmptyValue && !hasIfExplicit) {
|
|
11596
|
+
return true;
|
|
11597
|
+
}
|
|
11598
|
+
if (hasProperty(currentProperty, "const")) {
|
|
11599
|
+
return compareFormValueWithSchemaValue(value, currentProperty.const);
|
|
11600
|
+
}
|
|
11601
|
+
if (currentProperty.contains?.pattern) {
|
|
11602
|
+
const formValue = value || [];
|
|
11603
|
+
if (Array.isArray(formValue)) {
|
|
11604
|
+
const pattern = new RegExp(currentProperty.contains.pattern);
|
|
11605
|
+
return (value || []).some((item) => pattern.test(item));
|
|
11606
|
+
}
|
|
11607
|
+
}
|
|
11608
|
+
if (currentProperty.enum) {
|
|
11609
|
+
return currentProperty.enum.includes(value);
|
|
11610
|
+
}
|
|
11611
|
+
if (currentProperty.properties) {
|
|
11612
|
+
return checkIfConditionMatchesProperties(
|
|
11613
|
+
{ if: currentProperty },
|
|
11614
|
+
formValues[name],
|
|
11615
|
+
getField(name, formFields).fields,
|
|
11616
|
+
logic
|
|
11617
|
+
);
|
|
11618
|
+
}
|
|
11619
|
+
const field = getField(name, formFields);
|
|
11620
|
+
return validateFieldSchema(
|
|
11621
|
+
{
|
|
11622
|
+
...field,
|
|
11623
|
+
...currentProperty,
|
|
11624
|
+
required: true
|
|
11625
|
+
},
|
|
11626
|
+
value
|
|
11627
|
+
);
|
|
11628
|
+
});
|
|
11629
|
+
}
|
|
11630
|
+
function checkIfMatchesValidationsAndComputedValues(node, formValues, logic, parentID) {
|
|
11631
|
+
const validationsMatch = Object.entries(node.if.validations ?? {}).every(([name, property2]) => {
|
|
11632
|
+
const currentValue = logic.getScope(parentID).applyValidationRuleInCondition(name, formValues);
|
|
11633
|
+
if (Object.hasOwn(property2, "const") && currentValue === property2.const)
|
|
11634
|
+
return true;
|
|
11635
|
+
return false;
|
|
11636
|
+
});
|
|
11637
|
+
const computedValuesMatch = Object.entries(node.if.computedValues ?? {}).every(
|
|
11638
|
+
([name, property2]) => {
|
|
11639
|
+
const currentValue = logic.getScope(parentID).applyComputedValueRuleInCondition(name, formValues);
|
|
11640
|
+
if (Object.hasOwn(property2, "const") && currentValue === property2.const)
|
|
11641
|
+
return true;
|
|
11642
|
+
return false;
|
|
11643
|
+
}
|
|
11644
|
+
);
|
|
11645
|
+
return computedValuesMatch && validationsMatch;
|
|
11646
|
+
}
|
|
11647
|
+
|
|
11579
11648
|
// src/internals/helpers.js
|
|
11580
11649
|
var import_merge = __toESM(require_merge2());
|
|
11581
11650
|
var import_get2 = __toESM(require_get());
|
|
@@ -11835,76 +11904,6 @@ function _composeFieldCustomClosure(defaultComposeFn) {
|
|
|
11835
11904
|
};
|
|
11836
11905
|
}
|
|
11837
11906
|
|
|
11838
|
-
// src/internals/checkIfConditionMatches.js
|
|
11839
|
-
function checkIfConditionMatchesProperties(node, formValues, formFields, logic) {
|
|
11840
|
-
if (typeof node.if === "boolean") {
|
|
11841
|
-
return node.if;
|
|
11842
|
-
}
|
|
11843
|
-
if (node.if.anyOf) {
|
|
11844
|
-
return node.if.anyOf.some(
|
|
11845
|
-
(property2) => checkIfConditionMatchesProperties({ if: property2 }, formValues, formFields, logic)
|
|
11846
|
-
);
|
|
11847
|
-
}
|
|
11848
|
-
return Object.keys(node.if.properties ?? {}).every((name) => {
|
|
11849
|
-
const currentProperty = node.if.properties[name];
|
|
11850
|
-
const field = getField(name, formFields ?? []);
|
|
11851
|
-
const isFieldsetField = field?.inputType === supportedTypes.FIELDSET;
|
|
11852
|
-
const value = formValues?.[name] ?? (isFieldsetField ? {} : void 0);
|
|
11853
|
-
const hasEmptyValue = typeof value === "undefined" || // NOTE: This is a "Remote API" dependency, as empty fields are sent as "null".
|
|
11854
|
-
value === null;
|
|
11855
|
-
const hasIfExplicit = node.if.required?.includes(name);
|
|
11856
|
-
if (hasEmptyValue && !hasIfExplicit) {
|
|
11857
|
-
return true;
|
|
11858
|
-
}
|
|
11859
|
-
if (hasProperty(currentProperty, "const")) {
|
|
11860
|
-
return compareFormValueWithSchemaValue(value, currentProperty.const);
|
|
11861
|
-
}
|
|
11862
|
-
if (currentProperty.contains?.pattern) {
|
|
11863
|
-
const formValue = value || [];
|
|
11864
|
-
if (Array.isArray(formValue)) {
|
|
11865
|
-
const pattern = new RegExp(currentProperty.contains.pattern);
|
|
11866
|
-
return (value || []).some((item) => pattern.test(item));
|
|
11867
|
-
}
|
|
11868
|
-
}
|
|
11869
|
-
if (currentProperty.enum) {
|
|
11870
|
-
return currentProperty.enum.includes(value);
|
|
11871
|
-
}
|
|
11872
|
-
if (currentProperty.properties) {
|
|
11873
|
-
return checkIfConditionMatchesProperties(
|
|
11874
|
-
{ if: currentProperty },
|
|
11875
|
-
formValues[name],
|
|
11876
|
-
getField(name, formFields).fields,
|
|
11877
|
-
logic
|
|
11878
|
-
);
|
|
11879
|
-
}
|
|
11880
|
-
return validateFieldSchema(
|
|
11881
|
-
{
|
|
11882
|
-
...field,
|
|
11883
|
-
...currentProperty,
|
|
11884
|
-
required: true
|
|
11885
|
-
},
|
|
11886
|
-
value
|
|
11887
|
-
);
|
|
11888
|
-
});
|
|
11889
|
-
}
|
|
11890
|
-
function checkIfMatchesValidationsAndComputedValues(node, formValues, logic, parentID) {
|
|
11891
|
-
const validationsMatch = Object.entries(node.if.validations ?? {}).every(([name, property2]) => {
|
|
11892
|
-
const currentValue = logic.getScope(parentID).applyValidationRuleInCondition(name, formValues);
|
|
11893
|
-
if (Object.hasOwn(property2, "const") && currentValue === property2.const)
|
|
11894
|
-
return true;
|
|
11895
|
-
return false;
|
|
11896
|
-
});
|
|
11897
|
-
const computedValuesMatch = Object.entries(node.if.computedValues ?? {}).every(
|
|
11898
|
-
([name, property2]) => {
|
|
11899
|
-
const currentValue = logic.getScope(parentID).applyComputedValueRuleInCondition(name, formValues);
|
|
11900
|
-
if (Object.hasOwn(property2, "const") && currentValue === property2.const)
|
|
11901
|
-
return true;
|
|
11902
|
-
return false;
|
|
11903
|
-
}
|
|
11904
|
-
);
|
|
11905
|
-
return computedValuesMatch && validationsMatch;
|
|
11906
|
-
}
|
|
11907
|
-
|
|
11908
11907
|
// src/jsonLogic.js
|
|
11909
11908
|
var import_json_logic_js = __toESM(require_logic());
|
|
11910
11909
|
|
|
@@ -12093,6 +12092,8 @@ var getYupSchema = ({ inputType, ...field }) => {
|
|
|
12093
12092
|
switch (type) {
|
|
12094
12093
|
case "number":
|
|
12095
12094
|
return yupSchemas.radioOrSelectNumber(optionValues);
|
|
12095
|
+
case "integer":
|
|
12096
|
+
return yupSchemas.radioOrSelectNumber(optionValues);
|
|
12096
12097
|
case "boolean":
|
|
12097
12098
|
return yupSchemas.radioOrSelectBoolean(optionValues);
|
|
12098
12099
|
default:
|
|
@@ -12253,7 +12254,8 @@ function buildYupSchema(field, config, logic) {
|
|
|
12253
12254
|
if (inputType === supportedTypes.FILE) {
|
|
12254
12255
|
validators.push(withFile);
|
|
12255
12256
|
}
|
|
12256
|
-
|
|
12257
|
+
const hasOptions = field.options?.length > 0;
|
|
12258
|
+
if (jsonType === "integer" && !hasOptions) {
|
|
12257
12259
|
validators.push(withInteger);
|
|
12258
12260
|
}
|
|
12259
12261
|
if (typeof propertyFields.minimum !== "undefined") {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remoteoss/json-schema-form",
|
|
3
|
-
"version": "0.11.12-dev.
|
|
3
|
+
"version": "0.11.12-dev.20250313084704",
|
|
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",
|
|
@@ -596,74 +596,6 @@ describe('Conditional with anyOf', () => {
|
|
|
596
596
|
});
|
|
597
597
|
});
|
|
598
598
|
|
|
599
|
-
describe('Conditional with fieldset', () => {
|
|
600
|
-
const schema = {
|
|
601
|
-
additionalProperties: false,
|
|
602
|
-
type: 'object',
|
|
603
|
-
properties: {
|
|
604
|
-
field_a: {
|
|
605
|
-
type: 'object',
|
|
606
|
-
properties: {
|
|
607
|
-
min: { type: 'number' },
|
|
608
|
-
max: { type: 'number' },
|
|
609
|
-
},
|
|
610
|
-
},
|
|
611
|
-
field_b: { type: 'string' },
|
|
612
|
-
},
|
|
613
|
-
allOf: [
|
|
614
|
-
{
|
|
615
|
-
if: {
|
|
616
|
-
properties: {
|
|
617
|
-
field_a: {
|
|
618
|
-
properties: {
|
|
619
|
-
min: {
|
|
620
|
-
minimum: 10,
|
|
621
|
-
},
|
|
622
|
-
},
|
|
623
|
-
required: ['min'],
|
|
624
|
-
},
|
|
625
|
-
},
|
|
626
|
-
required: ['field_a'],
|
|
627
|
-
},
|
|
628
|
-
then: {
|
|
629
|
-
required: ['field_b'],
|
|
630
|
-
},
|
|
631
|
-
else: {
|
|
632
|
-
properties: {
|
|
633
|
-
field_b: false,
|
|
634
|
-
},
|
|
635
|
-
},
|
|
636
|
-
},
|
|
637
|
-
],
|
|
638
|
-
};
|
|
639
|
-
|
|
640
|
-
it('handles true case', () => {
|
|
641
|
-
const { fields, handleValidation } = createHeadlessForm(schema, { strictInputType: false });
|
|
642
|
-
|
|
643
|
-
expect(fields[1].isVisible).toBe(false);
|
|
644
|
-
expect(handleValidation({ field_a: { min: 100 } }).formErrors).toEqual({
|
|
645
|
-
field_b: 'Required field',
|
|
646
|
-
});
|
|
647
|
-
expect(fields[1].isVisible).toBe(true);
|
|
648
|
-
});
|
|
649
|
-
|
|
650
|
-
it('handles false case', () => {
|
|
651
|
-
const { fields, handleValidation } = createHeadlessForm(schema, { strictInputType: false });
|
|
652
|
-
|
|
653
|
-
expect(fields[1].isVisible).toBe(false);
|
|
654
|
-
expect(handleValidation({ field_a: { min: 1 } }).formErrors).toBeUndefined();
|
|
655
|
-
expect(fields[1].isVisible).toBe(false);
|
|
656
|
-
});
|
|
657
|
-
|
|
658
|
-
it('handles undefined fieldset case', () => {
|
|
659
|
-
const { fields, handleValidation } = createHeadlessForm(schema, { strictInputType: false });
|
|
660
|
-
|
|
661
|
-
expect(fields[1].isVisible).toBe(false);
|
|
662
|
-
expect(handleValidation({}).formErrors).toBeUndefined();
|
|
663
|
-
expect(fields[1].isVisible).toBe(false);
|
|
664
|
-
});
|
|
665
|
-
});
|
|
666
|
-
|
|
667
599
|
describe('Conditionals - bugs and code-smells', () => {
|
|
668
600
|
// Why do we have these bugs?
|
|
669
601
|
// To be honest we never realized it much later later.
|
|
@@ -63,6 +63,7 @@ import {
|
|
|
63
63
|
schemaForErrorMessageSpecificity,
|
|
64
64
|
jsfConfigForErrorMessageSpecificity,
|
|
65
65
|
schemaInputTypeFile,
|
|
66
|
+
schemaWithSelectInteger,
|
|
66
67
|
} from './helpers';
|
|
67
68
|
import { mockConsole, restoreConsoleAndEnsureItWasNotCalled } from './testUtils';
|
|
68
69
|
import { createHeadlessForm } from '@/createHeadlessForm';
|
|
@@ -657,6 +658,27 @@ describe('createHeadlessForm', () => {
|
|
|
657
658
|
],
|
|
658
659
|
});
|
|
659
660
|
});
|
|
661
|
+
|
|
662
|
+
it('supports "select" field with integer values', async () => {
|
|
663
|
+
const { handleValidation } = createHeadlessForm(schemaWithSelectInteger);
|
|
664
|
+
const validateForm = (vals) => friendlyError(handleValidation(vals));
|
|
665
|
+
|
|
666
|
+
// Check for invalid option
|
|
667
|
+
expect(
|
|
668
|
+
validateForm({
|
|
669
|
+
account_type: 4,
|
|
670
|
+
})
|
|
671
|
+
).toEqual({
|
|
672
|
+
account_type: 'The option 4 is not valid.',
|
|
673
|
+
});
|
|
674
|
+
|
|
675
|
+
// Check for valid option
|
|
676
|
+
expect(
|
|
677
|
+
validateForm({
|
|
678
|
+
account_type: 1,
|
|
679
|
+
})
|
|
680
|
+
).toBeUndefined();
|
|
681
|
+
});
|
|
660
682
|
});
|
|
661
683
|
describe('support "radio" field type', () => {
|
|
662
684
|
it('support "radio" field type @deprecated', () => {
|
package/src/tests/helpers.js
CHANGED
|
@@ -2327,3 +2327,24 @@ export const schemaWithCustomValidationsAndConditionals = {
|
|
|
2327
2327
|
},
|
|
2328
2328
|
],
|
|
2329
2329
|
};
|
|
2330
|
+
|
|
2331
|
+
export const schemaWithSelectInteger = {
|
|
2332
|
+
additionalProperties: false,
|
|
2333
|
+
type: 'object',
|
|
2334
|
+
properties: {
|
|
2335
|
+
account_type: {
|
|
2336
|
+
title: 'Select an account type',
|
|
2337
|
+
description: '',
|
|
2338
|
+
'x-jsf-presentation': {
|
|
2339
|
+
inputType: 'select',
|
|
2340
|
+
},
|
|
2341
|
+
oneOf: [
|
|
2342
|
+
{ title: 'Normal User', const: 0 },
|
|
2343
|
+
{ title: 'Business', const: 1 },
|
|
2344
|
+
{ title: 'Services Provider', const: 2 },
|
|
2345
|
+
],
|
|
2346
|
+
type: 'integer',
|
|
2347
|
+
},
|
|
2348
|
+
},
|
|
2349
|
+
required: [],
|
|
2350
|
+
};
|