@bpmn-io/form-js-viewer 0.4.4 → 0.7.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.
@@ -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
@@ -1062,17 +1121,20 @@ function Checkbox(props) {
1062
1121
  });
1063
1122
  };
1064
1123
 
1124
+ const {
1125
+ formId
1126
+ } = hooks.useContext(FormContext);
1065
1127
  return jsxRuntime.jsxs("div", {
1066
1128
  class: formFieldClasses(type$5, errors),
1067
1129
  children: [jsxRuntime.jsx(Label, {
1068
- id: prefixId(id),
1130
+ id: prefixId(id, formId),
1069
1131
  label: label,
1070
1132
  required: false,
1071
1133
  children: jsxRuntime.jsx("input", {
1072
1134
  checked: value,
1073
1135
  class: "fjs-input",
1074
1136
  disabled: disabled,
1075
- id: prefixId(id),
1137
+ id: prefixId(id, formId),
1076
1138
  type: "checkbox",
1077
1139
  onChange: onChange
1078
1140
  })
@@ -1092,31 +1154,7 @@ Checkbox.create = function (options = {}) {
1092
1154
  Checkbox.type = type$5;
1093
1155
  Checkbox.label = 'Checkbox';
1094
1156
  Checkbox.keyed = true;
1095
-
1096
- const FormRenderContext = preact.createContext({
1097
- Empty: props => {
1098
- return null;
1099
- },
1100
- Children: props => {
1101
- return props.children;
1102
- },
1103
- Element: props => {
1104
- return props.children;
1105
- }
1106
- });
1107
-
1108
- /**
1109
- * @param {string} type
1110
- * @param {boolean} [strict]
1111
- *
1112
- * @returns {any}
1113
- */
1114
-
1115
- function getService(type, strict) {}
1116
-
1117
- const FormContext = preact.createContext({
1118
- getService
1119
- });
1157
+ Checkbox.emptyValue = false;
1120
1158
 
1121
1159
  function useService (type, strict) {
1122
1160
  const {
@@ -1357,20 +1395,23 @@ function Number(props) {
1357
1395
  const parsedValue = parseInt(target.value, 10);
1358
1396
  props.onChange({
1359
1397
  field,
1360
- value: isNaN(parsedValue) ? undefined : parsedValue
1398
+ value: isNaN(parsedValue) ? null : parsedValue
1361
1399
  });
1362
1400
  };
1363
1401
 
1402
+ const {
1403
+ formId
1404
+ } = hooks.useContext(FormContext);
1364
1405
  return jsxRuntime.jsxs("div", {
1365
1406
  class: formFieldClasses(type$4, errors),
1366
1407
  children: [jsxRuntime.jsx(Label, {
1367
- id: prefixId(id),
1408
+ id: prefixId(id, formId),
1368
1409
  label: label,
1369
1410
  required: required
1370
1411
  }), jsxRuntime.jsx("input", {
1371
1412
  class: "fjs-input",
1372
1413
  disabled: disabled,
1373
- id: prefixId(id),
1414
+ id: prefixId(id, formId),
1374
1415
  onInput: onChange,
1375
1416
  type: "number",
1376
1417
  value: value || ''
@@ -1390,6 +1431,7 @@ Number.create = function (options = {}) {
1390
1431
  Number.type = type$4;
1391
1432
  Number.keyed = true;
1392
1433
  Number.label = 'Number';
1434
+ Number.emptyValue = null;
1393
1435
 
1394
1436
  const type$3 = 'radio';
1395
1437
  function Radio(props) {
@@ -1417,6 +1459,9 @@ function Radio(props) {
1417
1459
  });
1418
1460
  };
1419
1461
 
1462
+ const {
1463
+ formId
1464
+ } = hooks.useContext(FormContext);
1420
1465
  return jsxRuntime.jsxs("div", {
1421
1466
  class: formFieldClasses(type$3, errors),
1422
1467
  children: [jsxRuntime.jsx(Label, {
@@ -1424,18 +1469,18 @@ function Radio(props) {
1424
1469
  required: required
1425
1470
  }), values.map((v, index) => {
1426
1471
  return jsxRuntime.jsx(Label, {
1427
- id: prefixId(`${id}-${index}`),
1472
+ id: prefixId(`${id}-${index}`, formId),
1428
1473
  label: v.label,
1429
1474
  required: false,
1430
1475
  children: jsxRuntime.jsx("input", {
1431
1476
  checked: v.value === value,
1432
1477
  class: "fjs-input",
1433
1478
  disabled: disabled,
1434
- id: prefixId(`${id}-${index}`),
1479
+ id: prefixId(`${id}-${index}`, formId),
1435
1480
  type: "radio",
1436
1481
  onClick: () => onChange(v.value)
1437
1482
  })
1438
- }, v.value);
1483
+ }, `${id}-${index}`);
1439
1484
  }), jsxRuntime.jsx(Description, {
1440
1485
  description: description
1441
1486
  }), jsxRuntime.jsx(Errors, {
@@ -1457,6 +1502,7 @@ Radio.create = function (options = {}) {
1457
1502
  Radio.type = type$3;
1458
1503
  Radio.label = 'Radio';
1459
1504
  Radio.keyed = true;
1505
+ Radio.emptyValue = null;
1460
1506
 
1461
1507
  const type$2 = 'select';
1462
1508
  function Select(props) {
@@ -1482,29 +1528,32 @@ function Select(props) {
1482
1528
  }) => {
1483
1529
  props.onChange({
1484
1530
  field,
1485
- value: target.value === '' ? undefined : target.value
1531
+ value: target.value === '' ? null : target.value
1486
1532
  });
1487
1533
  };
1488
1534
 
1535
+ const {
1536
+ formId
1537
+ } = hooks.useContext(FormContext);
1489
1538
  return jsxRuntime.jsxs("div", {
1490
1539
  class: formFieldClasses(type$2, errors),
1491
1540
  children: [jsxRuntime.jsx(Label, {
1492
- id: prefixId(id),
1541
+ id: prefixId(id, formId),
1493
1542
  label: label,
1494
1543
  required: required
1495
1544
  }), jsxRuntime.jsxs("select", {
1496
1545
  class: "fjs-select",
1497
1546
  disabled: disabled,
1498
- id: prefixId(id),
1547
+ id: prefixId(id, formId),
1499
1548
  onChange: onChange,
1500
1549
  value: value || '',
1501
1550
  children: [jsxRuntime.jsx("option", {
1502
1551
  value: ""
1503
- }), values.map(v => {
1552
+ }), values.map((v, index) => {
1504
1553
  return jsxRuntime.jsx("option", {
1505
1554
  value: v.value,
1506
1555
  children: v.label
1507
- }, v.value);
1556
+ }, `${id}-${index}`);
1508
1557
  })]
1509
1558
  }), jsxRuntime.jsx(Description, {
1510
1559
  description: description
@@ -1527,6 +1576,7 @@ Select.create = function (options = {}) {
1527
1576
  Select.type = type$2;
1528
1577
  Select.label = 'Select';
1529
1578
  Select.keyed = true;
1579
+ Select.emptyValue = null;
1530
1580
 
1531
1581
  const type$1 = 'text';
1532
1582
  function Text(props) {
@@ -1582,16 +1632,19 @@ function Textfield(props) {
1582
1632
  });
1583
1633
  };
1584
1634
 
1635
+ const {
1636
+ formId
1637
+ } = hooks.useContext(FormContext);
1585
1638
  return jsxRuntime.jsxs("div", {
1586
1639
  class: formFieldClasses(type, errors),
1587
1640
  children: [jsxRuntime.jsx(Label, {
1588
- id: prefixId(id),
1641
+ id: prefixId(id, formId),
1589
1642
  label: label,
1590
1643
  required: required
1591
1644
  }), jsxRuntime.jsx("input", {
1592
1645
  class: "fjs-input",
1593
1646
  disabled: disabled,
1594
- id: prefixId(id),
1647
+ id: prefixId(id, formId),
1595
1648
  onInput: onChange,
1596
1649
  type: "text",
1597
1650
  value: value
@@ -1611,6 +1664,7 @@ Textfield.create = function (options = {}) {
1611
1664
  Textfield.type = type;
1612
1665
  Textfield.label = 'Text Field';
1613
1666
  Textfield.keyed = true;
1667
+ Textfield.emptyValue = '';
1614
1668
 
1615
1669
  const formFields = [Button, Checkbox, Default, Number, Radio, Select, Text, Textfield];
1616
1670
 
@@ -1641,8 +1695,9 @@ function Renderer(config, eventBus, form, injector) {
1641
1695
  const formContext = {
1642
1696
  getService(type, strict = true) {
1643
1697
  return injector.get(type, strict);
1644
- }
1698
+ },
1645
1699
 
1700
+ formId: form._id
1646
1701
  };
1647
1702
  eventBus.on('changed', newState => {
1648
1703
  setState(newState);
@@ -1722,6 +1777,7 @@ var core = {
1722
1777
  * } } State
1723
1778
  */
1724
1779
 
1780
+ const ids = new Ids__default['default']([32, 36, 1]);
1725
1781
  /**
1726
1782
  * The form.
1727
1783
  */
@@ -1732,10 +1788,16 @@ class Form {
1732
1788
  * @param {FormOptions} options
1733
1789
  */
1734
1790
  constructor(options = {}) {
1791
+ /**
1792
+ * @public
1793
+ * @type {String}
1794
+ */
1795
+ this._id = ids.next();
1735
1796
  /**
1736
1797
  * @private
1737
1798
  * @type {Element}
1738
1799
  */
1800
+
1739
1801
  this._container = createFormContainer();
1740
1802
  const {
1741
1803
  container,
@@ -1844,21 +1906,22 @@ class Form {
1844
1906
  throw new Error('form is read-only');
1845
1907
  }
1846
1908
 
1847
- const formFieldRegistry = this.get('formFieldRegistry'); // do not submit disabled form fields
1848
-
1909
+ const formFieldRegistry = this.get('formFieldRegistry');
1849
1910
  const data = formFieldRegistry.getAll().reduce((data, field) => {
1850
1911
  const {
1851
1912
  disabled,
1852
1913
  _path
1853
- } = field;
1914
+ } = field; // do not submit disabled form fields
1854
1915
 
1855
- if (disabled) {
1856
- // strip disabled field value
1857
- minDash.set(data, _path, undefined);
1916
+ if (disabled || !_path) {
1917
+ return data;
1858
1918
  }
1859
1919
 
1860
- return data;
1861
- }, clone(this._getState().data));
1920
+ const value = minDash.get(this._getState().data, _path);
1921
+ return { ...data,
1922
+ [_path[0]]: value
1923
+ };
1924
+ }, {});
1862
1925
  const errors = this.validate();
1863
1926
 
1864
1927
  this._emit('submit', {
@@ -2082,7 +2145,7 @@ class Form {
2082
2145
 
2083
2146
  }
2084
2147
 
2085
- const schemaVersion = 2;
2148
+ const schemaVersion = 4;
2086
2149
  /**
2087
2150
  * @typedef { import('./types').CreateFormOptions } CreateFormOptions
2088
2151
  */