@remoteoss/json-schema-form 0.9.1-dev.20240320135936 → 0.9.1-dev.20240321210726

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 CHANGED
@@ -1,8 +1,8 @@
1
1
 
2
2
  /*!
3
3
  Copyright (c) 2024 Remote Technology, Inc.
4
- NPM Package: @remoteoss/json-schema-form@0.9.1-dev.20240320135936
5
- Generated: Wed, 20 Mar 2024 13:59:53 GMT
4
+ NPM Package: @remoteoss/json-schema-form@0.9.1-dev.20240321210726
5
+ Generated: Thu, 21 Mar 2024 21:07:37 GMT
6
6
 
7
7
  MIT License
8
8
 
@@ -457,6 +457,15 @@ var validateMaxDate = (value, minDate) => {
457
457
  const compare = compareDates(value, minDate);
458
458
  return compare === "LESSER" || compare === "EQUAL" ? true : false;
459
459
  };
460
+ var validateRadioOrSelectOptions = (value, options) => {
461
+ if (value === void 0)
462
+ return true;
463
+ const exactMatch = options.some((option) => option.value === value);
464
+ if (exactMatch)
465
+ return true;
466
+ const patternMatch = options.some((option) => option.pattern?.test(value));
467
+ return !!patternMatch;
468
+ };
460
469
  var yupSchemas = {
461
470
  text: validateOnlyStrings,
462
471
  radioOrSelectString: (options) => {
@@ -469,28 +478,9 @@ var yupSchemas = {
469
478
  }
470
479
  return value === null ? void 0 : value;
471
480
  }).test(
472
- /*
473
- Custom test determines if the value either:
474
- - Matches a specific option by value
475
- - Matches a pattern
476
- If the option is undefined do not test, to allow for optional fields.
477
- */
478
481
  "matchesOptionOrPattern",
479
482
  ({ value }) => `The option ${JSON.stringify(value)} is not valid.`,
480
- (value) => {
481
- if (value === void 0) {
482
- return true;
483
- }
484
- const exactMatch = options.some((option) => option.value === value);
485
- if (exactMatch) {
486
- return true;
487
- }
488
- const patternMatch = options.some((option) => option.pattern?.test(value));
489
- if (patternMatch) {
490
- return true;
491
- }
492
- return false;
493
- }
483
+ (value) => validateRadioOrSelectOptions(value, options)
494
484
  );
495
485
  },
496
486
  date: ({ minDate, maxDate }) => {
@@ -519,9 +509,22 @@ var yupSchemas = {
519
509
  }
520
510
  return dateString;
521
511
  },
522
- radioOrSelectNumber: (options) => (0, import_yup.mixed)().typeError("The value must be a number").oneOf(options, ({ value }) => {
523
- return `The option ${JSON.stringify(value)} is not valid.`;
524
- }).nullable(),
512
+ radioOrSelectNumber: (options) => (0, import_yup.mixed)().typeError("The value must be a number").transform((value) => {
513
+ if (options?.some((option) => option.value === null)) {
514
+ return value;
515
+ }
516
+ return value === null ? void 0 : value;
517
+ }).test(
518
+ "matchesOptionOrPattern",
519
+ ({ value }) => {
520
+ return `The option ${JSON.stringify(value)} is not valid.`;
521
+ },
522
+ (value) => {
523
+ if (value !== void 0 && typeof value !== "number")
524
+ return false;
525
+ return validateRadioOrSelectOptions(value, options);
526
+ }
527
+ ).nullable(),
525
528
  number: (0, import_yup.number)().typeError("The value must be a number").nullable(),
526
529
  file: (0, import_yup.array)().nullable(),
527
530
  email: (0, import_yup.string)().trim().email("Please enter a valid email address").nullable(),
@@ -567,13 +570,16 @@ var getOptions = (field) => {
567
570
  };
