@remoteoss/json-schema-form 0.1.1-dev.20230619163824 → 0.3.0-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.
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Shorthand to lookup for keys with `x-jsf-*` preffix.
3
+ */
4
+ export function pickXKey(node: Object, key: 'presentation' | 'errorMessage'): Object | undefined;
5
+
6
+ type ValidationTypes =
7
+ | 'type'
8
+ | 'minimum'
9
+ | 'maximum'
10
+ | 'minLength'
11
+ | 'maxLength'
12
+ | 'pattern'
13
+ | 'maxFileSize'
14
+ | 'accept'
15
+ | 'required';
16
+
17
+ type JSFConfig = {
18
+ /**
19
+ * Initial json values to prefill the form fields.
20
+ * This influences the initial visibility of conditional fields.
21
+ */
22
+ initialValues?: Record<string, unknown>;
23
+ /**
24
+ * It inforces all json properties (fields) to have x-jsf-presentation.inputType.
25
+ @default true
26
+ */
27
+ strictInputType?: boolean;
28
+ /**
29
+ * Customize the output of a given named Field.
30
+ * Useful if you want to enhance the UI/UX of a particular field.
31
+ * @example
32
+ * { has_pet: { "optionsDirection": "horizontal" } }
33
+ */
34
+ customProperties?: {
35
+ description?: (description: string, field: $TSFixMe) => string | string;
36
+ [key: string]: unknown;
37
+ };
38
+ /**
39
+ * Customize the config for each inputType
40
+ */
41
+ inputTypes?: {
42
+ /**
43
+ * Customize the error error message of this input type.
44
+ * @example
45
+ * { required: "This number is required." }
46
+ */
47
+ errorMessage?: Partial<Record<ValidationTypes, string>>;
48
+ };
49
+ };
50
+ type Fields = Record<string, unknown>[]; //TODO: Type the field based on the given JSON Schema properties.
51
+
52
+ type $TSFixMe = any;
53
+
54
+ /**
55
+ * Returns the Yup schema structure of given fields.
56
+ * These fields must be the same from
57
+ * const { fields } = createHeadlessForm()
58
+ */
59
+ export function buildCompleteYupSchema(fields: Fields, config: JSFConfig): $TSFixMe; //TODO: We need to update Yup to 1.0 which supports TS.
60
+
61
+ type HeadlessFormOutput = {
62
+ /**
63
+ * List of Fields. Each Field corresponds to a form input from the json schema.
64
+ * @example
65
+ * [
66
+ {
67
+ name: "has_pet",
68
+ label: "Has Pet",
69
+ options: [
70
+ { label: "Yes", value: "yes" },
71
+ { label: "No", value: "no" }
72
+ ],
73
+ required: true,
74
+ inputType: "radio",
75
+ jsonType: "string",
76
+ description: "Do you have a pet?",
77
+ errorMessage: {},
78
+ isVisible: true
79
+ },
80
+ {
81
+ type: "text",
82
+ label: "Pet's name",
83
+ description: "What's your pet's name?",
84
+ required: false,
85
+ inputType: "text",
86
+ jsonType: "string",
87
+ isVisible: false
88
+ }
89
+ * ]
90
+ */
91
+ fields: Fields;
92
+ /**
93
+ * Validates given values and returns the respective errors.
94
+ * @example
95
+ * const { formErrors } = handleValidation({ has_pet: "yes" });
96
+ * console.log(formErrors) // { pet_name: "Required field." }
97
+ */
98
+ handleValidation: (values: Record<string, unknown>) => {
99
+ yupError: $TSFixMe;
100
+ formErrors: $TSFixMe;
101
+ };
102
+ isError: boolean;
103
+ error?: Error;
104
+ };
105
+
106
+ type JSONSchemaObjectType = Record<string, unknown>;
107
+
108
+ /**
109
+ * Generates the Headless form based on the provided JSON schema
110
+ */
111
+ export function createHeadlessForm(
112
+ /** A JSON Schema of type object */
113
+ jsonSchema: JSONSchemaObjectType,
114
+ customConfig?: JSFConfig
115
+ ): HeadlessFormOutput;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remoteoss/json-schema-form",
3
- "version": "0.1.1-dev.20230619163824",
3
+ "version": "0.3.0-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",
@@ -11,10 +11,12 @@
11
11
  },
