@remoteoss/json-schema-form 0.11.1-beta.0 → 0.11.2-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,8 +1,21 @@
1
+ #### 0.11.2-beta.0 (2024-07-30)
2
+
3
+ ##### Bug Fixes
4
+
5
+ - **modify:**
6
+
7
+ - Support x-jsf shorthands in all methods, fix TS declarations; ([#85](https://github.com/remoteoss/json-schema-form/pull/85)) ([9a87c19b](https://github.com/remoteoss/json-schema-form/commit/9a87c19b6d373a8f660dd24b20a48725f3dbe8d0))
8
+
9
+ - **createHeadlessForm:**
10
+
11
+ - mark createHeadlessForm config.customProperties as deprecated ([#85](https://github.com/remoteoss/json-schema-form/pull/85)) ([9a87c19b](https://github.com/remoteoss/json-schema-form/commit/9a87c19b6d373a8f660dd24b20a48725f3dbe8d0))
12
+ - support custom attributes as functions (do not execute them) ([#86](https://github.com/remoteoss/json-schema-form/pull/86)) ([3674fc87](https://github.com/remoteoss/json-schema-form/commit/3674fc87d44df44a5ba9b13b40465c2ccda448ca))
13
+
1
14
  #### 0.11.1-beta.0 (2024-07-26)
2
15
 
3
16
  ##### Chores
4
17
 
5
- * **modify:** Add missing Typescript declarations ([#84](https://github.com/remoteoss/json-schema-form/pull/84)) ([86b3af2a](https://github.com/remoteoss/json-schema-form/commit/86b3af2a31981718ad349ac8d08fbdce3aa86acf))
18
+ - **modify:** Add missing Typescript declarations ([#84](https://github.com/remoteoss/json-schema-form/pull/84)) ([86b3af2a](https://github.com/remoteoss/json-schema-form/commit/86b3af2a31981718ad349ac8d08fbdce3aa86acf))
6
19
 
7
20
  #### 0.11.0-beta.0 (2024-07-25)
8
21
 
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.11.1-beta.0
5
- Generated: Fri, 26 Jul 2024 12:33:47 GMT
4
+ NPM Package: @remoteoss/json-schema-form@0.11.2-beta.0
5
+ Generated: Tue, 30 Jul 2024 12:00:17 GMT
6
6
 
7
7
  MIT License
8
8
 
@@ -1196,7 +1196,10 @@ function updateField(field, requiredFields, node, formValues, logic, config) {
1196
1196
  }
1197
1197
  const updateAttributes = (fieldAttrs) => {
1198
1198
  Object.entries(fieldAttrs).forEach(([key, value]) => {
1199
- field[key] = typeof value === "function" ? value() : value;
1199
+ field[key] = value;
1200
+ if (key === "schema" && typeof value === "function") {
1201
+ field[key] = value();
1202
+ }
1200
1203
  if (key === "value") {
1201
1204
  const readOnlyPropertyWasUpdated = typeof fieldAttrs.readOnly !== "undefined";
1202
1205
  const isReadonlyByDefault = field.readOnly;
@@ -1917,7 +1920,7 @@ function rewriteAllFields(schema, configCallback, context) {
1917
1920
  (0, import_get4.default)(schema.properties, fieldName),
1918
1921
  {
1919
1922
  ...fieldAttrs,
1920
- ...configCallback(fullName, fieldAttrs)
1923
+ ...standardizeAttrs(configCallback(fullName, fieldAttrs))
1921
1924
  },
1922
1925
  mergeReplaceArray
1923
1926
  );
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.11.1-beta.0
5
- Generated: Fri, 26 Jul 2024 12:33:47 GMT
4
+ NPM Package: @remoteoss/json-schema-form@0.11.2-beta.0
5
+ Generated: Tue, 30 Jul 2024 12:00:17 GMT
6
6
 
7
7
  MIT License
8
8
 
@@ -1159,7 +1159,10 @@ function updateField(field, requiredFields, node, formValues, logic, config) {
1159
1159
  }
1160
1160
  const updateAttributes = (fieldAttrs) => {
1161
1161
  Object.entries(fieldAttrs).forEach(([key, value]) => {
1162
- field[key] = typeof value === "function" ? value() : value;
1162
+ field[key] = value;
1163
+ if (key === "schema" && typeof value === "function") {
1164
+ field[key] = value();
1165
+ }
1163
1166
  if (key === "value") {
1164
1167
  const readOnlyPropertyWasUpdated = typeof fieldAttrs.readOnly !== "undefined";
1165
1168
  const isReadonlyByDefault = field.readOnly;
@@ -1880,7 +1883,7 @@ function rewriteAllFields(schema, configCallback, context) {
1880
1883
  get4(schema.properties, fieldName),
1881
1884
  {
1882
1885
  ...fieldAttrs,
1883
- ...configCallback(fullName, fieldAttrs)
1886
+ ...standardizeAttrs(configCallback(fullName, fieldAttrs))
1884
1887
  },
1885
1888
  mergeReplaceArray
1886
1889
  );
@@ -1,8 +1,8 @@
1
1
 
2
2
  /*!
3
3
  Copyright (c) 2024 Remote Technology, Inc.
4
- NPM Package: @remoteoss/json-schema-form@0.11.1-beta.0
5
- Generated: Fri, 26 Jul 2024 12:33:47 GMT
4
+ NPM Package: @remoteoss/json-schema-form@0.11.2-beta.0
5
+ Generated: Tue, 30 Jul 2024 12:00:17 GMT
6
6
 
7
7
  MIT License
8
8
 
@@ -12675,7 +12675,10 @@ function updateField(field, requiredFields, node, formValues, logic, config) {
12675
12675
  }
12676
12676
  const updateAttributes = (fieldAttrs) => {
12677
12677
  Object.entries(fieldAttrs).forEach(([key, value]) => {
12678
- field[key] = typeof value === "function" ? value() : value;
12678
+ field[key] = value;
12679
+ if (key === "schema" && typeof value === "function") {
12680
+ field[key] = value();
12681
+ }
12679
12682
  if (key === "value") {
12680
12683
  const readOnlyPropertyWasUpdated = typeof fieldAttrs.readOnly !== "undefined";
12681
12684
  const isReadonlyByDefault = field.readOnly;
@@ -13396,7 +13399,7 @@ function rewriteAllFields(schema, configCallback, context) {
13396
13399
  (0, import_get5.default)(schema.properties, fieldName),
13397
13400
  {
13398
13401
  ...fieldAttrs,
13399
- ...configCallback(fullName, fieldAttrs)
13402
+ ...standardizeAttrs(configCallback(fullName, fieldAttrs))
13400
13403
  },
13401
13404
  mergeReplaceArray
13402
13405
  );
@@ -106,28 +106,26 @@ type JSONSchemaObjectType = Record<string, unknown>;
106
106
  type FieldName = string;
107
107
  type FieldAttrs = Record<string, unknown>;
108
108
 
109
- type FieldAttrsCallbackFn = (fieldName: FieldName, fieldAttrs: FieldAttrs) => FieldAttrs;
110
-
111
- type ModConfigProperties = Record<FieldName, FieldAttrs | FieldAttrsCallbackFn>;
112
-
113
109
  type ModifyConfig = {
114
110
  /**
115
111
  * An object with the fields to be modified with the returned attributes.
116
112
  */
117
- fields?: ModConfigProperties;
113
+ fields?: Record<FieldName, FieldAttrs | ((fieldAttrs: FieldAttrs) => FieldAttrs)>;
118
114
  /**
119
115
  * A callback function that runs through all fields, to modify them with the returned attributes.
120
116
  */
121
- allFields?: FieldAttrsCallbackFn;
117
+ allFields?: (fieldName: FieldName, fieldAttrs: FieldAttrs) => FieldAttrs;
122
118
  /**
123
119
  * An object of new fields to be created with the new attributes.
124
120
  */
125
- create?: ModConfigProperties;
121
+ create?: Record<FieldName, FieldAttrs>;
126
122
  /**
127
123
  * An array of the fields to keep, removing the remaining fields.
128
124
  */
129
125
  pick?: FieldName[];
130
- /* An array of fieldNames with the new order. Can be an object or callback function */
126
+ /**
127
+ * An array of fieldNames with the new order. Can be an object or callback function
128
+ * */
131
129
  orderRoot?: FieldName[] | ((originalOrder: FieldName[]) => FieldName[]);
132
130
  /**
133
131
  * Mutes any logs or warnings from the library.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remoteoss/json-schema-form",
3
- "version": "0.11.1-beta.0",
3
+ "version": "0.11.2-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",
@@ -2177,6 +2177,75 @@ describe('createHeadlessForm', () => {
2177
2177
  });
2178
2178
  });
2179
2179
 
2180
+ it('pass custom attributes as function', () => {
2181
+ function FakeComponent(props) {
2182
+ const { label, description } = props;
2183
+ return `A React component with ${label} and ${description}`;
2184
+ }
2185
+ // Any custom attributes must be inside "x-jsf-presentation"
2186
+ const { fields, handleValidation } = createHeadlessForm({
2187
+ properties: {
2188
+ field_a: {
2189
+ title: 'Field A',
2190
+ 'x-jsf-presentation': {
2191
+ inputType: 'text',
2192
+ MyComponent: FakeComponent,
2193
+ },
2194
+ },
2195
+ field_b: {
2196
+ title: 'Field B',
2197
+ 'x-jsf-presentation': {
2198
+ inputType: 'text',
2199
+ MyComponent: FakeComponent,
2200
+ },
2201
+ },
2202
+ },
2203
+ allOf: [
2204
+ {
2205
+ if: {
2206
+ properties: {
2207
+ field_a: { const: 'yes' },
2208
+ },
2209
+ required: ['field_a'],
2210
+ },
2211
+ then: {
2212
+ required: ['field_b'],
2213
+ },
2214
+ },
2215
+ ],
2216
+ });
2217
+
2218
+ const fieldA = getField(fields, 'field_a');
2219
+ expect(fieldA).toMatchObject({
2220
+ label: 'Field A',
2221
+ MyComponent: expect.any(Function),
2222
+ });
2223
+
2224
+ const fieldB = getField(fields, 'field_b');
2225
+ expect(fieldB).toMatchObject({
2226
+ label: 'Field B',
2227
+ required: false,
2228
+ MyComponent: expect.any(Function),
2229
+ });
2230
+
2231
+ const fakeProps = { label: 'Field B', description: 'fake description' };
2232
+ expect(fieldB.MyComponent(fakeProps)).toBe(
2233
+ 'A React component with Field B and fake description'
2234
+ );
2235
+
2236
+ // Ensure "MyComponent" attribute still exsits after a validation cycle.
2237
+ // This covers the updateField(). Check PR for more context.
2238
+ handleValidation({ field_a: 'yes' });
2239
+
2240
+ expect(getField(fields, 'field_a')).toMatchObject({
2241
+ MyComponent: expect.any(Function),
2242
+ });
2243
+ expect(getField(fields, 'field_b')).toMatchObject({
2244
+ required: true,
2245
+ MyComponent: expect.any(Function),
2246
+ });
2247
+ });
2248
+
2180
2249
  it('passes scopedJsonSchema to each field', () => {
2181
2250
  const { fields } = createHeadlessForm(schemaWithoutInputTypes, {
2182
2251
  strictInputType: false,
@@ -358,40 +358,94 @@ describe('modify() - basic mutations', () => {
358
358
  },
359
359
  });
360
360
  });
361
+ });
361
362
 
362
- it('customize x-jsf-errorMessage (shorthand)', () => {
363
- const result = modify(schemaPet, {
364
- fields: {
365
- pet_age: (fieldAttrs) => {
366
- return {
367
- errorMessage: {
368
- minimum: `We only accept pets up to ${fieldAttrs.maximum} months old.`,
369
- required: 'We need to know your pet name.',
363
+ describe('supporting shorthands', () => {
364
+ const invoiceSchema = {
365
+ properties: {
366
+ title: {
367
+ title: 'Invoice title',
368
+ 'x-jsf-presentation': {
369
+ inputType: 'text',
370
+ },
371
+ 'x-jsf-errorMessage': {
372
+ required: 'Cannot be empty.',
373
+ },
374
+ type: 'string',
375
+ },
376
+ total: {
377
+ title: 'Invoice amount',
378
+ 'x-jsf-presentation': {
379
+ inputType: 'money',
380
+ },
381
+ type: 'number',
382
+ },
383
+ taxes: {
384
+ title: 'Taxes details',
385
+ properties: {
386
+ country: {
387
+ title: 'Country',
388
+ 'x-jsf-presentation': {
389
+ inputType: 'country',
370
390
  },
371
- };
391
+ type: 'string',
392
+ },
393
+ percentage: {
394
+ title: 'Percentage',
395
+ 'x-jsf-presentation': {
396
+ inputType: 'number',
397
+ },
398
+ },
399
+ type: 'integer',
372
400
  },
373
- 'pet_address.street': {
401
+ },
402
+ },
403
+ required: ['title'],
404
+ };
405
+
406
+ it('basic support for x-jsf-presentation and x-jsf-errorMessage in config.fields', () => {
407
+ const result = modify(invoiceSchema, {
408
+ fields: {
409
+ title: {
374
410
  errorMessage: {
375
- required: 'Your pet cannot live in the street.',
411
+ maxLength: 'Must be shorter.',
412
+ },
413
+ presentation: {
414
+ dataFoo: 123,
415
+ },
416
+ },
417
+ 'taxes.country': {
418
+ errorMessage: {
419
+ required: 'The country is required.',
420
+ },
421
+ presentation: {
422
+ flags: true,
376
423
  },
377
424
  },
378
425
  },
379
- // ...
380
426
  });
381
427
 
428
+ // Assert all the other propreties are kept
429
+ expect(result.schema).toMatchObject(invoiceSchema);
430
+
382
431
  expect(result.schema).toMatchObject({
383
432
  properties: {
384
- pet_age: {
433
+ title: {
385
434
  'x-jsf-errorMessage': {
386
- minimum: `We only accept pets up to 24 months old.`,
387
- required: 'We need to know your pet name.',
435
+ maxLength: 'Must be shorter.',
436
+ },
437
+ 'x-jsf-presentation': {
438
+ dataFoo: 123,
388
439
  },
389
440
  },
390
- pet_address: {
441
+ taxes: {
391
442
  properties: {
392
- street: {
443
+ country: {
393
444
  'x-jsf-errorMessage': {
394
- required: 'Your pet cannot live in the street.',
445
+ required: 'The country is required.',
446
+ },
447
+ 'x-jsf-presentation': {
448
+ flags: true,
395
449
  },
396
450
  },
397
451
  },
@@ -400,47 +454,90 @@ describe('modify() - basic mutations', () => {
400
454
  });
401
455
  });
402
456
 
403
- it('customize x-jsf-presentation (shorthand)', () => {
404
- const result = modify(schemaPet, {
405
- fields: {
406
- pet_age: () => {
407
- return {
408
- presentation: {
409
- 'data-foo': 123,
410
- },
411
- };
457
+ it('shorthands work in config.allFields', () => {
458
+ const result = modify(invoiceSchema, {
459
+ allFields: (fieldName, attrs) => ({
460
+ errorMessage: {
461
+ required: `${attrs.title} cannot be empty.`,
412
462
  },
413
- 'pet_address.street': {
414
- presentation: {
415
- 'data-foo': 456,
416
- },
463
+ presentation: {
464
+ dataName: fieldName,
417
465
  },
418
- },
466
+ }),
419
467
  });
420
468
 
421
- const originalPetAgePresentation = schemaPet.properties.pet_age['x-jsf-presentation'];
422
- expect(originalPetAgePresentation).toBeDefined();
423
-
424
- const originalPetStreetPresentation =
425
- schemaPet.properties.pet_address.properties.street['x-jsf-presentation'];
426
- expect(originalPetStreetPresentation).toBeDefined();
427
-
428
469
  expect(result.schema).toMatchObject({
429
470
  properties: {
430
- pet_age: {
471
+ title: {
472
+ 'x-jsf-errorMessage': {
473
+ required: 'Invoice title cannot be empty.',
474
+ },
431
475
  'x-jsf-presentation': {
432
- ...originalPetAgePresentation,
433
- 'data-foo': 123,
476
+ dataName: 'title',
434
477
  },
435
478
  },
436
- pet_address: {
479
+ total: {
480
+ 'x-jsf-errorMessage': {
481
+ required: 'Invoice amount cannot be empty.',
482
+ },
483
+ 'x-jsf-presentation': {
484
+ dataName: 'total',
485
+ },
486
+ },
487
+ taxes: {
488
+ 'x-jsf-errorMessage': {
489
+ required: 'Taxes details cannot be empty.',
490
+ },
491
+ 'x-jsf-presentation': {
492
+ dataName: 'taxes',
493
+ },
437
494
  properties: {
438
- street: {
495
+ country: {
496
+ 'x-jsf-errorMessage': {
497
+ required: 'Country cannot be empty.',
498
+ },
439
499
  'x-jsf-presentation': {
440
- ...originalPetStreetPresentation,
441
- 'data-foo': 456,
500
+ dataName: 'taxes.country',
442
501
  },
443
502
  },
503
+ percentage: {
504
+ 'x-jsf-errorMessage': {
505
+ required: 'Percentage cannot be empty.',
506
+ },
507
+ 'x-jsf-presentation': {
508
+ dataName: 'taxes.percentage',
509
+ },
510
+ },
511
+ },
512
+ },
513
+ },
514
+ });
515
+ });
516
+
517
+ it('shorthands work in config.create', () => {
518
+ const result = modify(invoiceSchema, {
519
+ create: {
520
+ invoice_id: {
521
+ title: 'Invoice ID',
522
+ presentation: {
523
+ inputType: 'text',
524
+ },
525
+ errorMessage: {
526
+ pattern: 'Must have 5 characters.',
527
+ },
528
+ },
529
+ },
530
+ });
531
+
532
+ expect(result.schema).toMatchObject({
533
+ properties: {
534
+ invoice_id: {
535
+ title: 'Invoice ID',
536
+ 'x-jsf-presentation': {
537
+ inputType: 'text',
538
+ },
539
+ 'x-jsf-errorMessage': {
540
+ pattern: 'Must have 5 characters.',
444
541
  },
445
542
  },
446
543
  },