@remoteoss/json-schema-form 0.1.1-dev.20230619163824 → 0.2.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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ #### 0.2.0-beta.0 (2023-06-20)
2
+
3
+ ##### New Features
4
+
5
+ - Add typescript declarations to the library ([2404188c](https://github.com/remoteoss/json-schema-form/commit/2404188cba52a5a665f257430a65a0ebb938dd44))
6
+
7
+ ##### Fixes
8
+
9
+ - Support maximum 0 ([#10](https://github.com/remoteoss/json-schema-form/pull/10)) ([1e9d6cf9](https://github.com/remoteoss/json-schema-form/commit/1e9d6cf96436cf16018e045b351567c643e10dac))
10
+
11
+ ##### Chores
12
+
13
+ - Add json-schema-form meta schema ([#6](https://github.com/remoteoss/json-schema-form/pull/6)) ([414a5fe2](https://github.com/remoteoss/json-schema-form/commit/414a5fe2cf2b015a8761f554f03bbb507fae1784))
14
+
1
15
  #### 0.1.0-beta.0 (2023-05-18)
2
16
 
3
17
  ##### New Features
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.1.1-dev.20230619163824
5
- Generated: Mon, 19 Jun 2023 16:38:39 GMT
4
+ NPM Package: @remoteoss/json-schema-form@0.2.0-beta.0
5
+ Generated: Tue, 20 Jun 2023 08:31:44 GMT
6
6
 
7
7
  MIT License
8
8
 
@@ -371,18 +371,8 @@ var baseString = (0, import_yup.string)().trim();
371
371
  var todayDateHint = (/* @__PURE__ */ new Date()).toISOString().substring(0, 10);
372
372
  var convertBytesToKB = convertDiskSizeFromTo("Bytes", "KB");
373
373
  var convertKbBytesToMB = convertDiskSizeFromTo("KB", "MB");
374
- var validateOnlyStrings = (0, import_yup.string)().trim().nullable().test(
375
- "is-string",
376
- "${path} must be a `string` type, but the final value was: `${value}`.",
377
- (value, context) => {
378
- if (context.originalValue) {
379
- return typeof context.originalValue === "string";
380
- }
381
- return true;
382
- }
383
- );
384
374
  var yupSchemas = {
385
- text: validateOnlyStrings,
375
+ text: (0, import_yup.string)().trim().nullable(),
386
376
  select: (0, import_yup.string)().trim().nullable(),
387
377
  radio: (0, import_yup.string)().trim().nullable(),
388
378
  date: (0, import_yup.string)().nullable().trim().matches(
@@ -545,7 +535,7 @@ function buildYupSchema(field, config) {
545
535
  if (typeof propertyFields.minLength !== "undefined") {
546
536
  validators.push(withMinLength);
547
537
  }
548
- if (propertyFields.maximum) {
538
+ if (propertyFields.maximum !== void 0) {
549
539
  validators.push(withMax);
550
540
  }
551
541
  if (propertyFields.maxLength) {
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.1.1-dev.20230619163824
5
- Generated: Mon, 19 Jun 2023 16:38:39 GMT
4
+ NPM Package: @remoteoss/json-schema-form@0.2.0-beta.0
5
+ Generated: Tue, 20 Jun 2023 08:31:44 GMT
6
6
 
7
7
  MIT License
8
8
 
@@ -335,18 +335,8 @@ var baseString = string().trim();
335
335
  var todayDateHint = (/* @__PURE__ */ new Date()).toISOString().substring(0, 10);
336
336
  var convertBytesToKB = convertDiskSizeFromTo("Bytes", "KB");
337
337
  var convertKbBytesToMB = convertDiskSizeFromTo("KB", "MB");
338
- var validateOnlyStrings = string().trim().nullable().test(
339
- "is-string",
340
- "${path} must be a `string` type, but the final value was: `${value}`.",
341
- (value, context) => {
342
- if (context.originalValue) {
343
- return typeof context.originalValue === "string";
344
- }
345
- return true;
346
- }
347
- );
348
338
  var yupSchemas = {
349
- text: validateOnlyStrings,
339
+ text: string().trim().nullable(),
350
340
  select: string().trim().nullable(),
351
341
  radio: string().trim().nullable(),
352
342
  date: string().nullable().trim().matches(
@@ -509,7 +499,7 @@ function buildYupSchema(field, config) {
509
499
  if (typeof propertyFields.minLength !== "undefined") {
510
500
  validators.push(withMinLength);
511
501
  }
512
- if (propertyFields.maximum) {
502
+ if (propertyFields.maximum !== void 0) {
513
503
  validators.push(withMax);
514
504
  }
515
505
  if (propertyFields.maxLength) {
@@ -1,8 +1,8 @@
1
1
 
2
2
  /*!
3
3
  Copyright (c) 2023 Remote Technology, Inc.
4
- NPM Package: @remoteoss/json-schema-form@0.1.1-dev.20230619163824
5
- Generated: Mon, 19 Jun 2023 16:38:39 GMT
4
+ NPM Package: @remoteoss/json-schema-form@0.2.0-beta.0
5
+ Generated: Tue, 20 Jun 2023 08:31:44 GMT
6
6
 
7
7
  MIT License
8
8
 
@@ -11311,18 +11311,8 @@ var baseString = StringSchema().trim();
11311
11311
  var todayDateHint = (/* @__PURE__ */ new Date()).toISOString().substring(0, 10);
11312
11312
  var convertBytesToKB = convertDiskSizeFromTo("Bytes", "KB");
11313
11313
  var convertKbBytesToMB = convertDiskSizeFromTo("KB", "MB");
11314
- var validateOnlyStrings = StringSchema().trim().nullable().test(
11315
- "is-string",
11316
- "${path} must be a `string` type, but the final value was: `${value}`.",
11317
- (value, context) => {
11318
- if (context.originalValue) {
11319
- return typeof context.originalValue === "string";
11320
- }
11321
- return true;
11322
- }
11323
- );
11324
11314
  var yupSchemas = {
11325
- text: validateOnlyStrings,
11315
+ text: StringSchema().trim().nullable(),
11326
11316
  select: StringSchema().trim().nullable(),
11327
11317
  radio: StringSchema().trim().nullable(),
11328
11318
  date: StringSchema().nullable().trim().matches(
@@ -11485,7 +11475,7 @@ function buildYupSchema(field, config) {
11485
11475
  if (typeof propertyFields.minLength !== "undefined") {
11486
11476
  validators.push(withMinLength);
11487
11477
  }
11488
- if (propertyFields.maximum) {
11478
+ if (propertyFields.maximum !== void 0) {
11489
11479
  validators.push(withMax);
11490
11480
  }
11491
11481
  if (propertyFields.maxLength) {
@@ -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.2.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"
@@ -22,7 +24,6 @@
22
24
  "scripts": {
23
25
  "build": "node scripts/build.js",
24
26
  "test": "jest",
25
- "test:watch": "jest --watchAll",
26
27
  "lint": "eslint \"src/**/*.{js,ts}\"",
27
28
  "format": "npm run format:prettier && npm run format:eslint",
28
29
  "prepare": "husky install",
@@ -47,7 +48,7 @@
47
48
  "dependencies": {
48
49
  "lodash": "^4.17.21",
49
50
  "randexp": "^0.5.3",
50
- "yup": "^0.30.0"
51
+ "yup": "^0.29.1"
51
52
  },
52
53
  "devDependencies": {
53
54
  "@babel/core": "^7.21.5",
@@ -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,
@@ -419,7 +420,7 @@ describe('createHeadlessForm', () => {
419
420
 
420
421
  describe('field support', () => {
421
422
  it('support "text" field type', () => {
422
- const { fields, handleValidation } = createHeadlessForm(schemaInputTypeText);
423
+ const { fields } = createHeadlessForm(schemaInputTypeText);
423
424
 
424
425
  expect(fields[0]).toMatchObject({
425
426
  description: 'The number of your national identification (max 10 digits)',
@@ -435,14 +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);
442
-
443
- expect(handleValidation({ id_number: 1 }).formErrors).toEqual({
444
- id_number: 'id_number must be a `string` type, but the final value was: `1`.',
445
- });
439
+ expect(fieldValidator.isValidSync('CI007')).toBe(true);
440
+ expect(fieldValidator.isValidSync(true)).toBe(true); // @BUG RMT-446 - cannot be a bool
441
+ expect(fieldValidator.isValidSync(1)).toBe(true); // @BUG RMT-446 - cannot be a number
442
+ expect(fieldValidator.isValidSync(0)).toBe(true); // @BUG RMT-446 - cannot be a number
446
443
 
447
444
  expect(() => fieldValidator.validateSync('')).toThrowError('Required field');
448
445
  });
@@ -1843,6 +1840,19 @@ describe('createHeadlessForm', () => {
1843
1840
  ).resolves.toEqual(assertObj);
1844
1841
  });
1845
1842
  });
1843
+ describe('and maximum is set to zero', () => {
1844
+ it('shows the correct validation', () => {
1845
+ const { handleValidation } = createHeadlessForm(schemaInputTypeNumberZeroMaximum);
1846
+ const validateForm = (vals) => friendlyError(handleValidation(vals));
1847
+
1848
+ expect(validateForm({ tabs: '0' })).toBeUndefined();
1849
+ expect(validateForm({ tabs: '-10' })).toBeUndefined();
1850
+
1851
+ expect(validateForm({ tabs: 1 })).toEqual({
1852
+ tabs: 'Must be smaller or equal to 0',
1853
+ });
1854
+ });
1855
+ });
1846
1856
  });
1847
1857
 
1848
1858
  describe('when a field has a maxLength of 10', () => {
@@ -2317,7 +2327,7 @@ describe('createHeadlessForm', () => {
2317
2327
  validateForm({
2318
2328
  validate_tabs: 'no',
2319
2329
  a_fieldset: {
2320
- id_number: '123',
2330
+ id_number: 123,
2321
2331
  },
2322
2332
  mandatory_group_array: 'no',
2323
2333
  })
@@ -2332,7 +2342,7 @@ describe('createHeadlessForm', () => {
2332
2342
  validateForm({
2333
2343
  validate_tabs: 'yes',
2334
2344
  a_fieldset: {
2335
- id_number: '123',
2345
+ id_number: 123,
2336
2346
  },
2337
2347
  mandatory_group_array: 'no',
2338
2348
  })
@@ -2348,7 +2358,7 @@ describe('createHeadlessForm', () => {
2348
2358
  validateForm({
2349
2359
  validate_tabs: 'yes',
2350
2360
  a_fieldset: {
2351
- id_number: '123',
2361
+ id_number: 123,
2352
2362
  },
2353
2363
  mandatory_group_array: 'yes',
2354
2364
  a_group_array: [{ full_name: 'adfs' }],
@@ -2359,7 +2369,7 @@ describe('createHeadlessForm', () => {
2359
2369
  validateForm({
2360
2370
  validate_tabs: 'yes',
2361
2371
  a_fieldset: {
2362
- id_number: '123',
2372
+ id_number: 123,
2363
2373
  tabs: 2,
2364
2374
  },
2365
2375
  mandatory_group_array: 'no',
@@ -2450,7 +2460,7 @@ describe('createHeadlessForm', () => {
2450
2460
  validateForm({
2451
2461
  validate_fieldset: ['id_number'],
2452
2462
  a_fieldset: {
2453
- id_number: '123',
2463
+ id_number: 123,
2454
2464
  },
2455
2465
  })
2456
2466
  ).toBeUndefined();
@@ -2459,7 +2469,7 @@ describe('createHeadlessForm', () => {
2459
2469
  validateForm({
2460
2470
  validate_fieldset: ['id_number', 'all'],
2461
2471
  a_fieldset: {
2462
- id_number: '123',
2472
+ id_number: 123,
2463
2473
  },
2464
2474
  })
2465
2475
  ).toEqual({
@@ -2472,7 +2482,7 @@ describe('createHeadlessForm', () => {
2472
2482
  validateForm({
2473
2483
  validate_fieldset: ['id_number', 'all'],
2474
2484
  a_fieldset: {
2475
- id_number: '123',
2485
+ id_number: 123,
2476
2486
  tabs: 2,
2477
2487
  },
2478
2488
  })
@@ -2487,7 +2497,7 @@ describe('createHeadlessForm', () => {
2487
2497
  validateForm({
2488
2498
  validate_fieldset: ['id_number'],
2489
2499
  a_fieldset: {
2490
- id_number: '123',
2500
+ id_number: 123,
2491
2501
  },
2492
2502
  })
2493
2503
  ).toBeUndefined();
@@ -2496,7 +2506,7 @@ describe('createHeadlessForm', () => {
2496
2506
  validateForm({
2497
2507
  validate_fieldset: ['id_number', 'all'],
2498
2508
  a_fieldset: {
2499
- id_number: '123',
2509
+ id_number: 123,
2500
2510
  },
2501
2511
  })
2502
2512
  ).toEqual({
@@ -2509,7 +2519,7 @@ describe('createHeadlessForm', () => {
2509
2519
  validateForm({
2510
2520
  validate_fieldset: ['id_number', 'all'],
2511
2521
  a_fieldset: {
2512
- id_number: '123',
2522
+ id_number: 123,
2513
2523
  tabs: 2,
2514
2524
  },
2515
2525
  })
@@ -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?',