@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
@@ -2,45 +2,42 @@
2
2
  * Theming
3
3
  */
4
4
  .fjs-container {
5
- --color-blue-base-65: #4d90ff;
6
- --color-blue-base-65-opacity-10: rgba(77, 144, 255, 0.1);
7
- --color-blue-darken-48: #005df7;
8
- --color-blue-darken-55: #1a70ff;
9
- --color-blue-darken-62: #3c85ff;
10
- --color-blue-lighten-75: #80b0ff;
11
- --color-blue-lighten-82: #a2c5ff;
12
- --color-blue-lighten-93: #dbe9ff;
13
-
14
- --color-silver-base-97: #f8f8f8;
15
- --color-silver-lighten-99: #fcfcfc;
16
- --color-silver-darken-80: #cdcdcd;
17
- --color-silver-darken-87: #dedede;
18
- --color-silver-darken-94: #efefef;
19
-
20
- --color-grey-base-40: #666666;
21
- --color-grey-lighten-56: #909090;
22
- --color-grey-darken-23: #3b3b3b;
23
- --color-grey-darken-30: #4c4c4c;
24
- --color-grey-darken-33: #535353;
25
-
26
- --color-red-base-62: #ff3d3d;
27
- --color-red-darken-38: #C20000;
28
- --color-red-lighten-85: #ffb3b3;
29
-
30
- --color-black: #000000;
31
- --color-white: #ffffff;
5
+ --color-grey-225-10-15: hsl(225, 10%, 15%);
6
+ --color-grey-225-10-35: hsl(225, 10%, 35%);
7
+ --color-grey-225-10-55: hsl(225, 10%, 55%);
8
+ --color-grey-225-10-75: hsl(225, 10%, 75%);
9
+ --color-grey-225-10-80: hsl(225, 10%, 80%);
10
+ --color-grey-225-10-85: hsl(225, 10%, 85%);
11
+ --color-grey-225-10-90: hsl(225, 10%, 90%);
12
+ --color-grey-225-10-95: hsl(225, 10%, 95%);
13
+ --color-grey-225-10-97: hsl(225, 10%, 97%);
14
+
15
+ --color-blue-205-100-45: hsl(205, 100%, 45%);
16
+ --color-blue-205-100-50: hsl(205, 100%, 50%);
17
+ --color-blue-205-100-80: hsl(205, 100%, 80%);
18
+ --color-blue-205-100-95: hsl(205, 100%, 95%);
19
+
20
+ --color-green-150-86-44: hsl(150, 86%, 44%);
21
+
22
+ --color-red-360-100-40: hsl(360, 100%, 40%);
23
+ --color-red-360-100-45: hsl(360, 100%, 45%);
24
+ --color-red-360-100-92: hsl(360, 100%, 92%);
25
+ --color-red-360-100-97: hsl(360, 100%, 97%);
26
+
27
+ --color-white: hsl(0, 0%, 100%);
28
+ --color-black: hsl(0, 0%, 0%);
32
29
 
33
30
  --color-background: var(--color-white);
34
- --color-background-disabled: var(--color-silver-darken-94);
35
- --color-text: var(--color-grey-darken-23);
36
- --color-text-light: var(--color-grey-lighten-56);
37
- --color-text-lighter: var(--color-grey-base-40);
31
+ --color-background-disabled: var(--color-grey-225-10-95);
32
+ --color-text: var(--color-grey-225-10-15);
33
+ --color-text-light: var(--color-grey-225-10-35);
34
+ --color-text-lighter: var(--color-grey-225-10-55);
38
35
  --color-text-inverted: var(--color-white);
39
- --color-borders: var(--color-grey-lighten-56);
40
- --color-borders-disabled: var(--color-silver-darken-80);
41
- --color-warning: var(--color-red-base-62);
42
- --color-accent: var(--color-blue-darken-62);
43
- --color-accent-dark: var(--color-blue-darken-48);
36
+ --color-borders: var(--color-grey-225-10-55);
37
+ --color-borders-disabled: var(--color-grey-225-10-75);
38
+ --color-warning: var(--color-red-360-100-45);
39
+ --color-accent: var(--color-blue-205-100-45);
40
+ --color-accent-dark: var(--color-blue-205-100-45);
44
41
 
45
42
  --font-family: 'IBM Plex Sans', sans-serif;
46
43
 
@@ -108,7 +105,7 @@
108
105
  font-style: italic;
109
106
  letter-spacing: .25px;
110
107
 
111
- color: var(--color-text-light);
108
+ color: var(--color-text-lighter);
112
109
  }