568
571
  var getYupSchema = ({ inputType, ...field }) => {
569
572
  const jsonType = getJsonTypeInArray(field.jsonType);
570
- if (field.options?.length > 0 && field.jsonType !== "number") {
573
+ const hasOptions = field.options?.length > 0;
574
+ const generateOptionSchema = (type) => {
571
575
  const optionValues = getOptions(field);
572
- return yupSchemas.radioOrSelectString(optionValues);
573
- }
574
- if (field.options?.length > 0 && field.jsonType === "number") {
575
- const optionValues = getOptions(field).map((i) => i.value);
576
- return yupSchemas.radioOrSelectNumber(optionValues);
576
+ return type === "number" ? yupSchemas.radioOrSelectNumber(optionValues) : yupSchemas.radioOrSelectString(optionValues);
577
+ };
578
+ if (hasOptions) {
579
+ if (Array.isArray(field.jsonType)) {
580
+ return field.jsonType.includes("number") ? generateOptionSchema("number") : generateOptionSchema("string");
581
+ }
582
+ return generateOptionSchema(field.jsonType);
577
583
  }
578
584
  if (field.format === "date") {
579
585
  return yupSchemas.date({ minDate: field.minDate, maxDate: field.maxDate });
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
 
2
2
  /*!
3
3
  Copyright (c) 2024 Remote Technology, Inc.
4
- NPM Package: @remoteoss/json-schema-form@0.9.1-dev.20240320135936
5
- Generated: Wed, 20 Mar 2024 13:59:53 GMT
4
+ NPM Package: @remoteoss/json-schema-form@0.9.1-dev.20240321210726
5
+ Generated: Thu, 21 Mar 2024 21:07:37 GMT
6
6
 
7
7
  MIT License
8
8
 
@@ -421,6 +421,15 @@ var validateMaxDate = (value, minDate) => {
421
421
  const compare = compareDates(value, minDate);
422
422
  return compare === "LESSER" || compare === "EQUAL" ? true : false;
423
423
  };
424
+ var validateRadioOrSelectOptions = (value, options) => {
425
+ if (value === void 0)
426
+ return true;
427
+ const exactMatch = options.some((option) => option.value === value);
428
+ if (exactMatch)
429
+ return true;
430
+ const patternMatch = options.some((option) => option.pattern?.test(value));
431
+ return !!patternMatch;
432
+ };
424
433
  var yupSchemas = {
425
434
  text: validateOnlyStrings,
426
435
  radioOrSelectString: (options) => {
@@ -433,28 +442,9 @@ var yupSchemas = {
433
442
  }
434
443
  return value === null ? void 0 : value;
435
444
  }).test(
436
- /*
437
- Custom test determines if the value either:
438
- - Matches a specific option by value
439
- - Matches a pattern
440
- If the option is undefined do not test, to allow for optional fields.
441
- */
442
445
  "matchesOptionOrPattern",
443
446
  ({ value }) => `The option ${JSON.stringify(value)} is not valid.`,
444
- (value) => {
445
- if (value === void 0) {
446
- return true;
447
- }
448
- const exactMatch = options.some((option) => option.value === value);
449
- if (exactMatch) {
450
- return true;
451
- }
452
- const patternMatch = options.some((option) => option.pattern?.test(value));
453
- if (patternMatch) {
454
- return true;
455
- }
456
- return false;
457
- }
447
+ (value) => validateRadioOrSelectOptions(value, options)
458
448
  );
459
449
  },
460
450
  date: ({ minDate, maxDate }) => {
@@ -483,9 +473,22 @@ var yupSchemas = {
483
473
  }
484
474
  return dateString;
485
475
  },
486
- radioOrSelectNumber: (options) => mixed().typeError("The value must be a number").oneOf(options, ({ value }) => {
487
- return `The option ${JSON.stringify(value)} is not valid.`;
488
- }).nullable(),
476
+ radioOrSelectNumber: (options) => mixed().typeError("The value must be a number").transform((value) => {
477
+ if (options?.some((option) => option.value === null)) {
478
+ return value;
479
+ }
480
+ return value === null ? void 0 : value;
481
+ }).test(
482
+ "matchesOptionOrPattern",
483
+ ({ value }) => {
484
+ return `The option ${JSON.stringify(value)} is not valid.`;
485
+ },
486
+ (value) => {
487
+ if (value !== void 0 && typeof value !== "number")
488
+ return false;
489
+ return validateRadioOrSelectOptions(value, options);
490
+ }
491
+ ).nullable(),
489
492
  number: number().typeError("The value must be a number").nullable(),
490
493
  file: array().nullable(),
491
494
  email: string().trim().email("Please enter a valid email address").nullable(),
@@ -531,13 +534,16 @@ var getOptions = (field) => {
531
534
  };
532
535
  var getYupSchema = ({ inputType, ...field }) => {
533
536
  const jsonType = getJsonTypeInArray(field.jsonType);
534
- if (field.options?.length > 0 && field.jsonType !== "number") {
537
+ const hasOptions = field.options?.length > 0;
538
+ const generateOptionSchema = (type) => {
535
539
  const optionValues = getOptions(field);
536
- return yupSchemas.radioOrSelectString(optionValues);
537
- }
538
- if (field.options?.length > 0 && field.jsonType === "number") {
539
- const optionValues = getOptions(field).map((i) => i.value);
540
- return yupSchemas.radioOrSelectNumber(optionValues);
540
+ return type === "number" ? yupSchemas.radioOrSelectNumber(optionValues) : yupSchemas.radioOrSelectString(optionValues);
541
+ };
542
+ if (hasOptions) {
543
+ if (Array.isArray(field.jsonType)) {
544
+ return field.jsonType.includes("number") ? generateOptionSchema("number") : generateOptionSchema("string");
545
+ }
546
+ return generateOptionSchema(field.jsonType);
541
547
  }
542
548
  if (field.format === "date") {
543
549
  return yupSchemas.date({ minDate: field.minDate, maxDate: field.maxDate });
@@ -1,8 +1,8 @@
1
1
 
2
2
  /*!
3
3
  Copyright (c) 2024 Remote Technology, Inc.
4
- NPM Package: @remoteoss/json-schema-form@0.9.1-dev.20240320135936
5
- Generated: Wed, 20 Mar 2024 13:59:53 GMT
4
+ NPM Package: @remoteoss/json-schema-form@0.9.1-dev.20240321210726
5
+ Generated: Thu, 21 Mar 2024 21:07:37 GMT
6
6
 
7
7
  MIT License
8
8
 
@@ -11775,6 +11775,15 @@ var validateMaxDate = (value, minDate) => {
11775
11775
  const compare = compareDates(value, minDate);
11776
11776
  return compare === "LESSER" || compare === "EQUAL" ? true : false;
11777
11777
  };
11778
+ var validateRadioOrSelectOptions = (value, options) => {
11779
+ if (value === void 0)
11780
+ return true;
11781
+ const exactMatch = options.some((option) => option.value === value);
11782
+ if (exactMatch)
11783
+ return true;
11784
+ const patternMatch = options.some((option) => option.pattern?.test(value));
11785
+ return !!patternMatch;
11786
+ };
11778
11787
  var yupSchemas = {
11779
11788
  text: validateOnlyStrings,
11780
11789
  radioOrSelectString: (options) => {
@@ -11787,28 +11796,9 @@ var yupSchemas = {
11787
11796
  }
11788
11797
  return value === null ? void 0 : value;
11789
11798
  }).test(
11790
- /*
11791
- Custom test determines if the value either:
11792
- - Matches a specific option by value
11793
- - Matches a pattern
11794
- If the option is undefined do not test, to allow for optional fields.
11795
- */
11796
11799
  "matchesOptionOrPattern",
11797
11800
  ({ value }) => `The option ${JSON.stringify(value)} is not valid.`,
11798
- (value) => {
11799
- if (value === void 0) {
11800
- return true;
11801
- }
11802
- const exactMatch = options.some((option) => option.value === value);
11803
- if (exactMatch) {
11804
- return true;
11805
- }
11806
- const patternMatch = options.some((option) => option.pattern?.test(value));
11807
- if (patternMatch) {
11808
- return true;
11809
- }
11810
- return false;
11811
- }
11801
+ (value) => validateRadioOrSelectOptions(value, options)
11812
11802
  );
11813
11803
  },
11814
11804
  date: ({ minDate, maxDate }) => {
@@ -11837,9 +11827,22 @@ var yupSchemas = {
11837
11827
  }
11838
11828
  return dateString;
11839
11829
  },
11840
- radioOrSelectNumber: (options) => SchemaType().typeError("The value must be a number").oneOf(options, ({ value }) => {
11841
- return `The option ${JSON.stringify(value)} is not valid.`;
11842
- }).nullable(),
11830
+ radioOrSelectNumber: (options) => SchemaType().typeError("The value must be a number").transform((value) => {
11831
+ if (options?.some((option) => option.value === null)) {
11832
+ return value;
11833
+ }
11834
+ return value === null ? void 0 : value;
11835
+ }).test(
11836
+ "matchesOptionOrPattern",
11837
+ ({ value }) => {
11838
+ return `The option ${JSON.stringify(value)} is not valid.`;
11839
+ },
11840
+ (value) => {
11841
+ if (value !== void 0 && typeof value !== "number")
11842
+ return false;
11843
+ return validateRadioOrSelectOptions(value, options);
11844
+ }
11845
+ ).nullable(),
11843
11846
  number: NumberSchema().typeError("The value must be a number").nullable(),
11844
11847
  file: array_default().nullable(),
11845
11848
  email: StringSchema().trim().email("Please enter a valid email address").nullable(),
@@ -11885,13 +11888,16 @@ var getOptions = (field) => {
11885
11888
  };
11886
11889
  var getYupSchema = ({ inputType, ...field }) => {
11887
11890
  const jsonType = getJsonTypeInArray(field.jsonType);
11888
- if (field.options?.length > 0 && field.jsonType !== "number") {
11891
+ const hasOptions = field.options?.length > 0;
11892
+ const generateOptionSchema = (type) => {
11889
11893
  const optionValues = getOptions(field);
11890
- return yupSchemas.radioOrSelectString(optionValues);
11891
- }
11892
- if (field.options?.length > 0 && field.jsonType === "number") {
11893
- const optionValues = getOptions(field).map((i) => i.value);
11894
- return yupSchemas.radioOrSelectNumber(optionValues);
11894
+ return type === "number" ? yupSchemas.radioOrSelectNumber(optionValues) : yupSchemas.radioOrSelectString(optionValues);
11895
+ };
11896
+ if (hasOptions) {
11897
+ if (Array.isArray(field.jsonType)) {
11898
+ return field.jsonType.includes("number") ? generateOptionSchema("number") : generateOptionSchema("string");
11899
+ }
11900
+ return generateOptionSchema(field.jsonType);
11895
11901
  }
11896
11902
  if (field.format === "date") {
11897
11903
  return yupSchemas.date({ minDate: field.minDate, maxDate: field.maxDate });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remoteoss/json-schema-form",
3
- "version": "0.9.1-dev.20240320135936",
3
+ "version": "0.9.1-dev.20240321210726",
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",
@@ -195,7 +195,7 @@ describe('const/default with forced values', () => {
195
195
  });
196
196
 
197
197
  describe('OneOf const', () => {
198
- it('Validates numbers correctly', () => {
198
+ it('Validates numbers or strings correctly', () => {
199
199
  const { handleValidation } = createHeadlessForm(
200
200
  {
201
201
  properties: {
@@ -214,22 +214,23 @@ describe('OneOf const', () => {
214
214
  });
215
215
  });
216
216
 
217
- it('Validates strings', () => {
217
+ it('Validates numbers or strings when type is an array with null', () => {
218
218
  const { handleValidation } = createHeadlessForm(
219
219
  {
220
220
  properties: {
221
- number: { type: 'number', oneOf: [{ const: 'a' }, { const: 'b' }, { const: 'c' }] },
221
+ number: { type: ['number', 'null'], oneOf: [{ const: 0 }, { const: 1 }, { const: 2 }] },
222
222
  },
223
223
  },
224
224
  { strictInputType: false }
225
225
  );
226
226
  expect(handleValidation({}).formErrors).toEqual(undefined);
227
- expect(handleValidation({ number: 'd' }).formErrors).toEqual({
228
- number: 'The option "d" is not valid.',
227
+ expect(handleValidation({ number: 3 }).formErrors).toEqual({
228
+ number: 'The option 3 is not valid.',
229
229
  });
230
- expect(handleValidation({ number: 'a' }).formErrors).toBeUndefined();
230
+ expect(handleValidation({ number: 2 }).formErrors).toBeUndefined();
231
231
  expect(handleValidation({ number: '2' }).formErrors).toEqual({
232
232
  number: 'The option "2" is not valid.',
233
233
  });
234
+ expect(handleValidation({ number: null }).formErrors).toEqual(undefined);
234
235
  });
235
236
  });
@@ -2028,6 +2028,45 @@ describe('createHeadlessForm', () => {
2028
2028
  });
2029
2029
  });
2030
2030
 
2031
+ it('supports oneOf number const', () => {
2032
+ const result = createHeadlessForm({
2033
+ type: 'object',
2034
+ additionalProperties: false,
2035
+ properties: {
2036
+ pets: {
2037
+ title: 'How many pets?',
2038
+ oneOf: [
2039
+ {
2040
+ title: 'One',
2041
+ const: 0,
2042
+ },
2043
+ {
2044
+ title: 'Two',
2045
+ const: 2,
2046
+ },
2047
+ {
2048
+ title: 'null',
2049
+ const: 1,
2050
+ },
2051
+ ],
2052
+ 'x-jsf-presentation': {
2053
+ inputType: 'select',
2054
+ },
2055
+ type: ['number', 'null'],
2056
+ },
2057
+ },
2058
+ required: [],
2059
+ 'x-jsf-order': ['pets'],
2060
+ });
2061
+
2062
+ const fieldValidator = result.fields[0].schema;
2063
+
2064
+ expect(fieldValidator.isValidSync(0)).toBe(true);
2065
+ expect(fieldValidator.isValidSync(1)).toBe(true);
2066
+ expect(() => fieldValidator.validateSync('2')).toThrowError('The option "2" is not valid.');
2067
+ expect(fieldValidator.isValidSync(null)).toBe(true);
2068
+ });
2069
+
2031
2070
  describe('x-jsf-presentation attribute', () => {
2032
2071
  it('support field with "x-jsf-presentation.statement"', () => {
2033
2072
  const result = createHeadlessForm(schemaInputWithStatement);