@bpmn-io/form-js-viewer 0.4.2 → 0.6.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.
Files changed (41) hide show
  1. package/dist/assets/form-js.css +36 -38
  2. package/dist/index.cjs +128 -70
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.es.js +128 -70
  5. package/dist/index.es.js.map +1 -1
  6. package/dist/types/Form.d.ts +130 -143
  7. package/dist/types/core/EventBus.d.ts +1 -1
  8. package/dist/types/core/FormFieldRegistry.d.ts +17 -17
  9. package/dist/types/core/Validator.d.ts +3 -3
  10. package/dist/types/core/index.d.ts +16 -16
  11. package/dist/types/import/Importer.d.ts +43 -38
  12. package/dist/types/import/index.d.ts +5 -5
  13. package/dist/types/index.d.ts +18 -18
  14. package/dist/types/render/FormFields.d.ts +5 -5
  15. package/dist/types/render/Renderer.d.ts +23 -23
  16. package/dist/types/render/components/Description.d.ts +1 -1
  17. package/dist/types/render/components/Errors.d.ts +1 -1
  18. package/dist/types/render/components/FormComponent.d.ts +1 -1
  19. package/dist/types/render/components/FormField.d.ts +1 -1
  20. package/dist/types/render/components/Label.d.ts +1 -1
  21. package/dist/types/render/components/PoweredBy.d.ts +1 -1
  22. package/dist/types/render/components/Sanitizer.d.ts +7 -7
  23. package/dist/types/render/components/Util.d.ts +4 -4
  24. package/dist/types/render/components/form-fields/Button.d.ts +11 -11
  25. package/dist/types/render/components/form-fields/Checkbox.d.ts +10 -9
  26. package/dist/types/render/components/form-fields/Default.d.ts +9 -9
  27. package/dist/types/render/components/form-fields/Number.d.ts +10 -9
  28. package/dist/types/render/components/form-fields/Radio.d.ts +15 -14
  29. package/dist/types/render/components/form-fields/Select.d.ts +15 -14
  30. package/dist/types/render/components/form-fields/Text.d.ts +10 -10
  31. package/dist/types/render/components/form-fields/Textfield.d.ts +10 -9
  32. package/dist/types/render/components/index.d.ts +11 -11
  33. package/dist/types/render/context/FormContext.d.ts +12 -11
  34. package/dist/types/render/context/FormRenderContext.d.ts +6 -6
  35. package/dist/types/render/context/index.d.ts +2 -2
  36. package/dist/types/render/hooks/useService.d.ts +1 -1
  37. package/dist/types/render/index.d.ts +11 -11
  38. package/dist/types/util/form.d.ts +6 -6
  39. package/dist/types/util/index.d.ts +16 -16
  40. package/dist/types/util/injector.d.ts +1 -1
  41. package/package.json +3 -2
package/dist/index.es.js CHANGED
@@ -1,5 +1,5 @@
1
- import { isArray, isFunction, isNumber, bind, assign, get, set, isString } from 'min-dash';
2
1
  import Ids from 'ids';
2
+ import { isArray, isFunction, isNumber, bind, assign, isNil, get, isUndefined, set, isString } from 'min-dash';
3
3
  import snarkdown from '@bpmn-io/snarkdown';
4
4
  import { jsx, jsxs } from 'preact/jsx-runtime';
5
5
  import { useContext, useState, useCallback } from 'preact/hooks';
@@ -600,7 +600,7 @@ class Validator {
600
600
  errors = [...errors, `Field must match pattern ${validate.pattern}.`];
601
601
  }
602
602
 