113
110
 
114
111
  .fjs-container .fjs-form-field-label {
@@ -217,6 +214,7 @@
217
214
  }
218
215
 
219
216
  .fjs-container .fjs-form-field.fjs-has-errors .fjs-input,
217
+ .fjs-container .fjs-form-field.fjs-has-errors .fjs-select,
220
218
  .fjs-container .fjs-form-field.fjs-has-errors .fjs-textarea {
221
219
  border-color: var(--color-warning);
222
220
  }
@@ -236,5 +234,5 @@
236
234
  }
237
235
 
238
236
  .fjs-container .fjs-form-field-text a {
239
- color: var(--color-blue-darken-48);
237
+ color: var(--color-blue-205-100-45);
240
238
  }
package/dist/index.cjs CHANGED
@@ -2,8 +2,8 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var minDash = require('min-dash');
6
5
  var Ids = require('ids');
6
+ var minDash = require('min-dash');
7
7
  var snarkdown = require('@bpmn-io/snarkdown');
8
8
  var jsxRuntime = require('preact/jsx-runtime');
9
9
  var hooks = require('preact/hooks');
@@ -610,7 +610,7 @@ class Validator {
610
610
  errors = [...errors, `Field must match pattern ${validate.pattern}.`];
611
611
  }
612
612
 