12
12
  "main": "dist/index.cjs",
13
13
  "module": "dist/index.js",
14
+ "typings": "./json-schema-form.d.ts",
14
15
  "files": [
15
16
  "dist",
16
17
  "src/tests",
17
18
  "json-schema-form.schema.json",
19
+ "json-schema-form.d.ts",
18
20
  "README.md",
19
21
  "CHANGELOG.md",
20
22
  "LICENSE.md"
@@ -16,6 +16,7 @@ import {
16
16
  schemaInputTypeSelectMultiple,
17
17
  schemaInputTypeSelectMultipleOptional,
18
18
  schemaInputTypeNumber,
19
+ schemaInputTypeNumberZeroMaximum,
19
20
  schemaInputTypeDate,
20
21
  schemaInputTypeEmail,
21
22
  schemaInputWithStatement,
@@ -435,10 +436,10 @@ describe('createHeadlessForm', () => {
435
436
  });
436
437
 
437
438
  const fieldValidator = fields[0].schema;
438
- expect(fieldValidator.isValidSync('CI007', { strict: true })).toBe(true);
439
- expect(fieldValidator.isValidSync(true, { strict: true })).toBe(false);
440
- expect(fieldValidator.isValidSync(1, { strict: true })).toBe(false);
441
- expect(fieldValidator.isValidSync(0, { strict: true })).toBe(false);
439
+ expect(fieldValidator.isValidSync('CI007')).toBe(true);
440
+ expect(fieldValidator.isValidSync(true)).toBe(false);
441
+ expect(fieldValidator.isValidSync(1)).toBe(false);
442
+ expect(fieldValidator.isValidSync(0)).toBe(false);
442
443
 
443
444
  expect(handleValidation({ id_number: 1 }).formErrors).toEqual({
444
445
  id_number: 'id_number must be a `string` type, but the final value was: `1`.',
@@ -1843,6 +1844,19 @@ describe('createHeadlessForm', () => {
1843
1844
  ).resolves.toEqual(assertObj);
1844
1845
  });
1845
1846
  });
1847
+ describe('and maximum is set to zero', () => {
1848
+ it('shows the correct validation', () => {
1849
+ const { handleValidation } = createHeadlessForm(schemaInputTypeNumberZeroMaximum);
1850
+ const validateForm = (vals) => friendlyError(handleValidation(vals));
1851
+
1852
+ expect(validateForm({ tabs: '0' })).toBeUndefined();
1853
+ expect(validateForm({ tabs: '-10' })).toBeUndefined();
1854
+
1855
+ expect(validateForm({ tabs: 1 })).toEqual({
1856
+ tabs: 'Must be smaller or equal to 0',
1857
+ });
1858
+ });
1859
+ });
1846
1860
  });
1847
1861
 
1848
1862
  describe('when a field has a maxLength of 10', () => {
@@ -46,6 +46,21 @@ export const mockNumberInput = {
46
46
  type: 'number',
47
47
  };
48
48
 
49
+ export const schemaInputTypeNumberZeroMaximum = {
50
+ properties: {
51
+ tabs: {
52
+ title: 'Tabs',
53
+ description: 'How many open tabs do you have?',
54
+ 'x-jsf-presentation': {
55
+ inputType: 'number',
56
+ },
57
+ minimum: -100,
58
+ maximum: 0,
59
+ type: 'number',
60
+ },
61
+ },
62
+ };
63
+
49
64
  export const mockNumberInputWithPercentage = {
50
65
  title: 'Shares',
51
66
  description: 'What % of shares do you own?',