@bpmn-io/form-js-viewer 1.0.0 → 1.3.0-alpha.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/LICENSE +22 -22
- package/README.md +164 -164
- package/dist/assets/form-js-base.css +985 -917
- package/dist/assets/form-js.css +69 -1
- package/dist/index.cjs +1982 -859
- package/dist/index.cjs.map +1 -1
- package/dist/index.es.js +1977 -860
- package/dist/index.es.js.map +1 -1
- package/dist/types/Form.d.ts +12 -26
- package/dist/types/core/FieldFactory.d.ts +19 -0
- package/dist/types/core/FormFieldRegistry.d.ts +0 -1
- package/dist/types/core/Importer.d.ts +56 -0
- package/dist/types/core/PathRegistry.d.ts +71 -0
- package/dist/types/core/index.d.ts +9 -5
- package/dist/types/features/expression-language/ConditionChecker.d.ts +3 -2
- package/dist/types/features/expression-language/variableExtractionHelpers.d.ts +1 -1
- package/dist/types/features/index.d.ts +2 -0
- package/dist/types/features/viewerCommands/ViewerCommands.d.ts +14 -0
- package/dist/types/features/viewerCommands/cmd/UpdateFieldValidationHandler.d.ts +11 -0
- package/dist/types/features/viewerCommands/index.d.ts +8 -0
- package/dist/types/index.d.ts +2 -2
- package/dist/types/render/components/form-fields/Checklist.d.ts +2 -6
- package/dist/types/render/components/form-fields/Default.d.ts +3 -3
- package/dist/types/render/components/form-fields/Group.d.ts +14 -0
- package/dist/types/render/components/form-fields/Radio.d.ts +2 -6
- package/dist/types/render/components/form-fields/Select.d.ts +2 -6
- package/dist/types/render/components/form-fields/Spacer.d.ts +14 -0
- package/dist/types/render/components/form-fields/Taglist.d.ts +2 -6
- package/dist/types/render/components/form-fields/parts/Grid.d.ts +1 -0
- package/dist/types/render/components/index.d.ts +4 -2
- package/dist/types/render/components/util/localisationUtil.d.ts +24 -0
- package/dist/types/render/components/util/valuesUtil.d.ts +6 -0
- package/dist/types/render/context/FormRenderContext.d.ts +3 -0
- package/dist/types/types.d.ts +35 -35
- package/dist/types/util/index.d.ts +2 -5
- package/package.json +5 -4
- package/dist/types/import/Importer.d.ts +0 -45
- package/dist/types/import/index.d.ts +0 -5
package/dist/index.es.js
CHANGED
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
import Ids from 'ids';
|
|
2
|
-
import { isString, isArray, isFunction, isNumber, bind, assign, isNil,
|
|
3
|
-
import { parseExpressions, parseUnaryTests, evaluate, unaryTest } from 'feelin';
|
|
4
|
-
import { evaluate as evaluate$1, parser, buildSimpleTree } from 'feelers';
|
|
5
|
-
import showdown from 'showdown';
|
|
2
|
+
import { isString, get, set, isObject, values, uniqueBy, isArray, isFunction, isNumber, bind, assign, isNil, groupBy, flatten, findIndex, isUndefined } from 'min-dash';
|
|
6
3
|
import Big from 'big.js';
|
|
4
|
+
import { parseExpression, parseUnaryTests, evaluate, unaryTest } from 'feelin';
|
|
5
|
+
import { evaluate as evaluate$1, parser, buildSimpleTree } from 'feelers';
|
|
7
6
|
import classNames from 'classnames';
|
|
8
7
|
import { jsx, jsxs, Fragment as Fragment$1 } from 'preact/jsx-runtime';
|
|
9
|
-
import { useContext, useMemo, useEffect, useState, useRef, useCallback } from 'preact/hooks';
|
|
8
|
+
import { useContext, useMemo, useEffect, useState, useRef, useCallback, useLayoutEffect } from 'preact/hooks';
|
|
10
9
|
import { createContext, createElement, Fragment, render } from 'preact';
|
|
11
10
|
import * as React from 'preact/compat';
|
|
12
11
|
import { createPortal } from 'preact/compat';
|
|
13
12
|
import flatpickr from 'flatpickr';
|
|
14
13
|
import Markup from 'preact-markup';
|
|
15
14
|
import { Injector } from 'didi';
|
|
15
|
+
import showdown from 'showdown';
|
|
16
16
|
|
|
17
|
-
const getFlavouredFeelVariableNames = (feelString, feelFlavour, options = {}) => {
|
|
17
|
+
const getFlavouredFeelVariableNames = (feelString, feelFlavour = 'expression', options = {}) => {
|
|
18
18
|
const {
|
|
19
19
|
depth = 0,
|
|
20
20
|
specialDepthAccessors = {}
|
|
21
21
|
} = options;
|
|
22
22
|
if (!['expression', 'unaryTest'].includes(feelFlavour)) return [];
|
|
23
|
-
const tree = feelFlavour === 'expression' ?
|
|
23
|
+
const tree = feelFlavour === 'expression' ? parseExpression(feelString) : parseUnaryTests(feelString);
|
|
24
24
|
const simpleExpressionTree = _buildSimpleFeelStructureTree(tree, feelString);
|
|
25
|
-
|
|
25
|
+
const variables = function _unfoldVariables(node) {
|
|
26
26
|
if (node.name === 'PathExpression') {
|
|
27
27
|
if (Object.keys(specialDepthAccessors).length === 0) {
|
|
28
28
|
return depth === 0 ? [_getVariableNameAtPathIndex(node, 0)] : [];
|
|
@@ -35,34 +35,38 @@ const getFlavouredFeelVariableNames = (feelString, feelFlavour, options = {}) =>
|
|
|
35
35
|
|
|
36
36
|
// for any other kind of node, traverse its children and flatten the result
|
|
37
37
|
if (node.children) {
|
|
38
|
-
|
|
38
|
+
const variables = node.children.reduce((acc, child) => {
|
|
39
39
|
return acc.concat(_unfoldVariables(child));
|
|
40
40
|
}, []);
|
|
41
|
+
|
|
42
|
+
// if we are within a filter context, we need to remove the item variable as it is used for iteration there
|
|
43
|
+
return node.name === 'FilterContext' ? variables.filter(name => name !== 'item') : variables;
|
|
41
44
|
}
|
|
42
45
|
return [];
|
|
43
46
|
}(simpleExpressionTree);
|
|
47
|
+
return [...new Set(variables)];
|
|
44
48
|
};
|
|
45
49
|
|
|
46
|
-
/**
|
|
47
|
-
* Get the variable name at the specified index in a given path expression.
|
|
48
|
-
*
|
|
49
|
-
* @param {Object} root - The root node of the path expression tree.
|
|
50
|
-
* @param {number} index - The index of the variable name to retrieve.
|
|
51
|
-
* @returns {string|null} The variable name at the specified index or null if index is out of bounds.
|
|
50
|
+
/**
|
|
51
|
+
* Get the variable name at the specified index in a given path expression.
|
|
52
|
+
*
|
|
53
|
+
* @param {Object} root - The root node of the path expression tree.
|
|
54
|
+
* @param {number} index - The index of the variable name to retrieve.
|
|
55
|
+
* @returns {string|null} The variable name at the specified index or null if index is out of bounds.
|
|
52
56
|
*/
|
|
53
57
|
const _getVariableNameAtPathIndex = (root, index) => {
|
|
54
58
|
const accessors = _deconstructPathExpression(root);
|
|
55
59
|
return accessors[index] || null;
|
|
56
60
|
};
|
|
57
61
|
|
|
58
|
-
/**
|
|
59
|
-
* Extracts the variables which are required of the external context for a given path expression.
|
|
60
|
-
* This is done by traversing the path expression tree and keeping track of the current depth relative to the external context.
|
|
61
|
-
*
|
|
62
|
-
* @param {Object} node - The root node of the path expression tree.
|
|
63
|
-
* @param {number} initialDepth - The depth at which the root node is located in the outer context.
|
|
64
|
-
* @param {Object} specialDepthAccessors - Definitions of special keywords which represent more complex accesses of the outer context.
|
|
65
|
-
* @returns {Set} - A set containing the extracted variable names.
|
|
62
|
+
/**
|
|
63
|
+
* Extracts the variables which are required of the external context for a given path expression.
|
|
64
|
+
* This is done by traversing the path expression tree and keeping track of the current depth relative to the external context.
|
|
65
|
+
*
|
|
66
|
+
* @param {Object} node - The root node of the path expression tree.
|
|
67
|
+
* @param {number} initialDepth - The depth at which the root node is located in the outer context.
|
|
68
|
+
* @param {Object} specialDepthAccessors - Definitions of special keywords which represent more complex accesses of the outer context.
|
|
69
|
+
* @returns {Set} - A set containing the extracted variable names.
|
|
66
70
|
*/
|
|
67
71
|
const _smartExtractVariableNames = (node, initialDepth, specialDepthAccessors) => {
|
|
68
72
|
// depth info represents the previous (initialised as null) and current depth of the current accessor in the path expression
|
|
@@ -108,11 +112,11 @@ const _smartExtractVariableNames = (node, initialDepth, specialDepthAccessors) =
|
|
|
108
112
|
return new Set(extractedVariables);
|
|
109
113
|
};
|
|
110
114
|
|
|
111
|
-
/**
|
|
112
|
-
* Deconstructs a path expression tree into an array of components.
|
|
113
|
-
*
|
|
114
|
-
* @param {Object} root - The root node of the path expression tree.
|
|
115
|
-
* @returns {Array<string>} An array of components in the path expression, in the correct order.
|
|
115
|
+
/**
|
|
116
|
+
* Deconstructs a path expression tree into an array of components.
|
|
117
|
+
*
|
|
118
|
+
* @param {Object} root - The root node of the path expression tree.
|
|
119
|
+
* @returns {Array<string>} An array of components in the path expression, in the correct order.
|
|
116
120
|
*/
|
|
117
121
|
const _deconstructPathExpression = root => {
|
|
118
122
|
let node = root;
|
|
@@ -131,13 +135,13 @@ const _deconstructPathExpression = root => {
|
|
|
131
135
|
return parts.reverse();
|
|
132
136
|
};
|
|
133
137
|
|
|
134
|
-
/**
|
|
135
|
-
* Builds a simplified feel structure tree from the given parse tree and feel string.
|
|
136
|
-
* The nodes follow this structure: `{ name: string, children: Array, variableName?: string }`
|
|
137
|
-
*
|
|
138
|
-
* @param {Object} parseTree - The parse tree generated by a parser.
|
|
139
|
-
* @param {string} feelString - The feel string used for parsing.
|
|
140
|
-
* @returns {Object} The simplified feel structure tree.
|
|
138
|
+
/**
|
|
139
|
+
* Builds a simplified feel structure tree from the given parse tree and feel string.
|
|
140
|
+
* The nodes follow this structure: `{ name: string, children: Array, variableName?: string }`
|
|
141
|
+
*
|
|
142
|
+
* @param {Object} parseTree - The parse tree generated by a parser.
|
|
143
|
+
* @param {string} feelString - The feel string used for parsing.
|
|
144
|
+
* @returns {Object} The simplified feel structure tree.
|
|
141
145
|
*/
|
|
142
146
|
const _buildSimpleFeelStructureTree = (parseTree, feelString) => {
|
|
143
147
|
const stack = [{
|
|
@@ -160,7 +164,45 @@ const _buildSimpleFeelStructureTree = (parseTree, feelString) => {
|
|
|
160
164
|
parent.children.push(result);
|
|
161
165
|
}
|
|
162
166
|
});
|
|
163
|
-
return stack[0].children[0];
|
|
167
|
+
return _extractFilterExpressions(stack[0].children[0]);
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Restructure the tree in such a way to bring filters (which create new contexts) to the root of the tree.
|
|
172
|
+
* This is done to simplify the extraction of variables and match the context hierarchy.
|
|
173
|
+
*/
|
|
174
|
+
const _extractFilterExpressions = tree => {
|
|
175
|
+
const flattenedExpressionTree = {
|
|
176
|
+
name: 'Root',
|
|
177
|
+
children: [tree]
|
|
178
|
+
};
|
|
179
|
+
const iterate = node => {
|
|
180
|
+
if (node.children) {
|
|
181
|
+
for (let x = 0; x < node.children.length; x++) {
|
|
182
|
+
if (node.children[x].name === 'FilterExpression') {
|
|
183
|
+
const filterTarget = node.children[x].children[0];
|
|
184
|
+
const filterExpression = node.children[x].children[2];
|
|
185
|
+
|
|
186
|
+
// bypass the filter expression
|
|
187
|
+
node.children[x] = filterTarget;
|
|
188
|
+
const taggedFilterExpression = {
|
|
189
|
+
name: 'FilterContext',
|
|
190
|
+
children: [filterExpression]
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
// append the filter expression to the root
|
|
194
|
+
flattenedExpressionTree.children.push(taggedFilterExpression);
|
|
195
|
+
|
|
196
|
+
// recursively iterate the expression
|
|
197
|
+
iterate(filterExpression);
|
|
198
|
+
} else {
|
|
199
|
+
iterate(node.children[x]);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
iterate(tree);
|
|
205
|
+
return flattenedExpressionTree;
|
|
164
206
|
};
|
|
165
207
|
|
|
166
208
|
class FeelExpressionLanguage {
|
|
@@ -168,25 +210,25 @@ class FeelExpressionLanguage {
|
|
|
168
210
|
this._eventBus = eventBus;
|
|
169
211
|
}
|
|
170
212
|
|
|
171
|
-
/**
|
|
172
|
-
* Determines if the given value is a FEEL expression.
|
|
173
|
-
*
|
|
174
|
-
* @param {any} value
|
|
175
|
-
* @returns {boolean}
|
|
176
|
-
*
|
|
213
|
+
/**
|
|
214
|
+
* Determines if the given value is a FEEL expression.
|
|
215
|
+
*
|
|
216
|
+
* @param {any} value
|
|
217
|
+
* @returns {boolean}
|
|
218
|
+
*
|
|
177
219
|
*/
|
|
178
220
|
isExpression(value) {
|
|
179
221
|
return isString(value) && value.startsWith('=');
|
|
180
222
|
}
|
|
181
223
|
|
|
182
|
-
/**
|
|
183
|
-
* Retrieve variable names from a given FEEL expression.
|
|
184
|
-
*
|
|
185
|
-
* @param {string} expression
|
|
186
|
-
* @param {object} [options]
|
|
187
|
-
* @param {string} [options.type]
|
|
188
|
-
*
|
|
189
|
-
* @returns {string[]}
|
|
224
|
+
/**
|
|
225
|
+
* Retrieve variable names from a given FEEL expression.
|
|
226
|
+
*
|
|
227
|
+
* @param {string} expression
|
|
228
|
+
* @param {object} [options]
|
|
229
|
+
* @param {string} [options.type]
|
|
230
|
+
*
|
|
231
|
+
* @returns {string[]}
|
|
190
232
|
*/
|
|
191
233
|
getVariableNames(expression, options = {}) {
|
|
192
234
|
const {
|
|
@@ -201,13 +243,13 @@ class FeelExpressionLanguage {
|
|
|
201
243
|
return getFlavouredFeelVariableNames(expression, type);
|
|
202
244
|
}
|
|
203
245
|
|
|
204
|
-
/**
|
|
205
|
-
* Evaluate an expression.
|
|
206
|
-
*
|
|
207
|
-
* @param {string} expression
|
|
208
|
-
* @param {import('../../types').Data} [data]
|
|
209
|
-
*
|
|
210
|
-
* @returns {any}
|
|
246
|
+
/**
|
|
247
|
+
* Evaluate an expression.
|
|
248
|
+
*
|
|
249
|
+
* @param {string} expression
|
|
250
|
+
* @param {import('../../types').Data} [data]
|
|
251
|
+
*
|
|
252
|
+
* @returns {any}
|
|
211
253
|
*/
|
|
212
254
|
evaluate(expression, data = {}) {
|
|
213
255
|
if (!expression) {
|
|
@@ -232,23 +274,23 @@ FeelExpressionLanguage.$inject = ['eventBus'];
|
|
|
232
274
|
class FeelersTemplating {
|
|
233
275
|
constructor() {}
|
|
234
276
|
|
|
235
|
-
/**
|
|
236
|
-
* Determines if the given value is a feelers template.
|
|
237
|
-
*
|
|
238
|
-
* @param {any} value
|
|
239
|
-
* @returns {boolean}
|
|
240
|
-
*
|
|
277
|
+
/**
|
|
278
|
+
* Determines if the given value is a feelers template.
|
|
279
|
+
*
|
|
280
|
+
* @param {any} value
|
|
281
|
+
* @returns {boolean}
|
|
282
|
+
*
|
|
241
283
|
*/
|
|
242
284
|
isTemplate(value) {
|
|
243
285
|
return isString(value) && (value.startsWith('=') || /{{.*?}}/.test(value));
|
|
244
286
|
}
|
|
245
287
|
|
|
246
|
-
/**
|
|
247
|
-
* Retrieve variable names from a given feelers template.
|
|
248
|
-
*
|
|
249
|
-
* @param {string} template
|
|
250
|
-
*
|
|
251
|
-
* @returns {string[]}
|
|
288
|
+
/**
|
|
289
|
+
* Retrieve variable names from a given feelers template.
|
|
290
|
+
*
|
|
291
|
+
* @param {string} template
|
|
292
|
+
*
|
|
293
|
+
* @returns {string[]}
|
|
252
294
|
*/
|
|
253
295
|
getVariableNames(template) {
|
|
254
296
|
if (!this.isTemplate(template)) {
|
|
@@ -274,17 +316,17 @@ class FeelersTemplating {
|
|
|
274
316
|
}, []);
|
|
275
317
|
}
|
|
276
318
|
|
|
277
|
-
/**
|
|
278
|
-
* Evaluate a template.
|
|
279
|
-
*
|
|
280
|
-
* @param {string} template
|
|
281
|
-
* @param {Object<string, any>} context
|
|
282
|
-
* @param {Object} options
|
|
283
|
-
* @param {boolean} [options.debug = false]
|
|
284
|
-
* @param {boolean} [options.strict = false]
|
|
285
|
-
* @param {Function} [options.buildDebugString]
|
|
286
|
-
*
|
|
287
|
-
* @returns
|
|
319
|
+
/**
|
|
320
|
+
* Evaluate a template.
|
|
321
|
+
*
|
|
322
|
+
* @param {string} template
|
|
323
|
+
* @param {Object<string, any>} context
|
|
324
|
+
* @param {Object} options
|
|
325
|
+
* @param {boolean} [options.debug = false]
|
|
326
|
+
* @param {boolean} [options.strict = false]
|
|
327
|
+
* @param {Function} [options.buildDebugString]
|
|
328
|
+
*
|
|
329
|
+
* @returns
|
|
288
330
|
*/
|
|
289
331
|
evaluate(template, context = {}, options = {}) {
|
|
290
332
|
const {
|
|
@@ -299,22 +341,22 @@ class FeelersTemplating {
|
|
|
299
341
|
});
|
|
300
342
|
}
|
|
301
343
|
|
|
302
|
-
/**
|
|
303
|
-
* @typedef {Object} ExpressionWithDepth
|
|
304
|
-
* @property {number} depth - The depth of the expression in the syntax tree.
|
|
305
|
-
* @property {string} expression - The extracted expression
|
|
344
|
+
/**
|
|
345
|
+
* @typedef {Object} ExpressionWithDepth
|
|
346
|
+
* @property {number} depth - The depth of the expression in the syntax tree.
|
|
347
|
+
* @property {string} expression - The extracted expression
|
|
306
348
|
*/
|
|
307
349
|
|
|
308
|
-
/**
|
|
309
|
-
* Extracts all feel expressions in the template along with their depth in the syntax tree.
|
|
310
|
-
* The depth is incremented for child expressions of loops to account for context drilling.
|
|
311
|
-
|
|
312
|
-
* @param {string} template - A feelers template string.
|
|
313
|
-
* @returns {Array<ExpressionWithDepth>} An array of objects, each containing the depth and the extracted expression.
|
|
314
|
-
*
|
|
315
|
-
* @example
|
|
316
|
-
* const template = "Hello {{user}}, you have:{{#loop items}}\n- {{amount}} {{name}}{{/loop}}.";
|
|
317
|
-
* const extractedExpressions = _extractExpressionsWithDepth(template);
|
|
350
|
+
/**
|
|
351
|
+
* Extracts all feel expressions in the template along with their depth in the syntax tree.
|
|
352
|
+
* The depth is incremented for child expressions of loops to account for context drilling.
|
|
353
|
+
* @name extractExpressionsWithDepth
|
|
354
|
+
* @param {string} template - A feelers template string.
|
|
355
|
+
* @returns {Array<ExpressionWithDepth>} An array of objects, each containing the depth and the extracted expression.
|
|
356
|
+
*
|
|
357
|
+
* @example
|
|
358
|
+
* const template = "Hello {{user}}, you have:{{#loop items}}\n- {{amount}} {{name}}{{/loop}}.";
|
|
359
|
+
* const extractedExpressions = _extractExpressionsWithDepth(template);
|
|
318
360
|
*/
|
|
319
361
|
_extractExpressionsWithDepth(template) {
|
|
320
362
|
// build simplified feelers syntax tree
|
|
@@ -345,47 +387,271 @@ class FeelersTemplating {
|
|
|
345
387
|
}
|
|
346
388
|
FeelersTemplating.$inject = [];
|
|
347
389
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
390
|
+
// config ///////////////////
|
|
391
|
+
|
|
392
|
+
const MINUTES_IN_DAY = 60 * 24;
|
|
393
|
+
const DATETIME_SUBTYPES = {
|
|
394
|
+
DATE: 'date',
|
|
395
|
+
TIME: 'time',
|
|
396
|
+
DATETIME: 'datetime'
|
|
397
|
+
};
|
|
398
|
+
const TIME_SERIALISING_FORMATS = {
|
|
399
|
+
UTC_OFFSET: 'utc_offset',
|
|
400
|
+
UTC_NORMALIZED: 'utc_normalized',
|
|
401
|
+
NO_TIMEZONE: 'no_timezone'
|
|
402
|
+
};
|
|
403
|
+
const DATETIME_SUBTYPES_LABELS = {
|
|
404
|
+
[DATETIME_SUBTYPES.DATE]: 'Date',
|
|
405
|
+
[DATETIME_SUBTYPES.TIME]: 'Time',
|
|
406
|
+
[DATETIME_SUBTYPES.DATETIME]: 'Date & Time'
|
|
407
|
+
};
|
|
408
|
+
const TIME_SERIALISINGFORMAT_LABELS = {
|
|
409
|
+
[TIME_SERIALISING_FORMATS.UTC_OFFSET]: 'UTC offset',
|
|
410
|
+
[TIME_SERIALISING_FORMATS.UTC_NORMALIZED]: 'UTC normalized',
|
|
411
|
+
[TIME_SERIALISING_FORMATS.NO_TIMEZONE]: 'No timezone'
|
|
412
|
+
};
|
|
413
|
+
const DATETIME_SUBTYPE_PATH = ['subtype'];
|
|
414
|
+
const DATE_LABEL_PATH = ['dateLabel'];
|
|
415
|
+
const DATE_DISALLOW_PAST_PATH = ['disallowPassedDates'];
|
|
416
|
+
const TIME_LABEL_PATH = ['timeLabel'];
|
|
417
|
+
const TIME_USE24H_PATH = ['use24h'];
|
|
418
|
+
const TIME_INTERVAL_PATH = ['timeInterval'];
|
|
419
|
+
const TIME_SERIALISING_FORMAT_PATH = ['timeSerializingFormat'];
|
|
420
|
+
|
|
421
|
+
// config ///////////////////
|
|
422
|
+
|
|
423
|
+
const VALUES_SOURCES = {
|
|
424
|
+
STATIC: 'static',
|
|
425
|
+
INPUT: 'input',
|
|
426
|
+
EXPRESSION: 'expression'
|
|
427
|
+
};
|
|
428
|
+
const VALUES_SOURCE_DEFAULT = VALUES_SOURCES.STATIC;
|
|
429
|
+
const VALUES_SOURCES_LABELS = {
|
|
430
|
+
[VALUES_SOURCES.STATIC]: 'Static',
|
|
431
|
+
[VALUES_SOURCES.INPUT]: 'Input data',
|
|
432
|
+
[VALUES_SOURCES.EXPRESSION]: 'Expression'
|
|
433
|
+
};
|
|
434
|
+
const VALUES_SOURCES_PATHS = {
|
|
435
|
+
[VALUES_SOURCES.STATIC]: ['values'],
|
|
436
|
+
[VALUES_SOURCES.INPUT]: ['valuesKey'],
|
|
437
|
+
[VALUES_SOURCES.EXPRESSION]: ['valuesExpression']
|
|
438
|
+
};
|
|
439
|
+
const VALUES_SOURCES_DEFAULTS = {
|
|
440
|
+
[VALUES_SOURCES.STATIC]: [{
|
|
441
|
+
label: 'Value',
|
|
442
|
+
value: 'value'
|
|
443
|
+
}],
|
|
444
|
+
[VALUES_SOURCES.INPUT]: '',
|
|
445
|
+
[VALUES_SOURCES.EXPRESSION]: '='
|
|
446
|
+
};
|
|
447
|
+
|
|
448
|
+
// helpers ///////////////////
|
|
449
|
+
|
|
450
|
+
function getValuesSource(field) {
|
|
451
|
+
for (const source of Object.values(VALUES_SOURCES)) {
|
|
452
|
+
if (get(field, VALUES_SOURCES_PATHS[source]) !== undefined) {
|
|
453
|
+
return source;
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
return VALUES_SOURCE_DEFAULT;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
function createInjector(bootstrapModules) {
|
|
460
|
+
const injector = new Injector(bootstrapModules);
|
|
461
|
+
injector.init();
|
|
462
|
+
return injector;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* @param {string?} prefix
|
|
467
|
+
*
|
|
468
|
+
* @returns Element
|
|
469
|
+
*/
|
|
470
|
+
function createFormContainer(prefix = 'fjs') {
|
|
471
|
+
const container = document.createElement('div');
|
|
472
|
+
container.classList.add(`${prefix}-container`);
|
|
473
|
+
return container;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
const EXPRESSION_PROPERTIES = ['alt', 'appearance.prefixAdorner', 'appearance.suffixAdorner', 'conditional.hide', 'description', 'label', 'source', 'readonly', 'text', 'validate.min', 'validate.max', 'validate.minLength', 'validate.maxLength', 'valuesExpression'];
|
|
477
|
+
const TEMPLATE_PROPERTIES = ['alt', 'appearance.prefixAdorner', 'appearance.suffixAdorner', 'description', 'label', 'source', 'text'];
|
|
478
|
+
function isRequired(field) {
|
|
479
|
+
return field.required;
|
|
480
|
+
}
|
|
481
|
+
function pathParse(path) {
|
|
482
|
+
if (!path) {
|
|
483
|
+
return [];
|
|
484
|
+
}
|
|
485
|
+
return path.split('.').map(key => {
|
|
486
|
+
return isNaN(parseInt(key)) ? key : parseInt(key);
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
function pathsEqual(a, b) {
|
|
490
|
+
return a && b && a.length === b.length && a.every((value, index) => value === b[index]);
|
|
491
|
+
}
|
|
492
|
+
const indices = {};
|
|
493
|
+
function generateIndexForType(type) {
|
|
494
|
+
if (type in indices) {
|
|
495
|
+
indices[type]++;
|
|
496
|
+
} else {
|
|
497
|
+
indices[type] = 1;
|
|
498
|
+
}
|
|
499
|
+
return indices[type];
|
|
500
|
+
}
|
|
501
|
+
function generateIdForType(type) {
|
|
502
|
+
return `${type}${generateIndexForType(type)}`;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
/**
|
|
506
|
+
* @template T
|
|
507
|
+
* @param {T} data
|
|
508
|
+
* @param {(this: any, key: string, value: any) => any} [replacer]
|
|
509
|
+
* @return {T}
|
|
510
|
+
*/
|
|
511
|
+
function clone(data, replacer) {
|
|
512
|
+
return JSON.parse(JSON.stringify(data, replacer));
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
/**
|
|
516
|
+
* Parse the schema for input variables a form might make use of
|
|
517
|
+
*
|
|
518
|
+
* @param {any} schema
|
|
519
|
+
*
|
|
520
|
+
* @return {string[]}
|
|
521
|
+
*/
|
|
522
|
+
function getSchemaVariables(schema, options = {}) {
|
|
523
|
+
const {
|
|
524
|
+
expressionLanguage = new FeelExpressionLanguage(null),
|
|
525
|
+
templating = new FeelersTemplating(),
|
|
526
|
+
inputs = true,
|
|
527
|
+
outputs = true
|
|
528
|
+
} = options;
|
|
529
|
+
if (!schema.components) {
|
|
530
|
+
return [];
|
|
531
|
+
}
|
|
532
|
+
const getAllComponents = node => {
|
|
533
|
+
const components = [];
|
|
534
|
+
if (node.components) {
|
|
535
|
+
node.components.forEach(component => {
|
|
536
|
+
components.push(component);
|
|
537
|
+
components.push(...getAllComponents(component));
|
|
538
|
+
});
|
|
539
|
+
}
|
|
540
|
+
return components;
|
|
541
|
+
};
|
|
542
|
+
const variables = getAllComponents(schema).reduce((variables, component) => {
|
|
543
|
+
const {
|
|
544
|
+
valuesKey
|
|
545
|
+
} = component;
|
|
546
|
+
|
|
547
|
+
// collect input-only variables
|
|
548
|
+
if (inputs) {
|
|
549
|
+
if (valuesKey) {
|
|
550
|
+
variables = [...variables, valuesKey];
|
|
551
|
+
}
|
|
552
|
+
EXPRESSION_PROPERTIES.forEach(prop => {
|
|
553
|
+
const property = get(component, prop.split('.'));
|
|
554
|
+
if (property && expressionLanguage.isExpression(property)) {
|
|
555
|
+
const expressionVariables = expressionLanguage.getVariableNames(property, {
|
|
556
|
+
type: 'expression'
|
|
557
|
+
});
|
|
558
|
+
variables = [...variables, ...expressionVariables];
|
|
559
|
+
}
|
|
560
|
+
});
|
|
561
|
+
TEMPLATE_PROPERTIES.forEach(prop => {
|
|
562
|
+
const property = get(component, prop.split('.'));
|
|
563
|
+
if (property && !expressionLanguage.isExpression(property) && templating.isTemplate(property)) {
|
|
564
|
+
const templateVariables = templating.getVariableNames(property);
|
|
565
|
+
variables = [...variables, ...templateVariables];
|
|
566
|
+
}
|
|
567
|
+
});
|
|
568
|
+
}
|
|
569
|
+
return variables.filter(variable => variable !== undefined || variable !== null);
|
|
570
|
+
}, []);
|
|
571
|
+
const getBindingVariables = node => {
|
|
572
|
+
const bindingVariable = [];
|
|
573
|
+
|
|
574
|
+
// c.f. https://github.com/bpmn-io/form-js/issues/778 @Skaiir to remove?
|
|
575
|
+
if (node.type === 'button') {
|
|
576
|
+
return [];
|
|
577
|
+
} else if (node.key) {
|
|
578
|
+
return [node.key.split('.')[0]];
|
|
579
|
+
} else if (node.path) {
|
|
580
|
+
return [node.path.split('.')[0]];
|
|
581
|
+
} else if (node.components) {
|
|
582
|
+
node.components.forEach(component => {
|
|
583
|
+
bindingVariable.push(...getBindingVariables(component));
|
|
584
|
+
});
|
|
585
|
+
}
|
|
586
|
+
return bindingVariable;
|
|
587
|
+
};
|
|
588
|
+
|
|
589
|
+
// collect binding variables
|
|
590
|
+
if (inputs || outputs) {
|
|
591
|
+
variables.push(...getBindingVariables(schema));
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
// remove duplicates
|
|
595
|
+
return Array.from(new Set(variables));
|
|
596
|
+
}
|
|
597
|
+
function runRecursively(formField, fn) {
|
|
598
|
+
const components = formField.components || [];
|
|
599
|
+
components.forEach((component, index) => {
|
|
600
|
+
runRecursively(component, fn);
|
|
601
|
+
});
|
|
602
|
+
fn(formField);
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
/**
|
|
606
|
+
* @typedef {object} Condition
|
|
607
|
+
* @property {string} [hide]
|
|
351
608
|
*/
|
|
352
609
|
|
|
353
610
|
class ConditionChecker {
|
|
354
|
-
constructor(formFieldRegistry, eventBus) {
|
|
611
|
+
constructor(formFieldRegistry, pathRegistry, eventBus) {
|
|
355
612
|
this._formFieldRegistry = formFieldRegistry;
|
|
613
|
+
this._pathRegistry = pathRegistry;
|
|
356
614
|
this._eventBus = eventBus;
|
|
357
615
|
}
|
|
358
616
|
|
|
359
|
-
/**
|
|
360
|
-
* For given data, remove properties based on condition.
|
|
361
|
-
*
|
|
362
|
-
* @param {Object<string, any>} properties
|
|
363
|
-
* @param {Object<string, any>} data
|
|
617
|
+
/**
|
|
618
|
+
* For given data, remove properties based on condition.
|
|
619
|
+
*
|
|
620
|
+
* @param {Object<string, any>} properties
|
|
621
|
+
* @param {Object<string, any>} data
|
|
364
622
|
*/
|
|
365
623
|
applyConditions(properties, data = {}) {
|
|
366
|
-
const
|
|
367
|
-
const
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
for (const {
|
|
371
|
-
key,
|
|
372
|
-
condition
|
|
373
|
-
} of conditions) {
|
|
374
|
-
const shouldRemove = this._checkHideCondition(condition, data);
|
|
375
|
-
if (shouldRemove) {
|
|
376
|
-
delete newProperties[key];
|
|
377
|
-
}
|
|
624
|
+
const newProperties = clone(properties);
|
|
625
|
+
const form = this._formFieldRegistry.getAll().find(field => field.type === 'default');
|
|
626
|
+
if (!form) {
|
|
627
|
+
throw new Error('form field registry has no form');
|
|
378
628
|
}
|
|
629
|
+
this._pathRegistry.executeRecursivelyOnFields(form, ({
|
|
630
|
+
field,
|
|
631
|
+
isClosed,
|
|
632
|
+
context
|
|
633
|
+
}) => {
|
|
634
|
+
const {
|
|
635
|
+
conditional: condition
|
|
636
|
+
} = field;
|
|
637
|
+
context.isHidden = context.isHidden || condition && this._checkHideCondition(condition, data);
|
|
638
|
+
|
|
639
|
+
// only clear the leaf nodes, as groups may both point to the same path
|
|
640
|
+
if (context.isHidden && isClosed) {
|
|
641
|
+
const valuePath = this._pathRegistry.getValuePath(field);
|
|
642
|
+
this._clearObjectValueRecursively(valuePath, newProperties);
|
|
643
|
+
}
|
|
644
|
+
});
|
|
379
645
|
return newProperties;
|
|
380
646
|
}
|
|
381
647
|
|
|
382
|
-
/**
|
|
383
|
-
* Check if given condition is met. Returns null for invalid/missing conditions.
|
|
384
|
-
*
|
|
385
|
-
* @param {string} condition
|
|
386
|
-
* @param {import('../../types').Data} [data]
|
|
387
|
-
*
|
|
388
|
-
* @returns {boolean|null}
|
|
648
|
+
/**
|
|
649
|
+
* Check if given condition is met. Returns null for invalid/missing conditions.
|
|
650
|
+
*
|
|
651
|
+
* @param {string} condition
|
|
652
|
+
* @param {import('../../types').Data} [data]
|
|
653
|
+
*
|
|
654
|
+
* @returns {boolean|null}
|
|
389
655
|
*/
|
|
390
656
|
check(condition, data = {}) {
|
|
391
657
|
if (!condition) {
|
|
@@ -406,12 +672,12 @@ class ConditionChecker {
|
|
|
406
672
|
}
|
|
407
673
|
}
|
|
408
674
|
|
|
409
|
-
/**
|
|
410
|
-
* Check if hide condition is met.
|
|
411
|
-
*
|
|
412
|
-
* @param {Condition} condition
|
|
413
|
-
* @param {Object<string, any>} data
|
|
414
|
-
* @returns {boolean}
|
|
675
|
+
/**
|
|
676
|
+
* Check if hide condition is met.
|
|
677
|
+
*
|
|
678
|
+
* @param {Condition} condition
|
|
679
|
+
* @param {Object<string, any>} data
|
|
680
|
+
* @returns {boolean}
|
|
415
681
|
*/
|
|
416
682
|
_checkHideCondition(condition, data) {
|
|
417
683
|
if (!condition.hide) {
|
|
@@ -420,24 +686,18 @@ class ConditionChecker {
|
|
|
420
686
|
const result = this.check(condition.hide, data);
|
|
421
687
|
return result === true;
|
|
422
688
|
}
|
|
423
|
-
|
|
424
|
-
const
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
key,
|
|
433
|
-
condition
|
|
434
|
-
}];
|
|
435
|
-
}
|
|
436
|
-
return conditions;
|
|
437
|
-
}, []);
|
|
689
|
+
_clearObjectValueRecursively(valuePath, obj) {
|
|
690
|
+
const workingValuePath = [...valuePath];
|
|
691
|
+
let recurse = false;
|
|
692
|
+
do {
|
|
693
|
+
set(obj, workingValuePath, undefined);
|
|
694
|
+
workingValuePath.pop();
|
|
695
|
+
const parentObject = get(obj, workingValuePath);
|
|
696
|
+
recurse = isObject(parentObject) && !values(parentObject).length && !!workingValuePath.length;
|
|
697
|
+
} while (recurse);
|
|
438
698
|
}
|
|
439
699
|
}
|
|
440
|
-
ConditionChecker.$inject = ['formFieldRegistry', 'eventBus'];
|
|
700
|
+
ConditionChecker.$inject = ['formFieldRegistry', 'pathRegistry', 'eventBus'];
|
|
441
701
|
|
|
442
702
|
var ExpressionLanguageModule = {
|
|
443
703
|
__init__: ['expressionLanguage', 'templating', 'conditionChecker'],
|
|
@@ -453,12 +713,12 @@ class MarkdownRenderer {
|
|
|
453
713
|
this._converter = new showdown.Converter();
|
|
454
714
|
}
|
|
455
715
|
|
|
456
|
-
/**
|
|
457
|
-
* Render markdown to HTML.
|
|
458
|
-
*
|
|
459
|
-
* @param {string} markdown - The markdown to render
|
|
460
|
-
*
|
|
461
|
-
* @returns {string} HTML
|
|
716
|
+
/**
|
|
717
|
+
* Render markdown to HTML.
|
|
718
|
+
*
|
|
719
|
+
* @param {string} markdown - The markdown to render
|
|
720
|
+
*
|
|
721
|
+
* @returns {string} HTML
|
|
462
722
|
*/
|
|
463
723
|
render(markdown) {
|
|
464
724
|
return this._converter.makeHtml(markdown);
|
|
@@ -471,6 +731,538 @@ var MarkdownModule = {
|
|
|
471
731
|
markdownRenderer: ['type', MarkdownRenderer]
|
|
472
732
|
};
|
|
473
733
|
|
|
734
|
+
/**
|
|
735
|
+
* @typedef {import('didi').Injector} Injector
|
|
736
|
+
*
|
|
737
|
+
* @typedef {import('../core/Types').ElementLike} ElementLike
|
|
738
|
+
*
|
|
739
|
+
* @typedef {import('../core/EventBus').default} EventBus
|
|
740
|
+
* @typedef {import('./CommandHandler').default} CommandHandler
|
|
741
|
+
*
|
|
742
|
+
* @typedef { any } CommandContext
|
|
743
|
+
* @typedef { {
|
|
744
|
+
* new (...args: any[]) : CommandHandler
|
|
745
|
+
* } } CommandHandlerConstructor
|
|
746
|
+
* @typedef { {
|
|
747
|
+
* [key: string]: CommandHandler;
|
|
748
|
+
* } } CommandHandlerMap
|
|
749
|
+
* @typedef { {
|
|
750
|
+
* command: string;
|
|
751
|
+
* context: any;
|
|
752
|
+
* id?: any;
|
|
753
|
+
* } } CommandStackAction
|
|
754
|
+
* @typedef { {
|
|
755
|
+
* actions: CommandStackAction[];
|
|
756
|
+
* dirty: ElementLike[];
|
|
757
|
+
* trigger: 'execute' | 'undo' | 'redo' | 'clear' | null;
|
|
758
|
+
* atomic?: boolean;
|
|
759
|
+
* } } CurrentExecution
|
|
760
|
+
*/
|
|
761
|
+
|
|
762
|
+
/**
|
|
763
|
+
* A service that offers un- and redoable execution of commands.
|
|
764
|
+
*
|
|
765
|
+
* The command stack is responsible for executing modeling actions
|
|
766
|
+
* in a un- and redoable manner. To do this it delegates the actual
|
|
767
|
+
* command execution to {@link CommandHandler}s.
|
|
768
|
+
*
|
|
769
|
+
* Command handlers provide {@link CommandHandler#execute(ctx)} and
|
|
770
|
+
* {@link CommandHandler#revert(ctx)} methods to un- and redo a command
|
|
771
|
+
* identified by a command context.
|
|
772
|
+
*
|
|
773
|
+
*
|
|
774
|
+
* ## Life-Cycle events
|
|
775
|
+
*
|
|
776
|
+
* In the process the command stack fires a number of life-cycle events
|
|
777
|
+
* that other components to participate in the command execution.
|
|
778
|
+
*
|
|
779
|
+
* * preExecute
|
|
780
|
+
* * preExecuted
|
|
781
|
+
* * execute
|
|
782
|
+
* * executed
|
|
783
|
+
* * postExecute
|
|
784
|
+
* * postExecuted
|
|
785
|
+
* * revert
|
|
786
|
+
* * reverted
|
|
787
|
+
*
|
|
788
|
+
* A special event is used for validating, whether a command can be
|
|
789
|
+
* performed prior to its execution.
|
|
790
|
+
*
|
|
791
|
+
* * canExecute
|
|
792
|
+
*
|
|
793
|
+
* Each of the events is fired as `commandStack.{eventName}` and
|
|
794
|
+
* `commandStack.{commandName}.{eventName}`, respectively. This gives
|
|
795
|
+
* components fine grained control on where to hook into.
|
|
796
|
+
*
|
|
797
|
+
* The event object fired transports `command`, the name of the
|
|
798
|
+
* command and `context`, the command context.
|
|
799
|
+
*
|
|
800
|
+
*
|
|
801
|
+
* ## Creating Command Handlers
|
|
802
|
+
*
|
|
803
|
+
* Command handlers should provide the {@link CommandHandler#execute(ctx)}
|
|
804
|
+
* and {@link CommandHandler#revert(ctx)} methods to implement
|
|
805
|
+
* redoing and undoing of a command.
|
|
806
|
+
*
|
|
807
|
+
* A command handler _must_ ensure undo is performed properly in order
|
|
808
|
+
* not to break the undo chain. It must also return the shapes that
|
|
809
|
+
* got changed during the `execute` and `revert` operations.
|
|
810
|
+
*
|
|
811
|
+
* Command handlers may execute other modeling operations (and thus
|
|
812
|
+
* commands) in their `preExecute(d)` and `postExecute(d)` phases. The command
|
|
813
|
+
* stack will properly group all commands together into a logical unit
|
|
814
|
+
* that may be re- and undone atomically.
|
|
815
|
+
*
|
|
816
|
+
* Command handlers must not execute other commands from within their
|
|
817
|
+
* core implementation (`execute`, `revert`).
|
|
818
|
+
*
|
|
819
|
+
*
|
|
820
|
+
* ## Change Tracking
|
|
821
|
+
*
|
|
822
|
+
* During the execution of the CommandStack it will keep track of all
|
|
823
|
+
* elements that have been touched during the command's execution.
|
|
824
|
+
*
|
|
825
|
+
* At the end of the CommandStack execution it will notify interested
|
|
826
|
+
* components via an 'elements.changed' event with all the dirty
|
|
827
|
+
* elements.
|
|
828
|
+
*
|
|
829
|
+
* The event can be picked up by components that are interested in the fact
|
|
830
|
+
* that elements have been changed. One use case for this is updating
|
|
831
|
+
* their graphical representation after moving / resizing or deletion.
|
|
832
|
+
*
|
|
833
|
+
* @see CommandHandler
|
|
834
|
+
*
|
|
835
|
+
* @param {EventBus} eventBus
|
|
836
|
+
* @param {Injector} injector
|
|
837
|
+
*/
|
|
838
|
+
function CommandStack(eventBus, injector) {
|
|
839
|
+
/**
|
|
840
|
+
* A map of all registered command handlers.
|
|
841
|
+
*
|
|
842
|
+
* @type {CommandHandlerMap}
|
|
843
|
+
*/
|
|
844
|
+
this._handlerMap = {};
|
|
845
|
+
|
|
846
|
+
/**
|
|
847
|
+
* A stack containing all re/undoable actions on the diagram
|
|
848
|
+
*
|
|
849
|
+
* @type {CommandStackAction[]}
|
|
850
|
+
*/
|
|
851
|
+
this._stack = [];
|
|
852
|
+
|
|
853
|
+
/**
|
|
854
|
+
* The current index on the stack
|
|
855
|
+
*
|
|
856
|
+
* @type {number}
|
|
857
|
+
*/
|
|
858
|
+
this._stackIdx = -1;
|
|
859
|
+
|
|
860
|
+
/**
|
|
861
|
+
* Current active commandStack execution
|
|
862
|
+
*
|
|
863
|
+
* @type {CurrentExecution}
|
|
864
|
+
*/
|
|
865
|
+
this._currentExecution = {
|
|
866
|
+
actions: [],
|
|
867
|
+
dirty: [],
|
|
868
|
+
trigger: null
|
|
869
|
+
};
|
|
870
|
+
|
|
871
|
+
/**
|
|
872
|
+
* @type {Injector}
|
|
873
|
+
*/
|
|
874
|
+
this._injector = injector;
|
|
875
|
+
|
|
876
|
+
/**
|
|
877
|
+
* @type EventBus
|
|
878
|
+
*/
|
|
879
|
+
this._eventBus = eventBus;
|
|
880
|
+
|
|
881
|
+
/**
|
|
882
|
+
* @type { number }
|
|
883
|
+
*/
|
|
884
|
+
this._uid = 1;
|
|
885
|
+
eventBus.on(['diagram.destroy', 'diagram.clear'], function () {
|
|
886
|
+
this.clear(false);
|
|
887
|
+
}, this);
|
|
888
|
+
}
|
|
889
|
+
CommandStack.$inject = ['eventBus', 'injector'];
|
|
890
|
+
|
|
891
|
+
/**
|
|
892
|
+
* Execute a command.
|
|
893
|
+
*
|
|
894
|
+
* @param {string} command The command to execute.
|
|
895
|
+
* @param {CommandContext} context The context with which to execute the command.
|
|
896
|
+
*/
|
|
897
|
+
CommandStack.prototype.execute = function (command, context) {
|
|
898
|
+
if (!command) {
|
|
899
|
+
throw new Error('command required');
|
|
900
|
+
}
|
|
901
|
+
this._currentExecution.trigger = 'execute';
|
|
902
|
+
const action = {
|
|
903
|
+
command: command,
|
|
904
|
+
context: context
|
|
905
|
+
};
|
|
906
|
+
this._pushAction(action);
|
|
907
|
+
this._internalExecute(action);
|
|
908
|
+
this._popAction();
|
|
909
|
+
};
|
|
910
|
+
|
|
911
|
+
/**
|
|
912
|
+
* Check whether a command can be executed.
|
|
913
|
+
*
|
|
914
|
+
* Implementors may hook into the mechanism on two ways:
|
|
915
|
+
*
|
|
916
|
+
* * in event listeners:
|
|
917
|
+
*
|
|
918
|
+
* Users may prevent the execution via an event listener.
|
|
919
|
+
* It must prevent the default action for `commandStack.(<command>.)canExecute` events.
|
|
920
|
+
*
|
|
921
|
+
* * in command handlers:
|
|
922
|
+
*
|
|
923
|
+
* If the method {@link CommandHandler#canExecute} is implemented in a handler
|
|
924
|
+
* it will be called to figure out whether the execution is allowed.
|
|
925
|
+
*
|
|
926
|
+
* @param {string} command The command to execute.
|
|
927
|
+
* @param {CommandContext} context The context with which to execute the command.
|
|
928
|
+
*
|
|
929
|
+
* @return {boolean} Whether the command can be executed with the given context.
|
|
930
|
+
*/
|
|
931
|
+
CommandStack.prototype.canExecute = function (command, context) {
|
|
932
|
+
const action = {
|
|
933
|
+
command: command,
|
|
934
|
+
context: context
|
|
935
|
+
};
|
|
936
|
+
const handler = this._getHandler(command);
|
|
937
|
+
let result = this._fire(command, 'canExecute', action);
|
|
938
|
+
|
|
939
|
+
// handler#canExecute will only be called if no listener
|
|
940
|
+
// decided on a result already
|
|
941
|
+
if (result === undefined) {
|
|
942
|
+
if (!handler) {
|
|
943
|
+
return false;
|
|
944
|
+
}
|
|
945
|
+
if (handler.canExecute) {
|
|
946
|
+
result = handler.canExecute(context);
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
return result;
|
|
950
|
+
};
|
|
951
|
+
|
|
952
|
+
/**
|
|
953
|
+
* Clear the command stack, erasing all undo / redo history.
|
|
954
|
+
*
|
|
955
|
+
* @param {boolean} [emit=true] Whether to fire an event. Defaults to `true`.
|
|
956
|
+
*/
|
|
957
|
+
CommandStack.prototype.clear = function (emit) {
|
|
958
|
+
this._stack.length = 0;
|
|
959
|
+
this._stackIdx = -1;
|
|
960
|
+
if (emit !== false) {
|
|
961
|
+
this._fire('changed', {
|
|
962
|
+
trigger: 'clear'
|
|
963
|
+
});
|
|
964
|
+
}
|
|
965
|
+
};
|
|
966
|
+
|
|
967
|
+
/**
|
|
968
|
+
* Undo last command(s)
|
|
969
|
+
*/
|
|
970
|
+
CommandStack.prototype.undo = function () {
|
|
971
|
+
let action = this._getUndoAction(),
|
|
972
|
+
next;
|
|
973
|
+
if (action) {
|
|
974
|
+
this._currentExecution.trigger = 'undo';
|
|
975
|
+
this._pushAction(action);
|
|
976
|
+
while (action) {
|
|
977
|
+
this._internalUndo(action);
|
|
978
|
+
next = this._getUndoAction();
|
|
979
|
+
if (!next || next.id !== action.id) {
|
|
980
|
+
break;
|
|
981
|
+
}
|
|
982
|
+
action = next;
|
|
983
|
+
}
|
|
984
|
+
this._popAction();
|
|
985
|
+
}
|
|
986
|
+
};
|
|
987
|
+
|
|
988
|
+
/**
|
|
989
|
+
* Redo last command(s)
|
|
990
|
+
*/
|
|
991
|
+
CommandStack.prototype.redo = function () {
|
|
992
|
+
let action = this._getRedoAction(),
|
|
993
|
+
next;
|
|
994
|
+
if (action) {
|
|
995
|
+
this._currentExecution.trigger = 'redo';
|
|
996
|
+
this._pushAction(action);
|
|
997
|
+
while (action) {
|
|
998
|
+
this._internalExecute(action, true);
|
|
999
|
+
next = this._getRedoAction();
|
|
1000
|
+
if (!next || next.id !== action.id) {
|
|
1001
|
+
break;
|
|
1002
|
+
}
|
|
1003
|
+
action = next;
|
|
1004
|
+
}
|
|
1005
|
+
this._popAction();
|
|
1006
|
+
}
|
|
1007
|
+
};
|
|
1008
|
+
|
|
1009
|
+
/**
|
|
1010
|
+
* Register a handler instance with the command stack.
|
|
1011
|
+
*
|
|
1012
|
+
* @param {string} command Command to be executed.
|
|
1013
|
+
* @param {CommandHandler} handler Handler to execute the command.
|
|
1014
|
+
*/
|
|
1015
|
+
CommandStack.prototype.register = function (command, handler) {
|
|
1016
|
+
this._setHandler(command, handler);
|
|
1017
|
+
};
|
|
1018
|
+
|
|
1019
|
+
/**
|
|
1020
|
+
* Register a handler type with the command stack by instantiating it and
|
|
1021
|
+
* injecting its dependencies.
|
|
1022
|
+
*
|
|
1023
|
+
* @param {string} command Command to be executed.
|
|
1024
|
+
* @param {CommandHandlerConstructor} handlerCls Constructor to instantiate a {@link CommandHandler}.
|
|
1025
|
+
*/
|
|
1026
|
+
CommandStack.prototype.registerHandler = function (command, handlerCls) {
|
|
1027
|
+
if (!command || !handlerCls) {
|
|
1028
|
+
throw new Error('command and handlerCls must be defined');
|
|
1029
|
+
}
|
|
1030
|
+
const handler = this._injector.instantiate(handlerCls);
|
|
1031
|
+
this.register(command, handler);
|
|
1032
|
+
};
|
|
1033
|
+
|
|
1034
|
+
/**
|
|
1035
|
+
* @return {boolean}
|
|
1036
|
+
*/
|
|
1037
|
+
CommandStack.prototype.canUndo = function () {
|
|
1038
|
+
return !!this._getUndoAction();
|
|
1039
|
+
};
|
|
1040
|
+
|
|
1041
|
+
/**
|
|
1042
|
+
* @return {boolean}
|
|
1043
|
+
*/
|
|
1044
|
+
CommandStack.prototype.canRedo = function () {
|
|
1045
|
+
return !!this._getRedoAction();
|
|
1046
|
+
};
|
|
1047
|
+
|
|
1048
|
+
// stack access //////////////////////
|
|
1049
|
+
|
|
1050
|
+
CommandStack.prototype._getRedoAction = function () {
|
|
1051
|
+
return this._stack[this._stackIdx + 1];
|
|
1052
|
+
};
|
|
1053
|
+
CommandStack.prototype._getUndoAction = function () {
|
|
1054
|
+
return this._stack[this._stackIdx];
|
|
1055
|
+
};
|
|
1056
|
+
|
|
1057
|
+
// internal functionality //////////////////////
|
|
1058
|
+
|
|
1059
|
+
CommandStack.prototype._internalUndo = function (action) {
|
|
1060
|
+
const command = action.command,
|
|
1061
|
+
context = action.context;
|
|
1062
|
+
const handler = this._getHandler(command);
|
|
1063
|
+
|
|
1064
|
+
// guard against illegal nested command stack invocations
|
|
1065
|
+
this._atomicDo(() => {
|
|
1066
|
+
this._fire(command, 'revert', action);
|
|
1067
|
+
if (handler.revert) {
|
|
1068
|
+
this._markDirty(handler.revert(context));
|
|
1069
|
+
}
|
|
1070
|
+
this._revertedAction(action);
|
|
1071
|
+
this._fire(command, 'reverted', action);
|
|
1072
|
+
});
|
|
1073
|
+
};
|
|
1074
|
+
CommandStack.prototype._fire = function (command, qualifier, event) {
|
|
1075
|
+
if (arguments.length < 3) {
|
|
1076
|
+
event = qualifier;
|
|
1077
|
+
qualifier = null;
|
|
1078
|
+
}
|
|
1079
|
+
const names = qualifier ? [command + '.' + qualifier, qualifier] : [command];
|
|
1080
|
+
let result;
|
|
1081
|
+
event = this._eventBus.createEvent(event);
|
|
1082
|
+
for (const name of names) {
|
|
1083
|
+
result = this._eventBus.fire('commandStack.' + name, event);
|
|
1084
|
+
if (event.cancelBubble) {
|
|
1085
|
+
break;
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
return result;
|
|
1089
|
+
};
|
|
1090
|
+
CommandStack.prototype._createId = function () {
|
|
1091
|
+
return this._uid++;
|
|
1092
|
+
};
|
|
1093
|
+
CommandStack.prototype._atomicDo = function (fn) {
|
|
1094
|
+
const execution = this._currentExecution;
|
|
1095
|
+
execution.atomic = true;
|
|
1096
|
+
try {
|
|
1097
|
+
fn();
|
|
1098
|
+
} finally {
|
|
1099
|
+
execution.atomic = false;
|
|
1100
|
+
}
|
|
1101
|
+
};
|
|
1102
|
+
CommandStack.prototype._internalExecute = function (action, redo) {
|
|
1103
|
+
const command = action.command,
|
|
1104
|
+
context = action.context;
|
|
1105
|
+
const handler = this._getHandler(command);
|
|
1106
|
+
if (!handler) {
|
|
1107
|
+
throw new Error('no command handler registered for <' + command + '>');
|
|
1108
|
+
}
|
|
1109
|
+
this._pushAction(action);
|
|
1110
|
+
if (!redo) {
|
|
1111
|
+
this._fire(command, 'preExecute', action);
|
|
1112
|
+
if (handler.preExecute) {
|
|
1113
|
+
handler.preExecute(context);
|
|
1114
|
+
}
|
|
1115
|
+
this._fire(command, 'preExecuted', action);
|
|
1116
|
+
}
|
|
1117
|
+
|
|
1118
|
+
// guard against illegal nested command stack invocations
|
|
1119
|
+
this._atomicDo(() => {
|
|
1120
|
+
this._fire(command, 'execute', action);
|
|
1121
|
+
if (handler.execute) {
|
|
1122
|
+
// actual execute + mark return results as dirty
|
|
1123
|
+
this._markDirty(handler.execute(context));
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
// log to stack
|
|
1127
|
+
this._executedAction(action, redo);
|
|
1128
|
+
this._fire(command, 'executed', action);
|
|
1129
|
+
});
|
|
1130
|
+
if (!redo) {
|
|
1131
|
+
this._fire(command, 'postExecute', action);
|
|
1132
|
+
if (handler.postExecute) {
|
|
1133
|
+
handler.postExecute(context);
|
|
1134
|
+
}
|
|
1135
|
+
this._fire(command, 'postExecuted', action);
|
|
1136
|
+
}
|
|
1137
|
+
this._popAction();
|
|
1138
|
+
};
|
|
1139
|
+
CommandStack.prototype._pushAction = function (action) {
|
|
1140
|
+
const execution = this._currentExecution,
|
|
1141
|
+
actions = execution.actions;
|
|
1142
|
+
const baseAction = actions[0];
|
|
1143
|
+
if (execution.atomic) {
|
|
1144
|
+
throw new Error('illegal invocation in <execute> or <revert> phase (action: ' + action.command + ')');
|
|
1145
|
+
}
|
|
1146
|
+
if (!action.id) {
|
|
1147
|
+
action.id = baseAction && baseAction.id || this._createId();
|
|
1148
|
+
}
|
|
1149
|
+
actions.push(action);
|
|
1150
|
+
};
|
|
1151
|
+
CommandStack.prototype._popAction = function () {
|
|
1152
|
+
const execution = this._currentExecution,
|
|
1153
|
+
trigger = execution.trigger,
|
|
1154
|
+
actions = execution.actions,
|
|
1155
|
+
dirty = execution.dirty;
|
|
1156
|
+
actions.pop();
|
|
1157
|
+
if (!actions.length) {
|
|
1158
|
+
this._eventBus.fire('elements.changed', {
|
|
1159
|
+
elements: uniqueBy('id', dirty.reverse())
|
|
1160
|
+
});
|
|
1161
|
+
dirty.length = 0;
|
|
1162
|
+
this._fire('changed', {
|
|
1163
|
+
trigger: trigger
|
|
1164
|
+
});
|
|
1165
|
+
execution.trigger = null;
|
|
1166
|
+
}
|
|
1167
|
+
};
|
|
1168
|
+
CommandStack.prototype._markDirty = function (elements) {
|
|
1169
|
+
const execution = this._currentExecution;
|
|
1170
|
+
if (!elements) {
|
|
1171
|
+
return;
|
|
1172
|
+
}
|
|
1173
|
+
elements = isArray(elements) ? elements : [elements];
|
|
1174
|
+
execution.dirty = execution.dirty.concat(elements);
|
|
1175
|
+
};
|
|
1176
|
+
CommandStack.prototype._executedAction = function (action, redo) {
|
|
1177
|
+
const stackIdx = ++this._stackIdx;
|
|
1178
|
+
if (!redo) {
|
|
1179
|
+
this._stack.splice(stackIdx, this._stack.length, action);
|
|
1180
|
+
}
|
|
1181
|
+
};
|
|
1182
|
+
CommandStack.prototype._revertedAction = function (action) {
|
|
1183
|
+
this._stackIdx--;
|
|
1184
|
+
};
|
|
1185
|
+
CommandStack.prototype._getHandler = function (command) {
|
|
1186
|
+
return this._handlerMap[command];
|
|
1187
|
+
};
|
|
1188
|
+
CommandStack.prototype._setHandler = function (command, handler) {
|
|
1189
|
+
if (!command || !handler) {
|
|
1190
|
+
throw new Error('command and handler required');
|
|
1191
|
+
}
|
|
1192
|
+
if (this._handlerMap[command]) {
|
|
1193
|
+
throw new Error('overriding handler for command <' + command + '>');
|
|
1194
|
+
}
|
|
1195
|
+
this._handlerMap[command] = handler;
|
|
1196
|
+
};
|
|
1197
|
+
|
|
1198
|
+
/**
|
|
1199
|
+
* @type { import('didi').ModuleDeclaration }
|
|
1200
|
+
*/
|
|
1201
|
+
var commandModule = {
|
|
1202
|
+
commandStack: ['type', CommandStack]
|
|
1203
|
+
};
|
|
1204
|
+
|
|
1205
|
+
class UpdateFieldValidationHandler {
|
|
1206
|
+
constructor(form, validator) {
|
|
1207
|
+
this._form = form;
|
|
1208
|
+
this._validator = validator;
|
|
1209
|
+
}
|
|
1210
|
+
execute(context) {
|
|
1211
|
+
const {
|
|
1212
|
+
field,
|
|
1213
|
+
value
|
|
1214
|
+
} = context;
|
|
1215
|
+
const {
|
|
1216
|
+
errors
|
|
1217
|
+
} = this._form._getState();
|
|
1218
|
+
context.oldErrors = clone(errors);
|
|
1219
|
+
const fieldErrors = this._validator.validateField(field, value);
|
|
1220
|
+
const updatedErrors = set(errors, [field.id], fieldErrors.length ? fieldErrors : undefined);
|
|
1221
|
+
this._form._setState({
|
|
1222
|
+
errors: updatedErrors
|
|
1223
|
+
});
|
|
1224
|
+
}
|
|
1225
|
+
revert(context) {
|
|
1226
|
+
this._form._setState({
|
|
1227
|
+
errors: context.oldErrors
|
|
1228
|
+
});
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1231
|
+
UpdateFieldValidationHandler.$inject = ['form', 'validator'];
|
|
1232
|
+
|
|
1233
|
+
class ViewerCommands {
|
|
1234
|
+
constructor(commandStack, eventBus) {
|
|
1235
|
+
this._commandStack = commandStack;
|
|
1236
|
+
eventBus.on('form.init', () => {
|
|
1237
|
+
this.registerHandlers();
|
|
1238
|
+
});
|
|
1239
|
+
}
|
|
1240
|
+
registerHandlers() {
|
|
1241
|
+
Object.entries(this.getHandlers()).forEach(([id, handler]) => {
|
|
1242
|
+
this._commandStack.registerHandler(id, handler);
|
|
1243
|
+
});
|
|
1244
|
+
}
|
|
1245
|
+
getHandlers() {
|
|
1246
|
+
return {
|
|
1247
|
+
'formField.validation.update': UpdateFieldValidationHandler
|
|
1248
|
+
};
|
|
1249
|
+
}
|
|
1250
|
+
updateFieldValidation(field, value) {
|
|
1251
|
+
const context = {
|
|
1252
|
+
field,
|
|
1253
|
+
value
|
|
1254
|
+
};
|
|
1255
|
+
this._commandStack.execute('formField.validation.update', context);
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
ViewerCommands.$inject = ['commandStack', 'eventBus'];
|
|
1259
|
+
|
|
1260
|
+
var ViewerCommandsModule = {
|
|
1261
|
+
__depends__: [commandModule],
|
|
1262
|
+
__init__: ['viewerCommands'],
|
|
1263
|
+
viewerCommands: ['type', ViewerCommands]
|
|
1264
|
+
};
|
|
1265
|
+
|
|
474
1266
|
var FN_REF = '__fn';
|
|
475
1267
|
var DEFAULT_PRIORITY = 1000;
|
|
476
1268
|
var slice = Array.prototype.slice;
|
|
@@ -1074,8 +1866,8 @@ Validator.$inject = ['expressionLanguage', 'conditionChecker', 'form'];
|
|
|
1074
1866
|
|
|
1075
1867
|
// helpers //////////
|
|
1076
1868
|
|
|
1077
|
-
/**
|
|
1078
|
-
* Helper function to evaluate optional FEEL validation values.
|
|
1869
|
+
/**
|
|
1870
|
+
* Helper function to evaluate optional FEEL validation values.
|
|
1079
1871
|
*/
|
|
1080
1872
|
function evaluateFEELValues(validate, expressionLanguage, conditionChecker, form) {
|
|
1081
1873
|
const evaluatedValidate = {
|
|
@@ -1108,72 +1900,415 @@ function evaluateFEELValues(validate, expressionLanguage, conditionChecker, form
|
|
|
1108
1900
|
return evaluatedValidate;
|
|
1109
1901
|
}
|
|
1110
1902
|
|
|
1111
|
-
class
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1903
|
+
class Importer {
|
|
1904
|
+
/**
|
|
1905
|
+
* @constructor
|
|
1906
|
+
* @param { import('./FormFieldRegistry').default } formFieldRegistry
|
|
1907
|
+
* @param { import('./PathRegistry').default } pathRegistry
|
|
1908
|
+
* @param { import('./FieldFactory').default } fieldFactory
|
|
1909
|
+
* @param { import('./FormLayouter').default } formLayouter
|
|
1910
|
+
*/
|
|
1911
|
+
constructor(formFieldRegistry, pathRegistry, fieldFactory, formLayouter) {
|
|
1912
|
+
this._formFieldRegistry = formFieldRegistry;
|
|
1913
|
+
this._pathRegistry = pathRegistry;
|
|
1914
|
+
this._fieldFactory = fieldFactory;
|
|
1915
|
+
this._formLayouter = formLayouter;
|
|
1118
1916
|
}
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1917
|
+
|
|
1918
|
+
/**
|
|
1919
|
+
* Import schema creating rows, fields, attaching additional
|
|
1920
|
+
* information to each field and adding fields to the
|
|
1921
|
+
* field registry.
|
|
1922
|
+
*
|
|
1923
|
+
* Additional information attached:
|
|
1924
|
+
*
|
|
1925
|
+
* * `id` (unless present)
|
|
1926
|
+
* * `_parent`
|
|
1927
|
+
* * `_path`
|
|
1928
|
+
*
|
|
1929
|
+
* @param {any} schema
|
|
1930
|
+
*
|
|
1931
|
+
* @typedef {{ warnings: Error[], schema: any }} ImportResult
|
|
1932
|
+
* @returns {ImportResult}
|
|
1933
|
+
*/
|
|
1934
|
+
importSchema(schema) {
|
|
1935
|
+
// TODO: Add warnings
|
|
1936
|
+
const warnings = [];
|
|
1937
|
+
try {
|
|
1938
|
+
this._cleanup();
|
|
1939
|
+
const importedSchema = this.importFormField(clone(schema));
|
|
1940
|
+
this._formLayouter.calculateLayout(clone(importedSchema));
|
|
1941
|
+
return {
|
|
1942
|
+
schema: importedSchema,
|
|
1943
|
+
warnings
|
|
1944
|
+
};
|
|
1945
|
+
} catch (err) {
|
|
1946
|
+
this._cleanup();
|
|
1947
|
+
err.warnings = warnings;
|
|
1948
|
+
throw err;
|
|
1125
1949
|
}
|
|
1126
|
-
|
|
1127
|
-
|
|
1950
|
+
}
|
|
1951
|
+
_cleanup() {
|
|
1952
|
+
this._formLayouter.clear();
|
|
1953
|
+
this._formFieldRegistry.clear();
|
|
1954
|
+
this._pathRegistry.clear();
|
|
1955
|
+
}
|
|
1956
|
+
|
|
1957
|
+
/**
|
|
1958
|
+
* @param {{[x: string]: any}} fieldAttrs
|
|
1959
|
+
* @param {String} [parentId]
|
|
1960
|
+
* @param {number} [index]
|
|
1961
|
+
*
|
|
1962
|
+
* @return {any} field
|
|
1963
|
+
*/
|
|
1964
|
+
importFormField(fieldAttrs, parentId, index) {
|
|
1965
|
+
const {
|
|
1966
|
+
components
|
|
1967
|
+
} = fieldAttrs;
|
|
1968
|
+
let parent, path;
|
|
1969
|
+
if (parentId) {
|
|
1970
|
+
parent = this._formFieldRegistry.get(parentId);
|
|
1971
|
+
}
|
|
1972
|
+
|
|
1973
|
+
// set form field path
|
|
1974
|
+
path = parent ? [...parent._path, 'components', index] : [];
|
|
1975
|
+
const field = this._fieldFactory.create({
|
|
1976
|
+
...fieldAttrs,
|
|
1977
|
+
_path: path,
|
|
1978
|
+
_parent: parentId
|
|
1979
|
+
}, false);
|
|
1980
|
+
this._formFieldRegistry.add(field);
|
|
1981
|
+
if (components) {
|
|
1982
|
+
field.components = this.importFormFields(components, field.id);
|
|
1983
|
+
}
|
|
1984
|
+
return field;
|
|
1985
|
+
}
|
|
1986
|
+
|
|
1987
|
+
/**
|
|
1988
|
+
* @param {Array<any>} components
|
|
1989
|
+
* @param {string} parentId
|
|
1990
|
+
*
|
|
1991
|
+
* @return {Array<any>} imported components
|
|
1992
|
+
*/
|
|
1993
|
+
importFormFields(components, parentId) {
|
|
1994
|
+
return components.map((component, index) => {
|
|
1995
|
+
return this.importFormField(component, parentId, index);
|
|
1128
1996
|
});
|
|
1129
|
-
this._formFields[id] = formField;
|
|
1130
1997
|
}
|
|
1131
|
-
|
|
1998
|
+
}
|
|
1999
|
+
Importer.$inject = ['formFieldRegistry', 'pathRegistry', 'fieldFactory', 'formLayouter'];
|
|
2000
|
+
|
|
2001
|
+
class FieldFactory {
|
|
2002
|
+
/**
|
|
2003
|
+
* @constructor
|
|
2004
|
+
*
|
|
2005
|
+
* @param formFieldRegistry
|
|
2006
|
+
* @param formFields
|
|
2007
|
+
*/
|
|
2008
|
+
constructor(formFieldRegistry, pathRegistry, formFields) {
|
|
2009
|
+
this._formFieldRegistry = formFieldRegistry;
|
|
2010
|
+
this._pathRegistry = pathRegistry;
|
|
2011
|
+
this._formFields = formFields;
|
|
2012
|
+
}
|
|
2013
|
+
create(attrs, applyDefaults = true) {
|
|
1132
2014
|
const {
|
|
1133
|
-
id
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
2015
|
+
id,
|
|
2016
|
+
type,
|
|
2017
|
+
key,
|
|
2018
|
+
path,
|
|
2019
|
+
_parent
|
|
2020
|
+
} = attrs;
|
|
2021
|
+
const fieldDefinition = this._formFields.get(type);
|
|
2022
|
+
if (!fieldDefinition) {
|
|
2023
|
+
throw new Error(`form field of type <${type}> not supported`);
|
|
1137
2024
|
}
|
|
1138
|
-
|
|
1139
|
-
|
|
2025
|
+
const {
|
|
2026
|
+
config
|
|
2027
|
+
} = fieldDefinition;
|
|
2028
|
+
if (!config) {
|
|
2029
|
+
throw new Error(`form field of type <${type}> has no config`);
|
|
2030
|
+
}
|
|
2031
|
+
if (id && this._formFieldRegistry._ids.assigned(id)) {
|
|
2032
|
+
throw new Error(`form field with id <${id}> already exists`);
|
|
2033
|
+
}
|
|
2034
|
+
|
|
2035
|
+
// ensure that we can claim the path
|
|
2036
|
+
|
|
2037
|
+
const parent = _parent && this._formFieldRegistry.get(_parent);
|
|
2038
|
+
const parentPath = parent && this._pathRegistry.getValuePath(parent) || [];
|
|
2039
|
+
if (config.keyed && key && !this._pathRegistry.canClaimPath([...parentPath, ...key.split('.')], true)) {
|
|
2040
|
+
throw new Error(`binding path '${[...parentPath, key].join('.')}' is already claimed`);
|
|
2041
|
+
}
|
|
2042
|
+
if (config.pathed && path && !this._pathRegistry.canClaimPath([...parentPath, ...path.split('.')], false)) {
|
|
2043
|
+
throw new Error(`binding path '${[...parentPath, ...path.split('.')].join('.')}' is already claimed`);
|
|
2044
|
+
}
|
|
2045
|
+
const labelAttrs = applyDefaults && config.label ? {
|
|
2046
|
+
label: config.label
|
|
2047
|
+
} : {};
|
|
2048
|
+
const field = config.create({
|
|
2049
|
+
...labelAttrs,
|
|
2050
|
+
...attrs
|
|
1140
2051
|
});
|
|
1141
|
-
|
|
2052
|
+
this._ensureId(field);
|
|
2053
|
+
if (config.keyed) {
|
|
2054
|
+
this._ensureKey(field);
|
|
2055
|
+
}
|
|
2056
|
+
if (config.pathed && path) {
|
|
2057
|
+
this._pathRegistry.claimPath(this._pathRegistry.getValuePath(field), false);
|
|
2058
|
+
}
|
|
2059
|
+
return field;
|
|
1142
2060
|
}
|
|
1143
|
-
|
|
1144
|
-
|
|
2061
|
+
_ensureId(field) {
|
|
2062
|
+
if (field.id) {
|
|
2063
|
+
this._formFieldRegistry._ids.claim(field.id, field);
|
|
2064
|
+
return;
|
|
2065
|
+
}
|
|
2066
|
+
let prefix = 'Field';
|
|
2067
|
+
if (field.type === 'default') {
|
|
2068
|
+
prefix = 'Form';
|
|
2069
|
+
}
|
|
2070
|
+
field.id = this._formFieldRegistry._ids.nextPrefixed(`${prefix}_`, field);
|
|
2071
|
+
}
|
|
2072
|
+
_ensureKey(field) {
|
|
2073
|
+
if (!field.key) {
|
|
2074
|
+
let random;
|
|
2075
|
+
const parent = this._formFieldRegistry.get(field._parent);
|
|
2076
|
+
|
|
2077
|
+
// ensure key uniqueness at level
|
|
2078
|
+
do {
|
|
2079
|
+
random = Math.random().toString(36).substring(7);
|
|
2080
|
+
} while (parent && parent.components.some(child => child.key === random));
|
|
2081
|
+
field.key = `${field.type}_${random}`;
|
|
2082
|
+
}
|
|
2083
|
+
this._pathRegistry.claimPath(this._pathRegistry.getValuePath(field), true);
|
|
1145
2084
|
}
|
|
1146
|
-
|
|
1147
|
-
|
|
2085
|
+
}
|
|
2086
|
+
FieldFactory.$inject = ['formFieldRegistry', 'pathRegistry', 'formFields'];
|
|
2087
|
+
|
|
2088
|
+
/**
|
|
2089
|
+
* The PathRegistry class manages a hierarchical structure of paths associated with form fields.
|
|
2090
|
+
* It enables claiming, unclaiming, and validating paths within this structure.
|
|
2091
|
+
*
|
|
2092
|
+
* Example Tree Structure:
|
|
2093
|
+
*
|
|
2094
|
+
* [
|
|
2095
|
+
* {
|
|
2096
|
+
* segment: 'root',
|
|
2097
|
+
* claimCount: 1,
|
|
2098
|
+
* children: [
|
|
2099
|
+
* {
|
|
2100
|
+
* segment: 'child1',
|
|
2101
|
+
* claimCount: 2,
|
|
2102
|
+
* children: null // A leaf node (closed path)
|
|
2103
|
+
* },
|
|
2104
|
+
* {
|
|
2105
|
+
* segment: 'child2',
|
|
2106
|
+
* claimCount: 1,
|
|
2107
|
+
* children: [
|
|
2108
|
+
* {
|
|
2109
|
+
* segment: 'subChild1',
|
|
2110
|
+
* claimCount: 1,
|
|
2111
|
+
* children: [] // An open node (open path)
|
|
2112
|
+
* }
|
|
2113
|
+
* ]
|
|
2114
|
+
* }
|
|
2115
|
+
* ]
|
|
2116
|
+
* }
|
|
2117
|
+
* ]
|
|
2118
|
+
*/
|
|
2119
|
+
class PathRegistry {
|
|
2120
|
+
constructor(formFieldRegistry, formFields) {
|
|
2121
|
+
this._formFieldRegistry = formFieldRegistry;
|
|
2122
|
+
this._formFields = formFields;
|
|
2123
|
+
this._dataPaths = [];
|
|
1148
2124
|
}
|
|
1149
|
-
|
|
1150
|
-
|
|
2125
|
+
canClaimPath(path, closed = false) {
|
|
2126
|
+
let node = {
|
|
2127
|
+
children: this._dataPaths
|
|
2128
|
+
};
|
|
2129
|
+
for (const segment of path) {
|
|
2130
|
+
node = _getNextSegment(node, segment);
|
|
2131
|
+
|
|
2132
|
+
// if no node at that path, we can claim it no matter what
|
|
2133
|
+
if (!node) {
|
|
2134
|
+
return true;
|
|
2135
|
+
}
|
|
2136
|
+
|
|
2137
|
+
// if we reach a leaf node, definitely not claimable
|
|
2138
|
+
if (node.children === null) {
|
|
2139
|
+
return false;
|
|
2140
|
+
}
|
|
2141
|
+
}
|
|
2142
|
+
|
|
2143
|
+
// if after all segments we reach a node with children, we can claim it only openly
|
|
2144
|
+
return !closed;
|
|
2145
|
+
}
|
|
2146
|
+
claimPath(path, closed = false) {
|
|
2147
|
+
if (!this.canClaimPath(path, closed)) {
|
|
2148
|
+
throw new Error(`cannot claim path '${path.join('.')}'`);
|
|
2149
|
+
}
|
|
2150
|
+
let node = {
|
|
2151
|
+
children: this._dataPaths
|
|
2152
|
+
};
|
|
2153
|
+
for (const segment of path) {
|
|
2154
|
+
let child = _getNextSegment(node, segment);
|
|
2155
|
+
if (!child) {
|
|
2156
|
+
child = {
|
|
2157
|
+
segment,
|
|
2158
|
+
claimCount: 1,
|
|
2159
|
+
children: []
|
|
2160
|
+
};
|
|
2161
|
+
node.children.push(child);
|
|
2162
|
+
} else {
|
|
2163
|
+
child.claimCount++;
|
|
2164
|
+
}
|
|
2165
|
+
node = child;
|
|
2166
|
+
}
|
|
2167
|
+
if (closed) {
|
|
2168
|
+
node.children = null;
|
|
2169
|
+
}
|
|
2170
|
+
}
|
|
2171
|
+
unclaimPath(path) {
|
|
2172
|
+
// verification Pass
|
|
2173
|
+
let node = {
|
|
2174
|
+
children: this._dataPaths
|
|
2175
|
+
};
|
|
2176
|
+
for (const segment of path) {
|
|
2177
|
+
const child = _getNextSegment(node, segment);
|
|
2178
|
+
if (!child) {
|
|
2179
|
+
throw new Error(`no open path found for '${path.join('.')}'`);
|
|
2180
|
+
}
|
|
2181
|
+
node = child;
|
|
2182
|
+
}
|
|
2183
|
+
|
|
2184
|
+
// mutation Pass
|
|
2185
|
+
node = {
|
|
2186
|
+
children: this._dataPaths
|
|
2187
|
+
};
|
|
2188
|
+
for (const segment of path) {
|
|
2189
|
+
const child = _getNextSegment(node, segment);
|
|
2190
|
+
child.claimCount--;
|
|
2191
|
+
if (child.claimCount === 0) {
|
|
2192
|
+
node.children.splice(node.children.indexOf(child), 1);
|
|
2193
|
+
break; // Abort early if claimCount reaches zero
|
|
2194
|
+
}
|
|
2195
|
+
|
|
2196
|
+
node = child;
|
|
2197
|
+
}
|
|
2198
|
+
}
|
|
2199
|
+
|
|
2200
|
+
/**
|
|
2201
|
+
* Applies a function (fn) recursively on a given field and its children.
|
|
2202
|
+
*
|
|
2203
|
+
* - `field`: Starting field object.
|
|
2204
|
+
* - `fn`: Function to apply.
|
|
2205
|
+
* - `context`: Optional object for passing data between calls.
|
|
2206
|
+
*
|
|
2207
|
+
* Stops early if `fn` returns `false`. Useful for traversing the form field tree.
|
|
2208
|
+
*
|
|
2209
|
+
* @returns {boolean} Success status based on function execution.
|
|
2210
|
+
*/
|
|
2211
|
+
executeRecursivelyOnFields(field, fn, context = {}) {
|
|
2212
|
+
let result = true;
|
|
2213
|
+
const formFieldConfig = this._formFields.get(field.type).config;
|
|
2214
|
+
if (formFieldConfig.keyed) {
|
|
2215
|
+
const callResult = fn({
|
|
2216
|
+
field,
|
|
2217
|
+
isClosed: true,
|
|
2218
|
+
context
|
|
2219
|
+
});
|
|
2220
|
+
return result && callResult;
|
|
2221
|
+
} else if (formFieldConfig.pathed) {
|
|
2222
|
+
const callResult = fn({
|
|
2223
|
+
field,
|
|
2224
|
+
isClosed: false,
|
|
2225
|
+
context
|
|
2226
|
+
});
|
|
2227
|
+
result = result && callResult;
|
|
2228
|
+
}
|
|
2229
|
+
if (field.components) {
|
|
2230
|
+
for (const child of field.components) {
|
|
2231
|
+
const callResult = this.executeRecursivelyOnFields(child, fn, clone(context));
|
|
2232
|
+
result = result && callResult;
|
|
2233
|
+
|
|
2234
|
+
// only stop executing if false is specifically returned, not if undefined
|
|
2235
|
+
if (result === false) {
|
|
2236
|
+
return result;
|
|
2237
|
+
}
|
|
2238
|
+
}
|
|
2239
|
+
}
|
|
2240
|
+
return result;
|
|
2241
|
+
}
|
|
2242
|
+
|
|
2243
|
+
/**
|
|
2244
|
+
* Generates an array representing the binding path to an underlying data object for a form field.
|
|
2245
|
+
*
|
|
2246
|
+
* @param {Object} field - The field object with properties: `key`, `path`, `id`, and optionally `_parent`.
|
|
2247
|
+
* @param {Object} [options={}] - Configuration options.
|
|
2248
|
+
* @param {Object} [options.replacements={}] - A map of field IDs to alternative path arrays.
|
|
2249
|
+
* @param {Object} [options.cutoffNode] - The ID of the parent field at which to stop generating the path.
|
|
2250
|
+
*
|
|
2251
|
+
* @returns {(Array<string>|undefined)} An array of strings representing the binding path, or undefined if not determinable.
|
|
2252
|
+
*/
|
|
2253
|
+
getValuePath(field, options = {}) {
|
|
2254
|
+
const {
|
|
2255
|
+
replacements = {},
|
|
2256
|
+
cutoffNode = null
|
|
2257
|
+
} = options;
|
|
2258
|
+
let localValuePath = [];
|
|
2259
|
+
const hasReplacement = Object.prototype.hasOwnProperty.call(replacements, field.id);
|
|
2260
|
+
const formFieldConfig = this._formFields.get(field.type).config;
|
|
2261
|
+
if (hasReplacement) {
|
|
2262
|
+
const replacement = replacements[field.id];
|
|
2263
|
+
if (replacement === null || replacement === undefined || replacement === '') {
|
|
2264
|
+
localValuePath = [];
|
|
2265
|
+
} else if (typeof replacement === 'string') {
|
|
2266
|
+
localValuePath = replacement.split('.');
|
|
2267
|
+
} else if (Array.isArray(replacement)) {
|
|
2268
|
+
localValuePath = replacement;
|
|
2269
|
+
} else {
|
|
2270
|
+
throw new Error(`replacements for field ${field.id} must be a string, array or null/undefined`);
|
|
2271
|
+
}
|
|
2272
|
+
} else if (formFieldConfig.keyed) {
|
|
2273
|
+
localValuePath = field.key.split('.');
|
|
2274
|
+
} else if (formFieldConfig.pathed && field.path) {
|
|
2275
|
+
localValuePath = field.path.split('.');
|
|
2276
|
+
}
|
|
2277
|
+
if (field._parent && field._parent !== cutoffNode) {
|
|
2278
|
+
const parent = this._formFieldRegistry.get(field._parent);
|
|
2279
|
+
return [...(this.getValuePath(parent, options) || []), ...localValuePath];
|
|
2280
|
+
}
|
|
2281
|
+
return localValuePath;
|
|
1151
2282
|
}
|
|
1152
2283
|
clear() {
|
|
1153
|
-
this.
|
|
1154
|
-
this._ids.clear();
|
|
1155
|
-
this._keys.clear();
|
|
2284
|
+
this._dataPaths = [];
|
|
1156
2285
|
}
|
|
1157
2286
|
}
|
|
1158
|
-
|
|
2287
|
+
const _getNextSegment = (node, segment) => {
|
|
2288
|
+
if (isArray(node.children)) {
|
|
2289
|
+
return node.children.find(node => node.segment === segment) || null;
|
|
2290
|
+
}
|
|
2291
|
+
return null;
|
|
2292
|
+
};
|
|
2293
|
+
PathRegistry.$inject = ['formFieldRegistry', 'formFields'];
|
|
1159
2294
|
|
|
1160
|
-
/**
|
|
1161
|
-
* @typedef { { id: String, components: Array<String> } } FormRow
|
|
1162
|
-
* @typedef { { formFieldId: String, rows: Array<FormRow> } } FormRows
|
|
2295
|
+
/**
|
|
2296
|
+
* @typedef { { id: String, components: Array<String> } } FormRow
|
|
2297
|
+
* @typedef { { formFieldId: String, rows: Array<FormRow> } } FormRows
|
|
1163
2298
|
*/
|
|
1164
2299
|
|
|
1165
|
-
/**
|
|
1166
|
-
* Maintains the Form layout in a given structure, for example
|
|
1167
|
-
*
|
|
1168
|
-
* [
|
|
1169
|
-
* {
|
|
1170
|
-
* formFieldId: 'FormField_1',
|
|
1171
|
-
* rows: [
|
|
1172
|
-
* { id: 'Row_1', components: [ 'Text_1', 'Textdield_1', ... ] }
|
|
1173
|
-
* ]
|
|
1174
|
-
* }
|
|
1175
|
-
* ]
|
|
1176
|
-
*
|
|
2300
|
+
/**
|
|
2301
|
+
* Maintains the Form layout in a given structure, for example
|
|
2302
|
+
*
|
|
2303
|
+
* [
|
|
2304
|
+
* {
|
|
2305
|
+
* formFieldId: 'FormField_1',
|
|
2306
|
+
* rows: [
|
|
2307
|
+
* { id: 'Row_1', components: [ 'Text_1', 'Textdield_1', ... ] }
|
|
2308
|
+
* ]
|
|
2309
|
+
* }
|
|
2310
|
+
* ]
|
|
2311
|
+
*
|
|
1177
2312
|
*/
|
|
1178
2313
|
class FormLayouter {
|
|
1179
2314
|
constructor(eventBus) {
|
|
@@ -1183,8 +2318,8 @@ class FormLayouter {
|
|
|
1183
2318
|
this._eventBus = eventBus;
|
|
1184
2319
|
}
|
|
1185
2320
|
|
|
1186
|
-
/**
|
|
1187
|
-
* @param {FormRow} row
|
|
2321
|
+
/**
|
|
2322
|
+
* @param {FormRow} row
|
|
1188
2323
|
*/
|
|
1189
2324
|
addRow(formFieldId, row) {
|
|
1190
2325
|
let rowsPerComponent = this._rows.find(r => r.formFieldId === formFieldId);
|
|
@@ -1198,18 +2333,18 @@ class FormLayouter {
|
|
|
1198
2333
|
rowsPerComponent.rows.push(row);
|
|
1199
2334
|
}
|
|
1200
2335
|
|
|
1201
|
-
/**
|
|
1202
|
-
* @param {String} id
|
|
1203
|
-
* @returns {FormRow}
|
|
2336
|
+
/**
|
|
2337
|
+
* @param {String} id
|
|
2338
|
+
* @returns {FormRow}
|
|
1204
2339
|
*/
|
|
1205
2340
|
getRow(id) {
|
|
1206
2341
|
const rows = allRows(this._rows);
|
|
1207
2342
|
return rows.find(r => r.id === id);
|
|
1208
2343
|
}
|
|
1209
2344
|
|
|
1210
|
-
/**
|
|
1211
|
-
* @param {any} formField
|
|
1212
|
-
* @returns {FormRow}
|
|
2345
|
+
/**
|
|
2346
|
+
* @param {any} formField
|
|
2347
|
+
* @returns {FormRow}
|
|
1213
2348
|
*/
|
|
1214
2349
|
getRowForField(formField) {
|
|
1215
2350
|
return allRows(this._rows).find(r => {
|
|
@@ -1220,9 +2355,9 @@ class FormLayouter {
|
|
|
1220
2355
|
});
|
|
1221
2356
|
}
|
|
1222
2357
|
|
|
1223
|
-
/**
|
|
1224
|
-
* @param {String} formFieldId
|
|
1225
|
-
* @returns { Array<FormRow> }
|
|
2358
|
+
/**
|
|
2359
|
+
* @param {String} formFieldId
|
|
2360
|
+
* @returns { Array<FormRow> }
|
|
1226
2361
|
*/
|
|
1227
2362
|
getRows(formFieldId) {
|
|
1228
2363
|
const rowsForField = this._rows.find(r => formFieldId === r.formFieldId);
|
|
@@ -1232,22 +2367,22 @@ class FormLayouter {
|
|
|
1232
2367
|
return rowsForField.rows;
|
|
1233
2368
|
}
|
|
1234
2369
|
|
|
1235
|
-
/**
|
|
1236
|
-
* @returns {string}
|
|
2370
|
+
/**
|
|
2371
|
+
* @returns {string}
|
|
1237
2372
|
*/
|
|
1238
2373
|
nextRowId() {
|
|
1239
2374
|
return this._ids.nextPrefixed('Row_');
|
|
1240
2375
|
}
|
|
1241
2376
|
|
|
1242
|
-
/**
|
|
1243
|
-
* @param {any} formField
|
|
2377
|
+
/**
|
|
2378
|
+
* @param {any} formField
|
|
1244
2379
|
*/
|
|
1245
2380
|
calculateLayout(formField) {
|
|
1246
2381
|
const {
|
|
1247
2382
|
type,
|
|
1248
2383
|
components
|
|
1249
2384
|
} = formField;
|
|
1250
|
-
if (type !== 'default' || !components) {
|
|
2385
|
+
if (type !== 'default' && type !== 'group' || !components) {
|
|
1251
2386
|
return;
|
|
1252
2387
|
}
|
|
1253
2388
|
|
|
@@ -1269,363 +2404,85 @@ class FormLayouter {
|
|
|
1269
2404
|
rows: this._rows
|
|
1270
2405
|
});
|
|
1271
2406
|
}
|
|
1272
|
-
clear() {
|
|
1273
|
-
this._rows = [];
|
|
1274
|
-
this._ids.clear();
|
|
1275
|
-
|
|
1276
|
-
// fire event to notify interested parties
|
|
1277
|
-
this._eventBus.fire('form.layoutCleared');
|
|
1278
|
-
}
|
|
1279
|
-
}
|
|
1280
|
-
FormLayouter.$inject = ['eventBus'];
|
|
1281
|
-
|
|
1282
|
-
// helpers //////
|
|
1283
|
-
|
|
1284
|
-
function groupByRow(components, ids) {
|
|
1285
|
-
return groupBy(components, c => {
|
|
1286
|
-
// mitigate missing row by creating new (handle legacy)
|
|
1287
|
-
const {
|
|
1288
|
-
layout
|
|
1289
|
-
} = c;
|
|
1290
|
-
if (!layout || !layout.row) {
|
|
1291
|
-
return ids.nextPrefixed('Row_');
|
|
1292
|
-
}
|
|
1293
|
-
return layout.row;
|
|
1294
|
-
});
|
|
1295
|
-
}
|
|
1296
|
-
|
|
1297
|
-
/**
|
|
1298
|
-
* @param {Array<FormRows>} formRows
|
|
1299
|
-
* @returns {Array<FormRow>}
|
|
1300
|
-
*/
|
|
1301
|
-
function allRows(formRows) {
|
|
1302
|
-
return flatten(formRows.map(c => c.rows));
|
|
1303
|
-
}
|
|
1304
|
-
|
|
1305
|
-
// config ///////////////////
|
|
1306
|
-
|
|
1307
|
-
const MINUTES_IN_DAY = 60 * 24;
|
|
1308
|
-
const DATETIME_SUBTYPES = {
|
|
1309
|
-
DATE: 'date',
|
|
1310
|
-
TIME: 'time',
|
|
1311
|
-
DATETIME: 'datetime'
|
|
1312
|
-
};
|
|
1313
|
-
const TIME_SERIALISING_FORMATS = {
|
|
1314
|
-
UTC_OFFSET: 'utc_offset',
|
|
1315
|
-
UTC_NORMALIZED: 'utc_normalized',
|
|
1316
|
-
NO_TIMEZONE: 'no_timezone'
|
|
1317
|
-
};
|
|
1318
|
-
const DATETIME_SUBTYPES_LABELS = {
|
|
1319
|
-
[DATETIME_SUBTYPES.DATE]: 'Date',
|
|
1320
|
-
[DATETIME_SUBTYPES.TIME]: 'Time',
|
|
1321
|
-
[DATETIME_SUBTYPES.DATETIME]: 'Date & Time'
|
|
1322
|
-
};
|
|
1323
|
-
const TIME_SERIALISINGFORMAT_LABELS = {
|
|
1324
|
-
[TIME_SERIALISING_FORMATS.UTC_OFFSET]: 'UTC offset',
|
|
1325
|
-
[TIME_SERIALISING_FORMATS.UTC_NORMALIZED]: 'UTC normalized',
|
|
1326
|
-
[TIME_SERIALISING_FORMATS.NO_TIMEZONE]: 'No timezone'
|
|
1327
|
-
};
|
|
1328
|
-
const DATETIME_SUBTYPE_PATH = ['subtype'];
|
|
1329
|
-
const DATE_LABEL_PATH = ['dateLabel'];
|
|
1330
|
-
const DATE_DISALLOW_PAST_PATH = ['disallowPassedDates'];
|
|
1331
|
-
const TIME_LABEL_PATH = ['timeLabel'];
|
|
1332
|
-
const TIME_USE24H_PATH = ['use24h'];
|
|
1333
|
-
const TIME_INTERVAL_PATH = ['timeInterval'];
|
|
1334
|
-
const TIME_SERIALISING_FORMAT_PATH = ['timeSerializingFormat'];
|
|
1335
|
-
|
|
1336
|
-
// config ///////////////////
|
|
1337
|
-
|
|
1338
|
-
const VALUES_SOURCES = {
|
|
1339
|
-
STATIC: 'static',
|
|
1340
|
-
INPUT: 'input',
|
|
1341
|
-
EXPRESSION: 'expression'
|
|
1342
|
-
};
|
|
1343
|
-
const VALUES_SOURCE_DEFAULT = VALUES_SOURCES.STATIC;
|
|
1344
|
-
const VALUES_SOURCES_LABELS = {
|
|
1345
|
-
[VALUES_SOURCES.STATIC]: 'Static',
|
|
1346
|
-
[VALUES_SOURCES.INPUT]: 'Input data',
|
|
1347
|
-
[VALUES_SOURCES.EXPRESSION]: 'Expression'
|
|
1348
|
-
};
|
|
1349
|
-
const VALUES_SOURCES_PATHS = {
|
|
1350
|
-
[VALUES_SOURCES.STATIC]: ['values'],
|
|
1351
|
-
[VALUES_SOURCES.INPUT]: ['valuesKey'],
|
|
1352
|
-
[VALUES_SOURCES.EXPRESSION]: ['valuesExpression']
|
|
1353
|
-
};
|
|
1354
|
-
const VALUES_SOURCES_DEFAULTS = {
|
|
1355
|
-
[VALUES_SOURCES.STATIC]: [{
|
|
1356
|
-
label: 'Value',
|
|
1357
|
-
value: 'value'
|
|
1358
|
-
}],
|
|
1359
|
-
[VALUES_SOURCES.INPUT]: '',
|
|
1360
|
-
[VALUES_SOURCES.EXPRESSION]: '='
|
|
1361
|
-
};
|
|
1362
|
-
|
|
1363
|
-
// helpers ///////////////////
|
|
1364
|
-
|
|
1365
|
-
function getValuesSource(field) {
|
|
1366
|
-
for (const source of Object.values(VALUES_SOURCES)) {
|
|
1367
|
-
if (get(field, VALUES_SOURCES_PATHS[source]) !== undefined) {
|
|
1368
|
-
return source;
|
|
1369
|
-
}
|
|
1370
|
-
}
|
|
1371
|
-
return VALUES_SOURCE_DEFAULT;
|
|
1372
|
-
}
|
|
1373
|
-
|
|
1374
|
-
function createInjector(bootstrapModules) {
|
|
1375
|
-
const injector = new Injector(bootstrapModules);
|
|
1376
|
-
injector.init();
|
|
1377
|
-
return injector;
|
|
1378
|
-
}
|
|
1379
|
-
|
|
1380
|
-
/**
|
|
1381
|
-
* @param {string?} prefix
|
|
1382
|
-
*
|
|
1383
|
-
* @returns Element
|
|
1384
|
-
*/
|
|
1385
|
-
function createFormContainer(prefix = 'fjs') {
|
|
1386
|
-
const container = document.createElement('div');
|
|
1387
|
-
container.classList.add(`${prefix}-container`);
|
|
1388
|
-
return container;
|
|
1389
|
-
}
|
|
1390
|
-
|
|
1391
|
-
const EXPRESSION_PROPERTIES = ['alt', 'appearance.prefixAdorner', 'appearance.suffixAdorner', 'conditional.hide', 'description', 'label', 'source', 'readonly', 'text', 'validate.min', 'validate.max', 'validate.minLength', 'validate.maxLength', 'valuesExpression'];
|
|
1392
|
-
const TEMPLATE_PROPERTIES = ['alt', 'appearance.prefixAdorner', 'appearance.suffixAdorner', 'description', 'label', 'source', 'text'];
|
|
1393
|
-
function findErrors(errors, path) {
|
|
1394
|
-
return errors[pathStringify(path)];
|
|
1395
|
-
}
|
|
1396
|
-
function isRequired(field) {
|
|
1397
|
-
return field.required;
|
|
1398
|
-
}
|
|
1399
|
-
function pathParse(path) {
|
|
1400
|
-
if (!path) {
|
|
1401
|
-
return [];
|
|
1402
|
-
}
|
|
1403
|
-
return path.split('.').map(key => {
|
|
1404
|
-
return isNaN(parseInt(key)) ? key : parseInt(key);
|
|
1405
|
-
});
|
|
1406
|
-
}
|
|
1407
|
-
function pathsEqual(a, b) {
|
|
1408
|
-
return a && b && a.length === b.length && a.every((value, index) => value === b[index]);
|
|
1409
|
-
}
|
|
1410
|
-
function pathStringify(path) {
|
|
1411
|
-
if (!path) {
|
|
1412
|
-
return '';
|
|
1413
|
-
}
|
|
1414
|
-
return path.join('.');
|
|
1415
|
-
}
|
|
1416
|
-
const indices = {};
|
|
1417
|
-
function generateIndexForType(type) {
|
|
1418
|
-
if (type in indices) {
|
|
1419
|
-
indices[type]++;
|
|
1420
|
-
} else {
|
|
1421
|
-
indices[type] = 1;
|
|
1422
|
-
}
|
|
1423
|
-
return indices[type];
|
|
1424
|
-
}
|
|
1425
|
-
function generateIdForType(type) {
|
|
1426
|
-
return `${type}${generateIndexForType(type)}`;
|
|
1427
|
-
}
|
|
1428
|
-
|
|
1429
|
-
/**
|
|
1430
|
-
* @template T
|
|
1431
|
-
* @param {T} data
|
|
1432
|
-
* @param {(this: any, key: string, value: any) => any} [replacer]
|
|
1433
|
-
* @return {T}
|
|
1434
|
-
*/
|
|
1435
|
-
function clone(data, replacer) {
|
|
1436
|
-
return JSON.parse(JSON.stringify(data, replacer));
|
|
1437
|
-
}
|
|
1438
|
-
|
|
1439
|
-
/**
|
|
1440
|
-
* Parse the schema for input variables a form might make use of
|
|
1441
|
-
*
|
|
1442
|
-
* @param {any} schema
|
|
1443
|
-
*
|
|
1444
|
-
* @return {string[]}
|
|
1445
|
-
*/
|
|
1446
|
-
function getSchemaVariables(schema, expressionLanguage = new FeelExpressionLanguage(null), templating = new FeelersTemplating()) {
|
|
1447
|
-
if (!schema.components) {
|
|
1448
|
-
return [];
|
|
1449
|
-
}
|
|
1450
|
-
const variables = schema.components.reduce((variables, component) => {
|
|
1451
|
-
const {
|
|
1452
|
-
key,
|
|
1453
|
-
valuesKey,
|
|
1454
|
-
type
|
|
1455
|
-
} = component;
|
|
1456
|
-
if (['button'].includes(type)) {
|
|
1457
|
-
return variables;
|
|
1458
|
-
}
|
|
1459
|
-
if (key) {
|
|
1460
|
-
variables = [...variables, key];
|
|
1461
|
-
}
|
|
1462
|
-
if (valuesKey) {
|
|
1463
|
-
variables = [...variables, valuesKey];
|
|
1464
|
-
}
|
|
1465
|
-
EXPRESSION_PROPERTIES.forEach(prop => {
|
|
1466
|
-
const property = get(component, prop.split('.'));
|
|
1467
|
-
if (property && expressionLanguage.isExpression(property)) {
|
|
1468
|
-
const expressionVariables = expressionLanguage.getVariableNames(property, {
|
|
1469
|
-
type: 'expression'
|
|
1470
|
-
});
|
|
1471
|
-
variables = [...variables, ...expressionVariables];
|
|
1472
|
-
}
|
|
1473
|
-
});
|
|
1474
|
-
TEMPLATE_PROPERTIES.forEach(prop => {
|
|
1475
|
-
const property = get(component, prop.split('.'));
|
|
1476
|
-
if (property && !expressionLanguage.isExpression(property) && templating.isTemplate(property)) {
|
|
1477
|
-
const templateVariables = templating.getVariableNames(property);
|
|
1478
|
-
variables = [...variables, ...templateVariables];
|
|
1479
|
-
}
|
|
1480
|
-
});
|
|
1481
|
-
return variables;
|
|
1482
|
-
}, []);
|
|
1483
|
-
|
|
1484
|
-
// remove duplicates
|
|
1485
|
-
return Array.from(new Set(variables));
|
|
1486
|
-
}
|
|
1487
|
-
|
|
1488
|
-
class Importer {
|
|
1489
|
-
/**
|
|
1490
|
-
* @constructor
|
|
1491
|
-
* @param { import('../core').FormFieldRegistry } formFieldRegistry
|
|
1492
|
-
* @param { import('../render/FormFields').default } formFields
|
|
1493
|
-
* @param { import('../core').FormLayouter } formLayouter
|
|
1494
|
-
*/
|
|
1495
|
-
constructor(formFieldRegistry, formFields, formLayouter) {
|
|
1496
|
-
this._formFieldRegistry = formFieldRegistry;
|
|
1497
|
-
this._formFields = formFields;
|
|
1498
|
-
this._formLayouter = formLayouter;
|
|
1499
|
-
}
|
|
2407
|
+
clear() {
|
|
2408
|
+
this._rows = [];
|
|
2409
|
+
this._ids.clear();
|
|
1500
2410
|
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
* information to each field and adding it to the
|
|
1504
|
-
* form field registry.
|
|
1505
|
-
*
|
|
1506
|
-
* @param {any} schema
|
|
1507
|
-
* @param {any} [data]
|
|
1508
|
-
*
|
|
1509
|
-
* @return { { warnings: Array<any>, schema: any, data: any } }
|
|
1510
|
-
*/
|
|
1511
|
-
importSchema(schema, data = {}) {
|
|
1512
|
-
// TODO: Add warnings - https://github.com/bpmn-io/form-js/issues/289
|
|
1513
|
-
const warnings = [];
|
|
1514
|
-
try {
|
|
1515
|
-
this._formLayouter.clear();
|
|
1516
|
-
const importedSchema = this.importFormField(clone(schema)),
|
|
1517
|
-
initializedData = this.initializeFieldValues(clone(data));
|
|
1518
|
-
this._formLayouter.calculateLayout(clone(importedSchema));
|
|
1519
|
-
return {
|
|
1520
|
-
warnings,
|
|
1521
|
-
schema: importedSchema,
|
|
1522
|
-
data: initializedData
|
|
1523
|
-
};
|
|
1524
|
-
} catch (err) {
|
|
1525
|
-
err.warnings = warnings;
|
|
1526
|
-
throw err;
|
|
1527
|
-
}
|
|
2411
|
+
// fire event to notify interested parties
|
|
2412
|
+
this._eventBus.fire('form.layoutCleared');
|
|
1528
2413
|
}
|
|
2414
|
+
}
|
|
2415
|
+
FormLayouter.$inject = ['eventBus'];
|
|
1529
2416
|
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
*/
|
|
1536
|
-
importFormField(formField, parentId) {
|
|
2417
|
+
// helpers //////
|
|
2418
|
+
|
|
2419
|
+
function groupByRow(components, ids) {
|
|
2420
|
+
return groupBy(components, c => {
|
|
2421
|
+
// mitigate missing row by creating new (handle legacy)
|
|
1537
2422
|
const {
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
} = formField;
|
|
1543
|
-
if (parentId) {
|
|
1544
|
-
// set form field parent
|
|
1545
|
-
formField._parent = parentId;
|
|
1546
|
-
}
|
|
1547
|
-
if (!this._formFields.get(type)) {
|
|
1548
|
-
throw new Error(`form field of type <${type}> not supported`);
|
|
2423
|
+
layout
|
|
2424
|
+
} = c;
|
|
2425
|
+
if (!layout || !layout.row) {
|
|
2426
|
+
return ids.nextPrefixed('Row_');
|
|
1549
2427
|
}
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
throw new Error(`form field with key <${key}> already exists`);
|
|
1554
|
-
}
|
|
1555
|
-
this._formFieldRegistry._keys.claim(key, formField);
|
|
2428
|
+
return layout.row;
|
|
2429
|
+
});
|
|
2430
|
+
}
|
|
1556
2431
|
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
// validate <id> uniqueness
|
|
1565
|
-
if (this._formFieldRegistry._ids.assigned(id)) {
|
|
1566
|
-
throw new Error(`form field with id <${id}> already exists`);
|
|
1567
|
-
}
|
|
1568
|
-
this._formFieldRegistry._ids.claim(id, formField);
|
|
1569
|
-
}
|
|
2432
|
+
/**
|
|
2433
|
+
* @param {Array<FormRows>} formRows
|
|
2434
|
+
* @returns {Array<FormRow>}
|
|
2435
|
+
*/
|
|
2436
|
+
function allRows(formRows) {
|
|
2437
|
+
return flatten(formRows.map(c => c.rows));
|
|
2438
|
+
}
|
|
1570
2439
|
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
this.
|
|
1574
|
-
|
|
1575
|
-
|
|
2440
|
+
class FormFieldRegistry {
|
|
2441
|
+
constructor(eventBus) {
|
|
2442
|
+
this._eventBus = eventBus;
|
|
2443
|
+
this._formFields = {};
|
|
2444
|
+
eventBus.on('form.clear', () => this.clear());
|
|
2445
|
+
this._ids = new Ids([32, 36, 1]);
|
|
2446
|
+
}
|
|
2447
|
+
add(formField) {
|
|
2448
|
+
const {
|
|
2449
|
+
id
|
|
2450
|
+
} = formField;
|
|
2451
|
+
if (this._formFields[id]) {
|
|
2452
|
+
throw new Error(`form field with ID ${id} already exists`);
|
|
1576
2453
|
}
|
|
1577
|
-
|
|
2454
|
+
this._eventBus.fire('formField.add', {
|
|
2455
|
+
formField
|
|
2456
|
+
});
|
|
2457
|
+
this._formFields[id] = formField;
|
|
1578
2458
|
}
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
2459
|
+
remove(formField) {
|
|
2460
|
+
const {
|
|
2461
|
+
id
|
|
2462
|
+
} = formField;
|
|
2463
|
+
if (!this._formFields[id]) {
|
|
2464
|
+
return;
|
|
2465
|
+
}
|
|
2466
|
+
this._eventBus.fire('formField.remove', {
|
|
2467
|
+
formField
|
|
1582
2468
|
});
|
|
2469
|
+
delete this._formFields[id];
|
|
1583
2470
|
}
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
} = formField;
|
|
1597
|
-
|
|
1598
|
-
// try to get value from data
|
|
1599
|
-
// if unavailable - try to get default value from form field
|
|
1600
|
-
// if unavailable - get empty value from form field
|
|
1601
|
-
|
|
1602
|
-
if (_path) {
|
|
1603
|
-
const {
|
|
1604
|
-
config: fieldConfig
|
|
1605
|
-
} = this._formFields.get(type);
|
|
1606
|
-
let valueData = get(data, _path);
|
|
1607
|
-
if (!isUndefined(valueData) && fieldConfig.sanitizeValue) {
|
|
1608
|
-
valueData = fieldConfig.sanitizeValue({
|
|
1609
|
-
formField,
|
|
1610
|
-
data,
|
|
1611
|
-
value: valueData
|
|
1612
|
-
});
|
|
1613
|
-
}
|
|
1614
|
-
const initializedFieldValue = !isUndefined(valueData) ? valueData : !isUndefined(defaultValue) ? defaultValue : fieldConfig.emptyValue;
|
|
1615
|
-
initializedData = {
|
|
1616
|
-
...initializedData,
|
|
1617
|
-
[_path[0]]: initializedFieldValue
|
|
1618
|
-
};
|
|
1619
|
-
}
|
|
1620
|
-
return initializedData;
|
|
1621
|
-
}, data);
|
|
2471
|
+
get(id) {
|
|
2472
|
+
return this._formFields[id];
|
|
2473
|
+
}
|
|
2474
|
+
getAll() {
|
|
2475
|
+
return Object.values(this._formFields);
|
|
2476
|
+
}
|
|
2477
|
+
forEach(callback) {
|
|
2478
|
+
this.getAll().forEach(formField => callback(formField));
|
|
2479
|
+
}
|
|
2480
|
+
clear() {
|
|
2481
|
+
this._formFields = {};
|
|
2482
|
+
this._ids.clear();
|
|
1622
2483
|
}
|
|
1623
2484
|
}
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
var importModule = {
|
|
1627
|
-
importer: ['type', Importer]
|
|
1628
|
-
};
|
|
2485
|
+
FormFieldRegistry.$inject = ['eventBus'];
|
|
1629
2486
|
|
|
1630
2487
|
function formFieldClasses(type, {
|
|
1631
2488
|
errors = [],
|
|
@@ -1659,7 +2516,7 @@ function prefixId(id, formId) {
|
|
|
1659
2516
|
return `fjs-form-${id}`;
|
|
1660
2517
|
}
|
|
1661
2518
|
|
|
1662
|
-
const type$
|
|
2519
|
+
const type$c = 'button';
|
|
1663
2520
|
function Button(props) {
|
|
1664
2521
|
const {
|
|
1665
2522
|
disabled,
|
|
@@ -1669,7 +2526,7 @@ function Button(props) {
|
|
|
1669
2526
|
action = 'submit'
|
|
1670
2527
|
} = field;
|
|
1671
2528
|
return jsx("div", {
|
|
1672
|
-
class: formFieldClasses(type$
|
|
2529
|
+
class: formFieldClasses(type$c),
|
|
1673
2530
|
children: jsx("button", {
|
|
1674
2531
|
class: "fjs-button",
|
|
1675
2532
|
type: action,
|
|
@@ -1679,8 +2536,8 @@ function Button(props) {
|
|
|
1679
2536
|
});
|
|
1680
2537
|
}
|
|
1681
2538
|
Button.config = {
|
|
1682
|
-
type: type$
|
|
1683
|
-
keyed:
|
|
2539
|
+
type: type$c,
|
|
2540
|
+
keyed: false,
|
|
1684
2541
|
label: 'Button',
|
|
1685
2542
|
group: 'action',
|
|
1686
2543
|
create: (options = {}) => ({
|
|
@@ -1690,6 +2547,9 @@ Button.config = {
|
|
|
1690
2547
|
};
|
|
1691
2548
|
|
|
1692
2549
|
const FormRenderContext = createContext({
|
|
2550
|
+
EmptyRoot: props => {
|
|
2551
|
+
return null;
|
|
2552
|
+
},
|
|
1693
2553
|
Empty: props => {
|
|
1694
2554
|
return null;
|
|
1695
2555
|
},
|
|
@@ -1719,15 +2579,19 @@ const FormRenderContext = createContext({
|
|
|
1719
2579
|
class: props.class,
|
|
1720
2580
|
children: props.children
|
|
1721
2581
|
});
|
|
2582
|
+
},
|
|
2583
|
+
hoveredId: [],
|
|
2584
|
+
setHoveredId: newValue => {
|
|
2585
|
+
console.log(`setHoveredId not defined, called with '${newValue}'`);
|
|
1722
2586
|
}
|
|
1723
2587
|
});
|
|
1724
2588
|
var FormRenderContext$1 = FormRenderContext;
|
|
1725
2589
|
|
|
1726
|
-
/**
|
|
1727
|
-
* @param {string} type
|
|
1728
|
-
* @param {boolean} [strict]
|
|
1729
|
-
*
|
|
1730
|
-
* @returns {any}
|
|
2590
|
+
/**
|
|
2591
|
+
* @param {string} type
|
|
2592
|
+
* @param {boolean} [strict]
|
|
2593
|
+
*
|
|
2594
|
+
* @returns {any}
|
|
1731
2595
|
*/
|
|
1732
2596
|
function getService(type, strict) {}
|
|
1733
2597
|
const FormContext = createContext({
|
|
@@ -1743,10 +2607,10 @@ function useService(type, strict) {
|
|
|
1743
2607
|
return getService(type, strict);
|
|
1744
2608
|
}
|
|
1745
2609
|
|
|
1746
|
-
/**
|
|
1747
|
-
* Returns the conditionally filtered data of a form reactively.
|
|
1748
|
-
* Memoised to minimize re-renders
|
|
1749
|
-
*
|
|
2610
|
+
/**
|
|
2611
|
+
* Returns the conditionally filtered data of a form reactively.
|
|
2612
|
+
* Memoised to minimize re-renders
|
|
2613
|
+
*
|
|
1750
2614
|
*/
|
|
1751
2615
|
function useFilteredFormData() {
|
|
1752
2616
|
const {
|
|
@@ -1763,12 +2627,12 @@ function useFilteredFormData() {
|
|
|
1763
2627
|
}, [conditionChecker, data, initialData]);
|
|
1764
2628
|
}
|
|
1765
2629
|
|
|
1766
|
-
/**
|
|
1767
|
-
* Evaluate if condition is met reactively based on the conditionChecker and form data.
|
|
1768
|
-
*
|
|
1769
|
-
* @param {string | undefined} condition
|
|
1770
|
-
*
|
|
1771
|
-
* @returns {boolean} true if condition is met or no condition or condition checker exists
|
|
2630
|
+
/**
|
|
2631
|
+
* Evaluate if condition is met reactively based on the conditionChecker and form data.
|
|
2632
|
+
*
|
|
2633
|
+
* @param {string | undefined} condition
|
|
2634
|
+
*
|
|
2635
|
+
* @returns {boolean} true if condition is met or no condition or condition checker exists
|
|
1772
2636
|
*/
|
|
1773
2637
|
function useCondition(condition) {
|
|
1774
2638
|
const conditionChecker = useService('conditionChecker', false);
|
|
@@ -1778,13 +2642,13 @@ function useCondition(condition) {
|
|
|
1778
2642
|
}, [conditionChecker, condition, filteredData]);
|
|
1779
2643
|
}
|
|
1780
2644
|
|
|
1781
|
-
/**
|
|
1782
|
-
* Evaluate a string reactively based on the expressionLanguage and form data.
|
|
1783
|
-
* If the string is not an expression, it is returned as is.
|
|
1784
|
-
* Memoised to minimize re-renders.
|
|
1785
|
-
*
|
|
1786
|
-
* @param {string} value
|
|
1787
|
-
*
|
|
2645
|
+
/**
|
|
2646
|
+
* Evaluate a string reactively based on the expressionLanguage and form data.
|
|
2647
|
+
* If the string is not an expression, it is returned as is.
|
|
2648
|
+
* Memoised to minimize re-renders.
|
|
2649
|
+
*
|
|
2650
|
+
* @param {string} value
|
|
2651
|
+
*
|
|
1788
2652
|
*/
|
|
1789
2653
|
function useExpressionEvaluation(value) {
|
|
1790
2654
|
const formData = useFilteredFormData();
|
|
@@ -1813,16 +2677,16 @@ function useKeyDownAction(targetKey, action, listenerElement = window) {
|
|
|
1813
2677
|
});
|
|
1814
2678
|
}
|
|
1815
2679
|
|
|
1816
|
-
/**
|
|
1817
|
-
* Retrieve readonly value of a form field, given it can be an
|
|
1818
|
-
* expression optionally or configured globally.
|
|
1819
|
-
*
|
|
1820
|
-
* @typedef { import('../../types').FormProperties } FormProperties
|
|
1821
|
-
*
|
|
1822
|
-
* @param {any} formField
|
|
1823
|
-
* @param {FormProperties} properties
|
|
1824
|
-
*
|
|
1825
|
-
* @returns {boolean}
|
|
2680
|
+
/**
|
|
2681
|
+
* Retrieve readonly value of a form field, given it can be an
|
|
2682
|
+
* expression optionally or configured globally.
|
|
2683
|
+
*
|
|
2684
|
+
* @typedef { import('../../types').FormProperties } FormProperties
|
|
2685
|
+
*
|
|
2686
|
+
* @param {any} formField
|
|
2687
|
+
* @param {FormProperties} properties
|
|
2688
|
+
*
|
|
2689
|
+
* @returns {boolean}
|
|
1826
2690
|
*/
|
|
1827
2691
|
function useReadonly(formField, properties = {}) {
|
|
1828
2692
|
const expressionLanguage = useService('expressionLanguage');
|
|
@@ -1840,16 +2704,16 @@ function useReadonly(formField, properties = {}) {
|
|
|
1840
2704
|
return readonly || false;
|
|
1841
2705
|
}
|
|
1842
2706
|
|
|
1843
|
-
/**
|
|
1844
|
-
* Template a string reactively based on form data. If the string is not a template, it is returned as is.
|
|
1845
|
-
* Memoised to minimize re-renders
|
|
1846
|
-
*
|
|
1847
|
-
* @param {string} value
|
|
1848
|
-
* @param {Object} options
|
|
1849
|
-
* @param {boolean} [options.debug = false]
|
|
1850
|
-
* @param {boolean} [options.strict = false]
|
|
1851
|
-
* @param {Function} [options.buildDebugString]
|
|
1852
|
-
*
|
|
2707
|
+
/**
|
|
2708
|
+
* Template a string reactively based on form data. If the string is not a template, it is returned as is.
|
|
2709
|
+
* Memoised to minimize re-renders
|
|
2710
|
+
*
|
|
2711
|
+
* @param {string} value
|
|
2712
|
+
* @param {Object} options
|
|
2713
|
+
* @param {boolean} [options.debug = false]
|
|
2714
|
+
* @param {boolean} [options.strict = false]
|
|
2715
|
+
* @param {Function} [options.buildDebugString]
|
|
2716
|
+
*
|
|
1853
2717
|
*/
|
|
1854
2718
|
function useTemplateEvaluation(value, options) {
|
|
1855
2719
|
const filteredData = useFilteredFormData();
|
|
@@ -1862,17 +2726,17 @@ function useTemplateEvaluation(value, options) {
|
|
|
1862
2726
|
}, [filteredData, templating, value, options]);
|
|
1863
2727
|
}
|
|
1864
2728
|
|
|
1865
|
-
/**
|
|
1866
|
-
* Template a string reactively based on form data. If the string is not a template, it is returned as is.
|
|
1867
|
-
* If the string contains multiple lines, only the first line is returned.
|
|
1868
|
-
* Memoised to minimize re-renders
|
|
1869
|
-
*
|
|
1870
|
-
* @param {string} value
|
|
1871
|
-
* @param {Object} [options]
|
|
1872
|
-
* @param {boolean} [options.debug = false]
|
|
1873
|
-
* @param {boolean} [options.strict = false]
|
|
1874
|
-
* @param {Function} [options.buildDebugString]
|
|
1875
|
-
*
|
|
2729
|
+
/**
|
|
2730
|
+
* Template a string reactively based on form data. If the string is not a template, it is returned as is.
|
|
2731
|
+
* If the string contains multiple lines, only the first line is returned.
|
|
2732
|
+
* Memoised to minimize re-renders
|
|
2733
|
+
*
|
|
2734
|
+
* @param {string} value
|
|
2735
|
+
* @param {Object} [options]
|
|
2736
|
+
* @param {boolean} [options.debug = false]
|
|
2737
|
+
* @param {boolean} [options.strict = false]
|
|
2738
|
+
* @param {Function} [options.buildDebugString]
|
|
2739
|
+
*
|
|
1876
2740
|
*/
|
|
1877
2741
|
function useSingleLineTemplateEvaluation(value, options = {}) {
|
|
1878
2742
|
const evaluatedTemplate = useTemplateEvaluation(value, options);
|
|
@@ -1939,11 +2803,12 @@ function Label(props) {
|
|
|
1939
2803
|
});
|
|
1940
2804
|
}
|
|
1941
2805
|
|
|
1942
|
-
const type$
|
|
2806
|
+
const type$b = 'checkbox';
|
|
1943
2807
|
function Checkbox(props) {
|
|
1944
2808
|
const {
|
|
1945
2809
|
disabled,
|
|
1946
2810
|
errors = [],
|
|
2811
|
+
onBlur,
|
|
1947
2812
|
field,
|
|
1948
2813
|
readonly,
|
|
1949
2814
|
value = false
|
|
@@ -1970,7 +2835,7 @@ function Checkbox(props) {
|
|
|
1970
2835
|
} = useContext(FormContext$1);
|
|
1971
2836
|
const errorMessageId = errors.length === 0 ? undefined : `${prefixId(id, formId)}-error-message`;
|
|
1972
2837
|
return jsxs("div", {
|
|
1973
|
-
class: classNames(formFieldClasses(type$
|
|
2838
|
+
class: classNames(formFieldClasses(type$b, {
|
|
1974
2839
|
errors,
|
|
1975
2840
|
disabled,
|
|
1976
2841
|
readonly
|
|
@@ -1989,6 +2854,7 @@ function Checkbox(props) {
|
|
|
1989
2854
|
id: prefixId(id, formId),
|
|
1990
2855
|
type: "checkbox",
|
|
1991
2856
|
onChange: onChange,
|
|
2857
|
+
onBlur: onBlur,
|
|
1992
2858
|
"aria-describedby": errorMessageId
|
|
1993
2859
|
})
|
|
1994
2860
|
}), jsx(Description, {
|
|
@@ -2000,7 +2866,7 @@ function Checkbox(props) {
|
|
|
2000
2866
|
});
|
|
2001
2867
|
}
|
|
2002
2868
|
Checkbox.config = {
|
|
2003
|
-
type: type$
|
|
2869
|
+
type: type$b,
|
|
2004
2870
|
keyed: true,
|
|
2005
2871
|
label: 'Checkbox',
|
|
2006
2872
|
group: 'selection',
|
|
@@ -2058,9 +2924,24 @@ function _isReadableType(value) {
|
|
|
2058
2924
|
function _isValueSomething(value) {
|
|
2059
2925
|
return value || value === 0 || value === false;
|
|
2060
2926
|
}
|
|
2927
|
+
function createEmptyOptions(options = {}) {
|
|
2928
|
+
const defaults = {};
|
|
2061
2929
|
|
|
2062
|
-
|
|
2063
|
-
|
|
2930
|
+
// provide default values if valuesKey and valuesExpression are not set
|
|
2931
|
+
if (!options.valuesKey && !options.valuesExpression) {
|
|
2932
|
+
defaults.values = [{
|
|
2933
|
+
label: 'Value',
|
|
2934
|
+
value: 'value'
|
|
2935
|
+
}];
|
|
2936
|
+
}
|
|
2937
|
+
return {
|
|
2938
|
+
...defaults,
|
|
2939
|
+
...options
|
|
2940
|
+
};
|
|
2941
|
+
}
|
|
2942
|
+
|
|
2943
|
+
/**
|
|
2944
|
+
* @enum { String }
|
|
2064
2945
|
*/
|
|
2065
2946
|
const LOAD_STATES = {
|
|
2066
2947
|
LOADING: 'loading',
|
|
@@ -2068,17 +2949,17 @@ const LOAD_STATES = {
|
|
|
2068
2949
|
ERROR: 'error'
|
|
2069
2950
|
};
|
|
2070
2951
|
|
|
2071
|
-
/**
|
|
2072
|
-
* @typedef {Object} ValuesGetter
|
|
2073
|
-
* @property {Object[]} values - The values data
|
|
2074
|
-
* @property {(LOAD_STATES)} state - The values data's loading state, to use for conditional rendering
|
|
2952
|
+
/**
|
|
2953
|
+
* @typedef {Object} ValuesGetter
|
|
2954
|
+
* @property {Object[]} values - The values data
|
|
2955
|
+
* @property {(LOAD_STATES)} state - The values data's loading state, to use for conditional rendering
|
|
2075
2956
|
*/
|
|
2076
2957
|
|
|
2077
|
-
/**
|
|
2078
|
-
* A hook to load values for single and multiselect components.
|
|
2079
|
-
*
|
|
2080
|
-
* @param {Object} field - The form field to handle values for
|
|
2081
|
-
* @return {ValuesGetter} valuesGetter - A values getter object providing loading state and values
|
|
2958
|
+
/**
|
|
2959
|
+
* A hook to load values for single and multiselect components.
|
|
2960
|
+
*
|
|
2961
|
+
* @param {Object} field - The form field to handle values for
|
|
2962
|
+
* @return {ValuesGetter} valuesGetter - A values getter object providing loading state and values
|
|
2082
2963
|
*/
|
|
2083
2964
|
function useValuesAsync (field) {
|
|
2084
2965
|
const {
|
|
@@ -2343,11 +3224,12 @@ function sanitizeMultiSelectValue(options) {
|
|
|
2343
3224
|
}
|
|
2344
3225
|
}
|
|
2345
3226
|
|
|
2346
|
-
const type$
|
|
3227
|
+
const type$a = 'checklist';
|
|
2347
3228
|
function Checklist(props) {
|
|
2348
3229
|
const {
|
|
2349
3230
|
disabled,
|
|
2350
3231
|
errors = [],
|
|
3232
|
+
onBlur,
|
|
2351
3233
|
field,
|
|
2352
3234
|
readonly,
|
|
2353
3235
|
value = []
|
|
@@ -2358,6 +3240,7 @@ function Checklist(props) {
|
|
|
2358
3240
|
label,
|
|
2359
3241
|
validate = {}
|
|
2360
3242
|
} = field;
|
|
3243
|
+
const outerDivRef = useRef();
|
|
2361
3244
|
const {
|
|
2362
3245
|
required
|
|
2363
3246
|
} = validate;
|
|
@@ -2373,6 +3256,12 @@ function Checklist(props) {
|
|
|
2373
3256
|
value: newValue
|
|
2374
3257
|
});
|
|
2375
3258
|
};
|
|
3259
|
+
const onCheckboxBlur = e => {
|
|
3260
|
+
if (outerDivRef.current.contains(e.relatedTarget)) {
|
|
3261
|
+
return;
|
|
3262
|
+
}
|
|
3263
|
+
onBlur();
|
|
3264
|
+
};
|
|
2376
3265
|
const {
|
|
2377
3266
|
state: loadState,
|
|
2378
3267
|
values: options
|
|
@@ -2382,11 +3271,12 @@ function Checklist(props) {
|
|
|
2382
3271
|
} = useContext(FormContext$1);
|
|
2383
3272
|
const errorMessageId = errors.length === 0 ? undefined : `${prefixId(id, formId)}-error-message`;
|
|
2384
3273
|
return jsxs("div", {
|
|
2385
|
-
class: classNames(formFieldClasses(type$
|
|
3274
|
+
class: classNames(formFieldClasses(type$a, {
|
|
2386
3275
|
errors,
|
|
2387
3276
|
disabled,
|
|
2388
3277
|
readonly
|
|
2389
3278
|
})),
|
|
3279
|
+
ref: outerDivRef,
|
|
2390
3280
|
children: [jsx(Label, {
|
|
2391
3281
|
label: label,
|
|
2392
3282
|
required: required
|
|
@@ -2406,6 +3296,7 @@ function Checklist(props) {
|
|
|
2406
3296
|
id: prefixId(`${id}-${index}`, formId),
|
|
2407
3297
|
type: "checkbox",
|
|
2408
3298
|
onClick: () => toggleCheckbox(v.value),
|
|
3299
|
+
onBlur: onCheckboxBlur,
|
|
2409
3300
|
"aria-describedby": errorMessageId
|
|
2410
3301
|
})
|
|
2411
3302
|
}, `${id}-${index}`);
|
|
@@ -2418,27 +3309,13 @@ function Checklist(props) {
|
|
|
2418
3309
|
});
|
|
2419
3310
|
}
|
|
2420
3311
|
Checklist.config = {
|
|
2421
|
-
type: type$
|
|
3312
|
+
type: type$a,
|
|
2422
3313
|
keyed: true,
|
|
2423
3314
|
label: 'Checklist',
|
|
2424
3315
|
group: 'selection',
|
|
2425
3316
|
emptyValue: [],
|
|
2426
3317
|
sanitizeValue: sanitizeMultiSelectValue,
|
|
2427
|
-
create:
|
|
2428
|
-
const defaults = {};
|
|
2429
|
-
|
|
2430
|
-
// provide default values if valuesKey isn't set
|
|
2431
|
-
if (!options.valuesKey) {
|
|
2432
|
-
defaults.values = [{
|
|
2433
|
-
label: 'Value',
|
|
2434
|
-
value: 'value'
|
|
2435
|
-
}];
|
|
2436
|
-
}
|
|
2437
|
-
return {
|
|
2438
|
-
...defaults,
|
|
2439
|
-
...options
|
|
2440
|
-
};
|
|
2441
|
-
}
|
|
3318
|
+
create: createEmptyOptions
|
|
2442
3319
|
};
|
|
2443
3320
|
|
|
2444
3321
|
const noop$1 = () => false;
|
|
@@ -2448,8 +3325,11 @@ function FormField(props) {
|
|
|
2448
3325
|
onChange
|
|
2449
3326
|
} = props;
|
|
2450
3327
|
const formFields = useService('formFields'),
|
|
3328
|
+
viewerCommands = useService('viewerCommands', false),
|
|
3329
|
+
pathRegistry = useService('pathRegistry'),
|
|
2451
3330
|
form = useService('form');
|
|
2452
3331
|
const {
|
|
3332
|
+
initialData,
|
|
2453
3333
|
data,
|
|
2454
3334
|
errors,
|
|
2455
3335
|
properties
|
|
@@ -2463,12 +3343,23 @@ function FormField(props) {
|
|
|
2463
3343
|
if (!FormFieldComponent) {
|
|
2464
3344
|
throw new Error(`cannot render field <${field.type}>`);
|
|
2465
3345
|
}
|
|
2466
|
-
const
|
|
2467
|
-
const
|
|
3346
|
+
const valuePath = useMemo(() => pathRegistry.getValuePath(field), [field, pathRegistry]);
|
|
3347
|
+
const initialValue = useMemo(() => get(initialData, valuePath), [initialData, valuePath]);
|
|
2468
3348
|
const readonly = useReadonly(field, properties);
|
|
3349
|
+
const value = get(data, valuePath);
|
|
2469
3350
|
|
|
2470
3351
|
// add precedence: global readonly > form field disabled
|
|
2471
3352
|
const disabled = !properties.readOnly && (properties.disabled || field.disabled || false);
|
|
3353
|
+
const onBlur = useCallback(() => {
|
|
3354
|
+
if (viewerCommands) {
|
|
3355
|
+
viewerCommands.updateFieldValidation(field, value);
|
|
3356
|
+
}
|
|
3357
|
+
}, [viewerCommands, field, value]);
|
|
3358
|
+
useEffect(() => {
|
|
3359
|
+
if (viewerCommands && initialValue) {
|
|
3360
|
+
viewerCommands.updateFieldValidation(field, initialValue);
|
|
3361
|
+
}
|
|
3362
|
+
}, [viewerCommands, field, initialValue]);
|
|
2472
3363
|
const hidden = useCondition(field.conditional && field.conditional.hide || null);
|
|
2473
3364
|
if (hidden) {
|
|
2474
3365
|
return jsx(Empty, {});
|
|
@@ -2482,8 +3373,9 @@ function FormField(props) {
|
|
|
2482
3373
|
children: jsx(FormFieldComponent, {
|
|
2483
3374
|
...props,
|
|
2484
3375
|
disabled: disabled,
|
|
2485
|
-
errors:
|
|
3376
|
+
errors: errors[field.id],
|
|
2486
3377
|
onChange: disabled || readonly ? noop$1 : onChange,
|
|
3378
|
+
onBlur: disabled || readonly ? noop$1 : onBlur,
|
|
2487
3379
|
readonly: readonly,
|
|
2488
3380
|
value: value
|
|
2489
3381
|
})
|
|
@@ -2491,14 +3383,14 @@ function FormField(props) {
|
|
|
2491
3383
|
});
|
|
2492
3384
|
}
|
|
2493
3385
|
|
|
2494
|
-
function
|
|
3386
|
+
function Grid(props) {
|
|
2495
3387
|
const {
|
|
2496
3388
|
Children,
|
|
2497
|
-
Empty,
|
|
2498
3389
|
Row
|
|
2499
3390
|
} = useContext(FormRenderContext$1);
|
|
2500
3391
|
const {
|
|
2501
|
-
field
|
|
3392
|
+
field,
|
|
3393
|
+
Empty
|
|
2502
3394
|
} = props;
|
|
2503
3395
|
const {
|
|
2504
3396
|
id,
|
|
@@ -2535,7 +3427,20 @@ function Default(props) {
|
|
|
2535
3427
|
}), components.length ? null : jsx(Empty, {})]
|
|
2536
3428
|
});
|
|
2537
3429
|
}
|
|
2538
|
-
|
|
3430
|
+
|
|
3431
|
+
function FormComponent$1(props) {
|
|
3432
|
+
const {
|
|
3433
|
+
EmptyRoot
|
|
3434
|
+
} = useContext(FormRenderContext$1);
|
|
3435
|
+
const fullProps = {
|
|
3436
|
+
...props,
|
|
3437
|
+
Empty: EmptyRoot
|
|
3438
|
+
};
|
|
3439
|
+
return jsx(Grid, {
|
|
3440
|
+
...fullProps
|
|
3441
|
+
});
|
|
3442
|
+
}
|
|
3443
|
+
FormComponent$1.config = {
|
|
2539
3444
|
type: 'default',
|
|
2540
3445
|
keyed: false,
|
|
2541
3446
|
label: null,
|
|
@@ -2546,16 +3451,16 @@ Default.config = {
|
|
|
2546
3451
|
})
|
|
2547
3452
|
};
|
|
2548
3453
|
|
|
2549
|
-
var _path$
|
|
2550
|
-
function _extends$
|
|
3454
|
+
var _path$h;
|
|
3455
|
+
function _extends$k() { _extends$k = 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$k.apply(this, arguments); }
|
|
2551
3456
|
var SvgCalendar = function SvgCalendar(props) {
|
|
2552
|
-
return /*#__PURE__*/React.createElement("svg", _extends$
|
|
3457
|
+
return /*#__PURE__*/React.createElement("svg", _extends$k({
|
|
2553
3458
|
xmlns: "http://www.w3.org/2000/svg",
|
|
2554
3459
|
width: 14,
|
|
2555
3460
|
height: 15,
|
|
2556
3461
|
fill: "none",
|
|
2557
3462
|
viewBox: "0 0 28 30"
|
|
2558
|
-
}, props), _path$
|
|
3463
|
+
}, props), _path$h || (_path$h = /*#__PURE__*/React.createElement("path", {
|
|
2559
3464
|
fill: "currentColor",
|
|
2560
3465
|
fillRule: "evenodd",
|
|
2561
3466
|
d: "M19 2H9V0H7v2H2a2 2 0 0 0-2 2v24a2 2 0 0 0 2 2h24a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2h-5V0h-2v2ZM7 7V4H2v5h24V4h-5v3h-2V4H9v3H7Zm-5 4v17h24V11H2Z",
|
|
@@ -2564,6 +3469,74 @@ var SvgCalendar = function SvgCalendar(props) {
|
|
|
2564
3469
|
};
|
|
2565
3470
|
var CalendarIcon = SvgCalendar;
|
|
2566
3471
|
|
|
3472
|
+
/**
|
|
3473
|
+
* Returns date format for the provided locale.
|
|
3474
|
+
* If the locale is not provided, uses the browser's locale.
|
|
3475
|
+
*
|
|
3476
|
+
* @param {string} [locale] - The locale to get date format for.
|
|
3477
|
+
* @returns {string} The date format for the locale.
|
|
3478
|
+
*/
|
|
3479
|
+
function getLocaleDateFormat(locale = 'default') {
|
|
3480
|
+
const parts = new Intl.DateTimeFormat(locale).formatToParts(new Date(Date.UTC(2020, 5, 5)));
|
|
3481
|
+
return parts.map(part => {
|
|
3482
|
+
const len = part.value.length;
|
|
3483
|
+
switch (part.type) {
|
|
3484
|
+
case 'day':
|
|
3485
|
+
return 'd'.repeat(len);
|
|
3486
|
+
case 'month':
|
|
3487
|
+
return 'M'.repeat(len);
|
|
3488
|
+
case 'year':
|
|
3489
|
+
return 'y'.repeat(len);
|
|
3490
|
+
default:
|
|
3491
|
+
return part.value;
|
|
3492
|
+
}
|
|
3493
|
+
}).join('');
|
|
3494
|
+
}
|
|
3495
|
+
|
|
3496
|
+
/**
|
|
3497
|
+
* Returns readable date format for the provided locale.
|
|
3498
|
+
* If the locale is not provided, uses the browser's locale.
|
|
3499
|
+
*
|
|
3500
|
+
* @param {string} [locale] - The locale to get readable date format for.
|
|
3501
|
+
* @returns {string} The readable date format for the locale.
|
|
3502
|
+
*/
|
|
3503
|
+
function getLocaleReadableDateFormat(locale) {
|
|
3504
|
+
let format = getLocaleDateFormat(locale).toLowerCase();
|
|
3505
|
+
|
|
3506
|
+
// Ensure month is in 'mm' format
|
|
3507
|
+
if (!format.includes('mm')) {
|
|
3508
|
+
format = format.replace('m', 'mm');
|
|
3509
|
+
}
|
|
3510
|
+
|
|
3511
|
+
// Ensure day is in 'dd' format
|
|
3512
|
+
if (!format.includes('dd')) {
|
|
3513
|
+
format = format.replace('d', 'dd');
|
|
3514
|
+
}
|
|
3515
|
+
return format;
|
|
3516
|
+
}
|
|
3517
|
+
|
|
3518
|
+
/**
|
|
3519
|
+
* Returns flatpickr config for the provided locale.
|
|
3520
|
+
* If the locale is not provided, uses the browser's locale.
|
|
3521
|
+
*
|
|
3522
|
+
* @param {string} [locale] - The locale to get flatpickr config for.
|
|
3523
|
+
* @returns {object} The flatpickr config for the locale.
|
|
3524
|
+
*/
|
|
3525
|
+
function getLocaleDateFlatpickrConfig(locale) {
|
|
3526
|
+
return flatpickerizeDateFormat(getLocaleDateFormat(locale));
|
|
3527
|
+
}
|
|
3528
|
+
function flatpickerizeDateFormat(dateFormat) {
|
|
3529
|
+
const useLeadingZero = {
|
|
3530
|
+
day: dateFormat.includes('dd'),
|
|
3531
|
+
month: dateFormat.includes('MM'),
|
|
3532
|
+
year: dateFormat.includes('yyyy')
|
|
3533
|
+
};
|
|
3534
|
+
dateFormat = useLeadingZero.day ? dateFormat.replace('dd', 'd') : dateFormat.replace('d', 'j');
|
|
3535
|
+
dateFormat = useLeadingZero.month ? dateFormat.replace('MM', 'm') : dateFormat.replace('M', 'n');
|
|
3536
|
+
dateFormat = useLeadingZero.year ? dateFormat.replace('yyyy', 'Y') : dateFormat.replace('yy', 'y');
|
|
3537
|
+
return dateFormat;
|
|
3538
|
+
}
|
|
3539
|
+
|
|
2567
3540
|
function InputAdorner(props) {
|
|
2568
3541
|
const {
|
|
2569
3542
|
pre,
|
|
@@ -2607,6 +3580,7 @@ function Datepicker(props) {
|
|
|
2607
3580
|
id,
|
|
2608
3581
|
label,
|
|
2609
3582
|
collapseLabelOnEmpty,
|
|
3583
|
+
onDateTimeBlur,
|
|
2610
3584
|
formId,
|
|
2611
3585
|
required,
|
|
2612
3586
|
disabled,
|
|
@@ -2637,7 +3611,7 @@ function Datepicker(props) {
|
|
|
2637
3611
|
useEffect(() => {
|
|
2638
3612
|
let config = {
|
|
2639
3613
|
allowInput: true,
|
|
2640
|
-
dateFormat:
|
|
3614
|
+
dateFormat: getLocaleDateFlatpickrConfig(),
|
|
2641
3615
|
static: true,
|
|
2642
3616
|
clickOpens: false,
|
|
2643
3617
|
// TODO: support dates prior to 1900 (https://github.com/bpmn-io/form-js/issues/533)
|
|
@@ -2701,7 +3675,8 @@ function Datepicker(props) {
|
|
|
2701
3675
|
if (!isInputDirty || e.relatedTarget && e.relatedTarget.classList.contains('flatpickr-day')) return;
|
|
2702
3676
|
dateInputRef.current.dispatchEvent(ENTER_KEYDOWN_EVENT);
|
|
2703
3677
|
setIsInputDirty(false);
|
|
2704
|
-
|
|
3678
|
+
onDateTimeBlur(e);
|
|
3679
|
+
}, [isInputDirty, onDateTimeBlur]);
|
|
2705
3680
|
const fullId = `${prefixId(id, formId)}--date`;
|
|
2706
3681
|
return jsxs("div", {
|
|
2707
3682
|
class: "fjs-datetime-subsection",
|
|
@@ -2728,7 +3703,7 @@ function Datepicker(props) {
|
|
|
2728
3703
|
class: "fjs-input",
|
|
2729
3704
|
disabled: disabled,
|
|
2730
3705
|
readOnly: readonly,
|
|
2731
|
-
placeholder:
|
|
3706
|
+
placeholder: getLocaleReadableDateFormat(),
|
|
2732
3707
|
autoComplete: "off",
|
|
2733
3708
|
onFocus: onInputFocus,
|
|
2734
3709
|
onKeyDown: onInputKeyDown,
|
|
@@ -2743,19 +3718,19 @@ function Datepicker(props) {
|
|
|
2743
3718
|
});
|
|
2744
3719
|
}
|
|
2745
3720
|
|
|
2746
|
-
var _path$
|
|
2747
|
-
function _extends$
|
|
3721
|
+
var _path$g, _path2$4;
|
|
3722
|
+
function _extends$j() { _extends$j = 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$j.apply(this, arguments); }
|
|
2748
3723
|
var SvgClock = function SvgClock(props) {
|
|
2749
|
-
return /*#__PURE__*/React.createElement("svg", _extends$
|
|
3724
|
+
return /*#__PURE__*/React.createElement("svg", _extends$j({
|
|
2750
3725
|
xmlns: "http://www.w3.org/2000/svg",
|
|
2751
3726
|
width: 16,
|
|
2752
3727
|
height: 16,
|
|
2753
3728
|
fill: "none",
|
|
2754
3729
|
viewBox: "0 0 28 29"
|
|
2755
|
-
}, props), _path$
|
|
3730
|
+
}, props), _path$g || (_path$g = /*#__PURE__*/React.createElement("path", {
|
|
2756
3731
|
fill: "currentColor",
|
|
2757
3732
|
d: "M13 14.41 18.59 20 20 18.59l-5-5.01V5h-2v9.41Z"
|
|
2758
|
-
})), _path2$
|
|
3733
|
+
})), _path2$4 || (_path2$4 = /*#__PURE__*/React.createElement("path", {
|
|
2759
3734
|
fill: "currentColor",
|
|
2760
3735
|
fillRule: "evenodd",
|
|
2761
3736
|
d: "M6.222 25.64A14 14 0 1 0 21.778 2.36 14 14 0 0 0 6.222 25.64ZM7.333 4.023a12 12 0 1 1 13.334 19.955A12 12 0 0 1 7.333 4.022Z",
|
|
@@ -2864,6 +3839,7 @@ function Timepicker(props) {
|
|
|
2864
3839
|
id,
|
|
2865
3840
|
label,
|
|
2866
3841
|
collapseLabelOnEmpty,
|
|
3842
|
+
onDateTimeBlur,
|
|
2867
3843
|
formId,
|
|
2868
3844
|
required,
|
|
2869
3845
|
disabled,
|
|
@@ -2963,6 +3939,7 @@ function Timepicker(props) {
|
|
|
2963
3939
|
const onInputBlur = e => {
|
|
2964
3940
|
setDropdownIsOpen(false);
|
|
2965
3941
|
propagateRawToMinute();
|
|
3942
|
+
onDateTimeBlur(e);
|
|
2966
3943
|
};
|
|
2967
3944
|
const onDropdownValueSelected = value => {
|
|
2968
3945
|
setDropdownIsOpen(false);
|
|
@@ -3018,11 +3995,12 @@ function Timepicker(props) {
|
|
|
3018
3995
|
});
|
|
3019
3996
|
}
|
|
3020
3997
|
|
|
3021
|
-
const type$
|
|
3998
|
+
const type$9 = 'datetime';
|
|
3022
3999
|
function Datetime(props) {
|
|
3023
4000
|
const {
|
|
3024
4001
|
disabled,
|
|
3025
4002
|
errors = [],
|
|
4003
|
+
onBlur,
|
|
3026
4004
|
field,
|
|
3027
4005
|
onChange,
|
|
3028
4006
|
readonly,
|
|
@@ -3046,6 +4024,7 @@ function Datetime(props) {
|
|
|
3046
4024
|
const {
|
|
3047
4025
|
formId
|
|
3048
4026
|
} = useContext(FormContext$1);
|
|
4027
|
+
const dateTimeGroupRef = useRef();
|
|
3049
4028
|
const getNullDateTime = () => ({
|
|
3050
4029
|
date: new Date(Date.parse(null)),
|
|
3051
4030
|
time: null
|
|
@@ -3056,6 +4035,12 @@ function Datetime(props) {
|
|
|
3056
4035
|
const isValidTime = time => !isNaN(parseInt(time));
|
|
3057
4036
|
const useDatePicker = useMemo(() => subtype === DATETIME_SUBTYPES.DATE || subtype === DATETIME_SUBTYPES.DATETIME, [subtype]);
|
|
3058
4037
|
const useTimePicker = useMemo(() => subtype === DATETIME_SUBTYPES.TIME || subtype === DATETIME_SUBTYPES.DATETIME, [subtype]);
|
|
4038
|
+
const onDateTimeBlur = useCallback(e => {
|
|
4039
|
+
if (e.relatedTarget && dateTimeGroupRef.current.contains(e.relatedTarget)) {
|
|
4040
|
+
return;
|
|
4041
|
+
}
|
|
4042
|
+
onBlur();
|
|
4043
|
+
}, [onBlur]);
|
|
3059
4044
|
useEffect(() => {
|
|
3060
4045
|
let {
|
|
3061
4046
|
date,
|
|
@@ -3147,6 +4132,7 @@ function Datetime(props) {
|
|
|
3147
4132
|
id,
|
|
3148
4133
|
label: dateLabel,
|
|
3149
4134
|
collapseLabelOnEmpty: !timeLabel,
|
|
4135
|
+
onDateTimeBlur,
|
|
3150
4136
|
formId,
|
|
3151
4137
|
required,
|
|
3152
4138
|
disabled,
|
|
@@ -3160,6 +4146,7 @@ function Datetime(props) {
|
|
|
3160
4146
|
id,
|
|
3161
4147
|
label: timeLabel,
|
|
3162
4148
|
collapseLabelOnEmpty: !dateLabel,
|
|
4149
|
+
onDateTimeBlur,
|
|
3163
4150
|
formId,
|
|
3164
4151
|
required,
|
|
3165
4152
|
disabled,
|
|
@@ -3171,13 +4158,14 @@ function Datetime(props) {
|
|
|
3171
4158
|
'aria-describedby': errorMessageId
|
|
3172
4159
|
};
|
|
3173
4160
|
return jsxs("div", {
|
|
3174
|
-
class: formFieldClasses(type$
|
|
4161
|
+
class: formFieldClasses(type$9, {
|
|
3175
4162
|
errors: allErrors,
|
|
3176
4163
|
disabled,
|
|
3177
4164
|
readonly
|
|
3178
4165
|
}),
|
|
3179
4166
|
children: [jsxs("div", {
|
|
3180
4167
|
class: classNames('fjs-vertical-group'),
|
|
4168
|
+
ref: dateTimeGroupRef,
|
|
3181
4169
|
children: [useDatePicker && jsx(Datepicker, {
|
|
3182
4170
|
...datePickerProps
|
|
3183
4171
|
}), useTimePicker && useDatePicker && jsx("div", {
|
|
@@ -3194,7 +4182,7 @@ function Datetime(props) {
|
|
|
3194
4182
|
});
|
|
3195
4183
|
}
|
|
3196
4184
|
Datetime.config = {
|
|
3197
|
-
type: type$
|
|
4185
|
+
type: type$9,
|
|
3198
4186
|
keyed: true,
|
|
3199
4187
|
label: 'Date time',
|
|
3200
4188
|
group: 'basic-input',
|
|
@@ -3211,10 +4199,10 @@ Datetime.config = {
|
|
|
3211
4199
|
}
|
|
3212
4200
|
};
|
|
3213
4201
|
|
|
3214
|
-
/**
|
|
3215
|
-
* This file must not be changed or exchanged.
|
|
3216
|
-
*
|
|
3217
|
-
* @see http://bpmn.io/license for more information.
|
|
4202
|
+
/**
|
|
4203
|
+
* This file must not be changed or exchanged.
|
|
4204
|
+
*
|
|
4205
|
+
* @see http://bpmn.io/license for more information.
|
|
3218
4206
|
*/
|
|
3219
4207
|
function Logo() {
|
|
3220
4208
|
return jsxs("svg", {
|
|
@@ -3336,6 +4324,52 @@ function FormComponent(props) {
|
|
|
3336
4324
|
});
|
|
3337
4325
|
}
|
|
3338
4326
|
|
|
4327
|
+
function Group(props) {
|
|
4328
|
+
const {
|
|
4329
|
+
field
|
|
4330
|
+
} = props;
|
|
4331
|
+
const {
|
|
4332
|
+
label,
|
|
4333
|
+
id,
|
|
4334
|
+
type,
|
|
4335
|
+
showOutline
|
|
4336
|
+
} = field;
|
|
4337
|
+
const {
|
|
4338
|
+
formId
|
|
4339
|
+
} = useContext(FormContext$1);
|
|
4340
|
+
const {
|
|
4341
|
+
Empty
|
|
4342
|
+
} = useContext(FormRenderContext$1);
|
|
4343
|
+
const fullProps = {
|
|
4344
|
+
...props,
|
|
4345
|
+
Empty
|
|
4346
|
+
};
|
|
4347
|
+
return jsxs("div", {
|
|
4348
|
+
className: classNames(formFieldClasses(type), {
|
|
4349
|
+
'fjs-outlined': showOutline
|
|
4350
|
+
}),
|
|
4351
|
+
role: "group",
|
|
4352
|
+
"aria-labelledby": prefixId(id, formId),
|
|
4353
|
+
children: [jsx(Label, {
|
|
4354
|
+
id: prefixId(id, formId),
|
|
4355
|
+
label: label
|
|
4356
|
+
}), jsx(Grid, {
|
|
4357
|
+
...fullProps
|
|
4358
|
+
})]
|
|
4359
|
+
});
|
|
4360
|
+
}
|
|
4361
|
+
Group.config = {
|
|
4362
|
+
type: 'group',
|
|
4363
|
+
pathed: true,
|
|
4364
|
+
label: 'Group',
|
|
4365
|
+
group: 'presentation',
|
|
4366
|
+
create: (options = {}) => ({
|
|
4367
|
+
components: [],
|
|
4368
|
+
showOutline: true,
|
|
4369
|
+
...options
|
|
4370
|
+
})
|
|
4371
|
+
};
|
|
4372
|
+
|
|
3339
4373
|
const NODE_TYPE_TEXT = 3,
|
|
3340
4374
|
NODE_TYPE_ELEMENT = 1;
|
|
3341
4375
|
const ALLOWED_NODES = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'span', 'em', 'a', 'p', 'div', 'ul', 'ol', 'li', 'hr', 'blockquote', 'img', 'pre', 'code', 'br', 'strong', 'table', 'thead', 'tbody', 'tr', 'th', 'td'];
|
|
@@ -3346,11 +4380,11 @@ const ATTR_WHITESPACE_PATTERN = /[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u
|
|
|
3346
4380
|
|
|
3347
4381
|
const FORM_ELEMENT = document.createElement('form');
|
|
3348
4382
|
|
|
3349
|
-
/**
|
|
3350
|
-
* Sanitize a HTML string and return the cleaned, safe version.
|
|
3351
|
-
*
|
|
3352
|
-
* @param {string} html
|
|
3353
|
-
* @return {string}
|
|
4383
|
+
/**
|
|
4384
|
+
* Sanitize a HTML string and return the cleaned, safe version.
|
|
4385
|
+
*
|
|
4386
|
+
* @param {string} html
|
|
4387
|
+
* @return {string}
|
|
3354
4388
|
*/
|
|
3355
4389
|
|
|
3356
4390
|
// see https://github.com/developit/snarkdown/issues/70
|
|
@@ -3368,29 +4402,29 @@ function sanitizeHTML(html) {
|
|
|
3368
4402
|
}
|
|
3369
4403
|
}
|
|
3370
4404
|
|
|
3371
|
-
/**
|
|
3372
|
-
* Sanitizes an image source to ensure we only allow for data URI and links
|
|
3373
|
-
* that start with http(s).
|
|
3374
|
-
*
|
|
3375
|
-
* Note: Most browsers anyway do not support script execution in <img> elements.
|
|
3376
|
-
*
|
|
3377
|
-
* @param {string} src
|
|
3378
|
-
* @returns {string}
|
|
4405
|
+
/**
|
|
4406
|
+
* Sanitizes an image source to ensure we only allow for data URI and links
|
|
4407
|
+
* that start with http(s).
|
|
4408
|
+
*
|
|
4409
|
+
* Note: Most browsers anyway do not support script execution in <img> elements.
|
|
4410
|
+
*
|
|
4411
|
+
* @param {string} src
|
|
4412
|
+
* @returns {string}
|
|
3379
4413
|
*/
|
|
3380
4414
|
function sanitizeImageSource(src) {
|
|
3381
4415
|
const valid = ALLOWED_IMAGE_SRC_PATTERN.test(src);
|
|
3382
4416
|
return valid ? src : '';
|
|
3383
4417
|
}
|
|
3384
4418
|
|
|
3385
|
-
/**
|
|
3386
|
-
* Recursively sanitize a HTML node, potentially
|
|
3387
|
-
* removing it, its children or attributes.
|
|
3388
|
-
*
|
|
3389
|
-
* Inspired by https://github.com/developit/snarkdown/issues/70
|
|
3390
|
-
* and https://github.com/cure53/DOMPurify. Simplified
|
|
3391
|
-
* for our use-case.
|
|
3392
|
-
*
|
|
3393
|
-
* @param {Element} node
|
|
4419
|
+
/**
|
|
4420
|
+
* Recursively sanitize a HTML node, potentially
|
|
4421
|
+
* removing it, its children or attributes.
|
|
4422
|
+
*
|
|
4423
|
+
* Inspired by https://github.com/developit/snarkdown/issues/70
|
|
4424
|
+
* and https://github.com/cure53/DOMPurify. Simplified
|
|
4425
|
+
* for our use-case.
|
|
4426
|
+
*
|
|
4427
|
+
* @param {Element} node
|
|
3394
4428
|
*/
|
|
3395
4429
|
function sanitizeNode(node) {
|
|
3396
4430
|
// allow text nodes
|
|
@@ -3434,13 +4468,13 @@ function sanitizeNode(node) {
|
|
|
3434
4468
|
}
|
|
3435
4469
|
}
|
|
3436
4470
|
|
|
3437
|
-
/**
|
|
3438
|
-
* Validates attributes for validity.
|
|
3439
|
-
*
|
|
3440
|
-
* @param {string} lcTag
|
|
3441
|
-
* @param {string} lcName
|
|
3442
|
-
* @param {string} value
|
|
3443
|
-
* @return {boolean}
|
|
4471
|
+
/**
|
|
4472
|
+
* Validates attributes for validity.
|
|
4473
|
+
*
|
|
4474
|
+
* @param {string} lcTag
|
|
4475
|
+
* @param {string} lcName
|
|
4476
|
+
* @param {string} value
|
|
4477
|
+
* @return {boolean}
|
|
3444
4478
|
*/
|
|
3445
4479
|
function isValidAttribute(lcTag, lcName, value) {
|
|
3446
4480
|
// disallow most attributes based on whitelist
|
|
@@ -3463,9 +4497,9 @@ function isValidAttribute(lcTag, lcName, value) {
|
|
|
3463
4497
|
return true;
|
|
3464
4498
|
}
|
|
3465
4499
|
|
|
3466
|
-
function _extends$
|
|
4500
|
+
function _extends$i() { _extends$i = 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$i.apply(this, arguments); }
|
|
3467
4501
|
var SvgImagePlaceholder = function SvgImagePlaceholder(props) {
|
|
3468
|
-
return /*#__PURE__*/React.createElement("svg", _extends$
|
|
4502
|
+
return /*#__PURE__*/React.createElement("svg", _extends$i({
|
|
3469
4503
|
xmlns: "http://www.w3.org/2000/svg",
|
|
3470
4504
|
xmlSpace: "preserve",
|
|
3471
4505
|
width: 64,
|
|
@@ -3504,7 +4538,7 @@ var SvgImagePlaceholder = function SvgImagePlaceholder(props) {
|
|
|
3504
4538
|
};
|
|
3505
4539
|
var ImagePlaceholder = SvgImagePlaceholder;
|
|
3506
4540
|
|
|
3507
|
-
const type$
|
|
4541
|
+
const type$8 = 'image';
|
|
3508
4542
|
function Image(props) {
|
|
3509
4543
|
const {
|
|
3510
4544
|
field
|
|
@@ -3525,7 +4559,7 @@ function Image(props) {
|
|
|
3525
4559
|
formId
|
|
3526
4560
|
} = useContext(FormContext$1);
|
|
3527
4561
|
return jsx("div", {
|
|
3528
|
-
class: formFieldClasses(type$
|
|
4562
|
+
class: formFieldClasses(type$8),
|
|
3529
4563
|
children: jsxs("div", {
|
|
3530
4564
|
class: "fjs-image-container",
|
|
3531
4565
|
children: [safeSource && jsx("img", {
|
|
@@ -3543,7 +4577,7 @@ function Image(props) {
|
|
|
3543
4577
|
});
|
|
3544
4578
|
}
|
|
3545
4579
|
Image.config = {
|
|
3546
|
-
type: type$
|
|
4580
|
+
type: type$8,
|
|
3547
4581
|
keyed: false,
|
|
3548
4582
|
label: 'Image view',
|
|
3549
4583
|
group: 'presentation',
|
|
@@ -3570,14 +4604,14 @@ function TemplatedInputAdorner(props) {
|
|
|
3570
4604
|
});
|
|
3571
4605
|
}
|
|
3572
4606
|
|
|
3573
|
-
var _path$
|
|
3574
|
-
function _extends$
|
|
4607
|
+
var _path$f;
|
|
4608
|
+
function _extends$h() { _extends$h = 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$h.apply(this, arguments); }
|
|
3575
4609
|
var SvgAngelDown = function SvgAngelDown(props) {
|
|
3576
|
-
return /*#__PURE__*/React.createElement("svg", _extends$
|
|
4610
|
+
return /*#__PURE__*/React.createElement("svg", _extends$h({
|
|
3577
4611
|
xmlns: "http://www.w3.org/2000/svg",
|
|
3578
4612
|
width: 8,
|
|
3579
4613
|
height: 8
|
|
3580
|
-
}, props), _path$
|
|
4614
|
+
}, props), _path$f || (_path$f = /*#__PURE__*/React.createElement("path", {
|
|
3581
4615
|
fill: "currentColor",
|
|
3582
4616
|
fillRule: "evenodd",
|
|
3583
4617
|
stroke: "currentColor",
|
|
@@ -3588,14 +4622,14 @@ var SvgAngelDown = function SvgAngelDown(props) {
|
|
|
3588
4622
|
};
|
|
3589
4623
|
var AngelDownIcon = SvgAngelDown;
|
|
3590
4624
|
|
|
3591
|
-
var _path$
|
|
3592
|
-
function _extends$
|
|
4625
|
+
var _path$e;
|
|
4626
|
+
function _extends$g() { _extends$g = 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$g.apply(this, arguments); }
|
|
3593
4627
|
var SvgAngelUp = function SvgAngelUp(props) {
|
|
3594
|
-
return /*#__PURE__*/React.createElement("svg", _extends$
|
|
4628
|
+
return /*#__PURE__*/React.createElement("svg", _extends$g({
|
|
3595
4629
|
xmlns: "http://www.w3.org/2000/svg",
|
|
3596
4630
|
width: 8,
|
|
3597
4631
|
height: 8
|
|
3598
|
-
}, props), _path$
|
|
4632
|
+
}, props), _path$e || (_path$e = /*#__PURE__*/React.createElement("path", {
|
|
3599
4633
|
fill: "currentColor",
|
|
3600
4634
|
fillRule: "evenodd",
|
|
3601
4635
|
stroke: "currentColor",
|
|
@@ -3606,11 +4640,12 @@ var SvgAngelUp = function SvgAngelUp(props) {
|
|
|
3606
4640
|
};
|
|
3607
4641
|
var AngelUpIcon = SvgAngelUp;
|
|
3608
4642
|
|
|
3609
|
-
const type$
|
|
4643
|
+
const type$7 = 'number';
|
|
3610
4644
|
function Numberfield(props) {
|
|
3611
4645
|
const {
|
|
3612
4646
|
disabled,
|
|
3613
4647
|
errors = [],
|
|
4648
|
+
onBlur,
|
|
3614
4649
|
field,
|
|
3615
4650
|
value,
|
|
3616
4651
|
readonly,
|
|
@@ -3743,7 +4778,7 @@ function Numberfield(props) {
|
|
|
3743
4778
|
} = useContext(FormContext$1);
|
|
3744
4779
|
const errorMessageId = errors.length === 0 ? undefined : `${prefixId(id, formId)}-error-message`;
|
|
3745
4780
|
return jsxs("div", {
|
|
3746
|
-
class: formFieldClasses(type$
|
|
4781
|
+
class: formFieldClasses(type$7, {
|
|
3747
4782
|
errors,
|
|
3748
4783
|
disabled,
|
|
3749
4784
|
readonly
|
|
@@ -3771,7 +4806,8 @@ function Numberfield(props) {
|
|
|
3771
4806
|
readOnly: readonly,
|
|
3772
4807
|
id: prefixId(id, formId),
|
|
3773
4808
|
onKeyDown: onKeyDown,
|
|
3774
|
-
onKeyPress: onKeyPress
|
|
4809
|
+
onKeyPress: onKeyPress,
|
|
4810
|
+
onBlur: onBlur
|
|
3775
4811
|
|
|
3776
4812
|
// @ts-ignore
|
|
3777
4813
|
,
|
|
@@ -3814,7 +4850,7 @@ function Numberfield(props) {
|
|
|
3814
4850
|
});
|
|
3815
4851
|
}
|
|
3816
4852
|
Numberfield.config = {
|
|
3817
|
-
type: type$
|
|
4853
|
+
type: type$7,
|
|
3818
4854
|
keyed: true,
|
|
3819
4855
|
label: 'Number',
|
|
3820
4856
|
group: 'basic-input',
|
|
@@ -3837,11 +4873,12 @@ Numberfield.config = {
|
|
|
3837
4873
|
})
|
|
3838
4874
|
};
|
|
3839
4875
|
|
|
3840
|
-
const type$
|
|
4876
|
+
const type$6 = 'radio';
|
|
3841
4877
|
function Radio(props) {
|
|
3842
4878
|
const {
|
|
3843
4879
|
disabled,
|
|
3844
4880
|
errors = [],
|
|
4881
|
+
onBlur,
|
|
3845
4882
|
field,
|
|
3846
4883
|
readonly,
|
|
3847
4884
|
value
|
|
@@ -3852,6 +4889,7 @@ function Radio(props) {
|
|
|
3852
4889
|
label,
|
|
3853
4890
|
validate = {}
|
|
3854
4891
|
} = field;
|
|
4892
|
+
const outerDivRef = useRef();
|
|
3855
4893
|
const {
|
|
3856
4894
|
required
|
|
3857
4895
|
} = validate;
|
|
@@ -3861,6 +4899,12 @@ function Radio(props) {
|
|
|
3861
4899
|
value: v
|
|
3862
4900
|
});
|
|
3863
4901
|
};
|
|
4902
|
+
const onRadioBlur = e => {
|
|
4903
|
+
if (outerDivRef.current.contains(e.relatedTarget)) {
|
|
4904
|
+
return;
|
|
4905
|
+
}
|
|
4906
|
+
onBlur();
|
|
4907
|
+
};
|
|
3864
4908
|
const {
|
|
3865
4909
|
state: loadState,
|
|
3866
4910
|
values: options
|
|
@@ -3870,11 +4914,12 @@ function Radio(props) {
|
|
|
3870
4914
|
} = useContext(FormContext$1);
|
|
3871
4915
|
const errorMessageId = errors.length === 0 ? undefined : `${prefixId(id, formId)}-error-message`;
|
|
3872
4916
|
return jsxs("div", {
|
|
3873
|
-
class: formFieldClasses(type$
|
|
4917
|
+
class: formFieldClasses(type$6, {
|
|
3874
4918
|
errors,
|
|
3875
4919
|
disabled,
|
|
3876
4920
|
readonly
|
|
3877
4921
|
}),
|
|
4922
|
+
ref: outerDivRef,
|
|
3878
4923
|
children: [jsx(Label, {
|
|
3879
4924
|
label: label,
|
|
3880
4925
|
required: required
|
|
@@ -3894,6 +4939,7 @@ function Radio(props) {
|
|
|
3894
4939
|
id: prefixId(`${id}-${index}`, formId),
|
|
3895
4940
|
type: "radio",
|
|
3896
4941
|
onClick: () => onChange(option.value),
|
|
4942
|
+
onBlur: onRadioBlur,
|
|
3897
4943
|
"aria-describedby": errorMessageId
|
|
3898
4944
|
})
|
|
3899
4945
|
}, `${id}-${index}`);
|
|
@@ -3906,37 +4952,23 @@ function Radio(props) {
|
|
|
3906
4952
|
});
|
|
3907
4953
|
}
|
|
3908
4954
|
Radio.config = {
|
|
3909
|
-
type: type$
|
|
4955
|
+
type: type$6,
|
|
3910
4956
|
keyed: true,
|
|
3911
4957
|
label: 'Radio',
|
|
3912
4958
|
group: 'selection',
|
|
3913
4959
|
emptyValue: null,
|
|
3914
4960
|
sanitizeValue: sanitizeSingleSelectValue,
|
|
3915
|
-
create:
|
|
3916
|
-
const defaults = {};
|
|
3917
|
-
|
|
3918
|
-
// provide default values if valuesKey isn't set
|
|
3919
|
-
if (!options.valuesKey) {
|
|
3920
|
-
defaults.values = [{
|
|
3921
|
-
label: 'Value',
|
|
3922
|
-
value: 'value'
|
|
3923
|
-
}];
|
|
3924
|
-
}
|
|
3925
|
-
return {
|
|
3926
|
-
...defaults,
|
|
3927
|
-
...options
|
|
3928
|
-
};
|
|
3929
|
-
}
|
|
4961
|
+
create: createEmptyOptions
|
|
3930
4962
|
};
|
|
3931
4963
|
|
|
3932
|
-
var _path$
|
|
3933
|
-
function _extends$
|
|
4964
|
+
var _path$d;
|
|
4965
|
+
function _extends$f() { _extends$f = 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$f.apply(this, arguments); }
|
|
3934
4966
|
var SvgXMark = function SvgXMark(props) {
|
|
3935
|
-
return /*#__PURE__*/React.createElement("svg", _extends$
|
|
4967
|
+
return /*#__PURE__*/React.createElement("svg", _extends$f({
|
|
3936
4968
|
xmlns: "http://www.w3.org/2000/svg",
|
|
3937
4969
|
width: 8,
|
|
3938
4970
|
height: 8
|
|
3939
|
-
}, props), _path$
|
|
4971
|
+
}, props), _path$d || (_path$d = /*#__PURE__*/React.createElement("path", {
|
|
3940
4972
|
fill: "currentColor",
|
|
3941
4973
|
fillRule: "evenodd",
|
|
3942
4974
|
stroke: "currentColor",
|
|
@@ -3952,6 +4984,7 @@ function SearchableSelect(props) {
|
|
|
3952
4984
|
id,
|
|
3953
4985
|
disabled,
|
|
3954
4986
|
errors,
|
|
4987
|
+
onBlur,
|
|
3955
4988
|
field,
|
|
3956
4989
|
readonly,
|
|
3957
4990
|
value
|
|
@@ -4071,6 +5104,7 @@ function SearchableSelect(props) {
|
|
|
4071
5104
|
onBlur: () => {
|
|
4072
5105
|
setIsDropdownExpanded(false);
|
|
4073
5106
|
setFilter(valueLabel);
|
|
5107
|
+
onBlur();
|
|
4074
5108
|
},
|
|
4075
5109
|
"aria-describedby": props['aria-describedby']
|
|
4076
5110
|
}), displayState.displayCross && jsxs("span", {
|
|
@@ -4105,6 +5139,7 @@ function SimpleSelect(props) {
|
|
|
4105
5139
|
id,
|
|
4106
5140
|
disabled,
|
|
4107
5141
|
errors,
|
|
5142
|
+
onBlur,
|
|
4108
5143
|
field,
|
|
4109
5144
|
readonly,
|
|
4110
5145
|
value
|
|
@@ -4159,7 +5194,10 @@ function SimpleSelect(props) {
|
|
|
4159
5194
|
'hasErrors': errors.length
|
|
4160
5195
|
}),
|
|
4161
5196
|
onFocus: () => setIsDropdownExpanded(true),
|
|
4162
|
-
onBlur: () =>
|
|
5197
|
+
onBlur: () => {
|
|
5198
|
+
setIsDropdownExpanded(false);
|
|
5199
|
+
onBlur();
|
|
5200
|
+
},
|
|
4163
5201
|
onMouseDown: onMouseDown,
|
|
4164
5202
|
children: [jsx("div", {
|
|
4165
5203
|
class: classNames('fjs-select-display', {
|
|
@@ -4201,11 +5239,12 @@ function SimpleSelect(props) {
|
|
|
4201
5239
|
});
|
|
4202
5240
|
}
|
|
4203
5241
|
|
|
4204
|
-
const type$
|
|
5242
|
+
const type$5 = 'select';
|
|
4205
5243
|
function Select(props) {
|
|
4206
5244
|
const {
|
|
4207
5245
|
disabled,
|
|
4208
5246
|
errors = [],
|
|
5247
|
+
onBlur,
|
|
4209
5248
|
field,
|
|
4210
5249
|
onChange,
|
|
4211
5250
|
readonly,
|
|
@@ -4229,14 +5268,15 @@ function Select(props) {
|
|
|
4229
5268
|
id,
|
|
4230
5269
|
disabled,
|
|
4231
5270
|
errors,
|
|
5271
|
+
onBlur,
|
|
4232
5272
|
field,
|
|
4233
5273
|
value,
|
|
4234
5274
|
onChange,
|
|
4235
5275
|
readonly,
|
|
4236
5276
|
'aria-describedby': errorMessageId
|
|
4237
|
-
}), [disabled, errors, field, id, value, onChange, readonly, errorMessageId]);
|
|
5277
|
+
}), [disabled, errors, field, id, value, onChange, onBlur, readonly, errorMessageId]);
|
|
4238
5278
|
return jsxs("div", {
|
|
4239
|
-
class: formFieldClasses(type$
|
|
5279
|
+
class: formFieldClasses(type$5, {
|
|
4240
5280
|
errors,
|
|
4241
5281
|
disabled,
|
|
4242
5282
|
readonly
|
|
@@ -4264,27 +5304,39 @@ function Select(props) {
|
|
|
4264
5304
|
});
|
|
4265
5305
|
}
|
|
4266
5306
|
Select.config = {
|
|
4267
|
-
type: type$
|
|
5307
|
+
type: type$5,
|
|
4268
5308
|
keyed: true,
|
|
4269
5309
|
label: 'Select',
|
|
4270
5310
|
group: 'selection',
|
|
4271
5311
|
emptyValue: null,
|
|
4272
5312
|
sanitizeValue: sanitizeSingleSelectValue,
|
|
4273
|
-
create:
|
|
4274
|
-
|
|
5313
|
+
create: createEmptyOptions
|
|
5314
|
+
};
|
|
4275
5315
|
|
|
4276
|
-
|
|
4277
|
-
|
|
4278
|
-
|
|
4279
|
-
|
|
4280
|
-
|
|
4281
|
-
|
|
5316
|
+
const type$4 = 'spacer';
|
|
5317
|
+
function Spacer(props) {
|
|
5318
|
+
const {
|
|
5319
|
+
field
|
|
5320
|
+
} = props;
|
|
5321
|
+
const {
|
|
5322
|
+
height = 60
|
|
5323
|
+
} = field;
|
|
5324
|
+
return jsx("div", {
|
|
5325
|
+
class: formFieldClasses(type$4),
|
|
5326
|
+
style: {
|
|
5327
|
+
height: height
|
|
4282
5328
|
}
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
|
|
5329
|
+
});
|
|
5330
|
+
}
|
|
5331
|
+
Spacer.config = {
|
|
5332
|
+
type: type$4,
|
|
5333
|
+
keyed: false,
|
|
5334
|
+
label: 'Spacer',
|
|
5335
|
+
group: 'presentation',
|
|
5336
|
+
create: (options = {}) => ({
|
|
5337
|
+
height: 60,
|
|
5338
|
+
...options
|
|
5339
|
+
})
|
|
4288
5340
|
};
|
|
4289
5341
|
|
|
4290
5342
|
const type$3 = 'taglist';
|
|
@@ -4292,6 +5344,7 @@ function Taglist(props) {
|
|
|
4292
5344
|
const {
|
|
4293
5345
|
disabled,
|
|
4294
5346
|
errors = [],
|
|
5347
|
+
onBlur,
|
|
4295
5348
|
field,
|
|
4296
5349
|
readonly,
|
|
4297
5350
|
value: values = []
|
|
@@ -4384,9 +5437,10 @@ function Taglist(props) {
|
|
|
4384
5437
|
break;
|
|
4385
5438
|
}
|
|
4386
5439
|
};
|
|
4387
|
-
const
|
|
5440
|
+
const onComponentBlur = () => {
|
|
4388
5441
|
setIsDropdownExpanded(false);
|
|
4389
5442
|
setFilter('');
|
|
5443
|
+
onBlur();
|
|
4390
5444
|
};
|
|
4391
5445
|
const onTagRemoveClick = (event, value) => {
|
|
4392
5446
|
const {
|
|
@@ -4457,9 +5511,7 @@ function Taglist(props) {
|
|
|
4457
5511
|
onKeyDown: onInputKeyDown,
|
|
4458
5512
|
onMouseDown: () => setIsEscapeClose(false),
|
|
4459
5513
|
onFocus: () => !readonly && setIsDropdownExpanded(true),
|
|
4460
|
-
onBlur: () =>
|
|
4461
|
-
!readonly && onBlur();
|
|
4462
|
-
},
|
|
5514
|
+
onBlur: () => !readonly && onComponentBlur(),
|
|
4463
5515
|
"aria-describedby": errorMessageId
|
|
4464
5516
|
})]
|
|
4465
5517
|
}), jsx("div", {
|
|
@@ -4486,21 +5538,7 @@ Taglist.config = {
|
|
|
4486
5538
|
group: 'selection',
|
|
4487
5539
|
emptyValue: [],
|
|
4488
5540
|
sanitizeValue: sanitizeMultiSelectValue,
|
|
4489
|
-
create:
|
|
4490
|
-
const defaults = {};
|
|
4491
|
-
|
|
4492
|
-
// provide default values if valuesKey isn't set
|
|
4493
|
-
if (!options.valuesKey) {
|
|
4494
|
-
defaults.values = [{
|
|
4495
|
-
label: 'Value',
|
|
4496
|
-
value: 'value'
|
|
4497
|
-
}];
|
|
4498
|
-
}
|
|
4499
|
-
return {
|
|
4500
|
-
...defaults,
|
|
4501
|
-
...options
|
|
4502
|
-
};
|
|
4503
|
-
}
|
|
5541
|
+
create: createEmptyOptions
|
|
4504
5542
|
};
|
|
4505
5543
|
|
|
4506
5544
|
const type$2 = 'text';
|
|
@@ -4592,6 +5630,7 @@ function Textfield(props) {
|
|
|
4592
5630
|
const {
|
|
4593
5631
|
disabled,
|
|
4594
5632
|
errors = [],
|
|
5633
|
+
onBlur,
|
|
4595
5634
|
field,
|
|
4596
5635
|
readonly,
|
|
4597
5636
|
value = ''
|
|
@@ -4643,6 +5682,7 @@ function Textfield(props) {
|
|
|
4643
5682
|
readOnly: readonly,
|
|
4644
5683
|
id: prefixId(id, formId),
|
|
4645
5684
|
onInput: onChange,
|
|
5685
|
+
onBlur: onBlur,
|
|
4646
5686
|
type: "text",
|
|
4647
5687
|
value: value,
|
|
4648
5688
|
"aria-describedby": errorMessageId
|
|
@@ -4684,6 +5724,7 @@ function Textarea(props) {
|
|
|
4684
5724
|
const {
|
|
4685
5725
|
disabled,
|
|
4686
5726
|
errors = [],
|
|
5727
|
+
onBlur,
|
|
4687
5728
|
field,
|
|
4688
5729
|
readonly,
|
|
4689
5730
|
value = ''
|
|
@@ -4706,22 +5747,12 @@ function Textarea(props) {
|
|
|
4706
5747
|
value: target.value
|
|
4707
5748
|
});
|
|
4708
5749
|
};
|
|
4709
|
-
|
|
4710
|
-
|
|
4711
|
-
|
|
4712
|
-
const computed = window.getComputedStyle(textarea);
|
|
4713
|
-
const calculatedHeight = parseInt(computed.getPropertyValue('border-top-width')) + parseInt(computed.getPropertyValue('padding-top')) + textarea.scrollHeight + parseInt(computed.getPropertyValue('padding-bottom')) + parseInt(computed.getPropertyValue('border-bottom-width'));
|
|
4714
|
-
const minHeight = 75;
|
|
4715
|
-
const maxHeight = 350;
|
|
4716
|
-
const displayHeight = Math.max(Math.min(calculatedHeight, maxHeight), minHeight);
|
|
4717
|
-
textarea.style.height = `${displayHeight}px`;
|
|
4718
|
-
|
|
4719
|
-
// Overflow is hidden by default to hide scrollbar flickering
|
|
4720
|
-
textarea.style.overflow = calculatedHeight > maxHeight ? 'visible' : 'hidden';
|
|
4721
|
-
}, []);
|
|
5750
|
+
useLayoutEffect(() => {
|
|
5751
|
+
autoSizeTextarea(textareaRef.current);
|
|
5752
|
+
}, [value]);
|
|
4722
5753
|
useEffect(() => {
|
|
4723
5754
|
autoSizeTextarea(textareaRef.current);
|
|
4724
|
-
}, [
|
|
5755
|
+
}, []);
|
|
4725
5756
|
const {
|
|
4726
5757
|
formId
|
|
4727
5758
|
} = useContext(FormContext$1);
|
|
@@ -4742,6 +5773,7 @@ function Textarea(props) {
|
|
|
4742
5773
|
readonly: readonly,
|
|
4743
5774
|
id: prefixId(id, formId),
|
|
4744
5775
|
onInput: onInput,
|
|
5776
|
+
onBlur: onBlur,
|
|
4745
5777
|
value: value,
|
|
4746
5778
|
ref: textareaRef,
|
|
4747
5779
|
"aria-describedby": errorMessageId
|
|
@@ -4766,40 +5798,58 @@ Textarea.config = {
|
|
|
4766
5798
|
...options
|
|
4767
5799
|
})
|
|
4768
5800
|
};
|
|
5801
|
+
const autoSizeTextarea = textarea => {
|
|
5802
|
+
// Ensures the textarea shrinks back, and improves resizing behavior consistency
|
|
5803
|
+
textarea.style.height = '0px';
|
|
5804
|
+
const computed = window.getComputedStyle(textarea);
|
|
5805
|
+
const heightFromLines = () => {
|
|
5806
|
+
const lineHeight = parseInt(computed.getPropertyValue('line-height').replace('px', '')) || 0;
|
|
5807
|
+
const lines = textarea.value ? textarea.value.toString().split('\n').length : 0;
|
|
5808
|
+
return lines * lineHeight;
|
|
5809
|
+
};
|
|
5810
|
+
const calculatedHeight = parseInt(computed.getPropertyValue('border-top-width')) + parseInt(computed.getPropertyValue('padding-top')) + (textarea.scrollHeight || heightFromLines()) + parseInt(computed.getPropertyValue('padding-bottom')) + parseInt(computed.getPropertyValue('border-bottom-width'));
|
|
5811
|
+
const minHeight = 75;
|
|
5812
|
+
const maxHeight = 350;
|
|
5813
|
+
const displayHeight = Math.max(Math.min(calculatedHeight || 0, maxHeight), minHeight);
|
|
5814
|
+
textarea.style.height = `${displayHeight}px`;
|
|
5815
|
+
|
|
5816
|
+
// Overflow is hidden by default to hide scrollbar flickering
|
|
5817
|
+
textarea.style.overflow = calculatedHeight > maxHeight ? 'visible' : 'hidden';
|
|
5818
|
+
};
|
|
4769
5819
|
|
|
4770
|
-
var _path$
|
|
4771
|
-
function _extends$
|
|
5820
|
+
var _path$c;
|
|
5821
|
+
function _extends$e() { _extends$e = 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$e.apply(this, arguments); }
|
|
4772
5822
|
var SvgButton = function SvgButton(props) {
|
|
4773
|
-
return /*#__PURE__*/React.createElement("svg", _extends$
|
|
5823
|
+
return /*#__PURE__*/React.createElement("svg", _extends$e({
|
|
4774
5824
|
xmlns: "http://www.w3.org/2000/svg",
|
|
4775
5825
|
width: 54,
|
|
4776
5826
|
height: 54,
|
|
4777
5827
|
fill: "currentcolor"
|
|
4778
|
-
}, props), _path$
|
|
5828
|
+
}, props), _path$c || (_path$c = /*#__PURE__*/React.createElement("path", {
|
|
4779
5829
|
fillRule: "evenodd",
|
|
4780
5830
|
d: "M45 17a3 3 0 0 1 3 3v14a3 3 0 0 1-3 3H9a3 3 0 0 1-3-3V20a3 3 0 0 1 3-3h36zm-9 8.889H18v2.222h18v-2.222z"
|
|
4781
5831
|
})));
|
|
4782
5832
|
};
|
|
4783
5833
|
var ButtonIcon = SvgButton;
|
|
4784
5834
|
|
|
4785
|
-
var _path$
|
|
4786
|
-
function _extends$
|
|
5835
|
+
var _path$b;
|
|
5836
|
+
function _extends$d() { _extends$d = 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$d.apply(this, arguments); }
|
|
4787
5837
|
var SvgCheckbox = function SvgCheckbox(props) {
|
|
4788
|
-
return /*#__PURE__*/React.createElement("svg", _extends$
|
|
5838
|
+
return /*#__PURE__*/React.createElement("svg", _extends$d({
|
|
4789
5839
|
xmlns: "http://www.w3.org/2000/svg",
|
|
4790
5840
|
width: 54,
|
|
4791
5841
|
height: 54,
|
|
4792
5842
|
fill: "currentcolor"
|
|
4793
|
-
}, props), _path$
|
|
5843
|
+
}, props), _path$b || (_path$b = /*#__PURE__*/React.createElement("path", {
|
|
4794
5844
|
d: "M34 18H20a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V20a2 2 0 0 0-2-2zm-9 14-5-5 1.41-1.41L25 29.17l7.59-7.59L34 23l-9 9z"
|
|
4795
5845
|
})));
|
|
4796
5846
|
};
|
|
4797
5847
|
var CheckboxIcon = SvgCheckbox;
|
|
4798
5848
|
|
|
4799
5849
|
var _g, _use, _use2, _use3, _defs;
|
|
4800
|
-
function _extends$
|
|
5850
|
+
function _extends$c() { _extends$c = 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$c.apply(this, arguments); }
|
|
4801
5851
|
var SvgChecklist = function SvgChecklist(props) {
|
|
4802
|
-
return /*#__PURE__*/React.createElement("svg", _extends$
|
|
5852
|
+
return /*#__PURE__*/React.createElement("svg", _extends$c({
|
|
4803
5853
|
xmlns: "http://www.w3.org/2000/svg",
|
|
4804
5854
|
xmlnsXlink: "http://www.w3.org/1999/xlink",
|
|
4805
5855
|
width: 54,
|
|
@@ -4833,18 +5883,18 @@ var SvgChecklist = function SvgChecklist(props) {
|
|
|
4833
5883
|
};
|
|
4834
5884
|
var ChecklistIcon = SvgChecklist;
|
|
4835
5885
|
|
|
4836
|
-
var _path$
|
|
4837
|
-
function _extends$
|
|
5886
|
+
var _path$a, _path2$3, _path3;
|
|
5887
|
+
function _extends$b() { _extends$b = 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$b.apply(this, arguments); }
|
|
4838
5888
|
var SvgDatetime = function SvgDatetime(props) {
|
|
4839
|
-
return /*#__PURE__*/React.createElement("svg", _extends$
|
|
5889
|
+
return /*#__PURE__*/React.createElement("svg", _extends$b({
|
|
4840
5890
|
xmlns: "http://www.w3.org/2000/svg",
|
|
4841
5891
|
width: 54,
|
|
4842
5892
|
height: 54,
|
|
4843
5893
|
fill: "currentcolor"
|
|
4844
|
-
}, props), _path$
|
|
5894
|
+
}, props), _path$a || (_path$a = /*#__PURE__*/React.createElement("path", {
|
|
4845
5895
|
fillRule: "evenodd",
|
|
4846
5896
|
d: "M37.908 13.418h-5.004v-2.354h-1.766v2.354H21.13v-2.354h-1.766v2.354H14.36a2.07 2.07 0 0 0-2.06 2.06v23.549a2.07 2.07 0 0 0 2.06 2.06h6.77v-1.766h-6.358a.707.707 0 0 1-.706-.706V15.89c0-.39.316-.707.706-.707h4.592v2.355h1.766v-2.355h10.008v2.355h1.766v-2.355h4.592a.71.71 0 0 1 .707.707v6.358h1.765v-6.77c0-1.133-.927-2.06-2.06-2.06z"
|
|
4847
|
-
})), _path2$
|
|
5897
|
+
})), _path2$3 || (_path2$3 = /*#__PURE__*/React.createElement("path", {
|
|
4848
5898
|
d: "m35.13 37.603 1.237-1.237-3.468-3.475v-5.926h-1.754v6.654l3.984 3.984Z"
|
|
4849
5899
|
})), _path3 || (_path3 = /*#__PURE__*/React.createElement("path", {
|
|
4850
5900
|
fillRule: "evenodd",
|
|
@@ -4853,27 +5903,27 @@ var SvgDatetime = function SvgDatetime(props) {
|
|
|
4853
5903
|
};
|
|
4854
5904
|
var DatetimeIcon = SvgDatetime;
|
|
4855
5905
|
|
|
4856
|
-
var _path$
|
|
4857
|
-
function _extends$
|
|
5906
|
+
var _path$9, _path2$2;
|
|
5907
|
+
function _extends$a() { _extends$a = 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$a.apply(this, arguments); }
|
|
4858
5908
|
var SvgTaglist = function SvgTaglist(props) {
|
|
4859
|
-
return /*#__PURE__*/React.createElement("svg", _extends$
|
|
5909
|
+
return /*#__PURE__*/React.createElement("svg", _extends$a({
|
|
4860
5910
|
xmlns: "http://www.w3.org/2000/svg",
|
|
4861
5911
|
width: 54,
|
|
4862
5912
|
height: 54,
|
|
4863
5913
|
fill: "currentcolor"
|
|
4864
|
-
}, props), _path$
|
|
5914
|
+
}, props), _path$9 || (_path$9 = /*#__PURE__*/React.createElement("path", {
|
|
4865
5915
|
fillRule: "evenodd",
|
|
4866
5916
|
d: "M45 16a3 3 0 0 1 3 3v16a3 3 0 0 1-3 3H9a3 3 0 0 1-3-3V19a3 3 0 0 1 3-3h36Zm0 2H9a1 1 0 0 0-1 1v16a1 1 0 0 0 1 1h36a1 1 0 0 0 1-1V19a1 1 0 0 0-1-1Z"
|
|
4867
|
-
})), _path2$
|
|
5917
|
+
})), _path2$2 || (_path2$2 = /*#__PURE__*/React.createElement("path", {
|
|
4868
5918
|
d: "M11 22a1 1 0 0 1 1-1h19a1 1 0 0 1 1 1v10a1 1 0 0 1-1 1H12a1 1 0 0 1-1-1V22Z"
|
|
4869
5919
|
})));
|
|
4870
5920
|
};
|
|
4871
5921
|
var TaglistIcon = SvgTaglist;
|
|
4872
5922
|
|
|
4873
5923
|
var _rect, _rect2, _rect3;
|
|
4874
|
-
function _extends$
|
|
5924
|
+
function _extends$9() { _extends$9 = 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$9.apply(this, arguments); }
|
|
4875
5925
|
var SvgForm = function SvgForm(props) {
|
|
4876
|
-
return /*#__PURE__*/React.createElement("svg", _extends$
|
|
5926
|
+
return /*#__PURE__*/React.createElement("svg", _extends$9({
|
|
4877
5927
|
xmlns: "http://www.w3.org/2000/svg",
|
|
4878
5928
|
width: 54,
|
|
4879
5929
|
height: 54
|
|
@@ -4899,63 +5949,87 @@ var SvgForm = function SvgForm(props) {
|
|
|
4899
5949
|
};
|
|
4900
5950
|
var FormIcon = SvgForm;
|
|
4901
5951
|
|
|
5952
|
+
var _path$8;
|
|
5953
|
+
function _extends$8() { _extends$8 = 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$8.apply(this, arguments); }
|
|
5954
|
+
var SvgGroup = function SvgGroup(props) {
|
|
5955
|
+
return /*#__PURE__*/React.createElement("svg", _extends$8({
|
|
5956
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
5957
|
+
width: 54,
|
|
5958
|
+
height: 54,
|
|
5959
|
+
fill: "currentcolor"
|
|
5960
|
+
}, props), _path$8 || (_path$8 = /*#__PURE__*/React.createElement("path", {
|
|
5961
|
+
fillRule: "evenodd",
|
|
5962
|
+
d: "M8 33v5a1 1 0 0 0 1 1h4v2H9a3 3 0 0 1-3-3v-5h2Zm18 6v2H15v-2h11Zm13 0v2H28v-2h11Zm9-6v5a3 3 0 0 1-3 3h-4v-2h4a1 1 0 0 0 .993-.883L46 38v-5h2ZM8 22v9H6v-9h2Zm40 0v9h-2v-9h2Zm-35-9v2H9a1 1 0 0 0-.993.883L8 16v4H6v-4a3 3 0 0 1 3-3h4Zm32 0a3 3 0 0 1 3 3v4h-2v-4a1 1 0 0 0-.883-.993L45 15h-4v-2h4Zm-6 0v2H28v-2h11Zm-13 0v2H15v-2h11Z"
|
|
5963
|
+
})));
|
|
5964
|
+
};
|
|
5965
|
+
var GroupIcon = SvgGroup;
|
|
5966
|
+
|
|
4902
5967
|
var _path$7;
|
|
4903
5968
|
function _extends$7() { _extends$7 = 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$7.apply(this, arguments); }
|
|
4904
|
-
var
|
|
5969
|
+
var SvgNumber = function SvgNumber(props) {
|
|
4905
5970
|
return /*#__PURE__*/React.createElement("svg", _extends$7({
|
|
4906
5971
|
xmlns: "http://www.w3.org/2000/svg",
|
|
4907
5972
|
width: 54,
|
|
4908
|
-
height: 54
|
|
5973
|
+
height: 54,
|
|
5974
|
+
fill: "currentcolor"
|
|
4909
5975
|
}, props), _path$7 || (_path$7 = /*#__PURE__*/React.createElement("path", {
|
|
4910
5976
|
fillRule: "evenodd",
|
|
4911
|
-
d: "
|
|
5977
|
+
d: "M45 16a3 3 0 0 1 3 3v16a3 3 0 0 1-3 3H9a3 3 0 0 1-3-3V19a3 3 0 0 1 3-3h36zm0 2H9a1 1 0 0 0-1 1v16a1 1 0 0 0 1 1h36a1 1 0 0 0 1-1V19a1 1 0 0 0-1-1zM35 28.444h7l-3.5 4-3.5-4zM35 26h7l-3.5-4-3.5 4z"
|
|
4912
5978
|
})));
|
|
4913
5979
|
};
|
|
4914
|
-
var
|
|
5980
|
+
var NumberIcon = SvgNumber;
|
|
4915
5981
|
|
|
4916
5982
|
var _path$6;
|
|
4917
5983
|
function _extends$6() { _extends$6 = 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$6.apply(this, arguments); }
|
|
4918
|
-
var
|
|
5984
|
+
var SvgRadio = function SvgRadio(props) {
|
|
4919
5985
|
return /*#__PURE__*/React.createElement("svg", _extends$6({
|
|
4920
5986
|
xmlns: "http://www.w3.org/2000/svg",
|
|
4921
5987
|
width: 54,
|
|
4922
5988
|
height: 54,
|
|
4923
5989
|
fill: "currentcolor"
|
|
4924
5990
|
}, props), _path$6 || (_path$6 = /*#__PURE__*/React.createElement("path", {
|
|
4925
|
-
|
|
4926
|
-
d: "M45 16a3 3 0 0 1 3 3v16a3 3 0 0 1-3 3H9a3 3 0 0 1-3-3V19a3 3 0 0 1 3-3h36zm0 2H9a1 1 0 0 0-1 1v16a1 1 0 0 0 1 1h36a1 1 0 0 0 1-1V19a1 1 0 0 0-1-1zM35 28.444h7l-3.5 4-3.5-4zM35 26h7l-3.5-4-3.5 4z"
|
|
5991
|
+
d: "M27 22c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5zm0-5c-5.52 0-10 4.48-10 10s4.48 10 10 10 10-4.48 10-10-4.48-10-10-10zm0 18a8 8 0 1 1 0-16 8 8 0 1 1 0 16z"
|
|
4927
5992
|
})));
|
|
4928
5993
|
};
|
|
4929
|
-
var
|
|
5994
|
+
var RadioIcon = SvgRadio;
|
|
4930
5995
|
|
|
4931
5996
|
var _path$5;
|
|
4932
5997
|
function _extends$5() { _extends$5 = 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$5.apply(this, arguments); }
|
|
4933
|
-
var
|
|
5998
|
+
var SvgSelect = function SvgSelect(props) {
|
|
4934
5999
|
return /*#__PURE__*/React.createElement("svg", _extends$5({
|
|
4935
6000
|
xmlns: "http://www.w3.org/2000/svg",
|
|
4936
6001
|
width: 54,
|
|
4937
6002
|
height: 54,
|
|
4938
6003
|
fill: "currentcolor"
|
|
4939
6004
|
}, props), _path$5 || (_path$5 = /*#__PURE__*/React.createElement("path", {
|
|
4940
|
-
|
|
6005
|
+
fillRule: "evenodd",
|
|
6006
|
+
d: "M45 16a3 3 0 0 1 3 3v16a3 3 0 0 1-3 3H9a3 3 0 0 1-3-3V19a3 3 0 0 1 3-3h36zm0 2H9a1 1 0 0 0-1 1v16a1 1 0 0 0 1 1h36a1 1 0 0 0 1-1V19a1 1 0 0 0-1-1zm-12 7h9l-4.5 6-4.5-6z"
|
|
4941
6007
|
})));
|
|
4942
6008
|
};
|
|
4943
|
-
var
|
|
6009
|
+
var SelectIcon = SvgSelect;
|
|
4944
6010
|
|
|
4945
|
-
var _path$4;
|
|
6011
|
+
var _path$4, _path2$1;
|
|
4946
6012
|
function _extends$4() { _extends$4 = 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$4.apply(this, arguments); }
|
|
4947
|
-
var
|
|
6013
|
+
var SvgSpacer = function SvgSpacer(props) {
|
|
4948
6014
|
return /*#__PURE__*/React.createElement("svg", _extends$4({
|
|
4949
6015
|
xmlns: "http://www.w3.org/2000/svg",
|
|
4950
6016
|
width: 54,
|
|
4951
6017
|
height: 54,
|
|
4952
6018
|
fill: "currentcolor"
|
|
4953
6019
|
}, props), _path$4 || (_path$4 = /*#__PURE__*/React.createElement("path", {
|
|
4954
|
-
|
|
4955
|
-
|
|
6020
|
+
stroke: "currentcolor",
|
|
6021
|
+
strokeLinecap: "square",
|
|
6022
|
+
strokeWidth: 2,
|
|
6023
|
+
d: "M9 23h36M9 31h36"
|
|
6024
|
+
})), _path2$1 || (_path2$1 = /*#__PURE__*/React.createElement("path", {
|
|
6025
|
+
stroke: "currentcolor",
|
|
6026
|
+
strokeLinecap: "round",
|
|
6027
|
+
strokeLinejoin: "round",
|
|
6028
|
+
strokeWidth: 2,
|
|
6029
|
+
d: "m23 17 4-4 4 4M31 37l-4 4-4-4"
|
|
4956
6030
|
})));
|
|
4957
6031
|
};
|
|
4958
|
-
var
|
|
6032
|
+
var SpacerIcon = SvgSpacer;
|
|
4959
6033
|
|
|
4960
6034
|
var _path$3;
|
|
4961
6035
|
function _extends$3() { _extends$3 = 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$3.apply(this, arguments); }
|
|
@@ -5026,12 +6100,14 @@ const iconsByType = type => {
|
|
|
5026
6100
|
button: ButtonIcon,
|
|
5027
6101
|
checkbox: CheckboxIcon,
|
|
5028
6102
|
checklist: ChecklistIcon,
|
|
5029
|
-
columns:
|
|
6103
|
+
columns: GroupIcon,
|
|
5030
6104
|
datetime: DatetimeIcon,
|
|
6105
|
+
group: GroupIcon,
|
|
5031
6106
|
image: ImageIcon,
|
|
5032
6107
|
number: NumberIcon,
|
|
5033
6108
|
radio: RadioIcon,
|
|
5034
6109
|
select: SelectIcon,
|
|
6110
|
+
spacer: SpacerIcon,
|
|
5035
6111
|
taglist: TaglistIcon,
|
|
5036
6112
|
text: TextIcon,
|
|
5037
6113
|
textfield: TextfieldIcon,
|
|
@@ -5040,7 +6116,7 @@ const iconsByType = type => {
|
|
|
5040
6116
|
}[type];
|
|
5041
6117
|
};
|
|
5042
6118
|
|
|
5043
|
-
const formFields = [Button, Checkbox, Checklist,
|
|
6119
|
+
const formFields = [Button, Checkbox, Checklist, FormComponent$1, Group, Image, Numberfield, Datetime, Radio, Select, Spacer, Taglist, Text, Textfield, Textarea];
|
|
5044
6120
|
|
|
5045
6121
|
class FormFields {
|
|
5046
6122
|
constructor() {
|
|
@@ -5116,9 +6192,12 @@ var renderModule = {
|
|
|
5116
6192
|
};
|
|
5117
6193
|
|
|
5118
6194
|
var core = {
|
|
5119
|
-
__depends__: [
|
|
6195
|
+
__depends__: [renderModule],
|
|
5120
6196
|
eventBus: ['type', EventBus],
|
|
6197
|
+
importer: ['type', Importer],
|
|
6198
|
+
fieldFactory: ['type', FieldFactory],
|
|
5121
6199
|
formFieldRegistry: ['type', FormFieldRegistry],
|
|
6200
|
+
pathRegistry: ['type', PathRegistry],
|
|
5122
6201
|
formLayouter: ['type', FormLayouter],
|
|
5123
6202
|
validator: ['type', Validator]
|
|
5124
6203
|
};
|
|
@@ -5233,9 +6312,9 @@ class Form {
|
|
|
5233
6312
|
this.clear();
|
|
5234
6313
|
const {
|
|
5235
6314
|
schema: importedSchema,
|
|
5236
|
-
data: initializedData,
|
|
5237
6315
|
warnings
|
|
5238
|
-
} = this.get('importer').importSchema(schema
|
|
6316
|
+
} = this.get('importer').importSchema(schema);
|
|
6317
|
+
const initializedData = this._initializeFieldData(clone(data));
|
|
5239
6318
|
this._setState({
|
|
5240
6319
|
data: initializedData,
|
|
5241
6320
|
errors: {},
|
|
@@ -5293,21 +6372,21 @@ class Form {
|
|
|
5293
6372
|
*/
|
|
5294
6373
|
validate() {
|
|
5295
6374
|
const formFieldRegistry = this.get('formFieldRegistry'),
|
|
6375
|
+
pathRegistry = this.get('pathRegistry'),
|
|
5296
6376
|
validator = this.get('validator');
|
|
5297
6377
|
const {
|
|
5298
6378
|
data
|
|
5299
6379
|
} = this._getState();
|
|
5300
6380
|
const errors = formFieldRegistry.getAll().reduce((errors, field) => {
|
|
5301
6381
|
const {
|
|
5302
|
-
disabled
|
|
5303
|
-
_path
|
|
6382
|
+
disabled
|
|
5304
6383
|
} = field;
|
|
5305
6384
|
if (disabled) {
|
|
5306
6385
|
return errors;
|
|
5307
6386
|
}
|
|
5308
|
-
const value = get(data,
|
|
6387
|
+
const value = get(data, pathRegistry.getValuePath(field));
|
|
5309
6388
|
const fieldErrors = validator.validateField(field, value);
|
|
5310
|
-
return set(errors, [
|
|
6389
|
+
return set(errors, [field.id], fieldErrors.length ? fieldErrors : undefined);
|
|
5311
6390
|
}, /** @type {Errors} */{});
|
|
5312
6391
|
this._setState({
|
|
5313
6392
|
errors
|
|
@@ -5413,16 +6492,14 @@ class Form {
|
|
|
5413
6492
|
value
|
|
5414
6493
|
} = update;
|
|
5415
6494
|
const {
|
|
5416
|
-
_path
|
|
5417
|
-
} = field;
|
|
5418
|
-
let {
|
|
5419
6495
|
data,
|
|
5420
6496
|
errors
|
|
5421
6497
|
} = this._getState();
|
|
5422
|
-
const validator = this.get('validator')
|
|
6498
|
+
const validator = this.get('validator'),
|
|
6499
|
+
pathRegistry = this.get('pathRegistry');
|
|
5423
6500
|
const fieldErrors = validator.validateField(field, value);
|
|
5424
|
-
set(data,
|
|
5425
|
-
set(errors, [
|
|
6501
|
+
set(data, pathRegistry.getValuePath(field), value);
|
|
6502
|
+
set(errors, [field.id], fieldErrors.length ? fieldErrors : undefined);
|
|
5426
6503
|
this._setState({
|
|
5427
6504
|
data: clone(data),
|
|
5428
6505
|
errors: clone(errors)
|
|
@@ -5451,7 +6528,7 @@ class Form {
|
|
|
5451
6528
|
* @internal
|
|
5452
6529
|
*/
|
|
5453
6530
|
_getModules() {
|
|
5454
|
-
return [ExpressionLanguageModule, MarkdownModule];
|
|
6531
|
+
return [ExpressionLanguageModule, MarkdownModule, ViewerCommandsModule];
|
|
5455
6532
|
}
|
|
5456
6533
|
|
|
5457
6534
|
/**
|
|
@@ -5465,23 +6542,26 @@ class Form {
|
|
|
5465
6542
|
* @internal
|
|
5466
6543
|
*/
|
|
5467
6544
|
_getSubmitData() {
|
|
5468
|
-
const formFieldRegistry = this.get('formFieldRegistry')
|
|
6545
|
+
const formFieldRegistry = this.get('formFieldRegistry'),
|
|
6546
|
+
pathRegistry = this.get('pathRegistry'),
|
|
6547
|
+
formFields = this.get('formFields');
|
|
5469
6548
|
const formData = this._getState().data;
|
|
5470
6549
|
const submitData = formFieldRegistry.getAll().reduce((previous, field) => {
|
|
5471
6550
|
const {
|
|
5472
6551
|
disabled,
|
|
5473
|
-
|
|
6552
|
+
type
|
|
5474
6553
|
} = field;
|
|
6554
|
+
const {
|
|
6555
|
+
config: fieldConfig
|
|
6556
|
+
} = formFields.get(type);
|
|
5475
6557
|
|
|
5476
|
-
// do not submit disabled form fields
|
|
5477
|
-
if (disabled || !
|
|
6558
|
+
// do not submit disabled form fields or routing fields
|
|
6559
|
+
if (disabled || !fieldConfig.keyed) {
|
|
5478
6560
|
return previous;
|
|
5479
6561
|
}
|
|
5480
|
-
const
|
|
5481
|
-
|
|
5482
|
-
|
|
5483
|
-
[_path[0]]: value
|
|
5484
|
-
};
|
|
6562
|
+
const valuePath = pathRegistry.getValuePath(field);
|
|
6563
|
+
const value = get(formData, valuePath);
|
|
6564
|
+
return set(previous, valuePath, value);
|
|
5485
6565
|
}, {});
|
|
5486
6566
|
const filteredSubmitData = this._applyConditions(submitData, formData);
|
|
5487
6567
|
return filteredSubmitData;
|
|
@@ -5494,9 +6574,46 @@ class Form {
|
|
|
5494
6574
|
const conditionChecker = this.get('conditionChecker');
|
|
5495
6575
|
return conditionChecker.applyConditions(toFilter, data);
|
|
5496
6576
|
}
|
|
6577
|
+
|
|
6578
|
+
/**
|
|
6579
|
+
* @internal
|
|
6580
|
+
*/
|
|
6581
|
+
_initializeFieldData(data) {
|
|
6582
|
+
const formFieldRegistry = this.get('formFieldRegistry'),
|
|
6583
|
+
formFields = this.get('formFields'),
|
|
6584
|
+
pathRegistry = this.get('pathRegistry');
|
|
6585
|
+
return formFieldRegistry.getAll().reduce((initializedData, formField) => {
|
|
6586
|
+
const {
|
|
6587
|
+
defaultValue,
|
|
6588
|
+
type
|
|
6589
|
+
} = formField;
|
|
6590
|
+
|
|
6591
|
+
// try to get value from data
|
|
6592
|
+
// if unavailable - try to get default value from form field
|
|
6593
|
+
// if unavailable - get empty value from form field
|
|
6594
|
+
|
|
6595
|
+
const valuePath = pathRegistry.getValuePath(formField);
|
|
6596
|
+
if (valuePath) {
|
|
6597
|
+
const {
|
|
6598
|
+
config: fieldConfig
|
|
6599
|
+
} = formFields.get(type);
|
|
6600
|
+
let valueData = get(data, valuePath);
|
|
6601
|
+
if (!isUndefined(valueData) && fieldConfig.sanitizeValue) {
|
|
6602
|
+
valueData = fieldConfig.sanitizeValue({
|
|
6603
|
+
formField,
|
|
6604
|
+
data,
|
|
6605
|
+
value: valueData
|
|
6606
|
+
});
|
|
6607
|
+
}
|
|
6608
|
+
const initializedFieldValue = !isUndefined(valueData) ? valueData : !isUndefined(defaultValue) ? defaultValue : fieldConfig.emptyValue;
|
|
6609
|
+
return set(initializedData, valuePath, initializedFieldValue);
|
|
6610
|
+
}
|
|
6611
|
+
return initializedData;
|
|
6612
|
+
}, data);
|
|
6613
|
+
}
|
|
5497
6614
|
}
|
|
5498
6615
|
|
|
5499
|
-
const schemaVersion =
|
|
6616
|
+
const schemaVersion = 11;
|
|
5500
6617
|
|
|
5501
6618
|
/**
|
|
5502
6619
|
* @typedef { import('./types').CreateFormOptions } CreateFormOptions
|
|
@@ -5521,5 +6638,5 @@ function createForm(options) {
|
|
|
5521
6638
|
});
|
|
5522
6639
|
}
|
|
5523
6640
|
|
|
5524
|
-
export { Button, Checkbox, Checklist, ConditionChecker, DATETIME_SUBTYPES, DATETIME_SUBTYPES_LABELS, DATETIME_SUBTYPE_PATH, DATE_DISALLOW_PAST_PATH, DATE_LABEL_PATH, Datetime, Default, ExpressionLanguageModule, FeelExpressionLanguage, FeelersTemplating, Form, FormComponent, FormContext$1 as FormContext, FormFieldRegistry, FormFields, FormLayouter, FormRenderContext$1 as FormRenderContext, Image, MINUTES_IN_DAY, MarkdownModule, MarkdownRenderer, Numberfield, Radio, Select, TIME_INTERVAL_PATH, TIME_LABEL_PATH, TIME_SERIALISINGFORMAT_LABELS, TIME_SERIALISING_FORMATS, TIME_SERIALISING_FORMAT_PATH, TIME_USE24H_PATH, Taglist, Text, Textarea, Textfield, VALUES_SOURCES, VALUES_SOURCES_DEFAULTS, VALUES_SOURCES_LABELS, VALUES_SOURCES_PATHS, VALUES_SOURCE_DEFAULT, clone, createForm, createFormContainer, createInjector,
|
|
6641
|
+
export { Button, Checkbox, Checklist, ConditionChecker, DATETIME_SUBTYPES, DATETIME_SUBTYPES_LABELS, DATETIME_SUBTYPE_PATH, DATE_DISALLOW_PAST_PATH, DATE_LABEL_PATH, Datetime, FormComponent$1 as Default, ExpressionLanguageModule, FeelExpressionLanguage, FeelersTemplating, FieldFactory, Form, FormComponent, FormContext$1 as FormContext, FormFieldRegistry, FormFields, FormLayouter, FormRenderContext$1 as FormRenderContext, Group, Image, Importer, MINUTES_IN_DAY, MarkdownModule, MarkdownRenderer, Numberfield, PathRegistry, Radio, Select, Spacer, TIME_INTERVAL_PATH, TIME_LABEL_PATH, TIME_SERIALISINGFORMAT_LABELS, TIME_SERIALISING_FORMATS, TIME_SERIALISING_FORMAT_PATH, TIME_USE24H_PATH, Taglist, Text, Textarea, Textfield, VALUES_SOURCES, VALUES_SOURCES_DEFAULTS, VALUES_SOURCES_LABELS, VALUES_SOURCES_PATHS, VALUES_SOURCE_DEFAULT, ViewerCommands, ViewerCommandsModule, clone, createForm, createFormContainer, createInjector, formFields, generateIdForType, generateIndexForType, getSchemaVariables, getValuesSource, iconsByType, isRequired, pathParse, pathsEqual, runRecursively, schemaVersion };
|
|
5525
6642
|
//# sourceMappingURL=index.es.js.map
|