613
- if (validate.required && (typeof value === 'undefined' || value === '')) {
613
+ if (validate.required && (minDash.isNil(value) || value === '')) {
614
614
  errors = [...errors, 'Field is required.'];
615
615
  }
616
616
 
@@ -726,8 +726,8 @@ class Importer {
726
726
  const warnings = [];
727
727
 
728
728
  try {
729
- const importedData = clone(data);
730
- const importedSchema = this.importFormField(clone(schema), importedData);
729
+ const importedSchema = this.importFormField(clone(schema)),
730
+ importedData = this.importData(clone(data));
731
731
  return {
732
732
  warnings,
733
733
  schema: importedSchema,
@@ -740,14 +740,13 @@ class Importer {
740
740
  }
741
741
  /**
742
742
  * @param {any} formField
743
- * @param {Object} [data]
744
743
  * @param {string} [parentId]
745
744
  *
746
- * @return {any} field
745
+ * @return {any} importedField
747
746
  */
748
747
 
749
748
 
750
- importFormField(formField, data = {}, parentId) {
749
+ importFormField(formField, parentId) {
751
750
  const {
752
751
  components,
753
752
  key,
@@ -770,10 +769,13 @@ class Importer {
770
769
  throw new Error(`form field with key <${key}> already exists`);
771
770
  }
772
771
 
773
- this._formFieldRegistry._keys.claim(key, formField); // set form field path
772
+ this._formFieldRegistry._keys.claim(key, formField); // TODO: buttons should not have key
774
773
 
775
774
 
776
- formField._path = [key];
775
+ if (type !== 'button') {
776
+ // set form field path
777
+ formField._path = [key];
778
+ }
777
779
  }
778
780
 
779
781
  if (id) {
@@ -791,17 +793,44 @@ class Importer {
791
793
  this._formFieldRegistry.add(formField);
792
794
 
793
795
  if (components) {
794
- this.importFormFields(components, data, id);
796
+ this.importFormFields(components, id);
795
797
  }
796
798
 
797
799
  return formField;
798
800
  }
799
801
 
800
- importFormFields(components, data = {}, parentId) {
802
+ importFormFields(components, parentId) {
801
803
  components.forEach(component => {
802
- this.importFormField(component, data, parentId);
804
+ this.importFormField(component, parentId);
803
805
  });
804
806
  }
807
+ /**
808
+ * @param {Object} data
809
+ *
810
+ * @return {Object} importedData
811
+ */
812
+
813
+
814
+ importData(data) {
815
+ return this._formFieldRegistry.getAll().reduce((importedData, formField) => {
816
+ const {
817
+ defaultValue,
818
+ _path,
819
+ type
820
+ } = formField;
821
+
822
+ if (!_path) {
823
+ return importedData;
824
+ } // (1) try to get value from data
825
+ // (2) try to get default value from form field
826
+ // (3) get empty value from form field
827
+
828
+
829
+ return { ...importedData,
830
+ [_path[0]]: minDash.get(data, _path, minDash.isUndefined(defaultValue) ? this._formFields.get(type).emptyValue : defaultValue)
831
+ };
832
+ }, {});
833
+ }
805
834
 
806
835
  }
807
836
  Importer.$inject = ['formFieldRegistry', 'formFields'];
@@ -943,7 +972,11 @@ function formFieldClasses(type, errors = []) {
943
972
 
944
973
  return classes.join(' ');
945
974
  }
946
- function prefixId(id) {
975
+ function prefixId(id, formId) {
976
+ if (formId) {
977
+ return `fjs-form-${formId}-${id}`;
978
+ }
979
+
947
980
  return `fjs-form-${id}`;
948
981
  }
949
982
  function markdownToHTML(markdown) {
@@ -987,6 +1020,32 @@ Button.type = type$6;
987
1020
  Button.label = 'Button';
988
1021
  Button.keyed = true;
989
1022
 
1023
+ const FormRenderContext = preact.createContext({
1024
+ Empty: props => {
1025
+ return null;
1026
+ },
1027
+ Children: props => {
1028
+ return props.children;
1029
+ },
1030
+ Element: props => {
1031
+ return props.children;
1032
+ }
1033
+ });
1034
+
1035
+ /**
1036
+ * @param {string} type
1037
+ * @param {boolean} [strict]
1038
+ *
1039
+ * @returns {any}
1040
+ */
1041
+
1042
+ function getService(type, strict) {}
1043
+
1044
+ const FormContext = preact.createContext({
1045
+ getService,
1046
+ formId: null
1047
+ });
1048
+
990
1049
  function Description(props) {
991
1050
  const {
992
1051
  description
@@ -1029,15 +1088,10 @@ function Label(props) {
1029
1088
  label,
1030
1089
  required = false
1031
1090
  } = props;
1032
-
1033
- if (!label) {
1034
- return null;
1035
- }
1036
-
1037
1091
  return jsxRuntime.jsxs("label", {
1038
1092
  for: id,
1039
1093
  class: "fjs-form-field-label",
1040
- children: [props.children, label, required && jsxRuntime.jsx("span", {
1094
+ children: [props.children, label || '', required && jsxRuntime.jsx("span", {
1041
1095
  class: "fjs-asterix",
1042
1096
  children: "*"
1043
1097
  })]
@@ -1067,17 +1121,20 @@ function Checkbox(props) {
1067
1121
  });
1068
1122
  };
1069
1123
 
1124
+ const {
1125
+ formId
1126
+ } = hooks.useContext(FormContext);
1070
1127
  return jsxRuntime.jsxs("div", {
1071
1128
  class: formFieldClasses(type$5, errors),
1072
1129
  children: [jsxRuntime.jsx(Label, {
1073
- id: prefixId(id),
1130
+ id: prefixId(id, formId),
1074
1131
  label: label,
1075
1132
  required: false,
1076
1133
  children: jsxRuntime.jsx("input", {
1077
1134
  checked: value,
1078
1135
  class: "fjs-input",
1079
1136
  disabled: disabled,
1080
- id: prefixId(id),
1137
+ id: prefixId(id, formId),
1081
1138
  type: "checkbox",
1082
1139
  onChange: onChange
1083
1140
  })
@@ -1097,31 +1154,7 @@ Checkbox.create = function (options = {}) {
1097
1154
  Checkbox.type = type$5;
1098
1155
  Checkbox.label = 'Checkbox';
1099
1156
  Checkbox.keyed = true;
1100
-
1101
- const FormRenderContext = preact.createContext({
1102
- Empty: props => {
1103
- return null;
1104
- },
1105
- Children: props => {
1106
- return props.children;
1107
- },
1108
- Element: props => {
1109
- return props.children;
1110
- }
1111
- });
1112
-
1113
- /**
1114
- * @param {string} type
1115
- * @param {boolean} [strict]
1116
- *
1117
- * @returns {any}
1118
- */
1119
-
1120
- function getService(type, strict) {}
1121
-
1122
- const FormContext = preact.createContext({
1123
- getService
1124
- });
1157
+ Checkbox.emptyValue = false;
1125
1158
 
1126
1159
  function useService (type, strict) {
1127
1160
  const {
@@ -1344,7 +1377,7 @@ function Number(props) {
1344
1377
  disabled,
1345
1378
  errors = [],
1346
1379
  field,
1347
- value = ''
1380
+ value
1348
1381
  } = props;
1349
1382
  const {
1350
1383
  description,
@@ -1362,23 +1395,26 @@ function Number(props) {
1362
1395
  const parsedValue = parseInt(target.value, 10);
1363
1396
  props.onChange({
1364
1397
  field,
1365
- value: isNaN(parsedValue) ? undefined : parsedValue
1398
+ value: isNaN(parsedValue) ? null : parsedValue
1366
1399
  });
1367
1400
  };
1368
1401
 
1402
+ const {
1403
+ formId
1404
+ } = hooks.useContext(FormContext);
1369
1405
  return jsxRuntime.jsxs("div", {
1370
1406
  class: formFieldClasses(type$4, errors),
1371
1407
  children: [jsxRuntime.jsx(Label, {
1372
- id: prefixId(id),
1408
+ id: prefixId(id, formId),
1373
1409
  label: label,
1374
1410
  required: required
1375
1411
  }), jsxRuntime.jsx("input", {
1376
1412
  class: "fjs-input",
1377
1413
  disabled: disabled,
1378
- id: prefixId(id),
1414
+ id: prefixId(id, formId),
1379
1415
  onInput: onChange,
1380
1416
  type: "number",
1381
- value: value
1417
+ value: value || ''
1382
1418
  }), jsxRuntime.jsx(Description, {
1383
1419
  description: description
1384
1420
  }), jsxRuntime.jsx(Errors, {
@@ -1395,6 +1431,7 @@ Number.create = function (options = {}) {
1395
1431
  Number.type = type$4;
1396
1432
  Number.keyed = true;
1397
1433
  Number.label = 'Number';
1434
+ Number.emptyValue = null;
1398
1435
 
1399
1436
  const type$3 = 'radio';
1400
1437
  function Radio(props) {
@@ -1418,10 +1455,13 @@ function Radio(props) {
1418
1455
  const onChange = v => {
1419
1456
  props.onChange({
1420
1457
  field,
1421
- value: v === value ? undefined : v
1458
+ value: v
1422
1459
  });
1423
1460
  };
1424
1461
 
1462
+ const {
1463
+ formId
1464
+ } = hooks.useContext(FormContext);
1425
1465
  return jsxRuntime.jsxs("div", {
1426
1466
  class: formFieldClasses(type$3, errors),
1427
1467
  children: [jsxRuntime.jsx(Label, {
@@ -1429,14 +1469,14 @@ function Radio(props) {
1429
1469
  required: required
1430
1470
  }), values.map((v, index) => {
1431
1471
  return jsxRuntime.jsx(Label, {
1432
- id: prefixId(`${id}-${index}`),
1472
+ id: prefixId(`${id}-${index}`, formId),
1433
1473
  label: v.label,
1434
1474
  required: false,
1435
1475
  children: jsxRuntime.jsx("input", {
1436
1476
  checked: v.value === value,
1437
1477
  class: "fjs-input",
1438
1478
  disabled: disabled,
1439
- id: prefixId(`${id}-${index}`),
1479
+ id: prefixId(`${id}-${index}`, formId),
1440
1480
  type: "radio",
1441
1481
  onClick: () => onChange(v.value)
1442
1482
  })
@@ -1462,6 +1502,7 @@ Radio.create = function (options = {}) {
1462
1502
  Radio.type = type$3;
1463
1503
  Radio.label = 'Radio';
1464
1504
  Radio.keyed = true;
1505
+ Radio.emptyValue = null;
1465
1506
 
1466
1507
  const type$2 = 'select';
1467
1508
  function Select(props) {
@@ -1487,22 +1528,25 @@ function Select(props) {
1487
1528
  }) => {
1488
1529
  props.onChange({
1489
1530
  field,
1490
- value: target.value === '' ? undefined : target.value
1531
+ value: target.value === '' ? null : target.value
1491
1532
  });
1492
1533
  };
1493
1534
 
1535
+ const {
1536
+ formId
1537
+ } = hooks.useContext(FormContext);
1494
1538
  return jsxRuntime.jsxs("div", {
1495
1539
  class: formFieldClasses(type$2, errors),
1496
1540
  children: [jsxRuntime.jsx(Label, {
1497
- id: prefixId(id),
1541
+ id: prefixId(id, formId),
1498
1542
  label: label,
1499
1543
  required: required
1500
1544
  }), jsxRuntime.jsxs("select", {
1501
1545
  class: "fjs-select",
1502
1546
  disabled: disabled,
1503
- id: prefixId(id),
1547
+ id: prefixId(id, formId),
1504
1548
  onChange: onChange,
1505
- value: value,
1549
+ value: value || '',
1506
1550
  children: [jsxRuntime.jsx("option", {
1507
1551
  value: ""
1508
1552
  }), values.map(v => {
@@ -1532,6 +1576,7 @@ Select.create = function (options = {}) {
1532
1576
  Select.type = type$2;
1533
1577
  Select.label = 'Select';
1534
1578
  Select.keyed = true;
1579
+ Select.emptyValue = null;
1535
1580
 
1536
1581
  const type$1 = 'text';
1537
1582
  function Text(props) {
@@ -1587,16 +1632,19 @@ function Textfield(props) {
1587
1632
  });
1588
1633
  };
1589
1634
 
1635
+ const {
1636
+ formId
1637
+ } = hooks.useContext(FormContext);
1590
1638
  return jsxRuntime.jsxs("div", {
1591
1639
  class: formFieldClasses(type, errors),
1592
1640
  children: [jsxRuntime.jsx(Label, {
1593
- id: prefixId(id),
1641
+ id: prefixId(id, formId),
1594
1642
  label: label,
1595
1643
  required: required
1596
1644
  }), jsxRuntime.jsx("input", {
1597
1645
  class: "fjs-input",
1598
1646
  disabled: disabled,
1599
- id: prefixId(id),
1647
+ id: prefixId(id, formId),
1600
1648
  onInput: onChange,
1601
1649
  type: "text",
1602
1650
  value: value
@@ -1616,6 +1664,7 @@ Textfield.create = function (options = {}) {
1616
1664
  Textfield.type = type;
1617
1665
  Textfield.label = 'Text Field';
1618
1666
  Textfield.keyed = true;
1667
+ Textfield.emptyValue = '';
1619
1668
 
1620
1669
  const formFields = [Button, Checkbox, Default, Number, Radio, Select, Text, Textfield];
1621
1670
 
@@ -1646,8 +1695,9 @@ function Renderer(config, eventBus, form, injector) {
1646
1695
  const formContext = {
1647
1696
  getService(type, strict = true) {
1648
1697
  return injector.get(type, strict);
1649
- }
1698
+ },
1650
1699
 
1700
+ formId: form._id
1651
1701
  };
1652
1702
  eventBus.on('changed', newState => {
1653
1703
  setState(newState);
@@ -1727,6 +1777,7 @@ var core = {
1727
1777
  * } } State
1728
1778
  */
1729
1779
 
1780
+ const ids = new Ids__default['default']([32, 36, 1]);
1730
1781
  /**
1731
1782
  * The form.
1732
1783
  */
@@ -1737,10 +1788,16 @@ class Form {
1737
1788
  * @param {FormOptions} options
1738
1789
  */
1739
1790
  constructor(options = {}) {
1791
+ /**
1792
+ * @public
1793
+ * @type {String}
1794
+ */
1795
+ this._id = ids.next();
1740
1796
  /**
1741
1797
  * @private
1742
1798
  * @type {Element}
1743
1799
  */
1800
+
1744
1801
  this._container = createFormContainer();
1745
1802
  const {
1746
1803
  container,
@@ -1849,21 +1906,22 @@ class Form {
1849
1906
  throw new Error('form is read-only');
1850
1907
  }
1851
1908
 
1852
- const formFieldRegistry = this.get('formFieldRegistry'); // do not submit disabled form fields
1853
-
1909
+ const formFieldRegistry = this.get('formFieldRegistry');
1854
1910
  const data = formFieldRegistry.getAll().reduce((data, field) => {
1855
1911
  const {
1856
1912
  disabled,
1857
1913
  _path
1858
- } = field;
1914
+ } = field; // do not submit disabled form fields
1859
1915
 
1860
- if (disabled) {
1861
- // strip disabled field value
1862
- minDash.set(data, _path, undefined);
1916
+ if (disabled || !_path) {
1917
+ return data;
1863
1918
  }
1864
1919
 
1865
- return data;
1866
- }, clone(this._getState().data));
1920
+ const value = minDash.get(this._getState().data, _path);
1921
+ return { ...data,
1922
+ [_path[0]]: value
1923
+ };
1924
+ }, {});
1867
1925
  const errors = this.validate();
1868
1926
 
1869
1927
  this._emit('submit', {
@@ -2087,7 +2145,7 @@ class Form {
2087
2145
 
2088
2146
  }
2089
2147
 
2090
- const schemaVersion = 2;
2148
+ const schemaVersion = 3;
2091
2149
  /**
2092
2150
  * @typedef { import('./types').CreateFormOptions } CreateFormOptions
2093
2151
  */