@bpmn-io/form-js-viewer 1.6.0 → 1.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -22
- package/README.md +189 -189
- package/dist/assets/form-js-base.css +1244 -1244
- package/dist/index.cjs +777 -684
- package/dist/index.cjs.map +1 -1
- package/dist/index.es.js +778 -685
- package/dist/index.es.js.map +1 -1
- package/dist/types/render/components/util/sanitizerUtil.d.ts +1 -0
- package/dist/types/render/hooks/useFlushDebounce.d.ts +2 -0
- package/dist/types/render/hooks/useGetLabelCorrelation.d.ts +5 -0
- package/dist/types/types.d.ts +35 -35
- package/package.json +3 -2
package/dist/index.es.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import Ids from 'ids';
|
|
2
|
-
import { isString, get, some, isNumber, set, findIndex, isArray,
|
|
2
|
+
import { isString, get, some, isNil, isObject, isNumber, set, findIndex, isArray, isDefined, values, uniqueBy, isFunction, bind, assign, groupBy, flatten, isUndefined } from 'min-dash';
|
|
3
3
|
import Big from 'big.js';
|
|
4
4
|
import classNames from 'classnames';
|
|
5
5
|
import { jsx, jsxs, Fragment } from 'preact/jsx-runtime';
|
|
6
6
|
import { useContext, useMemo, useEffect, useRef, useState, useCallback, useLayoutEffect } from 'preact/hooks';
|
|
7
7
|
import { createContext, createElement, Fragment as Fragment$1, render } from 'preact';
|
|
8
|
+
import isEqual from 'lodash/isEqual';
|
|
8
9
|
import flatpickr from 'flatpickr';
|
|
9
10
|
import * as React from 'preact/compat';
|
|
10
11
|
import { createPortal } from 'preact/compat';
|
|
@@ -53,26 +54,26 @@ const getFlavouredFeelVariableNames = (feelString, feelFlavour = 'expression', o
|
|
|
53
54
|
return [...new Set(variables)];
|
|
54
55
|
};
|
|
55
56
|
|
|
56
|
-
/**
|
|
57
|
-
* Get the variable name at the specified index in a given path expression.
|
|
58
|
-
*
|
|
59
|
-
* @param {Object} root - The root node of the path expression tree.
|
|
60
|
-
* @param {number} index - The index of the variable name to retrieve.
|
|
61
|
-
* @returns {string|null} The variable name at the specified index or null if index is out of bounds.
|
|
57
|
+
/**
|
|
58
|
+
* Get the variable name at the specified index in a given path expression.
|
|
59
|
+
*
|
|
60
|
+
* @param {Object} root - The root node of the path expression tree.
|
|
61
|
+
* @param {number} index - The index of the variable name to retrieve.
|
|
62
|
+
* @returns {string|null} The variable name at the specified index or null if index is out of bounds.
|
|
62
63
|
*/
|
|
63
64
|
const _getVariableNameAtPathIndex = (root, index) => {
|
|
64
65
|
const nodes = _linearizePathExpression(root);
|
|
65
66
|
return nodes[index].variableName || null;
|
|
66
67
|
};
|
|
67
68
|
|
|
68
|
-
/**
|
|
69
|
-
* Extracts the variables which are required of the external context for a given path expression.
|
|
70
|
-
* This is done by traversing the path expression tree and keeping track of the current depth relative to the external context.
|
|
71
|
-
*
|
|
72
|
-
* @param {Object} node - The root node of the path expression tree.
|
|
73
|
-
* @param {number} initialDepth - The depth at which the root node is located in the outer context.
|
|
74
|
-
* @param {Object} specialDepthAccessors - Definitions of special keywords which represent more complex accesses of the outer context.
|
|
75
|
-
* @returns {Set} - A set containing the extracted variable names.
|
|
69
|
+
/**
|
|
70
|
+
* Extracts the variables which are required of the external context for a given path expression.
|
|
71
|
+
* This is done by traversing the path expression tree and keeping track of the current depth relative to the external context.
|
|
72
|
+
*
|
|
73
|
+
* @param {Object} node - The root node of the path expression tree.
|
|
74
|
+
* @param {number} initialDepth - The depth at which the root node is located in the outer context.
|
|
75
|
+
* @param {Object} specialDepthAccessors - Definitions of special keywords which represent more complex accesses of the outer context.
|
|
76
|
+
* @returns {Set} - A set containing the extracted variable names.
|
|
76
77
|
*/
|
|
77
78
|
const _smartExtractVariableNames = (node, initialDepth, specialDepthAccessors) => {
|
|
78
79
|
// depth info represents the previous (initialised as null) and current depth of the current accessor in the path expression
|
|
@@ -118,11 +119,11 @@ const _smartExtractVariableNames = (node, initialDepth, specialDepthAccessors) =
|
|
|
118
119
|
return new Set(extractedVariables);
|
|
119
120
|
};
|
|
120
121
|
|
|
121
|
-
/**
|
|
122
|
-
* Deconstructs a path expression tree into an array of components.
|
|
123
|
-
*
|
|
124
|
-
* @param {Object} root - The root node of the path expression tree.
|
|
125
|
-
* @returns {Array<object>} An array of components in the path expression, in the correct order.
|
|
122
|
+
/**
|
|
123
|
+
* Deconstructs a path expression tree into an array of components.
|
|
124
|
+
*
|
|
125
|
+
* @param {Object} root - The root node of the path expression tree.
|
|
126
|
+
* @returns {Array<object>} An array of components in the path expression, in the correct order.
|
|
126
127
|
*/
|
|
127
128
|
const _linearizePathExpression = root => {
|
|
128
129
|
let node = root;
|
|
@@ -141,13 +142,13 @@ const _linearizePathExpression = root => {
|
|
|
141
142
|
return parts.reverse();
|
|
142
143
|
};
|
|
143
144
|
|
|
144
|
-
/**
|
|
145
|
-
* Builds a simplified feel structure tree from the given parse tree and feel string.
|
|
146
|
-
* The nodes follow this structure: `{ name: string, children: Array, variableName?: string }`
|
|
147
|
-
*
|
|
148
|
-
* @param {Object} parseTree - The parse tree generated by a parser.
|
|
149
|
-
* @param {string} feelString - The feel string used for parsing.
|
|
150
|
-
* @returns {Object} The simplified feel structure tree.
|
|
145
|
+
/**
|
|
146
|
+
* Builds a simplified feel structure tree from the given parse tree and feel string.
|
|
147
|
+
* The nodes follow this structure: `{ name: string, children: Array, variableName?: string }`
|
|
148
|
+
*
|
|
149
|
+
* @param {Object} parseTree - The parse tree generated by a parser.
|
|
150
|
+
* @param {string} feelString - The feel string used for parsing.
|
|
151
|
+
* @returns {Object} The simplified feel structure tree.
|
|
151
152
|
*/
|
|
152
153
|
const _buildSimpleFeelStructureTree = (parseTree, feelString) => {
|
|
153
154
|
const stack = [{
|
|
@@ -173,9 +174,9 @@ const _buildSimpleFeelStructureTree = (parseTree, feelString) => {
|
|
|
173
174
|
return _extractFilterExpressions(stack[0].children[0]);
|
|
174
175
|
};
|
|
175
176
|
|
|
176
|
-
/**
|
|
177
|
-
* Restructure the tree in such a way to bring filters (which create new contexts) to the root of the tree.
|
|
178
|
-
* This is done to simplify the extraction of variables and match the context hierarchy.
|
|
177
|
+
/**
|
|
178
|
+
* Restructure the tree in such a way to bring filters (which create new contexts) to the root of the tree.
|
|
179
|
+
* This is done to simplify the extraction of variables and match the context hierarchy.
|
|
179
180
|
*/
|
|
180
181
|
const _extractFilterExpressions = tree => {
|
|
181
182
|
const flattenedExpressionTree = {
|
|
@@ -216,25 +217,25 @@ class FeelExpressionLanguage {
|
|
|
216
217
|
this._eventBus = eventBus;
|
|
217
218
|
}
|
|
218
219
|
|
|
219
|
-
/**
|
|
220
|
-
* Determines if the given value is a FEEL expression.
|
|
221
|
-
*
|
|
222
|
-
* @param {any} value
|
|
223
|
-
* @returns {boolean}
|
|
224
|
-
*
|
|
220
|
+
/**
|
|
221
|
+
* Determines if the given value is a FEEL expression.
|
|
222
|
+
*
|
|
223
|
+
* @param {any} value
|
|
224
|
+
* @returns {boolean}
|
|
225
|
+
*
|
|
225
226
|
*/
|
|
226
227
|
isExpression(value) {
|
|
227
228
|
return isString(value) && value.startsWith('=');
|
|
228
229
|
}
|
|
229
230
|
|
|
230
|
-
/**
|
|
231
|
-
* Retrieve variable names from a given FEEL expression.
|
|
232
|
-
*
|
|
233
|
-
* @param {string} expression
|
|
234
|
-
* @param {object} [options]
|
|
235
|
-
* @param {string} [options.type]
|
|
236
|
-
*
|
|
237
|
-
* @returns {string[]}
|
|
231
|
+
/**
|
|
232
|
+
* Retrieve variable names from a given FEEL expression.
|
|
233
|
+
*
|
|
234
|
+
* @param {string} expression
|
|
235
|
+
* @param {object} [options]
|
|
236
|
+
* @param {string} [options.type]
|
|
237
|
+
*
|
|
238
|
+
* @returns {string[]}
|
|
238
239
|
*/
|
|
239
240
|
getVariableNames(expression, options = {}) {
|
|
240
241
|
const {
|
|
@@ -249,13 +250,13 @@ class FeelExpressionLanguage {
|
|
|
249
250
|
return getFlavouredFeelVariableNames(expression, type);
|
|
250
251
|
}
|
|
251
252
|
|
|
252
|
-
/**
|
|
253
|
-
* Evaluate an expression.
|
|
254
|
-
*
|
|
255
|
-
* @param {string} expression
|
|
256
|
-
* @param {import('../../types').Data} [data]
|
|
257
|
-
*
|
|
258
|
-
* @returns {any}
|
|
253
|
+
/**
|
|
254
|
+
* Evaluate an expression.
|
|
255
|
+
*
|
|
256
|
+
* @param {string} expression
|
|
257
|
+
* @param {import('../../types').Data} [data]
|
|
258
|
+
*
|
|
259
|
+
* @returns {any}
|
|
259
260
|
*/
|
|
260
261
|
evaluate(expression, data = {}) {
|
|
261
262
|
if (!expression) {
|
|
@@ -280,23 +281,23 @@ FeelExpressionLanguage.$inject = ['eventBus'];
|
|
|
280
281
|
class FeelersTemplating {
|
|
281
282
|
constructor() {}
|
|
282
283
|
|
|
283
|
-
/**
|
|
284
|
-
* Determines if the given value is a feelers template.
|
|
285
|
-
*
|
|
286
|
-
* @param {any} value
|
|
287
|
-
* @returns {boolean}
|
|
288
|
-
*
|
|
284
|
+
/**
|
|
285
|
+
* Determines if the given value is a feelers template.
|
|
286
|
+
*
|
|
287
|
+
* @param {any} value
|
|
288
|
+
* @returns {boolean}
|
|
289
|
+
*
|
|
289
290
|
*/
|
|
290
291
|
isTemplate(value) {
|
|
291
292
|
return isString(value) && (value.startsWith('=') || /{{.*?}}/.test(value));
|
|
292
293
|
}
|
|
293
294
|
|
|
294
|
-
/**
|
|
295
|
-
* Retrieve variable names from a given feelers template.
|
|
296
|
-
*
|
|
297
|
-
* @param {string} template
|
|
298
|
-
*
|
|
299
|
-
* @returns {string[]}
|
|
295
|
+
/**
|
|
296
|
+
* Retrieve variable names from a given feelers template.
|
|
297
|
+
*
|
|
298
|
+
* @param {string} template
|
|
299
|
+
*
|
|
300
|
+
* @returns {string[]}
|
|
300
301
|
*/
|
|
301
302
|
getVariableNames(template) {
|
|
302
303
|
if (!this.isTemplate(template)) {
|
|
@@ -322,17 +323,17 @@ class FeelersTemplating {
|
|
|
322
323
|
}, []);
|
|
323
324
|
}
|
|
324
325
|
|
|
325
|
-
/**
|
|
326
|
-
* Evaluate a template.
|
|
327
|
-
*
|
|
328
|
-
* @param {string} template
|
|
329
|
-
* @param {Object<string, any>} context
|
|
330
|
-
* @param {Object} options
|
|
331
|
-
* @param {boolean} [options.debug = false]
|
|
332
|
-
* @param {boolean} [options.strict = false]
|
|
333
|
-
* @param {Function} [options.buildDebugString]
|
|
334
|
-
*
|
|
335
|
-
* @returns
|
|
326
|
+
/**
|
|
327
|
+
* Evaluate a template.
|
|
328
|
+
*
|
|
329
|
+
* @param {string} template
|
|
330
|
+
* @param {Object<string, any>} context
|
|
331
|
+
* @param {Object} options
|
|
332
|
+
* @param {boolean} [options.debug = false]
|
|
333
|
+
* @param {boolean} [options.strict = false]
|
|
334
|
+
* @param {Function} [options.buildDebugString]
|
|
335
|
+
*
|
|
336
|
+
* @returns
|
|
336
337
|
*/
|
|
337
338
|
evaluate(template, context = {}, options = {}) {
|
|
338
339
|
const {
|
|
@@ -347,22 +348,22 @@ class FeelersTemplating {
|
|
|
347
348
|
});
|
|
348
349
|
}
|
|
349
350
|
|
|
350
|
-
/**
|
|
351
|
-
* @typedef {Object} ExpressionWithDepth
|
|
352
|
-
* @property {number} depth - The depth of the expression in the syntax tree.
|
|
353
|
-
* @property {string} expression - The extracted expression
|
|
351
|
+
/**
|
|
352
|
+
* @typedef {Object} ExpressionWithDepth
|
|
353
|
+
* @property {number} depth - The depth of the expression in the syntax tree.
|
|
354
|
+
* @property {string} expression - The extracted expression
|
|
354
355
|
*/
|
|
355
356
|
|
|
356
|
-
/**
|
|
357
|
-
* Extracts all feel expressions in the template along with their depth in the syntax tree.
|
|
358
|
-
* The depth is incremented for child expressions of loops to account for context drilling.
|
|
359
|
-
|
|
360
|
-
* @param {string} template - A feelers template string.
|
|
361
|
-
* @returns {Array<ExpressionWithDepth>} An array of objects, each containing the depth and the extracted expression.
|
|
362
|
-
*
|
|
363
|
-
* @example
|
|
364
|
-
* const template = "Hello {{user}}, you have:{{#loop items}}\n- {{amount}} {{name}}{{/loop}}.";
|
|
365
|
-
* const extractedExpressions = _extractExpressionsWithDepth(template);
|
|
357
|
+
/**
|
|
358
|
+
* Extracts all feel expressions in the template along with their depth in the syntax tree.
|
|
359
|
+
* The depth is incremented for child expressions of loops to account for context drilling.
|
|
360
|
+
* @name extractExpressionsWithDepth
|
|
361
|
+
* @param {string} template - A feelers template string.
|
|
362
|
+
* @returns {Array<ExpressionWithDepth>} An array of objects, each containing the depth and the extracted expression.
|
|
363
|
+
*
|
|
364
|
+
* @example
|
|
365
|
+
* const template = "Hello {{user}}, you have:{{#loop items}}\n- {{amount}} {{name}}{{/loop}}.";
|
|
366
|
+
* const extractedExpressions = _extractExpressionsWithDepth(template);
|
|
366
367
|
*/
|
|
367
368
|
_extractExpressionsWithDepth(template) {
|
|
368
369
|
// build simplified feelers syntax tree
|
|
@@ -468,10 +469,10 @@ function createInjector(bootstrapModules) {
|
|
|
468
469
|
return injector;
|
|
469
470
|
}
|
|
470
471
|
|
|
471
|
-
/**
|
|
472
|
-
* @param {string?} prefix
|
|
473
|
-
*
|
|
474
|
-
* @returns Element
|
|
472
|
+
/**
|
|
473
|
+
* @param {string?} prefix
|
|
474
|
+
*
|
|
475
|
+
* @returns Element
|
|
475
476
|
*/
|
|
476
477
|
function createFormContainer(prefix = 'fjs') {
|
|
477
478
|
const container = document.createElement('div');
|
|
@@ -602,11 +603,11 @@ const LocalExpressionContext = createContext({
|
|
|
602
603
|
});
|
|
603
604
|
var LocalExpressionContext$1 = LocalExpressionContext;
|
|
604
605
|
|
|
605
|
-
/**
|
|
606
|
-
* @param {string} type
|
|
607
|
-
* @param {boolean} [strict]
|
|
608
|
-
*
|
|
609
|
-
* @returns {any}
|
|
606
|
+
/**
|
|
607
|
+
* @param {string} type
|
|
608
|
+
* @param {boolean} [strict]
|
|
609
|
+
*
|
|
610
|
+
* @returns {any}
|
|
610
611
|
*/
|
|
611
612
|
function getService(type, strict) {}
|
|
612
613
|
const FormContext = createContext({
|
|
@@ -649,21 +650,21 @@ function generateIdForType(type) {
|
|
|
649
650
|
return `${type}${generateIndexForType(type)}`;
|
|
650
651
|
}
|
|
651
652
|
|
|
652
|
-
/**
|
|
653
|
-
* @template T
|
|
654
|
-
* @param {T} data
|
|
655
|
-
* @param {(this: any, key: string, value: any) => any} [replacer]
|
|
656
|
-
* @return {T}
|
|
653
|
+
/**
|
|
654
|
+
* @template T
|
|
655
|
+
* @param {T} data
|
|
656
|
+
* @param {(this: any, key: string, value: any) => any} [replacer]
|
|
657
|
+
* @return {T}
|
|
657
658
|
*/
|
|
658
659
|
function clone(data, replacer) {
|
|
659
660
|
return JSON.parse(JSON.stringify(data, replacer));
|
|
660
661
|
}
|
|
661
662
|
|
|
662
|
-
/**
|
|
663
|
-
* Transform a LocalExpressionContext object into a usable FEEL context.
|
|
664
|
-
*
|
|
665
|
-
* @param {Object} context - The LocalExpressionContext object.
|
|
666
|
-
* @returns {Object} The usable FEEL context.
|
|
663
|
+
/**
|
|
664
|
+
* Transform a LocalExpressionContext object into a usable FEEL context.
|
|
665
|
+
*
|
|
666
|
+
* @param {Object} context - The LocalExpressionContext object.
|
|
667
|
+
* @returns {Object} The usable FEEL context.
|
|
667
668
|
*/
|
|
668
669
|
|
|
669
670
|
function buildExpressionContext(context) {
|
|
@@ -695,12 +696,12 @@ function _wrapObjectKeysWithUnderscores(obj) {
|
|
|
695
696
|
return newObj;
|
|
696
697
|
}
|
|
697
698
|
|
|
698
|
-
/**
|
|
699
|
-
* Evaluate if condition is met reactively based on the conditionChecker and form data.
|
|
700
|
-
*
|
|
701
|
-
* @param {string | undefined} condition
|
|
702
|
-
*
|
|
703
|
-
* @returns {boolean} true if condition is met or no condition or condition checker exists
|
|
699
|
+
/**
|
|
700
|
+
* Evaluate if condition is met reactively based on the conditionChecker and form data.
|
|
701
|
+
*
|
|
702
|
+
* @param {string | undefined} condition
|
|
703
|
+
*
|
|
704
|
+
* @returns {boolean} true if condition is met or no condition or condition checker exists
|
|
704
705
|
*/
|
|
705
706
|
function useCondition(condition) {
|
|
706
707
|
const conditionChecker = useService('conditionChecker', false);
|
|
@@ -710,17 +711,17 @@ function useCondition(condition) {
|
|
|
710
711
|
}, [conditionChecker, condition, expressionContextInfo]);
|
|
711
712
|
}
|
|
712
713
|
|
|
713
|
-
/**
|
|
714
|
-
* Custom hook to scroll an element into view only when it is not visible within the viewport.
|
|
715
|
-
*
|
|
716
|
-
* @param {Object} targetRef - A ref pointing to the DOM element to scroll into view.
|
|
717
|
-
* @param {Array} deps - An array of dependencies that trigger the effect.
|
|
718
|
-
* @param {Array} flagRefs - An array of refs that are used as flags to control when to scroll.
|
|
719
|
-
* @param {Object} [scrollOptions={}] - Options defining the behavior of the scrolling.
|
|
720
|
-
* @param {String} [scrollOptions.align='center'] - The alignment of the element within the viewport.
|
|
721
|
-
* @param {String} [scrollOptions.behavior='auto'] - The scrolling behavior.
|
|
722
|
-
* @param {Number} [scrollOptions.offset=0] - An offset that is added to the scroll position.
|
|
723
|
-
* @param {Boolean} [scrollOptions.scrollIfVisible=false] - Whether to scroll even if the element is visible.
|
|
714
|
+
/**
|
|
715
|
+
* Custom hook to scroll an element into view only when it is not visible within the viewport.
|
|
716
|
+
*
|
|
717
|
+
* @param {Object} targetRef - A ref pointing to the DOM element to scroll into view.
|
|
718
|
+
* @param {Array} deps - An array of dependencies that trigger the effect.
|
|
719
|
+
* @param {Array} flagRefs - An array of refs that are used as flags to control when to scroll.
|
|
720
|
+
* @param {Object} [scrollOptions={}] - Options defining the behavior of the scrolling.
|
|
721
|
+
* @param {String} [scrollOptions.align='center'] - The alignment of the element within the viewport.
|
|
722
|
+
* @param {String} [scrollOptions.behavior='auto'] - The scrolling behavior.
|
|
723
|
+
* @param {Number} [scrollOptions.offset=0] - An offset that is added to the scroll position.
|
|
724
|
+
* @param {Boolean} [scrollOptions.scrollIfVisible=false] - Whether to scroll even if the element is visible.
|
|
724
725
|
*/
|
|
725
726
|
function useScrollIntoView(targetRef, deps, scrollOptions = null, flagRefs = []) {
|
|
726
727
|
useEffect(() => {
|
|
@@ -785,13 +786,13 @@ function _getTopOffset(item, scrollContainer, options) {
|
|
|
785
786
|
return 0;
|
|
786
787
|
}
|
|
787
788
|
|
|
788
|
-
/**
|
|
789
|
-
* Evaluate a string reactively based on the expressionLanguage and form data.
|
|
790
|
-
* If the string is not an expression, it is returned as is.
|
|
791
|
-
* The function is memoized to minimize re-renders.
|
|
792
|
-
*
|
|
793
|
-
* @param {string} value - The string to evaluate.
|
|
794
|
-
* @returns {any} - Evaluated value or the original value if not an expression.
|
|
789
|
+
/**
|
|
790
|
+
* Evaluate a string reactively based on the expressionLanguage and form data.
|
|
791
|
+
* If the string is not an expression, it is returned as is.
|
|
792
|
+
* The function is memoized to minimize re-renders.
|
|
793
|
+
*
|
|
794
|
+
* @param {string} value - The string to evaluate.
|
|
795
|
+
* @returns {any} - Evaluated value or the original value if not an expression.
|
|
795
796
|
*/
|
|
796
797
|
function useExpressionEvaluation(value) {
|
|
797
798
|
const expressionLanguage = useService('expressionLanguage');
|
|
@@ -804,11 +805,11 @@ function useExpressionEvaluation(value) {
|
|
|
804
805
|
}, [expressionLanguage, expressionContextInfo, value]);
|
|
805
806
|
}
|
|
806
807
|
|
|
807
|
-
/**
|
|
808
|
-
* Returns the conditionally filtered data of a form reactively.
|
|
809
|
-
* Memoised to minimize re-renders
|
|
810
|
-
*
|
|
811
|
-
* Warning: costly operation, use with care
|
|
808
|
+
/**
|
|
809
|
+
* Returns the conditionally filtered data of a form reactively.
|
|
810
|
+
* Memoised to minimize re-renders
|
|
811
|
+
*
|
|
812
|
+
* Warning: costly operation, use with care
|
|
812
813
|
*/
|
|
813
814
|
function useFilteredFormData() {
|
|
814
815
|
const {
|
|
@@ -841,16 +842,16 @@ function useKeyDownAction(targetKey, action, listenerElement = window) {
|
|
|
841
842
|
});
|
|
842
843
|
}
|
|
843
844
|
|
|
844
|
-
/**
|
|
845
|
-
* Retrieve readonly value of a form field, given it can be an
|
|
846
|
-
* expression optionally or configured globally.
|
|
847
|
-
*
|
|
848
|
-
* @typedef { import('../../types').FormProperties } FormProperties
|
|
849
|
-
*
|
|
850
|
-
* @param {any} formField
|
|
851
|
-
* @param {FormProperties} properties
|
|
852
|
-
*
|
|
853
|
-
* @returns {boolean}
|
|
845
|
+
/**
|
|
846
|
+
* Retrieve readonly value of a form field, given it can be an
|
|
847
|
+
* expression optionally or configured globally.
|
|
848
|
+
*
|
|
849
|
+
* @typedef { import('../../types').FormProperties } FormProperties
|
|
850
|
+
*
|
|
851
|
+
* @param {any} formField
|
|
852
|
+
* @param {FormProperties} properties
|
|
853
|
+
*
|
|
854
|
+
* @returns {boolean}
|
|
854
855
|
*/
|
|
855
856
|
function useReadonly(formField, properties = {}) {
|
|
856
857
|
const expressionLanguage = useService('expressionLanguage');
|
|
@@ -874,12 +875,12 @@ function usePrevious(value, defaultValue, dependencies) {
|
|
|
874
875
|
return ref.current;
|
|
875
876
|
}
|
|
876
877
|
|
|
877
|
-
/**
|
|
878
|
-
* A custom hook to manage state changes with deep comparison.
|
|
879
|
-
*
|
|
880
|
-
* @param {any} value - The current value to manage.
|
|
881
|
-
* @param {any} defaultValue - The initial default value for the state.
|
|
882
|
-
* @returns {any} - Returns the current state.
|
|
878
|
+
/**
|
|
879
|
+
* A custom hook to manage state changes with deep comparison.
|
|
880
|
+
*
|
|
881
|
+
* @param {any} value - The current value to manage.
|
|
882
|
+
* @param {any} defaultValue - The initial default value for the state.
|
|
883
|
+
* @returns {any} - Returns the current state.
|
|
883
884
|
*/
|
|
884
885
|
function useDeepCompareState(value, defaultValue) {
|
|
885
886
|
const [state, setState] = useState(defaultValue);
|
|
@@ -899,16 +900,16 @@ function compare(a, b) {
|
|
|
899
900
|
return JSON.stringify(a) === JSON.stringify(b);
|
|
900
901
|
}
|
|
901
902
|
|
|
902
|
-
/**
|
|
903
|
-
* Template a string reactively based on form data. If the string is not a template, it is returned as is.
|
|
904
|
-
* Memoised to minimize re-renders
|
|
905
|
-
*
|
|
906
|
-
* @param {string} value
|
|
907
|
-
* @param {Object} options
|
|
908
|
-
* @param {boolean} [options.debug = false]
|
|
909
|
-
* @param {boolean} [options.strict = false]
|
|
910
|
-
* @param {Function} [options.buildDebugString]
|
|
911
|
-
*
|
|
903
|
+
/**
|
|
904
|
+
* Template a string reactively based on form data. If the string is not a template, it is returned as is.
|
|
905
|
+
* Memoised to minimize re-renders
|
|
906
|
+
*
|
|
907
|
+
* @param {string} value
|
|
908
|
+
* @param {Object} options
|
|
909
|
+
* @param {boolean} [options.debug = false]
|
|
910
|
+
* @param {boolean} [options.strict = false]
|
|
911
|
+
* @param {Function} [options.buildDebugString]
|
|
912
|
+
*
|
|
912
913
|
*/
|
|
913
914
|
function useTemplateEvaluation(value, options = {}) {
|
|
914
915
|
const templating = useService('templating');
|
|
@@ -921,17 +922,17 @@ function useTemplateEvaluation(value, options = {}) {
|
|
|
921
922
|
}, [templating, value, expressionContextInfo, options]);
|
|
922
923
|
}
|
|
923
924
|
|
|
924
|
-
/**
|
|
925
|
-
* Template a string reactively based on form data. If the string is not a template, it is returned as is.
|
|
926
|
-
* If the string contains multiple lines, only the first line is returned.
|
|
927
|
-
* Memoised to minimize re-renders
|
|
928
|
-
*
|
|
929
|
-
* @param {string} value
|
|
930
|
-
* @param {Object} [options]
|
|
931
|
-
* @param {boolean} [options.debug = false]
|
|
932
|
-
* @param {boolean} [options.strict = false]
|
|
933
|
-
* @param {Function} [options.buildDebugString]
|
|
934
|
-
*
|
|
925
|
+
/**
|
|
926
|
+
* Template a string reactively based on form data. If the string is not a template, it is returned as is.
|
|
927
|
+
* If the string contains multiple lines, only the first line is returned.
|
|
928
|
+
* Memoised to minimize re-renders
|
|
929
|
+
*
|
|
930
|
+
* @param {string} value
|
|
931
|
+
* @param {Object} [options]
|
|
932
|
+
* @param {boolean} [options.debug = false]
|
|
933
|
+
* @param {boolean} [options.strict = false]
|
|
934
|
+
* @param {Function} [options.buildDebugString]
|
|
935
|
+
*
|
|
935
936
|
*/
|
|
936
937
|
function useSingleLineTemplateEvaluation(value, options = {}) {
|
|
937
938
|
const evaluatedTemplate = useTemplateEvaluation(value, options);
|
|
@@ -1084,39 +1085,58 @@ function getOptionsData(formField, formData) {
|
|
|
1084
1085
|
|
|
1085
1086
|
// transforms the provided options into a normalized format, trimming invalid options
|
|
1086
1087
|
function normalizeOptionsData(optionsData) {
|
|
1087
|
-
return optionsData.filter(
|
|
1088
|
+
return optionsData.filter(_isAllowedValue).map(_normalizeOption).filter(o => !isNil(o));
|
|
1088
1089
|
}
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1090
|
+
|
|
1091
|
+
/**
|
|
1092
|
+
* Converts the provided option to a normalized format.
|
|
1093
|
+
* If the option is not valid, null is returned.
|
|
1094
|
+
*
|
|
1095
|
+
* @param {object} option
|
|
1096
|
+
* @param {string} option.label
|
|
1097
|
+
* @param {*} option.value
|
|
1098
|
+
*
|
|
1099
|
+
* @returns
|
|
1100
|
+
*/
|
|
1101
|
+
function _normalizeOption(option) {
|
|
1102
|
+
// (1) simple primitive case, use it as both label and value
|
|
1103
|
+
if (_isAllowedPrimitive(option)) {
|
|
1092
1104
|
return {
|
|
1093
|
-
value:
|
|
1094
|
-
label: `${
|
|
1105
|
+
value: option,
|
|
1106
|
+
label: `${option}`
|
|
1095
1107
|
};
|
|
1096
1108
|
}
|
|
1097
|
-
if (
|
|
1098
|
-
|
|
1099
|
-
|
|
1109
|
+
if (isObject(option)) {
|
|
1110
|
+
const isValidLabel = _isValidLabel(option.label);
|
|
1111
|
+
|
|
1112
|
+
// (2) no label provided, but value is a simple primitive, use it as label and value
|
|
1113
|
+
if (!isValidLabel && _isAllowedPrimitive(option.value)) {
|
|
1100
1114
|
return {
|
|
1101
|
-
value:
|
|
1102
|
-
label: `${
|
|
1115
|
+
value: option.value,
|
|
1116
|
+
label: `${option.value}`
|
|
1103
1117
|
};
|
|
1104
1118
|
}
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1119
|
+
|
|
1120
|
+
// (3) both label and value are provided, use them as is
|
|
1121
|
+
if (isValidLabel && _isAllowedValue(option.value)) {
|
|
1122
|
+
return option;
|
|
1108
1123
|
}
|
|
1109
1124
|
}
|
|
1110
1125
|
return null;
|
|
1111
1126
|
}
|
|
1112
|
-
function
|
|
1113
|
-
|
|
1127
|
+
function _isAllowedPrimitive(value) {
|
|
1128
|
+
const isAllowedPrimitiveType = ['number', 'string', 'boolean'].includes(typeof value);
|
|
1129
|
+
const isValid = value || value === 0 || value === false;
|
|
1130
|
+
return isAllowedPrimitiveType && isValid;
|
|
1114
1131
|
}
|
|
1115
|
-
function
|
|
1116
|
-
return
|
|
1132
|
+
function _isValidLabel(label) {
|
|
1133
|
+
return label && isString(label);
|
|
1117
1134
|
}
|
|
1118
|
-
function
|
|
1119
|
-
|
|
1135
|
+
function _isAllowedValue(value) {
|
|
1136
|
+
if (isObject(value)) {
|
|
1137
|
+
return Object.keys(value).length > 0;
|
|
1138
|
+
}
|
|
1139
|
+
return _isAllowedPrimitive(value);
|
|
1120
1140
|
}
|
|
1121
1141
|
function createEmptyOptions(options = {}) {
|
|
1122
1142
|
const defaults = {};
|
|
@@ -1134,8 +1154,8 @@ function createEmptyOptions(options = {}) {
|
|
|
1134
1154
|
};
|
|
1135
1155
|
}
|
|
1136
1156
|
|
|
1137
|
-
/**
|
|
1138
|
-
* @enum { String }
|
|
1157
|
+
/**
|
|
1158
|
+
* @enum { String }
|
|
1139
1159
|
*/
|
|
1140
1160
|
const LOAD_STATES = {
|
|
1141
1161
|
LOADING: 'loading',
|
|
@@ -1143,17 +1163,17 @@ const LOAD_STATES = {
|
|
|
1143
1163
|
ERROR: 'error'
|
|
1144
1164
|
};
|
|
1145
1165
|
|
|
1146
|
-
/**
|
|
1147
|
-
* @typedef {Object} OptionsGetter
|
|
1148
|
-
* @property {Object[]} options - The options data
|
|
1149
|
-
* @property {(LOAD_STATES)} loadState - The options data's loading state, to use for conditional rendering
|
|
1166
|
+
/**
|
|
1167
|
+
* @typedef {Object} OptionsGetter
|
|
1168
|
+
* @property {Object[]} options - The options data
|
|
1169
|
+
* @property {(LOAD_STATES)} loadState - The options data's loading state, to use for conditional rendering
|
|
1150
1170
|
*/
|
|
1151
1171
|
|
|
1152
|
-
/**
|
|
1153
|
-
* A hook to load options for single and multiselect components.
|
|
1154
|
-
*
|
|
1155
|
-
* @param {Object} field - The form field to handle options for
|
|
1156
|
-
* @return {OptionsGetter} optionsGetter - A options getter object providing loading state and options
|
|
1172
|
+
/**
|
|
1173
|
+
* A hook to load options for single and multiselect components.
|
|
1174
|
+
*
|
|
1175
|
+
* @param {Object} field - The form field to handle options for
|
|
1176
|
+
* @return {OptionsGetter} optionsGetter - A options getter object providing loading state and options
|
|
1157
1177
|
*/
|
|
1158
1178
|
function useOptionsAsync (field) {
|
|
1159
1179
|
const {
|
|
@@ -1210,30 +1230,6 @@ const buildLoadedState = options => ({
|
|
|
1210
1230
|
loadState: LOAD_STATES.LOADED
|
|
1211
1231
|
});
|
|
1212
1232
|
|
|
1213
|
-
function useCleanupMultiSelectValues (props) {
|
|
1214
|
-
const {
|
|
1215
|
-
field,
|
|
1216
|
-
options,
|
|
1217
|
-
loadState,
|
|
1218
|
-
onChange,
|
|
1219
|
-
values
|
|
1220
|
-
} = props;
|
|
1221
|
-
|
|
1222
|
-
// Ensures that the values are always a subset of the possible options
|
|
1223
|
-
useEffect(() => {
|
|
1224
|
-
if (loadState !== LOAD_STATES.LOADED) {
|
|
1225
|
-
return;
|
|
1226
|
-
}
|
|
1227
|
-
const hasValuesNotInOptions = values.some(v => !options.map(o => o.value).includes(v));
|
|
1228
|
-
if (hasValuesNotInOptions) {
|
|
1229
|
-
onChange({
|
|
1230
|
-
field,
|
|
1231
|
-
value: values.filter(v => options.map(o => o.value).includes(v))
|
|
1232
|
-
});
|
|
1233
|
-
}
|
|
1234
|
-
}, [field, options, onChange, JSON.stringify(values), loadState]);
|
|
1235
|
-
}
|
|
1236
|
-
|
|
1237
1233
|
const ENTER_KEYDOWN_EVENT = new KeyboardEvent('keydown', {
|
|
1238
1234
|
code: 'Enter',
|
|
1239
1235
|
key: 'Enter',
|
|
@@ -1409,6 +1405,12 @@ function sanitizeDateTimePickerValue(options) {
|
|
|
1409
1405
|
if (subtype === DATETIME_SUBTYPES.DATETIME && (isInvalidDateString(value) || !isDateTimeInputInformationSufficient(value))) return null;
|
|
1410
1406
|
return value;
|
|
1411
1407
|
}
|
|
1408
|
+
function hasEqualValue(value, array) {
|
|
1409
|
+
if (!Array.isArray(array)) {
|
|
1410
|
+
return false;
|
|
1411
|
+
}
|
|
1412
|
+
return array.some(element => isEqual(value, element));
|
|
1413
|
+
}
|
|
1412
1414
|
function sanitizeSingleSelectValue(options) {
|
|
1413
1415
|
const {
|
|
1414
1416
|
formField,
|
|
@@ -1417,7 +1419,7 @@ function sanitizeSingleSelectValue(options) {
|
|
|
1417
1419
|
} = options;
|
|
1418
1420
|
try {
|
|
1419
1421
|
const validValues = normalizeOptionsData(getOptionsData(formField, data)).map(v => v.value);
|
|
1420
|
-
return
|
|
1422
|
+
return hasEqualValue(value, validValues) ? value : null;
|
|
1421
1423
|
} catch (error) {
|
|
1422
1424
|
// use default value in case of formatting error
|
|
1423
1425
|
// TODO(@Skaiir): log a warning when this happens - https://github.com/bpmn-io/form-js/issues/289
|
|
@@ -1432,7 +1434,7 @@ function sanitizeMultiSelectValue(options) {
|
|
|
1432
1434
|
} = options;
|
|
1433
1435
|
try {
|
|
1434
1436
|
const validValues = normalizeOptionsData(getOptionsData(formField, data)).map(v => v.value);
|
|
1435
|
-
return value.filter(v =>
|
|
1437
|
+
return value.filter(v => hasEqualValue(v, validValues));
|
|
1436
1438
|
} catch (error) {
|
|
1437
1439
|
// use default value in case of formatting error
|
|
1438
1440
|
// TODO(@Skaiir): log a warning when this happens - https://github.com/bpmn-io/form-js/issues/289
|
|
@@ -1440,6 +1442,31 @@ function sanitizeMultiSelectValue(options) {
|
|
|
1440
1442
|
}
|
|
1441
1443
|
}
|
|
1442
1444
|
|
|
1445
|
+
function useCleanupMultiSelectValues (props) {
|
|
1446
|
+
const {
|
|
1447
|
+
field,
|
|
1448
|
+
options,
|
|
1449
|
+
loadState,
|
|
1450
|
+
onChange,
|
|
1451
|
+
values
|
|
1452
|
+
} = props;
|
|
1453
|
+
|
|
1454
|
+
// Ensures that the values are always a subset of the possible options
|
|
1455
|
+
useEffect(() => {
|
|
1456
|
+
if (loadState !== LOAD_STATES.LOADED) {
|
|
1457
|
+
return;
|
|
1458
|
+
}
|
|
1459
|
+
const optionValues = options.map(o => o.value);
|
|
1460
|
+
const hasValuesNotInOptions = values.some(v => !hasEqualValue(v, optionValues));
|
|
1461
|
+
if (hasValuesNotInOptions) {
|
|
1462
|
+
onChange({
|
|
1463
|
+
field,
|
|
1464
|
+
value: values.filter(v => hasEqualValue(v, optionValues))
|
|
1465
|
+
});
|
|
1466
|
+
}
|
|
1467
|
+
}, [field, options, onChange, JSON.stringify(values), loadState]);
|
|
1468
|
+
}
|
|
1469
|
+
|
|
1443
1470
|
const type$d = 'checklist';
|
|
1444
1471
|
function Checklist(props) {
|
|
1445
1472
|
const {
|
|
@@ -1462,16 +1489,11 @@ function Checklist(props) {
|
|
|
1462
1489
|
const {
|
|
1463
1490
|
required
|
|
1464
1491
|
} = validate;
|
|
1465
|
-
const toggleCheckbox =
|
|
1466
|
-
|
|
1467
|
-
if (!newValue.includes(v)) {
|
|
1468
|
-
newValue.push(v);
|
|
1469
|
-
} else {
|
|
1470
|
-
newValue = newValue.filter(x => x != v);
|
|
1471
|
-
}
|
|
1492
|
+
const toggleCheckbox = toggledValue => {
|
|
1493
|
+
const newValues = hasEqualValue(toggledValue, values) ? values.filter(value => !isEqual(value, toggledValue)) : [...values, toggledValue];
|
|
1472
1494
|
props.onChange({
|
|
1473
1495
|
field,
|
|
1474
|
-
value:
|
|
1496
|
+
value: newValues
|
|
1475
1497
|
});
|
|
1476
1498
|
};
|
|
1477
1499
|
const onCheckboxBlur = e => {
|
|
@@ -1509,15 +1531,16 @@ function Checklist(props) {
|
|
|
1509
1531
|
required: required
|
|
1510
1532
|
}), loadState == LOAD_STATES.LOADED && options.map((o, index) => {
|
|
1511
1533
|
const itemDomId = `${domId}-${index}`;
|
|
1534
|
+
const isChecked = hasEqualValue(o.value, values);
|
|
1512
1535
|
return jsx(Label, {
|
|
1513
1536
|
id: itemDomId,
|
|
1514
1537
|
label: o.label,
|
|
1515
1538
|
class: classNames({
|
|
1516
|
-
'fjs-checked':
|
|
1539
|
+
'fjs-checked': isChecked
|
|
1517
1540
|
}),
|
|
1518
1541
|
required: false,
|
|
1519
1542
|
children: jsx("input", {
|
|
1520
|
-
checked:
|
|
1543
|
+
checked: isChecked,
|
|
1521
1544
|
class: "fjs-input",
|
|
1522
1545
|
disabled: disabled,
|
|
1523
1546
|
readOnly: readonly,
|
|
@@ -1797,12 +1820,12 @@ FormComponent$1.config = {
|
|
|
1797
1820
|
})
|
|
1798
1821
|
};
|
|
1799
1822
|
|
|
1800
|
-
/**
|
|
1801
|
-
* Returns date format for the provided locale.
|
|
1802
|
-
* If the locale is not provided, uses the browser's locale.
|
|
1803
|
-
*
|
|
1804
|
-
* @param {string} [locale] - The locale to get date format for.
|
|
1805
|
-
* @returns {string} The date format for the locale.
|
|
1823
|
+
/**
|
|
1824
|
+
* Returns date format for the provided locale.
|
|
1825
|
+
* If the locale is not provided, uses the browser's locale.
|
|
1826
|
+
*
|
|
1827
|
+
* @param {string} [locale] - The locale to get date format for.
|
|
1828
|
+
* @returns {string} The date format for the locale.
|
|
1806
1829
|
*/
|
|
1807
1830
|
function getLocaleDateFormat(locale = 'default') {
|
|
1808
1831
|
const parts = new Intl.DateTimeFormat(locale).formatToParts(new Date(Date.UTC(2020, 5, 5)));
|
|
@@ -1821,12 +1844,12 @@ function getLocaleDateFormat(locale = 'default') {
|
|
|
1821
1844
|
}).join('');
|
|
1822
1845
|
}
|
|
1823
1846
|
|
|
1824
|
-
/**
|
|
1825
|
-
* Returns readable date format for the provided locale.
|
|
1826
|
-
* If the locale is not provided, uses the browser's locale.
|
|
1827
|
-
*
|
|
1828
|
-
* @param {string} [locale] - The locale to get readable date format for.
|
|
1829
|
-
* @returns {string} The readable date format for the locale.
|
|
1847
|
+
/**
|
|
1848
|
+
* Returns readable date format for the provided locale.
|
|
1849
|
+
* If the locale is not provided, uses the browser's locale.
|
|
1850
|
+
*
|
|
1851
|
+
* @param {string} [locale] - The locale to get readable date format for.
|
|
1852
|
+
* @returns {string} The readable date format for the locale.
|
|
1830
1853
|
*/
|
|
1831
1854
|
function getLocaleReadableDateFormat(locale) {
|
|
1832
1855
|
let format = getLocaleDateFormat(locale).toLowerCase();
|
|
@@ -1843,12 +1866,12 @@ function getLocaleReadableDateFormat(locale) {
|
|
|
1843
1866
|
return format;
|
|
1844
1867
|
}
|
|
1845
1868
|
|
|
1846
|
-
/**
|
|
1847
|
-
* Returns flatpickr config for the provided locale.
|
|
1848
|
-
* If the locale is not provided, uses the browser's locale.
|
|
1849
|
-
*
|
|
1850
|
-
* @param {string} [locale] - The locale to get flatpickr config for.
|
|
1851
|
-
* @returns {object} The flatpickr config for the locale.
|
|
1869
|
+
/**
|
|
1870
|
+
* Returns flatpickr config for the provided locale.
|
|
1871
|
+
* If the locale is not provided, uses the browser's locale.
|
|
1872
|
+
*
|
|
1873
|
+
* @param {string} [locale] - The locale to get flatpickr config for.
|
|
1874
|
+
* @returns {object} The flatpickr config for the locale.
|
|
1852
1875
|
*/
|
|
1853
1876
|
function getLocaleDateFlatpickrConfig(locale) {
|
|
1854
1877
|
return flatpickerizeDateFormat(getLocaleDateFormat(locale));
|
|
@@ -2560,10 +2583,10 @@ Datetime.config = {
|
|
|
2560
2583
|
}
|
|
2561
2584
|
};
|
|
2562
2585
|
|
|
2563
|
-
/**
|
|
2564
|
-
* This file must not be changed or exchanged.
|
|
2565
|
-
*
|
|
2566
|
-
* @see http://bpmn.io/license for more information.
|
|
2586
|
+
/**
|
|
2587
|
+
* This file must not be changed or exchanged.
|
|
2588
|
+
*
|
|
2589
|
+
* @see http://bpmn.io/license for more information.
|
|
2567
2590
|
*/
|
|
2568
2591
|
function Logo() {
|
|
2569
2592
|
return jsxs("svg", {
|
|
@@ -2749,11 +2772,11 @@ const ATTR_WHITESPACE_PATTERN = /[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u
|
|
|
2749
2772
|
|
|
2750
2773
|
const FORM_ELEMENT = document.createElement('form');
|
|
2751
2774
|
|
|
2752
|
-
/**
|
|
2753
|
-
* Sanitize a HTML string and return the cleaned, safe version.
|
|
2754
|
-
*
|
|
2755
|
-
* @param {string} html
|
|
2756
|
-
* @return {string}
|
|
2775
|
+
/**
|
|
2776
|
+
* Sanitize a HTML string and return the cleaned, safe version.
|
|
2777
|
+
*
|
|
2778
|
+
* @param {string} html
|
|
2779
|
+
* @return {string}
|
|
2757
2780
|
*/
|
|
2758
2781
|
|
|
2759
2782
|
// see https://github.com/developit/snarkdown/issues/70
|
|
@@ -2771,41 +2794,41 @@ function sanitizeHTML(html) {
|
|
|
2771
2794
|
}
|
|
2772
2795
|
}
|
|
2773
2796
|
|
|
2774
|
-
/**
|
|
2775
|
-
* Sanitizes an image source to ensure we only allow for data URI and links
|
|
2776
|
-
* that start with http(s).
|
|
2777
|
-
*
|
|
2778
|
-
* Note: Most browsers anyway do not support script execution in <img> elements.
|
|
2779
|
-
*
|
|
2780
|
-
* @param {string} src
|
|
2781
|
-
* @returns {string}
|
|
2797
|
+
/**
|
|
2798
|
+
* Sanitizes an image source to ensure we only allow for data URI and links
|
|
2799
|
+
* that start with http(s).
|
|
2800
|
+
*
|
|
2801
|
+
* Note: Most browsers anyway do not support script execution in <img> elements.
|
|
2802
|
+
*
|
|
2803
|
+
* @param {string} src
|
|
2804
|
+
* @returns {string}
|
|
2782
2805
|
*/
|
|
2783
2806
|
function sanitizeImageSource(src) {
|
|
2784
2807
|
const valid = ALLOWED_IMAGE_SRC_PATTERN.test(src);
|
|
2785
2808
|
return valid ? src : '';
|
|
2786
2809
|
}
|
|
2787
2810
|
|
|
2788
|
-
/**
|
|
2789
|
-
* Sanitizes an iframe source to ensure we only allow for links
|
|
2790
|
-
* that start with http(s).
|
|
2791
|
-
*
|
|
2792
|
-
* @param {string} src
|
|
2793
|
-
* @returns {string}
|
|
2811
|
+
/**
|
|
2812
|
+
* Sanitizes an iframe source to ensure we only allow for links
|
|
2813
|
+
* that start with http(s).
|
|
2814
|
+
*
|
|
2815
|
+
* @param {string} src
|
|
2816
|
+
* @returns {string}
|
|
2794
2817
|
*/
|
|
2795
2818
|
function sanitizeIFrameSource(src) {
|
|
2796
2819
|
const valid = ALLOWED_IFRAME_SRC_PATTERN.test(src);
|
|
2797
2820
|
return valid ? src : '';
|
|
2798
2821
|
}
|
|
2799
2822
|
|
|
2800
|
-
/**
|
|
2801
|
-
* Recursively sanitize a HTML node, potentially
|
|
2802
|
-
* removing it, its children or attributes.
|
|
2803
|
-
*
|
|
2804
|
-
* Inspired by https://github.com/developit/snarkdown/issues/70
|
|
2805
|
-
* and https://github.com/cure53/DOMPurify. Simplified
|
|
2806
|
-
* for our use-case.
|
|
2807
|
-
*
|
|
2808
|
-
* @param {Element} node
|
|
2823
|
+
/**
|
|
2824
|
+
* Recursively sanitize a HTML node, potentially
|
|
2825
|
+
* removing it, its children or attributes.
|
|
2826
|
+
*
|
|
2827
|
+
* Inspired by https://github.com/developit/snarkdown/issues/70
|
|
2828
|
+
* and https://github.com/cure53/DOMPurify. Simplified
|
|
2829
|
+
* for our use-case.
|
|
2830
|
+
*
|
|
2831
|
+
* @param {Element} node
|
|
2809
2832
|
*/
|
|
2810
2833
|
function sanitizeNode(node) {
|
|
2811
2834
|
// allow text nodes
|
|
@@ -2849,13 +2872,13 @@ function sanitizeNode(node) {
|
|
|
2849
2872
|
}
|
|
2850
2873
|
}
|
|
2851
2874
|
|
|
2852
|
-
/**
|
|
2853
|
-
* Validates attributes for validity.
|
|
2854
|
-
*
|
|
2855
|
-
* @param {string} lcTag
|
|
2856
|
-
* @param {string} lcName
|
|
2857
|
-
* @param {string} value
|
|
2858
|
-
* @return {boolean}
|
|
2875
|
+
/**
|
|
2876
|
+
* Validates attributes for validity.
|
|
2877
|
+
*
|
|
2878
|
+
* @param {string} lcTag
|
|
2879
|
+
* @param {string} lcName
|
|
2880
|
+
* @param {string} value
|
|
2881
|
+
* @return {boolean}
|
|
2859
2882
|
*/
|
|
2860
2883
|
function isValidAttribute(lcTag, lcName, value) {
|
|
2861
2884
|
// disallow most attributes based on whitelist
|
|
@@ -2918,7 +2941,7 @@ function IFrame(props) {
|
|
|
2918
2941
|
height: height,
|
|
2919
2942
|
class: "fjs-iframe",
|
|
2920
2943
|
id: prefixId(id, formId),
|
|
2921
|
-
sandbox: ""
|
|
2944
|
+
sandbox: "allow-scripts"
|
|
2922
2945
|
}), evaluatedUrl && !safeUrl && jsx(IFramePlaceholder, {
|
|
2923
2946
|
text: "External content couldn't be loaded."
|
|
2924
2947
|
})]
|
|
@@ -3035,6 +3058,40 @@ Image.config = {
|
|
|
3035
3058
|
})
|
|
3036
3059
|
};
|
|
3037
3060
|
|
|
3061
|
+
function useFlushDebounce(func, additionalDeps = []) {
|
|
3062
|
+
const timeoutRef = useRef(null);
|
|
3063
|
+
const lastArgsRef = useRef(null);
|
|
3064
|
+
const config = useService('config', false);
|
|
3065
|
+
const debounce = config && config.debounce;
|
|
3066
|
+
const shouldDebounce = debounce !== false && debounce !== 0;
|
|
3067
|
+
const delay = typeof debounce === 'number' ? debounce : 300;
|
|
3068
|
+
const debounceFunc = useCallback((...args) => {
|
|
3069
|
+
if (!shouldDebounce) {
|
|
3070
|
+
func(...args);
|
|
3071
|
+
return;
|
|
3072
|
+
}
|
|
3073
|
+
lastArgsRef.current = args;
|
|
3074
|
+
if (timeoutRef.current) {
|
|
3075
|
+
clearTimeout(timeoutRef.current);
|
|
3076
|
+
}
|
|
3077
|
+
timeoutRef.current = setTimeout(() => {
|
|
3078
|
+
func(...lastArgsRef.current);
|
|
3079
|
+
lastArgsRef.current = null;
|
|
3080
|
+
}, delay);
|
|
3081
|
+
}, [func, delay, shouldDebounce, ...additionalDeps]);
|
|
3082
|
+
const flushFunc = useCallback(() => {
|
|
3083
|
+
if (timeoutRef.current) {
|
|
3084
|
+
clearTimeout(timeoutRef.current);
|
|
3085
|
+
if (lastArgsRef.current !== null) {
|
|
3086
|
+
func(...lastArgsRef.current);
|
|
3087
|
+
lastArgsRef.current = null;
|
|
3088
|
+
}
|
|
3089
|
+
timeoutRef.current = null;
|
|
3090
|
+
}
|
|
3091
|
+
}, [func, ...additionalDeps]);
|
|
3092
|
+
return [debounceFunc, flushFunc];
|
|
3093
|
+
}
|
|
3094
|
+
|
|
3038
3095
|
function TemplatedInputAdorner(props) {
|
|
3039
3096
|
const {
|
|
3040
3097
|
pre,
|
|
@@ -3125,8 +3182,7 @@ function Numberfield(props) {
|
|
|
3125
3182
|
onFocus,
|
|
3126
3183
|
field,
|
|
3127
3184
|
value,
|
|
3128
|
-
readonly
|
|
3129
|
-
onChange
|
|
3185
|
+
readonly
|
|
3130
3186
|
} = props;
|
|
3131
3187
|
const {
|
|
3132
3188
|
description,
|
|
@@ -3146,6 +3202,16 @@ function Numberfield(props) {
|
|
|
3146
3202
|
} = validate;
|
|
3147
3203
|
const inputRef = useRef();
|
|
3148
3204
|
const [stringValueCache, setStringValueCache] = useState('');
|
|
3205
|
+
const [onChangeDebounced, flushOnChange] = useFlushDebounce(params => {
|
|
3206
|
+
props.onChange(params);
|
|
3207
|
+
}, [props.onChange]);
|
|
3208
|
+
const onInputBlur = () => {
|
|
3209
|
+
flushOnChange && flushOnChange();
|
|
3210
|
+
onBlur && onBlur();
|
|
3211
|
+
};
|
|
3212
|
+
const onInputFocus = () => {
|
|
3213
|
+
onFocus && onFocus();
|
|
3214
|
+
};
|
|
3149
3215
|
|
|
3150
3216
|
// checks whether the value currently in the form data is practically different from the one in the input field cache
|
|
3151
3217
|
// this allows us to guarantee the field always displays valid form data, but without auto-simplifying values like 1.000 to 1
|
|
@@ -3169,7 +3235,7 @@ function Numberfield(props) {
|
|
|
3169
3235
|
const setValue = useCallback(stringValue => {
|
|
3170
3236
|
if (isNullEquivalentValue(stringValue)) {
|
|
3171
3237
|
setStringValueCache('');
|
|
3172
|
-
|
|
3238
|
+
onChangeDebounced({
|
|
3173
3239
|
field,
|
|
3174
3240
|
value: null
|
|
3175
3241
|
});
|
|
@@ -3184,18 +3250,18 @@ function Numberfield(props) {
|
|
|
3184
3250
|
}
|
|
3185
3251
|
if (isNaN(Number(stringValue))) {
|
|
3186
3252
|
setStringValueCache('NaN');
|
|
3187
|
-
|
|
3253
|
+
onChangeDebounced({
|
|
3188
3254
|
field,
|
|
3189
3255
|
value: 'NaN'
|
|
3190
3256
|
});
|
|
3191
3257
|
return;
|
|
3192
3258
|
}
|
|
3193
3259
|
setStringValueCache(stringValue);
|
|
3194
|
-
|
|
3260
|
+
onChangeDebounced({
|
|
3195
3261
|
field,
|
|
3196
3262
|
value: serializeToString ? stringValue : Number(stringValue)
|
|
3197
3263
|
});
|
|
3198
|
-
}, [field,
|
|
3264
|
+
}, [field, onChangeDebounced, serializeToString]);
|
|
3199
3265
|
const increment = () => {
|
|
3200
3266
|
if (readonly) {
|
|
3201
3267
|
return;
|
|
@@ -3279,8 +3345,8 @@ function Numberfield(props) {
|
|
|
3279
3345
|
id: domId,
|
|
3280
3346
|
onKeyDown: onKeyDown,
|
|
3281
3347
|
onKeyPress: onKeyPress,
|
|
3282
|
-
onBlur:
|
|
3283
|
-
onFocus:
|
|
3348
|
+
onBlur: onInputBlur,
|
|
3349
|
+
onFocus: onInputFocus
|
|
3284
3350
|
|
|
3285
3351
|
// @ts-ignore
|
|
3286
3352
|
,
|
|
@@ -3357,7 +3423,8 @@ function useCleanupSingleSelectValue (props) {
|
|
|
3357
3423
|
if (loadState !== LOAD_STATES.LOADED) {
|
|
3358
3424
|
return;
|
|
3359
3425
|
}
|
|
3360
|
-
const
|
|
3426
|
+
const optionValues = options.map(o => o.value);
|
|
3427
|
+
const hasValueNotInOptions = value && !hasEqualValue(value, optionValues);
|
|
3361
3428
|
if (hasValueNotInOptions) {
|
|
3362
3429
|
onChange({
|
|
3363
3430
|
field,
|
|
@@ -3430,15 +3497,16 @@ function Radio(props) {
|
|
|
3430
3497
|
required: required
|
|
3431
3498
|
}), loadState == LOAD_STATES.LOADED && options.map((option, index) => {
|
|
3432
3499
|
const itemDomId = `${domId}-${index}`;
|
|
3500
|
+
const isChecked = isEqual(option.value, value);
|
|
3433
3501
|
return jsx(Label, {
|
|
3434
3502
|
id: itemDomId,
|
|
3435
3503
|
label: option.label,
|
|
3436
3504
|
class: classNames({
|
|
3437
|
-
'fjs-checked':
|
|
3505
|
+
'fjs-checked': isChecked
|
|
3438
3506
|
}),
|
|
3439
3507
|
required: false,
|
|
3440
3508
|
children: jsx("input", {
|
|
3441
|
-
checked:
|
|
3509
|
+
checked: isChecked,
|
|
3442
3510
|
class: "fjs-input",
|
|
3443
3511
|
disabled: disabled,
|
|
3444
3512
|
readOnly: readonly,
|
|
@@ -3468,6 +3536,21 @@ Radio.config = {
|
|
|
3468
3536
|
create: createEmptyOptions
|
|
3469
3537
|
};
|
|
3470
3538
|
|
|
3539
|
+
/**
|
|
3540
|
+
* This hook allows us to retrieve the label from a value in linear time by caching it in a map
|
|
3541
|
+
* @param {Array} options
|
|
3542
|
+
*/
|
|
3543
|
+
function useGetLabelCorrelation(options) {
|
|
3544
|
+
// This allows us to retrieve the label from a value in linear time
|
|
3545
|
+
const labelMap = useMemo(() => Object.assign({}, ...options.map(o => ({
|
|
3546
|
+
[_getValueHash(o.value)]: o.label
|
|
3547
|
+
}))), [options]);
|
|
3548
|
+
return useCallback(value => labelMap[_getValueHash(value)], [labelMap]);
|
|
3549
|
+
}
|
|
3550
|
+
const _getValueHash = value => {
|
|
3551
|
+
return isObject(value) ? JSON.stringify(value) : value;
|
|
3552
|
+
};
|
|
3553
|
+
|
|
3471
3554
|
var _path$q;
|
|
3472
3555
|
function _extends$r() { _extends$r = 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$r.apply(this, arguments); }
|
|
3473
3556
|
var SvgXMark = function SvgXMark(props) {
|
|
@@ -3499,7 +3582,7 @@ function SearchableSelect(props) {
|
|
|
3499
3582
|
} = props;
|
|
3500
3583
|
const [filter, setFilter] = useState('');
|
|
3501
3584
|
const [isDropdownExpanded, setIsDropdownExpanded] = useState(false);
|
|
3502
|
-
const [
|
|
3585
|
+
const [isFilterActive, setIsFilterActive] = useState(true);
|
|
3503
3586
|
const [isEscapeClosed, setIsEscapeClose] = useState(false);
|
|
3504
3587
|
const searchbarRef = useRef();
|
|
3505
3588
|
const eventBus = useService('eventBus');
|
|
@@ -3514,23 +3597,22 @@ function SearchableSelect(props) {
|
|
|
3514
3597
|
value,
|
|
3515
3598
|
onChange: props.onChange
|
|
3516
3599
|
});
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
const valueToOptionMap = useMemo(() => Object.assign({}, ...options.map((o, x) => ({
|
|
3520
|
-
[o.value]: options[x]
|
|
3521
|
-
}))), [options]);
|
|
3522
|
-
const valueLabel = useMemo(() => value && valueToOptionMap[value] && valueToOptionMap[value].label || '', [value, valueToOptionMap]);
|
|
3600
|
+
const getLabelCorrelation = useGetLabelCorrelation(options);
|
|
3601
|
+
const label = useMemo(() => value && getLabelCorrelation(value), [value, getLabelCorrelation]);
|
|
3523
3602
|
|
|
3524
3603
|
// whenever we change the underlying value, set the label to it
|
|
3525
3604
|
useEffect(() => {
|
|
3526
|
-
setFilter(
|
|
3527
|
-
}, [
|
|
3605
|
+
setFilter(label);
|
|
3606
|
+
}, [label]);
|
|
3528
3607
|
const filteredOptions = useMemo(() => {
|
|
3529
|
-
if (loadState
|
|
3530
|
-
return
|
|
3608
|
+
if (loadState !== LOAD_STATES.LOADED) {
|
|
3609
|
+
return [];
|
|
3531
3610
|
}
|
|
3532
|
-
|
|
3533
|
-
|
|
3611
|
+
if (!filter || !isFilterActive) {
|
|
3612
|
+
return options;
|
|
3613
|
+
}
|
|
3614
|
+
return options.filter(o => o.label && o.value && o.label.toLowerCase().includes(filter.toLowerCase()));
|
|
3615
|
+
}, [filter, loadState, options, isFilterActive]);
|
|
3534
3616
|
const setValue = useCallback(option => {
|
|
3535
3617
|
setFilter(option && option.label || '');
|
|
3536
3618
|
props.onChange({
|
|
@@ -3557,7 +3639,7 @@ function SearchableSelect(props) {
|
|
|
3557
3639
|
}) => {
|
|
3558
3640
|
setIsEscapeClose(false);
|
|
3559
3641
|
setIsDropdownExpanded(true);
|
|
3560
|
-
|
|
3642
|
+
setIsFilterActive(true);
|
|
3561
3643
|
setFilter(target.value || '');
|
|
3562
3644
|
eventBus.fire('formField.search', {
|
|
3563
3645
|
formField: field,
|
|
@@ -3573,7 +3655,7 @@ function SearchableSelect(props) {
|
|
|
3573
3655
|
{
|
|
3574
3656
|
if (!isDropdownExpanded) {
|
|
3575
3657
|
setIsDropdownExpanded(true);
|
|
3576
|
-
|
|
3658
|
+
setIsFilterActive(false);
|
|
3577
3659
|
}
|
|
3578
3660
|
keyDownEvent.preventDefault();
|
|
3579
3661
|
break;
|
|
@@ -3591,7 +3673,7 @@ function SearchableSelect(props) {
|
|
|
3591
3673
|
const onInputMouseDown = useCallback(() => {
|
|
3592
3674
|
setIsEscapeClose(false);
|
|
3593
3675
|
setIsDropdownExpanded(true);
|
|
3594
|
-
|
|
3676
|
+
setIsFilterActive(false);
|
|
3595
3677
|
}, []);
|
|
3596
3678
|
const onInputFocus = useCallback(() => {
|
|
3597
3679
|
setIsEscapeClose(false);
|
|
@@ -3600,9 +3682,9 @@ function SearchableSelect(props) {
|
|
|
3600
3682
|
}, [onFocus]);
|
|
3601
3683
|
const onInputBlur = useCallback(() => {
|
|
3602
3684
|
setIsDropdownExpanded(false);
|
|
3603
|
-
setFilter(
|
|
3685
|
+
setFilter(label);
|
|
3604
3686
|
onBlur && onBlur();
|
|
3605
|
-
}, [onBlur,
|
|
3687
|
+
}, [onBlur, label]);
|
|
3606
3688
|
return jsxs(Fragment, {
|
|
3607
3689
|
children: [jsxs("div", {
|
|
3608
3690
|
class: classNames('fjs-input-group', {
|
|
@@ -3679,12 +3761,8 @@ function SimpleSelect(props) {
|
|
|
3679
3761
|
value,
|
|
3680
3762
|
onChange: props.onChange
|
|
3681
3763
|
});
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
const valueToOptionMap = useMemo(() => Object.assign({}, ...options.map((o, x) => ({
|
|
3685
|
-
[o.value]: options[x]
|
|
3686
|
-
}))), [options]);
|
|
3687
|
-
const valueLabel = useMemo(() => value && valueToOptionMap[value] && valueToOptionMap[value].label || '', [value, valueToOptionMap]);
|
|
3764
|
+
const getLabelCorrelation = useGetLabelCorrelation(options);
|
|
3765
|
+
const valueLabel = useMemo(() => value && getLabelCorrelation(value), [value, getLabelCorrelation]);
|
|
3688
3766
|
const setValue = useCallback(option => {
|
|
3689
3767
|
props.onChange({
|
|
3690
3768
|
value: option && option.value || null,
|
|
@@ -3999,11 +4077,7 @@ function Taglist(props) {
|
|
|
3999
4077
|
values,
|
|
4000
4078
|
onChange: props.onChange
|
|
4001
4079
|
});
|
|
4002
|
-
|
|
4003
|
-
// We cache a map of option values to their index so that we don't need to search the whole options array every time to correlate the label
|
|
4004
|
-
const valueToOptionMap = useMemo(() => Object.assign({}, ...options.map((o, x) => ({
|
|
4005
|
-
[o.value]: options[x]
|
|
4006
|
-
}))), [options]);
|
|
4080
|
+
const getLabelCorrelation = useGetLabelCorrelation(options);
|
|
4007
4081
|
const hasOptionsLeft = useMemo(() => options.length > values.length, [options.length, values.length]);
|
|
4008
4082
|
|
|
4009
4083
|
// Usage of stringify is necessary here because we want this effect to only trigger when there is a value change to the array
|
|
@@ -4011,12 +4085,14 @@ function Taglist(props) {
|
|
|
4011
4085
|
if (loadState !== LOAD_STATES.LOADED) {
|
|
4012
4086
|
return [];
|
|
4013
4087
|
}
|
|
4014
|
-
|
|
4088
|
+
const isValidFilteredOption = option => {
|
|
4089
|
+
const filterMatches = option.label.toLowerCase().includes(filter.toLowerCase());
|
|
4090
|
+
return filterMatches && !hasEqualValue(option.value, values);
|
|
4091
|
+
};
|
|
4092
|
+
return options.filter(isValidFilteredOption);
|
|
4015
4093
|
}, [filter, options, JSON.stringify(values), loadState]);
|
|
4016
4094
|
const selectValue = value => {
|
|
4017
|
-
|
|
4018
|
-
setFilter('');
|
|
4019
|
-
}
|
|
4095
|
+
setFilter('');
|
|
4020
4096
|
|
|
4021
4097
|
// Ensure values cannot be double selected due to latency
|
|
4022
4098
|
if (values.at(-1) === value) {
|
|
@@ -4028,8 +4104,9 @@ function Taglist(props) {
|
|
|
4028
4104
|
});
|
|
4029
4105
|
};
|
|
4030
4106
|
const deselectValue = value => {
|
|
4107
|
+
const newValues = values.filter(v => !isEqual(v, value));
|
|
4031
4108
|
props.onChange({
|
|
4032
|
-
value:
|
|
4109
|
+
value: newValues,
|
|
4033
4110
|
field
|
|
4034
4111
|
});
|
|
4035
4112
|
};
|
|
@@ -4139,7 +4216,7 @@ function Taglist(props) {
|
|
|
4139
4216
|
onMouseDown: e => e.preventDefault(),
|
|
4140
4217
|
children: [jsx("span", {
|
|
4141
4218
|
class: "fjs-taglist-tag-label",
|
|
4142
|
-
children:
|
|
4219
|
+
children: getLabelCorrelation(v)
|
|
4143
4220
|
}), !disabled && !readonly && jsx("button", {
|
|
4144
4221
|
type: "button",
|
|
4145
4222
|
title: "Remove tag",
|
|
@@ -4305,13 +4382,20 @@ function Textfield(props) {
|
|
|
4305
4382
|
const {
|
|
4306
4383
|
required
|
|
4307
4384
|
} = validate;
|
|
4308
|
-
const
|
|
4385
|
+
const [onInputChange, flushOnChange] = useFlushDebounce(({
|
|
4309
4386
|
target
|
|
4310
4387
|
}) => {
|
|
4311
4388
|
props.onChange({
|
|
4312
4389
|
field,
|
|
4313
4390
|
value: target.value
|
|
4314
4391
|
});
|
|
4392
|
+
}, [props.onChange]);
|
|
4393
|
+
const onInputBlur = () => {
|
|
4394
|
+
flushOnChange && flushOnChange();
|
|
4395
|
+
onBlur && onBlur();
|
|
4396
|
+
};
|
|
4397
|
+
const onInputFocus = () => {
|
|
4398
|
+
onFocus && onFocus();
|
|
4315
4399
|
};
|
|
4316
4400
|
return jsxs("div", {
|
|
4317
4401
|
class: formFieldClasses(type$2, {
|
|
@@ -4333,9 +4417,9 @@ function Textfield(props) {
|
|
|
4333
4417
|
disabled: disabled,
|
|
4334
4418
|
readOnly: readonly,
|
|
4335
4419
|
id: domId,
|
|
4336
|
-
onInput:
|
|
4337
|
-
onBlur:
|
|
4338
|
-
onFocus:
|
|
4420
|
+
onInput: onInputChange,
|
|
4421
|
+
onBlur: onInputBlur,
|
|
4422
|
+
onFocus: onInputFocus,
|
|
4339
4423
|
type: "text",
|
|
4340
4424
|
value: value,
|
|
4341
4425
|
"aria-describedby": errorMessageId
|
|
@@ -4394,13 +4478,20 @@ function Textarea(props) {
|
|
|
4394
4478
|
required
|
|
4395
4479
|
} = validate;
|
|
4396
4480
|
const textareaRef = useRef();
|
|
4397
|
-
const
|
|
4481
|
+
const [onInputChange, flushOnChange] = useFlushDebounce(({
|
|
4398
4482
|
target
|
|
4399
4483
|
}) => {
|
|
4400
4484
|
props.onChange({
|
|
4401
4485
|
field,
|
|
4402
4486
|
value: target.value
|
|
4403
4487
|
});
|
|
4488
|
+
}, [props.onChange]);
|
|
4489
|
+
const onInputBlur = () => {
|
|
4490
|
+
flushOnChange && flushOnChange();
|
|
4491
|
+
onBlur && onBlur();
|
|
4492
|
+
};
|
|
4493
|
+
const onInputFocus = () => {
|
|
4494
|
+
onFocus && onFocus();
|
|
4404
4495
|
};
|
|
4405
4496
|
useLayoutEffect(() => {
|
|
4406
4497
|
autoSizeTextarea(textareaRef.current);
|
|
@@ -4423,9 +4514,9 @@ function Textarea(props) {
|
|
|
4423
4514
|
disabled: disabled,
|
|
4424
4515
|
readonly: readonly,
|
|
4425
4516
|
id: domId,
|
|
4426
|
-
onInput:
|
|
4427
|
-
onBlur:
|
|
4428
|
-
onFocus:
|
|
4517
|
+
onInput: onInputChange,
|
|
4518
|
+
onBlur: onInputBlur,
|
|
4519
|
+
onFocus: onInputFocus,
|
|
4429
4520
|
value: value,
|
|
4430
4521
|
ref: textareaRef,
|
|
4431
4522
|
"aria-describedby": errorMessageId
|
|
@@ -4525,28 +4616,28 @@ var CaretRightIcon = SvgCaretRight;
|
|
|
4525
4616
|
|
|
4526
4617
|
const type = 'table';
|
|
4527
4618
|
|
|
4528
|
-
/**
|
|
4529
|
-
* @typedef {('asc'|'desc')} Direction
|
|
4530
|
-
*
|
|
4531
|
-
* @typedef Sorting
|
|
4532
|
-
* @property {string} key
|
|
4533
|
-
* @property {Direction} direction
|
|
4534
|
-
*
|
|
4535
|
-
* @typedef Column
|
|
4536
|
-
* @property {string} label
|
|
4537
|
-
* @property {string} key
|
|
4538
|
-
*
|
|
4539
|
-
* @typedef Props
|
|
4540
|
-
* @property {Object} field
|
|
4541
|
-
* @property {string} field.id
|
|
4542
|
-
* @property {Array<Column>} [field.columns]
|
|
4543
|
-
* @property {string} [field.columnsExpression]
|
|
4544
|
-
* @property {string} [field.label]
|
|
4545
|
-
* @property {number} [field.rowCount]
|
|
4546
|
-
* @property {string} [field.dataSource]
|
|
4547
|
-
*
|
|
4548
|
-
* @param {Props} props
|
|
4549
|
-
* @returns {import("preact").JSX.Element}
|
|
4619
|
+
/**
|
|
4620
|
+
* @typedef {('asc'|'desc')} Direction
|
|
4621
|
+
*
|
|
4622
|
+
* @typedef Sorting
|
|
4623
|
+
* @property {string} key
|
|
4624
|
+
* @property {Direction} direction
|
|
4625
|
+
*
|
|
4626
|
+
* @typedef Column
|
|
4627
|
+
* @property {string} label
|
|
4628
|
+
* @property {string} key
|
|
4629
|
+
*
|
|
4630
|
+
* @typedef Props
|
|
4631
|
+
* @property {Object} field
|
|
4632
|
+
* @property {string} field.id
|
|
4633
|
+
* @property {Array<Column>} [field.columns]
|
|
4634
|
+
* @property {string} [field.columnsExpression]
|
|
4635
|
+
* @property {string} [field.label]
|
|
4636
|
+
* @property {number} [field.rowCount]
|
|
4637
|
+
* @property {string} [field.dataSource]
|
|
4638
|
+
*
|
|
4639
|
+
* @param {Props} props
|
|
4640
|
+
* @returns {import("preact").JSX.Element}
|
|
4550
4641
|
*/
|
|
4551
4642
|
function Table(props) {
|
|
4552
4643
|
const {
|
|
@@ -4756,10 +4847,10 @@ Table.config = {
|
|
|
4756
4847
|
|
|
4757
4848
|
// helpers /////////////////////////////
|
|
4758
4849
|
|
|
4759
|
-
/**
|
|
4760
|
-
* @param {string|void} columnsExpression
|
|
4761
|
-
* @param {Column[]} fallbackColumns
|
|
4762
|
-
* @returns {Column[]}
|
|
4850
|
+
/**
|
|
4851
|
+
* @param {string|void} columnsExpression
|
|
4852
|
+
* @param {Column[]} fallbackColumns
|
|
4853
|
+
* @returns {Column[]}
|
|
4763
4854
|
*/
|
|
4764
4855
|
function useEvaluatedColumns(columnsExpression, fallbackColumns) {
|
|
4765
4856
|
/** @type {Column[]|null} */
|
|
@@ -4767,18 +4858,18 @@ function useEvaluatedColumns(columnsExpression, fallbackColumns) {
|
|
|
4767
4858
|
return Array.isArray(evaluation) && evaluation.every(isColumn) ? evaluation : fallbackColumns;
|
|
4768
4859
|
}
|
|
4769
4860
|
|
|
4770
|
-
/**
|
|
4771
|
-
* @param {any} column
|
|
4772
|
-
* @returns {column is Column}
|
|
4861
|
+
/**
|
|
4862
|
+
* @param {any} column
|
|
4863
|
+
* @returns {column is Column}
|
|
4773
4864
|
*/
|
|
4774
4865
|
function isColumn(column) {
|
|
4775
4866
|
return isObject(column) && isString(column['label']) && isString(column['key']);
|
|
4776
4867
|
}
|
|
4777
4868
|
|
|
4778
|
-
/**
|
|
4779
|
-
* @param {Array} array
|
|
4780
|
-
* @param {number} size
|
|
4781
|
-
* @returns {Array}
|
|
4869
|
+
/**
|
|
4870
|
+
* @param {Array} array
|
|
4871
|
+
* @param {number} size
|
|
4872
|
+
* @returns {Array}
|
|
4782
4873
|
*/
|
|
4783
4874
|
function chunk(array, size) {
|
|
4784
4875
|
return array.reduce((chunks, item, index) => {
|
|
@@ -4791,11 +4882,11 @@ function chunk(array, size) {
|
|
|
4791
4882
|
}, []);
|
|
4792
4883
|
}
|
|
4793
4884
|
|
|
4794
|
-
/**
|
|
4795
|
-
* @param {unknown[]} array
|
|
4796
|
-
* @param {string} key
|
|
4797
|
-
* @param {Direction} direction
|
|
4798
|
-
* @returns {unknown[]}
|
|
4885
|
+
/**
|
|
4886
|
+
* @param {unknown[]} array
|
|
4887
|
+
* @param {string} key
|
|
4888
|
+
* @param {Direction} direction
|
|
4889
|
+
* @returns {unknown[]}
|
|
4799
4890
|
*/
|
|
4800
4891
|
function sortByColumn(array, key, direction) {
|
|
4801
4892
|
return [...array].sort((a, b) => {
|
|
@@ -4809,10 +4900,10 @@ function sortByColumn(array, key, direction) {
|
|
|
4809
4900
|
});
|
|
4810
4901
|
}
|
|
4811
4902
|
|
|
4812
|
-
/**
|
|
4813
|
-
* @param {null|Sorting} sortBy
|
|
4814
|
-
* @param {string} key
|
|
4815
|
-
* @param {string} label
|
|
4903
|
+
/**
|
|
4904
|
+
* @param {null|Sorting} sortBy
|
|
4905
|
+
* @param {string} key
|
|
4906
|
+
* @param {string} label
|
|
4816
4907
|
*/
|
|
4817
4908
|
function getHeaderAriaLabel(sortBy, key, label) {
|
|
4818
4909
|
if (sortBy === null || sortBy.key !== key) {
|
|
@@ -5187,37 +5278,37 @@ class FormFields {
|
|
|
5187
5278
|
const EXPRESSION_PROPERTIES = ['alt', 'appearance.prefixAdorner', 'appearance.suffixAdorner', 'conditional.hide', 'description', 'label', 'source', 'readonly', 'text', 'validate.min', 'validate.max', 'validate.minLength', 'validate.maxLength', 'valuesExpression', 'url', 'dataSource', 'columnsExpression'];
|
|
5188
5279
|
const TEMPLATE_PROPERTIES = ['alt', 'appearance.prefixAdorner', 'appearance.suffixAdorner', 'description', 'label', 'source', 'text', 'url'];
|
|
5189
5280
|
|
|
5190
|
-
/**
|
|
5191
|
-
* @typedef { import('../types').Schema } Schema
|
|
5281
|
+
/**
|
|
5282
|
+
* @typedef { import('../types').Schema } Schema
|
|
5192
5283
|
*/
|
|
5193
5284
|
|
|
5194
|
-
/**
|
|
5195
|
-
* Parse the schema for variables a form might make use of.
|
|
5196
|
-
*
|
|
5197
|
-
* @example
|
|
5198
|
-
*
|
|
5199
|
-
* // retrieve variables from schema
|
|
5200
|
-
* const variables = getSchemaVariables(schema);
|
|
5201
|
-
*
|
|
5202
|
-
* @example
|
|
5203
|
-
*
|
|
5204
|
-
* // retrieve input variables from schema
|
|
5205
|
-
* const inputVariables = getSchemaVariables(schema, { outputs: false });
|
|
5206
|
-
*
|
|
5207
|
-
* @example
|
|
5208
|
-
*
|
|
5209
|
-
* // retrieve output variables from schema
|
|
5210
|
-
* const outputVariables = getSchemaVariables(schema, { inputs: false });
|
|
5211
|
-
*
|
|
5212
|
-
* @param {Schema} schema
|
|
5213
|
-
* @param {object} [options]
|
|
5214
|
-
* @param {any} [options.expressionLanguage]
|
|
5215
|
-
* @param {any} [options.templating]
|
|
5216
|
-
* @param {any} [options.formFields]
|
|
5217
|
-
* @param {boolean} [options.inputs=true]
|
|
5218
|
-
* @param {boolean} [options.outputs=true]
|
|
5219
|
-
*
|
|
5220
|
-
* @return {string[]}
|
|
5285
|
+
/**
|
|
5286
|
+
* Parse the schema for variables a form might make use of.
|
|
5287
|
+
*
|
|
5288
|
+
* @example
|
|
5289
|
+
*
|
|
5290
|
+
* // retrieve variables from schema
|
|
5291
|
+
* const variables = getSchemaVariables(schema);
|
|
5292
|
+
*
|
|
5293
|
+
* @example
|
|
5294
|
+
*
|
|
5295
|
+
* // retrieve input variables from schema
|
|
5296
|
+
* const inputVariables = getSchemaVariables(schema, { outputs: false });
|
|
5297
|
+
*
|
|
5298
|
+
* @example
|
|
5299
|
+
*
|
|
5300
|
+
* // retrieve output variables from schema
|
|
5301
|
+
* const outputVariables = getSchemaVariables(schema, { inputs: false });
|
|
5302
|
+
*
|
|
5303
|
+
* @param {Schema} schema
|
|
5304
|
+
* @param {object} [options]
|
|
5305
|
+
* @param {any} [options.expressionLanguage]
|
|
5306
|
+
* @param {any} [options.templating]
|
|
5307
|
+
* @param {any} [options.formFields]
|
|
5308
|
+
* @param {boolean} [options.inputs=true]
|
|
5309
|
+
* @param {boolean} [options.outputs=true]
|
|
5310
|
+
*
|
|
5311
|
+
* @return {string[]}
|
|
5221
5312
|
*/
|
|
5222
5313
|
function getSchemaVariables(schema, options = {}) {
|
|
5223
5314
|
const {
|
|
@@ -5293,13 +5384,13 @@ function getSchemaVariables(schema, options = {}) {
|
|
|
5293
5384
|
return Array.from(new Set(variables));
|
|
5294
5385
|
}
|
|
5295
5386
|
|
|
5296
|
-
/**
|
|
5297
|
-
* Get the ancestry list of a form field.
|
|
5298
|
-
*
|
|
5299
|
-
* @param {string} formFieldId
|
|
5300
|
-
* @param {import('../core/FormFieldRegistry').default} formFieldRegistry
|
|
5301
|
-
*
|
|
5302
|
-
* @return {Array<string>} ancestry list
|
|
5387
|
+
/**
|
|
5388
|
+
* Get the ancestry list of a form field.
|
|
5389
|
+
*
|
|
5390
|
+
* @param {string} formFieldId
|
|
5391
|
+
* @param {import('../core/FormFieldRegistry').default} formFieldRegistry
|
|
5392
|
+
*
|
|
5393
|
+
* @return {Array<string>} ancestry list
|
|
5303
5394
|
*/
|
|
5304
5395
|
const getAncestryList = (formFieldId, formFieldRegistry) => {
|
|
5305
5396
|
const ids = [];
|
|
@@ -5311,9 +5402,9 @@ const getAncestryList = (formFieldId, formFieldRegistry) => {
|
|
|
5311
5402
|
return ids;
|
|
5312
5403
|
};
|
|
5313
5404
|
|
|
5314
|
-
/**
|
|
5315
|
-
* @typedef {object} Condition
|
|
5316
|
-
* @property {string} [hide]
|
|
5405
|
+
/**
|
|
5406
|
+
* @typedef {object} Condition
|
|
5407
|
+
* @property {string} [hide]
|
|
5317
5408
|
*/
|
|
5318
5409
|
|
|
5319
5410
|
class ConditionChecker {
|
|
@@ -5323,14 +5414,14 @@ class ConditionChecker {
|
|
|
5323
5414
|
this._eventBus = eventBus;
|
|
5324
5415
|
}
|
|
5325
5416
|
|
|
5326
|
-
/**
|
|
5327
|
-
* For given data, remove properties based on condition.
|
|
5328
|
-
*
|
|
5329
|
-
* @param {Object<string, any>} data
|
|
5330
|
-
* @param {Object<string, any>} contextData
|
|
5331
|
-
* @param {Object} [options]
|
|
5332
|
-
* @param {Function} [options.getFilterPath]
|
|
5333
|
-
* @param {boolean} [options.leafNodeDeletionOnly]
|
|
5417
|
+
/**
|
|
5418
|
+
* For given data, remove properties based on condition.
|
|
5419
|
+
*
|
|
5420
|
+
* @param {Object<string, any>} data
|
|
5421
|
+
* @param {Object<string, any>} contextData
|
|
5422
|
+
* @param {Object} [options]
|
|
5423
|
+
* @param {Function} [options.getFilterPath]
|
|
5424
|
+
* @param {boolean} [options.leafNodeDeletionOnly]
|
|
5334
5425
|
*/
|
|
5335
5426
|
applyConditions(data, contextData = {}, options = {}) {
|
|
5336
5427
|
const workingData = clone(data);
|
|
@@ -5424,13 +5515,13 @@ class ConditionChecker {
|
|
|
5424
5515
|
return workingData;
|
|
5425
5516
|
}
|
|
5426
5517
|
|
|
5427
|
-
/**
|
|
5428
|
-
* Check if given condition is met. Returns null for invalid/missing conditions.
|
|
5429
|
-
*
|
|
5430
|
-
* @param {string} condition
|
|
5431
|
-
* @param {import('../../types').Data} [data]
|
|
5432
|
-
*
|
|
5433
|
-
* @returns {boolean|null}
|
|
5518
|
+
/**
|
|
5519
|
+
* Check if given condition is met. Returns null for invalid/missing conditions.
|
|
5520
|
+
*
|
|
5521
|
+
* @param {string} condition
|
|
5522
|
+
* @param {import('../../types').Data} [data]
|
|
5523
|
+
*
|
|
5524
|
+
* @returns {boolean|null}
|
|
5434
5525
|
*/
|
|
5435
5526
|
check(condition, data = {}) {
|
|
5436
5527
|
if (!condition) {
|
|
@@ -5451,12 +5542,12 @@ class ConditionChecker {
|
|
|
5451
5542
|
}
|
|
5452
5543
|
}
|
|
5453
5544
|
|
|
5454
|
-
/**
|
|
5455
|
-
* Check if hide condition is met.
|
|
5456
|
-
*
|
|
5457
|
-
* @param {Condition} condition
|
|
5458
|
-
* @param {Object<string, any>} data
|
|
5459
|
-
* @returns {boolean}
|
|
5545
|
+
/**
|
|
5546
|
+
* Check if hide condition is met.
|
|
5547
|
+
*
|
|
5548
|
+
* @param {Condition} condition
|
|
5549
|
+
* @param {Object<string, any>} data
|
|
5550
|
+
* @returns {boolean}
|
|
5460
5551
|
*/
|
|
5461
5552
|
_checkHideCondition(condition, data) {
|
|
5462
5553
|
if (!condition.hide) {
|
|
@@ -5498,12 +5589,12 @@ class MarkdownRenderer {
|
|
|
5498
5589
|
this._converter = new showdown.Converter();
|
|
5499
5590
|
}
|
|
5500
5591
|
|
|
5501
|
-
/**
|
|
5502
|
-
* Render markdown to HTML.
|
|
5503
|
-
*
|
|
5504
|
-
* @param {string} markdown - The markdown to render
|
|
5505
|
-
*
|
|
5506
|
-
* @returns {string} HTML
|
|
5592
|
+
/**
|
|
5593
|
+
* Render markdown to HTML.
|
|
5594
|
+
*
|
|
5595
|
+
* @param {string} markdown - The markdown to render
|
|
5596
|
+
*
|
|
5597
|
+
* @returns {string} HTML
|
|
5507
5598
|
*/
|
|
5508
5599
|
render(markdown) {
|
|
5509
5600
|
return this._converter.makeHtml(markdown);
|
|
@@ -6124,11 +6215,11 @@ class RepeatRenderManager {
|
|
|
6124
6215
|
this.RepeatFooter = this.RepeatFooter.bind(this);
|
|
6125
6216
|
}
|
|
6126
6217
|
|
|
6127
|
-
/**
|
|
6128
|
-
* Checks whether a field is currently repeating its children.
|
|
6129
|
-
*
|
|
6130
|
-
* @param {string} id - The id of the field to check
|
|
6131
|
-
* @returns {boolean} - True if repeatable, false otherwise
|
|
6218
|
+
/**
|
|
6219
|
+
* Checks whether a field is currently repeating its children.
|
|
6220
|
+
*
|
|
6221
|
+
* @param {string} id - The id of the field to check
|
|
6222
|
+
* @returns {boolean} - True if repeatable, false otherwise
|
|
6132
6223
|
*/
|
|
6133
6224
|
isFieldRepeating(id) {
|
|
6134
6225
|
if (!id) {
|
|
@@ -6888,8 +6979,8 @@ Validator.$inject = ['expressionLanguage', 'conditionChecker', 'form'];
|
|
|
6888
6979
|
|
|
6889
6980
|
// helpers //////////
|
|
6890
6981
|
|
|
6891
|
-
/**
|
|
6892
|
-
* Helper function to evaluate optional FEEL validation values.
|
|
6982
|
+
/**
|
|
6983
|
+
* Helper function to evaluate optional FEEL validation values.
|
|
6893
6984
|
*/
|
|
6894
6985
|
function evaluateFEELValues(validate, expressionLanguage, conditionChecker, form) {
|
|
6895
6986
|
const evaluatedValidate = {
|
|
@@ -6923,12 +7014,12 @@ function evaluateFEELValues(validate, expressionLanguage, conditionChecker, form
|
|
|
6923
7014
|
}
|
|
6924
7015
|
|
|
6925
7016
|
class Importer {
|
|
6926
|
-
/**
|
|
6927
|
-
* @constructor
|
|
6928
|
-
* @param { import('./FormFieldRegistry').default } formFieldRegistry
|
|
6929
|
-
* @param { import('./PathRegistry').default } pathRegistry
|
|
6930
|
-
* @param { import('./FieldFactory').default } fieldFactory
|
|
6931
|
-
* @param { import('./FormLayouter').default } formLayouter
|
|
7017
|
+
/**
|
|
7018
|
+
* @constructor
|
|
7019
|
+
* @param { import('./FormFieldRegistry').default } formFieldRegistry
|
|
7020
|
+
* @param { import('./PathRegistry').default } pathRegistry
|
|
7021
|
+
* @param { import('./FieldFactory').default } fieldFactory
|
|
7022
|
+
* @param { import('./FormLayouter').default } formLayouter
|
|
6932
7023
|
*/
|
|
6933
7024
|
constructor(formFieldRegistry, pathRegistry, fieldFactory, formLayouter) {
|
|
6934
7025
|
this._formFieldRegistry = formFieldRegistry;
|
|
@@ -6937,21 +7028,21 @@ class Importer {
|
|
|
6937
7028
|
this._formLayouter = formLayouter;
|
|
6938
7029
|
}
|
|
6939
7030
|
|
|
6940
|
-
/**
|
|
6941
|
-
* Import schema creating rows, fields, attaching additional
|
|
6942
|
-
* information to each field and adding fields to the
|
|
6943
|
-
* field registry.
|
|
6944
|
-
*
|
|
6945
|
-
* Additional information attached:
|
|
6946
|
-
*
|
|
6947
|
-
* * `id` (unless present)
|
|
6948
|
-
* * `_parent`
|
|
6949
|
-
* * `_path`
|
|
6950
|
-
*
|
|
6951
|
-
* @param {any} schema
|
|
6952
|
-
*
|
|
6953
|
-
* @typedef {{ warnings: Error[], schema: any }} ImportResult
|
|
6954
|
-
* @returns {ImportResult}
|
|
7031
|
+
/**
|
|
7032
|
+
* Import schema creating rows, fields, attaching additional
|
|
7033
|
+
* information to each field and adding fields to the
|
|
7034
|
+
* field registry.
|
|
7035
|
+
*
|
|
7036
|
+
* Additional information attached:
|
|
7037
|
+
*
|
|
7038
|
+
* * `id` (unless present)
|
|
7039
|
+
* * `_parent`
|
|
7040
|
+
* * `_path`
|
|
7041
|
+
*
|
|
7042
|
+
* @param {any} schema
|
|
7043
|
+
*
|
|
7044
|
+
* @typedef {{ warnings: Error[], schema: any }} ImportResult
|
|
7045
|
+
* @returns {ImportResult}
|
|
6955
7046
|
*/
|
|
6956
7047
|
importSchema(schema) {
|
|
6957
7048
|
// TODO: Add warnings
|
|
@@ -6976,12 +7067,12 @@ class Importer {
|
|
|
6976
7067
|
this._pathRegistry.clear();
|
|
6977
7068
|
}
|
|
6978
7069
|
|
|
6979
|
-
/**
|
|
6980
|
-
* @param {{[x: string]: any}} fieldAttrs
|
|
6981
|
-
* @param {String} [parentId]
|
|
6982
|
-
* @param {number} [index]
|
|
6983
|
-
*
|
|
6984
|
-
* @return {any} field
|
|
7070
|
+
/**
|
|
7071
|
+
* @param {{[x: string]: any}} fieldAttrs
|
|
7072
|
+
* @param {String} [parentId]
|
|
7073
|
+
* @param {number} [index]
|
|
7074
|
+
*
|
|
7075
|
+
* @return {any} field
|
|
6985
7076
|
*/
|
|
6986
7077
|
importFormField(fieldAttrs, parentId, index) {
|
|
6987
7078
|
const {
|
|
@@ -7006,11 +7097,11 @@ class Importer {
|
|
|
7006
7097
|
return field;
|
|
7007
7098
|
}
|
|
7008
7099
|
|
|
7009
|
-
/**
|
|
7010
|
-
* @param {Array<any>} components
|
|
7011
|
-
* @param {string} parentId
|
|
7012
|
-
*
|
|
7013
|
-
* @return {Array<any>} imported components
|
|
7100
|
+
/**
|
|
7101
|
+
* @param {Array<any>} components
|
|
7102
|
+
* @param {string} parentId
|
|
7103
|
+
*
|
|
7104
|
+
* @return {Array<any>} imported components
|
|
7014
7105
|
*/
|
|
7015
7106
|
importFormFields(components, parentId) {
|
|
7016
7107
|
return components.map((component, index) => {
|
|
@@ -7021,11 +7112,11 @@ class Importer {
|
|
|
7021
7112
|
Importer.$inject = ['formFieldRegistry', 'pathRegistry', 'fieldFactory', 'formLayouter'];
|
|
7022
7113
|
|
|
7023
7114
|
class FieldFactory {
|
|
7024
|
-
/**
|
|
7025
|
-
* @constructor
|
|
7026
|
-
*
|
|
7027
|
-
* @param formFieldRegistry
|
|
7028
|
-
* @param formFields
|
|
7115
|
+
/**
|
|
7116
|
+
* @constructor
|
|
7117
|
+
*
|
|
7118
|
+
* @param formFieldRegistry
|
|
7119
|
+
* @param formFields
|
|
7029
7120
|
*/
|
|
7030
7121
|
constructor(formFieldRegistry, pathRegistry, formFields) {
|
|
7031
7122
|
this._formFieldRegistry = formFieldRegistry;
|
|
@@ -7135,36 +7226,36 @@ class FieldFactory {
|
|
|
7135
7226
|
}
|
|
7136
7227
|
FieldFactory.$inject = ['formFieldRegistry', 'pathRegistry', 'formFields'];
|
|
7137
7228
|
|
|
7138
|
-
/**
|
|
7139
|
-
* The PathRegistry class manages a hierarchical structure of paths associated with form fields.
|
|
7140
|
-
* It enables claiming, unclaiming, and validating paths within this structure.
|
|
7141
|
-
*
|
|
7142
|
-
* Example Tree Structure:
|
|
7143
|
-
*
|
|
7144
|
-
* [
|
|
7145
|
-
* {
|
|
7146
|
-
* segment: 'root',
|
|
7147
|
-
* claimCount: 1,
|
|
7148
|
-
* children: [
|
|
7149
|
-
* {
|
|
7150
|
-
* segment: 'child1',
|
|
7151
|
-
* claimCount: 2,
|
|
7152
|
-
* children: null // A leaf node (closed path)
|
|
7153
|
-
* },
|
|
7154
|
-
* {
|
|
7155
|
-
* segment: 'child2',
|
|
7156
|
-
* claimCount: 1,
|
|
7157
|
-
* children: [
|
|
7158
|
-
* {
|
|
7159
|
-
* segment: 'subChild1',
|
|
7160
|
-
* claimCount: 1,
|
|
7161
|
-
* children: [] // An open node (open path)
|
|
7162
|
-
* }
|
|
7163
|
-
* ]
|
|
7164
|
-
* }
|
|
7165
|
-
* ]
|
|
7166
|
-
* }
|
|
7167
|
-
* ]
|
|
7229
|
+
/**
|
|
7230
|
+
* The PathRegistry class manages a hierarchical structure of paths associated with form fields.
|
|
7231
|
+
* It enables claiming, unclaiming, and validating paths within this structure.
|
|
7232
|
+
*
|
|
7233
|
+
* Example Tree Structure:
|
|
7234
|
+
*
|
|
7235
|
+
* [
|
|
7236
|
+
* {
|
|
7237
|
+
* segment: 'root',
|
|
7238
|
+
* claimCount: 1,
|
|
7239
|
+
* children: [
|
|
7240
|
+
* {
|
|
7241
|
+
* segment: 'child1',
|
|
7242
|
+
* claimCount: 2,
|
|
7243
|
+
* children: null // A leaf node (closed path)
|
|
7244
|
+
* },
|
|
7245
|
+
* {
|
|
7246
|
+
* segment: 'child2',
|
|
7247
|
+
* claimCount: 1,
|
|
7248
|
+
* children: [
|
|
7249
|
+
* {
|
|
7250
|
+
* segment: 'subChild1',
|
|
7251
|
+
* claimCount: 1,
|
|
7252
|
+
* children: [] // An open node (open path)
|
|
7253
|
+
* }
|
|
7254
|
+
* ]
|
|
7255
|
+
* }
|
|
7256
|
+
* ]
|
|
7257
|
+
* }
|
|
7258
|
+
* ]
|
|
7168
7259
|
*/
|
|
7169
7260
|
class PathRegistry {
|
|
7170
7261
|
constructor(formFieldRegistry, formFields, injector) {
|
|
@@ -7280,16 +7371,16 @@ class PathRegistry {
|
|
|
7280
7371
|
}
|
|
7281
7372
|
}
|
|
7282
7373
|
|
|
7283
|
-
/**
|
|
7284
|
-
* Applies a function (fn) recursively on a given field and its children.
|
|
7285
|
-
*
|
|
7286
|
-
* - `field`: Starting field object.
|
|
7287
|
-
* - `fn`: Function to apply.
|
|
7288
|
-
* - `context`: Optional object for passing data between calls.
|
|
7289
|
-
*
|
|
7290
|
-
* Stops early if `fn` returns `false`. Useful for traversing the form field tree.
|
|
7291
|
-
*
|
|
7292
|
-
* @returns {boolean} Success status based on function execution.
|
|
7374
|
+
/**
|
|
7375
|
+
* Applies a function (fn) recursively on a given field and its children.
|
|
7376
|
+
*
|
|
7377
|
+
* - `field`: Starting field object.
|
|
7378
|
+
* - `fn`: Function to apply.
|
|
7379
|
+
* - `context`: Optional object for passing data between calls.
|
|
7380
|
+
*
|
|
7381
|
+
* Stops early if `fn` returns `false`. Useful for traversing the form field tree.
|
|
7382
|
+
*
|
|
7383
|
+
* @returns {boolean} Success status based on function execution.
|
|
7293
7384
|
*/
|
|
7294
7385
|
executeRecursivelyOnFields(field, fn, context = {}) {
|
|
7295
7386
|
let result = true;
|
|
@@ -7330,16 +7421,16 @@ class PathRegistry {
|
|
|
7330
7421
|
return result;
|
|
7331
7422
|
}
|
|
7332
7423
|
|
|
7333
|
-
/**
|
|
7334
|
-
* Generates an array representing the binding path to an underlying data object for a form field.
|
|
7335
|
-
*
|
|
7336
|
-
* @param {Object} field - The field object with properties: `key`, `path`, `id`, and optionally `_parent`.
|
|
7337
|
-
* @param {Object} [options={}] - Configuration options.
|
|
7338
|
-
* @param {Object} [options.replacements={}] - A map of field IDs to alternative path arrays.
|
|
7339
|
-
* @param {Object} [options.indexes=null] - A map of parent IDs to the index of the field within said parent, leave null to get an unindexed path.
|
|
7340
|
-
* @param {Object} [options.cutoffNode] - The ID of the parent field at which to stop generating the path.
|
|
7341
|
-
*
|
|
7342
|
-
* @returns {(Array<string>|undefined)} An array of strings representing the binding path, or undefined if not determinable.
|
|
7424
|
+
/**
|
|
7425
|
+
* Generates an array representing the binding path to an underlying data object for a form field.
|
|
7426
|
+
*
|
|
7427
|
+
* @param {Object} field - The field object with properties: `key`, `path`, `id`, and optionally `_parent`.
|
|
7428
|
+
* @param {Object} [options={}] - Configuration options.
|
|
7429
|
+
* @param {Object} [options.replacements={}] - A map of field IDs to alternative path arrays.
|
|
7430
|
+
* @param {Object} [options.indexes=null] - A map of parent IDs to the index of the field within said parent, leave null to get an unindexed path.
|
|
7431
|
+
* @param {Object} [options.cutoffNode] - The ID of the parent field at which to stop generating the path.
|
|
7432
|
+
*
|
|
7433
|
+
* @returns {(Array<string>|undefined)} An array of strings representing the binding path, or undefined if not determinable.
|
|
7343
7434
|
*/
|
|
7344
7435
|
getValuePath(field, options = {}) {
|
|
7345
7436
|
const {
|
|
@@ -7400,23 +7491,23 @@ const _getNextSegment = (node, segment) => {
|
|
|
7400
7491
|
};
|
|
7401
7492
|
PathRegistry.$inject = ['formFieldRegistry', 'formFields', 'injector'];
|
|
7402
7493
|
|
|
7403
|
-
/**
|
|
7404
|
-
* @typedef { { id: String, components: Array<String> } } FormRow
|
|
7405
|
-
* @typedef { { formFieldId: String, rows: Array<FormRow> } } FormRows
|
|
7494
|
+
/**
|
|
7495
|
+
* @typedef { { id: String, components: Array<String> } } FormRow
|
|
7496
|
+
* @typedef { { formFieldId: String, rows: Array<FormRow> } } FormRows
|
|
7406
7497
|
*/
|
|
7407
7498
|
|
|
7408
|
-
/**
|
|
7409
|
-
* Maintains the Form layout in a given structure, for example
|
|
7410
|
-
*
|
|
7411
|
-
* [
|
|
7412
|
-
* {
|
|
7413
|
-
* formFieldId: 'FormField_1',
|
|
7414
|
-
* rows: [
|
|
7415
|
-
* { id: 'Row_1', components: [ 'Text_1', 'Textdield_1', ... ] }
|
|
7416
|
-
* ]
|
|
7417
|
-
* }
|
|
7418
|
-
* ]
|
|
7419
|
-
*
|
|
7499
|
+
/**
|
|
7500
|
+
* Maintains the Form layout in a given structure, for example
|
|
7501
|
+
*
|
|
7502
|
+
* [
|
|
7503
|
+
* {
|
|
7504
|
+
* formFieldId: 'FormField_1',
|
|
7505
|
+
* rows: [
|
|
7506
|
+
* { id: 'Row_1', components: [ 'Text_1', 'Textdield_1', ... ] }
|
|
7507
|
+
* ]
|
|
7508
|
+
* }
|
|
7509
|
+
* ]
|
|
7510
|
+
*
|
|
7420
7511
|
*/
|
|
7421
7512
|
class FormLayouter {
|
|
7422
7513
|
constructor(eventBus) {
|
|
@@ -7426,8 +7517,8 @@ class FormLayouter {
|
|
|
7426
7517
|
this._eventBus = eventBus;
|
|
7427
7518
|
}
|
|
7428
7519
|
|
|
7429
|
-
/**
|
|
7430
|
-
* @param {FormRow} row
|
|
7520
|
+
/**
|
|
7521
|
+
* @param {FormRow} row
|
|
7431
7522
|
*/
|
|
7432
7523
|
addRow(formFieldId, row) {
|
|
7433
7524
|
let rowsPerComponent = this._rows.find(r => r.formFieldId === formFieldId);
|
|
@@ -7441,18 +7532,18 @@ class FormLayouter {
|
|
|
7441
7532
|
rowsPerComponent.rows.push(row);
|
|
7442
7533
|
}
|
|
7443
7534
|
|
|
7444
|
-
/**
|
|
7445
|
-
* @param {String} id
|
|
7446
|
-
* @returns {FormRow}
|
|
7535
|
+
/**
|
|
7536
|
+
* @param {String} id
|
|
7537
|
+
* @returns {FormRow}
|
|
7447
7538
|
*/
|
|
7448
7539
|
getRow(id) {
|
|
7449
7540
|
const rows = allRows(this._rows);
|
|
7450
7541
|
return rows.find(r => r.id === id);
|
|
7451
7542
|
}
|
|
7452
7543
|
|
|
7453
|
-
/**
|
|
7454
|
-
* @param {any} formField
|
|
7455
|
-
* @returns {FormRow}
|
|
7544
|
+
/**
|
|
7545
|
+
* @param {any} formField
|
|
7546
|
+
* @returns {FormRow}
|
|
7456
7547
|
*/
|
|
7457
7548
|
getRowForField(formField) {
|
|
7458
7549
|
return allRows(this._rows).find(r => {
|
|
@@ -7463,9 +7554,9 @@ class FormLayouter {
|
|
|
7463
7554
|
});
|
|
7464
7555
|
}
|
|
7465
7556
|
|
|
7466
|
-
/**
|
|
7467
|
-
* @param {String} formFieldId
|
|
7468
|
-
* @returns { Array<FormRow> }
|
|
7557
|
+
/**
|
|
7558
|
+
* @param {String} formFieldId
|
|
7559
|
+
* @returns { Array<FormRow> }
|
|
7469
7560
|
*/
|
|
7470
7561
|
getRows(formFieldId) {
|
|
7471
7562
|
const rowsForField = this._rows.find(r => formFieldId === r.formFieldId);
|
|
@@ -7475,15 +7566,15 @@ class FormLayouter {
|
|
|
7475
7566
|
return rowsForField.rows;
|
|
7476
7567
|
}
|
|
7477
7568
|
|
|
7478
|
-
/**
|
|
7479
|
-
* @returns {string}
|
|
7569
|
+
/**
|
|
7570
|
+
* @returns {string}
|
|
7480
7571
|
*/
|
|
7481
7572
|
nextRowId() {
|
|
7482
7573
|
return this._ids.nextPrefixed('Row_');
|
|
7483
7574
|
}
|
|
7484
7575
|
|
|
7485
|
-
/**
|
|
7486
|
-
* @param {any} formField
|
|
7576
|
+
/**
|
|
7577
|
+
* @param {any} formField
|
|
7487
7578
|
*/
|
|
7488
7579
|
calculateLayout(formField) {
|
|
7489
7580
|
const {
|
|
@@ -7537,9 +7628,9 @@ function groupByRow(components, ids) {
|
|
|
7537
7628
|
});
|
|
7538
7629
|
}
|
|
7539
7630
|
|
|
7540
|
-
/**
|
|
7541
|
-
* @param {Array<FormRows>} formRows
|
|
7542
|
-
* @returns {Array<FormRow>}
|
|
7631
|
+
/**
|
|
7632
|
+
* @param {Array<FormRows>} formRows
|
|
7633
|
+
* @returns {Array<FormRow>}
|
|
7543
7634
|
*/
|
|
7544
7635
|
function allRows(formRows) {
|
|
7545
7636
|
return flatten(formRows.map(c => c.rows));
|
|
@@ -7664,55 +7755,55 @@ var core = {
|
|
|
7664
7755
|
validator: ['type', Validator]
|
|
7665
7756
|
};
|
|
7666
7757
|
|
|
7667
|
-
/**
|
|
7668
|
-
* @typedef { import('./types').Injector } Injector
|
|
7669
|
-
* @typedef { import('./types').Data } Data
|
|
7670
|
-
* @typedef { import('./types').Errors } Errors
|
|
7671
|
-
* @typedef { import('./types').Schema } Schema
|
|
7672
|
-
* @typedef { import('./types').FormProperties } FormProperties
|
|
7673
|
-
* @typedef { import('./types').FormProperty } FormProperty
|
|
7674
|
-
* @typedef { import('./types').FormEvent } FormEvent
|
|
7675
|
-
* @typedef { import('./types').FormOptions } FormOptions
|
|
7676
|
-
*
|
|
7677
|
-
* @typedef { {
|
|
7678
|
-
* data: Data,
|
|
7679
|
-
* initialData: Data,
|
|
7680
|
-
* errors: Errors,
|
|
7681
|
-
* properties: FormProperties,
|
|
7682
|
-
* schema: Schema
|
|
7683
|
-
* } } State
|
|
7684
|
-
*
|
|
7685
|
-
* @typedef { (type:FormEvent, priority:number, handler:Function) => void } OnEventWithPriority
|
|
7686
|
-
* @typedef { (type:FormEvent, handler:Function) => void } OnEventWithOutPriority
|
|
7687
|
-
* @typedef { OnEventWithPriority & OnEventWithOutPriority } OnEventType
|
|
7758
|
+
/**
|
|
7759
|
+
* @typedef { import('./types').Injector } Injector
|
|
7760
|
+
* @typedef { import('./types').Data } Data
|
|
7761
|
+
* @typedef { import('./types').Errors } Errors
|
|
7762
|
+
* @typedef { import('./types').Schema } Schema
|
|
7763
|
+
* @typedef { import('./types').FormProperties } FormProperties
|
|
7764
|
+
* @typedef { import('./types').FormProperty } FormProperty
|
|
7765
|
+
* @typedef { import('./types').FormEvent } FormEvent
|
|
7766
|
+
* @typedef { import('./types').FormOptions } FormOptions
|
|
7767
|
+
*
|
|
7768
|
+
* @typedef { {
|
|
7769
|
+
* data: Data,
|
|
7770
|
+
* initialData: Data,
|
|
7771
|
+
* errors: Errors,
|
|
7772
|
+
* properties: FormProperties,
|
|
7773
|
+
* schema: Schema
|
|
7774
|
+
* } } State
|
|
7775
|
+
*
|
|
7776
|
+
* @typedef { (type:FormEvent, priority:number, handler:Function) => void } OnEventWithPriority
|
|
7777
|
+
* @typedef { (type:FormEvent, handler:Function) => void } OnEventWithOutPriority
|
|
7778
|
+
* @typedef { OnEventWithPriority & OnEventWithOutPriority } OnEventType
|
|
7688
7779
|
*/
|
|
7689
7780
|
|
|
7690
7781
|
const ids = new Ids([32, 36, 1]);
|
|
7691
7782
|
|
|
7692
|
-
/**
|
|
7693
|
-
* The form.
|
|
7783
|
+
/**
|
|
7784
|
+
* The form.
|
|
7694
7785
|
*/
|
|
7695
7786
|
class Form {
|
|
7696
|
-
/**
|
|
7697
|
-
* @constructor
|
|
7698
|
-
* @param {FormOptions} options
|
|
7787
|
+
/**
|
|
7788
|
+
* @constructor
|
|
7789
|
+
* @param {FormOptions} options
|
|
7699
7790
|
*/
|
|
7700
7791
|
constructor(options = {}) {
|
|
7701
|
-
/**
|
|
7702
|
-
* @public
|
|
7703
|
-
* @type {OnEventType}
|
|
7792
|
+
/**
|
|
7793
|
+
* @public
|
|
7794
|
+
* @type {OnEventType}
|
|
7704
7795
|
*/
|
|
7705
7796
|
this.on = this._onEvent;
|
|
7706
7797
|
|
|
7707
|
-
/**
|
|
7708
|
-
* @public
|
|
7709
|
-
* @type {String}
|
|
7798
|
+
/**
|
|
7799
|
+
* @public
|
|
7800
|
+
* @type {String}
|
|
7710
7801
|
*/
|
|
7711
7802
|
this._id = ids.next();
|
|
7712
7803
|
|
|
7713
|
-
/**
|
|
7714
|
-
* @private
|
|
7715
|
-
* @type {Element}
|
|
7804
|
+
/**
|
|
7805
|
+
* @private
|
|
7806
|
+
* @type {Element}
|
|
7716
7807
|
*/
|
|
7717
7808
|
this._container = createFormContainer();
|
|
7718
7809
|
const {
|
|
@@ -7721,9 +7812,9 @@ class Form {
|
|
|
7721
7812
|
properties = {}
|
|
7722
7813
|
} = options;
|
|
7723
7814
|
|
|
7724
|
-
/**
|
|
7725
|
-
* @private
|
|
7726
|
-
* @type {State}
|
|
7815
|
+
/**
|
|
7816
|
+
* @private
|
|
7817
|
+
* @type {State}
|
|
7727
7818
|
*/
|
|
7728
7819
|
this._state = {
|
|
7729
7820
|
initialData: null,
|
|
@@ -7747,9 +7838,9 @@ class Form {
|
|
|
7747
7838
|
this._emit('form.clear');
|
|
7748
7839
|
}
|
|
7749
7840
|
|
|
7750
|
-
/**
|
|
7751
|
-
* Destroy the form, removing it from DOM,
|
|
7752
|
-
* if attached.
|
|
7841
|
+
/**
|
|
7842
|
+
* Destroy the form, removing it from DOM,
|
|
7843
|
+
* if attached.
|
|
7753
7844
|
*/
|
|
7754
7845
|
destroy() {
|
|
7755
7846
|
// destroy form services
|
|
@@ -7760,13 +7851,13 @@ class Form {
|
|
|
7760
7851
|
this._detach(false);
|
|
7761
7852
|
}
|
|
7762
7853
|
|
|
7763
|
-
/**
|
|
7764
|
-
* Open a form schema with the given initial data.
|
|
7765
|
-
*
|
|
7766
|
-
* @param {Schema} schema
|
|
7767
|
-
* @param {Data} [data]
|
|
7768
|
-
*
|
|
7769
|
-
* @return Promise<{ warnings: Array<any> }>
|
|
7854
|
+
/**
|
|
7855
|
+
* Open a form schema with the given initial data.
|
|
7856
|
+
*
|
|
7857
|
+
* @param {Schema} schema
|
|
7858
|
+
* @param {Data} [data]
|
|
7859
|
+
*
|
|
7860
|
+
* @return Promise<{ warnings: Array<any> }>
|
|
7770
7861
|
*/
|
|
7771
7862
|
importSchema(schema, data = {}) {
|
|
7772
7863
|
return new Promise((resolve, reject) => {
|
|
@@ -7799,10 +7890,10 @@ class Form {
|
|
|
7799
7890
|
});
|
|
7800
7891
|
}
|
|
7801
7892
|
|
|
7802
|
-
/**
|
|
7803
|
-
* Submit the form, triggering all field validations.
|
|
7804
|
-
*
|
|
7805
|
-
* @returns { { data: Data, errors: Errors } }
|
|
7893
|
+
/**
|
|
7894
|
+
* Submit the form, triggering all field validations.
|
|
7895
|
+
*
|
|
7896
|
+
* @returns { { data: Data, errors: Errors } }
|
|
7806
7897
|
*/
|
|
7807
7898
|
submit() {
|
|
7808
7899
|
const {
|
|
@@ -7828,8 +7919,8 @@ class Form {
|
|
|
7828
7919
|
});
|
|
7829
7920
|
}
|
|
7830
7921
|
|
|
7831
|
-
/**
|
|
7832
|
-
* @returns {Errors}
|
|
7922
|
+
/**
|
|
7923
|
+
* @returns {Errors}
|
|
7833
7924
|
*/
|
|
7834
7925
|
validate() {
|
|
7835
7926
|
const formFields = this.get('formFields'),
|
|
@@ -7901,8 +7992,8 @@ class Form {
|
|
|
7901
7992
|
return filteredErrors;
|
|
7902
7993
|
}
|
|
7903
7994
|
|
|
7904
|
-
/**
|
|
7905
|
-
* @param {Element|string} parentNode
|
|
7995
|
+
/**
|
|
7996
|
+
* @param {Element|string} parentNode
|
|
7906
7997
|
*/
|
|
7907
7998
|
attachTo(parentNode) {
|
|
7908
7999
|
if (!parentNode) {
|
|
@@ -7920,10 +8011,10 @@ class Form {
|
|
|
7920
8011
|
this._detach();
|
|
7921
8012
|
}
|
|
7922
8013
|
|
|
7923
|
-
/**
|
|
7924
|
-
* @private
|
|
7925
|
-
*
|
|
7926
|
-
* @param {boolean} [emit]
|
|
8014
|
+
/**
|
|
8015
|
+
* @private
|
|
8016
|
+
*
|
|
8017
|
+
* @param {boolean} [emit]
|
|
7927
8018
|
*/
|
|
7928
8019
|
_detach(emit = true) {
|
|
7929
8020
|
const container = this._container,
|
|
@@ -7937,9 +8028,9 @@ class Form {
|
|
|
7937
8028
|
parentNode.removeChild(container);
|
|
7938
8029
|
}
|
|
7939
8030
|
|
|
7940
|
-
/**
|
|
7941
|
-
* @param {FormProperty} property
|
|
7942
|
-
* @param {any} value
|
|
8031
|
+
/**
|
|
8032
|
+
* @param {FormProperty} property
|
|
8033
|
+
* @param {any} value
|
|
7943
8034
|
*/
|
|
7944
8035
|
setProperty(property, value) {
|
|
7945
8036
|
const properties = set(this._getState().properties, [property], value);
|
|
@@ -7948,50 +8039,52 @@ class Form {
|
|
|
7948
8039
|
});
|
|
7949
8040
|
}
|
|
7950
8041
|
|
|
7951
|
-
/**
|
|
7952
|
-
* @param {FormEvent} type
|
|
7953
|
-
* @param {Function} handler
|
|
8042
|
+
/**
|
|
8043
|
+
* @param {FormEvent} type
|
|
8044
|
+
* @param {Function} handler
|
|
7954
8045
|
*/
|
|
7955
8046
|
off(type, handler) {
|
|
7956
8047
|
this.get('eventBus').off(type, handler);
|
|
7957
8048
|
}
|
|
7958
8049
|
|
|
7959
|
-
/**
|
|
7960
|
-
* @private
|
|
7961
|
-
*
|
|
7962
|
-
* @param {FormOptions} options
|
|
7963
|
-
* @param {Element} container
|
|
7964
|
-
*
|
|
7965
|
-
* @returns {Injector}
|
|
8050
|
+
/**
|
|
8051
|
+
* @private
|
|
8052
|
+
*
|
|
8053
|
+
* @param {FormOptions} options
|
|
8054
|
+
* @param {Element} container
|
|
8055
|
+
*
|
|
8056
|
+
* @returns {Injector}
|
|
7966
8057
|
*/
|
|
7967
8058
|
_createInjector(options, container) {
|
|
7968
8059
|
const {
|
|
8060
|
+
modules = this._getModules(),
|
|
7969
8061
|
additionalModules = [],
|
|
7970
|
-
|
|
8062
|
+
...config
|
|
7971
8063
|
} = options;
|
|
7972
|
-
const
|
|
8064
|
+
const enrichedConfig = {
|
|
8065
|
+
...config,
|
|
7973
8066
|
renderer: {
|
|
7974
8067
|
container
|
|
7975
8068
|
}
|
|
7976
8069
|
};
|
|
7977
8070
|
return createInjector([{
|
|
7978
|
-
config: ['value',
|
|
8071
|
+
config: ['value', enrichedConfig]
|
|
7979
8072
|
}, {
|
|
7980
8073
|
form: ['value', this]
|
|
7981
8074
|
}, core, ...modules, ...additionalModules]);
|
|
7982
8075
|
}
|
|
7983
8076
|
|
|
7984
|
-
/**
|
|
7985
|
-
* @private
|
|
8077
|
+
/**
|
|
8078
|
+
* @private
|
|
7986
8079
|
*/
|
|
7987
8080
|
_emit(type, data) {
|
|
7988
8081
|
this.get('eventBus').fire(type, data);
|
|
7989
8082
|
}
|
|
7990
8083
|
|
|
7991
|
-
/**
|
|
7992
|
-
* @internal
|
|
7993
|
-
*
|
|
7994
|
-
* @param { { add?: boolean, field: any, indexes: object, remove?: number, value?: any } } update
|
|
8084
|
+
/**
|
|
8085
|
+
* @internal
|
|
8086
|
+
*
|
|
8087
|
+
* @param { { add?: boolean, field: any, indexes: object, remove?: number, value?: any } } update
|
|
7995
8088
|
*/
|
|
7996
8089
|
_update(update) {
|
|
7997
8090
|
const {
|
|
@@ -8017,15 +8110,15 @@ class Form {
|
|
|
8017
8110
|
});
|
|
8018
8111
|
}
|
|
8019
8112
|
|
|
8020
|
-
/**
|
|
8021
|
-
* @internal
|
|
8113
|
+
/**
|
|
8114
|
+
* @internal
|
|
8022
8115
|
*/
|
|
8023
8116
|
_getState() {
|
|
8024
8117
|
return this._state;
|
|
8025
8118
|
}
|
|
8026
8119
|
|
|
8027
|
-
/**
|
|
8028
|
-
* @internal
|
|
8120
|
+
/**
|
|
8121
|
+
* @internal
|
|
8029
8122
|
*/
|
|
8030
8123
|
_setState(state) {
|
|
8031
8124
|
this._state = {
|
|
@@ -8035,22 +8128,22 @@ class Form {
|
|
|
8035
8128
|
this._emit('changed', this._getState());
|
|
8036
8129
|
}
|
|
8037
8130
|
|
|
8038
|
-
/**
|
|
8039
|
-
* @internal
|
|
8131
|
+
/**
|
|
8132
|
+
* @internal
|
|
8040
8133
|
*/
|
|
8041
8134
|
_getModules() {
|
|
8042
8135
|
return [ExpressionLanguageModule, MarkdownModule, ViewerCommandsModule, RepeatRenderModule];
|
|
8043
8136
|
}
|
|
8044
8137
|
|
|
8045
|
-
/**
|
|
8046
|
-
* @internal
|
|
8138
|
+
/**
|
|
8139
|
+
* @internal
|
|
8047
8140
|
*/
|
|
8048
8141
|
_onEvent(type, priority, handler) {
|
|
8049
8142
|
this.get('eventBus').on(type, priority, handler);
|
|
8050
8143
|
}
|
|
8051
8144
|
|
|
8052
|
-
/**
|
|
8053
|
-
* @internal
|
|
8145
|
+
/**
|
|
8146
|
+
* @internal
|
|
8054
8147
|
*/
|
|
8055
8148
|
_getSubmitData() {
|
|
8056
8149
|
const formFieldRegistry = this.get('formFieldRegistry');
|
|
@@ -8107,16 +8200,16 @@ class Form {
|
|
|
8107
8200
|
return this._applyConditions(workingSubmitData, formData);
|
|
8108
8201
|
}
|
|
8109
8202
|
|
|
8110
|
-
/**
|
|
8111
|
-
* @internal
|
|
8203
|
+
/**
|
|
8204
|
+
* @internal
|
|
8112
8205
|
*/
|
|
8113
8206
|
_applyConditions(toFilter, data, options = {}) {
|
|
8114
8207
|
const conditionChecker = this.get('conditionChecker');
|
|
8115
8208
|
return conditionChecker.applyConditions(toFilter, data, options);
|
|
8116
8209
|
}
|
|
8117
8210
|
|
|
8118
|
-
/**
|
|
8119
|
-
* @internal
|
|
8211
|
+
/**
|
|
8212
|
+
* @internal
|
|
8120
8213
|
*/
|
|
8121
8214
|
_getInitializedFieldData(data, options = {}) {
|
|
8122
8215
|
const formFieldRegistry = this.get('formFieldRegistry');
|
|
@@ -8222,9 +8315,9 @@ function createForm(options) {
|
|
|
8222
8315
|
const {
|
|
8223
8316
|
data,
|
|
8224
8317
|
schema,
|
|
8225
|
-
...
|
|
8318
|
+
...formOptions
|
|
8226
8319
|
} = options;
|
|
8227
|
-
const form = new Form(
|
|
8320
|
+
const form = new Form(formOptions);
|
|
8228
8321
|
return form.importSchema(schema, data).then(function () {
|
|
8229
8322
|
return form;
|
|
8230
8323
|
});
|