603
- if (validate.required && (typeof value === 'undefined' || value === '')) {
603
+ if (validate.required && (isNil(value) || value === '')) {
604
604
  errors = [...errors, 'Field is required.'];
605
605
  }
606
606
 
@@ -716,8 +716,8 @@ class Importer {
716
716
  const warnings = [];
717
717
 
718
718
  try {
719
- const importedData = clone(data);
720
- const importedSchema = this.importFormField(clone(schema), importedData);
719
+ const importedSchema = this.importFormField(clone(schema)),
720
+ importedData = this.importData(clone(data));
721
721
  return {
722
722
  warnings,
723
723
  schema: importedSchema,
@@ -730,14 +730,13 @@ class Importer {
730
730
  }
731
731
  /**
732
732
  * @param {any} formField
733
- * @param {Object} [data]
734
733
  * @param {string} [parentId]
735
734
  *
736
- * @return {any} field
735
+ * @return {any} importedField
737
736
  */
738
737
 
739
738
 
740
- importFormField(formField, data = {}, parentId) {
739
+ importFormField(formField, parentId) {
741
740
  const {
742
741
  components,
743
742
  key,
@@ -760,10 +759,13 @@ class Importer {
760
759
  throw new Error(`form field with key <${key}> already exists`);
761
760
  }
762
761
 
763
- this._formFieldRegistry._keys.claim(key, formField); // set form field path
762
+ this._formFieldRegistry._keys.claim(key, formField); // TODO: buttons should not have key
764
763
 
765
764
 
766
- formField._path = [key];
765
+ if (type !== 'button') {
766
+ // set form field path
767
+ formField._path = [key];
768
+ }
767
769
  }
768
770
 
769
771
  if (id) {
@@ -781,17 +783,44 @@ class Importer {
781
783
  this._formFieldRegistry.add(formField);
782
784
 
783
785
  if (components) {
784
- this.importFormFields(components, data, id);
786
+ this.importFormFields(components, id);
785
787
  }
786
788
 
787
789
  return formField;
788
790
  }
789
791
 
790
- importFormFields(components, data = {}, parentId) {
792
+ importFormFields(components, parentId) {
791
793
  components.forEach(component => {
792
- this.importFormField(component, data, parentId);
794
+ this.importFormField(component, parentId);
793
795
  });
794
796
  }
797
+ /**
798
+ * @param {Object} data
799
+ *
800
+ * @return {Object} importedData
801
+ */
802
+
803
+
804
+ importData(data) {
805
+ return this._formFieldRegistry.getAll().reduce((importedData, formField) => {
806
+ const {
807
+ defaultValue,
808
+ _path,
809
+ type
810
+ } = formField;
811
+
812
+ if (!_path) {
813
+ return importedData;
814
+ } // (1) try to get value from data
815
+ // (2) try to get default value from form field
816
+ // (3) get empty value from form field
817
+
818
+
819
+ return { ...importedData,
820
+ [_path[0]]: get(data, _path, isUndefined(defaultValue) ? this._formFields.get(type).emptyValue : defaultValue)
821
+ };
822
+ }, {});
823
+ }
795
824
 
796
825
  }
797
826
  Importer.$inject = ['formFieldRegistry', 'formFields'];
@@ -933,7 +962,11 @@ function formFieldClasses(type, errors = []) {
933
962
 
934
963
  return classes.join(' ');
935
964
  }
936
- function prefixId(id) {
965
+ function prefixId(id, formId) {
966
+ if (formId) {
967
+ return `fjs-form-${formId}-${id}`;
968
+ }
969
+
937
970
  return `fjs-form-${id}`;
938
971
  }
939
972
  function markdownToHTML(markdown) {
@@ -977,6 +1010,32 @@ Button.type = type$6;
977
1010
  Button.label = 'Button';
978
1011
  Button.keyed = true;
979
1012
 
1013
+ const FormRenderContext = createContext({
1014
+ Empty: props => {
1015
+ return null;
1016
+ },
1017
+ Children: props => {
1018
+ return props.children;
1019
+ },
1020
+ Element: props => {
1021
+ return props.children;
1022
+ }
1023
+ });
1024
+
1025
+ /**
1026
+ * @param {string} type
1027
+ * @param {boolean} [strict]
1028
+ *
1029
+ * @returns {any}
1030
+ */
1031
+
1032
+ function getService(type, strict) {}
1033
+
1034
+ const FormContext = createContext({
1035
+ getService,
1036
+ formId: null
1037
+ });
1038
+
980
1039
  function Description(props) {
981
1040
  const {
982
1041
  description
@@ -1019,15 +1078,10 @@ function Label(props) {
1019
1078
  label,
1020
1079
  required = false
1021
1080
  } = props;
1022
-
1023
- if (!label) {
1024
- return null;
1025
- }
1026
-
1027
1081
  return jsxs("label", {
1028
1082
  for: id,
1029
1083
  class: "fjs-form-field-label",
1030
- children: [props.children, label, required && jsx("span", {
1084
+ children: [props.children, label || '', required && jsx("span", {
1031
1085
  class: "fjs-asterix",
1032
1086
  children: "*"
1033
1087
  })]
@@ -1057,17 +1111,20 @@ function Checkbox(props) {
1057
1111
  });
1058
1112
  };
1059
1113
 
1114
+ const {
1115
+ formId
1116
+ } = useContext(FormContext);
1060
1117
  return jsxs("div", {
1061
1118
  class: formFieldClasses(type$5, errors),
1062
1119
  children: [jsx(Label, {
1063
- id: prefixId(id),
1120
+ id: prefixId(id, formId),
1064
1121
  label: label,
1065
1122
  required: false,
1066
1123
  children: jsx("input", {
1067
1124
  checked: value,
1068
1125
  class: "fjs-input",
1069
1126
  disabled: disabled,
1070
- id: prefixId(id),
1127
+ id: prefixId(id, formId),
1071
1128
  type: "checkbox",
1072
1129
  onChange: onChange
1073
1130
  })
@@ -1087,31 +1144,7 @@ Checkbox.create = function (options = {}) {
1087
1144
  Checkbox.type = type$5;
1088
1145
  Checkbox.label = 'Checkbox';
1089
1146
  Checkbox.keyed = true;
1090
-
1091
- const FormRenderContext = createContext({
1092
- Empty: props => {
1093
- return null;
1094
- },
1095
- Children: props => {
1096
- return props.children;
1097
- },
1098
- Element: props => {
1099
- return props.children;
1100
- }
1101
- });
1102
-
1103
- /**
1104
- * @param {string} type
1105
- * @param {boolean} [strict]
1106
- *
1107
- * @returns {any}
1108
- */
1109
-
1110
- function getService(type, strict) {}
1111
-
1112
- const FormContext = createContext({
1113
- getService
1114
- });
1147
+ Checkbox.emptyValue = false;
1115
1148
 
1116
1149
  function useService (type, strict) {
1117
1150
  const {
@@ -1334,7 +1367,7 @@ function Number(props) {
1334
1367
  disabled,
1335
1368
  errors = [],
1336
1369
  field,
1337
- value = ''
1370
+ value
1338
1371
  } = props;
1339
1372
  const {
1340
1373
  description,
@@ -1352,23 +1385,26 @@ function Number(props) {
1352
1385
  const parsedValue = parseInt(target.value, 10);
1353
1386
  props.onChange({
1354
1387
  field,
1355
- value: isNaN(parsedValue) ? undefined : parsedValue
1388
+ value: isNaN(parsedValue) ? null : parsedValue
1356
1389
  });
1357
1390
  };
1358
1391
 
1392
+ const {
1393
+ formId
1394
+ } = useContext(FormContext);
1359
1395
  return jsxs("div", {
1360
1396
  class: formFieldClasses(type$4, errors),
1361
1397
  children: [jsx(Label, {
1362
- id: prefixId(id),
1398
+ id: prefixId(id, formId),
1363
1399
  label: label,
1364
1400
  required: required
1365
1401
  }), jsx("input", {
1366
1402
  class: "fjs-input",
1367
1403
  disabled: disabled,
1368
- id: prefixId(id),
1404
+ id: prefixId(id, formId),
1369
1405
  onInput: onChange,
1370
1406
  type: "number",
1371
- value: value
1407
+ value: value || ''
1372
1408
  }), jsx(Description, {
1373
1409
  description: description
1374
1410
  }), jsx(Errors, {
@@ -1385,6 +1421,7 @@ Number.create = function (options = {}) {
1385
1421
  Number.type = type$4;
1386
1422
  Number.keyed = true;
1387
1423
  Number.label = 'Number';
1424
+ Number.emptyValue = null;
1388
1425
 
1389
1426
  const type$3 = 'radio';
1390
1427
  function Radio(props) {
@@ -1408,10 +1445,13 @@ function Radio(props) {
1408
1445
  const onChange = v => {
1409
1446
  props.onChange({
1410
1447
  field,
1411
- value: v === value ? undefined : v
1448
+ value: v
1412
1449
  });
1413
1450
  };
1414
1451
 
1452
+ const {
1453
+ formId
1454
+ } = useContext(FormContext);
1415
1455
  return jsxs("div", {
1416
1456
  class: formFieldClasses(type$3, errors),
1417
1457
  children: [jsx(Label, {
@@ -1419,14 +1459,14 @@ function Radio(props) {
1419
1459
  required: required
1420
1460
  }), values.map((v, index) => {
1421
1461
  return jsx(Label, {
1422
- id: prefixId(`${id}-${index}`),
1462
+ id: prefixId(`${id}-${index}`, formId),
1423
1463
  label: v.label,
1424
1464
  required: false,
1425
1465
  children: jsx("input", {
1426
1466
  checked: v.value === value,
1427
1467
  class: "fjs-input",
1428
1468
  disabled: disabled,
1429
- id: prefixId(`${id}-${index}`),
1469
+ id: prefixId(`${id}-${index}`, formId),
1430
1470
  type: "radio",
1431
1471
  onClick: () => onChange(v.value)
1432
1472
  })
@@ -1452,6 +1492,7 @@ Radio.create = function (options = {}) {
1452
1492
  Radio.type = type$3;
1453
1493
  Radio.label = 'Radio';
1454
1494
  Radio.keyed = true;
1495
+ Radio.emptyValue = null;
1455
1496
 
1456
1497
  const type$2 = 'select';
1457
1498
  function Select(props) {
@@ -1477,22 +1518,25 @@ function Select(props) {
1477
1518
  }) => {
1478
1519
  props.onChange({
1479
1520
  field,
1480
- value: target.value === '' ? undefined : target.value
1521
+ value: target.value === '' ? null : target.value
1481
1522
  });
1482
1523
  };
1483
1524
 
1525
+ const {
1526
+ formId
1527
+ } = useContext(FormContext);
1484
1528
  return jsxs("div", {
1485
1529
  class: formFieldClasses(type$2, errors),
1486
1530
  children: [jsx(Label, {
1487
- id: prefixId(id),
1531
+ id: prefixId(id, formId),
1488
1532
  label: label,
1489
1533
  required: required
1490
1534
  }), jsxs("select", {
1491
1535
  class: "fjs-select",
1492
1536
  disabled: disabled,
1493
- id: prefixId(id),
1537
+ id: prefixId(id, formId),
1494
1538
  onChange: onChange,
1495
- value: value,
1539
+ value: value || '',
1496
1540
  children: [jsx("option", {
1497
1541
  value: ""
1498
1542
  }), values.map(v => {
@@ -1522,6 +1566,7 @@ Select.create = function (options = {}) {
1522
1566
  Select.type = type$2;
1523
1567
  Select.label = 'Select';
1524
1568
  Select.keyed = true;
1569
+ Select.emptyValue = null;
1525
1570
 
1526
1571
  const type$1 = 'text';
1527
1572
  function Text(props) {
@@ -1577,16 +1622,19 @@ function Textfield(props) {
1577
1622
  });
1578
1623
  };
1579
1624
 
1625
+ const {
1626
+ formId
1627
+ } = useContext(FormContext);
1580
1628
  return jsxs("div", {
1581
1629
  class: formFieldClasses(type, errors),
1582
1630
  children: [jsx(Label, {
1583
- id: prefixId(id),
1631
+ id: prefixId(id, formId),
1584
1632
  label: label,
1585
1633
  required: required
1586
1634
  }), jsx("input", {
1587
1635
  class: "fjs-input",
1588
1636
  disabled: disabled,
1589
- id: prefixId(id),
1637
+ id: prefixId(id, formId),
1590
1638
  onInput: onChange,
1591
1639
  type: "text",
1592
1640
  value: value
@@ -1606,6 +1654,7 @@ Textfield.create = function (options = {}) {
1606
1654
  Textfield.type = type;
1607
1655
  Textfield.label = 'Text Field';
1608
1656
  Textfield.keyed = true;
1657
+ Textfield.emptyValue = '';
1609
1658
 
1610
1659
  const formFields = [Button, Checkbox, Default, Number, Radio, Select, Text, Textfield];
1611
1660
 
@@ -1636,8 +1685,9 @@ function Renderer(config, eventBus, form, injector) {
1636
1685
  const formContext = {
1637
1686
  getService(type, strict = true) {
1638
1687
  return injector.get(type, strict);
1639
- }
1688
+ },
1640
1689
 
1690
+ formId: form._id
1641
1691
  };
1642
1692
  eventBus.on('changed', newState => {
1643
1693
  setState(newState);
@@ -1717,6 +1767,7 @@ var core = {
1717
1767
  * } } State
1718
1768
  */
1719
1769
 
1770
+ const ids = new Ids([32, 36, 1]);
1720
1771
  /**
1721
1772
  * The form.
1722
1773
  */
@@ -1727,10 +1778,16 @@ class Form {
1727
1778
  * @param {FormOptions} options
1728
1779
  */
1729
1780
  constructor(options = {}) {
1781
+ /**
1782
+ * @public
1783
+ * @type {String}
1784
+ */
1785
+ this._id = ids.next();
1730
1786
  /**
1731
1787
  * @private
1732
1788
  * @type {Element}
1733
1789
  */
1790
+
1734
1791
  this._container = createFormContainer();
1735
1792
  const {
1736
1793
  container,
@@ -1839,21 +1896,22 @@ class Form {
1839
1896
  throw new Error('form is read-only');
1840
1897
  }
1841
1898
 
1842
- const formFieldRegistry = this.get('formFieldRegistry'); // do not submit disabled form fields
1843
-
1899
+ const formFieldRegistry = this.get('formFieldRegistry');
1844
1900
  const data = formFieldRegistry.getAll().reduce((data, field) => {
1845
1901
  const {
1846
1902
  disabled,
1847
1903
  _path
1848
- } = field;
1904
+ } = field; // do not submit disabled form fields
1849
1905
 
1850
- if (disabled) {
1851
- // strip disabled field value
1852
- set(data, _path, undefined);
1906
+ if (disabled || !_path) {
1907
+ return data;
1853
1908
  }
1854
1909
 
1855
- return data;
1856
- }, clone(this._getState().data));
1910
+ const value = get(this._getState().data, _path);
1911
+ return { ...data,
1912
+ [_path[0]]: value
1913
+ };
1914
+ }, {});
1857
1915
  const errors = this.validate();
1858
1916
 
1859
1917
  this._emit('submit', {
@@ -2077,7 +2135,7 @@ class Form {
2077
2135
 
2078
2136
  }
2079
2137
 
2080
- const schemaVersion = 2;
2138
+ const schemaVersion = 3;
2081
2139
  /**
2082
2140
  * @typedef { import('./types').CreateFormOptions } CreateFormOptions
2083
2141
  */