@remoteoss/json-schema-form 0.12.0-beta.0 → 0.12.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 +6 -0
- package/dist/index.cjs +13 -6
- package/dist/index.js +12 -6
- package/dist/standalone.js +12 -6
- package/package.json +2 -5
- package/src/tests/createHeadlessForm.test.js +22 -0
- package/src/tests/jsonLogic.fixtures.js +50 -2
- package/src/tests/jsonLogic.test.js +14 -2
- package/LICENSE +0 -21
- package/README.md +0 -44
- package/json-schema-form.schema.json +0 -188
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
#### 0.12.1-beta.0 (2025-10-09)
|
|
2
|
+
|
|
3
|
+
##### Bug Fixes
|
|
4
|
+
|
|
5
|
+
* **checkbox:** Support optional boolean type for v0 ([#236](https://github.com/remoteoss/json-schema-form/pull/236)) ([76e8927f](https://github.com/remoteoss/json-schema-form/commit/76e8927fc2f4615620fe34eef303b2f9c8c81e6e))
|
|
6
|
+
|
|
1
7
|
#### 0.12.0-beta.0 (2025-06-25)
|
|
2
8
|
|
|
3
9
|
##### New Features
|
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.12.
|
|
5
|
-
Generated:
|
|
4
|
+
NPM Package: @remoteoss/json-schema-form@0.12.1-beta.0
|
|
5
|
+
Generated: Thu, 09 Oct 2025 03:22:56 GMT
|
|
6
6
|
|
|
7
7
|
MIT License
|
|
8
8
|
|
|
@@ -27,6 +27,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
|
27
27
|
SOFTWARE.
|
|
28
28
|
|
|
29
29
|
*/
|
|
30
|
+
"use strict";
|
|
30
31
|
var __create = Object.create;
|
|
31
32
|
var __defProp = Object.defineProperty;
|
|
32
33
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -1065,20 +1066,26 @@ function validateInlineRules(jsonSchema, sampleEmptyObject) {
|
|
|
1065
1066
|
});
|
|
1066
1067
|
});
|
|
1067
1068
|
}
|
|
1068
|
-
function checkRuleIntegrity(rule, id, data, errorMessage = (item) => `[json-schema-form] json-logic error: rule "${id}" has no variable "${item.var}"
|
|
1069
|
+
function checkRuleIntegrity(rule, id, data, errorMessage = (item) => `[json-schema-form] json-logic error: rule "${id}" has no variable "${item.var}".`, inReduceOrMap = false) {
|
|
1069
1070
|
Object.entries(rule ?? {}).map(([operator, subRule]) => {
|
|
1070
1071
|
if (!Array.isArray(subRule) && subRule !== null && subRule !== void 0)
|
|
1071
1072
|
return;
|
|
1072
1073
|
throwIfUnknownOperator(operator, subRule, id);
|
|
1074
|
+
const isReduceOrMap = inReduceOrMap || operator === "reduce" || operator === "map";
|
|
1075
|
+
const validationData = isReduceOrMap ? {
|
|
1076
|
+
...data,
|
|
1077
|
+
accumulator: 0,
|
|
1078
|
+
current: null
|
|
1079
|
+
} : data;
|
|
1073
1080
|
subRule.map((item) => {
|
|
1074
1081
|
const isVar = item !== null && typeof item === "object" && Object.hasOwn(item, "var");
|
|
1075
1082
|
if (isVar) {
|
|
1076
|
-
const exists = import_json_logic_js.default.apply({ var: removeIndicesFromPath(item.var) },
|
|
1083
|
+
const exists = import_json_logic_js.default.apply({ var: removeIndicesFromPath(item.var) }, validationData);
|
|
1077
1084
|
if (exists === null) {
|
|
1078
1085
|
throw Error(errorMessage(item));
|
|
1079
1086
|
}
|
|
1080
1087
|
} else {
|
|
1081
|
-
checkRuleIntegrity(item, id, data);
|
|
1088
|
+
checkRuleIntegrity(item, id, data, errorMessage, isReduceOrMap);
|
|
1082
1089
|
}
|
|
1083
1090
|
});
|
|
1084
1091
|
});
|
|
@@ -1506,7 +1513,7 @@ function extractParametersFromNode(schemaNode) {
|
|
|
1506
1513
|
// — For checkboxes that only accept one value (string)
|
|
1507
1514
|
...presentation?.inputType === "checkbox" && { checkboxValue: node.const },
|
|
1508
1515
|
// - For checkboxes with boolean value
|
|
1509
|
-
...presentation?.inputType === "checkbox" && node.type
|
|
1516
|
+
...presentation?.inputType === "checkbox" && hasType(node.type, "boolean") && {
|
|
1510
1517
|
// true is what describes this checkbox as a boolean, regardless if its required or not
|
|
1511
1518
|
checkboxValue: true
|
|
1512
1519
|
},
|
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.12.
|
|
5
|
-
Generated:
|
|
4
|
+
NPM Package: @remoteoss/json-schema-form@0.12.1-beta.0
|
|
5
|
+
Generated: Thu, 09 Oct 2025 03:22:56 GMT
|
|
6
6
|
|
|
7
7
|
MIT License
|
|
8
8
|
|
|
@@ -1028,20 +1028,26 @@ function validateInlineRules(jsonSchema, sampleEmptyObject) {
|
|
|
1028
1028
|
});
|
|
1029
1029
|
});
|
|
1030
1030
|
}
|
|
1031
|
-
function checkRuleIntegrity(rule, id, data, errorMessage = (item) => `[json-schema-form] json-logic error: rule "${id}" has no variable "${item.var}"
|
|
1031
|
+
function checkRuleIntegrity(rule, id, data, errorMessage = (item) => `[json-schema-form] json-logic error: rule "${id}" has no variable "${item.var}".`, inReduceOrMap = false) {
|
|
1032
1032
|
Object.entries(rule ?? {}).map(([operator, subRule]) => {
|
|
1033
1033
|
if (!Array.isArray(subRule) && subRule !== null && subRule !== void 0)
|
|
1034
1034
|
return;
|
|
1035
1035
|
throwIfUnknownOperator(operator, subRule, id);
|
|
1036
|
+
const isReduceOrMap = inReduceOrMap || operator === "reduce" || operator === "map";
|
|
1037
|
+
const validationData = isReduceOrMap ? {
|
|
1038
|
+
...data,
|
|
1039
|
+
accumulator: 0,
|
|
1040
|
+
current: null
|
|
1041
|
+
} : data;
|
|
1036
1042
|
subRule.map((item) => {
|
|
1037
1043
|
const isVar = item !== null && typeof item === "object" && Object.hasOwn(item, "var");
|
|
1038
1044
|
if (isVar) {
|
|
1039
|
-
const exists = jsonLogic.apply({ var: removeIndicesFromPath(item.var) },
|
|
1045
|
+
const exists = jsonLogic.apply({ var: removeIndicesFromPath(item.var) }, validationData);
|
|
1040
1046
|
if (exists === null) {
|
|
1041
1047
|
throw Error(errorMessage(item));
|
|
1042
1048
|
}
|
|
1043
1049
|
} else {
|
|
1044
|
-
checkRuleIntegrity(item, id, data);
|
|
1050
|
+
checkRuleIntegrity(item, id, data, errorMessage, isReduceOrMap);
|
|
1045
1051
|
}
|
|
1046
1052
|
});
|
|
1047
1053
|
});
|
|
@@ -1469,7 +1475,7 @@ function extractParametersFromNode(schemaNode) {
|
|
|
1469
1475
|
// — For checkboxes that only accept one value (string)
|
|
1470
1476
|
...presentation?.inputType === "checkbox" && { checkboxValue: node.const },
|
|
1471
1477
|
// - For checkboxes with boolean value
|
|
1472
|
-
...presentation?.inputType === "checkbox" && node.type
|
|
1478
|
+
...presentation?.inputType === "checkbox" && hasType(node.type, "boolean") && {
|
|
1473
1479
|
// true is what describes this checkbox as a boolean, regardless if its required or not
|
|
1474
1480
|
checkboxValue: true
|
|
1475
1481
|
},
|
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.12.
|
|
5
|
-
Generated:
|
|
4
|
+
NPM Package: @remoteoss/json-schema-form@0.12.1-beta.0
|
|
5
|
+
Generated: Thu, 09 Oct 2025 03:22:56 GMT
|
|
6
6
|
|
|
7
7
|
MIT License
|
|
8
8
|
|
|
@@ -12544,20 +12544,26 @@ function validateInlineRules(jsonSchema, sampleEmptyObject) {
|
|
|
12544
12544
|
});
|
|
12545
12545
|
});
|
|
12546
12546
|
}
|
|
12547
|
-
function checkRuleIntegrity(rule, id, data, errorMessage = (item) => `[json-schema-form] json-logic error: rule "${id}" has no variable "${item.var}"
|
|
12547
|
+
function checkRuleIntegrity(rule, id, data, errorMessage = (item) => `[json-schema-form] json-logic error: rule "${id}" has no variable "${item.var}".`, inReduceOrMap = false) {
|
|
12548
12548
|
Object.entries(rule ?? {}).map(([operator, subRule]) => {
|
|
12549
12549
|
if (!Array.isArray(subRule) && subRule !== null && subRule !== void 0)
|
|
12550
12550
|
return;
|
|
12551
12551
|
throwIfUnknownOperator(operator, subRule, id);
|
|
12552
|
+
const isReduceOrMap = inReduceOrMap || operator === "reduce" || operator === "map";
|
|
12553
|
+
const validationData = isReduceOrMap ? {
|
|
12554
|
+
...data,
|
|
12555
|
+
accumulator: 0,
|
|
12556
|
+
current: null
|
|
12557
|
+
} : data;
|
|
12552
12558
|
subRule.map((item) => {
|
|
12553
12559
|
const isVar = item !== null && typeof item === "object" && Object.hasOwn(item, "var");
|
|
12554
12560
|
if (isVar) {
|
|
12555
|
-
const exists = import_json_logic_js.default.apply({ var: removeIndicesFromPath(item.var) },
|
|
12561
|
+
const exists = import_json_logic_js.default.apply({ var: removeIndicesFromPath(item.var) }, validationData);
|
|
12556
12562
|
if (exists === null) {
|
|
12557
12563
|
throw Error(errorMessage(item));
|
|
12558
12564
|
}
|
|
12559
12565
|
} else {
|
|
12560
|
-
checkRuleIntegrity(item, id, data);
|
|
12566
|
+
checkRuleIntegrity(item, id, data, errorMessage, isReduceOrMap);
|
|
12561
12567
|
}
|
|
12562
12568
|
});
|
|
12563
12569
|
});
|
|
@@ -12985,7 +12991,7 @@ function extractParametersFromNode(schemaNode) {
|
|
|
12985
12991
|
// — For checkboxes that only accept one value (string)
|
|
12986
12992
|
...presentation?.inputType === "checkbox" && { checkboxValue: node.const },
|
|
12987
12993
|
// - For checkboxes with boolean value
|
|
12988
|
-
...presentation?.inputType === "checkbox" && node.type
|
|
12994
|
+
...presentation?.inputType === "checkbox" && hasType(node.type, "boolean") && {
|
|
12989
12995
|
// true is what describes this checkbox as a boolean, regardless if its required or not
|
|
12990
12996
|
checkboxValue: true
|
|
12991
12997
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remoteoss/json-schema-form",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.1-beta.0",
|
|
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",
|
|
@@ -27,19 +27,16 @@
|
|
|
27
27
|
"test:watch": "jest --watchAll",
|
|
28
28
|
"lint": "eslint \"src/**/*.{js,ts}\"",
|
|
29
29
|
"format": "npm run format:prettier && npm run format:eslint",
|
|
30
|
-
"prepare": "husky install",
|
|
30
|
+
"prepare": "cd .. && husky install",
|
|
31
31
|
"format:eslint": "eslint --fix \"src/**/*.{js,ts}\"",
|
|
32
32
|
"format:prettier": "prettier --write \"src/**/*.{js,ts}\"",
|
|
33
33
|
"prettier:check": "prettier --check \"src/**/*.{js,ts}\"",
|
|
34
34
|
"check:pr-version": "node scripts/pr_dev_version",
|
|
35
|
-
"check:pr-next-version": "node scripts/pr_next_dev_version",
|
|
36
35
|
"release:local": "node scripts/release_local",
|
|
37
36
|
"release:dev:patch": "node scripts/release_dev patch",
|
|
38
37
|
"release:dev:minor": "node scripts/release_dev minor",
|
|
39
38
|
"release:main:patch": "node scripts/release_main patch",
|
|
40
39
|
"release:main:minor": "node scripts/release_main minor",
|
|
41
|
-
"release:v1:dev": "node scripts/release_v1 dev",
|
|
42
|
-
"release:v1:beta": "node scripts/release_v1 beta",
|
|
43
40
|
"version_as_main": "node scripts/version_as_main.js",
|
|
44
41
|
"psrepublishOnly": "if [[ ! $PWD =~ scripts$ ]]; then npm run publish:nopublish; fi",
|
|
45
42
|
"psublish:nopublish": "echo 'Use `npm release:*` script instead && exit 1"
|
|
@@ -2327,6 +2327,28 @@ describe('createHeadlessForm', () => {
|
|
|
2327
2327
|
// Explained at "Given values from hidden fields, it does not thrown an error"
|
|
2328
2328
|
expect(handleValidation({ has_pet: false, pet_is_cat: true }).formErrors).toBeUndefined();
|
|
2329
2329
|
});
|
|
2330
|
+
|
|
2331
|
+
it('should set checkboxValue: true for optional boolean type', () => {
|
|
2332
|
+
const schema = {
|
|
2333
|
+
type: 'object',
|
|
2334
|
+
properties: {
|
|
2335
|
+
boolean_checkbox: {
|
|
2336
|
+
title: 'Boolean Checkbox Test',
|
|
2337
|
+
type: ['boolean', 'null'],
|
|
2338
|
+
'x-jsf-presentation': {
|
|
2339
|
+
inputType: 'checkbox',
|
|
2340
|
+
},
|
|
2341
|
+
},
|
|
2342
|
+
},
|
|
2343
|
+
required: [],
|
|
2344
|
+
};
|
|
2345
|
+
|
|
2346
|
+
const result = createHeadlessForm(schema);
|
|
2347
|
+
|
|
2348
|
+
const [optionalCheckbox] = result.fields;
|
|
2349
|
+
expect(optionalCheckbox?.inputType).toBe('checkbox');
|
|
2350
|
+
expect(optionalCheckbox?.checkboxValue).toBe(true);
|
|
2351
|
+
});
|
|
2330
2352
|
});
|
|
2331
2353
|
});
|
|
2332
2354
|
|
|
@@ -1061,7 +1061,7 @@ export const schemaWithReduceAccumulator = {
|
|
|
1061
1061
|
type: 'number',
|
|
1062
1062
|
'x-jsf-logic-computedAttrs': {
|
|
1063
1063
|
const: 'computed_work_hours_per_week',
|
|
1064
|
-
|
|
1064
|
+
default: 'computed_work_hours_per_week',
|
|
1065
1065
|
title: '{{computed_work_hours_per_week}} hours per week',
|
|
1066
1066
|
},
|
|
1067
1067
|
},
|
|
@@ -1073,7 +1073,7 @@ export const schemaWithReduceAccumulator = {
|
|
|
1073
1073
|
'*': [
|
|
1074
1074
|
{ var: 'working_hours_per_day' },
|
|
1075
1075
|
{
|
|
1076
|
-
reduce: [{ var: 'work_days' }, { '+': [{ var:
|
|
1076
|
+
reduce: [{ var: 'work_days' }, { '+': [{ var: 'accumulator' }, 1] }, 0],
|
|
1077
1077
|
},
|
|
1078
1078
|
],
|
|
1079
1079
|
},
|
|
@@ -1081,3 +1081,51 @@ export const schemaWithReduceAccumulator = {
|
|
|
1081
1081
|
},
|
|
1082
1082
|
},
|
|
1083
1083
|
};
|
|
1084
|
+
|
|
1085
|
+
export const schemaWithReduceAccumulatorAndMerge = {
|
|
1086
|
+
properties: {
|
|
1087
|
+
work_days: {
|
|
1088
|
+
items: {
|
|
1089
|
+
anyOf: [
|
|
1090
|
+
{ const: 'monday', title: 'Monday' },
|
|
1091
|
+
{ const: 'tuesday', title: 'Tuesday' },
|
|
1092
|
+
{ const: 'wednesday', title: 'Wednesday' },
|
|
1093
|
+
{ const: 'thursday', title: 'Thursday' },
|
|
1094
|
+
{ const: 'friday', title: 'Friday' },
|
|
1095
|
+
{ const: 'saturday', title: 'Saturday' },
|
|
1096
|
+
{ const: 'sunday', title: 'Sunday' },
|
|
1097
|
+
],
|
|
1098
|
+
},
|
|
1099
|
+
type: 'array',
|
|
1100
|
+
uniqueItems: true,
|
|
1101
|
+
'x-jsf-presentation': {
|
|
1102
|
+
inputType: 'select',
|
|
1103
|
+
},
|
|
1104
|
+
},
|
|
1105
|
+
working_hours_per_day: {
|
|
1106
|
+
type: 'number',
|
|
1107
|
+
},
|
|
1108
|
+
working_hours_per_week: {
|
|
1109
|
+
type: 'number',
|
|
1110
|
+
'x-jsf-logic-computedAttrs': {
|
|
1111
|
+
const: 'computed_work_hours_per_week',
|
|
1112
|
+
default: 'computed_work_hours_per_week',
|
|
1113
|
+
title: '{{computed_work_hours_per_week}} hours per week',
|
|
1114
|
+
},
|
|
1115
|
+
},
|
|
1116
|
+
},
|
|
1117
|
+
'x-jsf-logic': {
|
|
1118
|
+
computedValues: {
|
|
1119
|
+
computed_work_hours_per_week: {
|
|
1120
|
+
rule: {
|
|
1121
|
+
reduce: [
|
|
1122
|
+
{ var: 'work_days' },
|
|
1123
|
+
{ merge: [{ var: 'accumulator' }, [{ var: 'current' }]] },
|
|
1124
|
+
// note we use the wrong accumulator type
|
|
1125
|
+
0,
|
|
1126
|
+
],
|
|
1127
|
+
},
|
|
1128
|
+
},
|
|
1129
|
+
},
|
|
1130
|
+
},
|
|
1131
|
+
};
|
|
@@ -35,6 +35,7 @@ import {
|
|
|
35
35
|
schemaWithValidationThatDoesNotExistOnProperty,
|
|
36
36
|
badSchemaThatWillNotSetAForcedValue,
|
|
37
37
|
schemaWithReduceAccumulator,
|
|
38
|
+
schemaWithReduceAccumulatorAndMerge,
|
|
38
39
|
schemaWithComputedPresentationAttributes,
|
|
39
40
|
} from './jsonLogic.fixtures';
|
|
40
41
|
import { mockConsole, restoreConsoleAndEnsureItWasNotCalled } from './testUtils';
|
|
@@ -245,8 +246,7 @@ describe('jsonLogic: cross-values validations', () => {
|
|
|
245
246
|
});
|
|
246
247
|
});
|
|
247
248
|
|
|
248
|
-
|
|
249
|
-
describe.skip('Reduce', () => {
|
|
249
|
+
describe('Reduce', () => {
|
|
250
250
|
it('reduce: working_hours_per_day * work_days', () => {
|
|
251
251
|
const { fields, handleValidation } = createHeadlessForm(schemaWithReduceAccumulator, {
|
|
252
252
|
strictInputType: false,
|
|
@@ -260,6 +260,18 @@ describe('jsonLogic: cross-values validations', () => {
|
|
|
260
260
|
expect(field.default).toEqual(16);
|
|
261
261
|
expect(field.label).toEqual('16 hours per week');
|
|
262
262
|
});
|
|
263
|
+
|
|
264
|
+
it('reduce: handles when operator is non numerical', () => {
|
|
265
|
+
const { fields, handleValidation } = createHeadlessForm(schemaWithReduceAccumulatorAndMerge, {
|
|
266
|
+
strictInputType: false,
|
|
267
|
+
});
|
|
268
|
+
handleValidation({
|
|
269
|
+
work_days: ['monday', 'tuesday'],
|
|
270
|
+
working_hours_per_day: 8,
|
|
271
|
+
});
|
|
272
|
+
const field = fields.find((i) => i.name === 'working_hours_per_week');
|
|
273
|
+
expect(field.const).toEqual([0, 'monday', 'tuesday']);
|
|
274
|
+
});
|
|
263
275
|
});
|
|
264
276
|
|
|
265
277
|
describe('Logical: ||, &&', () => {
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2023 Remote Technology, Inc.
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
package/README.md
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
<p align="center">
|
|
2
|
-
<img src=".github/media/jsf_logo_dark.png" width="600" alt="json-schema-form">
|
|
3
|
-
</p>
|
|
4
|
-
|
|
5
|
-
<p align="center">
|
|
6
|
-
<code>json-schema-form</code> is a headless UI form library powered by <a href="https://json-schema.org/">JSON Schemas</a>.
|
|
7
|
-
<br/>
|
|
8
|
-
It transforms JSON schemas into Javascript `fields` to be more easily consumed by your UI libraries.
|
|
9
|
-
</p>
|
|
10
|
-
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
### Why JSON Schemas for forms?
|
|
14
|
-
|
|
15
|
-
JSON Schemas are the SSoT (Single Source of Truth) that allows you to share form's data _structure_ and _validations_ between the server (backend) and the client (frontend), regardless of the language used.
|
|
16
|
-
|
|
17
|
-
You can use it beyond UI Forms, like lists, tables, and any other UI that needs structured JSON data.
|
|
18
|
-
|
|
19
|
-
## Installation
|
|
20
|
-
|
|
21
|
-
Available on [NPM](https://www.npmjs.com/package/@remoteoss/json-schema-form).
|
|
22
|
-
|
|
23
|
-
```bash
|
|
24
|
-
npm install @remoteoss/json-schema-form
|
|
25
|
-
# or
|
|
26
|
-
|
|
27
|
-
yarn install @remoteoss/json-schema-form
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
## Getting Started
|
|
31
|
-
|
|
32
|
-
Check the 📚 **[JSF website](https://json-schema-form.vercel.app/)** for documentation.
|
|
33
|
-
|
|
34
|
-
### Playground
|
|
35
|
-
|
|
36
|
-
Check the 🕹️ **[JSF Playground](https://json-schema-form.vercel.app/?path=/docs/playground--docs)** for demos.
|
|
37
|
-
|
|
38
|
-
## Contributing
|
|
39
|
-
|
|
40
|
-
Read [CONTRIBUTING](CONTRIBUTING.md) to get started.
|
|
41
|
-
|
|
42
|
-
We are working on the [next version v1.0](/next). A rewrite in TypeScript with major bugfixes and missing features. It aims to support the latest JSON Schema dialect 2020-12.
|
|
43
|
-
|
|
44
|
-
_Backed by [Remote.com](https://remote.com/)_
|
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
-
"title": "JSON json-schema-form-Schema",
|
|
4
|
-
"definitions": {
|
|
5
|
-
"schemaArray": {
|
|
6
|
-
"allOf": [
|
|
7
|
-
{
|
|
8
|
-
"$ref": "http://json-schema.org/draft-07/schema#/definitions/schemaArray"
|
|
9
|
-
},
|
|
10
|
-
{
|
|
11
|
-
"items": { "$ref": "#" }
|
|
12
|
-
}
|
|
13
|
-
]
|
|
14
|
-
}
|
|
15
|
-
},
|
|
16
|
-
"allOf": [{ "$ref": "http://json-schema.org/draft-07/schema#" }],
|
|
17
|
-
"properties": {
|
|
18
|
-
"additionalItems": { "$ref": "#" },
|
|
19
|
-
"additionalProperties": { "$ref": "#" },
|
|
20
|
-
"dependencies": {
|
|
21
|
-
"additionalProperties": {
|
|
22
|
-
"anyOf": [{ "$ref": "#" }, { "type": "array" }]
|
|
23
|
-
}
|
|
24
|
-
},
|
|
25
|
-
"items": {
|
|
26
|
-
"anyOf": [{ "$ref": "#" }, { "$ref": "#/definitions/schemaArray" }]
|
|
27
|
-
},
|
|
28
|
-
"definitions": {
|
|
29
|
-
"additionalProperties": { "$ref": "#" }
|
|
30
|
-
},
|
|
31
|
-
"patternProperties": {
|
|
32
|
-
"additionalProperties": { "$ref": "#" }
|
|
33
|
-
},
|
|
34
|
-
"properties": {
|
|
35
|
-
"additionalProperties": { "$ref": "#" }
|
|
36
|
-
},
|
|
37
|
-
"if": { "$ref": "#" },
|
|
38
|
-
"then": { "$ref": "#" },
|
|
39
|
-
"else": { "$ref": "#" },
|
|
40
|
-
"allOf": { "$ref": "#/definitions/schemaArray" },
|
|
41
|
-
"anyOf": { "$ref": "#/definitions/schemaArray" },
|
|
42
|
-
"oneOf": { "$ref": "#/definitions/schemaArray" },
|
|
43
|
-
"not": { "$ref": "#" },
|
|
44
|
-
"contains": { "$ref": "#" },
|
|
45
|
-
"propertyNames": { "$ref": "#" },
|
|
46
|
-
"x-jsf-order": {
|
|
47
|
-
"description": "This keyword defines the order of fields for a given form or fieldset. It's placed at the schema root and inside of each fieldset.",
|
|
48
|
-
"$ref": "http://json-schema.org/draft-07/schema#/definitions/stringArray"
|
|
49
|
-
},
|
|
50
|
-
"x-jsf-errorMessage": {
|
|
51
|
-
"type": "object",
|
|
52
|
-
"additionalProperties": false,
|
|
53
|
-
"properties": {
|
|
54
|
-
"type": {
|
|
55
|
-
"type": "string",
|
|
56
|
-
"description": "Message shown when the value is not of the correct type."
|
|
57
|
-
},
|
|
58
|
-
"required": {
|
|
59
|
-
"type": "string",
|
|
60
|
-
"description": "Message shown when the value is required and not provided."
|
|
61
|
-
},
|
|
62
|
-
"minimum": {
|
|
63
|
-
"type": "string",
|
|
64
|
-
"description": "Message shown when the value is less than the minimum value."
|
|
65
|
-
},
|
|
66
|
-
"minLength": {
|
|
67
|
-
"type": "string",
|
|
68
|
-
"description": "Message shown when the value is less than the minimum length."
|
|
69
|
-
},
|
|
70
|
-
"maximum": {
|
|
71
|
-
"type": "string",
|
|
72
|
-
"description": "Message shown when the value is greater than the maximum value."
|
|
73
|
-
},
|
|
74
|
-
"maxLength": {
|
|
75
|
-
"type": "string",
|
|
76
|
-
"description": "Message shown when the value is greater than the maximum length."
|
|
77
|
-
},
|
|
78
|
-
"pattern": {
|
|
79
|
-
"type": "string",
|
|
80
|
-
"description": "Message shown when the value is not the correct format and does not match the pattern property."
|
|
81
|
-
},
|
|
82
|
-
"maxFileSize": {
|
|
83
|
-
"type": "string",
|
|
84
|
-
"description": "Message shown when the file size is greater than the maximum file size."
|
|
85
|
-
},
|
|
86
|
-
"accept": {
|
|
87
|
-
"type": "string",
|
|
88
|
-
"description": "Message shown when the file type is not accepted."
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
},
|
|
92
|
-
"x-jsf-presentation": {
|
|
93
|
-
"type": "object",
|
|
94
|
-
"description": "Presentation overrides for the schema",
|
|
95
|
-
"properties": {
|
|
96
|
-
"inputType": {
|
|
97
|
-
"description": "Input type for the generated UI field",
|
|
98
|
-
"type": "string",
|
|
99
|
-
"anyOf": [
|
|
100
|
-
{
|
|
101
|
-
"const": "text",
|
|
102
|
-
"description": "Similar to the native HTML input with text type."
|
|
103
|
-
},
|
|
104
|
-
{
|
|
105
|
-
"const": "select",
|
|
106
|
-
"description": "Similar to the native HTML select element."
|
|
107
|
-
},
|
|
108
|
-
{
|
|
109
|
-
"const": "radio",
|
|
110
|
-
"description": "Similar to a native HTML input with radio type."
|
|
111
|
-
},
|
|
112
|
-
{
|
|
113
|
-
"const": "number",
|
|
114
|
-
"description": "Similar to the native HTML input with number type."
|
|
115
|
-
},
|
|
116
|
-
{
|
|
117
|
-
"const": "date",
|
|
118
|
-
"description": "Expects a value with format YYY-MM-DD."
|
|
119
|
-
},
|
|
120
|
-
{
|
|
121
|
-
"const": "checkbox",
|
|
122
|
-
"description": "Similar to the native HTML input with checkbox type."
|
|
123
|
-
},
|
|
124
|
-
{
|
|
125
|
-
"const": "email",
|
|
126
|
-
"description": "Similar to the native HTML input with email type."
|
|
127
|
-
},
|
|
128
|
-
{
|
|
129
|
-
"const": "file",
|
|
130
|
-
"description": "Similar to the native HTML input with file type."
|
|
131
|
-
},
|
|
132
|
-
{
|
|
133
|
-
"const": "fieldset",
|
|
134
|
-
"description": "Groups multiple Fields inside. Its expected value is a nested object."
|
|
135
|
-
},
|
|
136
|
-
{
|
|
137
|
-
"const": "group-array",
|
|
138
|
-
"description": "A list of inputs that can be repeated. Its expected value is an array."
|
|
139
|
-
},
|
|
140
|
-
{
|
|
141
|
-
"type": "string",
|
|
142
|
-
"description": "Any arbitrary custom inputType you might want to represent your UI Field."
|
|
143
|
-
}
|
|
144
|
-
]
|
|
145
|
-
},
|
|
146
|
-
"accept": {
|
|
147
|
-
"description": "For `inputType: \"file\"`. The accepted file types, as a comma separated string.",
|
|
148
|
-
"type": "string"
|
|
149
|
-
},
|
|
150
|
-
"description": {
|
|
151
|
-
"description": "Field description with HTML. If you don't need HTML, please use the native description keyword.",
|
|
152
|
-
"type": "string"
|
|
153
|
-
},
|
|
154
|
-
"statement": {
|
|
155
|
-
"description": "Special message about the field. Useful in cases where this message is based on the field value.",
|
|
156
|
-
"type": "object",
|
|
157
|
-
"properties": {
|
|
158
|
-
"title": {
|
|
159
|
-
"type": "string"
|
|
160
|
-
},
|
|
161
|
-
"description": {
|
|
162
|
-
"description": "The sentence itself. Might include HTML.",
|
|
163
|
-
"type": "string"
|
|
164
|
-
},
|
|
165
|
-
"severity": {
|
|
166
|
-
"description": "Defines the type of message.",
|
|
167
|
-
"anyOf": [
|
|
168
|
-
{ "type": "string", "const": "info" },
|
|
169
|
-
{ "type": "string", "const": "warning" },
|
|
170
|
-
{ "type": "string", "const": "error" },
|
|
171
|
-
{ "type": "string", "const": "success" },
|
|
172
|
-
{}
|
|
173
|
-
]
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
},
|
|
177
|
-
"maxFileSize": {
|
|
178
|
-
"description": "For `inputType: \"file\"`. The maximum file size in KB. It's used to enhanced Yup validation.",
|
|
179
|
-
"type": "number"
|
|
180
|
-
},
|
|
181
|
-
"addFieldText": {
|
|
182
|
-
"description": "Used in `group-array` fields. The button text to add a new field.",
|
|
183
|
-
"type": "string"
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
}
|