@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.
- package/dist/assets/form-js.css +36 -38
- package/dist/index.cjs +128 -70
- package/dist/index.cjs.map +1 -1
- package/dist/index.es.js +128 -70
- package/dist/index.es.js.map +1 -1
- package/dist/types/Form.d.ts +130 -143
- package/dist/types/core/EventBus.d.ts +1 -1
- package/dist/types/core/FormFieldRegistry.d.ts +17 -17
- package/dist/types/core/Validator.d.ts +3 -3
- package/dist/types/core/index.d.ts +16 -16
- package/dist/types/import/Importer.d.ts +43 -38
- package/dist/types/import/index.d.ts +5 -5
- package/dist/types/index.d.ts +18 -18
- package/dist/types/render/FormFields.d.ts +5 -5
- package/dist/types/render/Renderer.d.ts +23 -23
- package/dist/types/render/components/Description.d.ts +1 -1
- package/dist/types/render/components/Errors.d.ts +1 -1
- package/dist/types/render/components/FormComponent.d.ts +1 -1
- package/dist/types/render/components/FormField.d.ts +1 -1
- package/dist/types/render/components/Label.d.ts +1 -1
- package/dist/types/render/components/PoweredBy.d.ts +1 -1
- package/dist/types/render/components/Sanitizer.d.ts +7 -7
- package/dist/types/render/components/Util.d.ts +4 -4
- package/dist/types/render/components/form-fields/Button.d.ts +11 -11
- package/dist/types/render/components/form-fields/Checkbox.d.ts +10 -9
- package/dist/types/render/components/form-fields/Default.d.ts +9 -9
- package/dist/types/render/components/form-fields/Number.d.ts +10 -9
- package/dist/types/render/components/form-fields/Radio.d.ts +15 -14
- package/dist/types/render/components/form-fields/Select.d.ts +15 -14
- package/dist/types/render/components/form-fields/Text.d.ts +10 -10
- package/dist/types/render/components/form-fields/Textfield.d.ts +10 -9
- package/dist/types/render/components/index.d.ts +11 -11
- package/dist/types/render/context/FormContext.d.ts +12 -11
- package/dist/types/render/context/FormRenderContext.d.ts +6 -6
- package/dist/types/render/context/index.d.ts +2 -2
- package/dist/types/render/hooks/useService.d.ts +1 -1
- package/dist/types/render/index.d.ts +11 -11
- package/dist/types/util/form.d.ts +6 -6
- package/dist/types/util/index.d.ts +16 -16
- package/dist/types/util/injector.d.ts +1 -1
- 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 && (
|
|
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
|
|
720
|
-
|
|
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}
|
|
735
|
+
* @return {any} importedField
|
|
737
736
|
*/
|
|
738
737
|
|
|
739
738
|
|
|
740
|
-
importFormField(formField,
|
|
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); //
|
|
762
|
+
this._formFieldRegistry._keys.claim(key, formField); // TODO: buttons should not have key
|
|
764
763
|
|
|
765
764
|
|
|
766
|
-
|
|
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,
|
|
786
|
+
this.importFormFields(components, id);
|
|
785
787
|
}
|
|
786
788
|
|
|
787
789
|
return formField;
|
|
788
790
|
}
|
|
789
791
|
|
|
790
|
-
importFormFields(components,
|
|
792
|
+
importFormFields(components, parentId) {
|
|
791
793
|
components.forEach(component => {
|
|
792
|
-
this.importFormField(component,
|
|
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) ?
|
|
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
|
|
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 === '' ?
|
|
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');
|
|
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
|
-
|
|
1852
|
-
set(data, _path, undefined);
|
|
1906
|
+
if (disabled || !_path) {
|
|
1907
|
+
return data;
|
|
1853
1908
|
}
|
|
1854
1909
|
|
|
1855
|
-
|
|
1856
|
-
|
|
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 =
|
|
2138
|
+
const schemaVersion = 3;
|
|
2081
2139
|
/**
|
|
2082
2140
|
* @typedef { import('./types').CreateFormOptions } CreateFormOptions
|
|
2083
2141
|
*/
|