@remoteoss/json-schema-form 0.11.14-dev.20250514093749 → 0.11.15-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,15 @@
1
+ #### 0.11.15-beta.0 (2025-06-06)
2
+
3
+ ##### Bug Fixes
4
+
5
+ * **v0:** Handle computed presentational attributes correctly ([#195](https://github.com/remoteoss/json-schema-form/pull/195)) ([19c7ff5b](https://github.com/remoteoss/json-schema-form/commit/19c7ff5b4c5cc90bd1025a3ad3032076e4e25b65))
6
+
7
+ #### 0.11.14-beta.0 (2025-05-14)
8
+
9
+ ##### Chores
10
+
11
+ * Reminder to publish GitHub release ([#183](https://github.com/remoteoss/json-schema-form/pull/183)) ([adfa8c14](https://github.com/remoteoss/json-schema-form/commit/adfa8c14ca118b1012642f39c8388cf2ba1614c9))
12
+
1
13
  #### 0.11.13-beta.0 (2025-05-05)
2
14
 
3
15
  ##### Bug Fixes
package/README.md CHANGED
@@ -5,14 +5,16 @@
5
5
  <p align="center">
6
6
  <code>json-schema-form</code> is a headless UI form library powered by <a href="https://json-schema.org/">JSON Schemas</a>.
7
7
  <br/>
8
- It transforms JSON schemas into Javascript to be consumed by your UI libraries.
8
+ It transforms JSON schemas into Javascript `fields` to be more easily consumed by your UI libraries.
9
9
  </p>
10
10
 
11
11
  ---
12
12
 
13
13
  ### Why JSON Schemas for forms?
14
14
 
15
- JSON Schemas are the SSoT (Single Source of Truth) that allows you to share form's _structure_ and _validations_ between frontend and backend, regardless of the language used.
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.
16
18
 
17
19
  ## Installation
18
20
 
@@ -25,12 +27,18 @@ npm install @remoteoss/json-schema-form
25
27
  yarn install @remoteoss/json-schema-form
26
28
  ```
27
29
 
28
- ## Documentation
30
+ ## Getting Started
31
+
32
+ Check the 📚 **[JSF website](https://json-schema-form.vercel.app/)** for documentation.
29
33
 
30
- Check the 📚 **[JSF website](https://json-schema-form.vercel.app/)** for documentation and demos.
34
+ ### Playground
35
+
36
+ Check the đŸ•šī¸ **[JSF Playground](https://json-schema-form.vercel.app/?path=/docs/playground--docs)** for demos.
31
37
 
32
38
  ## Contributing
33
39
 
34
40
  Read [CONTRIBUTING](CONTRIBUTING.md) to get started.
35
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
+
36
44
  _Backed by [Remote.com](https://remote.com/)_
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.11.14-dev.20250514093749
5
- Generated: Wed, 14 May 2025 09:38:11 GMT
4
+ NPM Package: @remoteoss/json-schema-form@0.11.15-beta.0
5
+ Generated: Fri, 06 Jun 2025 13:25:38 GMT
6
6
 
7
7
  MIT License
8
8
 
@@ -967,9 +967,16 @@ function replaceHandlebarsTemplates({
967
967
  function calculateComputedAttributes(fieldParams, { parentID = "root" } = {}) {
968
968
  return ({ logic, isRequired, config, formValues }) => {
969
969
  const { name, computedAttributes } = fieldParams;
970
- const attributes = Object.fromEntries(
970
+ let attributes = Object.fromEntries(
971
971
  Object.entries(computedAttributes).map(handleComputedAttribute(logic, formValues, parentID, name)).filter(([, value]) => value !== null)
972
972
  );
973
+ const { "x-jsf-presentation": presentation, ...rest } = attributes;
974
+ if (presentation) {
975
+ attributes = {
976
+ ...rest,
977
+ ...presentation
978
+ };
979
+ }
973
980
  return {
974
981
  ...attributes,
975
982
  schema: buildYupSchema(
@@ -993,16 +1000,21 @@ function handleComputedAttribute(logic, formValues, parentID, name) {
993
1000
  handleNestedObjectForComputedValues(value, formValues, parentID, logic, name)
994
1001
  ];
995
1002
  case "x-jsf-presentation": {
996
- if (value.statement) {
997
- return [
998
- "statement",
999
- handleNestedObjectForComputedValues(value.statement, formValues, parentID, logic, name)
1000
- ];
1001
- }
1002
- return [
1003
- key,
1004
- handleNestedObjectForComputedValues(value.statement, formValues, parentID, logic, name)
1005
- ];
1003
+ const values = {};
1004
+ Object.entries(value).forEach(([presentationKey, presentationValue]) => {
1005
+ if (typeof presentationValue === "object") {
1006
+ values[presentationKey] = handleNestedObjectForComputedValues(
1007
+ presentationValue,
1008
+ formValues,
1009
+ parentID,
1010
+ logic,
1011
+ name
1012
+ );
1013
+ } else {
1014
+ values[presentationKey] = logic.getScope(parentID).applyComputedValueInField(presentationValue, formValues, name);
1015
+ }
1016
+ });
1017
+ return [key, values];
1006
1018
  }
1007
1019
  case "const":
1008
1020
  default: {
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.11.14-dev.20250514093749
5
- Generated: Wed, 14 May 2025 09:38:11 GMT
4
+ NPM Package: @remoteoss/json-schema-form@0.11.15-beta.0
5
+ Generated: Fri, 06 Jun 2025 13:25:38 GMT
6
6
 
7
7
  MIT License
8
8
 
@@ -930,9 +930,16 @@ function replaceHandlebarsTemplates({
930
930
  function calculateComputedAttributes(fieldParams, { parentID = "root" } = {}) {
931
931
  return ({ logic, isRequired, config, formValues }) => {
932
932
  const { name, computedAttributes } = fieldParams;
933
- const attributes = Object.fromEntries(
933
+ let attributes = Object.fromEntries(
934
934
  Object.entries(computedAttributes).map(handleComputedAttribute(logic, formValues, parentID, name)).filter(([, value]) => value !== null)
935
935
  );
936
+ const { "x-jsf-presentation": presentation, ...rest } = attributes;
937
+ if (presentation) {
938
+ attributes = {
939
+ ...rest,
940
+ ...presentation
941
+ };
942
+ }
936
943
  return {
937
944
  ...attributes,
938
945
  schema: buildYupSchema(
@@ -956,16 +963,21 @@ function handleComputedAttribute(logic, formValues, parentID, name) {
956
963
  handleNestedObjectForComputedValues(value, formValues, parentID, logic, name)
957
964
  ];
958
965
  case "x-jsf-presentation": {
959
- if (value.statement) {
960
- return [
961
- "statement",
962
- handleNestedObjectForComputedValues(value.statement, formValues, parentID, logic, name)
963
- ];
964
- }
965
- return [
966
- key,
967
- handleNestedObjectForComputedValues(value.statement, formValues, parentID, logic, name)
968
- ];
966
+ const values = {};
967
+ Object.entries(value).forEach(([presentationKey, presentationValue]) => {
968
+ if (typeof presentationValue === "object") {
969
+ values[presentationKey] = handleNestedObjectForComputedValues(
970
+ presentationValue,
971
+ formValues,
972
+ parentID,
973
+ logic,
974
+ name
975
+ );
976
+ } else {
977
+ values[presentationKey] = logic.getScope(parentID).applyComputedValueInField(presentationValue, formValues, name);
978
+ }
979
+ });
980
+ return [key, values];
969
981
  }
970
982
  case "const":
971
983
  default: {
@@ -1,8 +1,8 @@
1
1
 
2
2
  /*!
3
3
  Copyright (c) 2025 Remote Technology, Inc.
4
- NPM Package: @remoteoss/json-schema-form@0.11.14-dev.20250514093749
5
- Generated: Wed, 14 May 2025 09:38:11 GMT
4
+ NPM Package: @remoteoss/json-schema-form@0.11.15-beta.0
5
+ Generated: Fri, 06 Jun 2025 13:25:38 GMT
6
6
 
7
7
  MIT License
8
8
 
@@ -12446,9 +12446,16 @@ function replaceHandlebarsTemplates({
12446
12446
  function calculateComputedAttributes(fieldParams, { parentID = "root" } = {}) {
12447
12447
  return ({ logic, isRequired, config, formValues }) => {
12448
12448
  const { name, computedAttributes } = fieldParams;
12449
- const attributes = Object.fromEntries(
12449
+ let attributes = Object.fromEntries(
12450
12450
  Object.entries(computedAttributes).map(handleComputedAttribute(logic, formValues, parentID, name)).filter(([, value]) => value !== null)
12451
12451
  );
12452
+ const { "x-jsf-presentation": presentation, ...rest } = attributes;
12453
+ if (presentation) {
12454
+ attributes = {
12455
+ ...rest,
12456
+ ...presentation
12457
+ };
12458
+ }
12452
12459
  return {
12453
12460
  ...attributes,
12454
12461
  schema: buildYupSchema(
@@ -12472,16 +12479,21 @@ function handleComputedAttribute(logic, formValues, parentID, name) {
12472
12479
  handleNestedObjectForComputedValues(value, formValues, parentID, logic, name)
12473
12480
  ];
12474
12481
  case "x-jsf-presentation": {
12475
- if (value.statement) {
12476
- return [
12477
- "statement",
12478
- handleNestedObjectForComputedValues(value.statement, formValues, parentID, logic, name)
12479
- ];
12480
- }
12481
- return [
12482
- key,
12483
- handleNestedObjectForComputedValues(value.statement, formValues, parentID, logic, name)
12484
- ];
12482
+ const values2 = {};
12483
+ Object.entries(value).forEach(([presentationKey, presentationValue]) => {
12484
+ if (typeof presentationValue === "object") {
12485
+ values2[presentationKey] = handleNestedObjectForComputedValues(
12486
+ presentationValue,
12487
+ formValues,
12488
+ parentID,
12489
+ logic,
12490
+ name
12491
+ );
12492
+ } else {
12493
+ values2[presentationKey] = logic.getScope(parentID).applyComputedValueInField(presentationValue, formValues, name);
12494
+ }
12495
+ });
12496
+ return [key, values2];
12485
12497
  }
12486
12498
  case "const":
12487
12499
  default: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remoteoss/json-schema-form",
3
- "version": "0.11.14-dev.20250514093749",
3
+ "version": "0.11.15-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",
@@ -205,7 +205,7 @@ export const schemaInputTypeHidden = {
205
205
  a_hidden_select_multiple: {
206
206
  ...schemaInputTypeCountriesMultiple.properties.nationality,
207
207
  title: 'Select multi hidden',
208
- default: ['Albania, Algeria'],
208
+ default: ['Albania', 'Algeria'],
209
209
  'x-jsf-presentation': { inputType: 'hidden' },
210
210
  type: 'array',
211
211
  },
@@ -1468,7 +1468,6 @@ export const schemaDynamicValidationConst = {
1468
1468
  required: ['a_fieldset', 'validate_tabs', 'mandatory_group_array'],
1469
1469
  'x-jsf-order': ['validate_tabs', 'a_fieldset', 'mandatory_group_array', 'a_group_array'],
1470
1470
  };
1471
-
1472
1471
  export const schemaDynamicValidationMinimumMaximum = JSONSchemaBuilder()
1473
1472
  .addInput({
1474
1473
  a_number: mockNumberInput,
@@ -1542,6 +1541,7 @@ export const schemaDynamicValidationContains = JSONSchemaBuilder()
1542
1541
  },
1543
1542
  'x-jsf-presentation': {
1544
1543
  inputType: 'select',
1544
+ multiple: true,
1545
1545
  options: [
1546
1546
  {
1547
1547
  label: 'All',
@@ -364,6 +364,55 @@ export const schemaWithComputedAttributesAndErrorMessages = {
364
364
  },
365
365
  };
366
366
 
367
+ export const schemaWithComputedPresentationAttributes = {
368
+ properties: {
369
+ amount: {
370
+ description: 'Total amount to be reimbursed, including taxes.',
371
+ minimum: 0,
372
+ title: 'Total amount',
373
+ type: 'number',
374
+ 'x-jsf-logic-computedAttrs': {
375
+ 'x-jsf-presentation': {
376
+ currency: 'currency_selected',
377
+ },
378
+ },
379
+ 'x-jsf-presentation': {
380
+ currency: '---',
381
+ inputType: 'money',
382
+ },
383
+ },
384
+ currency: {
385
+ default: 'USD',
386
+ description: 'Currency in which the expense was paid.',
387
+ oneOf: [
388
+ {
389
+ const: 'UGX',
390
+ title: 'UGX - Ugandan Shilling',
391
+ },
392
+ {
393
+ const: 'USD',
394
+ title: 'USD - United States Dollar',
395
+ },
396
+ ],
397
+ title: 'Currency',
398
+ type: 'string',
399
+ 'x-jsf-presentation': {
400
+ inputType: 'select',
401
+ },
402
+ },
403
+ },
404
+ type: 'object',
405
+ 'x-jsf-logic': {
406
+ computedValues: {
407
+ currency_selected: {
408
+ rule: {
409
+ var: 'currency',
410
+ },
411
+ },
412
+ },
413
+ },
414
+ };
415
+
367
416
  export const schemaWithDeepVarThatDoesNotExist = {
368
417
  properties: {
369
418
  field_a: {
@@ -35,6 +35,7 @@ import {
35
35
  schemaWithValidationThatDoesNotExistOnProperty,
36
36
  badSchemaThatWillNotSetAForcedValue,
37
37
  schemaWithReduceAccumulator,
38
+ schemaWithComputedPresentationAttributes,
38
39
  } from './jsonLogic.fixtures';
39
40
  import { mockConsole, restoreConsoleAndEnsureItWasNotCalled } from './testUtils';
40
41
  import { createHeadlessForm } from '@/createHeadlessForm';
@@ -385,6 +386,17 @@ describe('jsonLogic: cross-values validations', () => {
385
386
  expect(fieldB.statement).toEqual({ description: 'Must be bigger than 4 and smaller than 8' });
386
387
  });
387
388
 
389
+ it('presentation attributes work', () => {
390
+ const { fields, handleValidation } = createHeadlessForm(
391
+ schemaWithComputedPresentationAttributes,
392
+ { strictInputType: false }
393
+ );
394
+ const fieldB = fields.find((i) => i.name === 'amount');
395
+ expect(handleValidation({ currency: 'UGX' }).formErrors).toEqual(undefined);
396
+ expect(fieldB.inputType).toEqual('money');
397
+ expect(fieldB.currency).toEqual('UGX');
398
+ });
399
+
388
400
  it('Use a inline-rule in a schema for a title attribute', () => {
389
401
  const { fields, handleValidation } = createHeadlessForm(
390
402
  schemaWithInlineRuleForComputedAttributeWithCopy,