@bpmn-io/form-js-viewer 0.10.0-alpha.1 → 0.10.0-alpha.2
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 +138 -4
- package/dist/index.cjs +589 -81
- package/dist/index.cjs.map +1 -1
- package/dist/index.es.js +588 -82
- package/dist/index.es.js.map +1 -1
- package/dist/types/Form.d.ts +4 -0
- package/dist/types/core/ConditionChecker.d.ts +57 -0
- package/dist/types/core/index.d.ts +2 -0
- package/dist/types/import/Importer.d.ts +2 -2
- package/dist/types/render/components/Sanitizer.d.ts +1 -0
- package/dist/types/render/components/Util.d.ts +10 -0
- package/dist/types/render/components/form-fields/Image.d.ts +8 -0
- package/dist/types/render/components/form-fields/Number.d.ts +6 -5
- package/dist/types/render/components/index.d.ts +4 -3
- package/dist/types/render/components/util/numberFieldUtil.d.ts +4 -0
- package/dist/types/render/hooks/useCondition.d.ts +9 -0
- package/dist/types/render/hooks/useEvaluation.d.ts +6 -0
- package/dist/types/render/hooks/useExpressionValue.d.ts +5 -0
- package/dist/types/{types.d.ts → src/types.d.ts} +0 -0
- package/dist/types/util/feel.d.ts +14 -0
- package/package.json +5 -3
package/dist/index.cjs
CHANGED
|
@@ -4,6 +4,8 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
4
4
|
|
|
5
5
|
var Ids = require('ids');
|
|
6
6
|
var minDash = require('min-dash');
|
|
7
|
+
var feelin = require('feelin');
|
|
8
|
+
var Big = require('big.js');
|
|
7
9
|
var snarkdown = require('@bpmn-io/snarkdown');
|
|
8
10
|
var classNames = require('classnames');
|
|
9
11
|
var jsxRuntime = require('preact/jsx-runtime');
|
|
@@ -16,11 +18,132 @@ var didi = require('didi');
|
|
|
16
18
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
17
19
|
|
|
18
20
|
var Ids__default = /*#__PURE__*/_interopDefaultLegacy(Ids);
|
|
21
|
+
var Big__default = /*#__PURE__*/_interopDefaultLegacy(Big);
|
|
19
22
|
var snarkdown__default = /*#__PURE__*/_interopDefaultLegacy(snarkdown);
|
|
20
23
|
var classNames__default = /*#__PURE__*/_interopDefaultLegacy(classNames);
|
|
21
24
|
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
|
|
22
25
|
var Markup__default = /*#__PURE__*/_interopDefaultLegacy(Markup);
|
|
23
26
|
|
|
27
|
+
/**
|
|
28
|
+
* @typedef {object} Condition
|
|
29
|
+
* @property {string} [hide]
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
class ConditionChecker {
|
|
33
|
+
constructor(formFieldRegistry, eventBus) {
|
|
34
|
+
this._formFieldRegistry = formFieldRegistry;
|
|
35
|
+
this._eventBus = eventBus;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* For given data, remove properties based on condition.
|
|
40
|
+
*
|
|
41
|
+
* @param {Object<string, any>} properties
|
|
42
|
+
* @param {Object<string, any>} data
|
|
43
|
+
*/
|
|
44
|
+
applyConditions(properties, data = {}) {
|
|
45
|
+
const conditions = this._getConditions();
|
|
46
|
+
const newProperties = {
|
|
47
|
+
...properties
|
|
48
|
+
};
|
|
49
|
+
for (const {
|
|
50
|
+
key,
|
|
51
|
+
condition
|
|
52
|
+
} of conditions) {
|
|
53
|
+
const shouldRemove = this._checkHideCondition(condition, data);
|
|
54
|
+
if (shouldRemove) {
|
|
55
|
+
delete newProperties[key];
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return newProperties;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Check if given condition is met. Returns null for invalid/missing conditions.
|
|
63
|
+
*
|
|
64
|
+
* @param {string} condition
|
|
65
|
+
* @param {import('../types').Data} [data]
|
|
66
|
+
*
|
|
67
|
+
* @returns {boolean|null}
|
|
68
|
+
*/
|
|
69
|
+
check(condition, data = {}) {
|
|
70
|
+
if (!condition) {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
if (!minDash.isString(condition) || !condition.startsWith('=')) {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
try {
|
|
77
|
+
// cut off initial '='
|
|
78
|
+
const result = feelin.unaryTest(condition.slice(1), data);
|
|
79
|
+
return result;
|
|
80
|
+
} catch (error) {
|
|
81
|
+
this._eventBus.fire('error', {
|
|
82
|
+
error
|
|
83
|
+
});
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Check if hide condition is met.
|
|
90
|
+
*
|
|
91
|
+
* @param {Condition} condition
|
|
92
|
+
* @param {Object<string, any>} data
|
|
93
|
+
* @returns {boolean}
|
|
94
|
+
*/
|
|
95
|
+
_checkHideCondition(condition, data) {
|
|
96
|
+
if (!condition.hide) {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
const result = this.check(condition.hide, data);
|
|
100
|
+
return result === true;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Evaluate an expression.
|
|
105
|
+
*
|
|
106
|
+
* @param {string} expression
|
|
107
|
+
* @param {import('../types').Data} [data]
|
|
108
|
+
*
|
|
109
|
+
* @returns {any}
|
|
110
|
+
*/
|
|
111
|
+
evaluate(expression, data = {}) {
|
|
112
|
+
if (!expression) {
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
if (!minDash.isString(expression) || !expression.startsWith('=')) {
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
try {
|
|
119
|
+
const result = feelin.evaluate(expression.slice(1), data);
|
|
120
|
+
return result;
|
|
121
|
+
} catch (error) {
|
|
122
|
+
this._eventBus.fire('error', {
|
|
123
|
+
error
|
|
124
|
+
});
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
_getConditions() {
|
|
129
|
+
const formFields = this._formFieldRegistry.getAll();
|
|
130
|
+
return formFields.reduce((conditions, formField) => {
|
|
131
|
+
const {
|
|
132
|
+
key,
|
|
133
|
+
conditional: condition
|
|
134
|
+
} = formField;
|
|
135
|
+
if (key && condition) {
|
|
136
|
+
return [...conditions, {
|
|
137
|
+
key,
|
|
138
|
+
condition
|
|
139
|
+
}];
|
|
140
|
+
}
|
|
141
|
+
return conditions;
|
|
142
|
+
}, []);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
ConditionChecker.$inject = ['formFieldRegistry', 'eventBus'];
|
|
146
|
+
|
|
24
147
|
var FN_REF = '__fn';
|
|
25
148
|
var DEFAULT_PRIORITY = 1000;
|
|
26
149
|
var slice = Array.prototype.slice;
|
|
@@ -454,14 +577,63 @@ function invokeFunction(fn, args) {
|
|
|
454
577
|
return fn.apply(null, args);
|
|
455
578
|
}
|
|
456
579
|
|
|
580
|
+
function countDecimals(number) {
|
|
581
|
+
const num = Big__default['default'](number);
|
|
582
|
+
if (num.toString() === num.toFixed(0)) return 0;
|
|
583
|
+
return num.toFixed().split('.')[1].length || 0;
|
|
584
|
+
}
|
|
585
|
+
function isValidNumber(value) {
|
|
586
|
+
return (typeof value === 'number' || typeof value === 'string') && value !== '' && !isNaN(Number(value));
|
|
587
|
+
}
|
|
588
|
+
function willKeyProduceValidNumber(key, previousValue, carretIndex, selectionWidth, decimalDigits) {
|
|
589
|
+
// Dot and comma are both treated as dot
|
|
590
|
+
previousValue = previousValue.replace(',', '.');
|
|
591
|
+
const isFirstDot = !previousValue.includes('.') && (key === '.' || key === ',');
|
|
592
|
+
const isFirstMinus = !previousValue.includes('-') && key === '-' && carretIndex === 0;
|
|
593
|
+
const keypressIsNumeric = /^[0-9]$/i.test(key);
|
|
594
|
+
const dotIndex = previousValue?.indexOf('.') ?? -1;
|
|
595
|
+
|
|
596
|
+
// If the carret is positioned after a dot, and the current decimal digits count is equal or greater to the maximum, disallow the key press
|
|
597
|
+
const overflowsDecimalSpace = typeof decimalDigits === 'number' && selectionWidth === 0 && dotIndex !== -1 && previousValue.includes('.') && previousValue.split('.')[1].length >= decimalDigits && carretIndex > dotIndex;
|
|
598
|
+
const keypressIsAllowedChar = keypressIsNumeric || decimalDigits !== 0 && isFirstDot || isFirstMinus;
|
|
599
|
+
return keypressIsAllowedChar && !overflowsDecimalSpace;
|
|
600
|
+
}
|
|
601
|
+
function isNullEquivalentValue(value) {
|
|
602
|
+
return value === undefined || value === null || value === '';
|
|
603
|
+
}
|
|
604
|
+
|
|
457
605
|
const EMAIL_PATTERN = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
|
|
458
606
|
const PHONE_PATTERN = /(\+|00)(297|93|244|1264|358|355|376|971|54|374|1684|1268|61|43|994|257|32|229|226|880|359|973|1242|387|590|375|501|1441|591|55|1246|673|975|267|236|1|61|41|56|86|225|237|243|242|682|57|269|238|506|53|5999|61|1345|357|420|49|253|1767|45|1809|1829|1849|213|593|20|291|212|34|372|251|358|679|500|33|298|691|241|44|995|44|233|350|224|590|220|245|240|30|1473|299|502|594|1671|592|852|504|385|509|36|62|44|91|246|353|98|964|354|972|39|1876|44|962|81|76|77|254|996|855|686|1869|82|383|965|856|961|231|218|1758|423|94|266|370|352|371|853|590|212|377|373|261|960|52|692|389|223|356|95|382|976|1670|258|222|1664|596|230|265|60|262|264|687|227|672|234|505|683|31|47|977|674|64|968|92|507|64|51|63|680|675|48|1787|1939|850|351|595|970|689|974|262|40|7|250|966|249|221|65|500|4779|677|232|503|378|252|508|381|211|239|597|421|386|46|268|1721|248|963|1649|235|228|66|992|690|993|670|676|1868|216|90|688|886|255|256|380|598|1|998|3906698|379|1784|58|1284|1340|84|678|681|685|967|27|260|263)(9[976]\d|8[987530]\d|6[987]\d|5[90]\d|42\d|3[875]\d|2[98654321]\d|9[8543210]|8[6421]|6[6543210]|5[87654321]|4[987654310]|3[9643210]|2[70]|7|1)\d{4,20}$/;
|
|
459
607
|
class Validator {
|
|
460
608
|
validateField(field, value) {
|
|
461
609
|
const {
|
|
610
|
+
type,
|
|
462
611
|
validate
|
|
463
612
|
} = field;
|
|
464
613
|
let errors = [];
|
|
614
|
+
if (type === 'number') {
|
|
615
|
+
const {
|
|
616
|
+
decimalDigits,
|
|
617
|
+
step
|
|
618
|
+
} = field;
|
|
619
|
+
if (value === 'NaN') {
|
|
620
|
+
errors = [...errors, 'Value is not a number.'];
|
|
621
|
+
} else if (value) {
|
|
622
|
+
if (decimalDigits >= 0 && countDecimals(value) > decimalDigits) {
|
|
623
|
+
errors = [...errors, 'Value is expected to ' + (decimalDigits === 0 ? 'be an integer' : `have at most ${decimalDigits} decimal digit${decimalDigits > 1 ? 's' : ''}`) + '.'];
|
|
624
|
+
}
|
|
625
|
+
if (step) {
|
|
626
|
+
const bigValue = Big__default['default'](value);
|
|
627
|
+
const bigStep = Big__default['default'](step);
|
|
628
|
+
const offset = bigValue.mod(bigStep);
|
|
629
|
+
if (offset.cmp(0) !== 0) {
|
|
630
|
+
const previousValue = bigValue.minus(offset);
|
|
631
|
+
const nextValue = previousValue.plus(bigStep);
|
|
632
|
+
errors = [...errors, `Please select a valid value, the two nearest valid values are ${previousValue} and ${nextValue}.`];
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
}
|
|
465
637
|
if (!validate) {
|
|
466
638
|
return errors;
|
|
467
639
|
}
|
|
@@ -543,6 +715,44 @@ class FormFieldRegistry {
|
|
|
543
715
|
}
|
|
544
716
|
FormFieldRegistry.$inject = ['eventBus'];
|
|
545
717
|
|
|
718
|
+
/**
|
|
719
|
+
* Retrieve variable names from given FEEL unary test.
|
|
720
|
+
*
|
|
721
|
+
* @param {string} unaryTest
|
|
722
|
+
* @returns {string[]}
|
|
723
|
+
*/
|
|
724
|
+
function getVariableNames(unaryTest) {
|
|
725
|
+
const tree = feelin.parseUnaryTests(unaryTest);
|
|
726
|
+
const cursor = tree.cursor();
|
|
727
|
+
const variables = new Set();
|
|
728
|
+
do {
|
|
729
|
+
const node = cursor.node;
|
|
730
|
+
if (node.type.name === 'VariableName') {
|
|
731
|
+
variables.add(unaryTest.slice(node.from, node.to));
|
|
732
|
+
}
|
|
733
|
+
} while (cursor.next());
|
|
734
|
+
return Array.from(variables);
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
/**
|
|
738
|
+
* Retrieve variable names from given FEEL expression.
|
|
739
|
+
*
|
|
740
|
+
* @param {string} expression
|
|
741
|
+
* @returns {string[]}
|
|
742
|
+
*/
|
|
743
|
+
function getExpressionVariableNames(expression) {
|
|
744
|
+
const tree = feelin.parseExpressions(expression);
|
|
745
|
+
const cursor = tree.cursor();
|
|
746
|
+
const variables = new Set();
|
|
747
|
+
do {
|
|
748
|
+
const node = cursor.node;
|
|
749
|
+
if (node.type.name === 'VariableName') {
|
|
750
|
+
variables.add(expression.slice(node.from, node.to));
|
|
751
|
+
}
|
|
752
|
+
} while (cursor.next());
|
|
753
|
+
return Array.from(variables);
|
|
754
|
+
}
|
|
755
|
+
|
|
546
756
|
function createInjector(bootstrapModules) {
|
|
547
757
|
const injector = new didi.Injector(bootstrapModules);
|
|
548
758
|
injector.init();
|
|
@@ -560,6 +770,7 @@ function createFormContainer(prefix = 'fjs') {
|
|
|
560
770
|
return container;
|
|
561
771
|
}
|
|
562
772
|
|
|
773
|
+
const EXPRESSION_PROPERTIES = ['alt', 'source'];
|
|
563
774
|
function findErrors(errors, path) {
|
|
564
775
|
return errors[pathStringify(path)];
|
|
565
776
|
}
|
|
@@ -613,16 +824,16 @@ function clone(data, replacer) {
|
|
|
613
824
|
*
|
|
614
825
|
* @return {string[]}
|
|
615
826
|
*/
|
|
616
|
-
|
|
617
827
|
function getSchemaVariables(schema) {
|
|
618
828
|
if (!schema.components) {
|
|
619
829
|
return [];
|
|
620
830
|
}
|
|
621
|
-
|
|
831
|
+
const variables = schema.components.reduce((variables, component) => {
|
|
622
832
|
const {
|
|
623
833
|
key,
|
|
624
834
|
valuesKey,
|
|
625
|
-
type
|
|
835
|
+
type,
|
|
836
|
+
conditional
|
|
626
837
|
} = component;
|
|
627
838
|
if (['text', 'button'].includes(type)) {
|
|
628
839
|
return variables;
|
|
@@ -630,11 +841,33 @@ function getSchemaVariables(schema) {
|
|
|
630
841
|
if (key) {
|
|
631
842
|
variables = [...variables, key];
|
|
632
843
|
}
|
|
633
|
-
if (valuesKey
|
|
844
|
+
if (valuesKey) {
|
|
634
845
|
variables = [...variables, valuesKey];
|
|
635
846
|
}
|
|
847
|
+
if (conditional && conditional.hide) {
|
|
848
|
+
// cut off initial '='
|
|
849
|
+
const conditionVariables = getVariableNames(conditional.hide.slice(1));
|
|
850
|
+
variables = [...variables, ...conditionVariables];
|
|
851
|
+
}
|
|
852
|
+
EXPRESSION_PROPERTIES.forEach(prop => {
|
|
853
|
+
const property = component[prop];
|
|
854
|
+
if (property && isExpression$1(property)) {
|
|
855
|
+
// cut off initial '='
|
|
856
|
+
const expressionVariables = getExpressionVariableNames(property.slice(1));
|
|
857
|
+
variables = [...variables, ...expressionVariables];
|
|
858
|
+
}
|
|
859
|
+
});
|
|
636
860
|
return variables;
|
|
637
861
|
}, []);
|
|
862
|
+
|
|
863
|
+
// remove duplicates
|
|
864
|
+
return Array.from(new Set(variables));
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
// helper ///////////////
|
|
868
|
+
|
|
869
|
+
function isExpression$1(value) {
|
|
870
|
+
return minDash.isString(value) && value.startsWith('=');
|
|
638
871
|
}
|
|
639
872
|
|
|
640
873
|
class Importer {
|
|
@@ -663,11 +896,11 @@ class Importer {
|
|
|
663
896
|
const warnings = [];
|
|
664
897
|
try {
|
|
665
898
|
const importedSchema = this.importFormField(clone(schema)),
|
|
666
|
-
|
|
899
|
+
initializedData = this.initializeFieldValues(clone(data));
|
|
667
900
|
return {
|
|
668
901
|
warnings,
|
|
669
902
|
schema: importedSchema,
|
|
670
|
-
data:
|
|
903
|
+
data: initializedData
|
|
671
904
|
};
|
|
672
905
|
} catch (err) {
|
|
673
906
|
err.warnings = warnings;
|
|
@@ -733,26 +966,16 @@ class Importer {
|
|
|
733
966
|
/**
|
|
734
967
|
* @param {Object} data
|
|
735
968
|
*
|
|
736
|
-
* @return {Object}
|
|
969
|
+
* @return {Object} initializedData
|
|
737
970
|
*/
|
|
738
|
-
|
|
739
|
-
return this._formFieldRegistry.getAll().reduce((
|
|
971
|
+
initializeFieldValues(data) {
|
|
972
|
+
return this._formFieldRegistry.getAll().reduce((initializedData, formField) => {
|
|
740
973
|
const {
|
|
741
974
|
defaultValue,
|
|
742
975
|
_path,
|
|
743
|
-
type
|
|
744
|
-
valuesKey
|
|
976
|
+
type
|
|
745
977
|
} = formField;
|
|
746
978
|
|
|
747
|
-
// get values defined via valuesKey
|
|
748
|
-
|
|
749
|
-
if (valuesKey) {
|
|
750
|
-
importedData = {
|
|
751
|
-
...importedData,
|
|
752
|
-
[valuesKey]: minDash.get(data, [valuesKey])
|
|
753
|
-
};
|
|
754
|
-
}
|
|
755
|
-
|
|
756
979
|
// try to get value from data
|
|
757
980
|
// if unavailable - try to get default value from form field
|
|
758
981
|
// if unavailable - get empty value from form field
|
|
@@ -767,14 +990,14 @@ class Importer {
|
|
|
767
990
|
value: valueData
|
|
768
991
|
});
|
|
769
992
|
}
|
|
770
|
-
const
|
|
771
|
-
|
|
772
|
-
...
|
|
773
|
-
[_path[0]]:
|
|
993
|
+
const initializedFieldValue = !minDash.isUndefined(valueData) ? valueData : !minDash.isUndefined(defaultValue) ? defaultValue : fieldImplementation.emptyValue;
|
|
994
|
+
initializedData = {
|
|
995
|
+
...initializedData,
|
|
996
|
+
[_path[0]]: initializedFieldValue
|
|
774
997
|
};
|
|
775
998
|
}
|
|
776
|
-
return
|
|
777
|
-
},
|
|
999
|
+
return initializedData;
|
|
1000
|
+
}, data);
|
|
778
1001
|
}
|
|
779
1002
|
}
|
|
780
1003
|
Importer.$inject = ['formFieldRegistry', 'formFields'];
|
|
@@ -788,6 +1011,7 @@ const NODE_TYPE_TEXT = 3,
|
|
|
788
1011
|
const ALLOWED_NODES = ['h1', 'h2', 'h3', 'h4', 'h5', 'span', 'em', 'a', 'p', 'div', 'ul', 'ol', 'li', 'hr', 'blockquote', 'img', 'pre', 'code', 'br', 'strong'];
|
|
789
1012
|
const ALLOWED_ATTRIBUTES = ['align', 'alt', 'class', 'href', 'id', 'name', 'rel', 'target', 'src'];
|
|
790
1013
|
const ALLOWED_URI_PATTERN = /^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i; // eslint-disable-line no-useless-escape
|
|
1014
|
+
const ALLOWED_IMAGE_SRC_PATTERN = /^(https?|data):.*/i; // eslint-disable-line no-useless-escape
|
|
791
1015
|
const ATTR_WHITESPACE_PATTERN = /[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g; // eslint-disable-line no-control-regex
|
|
792
1016
|
|
|
793
1017
|
const FORM_ELEMENT = document.createElement('form');
|
|
@@ -811,6 +1035,10 @@ function sanitizeHTML(html) {
|
|
|
811
1035
|
return '';
|
|
812
1036
|
}
|
|
813
1037
|
}
|
|
1038
|
+
function sanitizeImageSource(src) {
|
|
1039
|
+
const valid = ALLOWED_IMAGE_SRC_PATTERN.test(src);
|
|
1040
|
+
return valid ? src : '';
|
|
1041
|
+
}
|
|
814
1042
|
|
|
815
1043
|
/**
|
|
816
1044
|
* Recursively sanitize a HTML node, potentially
|
|
@@ -921,6 +1149,19 @@ function safeMarkdown(markdown) {
|
|
|
921
1149
|
const html = markdownToHTML(markdown);
|
|
922
1150
|
return sanitizeHTML(html);
|
|
923
1151
|
}
|
|
1152
|
+
|
|
1153
|
+
/**
|
|
1154
|
+
* Sanitizes an image source to ensure we only allow for data URI and links
|
|
1155
|
+
* that start with http(s).
|
|
1156
|
+
*
|
|
1157
|
+
* Note: Most browsers anyway do not support script execution in <img> elements.
|
|
1158
|
+
*
|
|
1159
|
+
* @param {string} src
|
|
1160
|
+
* @returns {string}
|
|
1161
|
+
*/
|
|
1162
|
+
function safeImageSource(src) {
|
|
1163
|
+
return sanitizeImageSource(src);
|
|
1164
|
+
}
|
|
924
1165
|
function sanitizeSingleSelectValue(options) {
|
|
925
1166
|
const {
|
|
926
1167
|
formField,
|
|
@@ -960,7 +1201,7 @@ function sanitizeMultiSelectValue(options) {
|
|
|
960
1201
|
}
|
|
961
1202
|
}
|
|
962
1203
|
|
|
963
|
-
const type$
|
|
1204
|
+
const type$a = 'button';
|
|
964
1205
|
function Button(props) {
|
|
965
1206
|
const {
|
|
966
1207
|
disabled,
|
|
@@ -970,7 +1211,7 @@ function Button(props) {
|
|
|
970
1211
|
action = 'submit'
|
|
971
1212
|
} = field;
|
|
972
1213
|
return jsxRuntime.jsx("div", {
|
|
973
|
-
class: formFieldClasses(type$
|
|
1214
|
+
class: formFieldClasses(type$a),
|
|
974
1215
|
children: jsxRuntime.jsx("button", {
|
|
975
1216
|
class: "fjs-button",
|
|
976
1217
|
type: action,
|
|
@@ -985,7 +1226,7 @@ Button.create = function (options = {}) {
|
|
|
985
1226
|
...options
|
|
986
1227
|
};
|
|
987
1228
|
};
|
|
988
|
-
Button.type = type$
|
|
1229
|
+
Button.type = type$a;
|
|
989
1230
|
Button.label = 'Button';
|
|
990
1231
|
Button.keyed = true;
|
|
991
1232
|
|
|
@@ -1061,7 +1302,7 @@ function Label(props) {
|
|
|
1061
1302
|
});
|
|
1062
1303
|
}
|
|
1063
1304
|
|
|
1064
|
-
const type$
|
|
1305
|
+
const type$9 = 'checkbox';
|
|
1065
1306
|
function Checkbox(props) {
|
|
1066
1307
|
const {
|
|
1067
1308
|
disabled,
|
|
@@ -1086,7 +1327,7 @@ function Checkbox(props) {
|
|
|
1086
1327
|
formId
|
|
1087
1328
|
} = hooks.useContext(FormContext);
|
|
1088
1329
|
return jsxRuntime.jsxs("div", {
|
|
1089
|
-
class: classNames__default['default'](formFieldClasses(type$
|
|
1330
|
+
class: classNames__default['default'](formFieldClasses(type$9, {
|
|
1090
1331
|
errors,
|
|
1091
1332
|
disabled
|
|
1092
1333
|
}), {
|
|
@@ -1116,7 +1357,7 @@ Checkbox.create = function (options = {}) {
|
|
|
1116
1357
|
...options
|
|
1117
1358
|
};
|
|
1118
1359
|
};
|
|
1119
|
-
Checkbox.type = type$
|
|
1360
|
+
Checkbox.type = type$9;
|
|
1120
1361
|
Checkbox.label = 'Checkbox';
|
|
1121
1362
|
Checkbox.keyed = true;
|
|
1122
1363
|
Checkbox.emptyValue = false;
|
|
@@ -1191,7 +1432,7 @@ const buildLoadedState = values => ({
|
|
|
1191
1432
|
state: LOAD_STATES.LOADED
|
|
1192
1433
|
});
|
|
1193
1434
|
|
|
1194
|
-
const type$
|
|
1435
|
+
const type$8 = 'checklist';
|
|
1195
1436
|
function Checklist(props) {
|
|
1196
1437
|
const {
|
|
1197
1438
|
disabled,
|
|
@@ -1224,7 +1465,7 @@ function Checklist(props) {
|
|
|
1224
1465
|
formId
|
|
1225
1466
|
} = hooks.useContext(FormContext);
|
|
1226
1467
|
return jsxRuntime.jsxs("div", {
|
|
1227
|
-
class: classNames__default['default'](formFieldClasses(type$
|
|
1468
|
+
class: classNames__default['default'](formFieldClasses(type$8, {
|
|
1228
1469
|
errors,
|
|
1229
1470
|
disabled
|
|
1230
1471
|
})),
|
|
@@ -1264,12 +1505,28 @@ Checklist.create = function (options = {}) {
|
|
|
1264
1505
|
...options
|
|
1265
1506
|
};
|
|
1266
1507
|
};
|
|
1267
|
-
Checklist.type = type$
|
|
1508
|
+
Checklist.type = type$8;
|
|
1268
1509
|
Checklist.label = 'Checklist';
|
|
1269
1510
|
Checklist.keyed = true;
|
|
1270
1511
|
Checklist.emptyValue = [];
|
|
1271
1512
|
Checklist.sanitizeValue = sanitizeMultiSelectValue;
|
|
1272
1513
|
|
|
1514
|
+
/**
|
|
1515
|
+
* Check if condition is met with given variables.
|
|
1516
|
+
*
|
|
1517
|
+
* @param {string | undefined} condition
|
|
1518
|
+
* @param {import('../../types').Data} data
|
|
1519
|
+
*
|
|
1520
|
+
* @returns {boolean} true if condition is met or no condition or condition checker exists
|
|
1521
|
+
*/
|
|
1522
|
+
function useCondition(condition, data) {
|
|
1523
|
+
const conditionChecker = useService('conditionChecker', false);
|
|
1524
|
+
if (!conditionChecker) {
|
|
1525
|
+
return null;
|
|
1526
|
+
}
|
|
1527
|
+
return conditionChecker.check(condition, data);
|
|
1528
|
+
}
|
|
1529
|
+
|
|
1273
1530
|
const noop$1 = () => false;
|
|
1274
1531
|
function FormField(props) {
|
|
1275
1532
|
const {
|
|
@@ -1287,7 +1544,8 @@ function FormField(props) {
|
|
|
1287
1544
|
properties
|
|
1288
1545
|
} = form._getState();
|
|
1289
1546
|
const {
|
|
1290
|
-
Element
|
|
1547
|
+
Element,
|
|
1548
|
+
Empty
|
|
1291
1549
|
} = hooks.useContext(FormRenderContext);
|
|
1292
1550
|
const FormFieldComponent = formFields.get(field.type);
|
|
1293
1551
|
if (!FormFieldComponent) {
|
|
@@ -1296,6 +1554,10 @@ function FormField(props) {
|
|
|
1296
1554
|
const value = minDash.get(data, _path);
|
|
1297
1555
|
const fieldErrors = findErrors(errors, _path);
|
|
1298
1556
|
const disabled = properties.readOnly || field.disabled || false;
|
|
1557
|
+
const hidden = useHideCondition(field, data);
|
|
1558
|
+
if (hidden) {
|
|
1559
|
+
return jsxRuntime.jsx(Empty, {});
|
|
1560
|
+
}
|
|
1299
1561
|
return jsxRuntime.jsx(Element, {
|
|
1300
1562
|
field: field,
|
|
1301
1563
|
children: jsxRuntime.jsx(FormFieldComponent, {
|
|
@@ -1307,6 +1569,10 @@ function FormField(props) {
|
|
|
1307
1569
|
})
|
|
1308
1570
|
});
|
|
1309
1571
|
}
|
|
1572
|
+
function useHideCondition(field, data) {
|
|
1573
|
+
const hideCondition = field.conditional && field.conditional.hide;
|
|
1574
|
+
return useCondition(hideCondition, data) === true;
|
|
1575
|
+
}
|
|
1310
1576
|
|
|
1311
1577
|
function Default(props) {
|
|
1312
1578
|
const {
|
|
@@ -1452,6 +1718,7 @@ function FormComponent(props) {
|
|
|
1452
1718
|
class: "fjs-form",
|
|
1453
1719
|
onSubmit: handleSubmit,
|
|
1454
1720
|
onReset: handleReset,
|
|
1721
|
+
noValidate: true,
|
|
1455
1722
|
children: [jsxRuntime.jsx(FormField, {
|
|
1456
1723
|
field: schema,
|
|
1457
1724
|
onChange: onChange
|
|
@@ -1459,32 +1726,226 @@ function FormComponent(props) {
|
|
|
1459
1726
|
});
|
|
1460
1727
|
}
|
|
1461
1728
|
|
|
1729
|
+
/**
|
|
1730
|
+
*
|
|
1731
|
+
* @param {string | undefined} expression
|
|
1732
|
+
* @param {import('../../types').Data} data
|
|
1733
|
+
*/
|
|
1734
|
+
function useEvaluation(expression, data) {
|
|
1735
|
+
const conditionChecker = useService('conditionChecker', false);
|
|
1736
|
+
if (!conditionChecker) {
|
|
1737
|
+
return null;
|
|
1738
|
+
}
|
|
1739
|
+
return conditionChecker.evaluate(expression, data);
|
|
1740
|
+
}
|
|
1741
|
+
|
|
1742
|
+
/**
|
|
1743
|
+
*
|
|
1744
|
+
* @param {string} value
|
|
1745
|
+
*/
|
|
1746
|
+
function useExpressionValue(value) {
|
|
1747
|
+
const formData = useService('form')._getState().data;
|
|
1748
|
+
if (!isExpression(value)) {
|
|
1749
|
+
return value;
|
|
1750
|
+
}
|
|
1751
|
+
|
|
1752
|
+
// We can ignore this hook rule as we do not use
|
|
1753
|
+
// state or effects in our custom hooks
|
|
1754
|
+
/* eslint-disable-next-line react-hooks/rules-of-hooks */
|
|
1755
|
+
return useEvaluation(value, formData);
|
|
1756
|
+
}
|
|
1757
|
+
|
|
1758
|
+
// helper ///////////////
|
|
1759
|
+
|
|
1760
|
+
function isExpression(value) {
|
|
1761
|
+
return minDash.isString(value) && value.startsWith('=');
|
|
1762
|
+
}
|
|
1763
|
+
|
|
1764
|
+
function _extends$1() { _extends$1 = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$1.apply(this, arguments); }
|
|
1765
|
+
var ImagePlaceholder = (({
|
|
1766
|
+
styles = {},
|
|
1767
|
+
...props
|
|
1768
|
+
}) => /*#__PURE__*/React__default['default'].createElement("svg", _extends$1({
|
|
1769
|
+
width: "64",
|
|
1770
|
+
height: "64",
|
|
1771
|
+
viewBox: "0 0 1280 1280",
|
|
1772
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1773
|
+
fillRule: "evenodd",
|
|
1774
|
+
clipRule: "evenodd",
|
|
1775
|
+
strokeLinejoin: "round",
|
|
1776
|
+
strokeMiterlimit: "2"
|
|
1777
|
+
}, props), /*#__PURE__*/React__default['default'].createElement("path", {
|
|
1778
|
+
fill: "#e5e9ed",
|
|
1779
|
+
d: "M0 0h1280v1280H0z"
|
|
1780
|
+
}), /*#__PURE__*/React__default['default'].createElement("path", {
|
|
1781
|
+
d: "M910 410H370v470h540V410zm-57.333 57.333v355.334H427.333V467.333h425.334z",
|
|
1782
|
+
fill: "#cad3db"
|
|
1783
|
+
}), /*#__PURE__*/React__default['default'].createElement("path", {
|
|
1784
|
+
d: "M810 770H480v-60l100-170 130 170 100-65v125z",
|
|
1785
|
+
fill: "#cad3db"
|
|
1786
|
+
}), /*#__PURE__*/React__default['default'].createElement("circle", {
|
|
1787
|
+
cx: "750",
|
|
1788
|
+
cy: "550",
|
|
1789
|
+
r: "50",
|
|
1790
|
+
fill: "#cad3db",
|
|
1791
|
+
transform: "translate(10 10)"
|
|
1792
|
+
})));
|
|
1793
|
+
|
|
1794
|
+
const type$7 = 'image';
|
|
1795
|
+
function Image(props) {
|
|
1796
|
+
const {
|
|
1797
|
+
field
|
|
1798
|
+
} = props;
|
|
1799
|
+
const {
|
|
1800
|
+
alt,
|
|
1801
|
+
id,
|
|
1802
|
+
source
|
|
1803
|
+
} = field;
|
|
1804
|
+
const safeSource = safeImageSource(useExpressionValue(source));
|
|
1805
|
+
const altText = useExpressionValue(alt);
|
|
1806
|
+
const {
|
|
1807
|
+
formId
|
|
1808
|
+
} = hooks.useContext(FormContext);
|
|
1809
|
+
return jsxRuntime.jsx("div", {
|
|
1810
|
+
class: formFieldClasses(type$7),
|
|
1811
|
+
children: jsxRuntime.jsxs("div", {
|
|
1812
|
+
class: "fjs-image-container",
|
|
1813
|
+
children: [safeSource && jsxRuntime.jsx("img", {
|
|
1814
|
+
alt: altText,
|
|
1815
|
+
src: safeSource,
|
|
1816
|
+
class: "fjs-image",
|
|
1817
|
+
id: prefixId(id, formId)
|
|
1818
|
+
}), !safeSource && jsxRuntime.jsx("div", {
|
|
1819
|
+
class: "fjs-image-placeholder",
|
|
1820
|
+
children: jsxRuntime.jsx(ImagePlaceholder, {
|
|
1821
|
+
alt: "This is an image placeholder"
|
|
1822
|
+
})
|
|
1823
|
+
})]
|
|
1824
|
+
})
|
|
1825
|
+
});
|
|
1826
|
+
}
|
|
1827
|
+
Image.create = function (options = {}) {
|
|
1828
|
+
return {
|
|
1829
|
+
...options
|
|
1830
|
+
};
|
|
1831
|
+
};
|
|
1832
|
+
Image.type = type$7;
|
|
1833
|
+
Image.keyed = false;
|
|
1834
|
+
|
|
1462
1835
|
const type$6 = 'number';
|
|
1463
|
-
function
|
|
1836
|
+
function Numberfield(props) {
|
|
1464
1837
|
const {
|
|
1465
1838
|
disabled,
|
|
1466
1839
|
errors = [],
|
|
1467
1840
|
field,
|
|
1468
|
-
value
|
|
1841
|
+
value,
|
|
1842
|
+
onChange
|
|
1469
1843
|
} = props;
|
|
1470
1844
|
const {
|
|
1471
1845
|
description,
|
|
1472
1846
|
id,
|
|
1473
1847
|
label,
|
|
1474
|
-
validate = {}
|
|
1848
|
+
validate = {},
|
|
1849
|
+
decimalDigits,
|
|
1850
|
+
serializeToString = false,
|
|
1851
|
+
increment: incrementValue
|
|
1475
1852
|
} = field;
|
|
1476
1853
|
const {
|
|
1477
1854
|
required
|
|
1478
1855
|
} = validate;
|
|
1479
|
-
const
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1856
|
+
const inputRef = hooks.useRef();
|
|
1857
|
+
const [stringValueCache, setStringValueCache] = hooks.useState('');
|
|
1858
|
+
|
|
1859
|
+
// checks whether the value currently in the form data is practically different from the one in the input field cache
|
|
1860
|
+
// this allows us to guarantee the field always displays valid form data, but without auto-simplifying values like 1.000 to 1
|
|
1861
|
+
const cacheValueMatchesState = hooks.useMemo(() => Numberfield.sanitizeValue({
|
|
1862
|
+
value,
|
|
1863
|
+
formField: field
|
|
1864
|
+
}) === Numberfield.sanitizeValue({
|
|
1865
|
+
value: stringValueCache,
|
|
1866
|
+
formField: field
|
|
1867
|
+
}), [stringValueCache, value, field]);
|
|
1868
|
+
const displayValue = hooks.useMemo(() => {
|
|
1869
|
+
if (value === 'NaN') return 'NaN';
|
|
1870
|
+
return cacheValueMatchesState ? stringValueCache : value || value === 0 ? Big__default['default'](value).toFixed() : '';
|
|
1871
|
+
}, [stringValueCache, value, cacheValueMatchesState]);
|
|
1872
|
+
const arrowIncrementValue = hooks.useMemo(() => {
|
|
1873
|
+
if (incrementValue) return Big__default['default'](incrementValue);
|
|
1874
|
+
if (decimalDigits) return Big__default['default'](`1e-${decimalDigits}`);
|
|
1875
|
+
return Big__default['default']('1');
|
|
1876
|
+
}, [decimalDigits, incrementValue]);
|
|
1877
|
+
const setValue = hooks.useCallback(stringValue => {
|
|
1878
|
+
if (isNullEquivalentValue(stringValue)) {
|
|
1879
|
+
setStringValueCache('');
|
|
1880
|
+
onChange({
|
|
1881
|
+
field,
|
|
1882
|
+
value: null
|
|
1883
|
+
});
|
|
1884
|
+
return;
|
|
1885
|
+
}
|
|
1886
|
+
|
|
1887
|
+
// treat commas as dots
|
|
1888
|
+
stringValue = stringValue.replaceAll(',', '.');
|
|
1889
|
+
if (isNaN(Number(stringValue))) {
|
|
1890
|
+
setStringValueCache('NaN');
|
|
1891
|
+
onChange({
|
|
1892
|
+
field,
|
|
1893
|
+
value: 'NaN'
|
|
1894
|
+
});
|
|
1895
|
+
return;
|
|
1896
|
+
}
|
|
1897
|
+
setStringValueCache(stringValue);
|
|
1898
|
+
onChange({
|
|
1483
1899
|
field,
|
|
1484
|
-
value: Number
|
|
1485
|
-
value: target.value
|
|
1486
|
-
})
|
|
1900
|
+
value: serializeToString ? stringValue : Number(stringValue)
|
|
1487
1901
|
});
|
|
1902
|
+
}, [field, onChange, serializeToString]);
|
|
1903
|
+
const increment = () => {
|
|
1904
|
+
const base = isValidNumber(value) ? Big__default['default'](value) : Big__default['default'](0);
|
|
1905
|
+
const stepFlooredValue = base.minus(base.mod(arrowIncrementValue));
|
|
1906
|
+
|
|
1907
|
+
// note: toFixed() behaves differently in big.js
|
|
1908
|
+
setValue(stepFlooredValue.plus(arrowIncrementValue).toFixed());
|
|
1909
|
+
};
|
|
1910
|
+
const decrement = () => {
|
|
1911
|
+
const base = isValidNumber(value) ? Big__default['default'](value) : Big__default['default'](0);
|
|
1912
|
+
const offset = base.mod(arrowIncrementValue);
|
|
1913
|
+
if (offset.cmp(0) === 0) {
|
|
1914
|
+
// if we're already on a valid step, decrement
|
|
1915
|
+
setValue(base.minus(arrowIncrementValue).toFixed());
|
|
1916
|
+
} else {
|
|
1917
|
+
// otherwise floor to the step
|
|
1918
|
+
const stepFlooredValue = base.minus(base.mod(arrowIncrementValue));
|
|
1919
|
+
setValue(stepFlooredValue.toFixed());
|
|
1920
|
+
}
|
|
1921
|
+
};
|
|
1922
|
+
const onKeyDown = e => {
|
|
1923
|
+
// delete the NaN state all at once on backspace or delete
|
|
1924
|
+
if (value === 'NaN' && (e.code === 'Backspace' || e.code === 'Delete')) {
|
|
1925
|
+
setValue(null);
|
|
1926
|
+
e.preventDefault();
|
|
1927
|
+
return;
|
|
1928
|
+
}
|
|
1929
|
+
if (e.code === 'ArrowUp') {
|
|
1930
|
+
increment();
|
|
1931
|
+
e.preventDefault();
|
|
1932
|
+
return;
|
|
1933
|
+
}
|
|
1934
|
+
if (e.code === 'ArrowDown') {
|
|
1935
|
+
decrement();
|
|
1936
|
+
e.preventDefault();
|
|
1937
|
+
return;
|
|
1938
|
+
}
|
|
1939
|
+
};
|
|
1940
|
+
|
|
1941
|
+
// intercept key presses which would lead to an invalid number
|
|
1942
|
+
const onKeyPress = e => {
|
|
1943
|
+
const carretIndex = inputRef.current.selectionStart;
|
|
1944
|
+
const selectionWidth = inputRef.current.selectionStart - inputRef.current.selectionEnd;
|
|
1945
|
+
const previousValue = inputRef.current.value;
|
|
1946
|
+
if (!willKeyProduceValidNumber(e.key, previousValue, carretIndex, selectionWidth, decimalDigits)) {
|
|
1947
|
+
e.preventDefault();
|
|
1948
|
+
}
|
|
1488
1949
|
};
|
|
1489
1950
|
const {
|
|
1490
1951
|
formId
|
|
@@ -1498,13 +1959,45 @@ function Number(props) {
|
|
|
1498
1959
|
id: prefixId(id, formId),
|
|
1499
1960
|
label: label,
|
|
1500
1961
|
required: required
|
|
1501
|
-
}), jsxRuntime.
|
|
1502
|
-
class:
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1962
|
+
}), jsxRuntime.jsxs("div", {
|
|
1963
|
+
class: classNames__default['default']('fjs-input-group', {
|
|
1964
|
+
'disabled': disabled
|
|
1965
|
+
}, {
|
|
1966
|
+
'hasErrors': errors.length
|
|
1967
|
+
}),
|
|
1968
|
+
children: [jsxRuntime.jsx("input", {
|
|
1969
|
+
ref: inputRef,
|
|
1970
|
+
class: "fjs-input",
|
|
1971
|
+
disabled: disabled,
|
|
1972
|
+
id: prefixId(id, formId),
|
|
1973
|
+
onKeyDown: onKeyDown,
|
|
1974
|
+
onKeyPress: onKeyPress
|
|
1975
|
+
|
|
1976
|
+
// @ts-ignore
|
|
1977
|
+
,
|
|
1978
|
+
onInput: e => setValue(e.target.value),
|
|
1979
|
+
type: "text",
|
|
1980
|
+
autoComplete: "off",
|
|
1981
|
+
step: arrowIncrementValue,
|
|
1982
|
+
value: displayValue
|
|
1983
|
+
}), jsxRuntime.jsxs("div", {
|
|
1984
|
+
class: classNames__default['default']('fjs-number-arrow-container', {
|
|
1985
|
+
'disabled': disabled
|
|
1986
|
+
}),
|
|
1987
|
+
children: [jsxRuntime.jsx("button", {
|
|
1988
|
+
class: "fjs-number-arrow-up",
|
|
1989
|
+
onClick: () => increment(),
|
|
1990
|
+
tabIndex: -1,
|
|
1991
|
+
children: "\u02C4"
|
|
1992
|
+
}), jsxRuntime.jsx("div", {
|
|
1993
|
+
class: "fjs-number-arrow-separator"
|
|
1994
|
+
}), jsxRuntime.jsx("button", {
|
|
1995
|
+
class: "fjs-number-arrow-down",
|
|
1996
|
+
onClick: () => decrement(),
|
|
1997
|
+
tabIndex: -1,
|
|
1998
|
+
children: "\u02C5"
|
|
1999
|
+
})]
|
|
2000
|
+
})]
|
|
1508
2001
|
}), jsxRuntime.jsx(Description, {
|
|
1509
2002
|
description: description
|
|
1510
2003
|
}), jsxRuntime.jsx(Errors, {
|
|
@@ -1512,21 +2005,24 @@ function Number(props) {
|
|
|
1512
2005
|
})]
|
|
1513
2006
|
});
|
|
1514
2007
|
}
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
};
|
|
1520
|
-
Number.sanitizeValue = ({
|
|
1521
|
-
value
|
|
2008
|
+
Numberfield.create = (options = {}) => options;
|
|
2009
|
+
Numberfield.sanitizeValue = ({
|
|
2010
|
+
value,
|
|
2011
|
+
formField
|
|
1522
2012
|
}) => {
|
|
1523
|
-
|
|
1524
|
-
|
|
2013
|
+
// null state is allowed
|
|
2014
|
+
if (isNullEquivalentValue(value)) return null;
|
|
2015
|
+
|
|
2016
|
+
// if data cannot be parsed as a valid number, go into invalid NaN state
|
|
2017
|
+
if (!isValidNumber(value)) return 'NaN';
|
|
2018
|
+
|
|
2019
|
+
// otherwise parse to formatting type
|
|
2020
|
+
return formField.serializeToString ? value.toString() : Number(value);
|
|
1525
2021
|
};
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
2022
|
+
Numberfield.type = type$6;
|
|
2023
|
+
Numberfield.keyed = true;
|
|
2024
|
+
Numberfield.label = 'Number';
|
|
2025
|
+
Numberfield.emptyValue = null;
|
|
1530
2026
|
|
|
1531
2027
|
const type$5 = 'radio';
|
|
1532
2028
|
function Radio(props) {
|
|
@@ -2160,7 +2656,7 @@ Textarea.sanitizeValue = ({
|
|
|
2160
2656
|
value
|
|
2161
2657
|
}) => minDash.isArray(value) || minDash.isObject(value) ? '' : String(value);
|
|
2162
2658
|
|
|
2163
|
-
const formFields = [Button, Checkbox, Checklist, Default,
|
|
2659
|
+
const formFields = [Button, Checkbox, Checklist, Default, Image, Numberfield, Radio, Select, Taglist, Text, Textfield, Textarea];
|
|
2164
2660
|
|
|
2165
2661
|
class FormFields {
|
|
2166
2662
|
constructor() {
|
|
@@ -2240,6 +2736,7 @@ var renderModule = {
|
|
|
2240
2736
|
|
|
2241
2737
|
var core = {
|
|
2242
2738
|
__depends__: [importModule, renderModule],
|
|
2739
|
+
conditionChecker: ['type', ConditionChecker],
|
|
2243
2740
|
eventBus: ['type', EventBus],
|
|
2244
2741
|
formFieldRegistry: ['type', FormFieldRegistry],
|
|
2245
2742
|
validator: ['type', Validator]
|
|
@@ -2355,14 +2852,14 @@ class Form {
|
|
|
2355
2852
|
this.clear();
|
|
2356
2853
|
const {
|
|
2357
2854
|
schema: importedSchema,
|
|
2358
|
-
data:
|
|
2855
|
+
data: initializedData,
|
|
2359
2856
|
warnings
|
|
2360
2857
|
} = this.get('importer').importSchema(schema, data);
|
|
2361
2858
|
this._setState({
|
|
2362
|
-
data:
|
|
2859
|
+
data: initializedData,
|
|
2363
2860
|
errors: {},
|
|
2364
2861
|
schema: importedSchema,
|
|
2365
|
-
initialData: clone(
|
|
2862
|
+
initialData: clone(initializedData)
|
|
2366
2863
|
});
|
|
2367
2864
|
this._emit('import.done', {
|
|
2368
2865
|
warnings
|
|
@@ -2394,14 +2891,13 @@ class Form {
|
|
|
2394
2891
|
}
|
|
2395
2892
|
const data = this._getSubmitData();
|
|
2396
2893
|
const errors = this.validate();
|
|
2397
|
-
this.
|
|
2894
|
+
const filteredErrors = this._applyConditions(errors, data);
|
|
2895
|
+
const result = {
|
|
2398
2896
|
data,
|
|
2399
|
-
errors
|
|
2400
|
-
});
|
|
2401
|
-
return {
|
|
2402
|
-
data,
|
|
2403
|
-
errors
|
|
2897
|
+
errors: filteredErrors
|
|
2404
2898
|
};
|
|
2899
|
+
this._emit('submit', result);
|
|
2900
|
+
return result;
|
|
2405
2901
|
}
|
|
2406
2902
|
reset() {
|
|
2407
2903
|
this._emit('reset');
|
|
@@ -2582,7 +3078,8 @@ class Form {
|
|
|
2582
3078
|
*/
|
|
2583
3079
|
_getSubmitData() {
|
|
2584
3080
|
const formFieldRegistry = this.get('formFieldRegistry');
|
|
2585
|
-
|
|
3081
|
+
const formData = this._getState().data;
|
|
3082
|
+
const submitData = formFieldRegistry.getAll().reduce((previous, field) => {
|
|
2586
3083
|
const {
|
|
2587
3084
|
disabled,
|
|
2588
3085
|
_path
|
|
@@ -2590,14 +3087,24 @@ class Form {
|
|
|
2590
3087
|
|
|
2591
3088
|
// do not submit disabled form fields
|
|
2592
3089
|
if (disabled || !_path) {
|
|
2593
|
-
return
|
|
3090
|
+
return previous;
|
|
2594
3091
|
}
|
|
2595
|
-
const value = minDash.get(
|
|
3092
|
+
const value = minDash.get(formData, _path);
|
|
2596
3093
|
return {
|
|
2597
|
-
...
|
|
3094
|
+
...previous,
|
|
2598
3095
|
[_path[0]]: value
|
|
2599
3096
|
};
|
|
2600
3097
|
}, {});
|
|
3098
|
+
const filteredSubmitData = this._applyConditions(submitData, formData);
|
|
3099
|
+
return filteredSubmitData;
|
|
3100
|
+
}
|
|
3101
|
+
|
|
3102
|
+
/**
|
|
3103
|
+
* @internal
|
|
3104
|
+
*/
|
|
3105
|
+
_applyConditions(toFilter, data) {
|
|
3106
|
+
const conditionChecker = this.get('conditionChecker');
|
|
3107
|
+
return conditionChecker.applyConditions(toFilter, data);
|
|
2601
3108
|
}
|
|
2602
3109
|
}
|
|
2603
3110
|
|
|
@@ -2636,7 +3143,8 @@ exports.FormContext = FormContext;
|
|
|
2636
3143
|
exports.FormFieldRegistry = FormFieldRegistry;
|
|
2637
3144
|
exports.FormFields = FormFields;
|
|
2638
3145
|
exports.FormRenderContext = FormRenderContext;
|
|
2639
|
-
exports.
|
|
3146
|
+
exports.Image = Image;
|
|
3147
|
+
exports.Numberfield = Numberfield;
|
|
2640
3148
|
exports.Radio = Radio;
|
|
2641
3149
|
exports.Select = Select;
|
|
2642
3150
|
exports.Taglist = Taglist;
|