@bpmn-io/form-js-viewer 0.14.0 → 0.15.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/LICENSE +22 -22
  2. package/README.md +164 -164
  3. package/dist/assets/form-js-base.css +832 -781
  4. package/dist/assets/form-js.css +92 -41
  5. package/dist/index.cjs +956 -541
  6. package/dist/index.cjs.map +1 -1
  7. package/dist/index.es.js +958 -543
  8. package/dist/index.es.js.map +1 -1
  9. package/dist/types/Form.d.ts +23 -1
  10. package/dist/types/core/EventBus.d.ts +1 -1
  11. package/dist/types/core/index.d.ts +2 -1
  12. package/dist/types/features/expression-language/FeelExpressionLanguage.d.ts +3 -5
  13. package/dist/types/features/expression-language/FeelersTemplating.d.ts +42 -0
  14. package/dist/types/features/expression-language/variableExtractionHelpers.d.ts +1 -0
  15. package/dist/types/render/Renderer.d.ts +2 -2
  16. package/dist/types/render/components/Util.d.ts +2 -2
  17. package/dist/types/render/components/form-fields/Button.d.ts +9 -7
  18. package/dist/types/render/components/form-fields/Checkbox.d.ts +11 -9
  19. package/dist/types/render/components/form-fields/Checklist.d.ts +14 -12
  20. package/dist/types/render/components/form-fields/Datetime.d.ts +9 -7
  21. package/dist/types/render/components/form-fields/Default.d.ts +9 -7
  22. package/dist/types/render/components/form-fields/Image.d.ts +7 -5
  23. package/dist/types/render/components/form-fields/Number.d.ts +12 -10
  24. package/dist/types/render/components/form-fields/Radio.d.ts +14 -12
  25. package/dist/types/render/components/form-fields/Select.d.ts +14 -12
  26. package/dist/types/render/components/form-fields/Taglist.d.ts +14 -12
  27. package/dist/types/render/components/form-fields/Text.d.ts +9 -7
  28. package/dist/types/render/components/form-fields/Textarea.d.ts +11 -9
  29. package/dist/types/render/components/form-fields/Textfield.d.ts +11 -9
  30. package/dist/types/types.d.ts +35 -35
  31. package/dist/types/util/index.d.ts +2 -1
  32. package/package.json +3 -2
package/dist/index.es.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import Ids from 'ids';
2
2
  import { isString, isArray, isFunction, isNumber, bind, assign, isNil, groupBy, flatten, get, isUndefined, set, findIndex, isObject } from 'min-dash';
3
- import { evaluate, parseExpressions, parseUnaryTests, unaryTest } from 'feelin';
4
- import { evaluate as evaluate$1 } from 'feelers';
3
+ import { parseExpressions, parseUnaryTests, evaluate, unaryTest } from 'feelin';
4
+ import { evaluate as evaluate$1, parser, buildSimpleTree } from 'feelers';
5
5
  import showdown from 'showdown';
6
6
  import Big from 'big.js';
7
7
  import classNames from 'classnames';
@@ -13,30 +13,179 @@ import flatpickr from 'flatpickr';
13
13
  import Markup from 'preact-markup';
14
14
  import { Injector } from 'didi';
15
15
 
16
+ const getFlavouredFeelVariableNames = (feelString, feelFlavour, options = {}) => {
17
+ const {
18
+ depth = 0,
19
+ specialDepthAccessors = {}
20
+ } = options;
21
+ if (!['expression', 'unaryTest'].includes(feelFlavour)) return [];
22
+ const tree = feelFlavour === 'expression' ? parseExpressions(feelString) : parseUnaryTests(feelString);
23
+ const simpleExpressionTree = _buildSimpleFeelStructureTree(tree, feelString);
24
+ return function _unfoldVariables(node) {
25
+ if (node.name === 'PathExpression') {
26
+ if (Object.keys(specialDepthAccessors).length === 0) {
27
+ return depth === 0 ? [_getVariableNameAtPathIndex(node, 0)] : [];
28
+ }
29
+
30
+ // if using special depth accessors, use a more complex extraction
31
+ return Array.from(_smartExtractVariableNames(node, depth, specialDepthAccessors));
32
+ }
33
+ if (depth === 0 && node.name === 'VariableName') return [node.variableName];
34
+
35
+ // for any other kind of node, traverse its children and flatten the result
36
+ if (node.children) {
37
+ return node.children.reduce((acc, child) => {
38
+ return acc.concat(_unfoldVariables(child));
39
+ }, []);
40
+ }
41
+ return [];
42
+ }(simpleExpressionTree);
43
+ };
44
+
45
+ /**
46
+ * Get the variable name at the specified index in a given path expression.
47
+ *
48
+ * @param {Object} root - The root node of the path expression tree.
49
+ * @param {number} index - The index of the variable name to retrieve.
50
+ * @returns {string|null} The variable name at the specified index or null if index is out of bounds.
51
+ */
52
+ const _getVariableNameAtPathIndex = (root, index) => {
53
+ const accessors = _deconstructPathExpression(root);
54
+ return accessors[index] || null;
55
+ };
56
+
57
+ /**
58
+ * Extracts the variables which are required of the external context for a given path expression.
59
+ * This is done by traversing the path expression tree and keeping track of the current depth relative to the external context.
60
+ *
61
+ * @param {Object} node - The root node of the path expression tree.
62
+ * @param {number} initialDepth - The depth at which the root node is located in the outer context.
63
+ * @param {Object} specialDepthAccessors - Definitions of special keywords which represent more complex accesses of the outer context.
64
+ * @returns {Set} - A set containing the extracted variable names.
65
+ */
66
+ const _smartExtractVariableNames = (node, initialDepth, specialDepthAccessors) => {
67
+ // depth info represents the previous (initialised as null) and current depth of the current accessor in the path expression
68
+ // we track multiple of these to account for the fact that a path expression may be ambiguous due to special keywords
69
+ let accessorDepthInfos = [{
70
+ previous: null,
71
+ current: initialDepth - 1
72
+ }];
73
+ const extractedVariables = new Set();
74
+ const nodeAccessors = _deconstructPathExpression(node);
75
+ for (let i = 0; i < nodeAccessors.length; i++) {
76
+ const currentAccessor = nodeAccessors[i];
77
+ if (currentAccessor in specialDepthAccessors) {
78
+ const depthOffsets = specialDepthAccessors[currentAccessor];
79
+
80
+ // if the current accessor is a special keyword, we need to expand the current depth info set
81
+ // this is done to account for the ambiguity of keywords like parent, which may be used to access
82
+ // the parent of the current node, or a child variable of the same name
83
+ accessorDepthInfos = depthOffsets.reduce((accumulator, offset) => {
84
+ return [...accumulator, ...accessorDepthInfos.map(depthInfo => ({
85
+ previous: depthInfo.current,
86
+ current: depthInfo.current + offset
87
+ }))];
88
+ }, []).filter(depthInfo => depthInfo.current >= -1); // discard all depth infos which are out of bounds
89
+ } else {
90
+ // if the current accessor is not a special keyword, we know it's simply accessing a child
91
+ // hence we are now one level deeper in the tree and simply increment
92
+ accessorDepthInfos = accessorDepthInfos.map(depthInfo => ({
93
+ previous: depthInfo.current,
94
+ current: depthInfo.current + 1
95
+ }));
96
+ }
97
+
98
+ // finally, we check if for the current accessor, there is a scenario where:
99
+ // previous it was at depth -1 (i.e. the root context), and is now at depth 0 (i.e. a variable)
100
+ // these are the variables we need to request, so we add them to the set
101
+ if (accessorDepthInfos.some(depthInfo => depthInfo.previous === -1 && depthInfo.current === 0)) {
102
+ extractedVariables.add(currentAccessor);
103
+ }
104
+ }
105
+
106
+ // we return a set to avoid duplicates
107
+ return new Set(extractedVariables);
108
+ };
109
+
110
+ /**
111
+ * Deconstructs a path expression tree into an array of components.
112
+ *
113
+ * @param {Object} root - The root node of the path expression tree.
114
+ * @returns {Array<string>} An array of components in the path expression, in the correct order.
115
+ */
116
+ const _deconstructPathExpression = root => {
117
+ let node = root;
118
+ let parts = [];
119
+
120
+ // Traverse the tree and collect path components
121
+ while (node.name === 'PathExpression') {
122
+ parts.push(node.children[1].variableName);
123
+ node = node.children[0];
124
+ }
125
+
126
+ // Add the last component to the array
127
+ parts.push(node.variableName);
128
+
129
+ // Reverse and return the array to get the correct order
130
+ return parts.reverse();
131
+ };
132
+
133
+ /**
134
+ * Builds a simplified feel structure tree from the given parse tree and feel string.
135
+ * The nodes follow this structure: `{ name: string, children: Array, variableName?: string }`
136
+ *
137
+ * @param {Object} parseTree - The parse tree generated by a parser.
138
+ * @param {string} feelString - The feel string used for parsing.
139
+ * @returns {Object} The simplified feel structure tree.
140
+ */
141
+ const _buildSimpleFeelStructureTree = (parseTree, feelString) => {
142
+ const stack = [{
143
+ children: []
144
+ }];
145
+ parseTree.iterate({
146
+ enter: node => {
147
+ const nodeRepresentation = {
148
+ name: node.type.name,
149
+ children: []
150
+ };
151
+ if (node.type.name === 'VariableName') {
152
+ nodeRepresentation.variableName = feelString.slice(node.from, node.to);
153
+ }
154
+ stack.push(nodeRepresentation);
155
+ },
156
+ leave: () => {
157
+ const result = stack.pop();
158
+ const parent = stack[stack.length - 1];
159
+ parent.children.push(result);
160
+ }
161
+ });
162
+ return stack[0].children[0];
163
+ };
164
+
16
165
  class FeelExpressionLanguage {
17
166
  constructor(eventBus) {
18
167
  this._eventBus = eventBus;
19
168
  }
20
169
 
21
- /**
22
- * Determines if the given string is a FEEL expression.
23
- *
24
- * @param {string} value
25
- * @returns {boolean}
26
- *
170
+ /**
171
+ * Determines if the given value is a FEEL expression.
172
+ *
173
+ * @param {any} value
174
+ * @returns {boolean}
175
+ *
27
176
  */
28
177
  isExpression(value) {
29
178
  return isString(value) && value.startsWith('=');
30
179
  }
31
180
 
32
- /**
33
- * Retrieve variable names from a given FEEL expression.
34
- *
35
- * @param {string} expression
36
- * @param {object} [options]
37
- * @param {string} [options.type]
38
- *
39
- * @returns {string[]}
181
+ /**
182
+ * Retrieve variable names from a given FEEL expression.
183
+ *
184
+ * @param {string} expression
185
+ * @param {object} [options]
186
+ * @param {string} [options.type]
187
+ *
188
+ * @returns {string[]}
40
189
  */
41
190
  getVariableNames(expression, options = {}) {
42
191
  const {
@@ -45,21 +194,19 @@ class FeelExpressionLanguage {
45
194
  if (!this.isExpression(expression)) {
46
195
  return [];
47
196
  }
48
- if (type === 'unaryTest') {
49
- return this._getUnaryVariableNames(expression);
50
- } else if (type === 'expression') {
51
- return this._getExpressionVariableNames(expression);
197
+ if (!['unaryTest', 'expression'].includes(type)) {
198
+ throw new Error('Unknown expression type: ' + type);
52
199
  }
53
- throw new Error('Unknown expression type: ' + options.type);
200
+ return getFlavouredFeelVariableNames(expression, type);
54
201
  }
55
202
 
56
- /**
57
- * Evaluate an expression.
58
- *
59
- * @param {string} expression
60
- * @param {import('../../types').Data} [data]
61
- *
62
- * @returns {any}
203
+ /**
204
+ * Evaluate an expression.
205
+ *
206
+ * @param {string} expression
207
+ * @param {import('../../types').Data} [data]
208
+ *
209
+ * @returns {any}
63
210
  */
64
211
  evaluate(expression, data = {}) {
65
212
  if (!expression) {
@@ -78,50 +225,65 @@ class FeelExpressionLanguage {
78
225
  return null;
79
226
  }
80
227
  }
81
- _getExpressionVariableNames(expression) {
82
- const tree = parseExpressions(expression);
83
- const cursor = tree.cursor();
84
- const variables = new Set();
85
- do {
86
- const node = cursor.node;
87
- if (node.type.name === 'VariableName') {
88
- variables.add(expression.slice(node.from, node.to));
89
- }
90
- } while (cursor.next());
91
- return Array.from(variables);
92
- }
93
- _getUnaryVariableNames(unaryTest) {
94
- const tree = parseUnaryTests(unaryTest);
95
- const cursor = tree.cursor();
96
- const variables = new Set();
97
- do {
98
- const node = cursor.node;
99
- if (node.type.name === 'VariableName') {
100
- variables.add(unaryTest.slice(node.from, node.to));
101
- }
102
- } while (cursor.next());
103
- return Array.from(variables);
104
- }
105
228
  }
106
229
  FeelExpressionLanguage.$inject = ['eventBus'];
107
230
 
108
231
  class FeelersTemplating {
109
232
  constructor() {}
233
+
234
+ /**
235
+ * Determines if the given value is a feelers template.
236
+ *
237
+ * @param {any} value
238
+ * @returns {boolean}
239
+ *
240
+ */
110
241
  isTemplate(value) {
111
- return isString(value) && (value.startsWith('=') || /{{/.test(value));
242
+ return isString(value) && (value.startsWith('=') || /{{.*?}}/.test(value));
112
243
  }
113
244
 
114
- /**
115
- * Evaluate a template.
116
- *
117
- * @param {string} template
118
- * @param {Object<string, any>} context
119
- * @param {Object} options
120
- * @param {boolean} [options.debug = false]
121
- * @param {boolean} [options.strict = false]
122
- * @param {Function} [options.buildDebugString]
123
- *
124
- * @returns
245
+ /**
246
+ * Retrieve variable names from a given feelers template.
247
+ *
248
+ * @param {string} template
249
+ *
250
+ * @returns {string[]}
251
+ */
252
+ getVariableNames(template) {
253
+ if (!this.isTemplate(template)) {
254
+ return [];
255
+ }
256
+ const expressions = this._extractExpressionsWithDepth(template);
257
+
258
+ // defines special accessors, and the change(s) in depth they could imply (e.g. parent can be used to access the parent context (depth - 1) or a child variable named parent (depth + 1)
259
+ const specialDepthAccessors = {
260
+ parent: [-1, 1],
261
+ _parent_: [-1],
262
+ this: [0, 1],
263
+ _this_: [0]
264
+ };
265
+ return expressions.reduce((variables, {
266
+ expression,
267
+ depth
268
+ }) => {
269
+ return variables.concat(getFlavouredFeelVariableNames(expression, 'expression', {
270
+ depth,
271
+ specialDepthAccessors
272
+ }));
273
+ }, []);
274
+ }
275
+
276
+ /**
277
+ * Evaluate a template.
278
+ *
279
+ * @param {string} template
280
+ * @param {Object<string, any>} context
281
+ * @param {Object} options
282
+ * @param {boolean} [options.debug = false]
283
+ * @param {boolean} [options.strict = false]
284
+ * @param {Function} [options.buildDebugString]
285
+ *
286
+ * @returns
125
287
  */
126
288
  evaluate(template, context = {}, options = {}) {
127
289
  const {
@@ -135,12 +297,56 @@ class FeelersTemplating {
135
297
  buildDebugString
136
298
  });
137
299
  }
300
+
301
+ /**
302
+ * @typedef {Object} ExpressionWithDepth
303
+ * @property {number} depth - The depth of the expression in the syntax tree.
304
+ * @property {string} expression - The extracted expression
305
+ */
306
+
307
+ /**
308
+ * Extracts all feel expressions in the template along with their depth in the syntax tree.
309
+ * The depth is incremented for child expressions of loops to account for context drilling.
310
+ * @name extractExpressionsWithDepth
311
+ * @param {string} template - A feelers template string.
312
+ * @returns {Array<ExpressionWithDepth>} An array of objects, each containing the depth and the extracted expression.
313
+ *
314
+ * @example
315
+ * const template = "Hello {{user}}, you have:{{#loop items}}\n- {{amount}} {{name}}{{/loop}}.";
316
+ * const extractedExpressions = _extractExpressionsWithDepth(template);
317
+ */
318
+ _extractExpressionsWithDepth(template) {
319
+ // build simplified feelers syntax tree
320
+ const parseTree = parser.parse(template);
321
+ const tree = buildSimpleTree(parseTree, template);
322
+ return function _traverse(n, depth = 0) {
323
+ if (['Feel', 'FeelBlock'].includes(n.name)) {
324
+ return [{
325
+ depth,
326
+ expression: n.content
327
+ }];
328
+ }
329
+ if (n.name === 'LoopSpanner') {
330
+ const loopExpression = n.children[0].content;
331
+ const childResults = n.children.slice(1).reduce((acc, child) => {
332
+ return acc.concat(_traverse(child, depth + 1));
333
+ }, []);
334
+ return [{
335
+ depth,
336
+ expression: loopExpression
337
+ }, ...childResults];
338
+ }
339
+ return n.children.reduce((acc, child) => {
340
+ return acc.concat(_traverse(child, depth));
341
+ }, []);
342
+ }(tree);
343
+ }
138
344
  }
139
345
  FeelersTemplating.$inject = [];
140
346
 
141
- /**
142
- * @typedef {object} Condition
143
- * @property {string} [hide]
347
+ /**
348
+ * @typedef {object} Condition
349
+ * @property {string} [hide]
144
350
  */
145
351
 
146
352
  class ConditionChecker {
@@ -149,11 +355,11 @@ class ConditionChecker {
149
355
  this._eventBus = eventBus;
150
356
  }
151
357
 
152
- /**
153
- * For given data, remove properties based on condition.
154
- *
155
- * @param {Object<string, any>} properties
156
- * @param {Object<string, any>} data
358
+ /**
359
+ * For given data, remove properties based on condition.
360
+ *
361
+ * @param {Object<string, any>} properties
362
+ * @param {Object<string, any>} data
157
363
  */
158
364
  applyConditions(properties, data = {}) {
159
365
  const conditions = this._getConditions();
@@ -172,13 +378,13 @@ class ConditionChecker {
172
378
  return newProperties;
173
379
  }
174
380
 
175
- /**
176
- * Check if given condition is met. Returns null for invalid/missing conditions.
177
- *
178
- * @param {string} condition
179
- * @param {import('../../types').Data} [data]
180
- *
181
- * @returns {boolean|null}
381
+ /**
382
+ * Check if given condition is met. Returns null for invalid/missing conditions.
383
+ *
384
+ * @param {string} condition
385
+ * @param {import('../../types').Data} [data]
386
+ *
387
+ * @returns {boolean|null}
182
388
  */
183
389
  check(condition, data = {}) {
184
390
  if (!condition) {
@@ -199,12 +405,12 @@ class ConditionChecker {
199
405
  }
200
406
  }
201
407
 
202
- /**
203
- * Check if hide condition is met.
204
- *
205
- * @param {Condition} condition
206
- * @param {Object<string, any>} data
207
- * @returns {boolean}
408
+ /**
409
+ * Check if hide condition is met.
410
+ *
411
+ * @param {Condition} condition
412
+ * @param {Object<string, any>} data
413
+ * @returns {boolean}
208
414
  */
209
415
  _checkHideCondition(condition, data) {
210
416
  if (!condition.hide) {
@@ -246,12 +452,12 @@ class MarkdownRenderer {
246
452
  this._converter = new showdown.Converter();
247
453
  }
248
454
 
249
- /**
250
- * Render markdown to HTML.
251
- *
252
- * @param {string} markdown - The markdown to render
253
- *
254
- * @returns {string} HTML
455
+ /**
456
+ * Render markdown to HTML.
457
+ *
458
+ * @param {string} markdown - The markdown to render
459
+ *
460
+ * @returns {string} HTML
255
461
  */
256
462
  render(markdown) {
257
463
  return this._converter.makeHtml(markdown);
@@ -268,6 +474,30 @@ var FN_REF = '__fn';
268
474
  var DEFAULT_PRIORITY = 1000;
269
475
  var slice = Array.prototype.slice;
270
476
 
477
+ /**
478
+ * @typedef { {
479
+ * stopPropagation(): void;
480
+ * preventDefault(): void;
481
+ * cancelBubble: boolean;
482
+ * defaultPrevented: boolean;
483
+ * returnValue: any;
484
+ * } } Event
485
+ */
486
+
487
+ /**
488
+ * @template E
489
+ *
490
+ * @typedef { (event: E & Event, ...any) => any } EventBusEventCallback
491
+ */
492
+
493
+ /**
494
+ * @typedef { {
495
+ * priority: number;
496
+ * next: EventBusListener | null;
497
+ * callback: EventBusEventCallback<any>;
498
+ * } } EventBusListener
499
+ */
500
+
271
501
  /**
272
502
  * A general purpose event bus.
273
503
  *
@@ -352,6 +582,9 @@ var slice = Array.prototype.slice;
352
582
  * ```
353
583
  */
354
584
  function EventBus() {
585
+ /**
586
+ * @type { Record<string, EventBusListener> }
587
+ */
355
588
  this._listeners = {};
356
589
 
357
590
  // cleanup on destroy on lowest priority to allow
@@ -371,10 +604,12 @@ function EventBus() {
371
604
  *
372
605
  * Returning anything but `undefined` from a listener will stop the listener propagation.
373
606
  *
374
- * @param {string|Array<string>} events
375
- * @param {number} [priority=1000] the priority in which this listener is called, larger is higher
376
- * @param {Function} callback
377
- * @param {Object} [that] Pass context (`this`) to the callback
607
+ * @template T
608
+ *
609
+ * @param {string|string[]} events to subscribe to
610
+ * @param {number} [priority=1000] listen priority
611
+ * @param {EventBusEventCallback<T>} callback
612
+ * @param {any} [that] callback context
378
613
  */
379
614
  EventBus.prototype.on = function (events, priority, callback, that) {
380
615
  events = isArray(events) ? events : [events];
@@ -406,14 +641,16 @@ EventBus.prototype.on = function (events, priority, callback, that) {
406
641
  };
407
642
 
408
643
  /**
409
- * Register an event listener that is executed only once.
644
+ * Register an event listener that is called only once.
410
645
  *
411
- * @param {string} event the event name to register for
412
- * @param {number} [priority=1000] the priority in which this listener is called, larger is higher
413
- * @param {Function} callback the callback to execute
414
- * @param {Object} [that] Pass context (`this`) to the callback
646
+ * @template T
647
+ *
648
+ * @param {string|string[]} events to subscribe to
649
+ * @param {number} [priority=1000] the listen priority
650
+ * @param {EventBusEventCallback<T>} callback
651
+ * @param {any} [that] callback context
415
652
  */
416
- EventBus.prototype.once = function (event, priority, callback, that) {
653
+ EventBus.prototype.once = function (events, priority, callback, that) {
417
654
  var self = this;
418
655
  if (isFunction(priority)) {
419
656
  that = callback;
@@ -426,7 +663,7 @@ EventBus.prototype.once = function (event, priority, callback, that) {
426
663
  function wrappedCallback() {
427
664
  wrappedCallback.__isTomb = true;
428
665
  var result = callback.apply(that, arguments);
429
- self.off(event, wrappedCallback);
666
+ self.off(events, wrappedCallback);
430
667
  return result;
431
668
  }
432
669
 
@@ -434,7 +671,7 @@ EventBus.prototype.once = function (event, priority, callback, that) {
434
671
  // bound callbacks via {@link #off} using the original
435
672
  // callback
436
673
  wrappedCallback[FN_REF] = callback;
437
- this.on(event, priority, wrappedCallback);
674
+ this.on(events, priority, wrappedCallback);
438
675
  };
439
676
 
440
677
  /**
@@ -442,8 +679,8 @@ EventBus.prototype.once = function (event, priority, callback, that) {
442
679
  *
443
680
  * If no callback is given, all listeners for a given event name are being removed.
444
681
  *
445
- * @param {string|Array<string>} events
446
- * @param {Function} [callback]
682
+ * @param {string|string[]} events
683
+ * @param {EventBusEventCallback} [callback]
447
684
  */
448
685
  EventBus.prototype.off = function (events, callback) {
449
686
  events = isArray(events) ? events : [events];
@@ -454,11 +691,11 @@ EventBus.prototype.off = function (events, callback) {
454
691
  };
455
692
 
456
693
  /**
457
- * Create an EventBus event.
694
+ * Create an event recognized be the event bus.
458
695
  *
459
- * @param {Object} data
696
+ * @param {Object} data Event data.
460
697
  *
461
- * @return {Object} event, recognized by the eventBus
698
+ * @return {Event} An event that will be recognized by the event bus.
462
699
  */
463
700
  EventBus.prototype.createEvent = function (data) {
464
701
  var event = new InternalEvent();
@@ -467,10 +704,11 @@ EventBus.prototype.createEvent = function (data) {
467
704
  };
468
705
 
469
706
  /**
470
- * Fires a named event.
707
+ * Fires an event.
471
708
  *
472
709
  * @example
473
710
  *
711
+ * ```javascript
474
712
  * // fire event by name
475
713
  * events.fire('foo');
476
714
  *
@@ -488,13 +726,13 @@ EventBus.prototype.createEvent = function (data) {
488
726
  * });
489
727
  *
490
728
  * events.fire({ type: 'foo' }, 'I am bar!');
729
+ * ```
491
730
  *
492
- * @param {string} [name] the optional event name
493
- * @param {Object} [event] the event object
494
- * @param {...Object} additional arguments to be passed to the callback functions
731
+ * @param {string} [type] event type
732
+ * @param {Object} [data] event or event data
733
+ * @param {...any} [args] additional arguments the callback will be called with.
495
734
  *
496
- * @return {boolean} the events return value, if specified or false if the
497
- * default action was prevented by listeners
735
+ * @return {any} The return value. Will be set to `false` if the default was prevented.
498
736
  */
499
737
  EventBus.prototype.fire = function (type, data) {
500
738
  var event, firstListener, returnValue, args;
@@ -546,6 +784,14 @@ EventBus.prototype.fire = function (type, data) {
546
784
  }
547
785
  return returnValue;
548
786
  };
787
+
788
+ /**
789
+ * Handle an error by firing an event.
790
+ *
791
+ * @param {Error} error The error to be handled.
792
+ *
793
+ * @return {boolean} Whether the error was handled.
794
+ */
549
795
  EventBus.prototype.handleError = function (error) {
550
796
  return this.fire('error', {
551
797
  error: error
@@ -554,6 +800,14 @@ EventBus.prototype.handleError = function (error) {
554
800
  EventBus.prototype._destroy = function () {
555
801
  this._listeners = {};
556
802
  };
803
+
804
+ /**
805
+ * @param {Event} event
806
+ * @param {any[]} args
807
+ * @param {EventBusListener} listener
808
+ *
809
+ * @return {any}
810
+ */
557
811
  EventBus.prototype._invokeListeners = function (event, args, listener) {
558
812
  var returnValue;
559
813
  while (listener) {
@@ -566,6 +820,14 @@ EventBus.prototype._invokeListeners = function (event, args, listener) {
566
820
  }
567
821
  return returnValue;
568
822
  };
823
+
824
+ /**
825
+ * @param {Event} event
826
+ * @param {any[]} args
827
+ * @param {EventBusListener} listener
828
+ *
829
+ * @return {any}
830
+ */
569
831
  EventBus.prototype._invokeListener = function (event, args, listener) {
570
832
  var returnValue;
571
833
  if (listener.callback.__isTomb) {
@@ -594,7 +856,7 @@ EventBus.prototype._invokeListener = function (event, args, listener) {
594
856
  return returnValue;
595
857
  };
596
858
 
597
- /*
859
+ /**
598
860
  * Add new listener with a certain priority to the list
599
861
  * of listeners (for the given event).
600
862
  *
@@ -608,7 +870,7 @@ EventBus.prototype._invokeListener = function (event, args, listener) {
608
870
  * * after: [ 1500, 1500, (new=1300), 1000, 1000, (new=1000) ]
609
871
  *
610
872
  * @param {string} event
611
- * @param {Object} listener { priority, callback }
873
+ * @param {EventBusListener} listener
612
874
  */
613
875
  EventBus.prototype._addListener = function (event, newListener) {
614
876
  var listener = this._getListeners(event),
@@ -639,9 +901,20 @@ EventBus.prototype._addListener = function (event, newListener) {
639
901
  // add new listener to back
640
902
  previousListener.next = newListener;
641
903
  };
904
+
905
+ /**
906
+ * @param {string} name
907
+ *
908
+ * @return {EventBusListener}
909
+ */
642
910
  EventBus.prototype._getListeners = function (name) {
643
911
  return this._listeners[name];
644
912
  };
913
+
914
+ /**
915
+ * @param {string} name
916
+ * @param {EventBusListener} listener
917
+ */
645
918
  EventBus.prototype._setListeners = function (name, listener) {
646
919
  this._listeners[name] = listener;
647
920
  };
@@ -689,9 +962,9 @@ InternalEvent.prototype.init = function (data) {
689
962
  * Invoke function. Be fast...
690
963
  *
691
964
  * @param {Function} fn
692
- * @param {Array<Object>} args
965
+ * @param {any[]} args
693
966
  *
694
- * @return {Any}
967
+ * @return {any}
695
968
  */
696
969
  function invokeFunction(fn, args) {
697
970
  return fn.apply(null, args);
@@ -840,23 +1113,23 @@ class FormFieldRegistry {
840
1113
  }
841
1114
  FormFieldRegistry.$inject = ['eventBus'];
842
1115
 
843
- /**
844
- * @typedef { { id: String, components: Array<String> } } FormRow
845
- * @typedef { { formFieldId: String, rows: Array<FormRow> } } FormRows
1116
+ /**
1117
+ * @typedef { { id: String, components: Array<String> } } FormRow
1118
+ * @typedef { { formFieldId: String, rows: Array<FormRow> } } FormRows
846
1119
  */
847
1120
 
848
- /**
849
- * Maintains the Form layout in a given structure, for example
850
- *
851
- * [
852
- * {
853
- * formFieldId: 'FormField_1',
854
- * rows: [
855
- * { id: 'Row_1', components: [ 'Text_1', 'Textdield_1', ... ] }
856
- * ]
857
- * }
858
- * ]
859
- *
1121
+ /**
1122
+ * Maintains the Form layout in a given structure, for example
1123
+ *
1124
+ * [
1125
+ * {
1126
+ * formFieldId: 'FormField_1',
1127
+ * rows: [
1128
+ * { id: 'Row_1', components: [ 'Text_1', 'Textdield_1', ... ] }
1129
+ * ]
1130
+ * }
1131
+ * ]
1132
+ *
860
1133
  */
861
1134
  class FormLayouter {
862
1135
  constructor(eventBus) {
@@ -866,8 +1139,8 @@ class FormLayouter {
866
1139
  this._eventBus = eventBus;
867
1140
  }
868
1141
 
869
- /**
870
- * @param {FormRow} row
1142
+ /**
1143
+ * @param {FormRow} row
871
1144
  */
872
1145
  addRow(formFieldId, row) {
873
1146
  let rowsPerComponent = this._rows.find(r => r.formFieldId === formFieldId);
@@ -881,18 +1154,18 @@ class FormLayouter {
881
1154
  rowsPerComponent.rows.push(row);
882
1155
  }
883
1156
 
884
- /**
885
- * @param {String} id
886
- * @returns {FormRow}
1157
+ /**
1158
+ * @param {String} id
1159
+ * @returns {FormRow}
887
1160
  */
888
1161
  getRow(id) {
889
1162
  const rows = allRows(this._rows);
890
1163
  return rows.find(r => r.id === id);
891
1164
  }
892
1165
 
893
- /**
894
- * @param {any} formField
895
- * @returns {FormRow}
1166
+ /**
1167
+ * @param {any} formField
1168
+ * @returns {FormRow}
896
1169
  */
897
1170
  getRowForField(formField) {
898
1171
  return allRows(this._rows).find(r => {
@@ -903,9 +1176,9 @@ class FormLayouter {
903
1176
  });
904
1177
  }
905
1178
 
906
- /**
907
- * @param {String} formFieldId
908
- * @returns { Array<FormRow> }
1179
+ /**
1180
+ * @param {String} formFieldId
1181
+ * @returns { Array<FormRow> }
909
1182
  */
910
1183
  getRows(formFieldId) {
911
1184
  const rowsForField = this._rows.find(r => formFieldId === r.formFieldId);
@@ -915,15 +1188,15 @@ class FormLayouter {
915
1188
  return rowsForField.rows;
916
1189
  }
917
1190
 
918
- /**
919
- * @returns {string}
1191
+ /**
1192
+ * @returns {string}
920
1193
  */
921
1194
  nextRowId() {
922
1195
  return this._ids.nextPrefixed('Row_');
923
1196
  }
924
1197
 
925
- /**
926
- * @param {any} formField
1198
+ /**
1199
+ * @param {any} formField
927
1200
  */
928
1201
  calculateLayout(formField) {
929
1202
  const {
@@ -977,9 +1250,9 @@ function groupByRow(components, ids) {
977
1250
  });
978
1251
  }
979
1252
 
980
- /**
981
- * @param {Array<FormRows>} formRows
982
- * @returns {Array<FormRow>}
1253
+ /**
1254
+ * @param {Array<FormRows>} formRows
1255
+ * @returns {Array<FormRow>}
983
1256
  */
984
1257
  function allRows(formRows) {
985
1258
  return flatten(formRows.map(c => c.rows));
@@ -1056,10 +1329,10 @@ function createInjector(bootstrapModules) {
1056
1329
  return injector;
1057
1330
  }
1058
1331
 
1059
- /**
1060
- * @param {string?} prefix
1061
- *
1062
- * @returns Element
1332
+ /**
1333
+ * @param {string?} prefix
1334
+ *
1335
+ * @returns Element
1063
1336
  */
1064
1337
  function createFormContainer(prefix = 'fjs') {
1065
1338
  const container = document.createElement('div');
@@ -1068,6 +1341,7 @@ function createFormContainer(prefix = 'fjs') {
1068
1341
  }
1069
1342
 
1070
1343
  const EXPRESSION_PROPERTIES = ['alt', 'source', 'text'];
1344
+ const TEMPLATE_PROPERTIES = ['text'];
1071
1345
  function findErrors(errors, path) {
1072
1346
  return errors[pathStringify(path)];
1073
1347
  }
@@ -1104,24 +1378,24 @@ function generateIdForType(type) {
1104
1378
  return `${type}${generateIndexForType(type)}`;
1105
1379
  }
1106
1380
 
1107
- /**
1108
- * @template T
1109
- * @param {T} data
1110
- * @param {(this: any, key: string, value: any) => any} [replacer]
1111
- * @return {T}
1381
+ /**
1382
+ * @template T
1383
+ * @param {T} data
1384
+ * @param {(this: any, key: string, value: any) => any} [replacer]
1385
+ * @return {T}
1112
1386
  */
1113
1387
  function clone(data, replacer) {
1114
1388
  return JSON.parse(JSON.stringify(data, replacer));
1115
1389
  }
1116
1390
 
1117
- /**
1118
- * Parse the schema for input variables a form might make use of
1119
- *
1120
- * @param {any} schema
1121
- *
1122
- * @return {string[]}
1391
+ /**
1392
+ * Parse the schema for input variables a form might make use of
1393
+ *
1394
+ * @param {any} schema
1395
+ *
1396
+ * @return {string[]}
1123
1397
  */
1124
- function getSchemaVariables(schema, expressionLanguage = new FeelExpressionLanguage(null)) {
1398
+ function getSchemaVariables(schema, expressionLanguage = new FeelExpressionLanguage(null), templating = new FeelersTemplating()) {
1125
1399
  if (!schema.components) {
1126
1400
  return [];
1127
1401
  }
@@ -1156,6 +1430,13 @@ function getSchemaVariables(schema, expressionLanguage = new FeelExpressionLangu
1156
1430
  variables = [...variables, ...expressionVariables];
1157
1431
  }
1158
1432
  });
1433
+ TEMPLATE_PROPERTIES.forEach(prop => {
1434
+ const property = component[prop];
1435
+ if (property && !expressionLanguage.isExpression(property) && templating.isTemplate(property)) {
1436
+ const templateVariables = templating.getVariableNames(property);
1437
+ variables = [...variables, ...templateVariables];
1438
+ }
1439
+ });
1159
1440
  return variables;
1160
1441
  }, []);
1161
1442
 
@@ -1164,11 +1445,11 @@ function getSchemaVariables(schema, expressionLanguage = new FeelExpressionLangu
1164
1445
  }
1165
1446
 
1166
1447
  class Importer {
1167
- /**
1168
- * @constructor
1169
- * @param { import('../core').FormFieldRegistry } formFieldRegistry
1170
- * @param { import('../render/FormFields').default } formFields
1171
- * @param { import('../core').FormLayouter } formLayouter
1448
+ /**
1449
+ * @constructor
1450
+ * @param { import('../core').FormFieldRegistry } formFieldRegistry
1451
+ * @param { import('../render/FormFields').default } formFields
1452
+ * @param { import('../core').FormLayouter } formLayouter
1172
1453
  */
1173
1454
  constructor(formFieldRegistry, formFields, formLayouter) {
1174
1455
  this._formFieldRegistry = formFieldRegistry;
@@ -1176,15 +1457,15 @@ class Importer {
1176
1457
  this._formLayouter = formLayouter;
1177
1458
  }
1178
1459
 
1179
- /**
1180
- * Import schema adding `id`, `_parent` and `_path`
1181
- * information to each field and adding it to the
1182
- * form field registry.
1183
- *
1184
- * @param {any} schema
1185
- * @param {any} [data]
1186
- *
1187
- * @return { { warnings: Array<any>, schema: any, data: any } }
1460
+ /**
1461
+ * Import schema adding `id`, `_parent` and `_path`
1462
+ * information to each field and adding it to the
1463
+ * form field registry.
1464
+ *
1465
+ * @param {any} schema
1466
+ * @param {any} [data]
1467
+ *
1468
+ * @return { { warnings: Array<any>, schema: any, data: any } }
1188
1469
  */
1189
1470
  importSchema(schema, data = {}) {
1190
1471
  // TODO: Add warnings - https://github.com/bpmn-io/form-js/issues/289
@@ -1205,11 +1486,11 @@ class Importer {
1205
1486
  }
1206
1487
  }
1207
1488
 
1208
- /**
1209
- * @param {any} formField
1210
- * @param {string} [parentId]
1211
- *
1212
- * @return {any} importedField
1489
+ /**
1490
+ * @param {any} formField
1491
+ * @param {string} [parentId]
1492
+ *
1493
+ * @return {any} importedField
1213
1494
  */
1214
1495
  importFormField(formField, parentId) {
1215
1496
  const {
@@ -1260,10 +1541,10 @@ class Importer {
1260
1541
  });
1261
1542
  }
1262
1543
 
1263
- /**
1264
- * @param {Object} data
1265
- *
1266
- * @return {Object} initializedData
1544
+ /**
1545
+ * @param {Object} data
1546
+ *
1547
+ * @return {Object} initializedData
1267
1548
  */
1268
1549
  initializeFieldValues(data) {
1269
1550
  return this._formFieldRegistry.getAll().reduce((initializedData, formField) => {
@@ -1278,16 +1559,18 @@ class Importer {
1278
1559
  // if unavailable - get empty value from form field
1279
1560
 
1280
1561
  if (_path) {
1281
- const fieldImplementation = this._formFields.get(type);
1562
+ const {
1563
+ config: fieldConfig
1564
+ } = this._formFields.get(type);
1282
1565
  let valueData = get(data, _path);
1283
- if (!isUndefined(valueData) && fieldImplementation.sanitizeValue) {
1284
- valueData = fieldImplementation.sanitizeValue({
1566
+ if (!isUndefined(valueData) && fieldConfig.sanitizeValue) {
1567
+ valueData = fieldConfig.sanitizeValue({
1285
1568
  formField,
1286
1569
  data,
1287
1570
  value: valueData
1288
1571
  });
1289
1572
  }
1290
- const initializedFieldValue = !isUndefined(valueData) ? valueData : !isUndefined(defaultValue) ? defaultValue : fieldImplementation.emptyValue;
1573
+ const initializedFieldValue = !isUndefined(valueData) ? valueData : !isUndefined(defaultValue) ? defaultValue : fieldConfig.emptyValue;
1291
1574
  initializedData = {
1292
1575
  ...initializedData,
1293
1576
  [_path[0]]: initializedFieldValue
@@ -1352,14 +1635,16 @@ function Button(props) {
1352
1635
  })
1353
1636
  });
1354
1637
  }
1355
- Button.create = (options = {}) => ({
1356
- action: 'submit',
1357
- ...options
1358
- });
1359
- Button.type = type$b;
1360
- Button.label = 'Button';
1361
- Button.keyed = true;
1362
- Button.group = 'action';
1638
+ Button.config = {
1639
+ type: type$b,
1640
+ keyed: true,
1641
+ label: 'Button',
1642
+ group: 'action',
1643
+ create: (options = {}) => ({
1644
+ action: 'submit',
1645
+ ...options
1646
+ })
1647
+ };
1363
1648
 
1364
1649
  const FormRenderContext = createContext({
1365
1650
  Empty: props => {
@@ -1395,11 +1680,11 @@ const FormRenderContext = createContext({
1395
1680
  });
1396
1681
  var FormRenderContext$1 = FormRenderContext;
1397
1682
 
1398
- /**
1399
- * @param {string} type
1400
- * @param {boolean} [strict]
1401
- *
1402
- * @returns {any}
1683
+ /**
1684
+ * @param {string} type
1685
+ * @param {boolean} [strict]
1686
+ *
1687
+ * @returns {any}
1403
1688
  */
1404
1689
  function getService(type, strict) {}
1405
1690
  const FormContext = createContext({
@@ -1423,13 +1708,16 @@ function Description(props) {
1423
1708
 
1424
1709
  function Errors(props) {
1425
1710
  const {
1426
- errors
1711
+ errors,
1712
+ id
1427
1713
  } = props;
1428
1714
  if (!errors.length) {
1429
1715
  return null;
1430
1716
  }
1431
1717
  return jsx("div", {
1432
1718
  class: "fjs-form-field-error",
1719
+ "aria-live": "polite",
1720
+ id: id,
1433
1721
  children: jsx("ul", {
1434
1722
  children: errors.map(error => {
1435
1723
  return jsx("li", {
@@ -1487,6 +1775,7 @@ function Checkbox(props) {
1487
1775
  const {
1488
1776
  formId
1489
1777
  } = useContext(FormContext$1);
1778
+ const errorMessageId = errors.length === 0 ? undefined : `${prefixId(id, formId)}-error-message`;
1490
1779
  return jsxs("div", {
1491
1780
  class: classNames(formFieldClasses(type$a, {
1492
1781
  errors,
@@ -1504,26 +1793,30 @@ function Checkbox(props) {
1504
1793
  disabled: disabled,
1505
1794
  id: prefixId(id, formId),
1506
1795
  type: "checkbox",
1507
- onChange: onChange
1796
+ onChange: onChange,
1797
+ "aria-describedby": errorMessageId
1508
1798
  })
1509
1799
  }), jsx(Description, {
1510
1800
  description: description
1511
1801
  }), jsx(Errors, {
1512
- errors: errors
1802
+ errors: errors,
1803
+ id: errorMessageId
1513
1804
  })]
1514
1805
  });
1515
1806
  }
1516
- Checkbox.create = (options = {}) => ({
1517
- ...options
1518
- });
1519
- Checkbox.type = type$a;
1520
- Checkbox.label = 'Checkbox';
1521
- Checkbox.keyed = true;
1522
- Checkbox.emptyValue = false;
1523
- Checkbox.sanitizeValue = ({
1524
- value
1525
- }) => value === true;
1526
- Checkbox.group = 'selection';
1807
+ Checkbox.config = {
1808
+ type: type$a,
1809
+ keyed: true,
1810
+ label: 'Checkbox',
1811
+ group: 'selection',
1812
+ emptyValue: false,
1813
+ sanitizeValue: ({
1814
+ value
1815
+ }) => value === true,
1816
+ create: (options = {}) => ({
1817
+ ...options
1818
+ })
1819
+ };
1527
1820
 
1528
1821
  // parses the options data from the provided form field and form data
1529
1822
  function getValuesData(formField, formData) {
@@ -1578,8 +1871,8 @@ function useService(type, strict) {
1578
1871
  return getService(type, strict);
1579
1872
  }
1580
1873
 
1581
- /**
1582
- * @enum { String }
1874
+ /**
1875
+ * @enum { String }
1583
1876
  */
1584
1877
  const LOAD_STATES = {
1585
1878
  LOADING: 'loading',
@@ -1587,17 +1880,17 @@ const LOAD_STATES = {
1587
1880
  ERROR: 'error'
1588
1881
  };
1589
1882
 
1590
- /**
1591
- * @typedef {Object} ValuesGetter
1592
- * @property {Object[]} values - The values data
1593
- * @property {(LOAD_STATES)} state - The values data's loading state, to use for conditional rendering
1883
+ /**
1884
+ * @typedef {Object} ValuesGetter
1885
+ * @property {Object[]} values - The values data
1886
+ * @property {(LOAD_STATES)} state - The values data's loading state, to use for conditional rendering
1594
1887
  */
1595
1888
 
1596
- /**
1597
- * A hook to load values for single and multiselect components.
1598
- *
1599
- * @param {Object} field - The form field to handle values for
1600
- * @return {ValuesGetter} valuesGetter - A values getter object providing loading state and values
1889
+ /**
1890
+ * A hook to load values for single and multiselect components.
1891
+ *
1892
+ * @param {Object} field - The form field to handle values for
1893
+ * @return {ValuesGetter} valuesGetter - A values getter object providing loading state and values
1601
1894
  */
1602
1895
  function useValuesAsync (field) {
1603
1896
  const {
@@ -1889,6 +2182,7 @@ function Checklist(props) {
1889
2182
  const {
1890
2183
  formId
1891
2184
  } = useContext(FormContext$1);
2185
+ const errorMessageId = errors.length === 0 ? undefined : `${prefixId(id, formId)}-error-message`;
1892
2186
  return jsxs("div", {
1893
2187
  class: classNames(formFieldClasses(type$9, {
1894
2188
  errors,
@@ -1911,42 +2205,46 @@ function Checklist(props) {
1911
2205
  disabled: disabled,
1912
2206
  id: prefixId(`${id}-${index}`, formId),
1913
2207
  type: "checkbox",
1914
- onClick: () => toggleCheckbox(v.value)
2208
+ onClick: () => toggleCheckbox(v.value),
2209
+ "aria-describedby": errorMessageId
1915
2210
  })
1916
2211
  }, `${id}-${index}`);
1917
2212
  }), jsx(Description, {
1918
2213
  description: description
1919
2214
  }), jsx(Errors, {
1920
- errors: errors
2215
+ errors: errors,
2216
+ id: errorMessageId
1921
2217
  })]
1922
2218
  });
1923
2219
  }
1924
- Checklist.create = (options = {}) => {
1925
- const defaults = {};
1926
-
1927
- // provide default values if valuesKey isn't set
1928
- if (!options.valuesKey) {
1929
- defaults.values = [{
1930
- label: 'Value',
1931
- value: 'value'
1932
- }];
2220
+ Checklist.config = {
2221
+ type: type$9,
2222
+ keyed: true,
2223
+ label: 'Checklist',
2224
+ group: 'selection',
2225
+ emptyValue: [],
2226
+ sanitizeValue: sanitizeMultiSelectValue,
2227
+ create: (options = {}) => {
2228
+ const defaults = {};
2229
+
2230
+ // provide default values if valuesKey isn't set
2231
+ if (!options.valuesKey) {
2232
+ defaults.values = [{
2233
+ label: 'Value',
2234
+ value: 'value'
2235
+ }];
2236
+ }
2237
+ return {
2238
+ ...defaults,
2239
+ ...options
2240
+ };
1933
2241
  }
1934
- return {
1935
- ...defaults,
1936
- ...options
1937
- };
1938
2242
  };
1939
- Checklist.type = type$9;
1940
- Checklist.label = 'Checklist';
1941
- Checklist.keyed = true;
1942
- Checklist.emptyValue = [];
1943
- Checklist.sanitizeValue = sanitizeMultiSelectValue;
1944
- Checklist.group = 'selection';
1945
2243
 
1946
- /**
1947
- * Returns the conditionally filtered data of a form reactively.
1948
- * Memoised to minimize re-renders
1949
- *
2244
+ /**
2245
+ * Returns the conditionally filtered data of a form reactively.
2246
+ * Memoised to minimize re-renders
2247
+ *
1950
2248
  */
1951
2249
  function useFilteredFormData() {
1952
2250
  const {
@@ -1963,12 +2261,12 @@ function useFilteredFormData() {
1963
2261
  }, [conditionChecker, data, initialData]);
1964
2262
  }
1965
2263
 
1966
- /**
1967
- * Evaluate if condition is met reactively based on the conditionChecker and form data.
1968
- *
1969
- * @param {string | undefined} condition
1970
- *
1971
- * @returns {boolean} true if condition is met or no condition or condition checker exists
2264
+ /**
2265
+ * Evaluate if condition is met reactively based on the conditionChecker and form data.
2266
+ *
2267
+ * @param {string | undefined} condition
2268
+ *
2269
+ * @returns {boolean} true if condition is met or no condition or condition checker exists
1972
2270
  */
1973
2271
  function useCondition(condition) {
1974
2272
  const conditionChecker = useService('conditionChecker', false);
@@ -1978,13 +2276,13 @@ function useCondition(condition) {
1978
2276
  }, [conditionChecker, condition, filteredData]);
1979
2277
  }
1980
2278
 
1981
- /**
1982
- * Evaluate a string reactively based on the expressionLanguage and form data.
1983
- * If the string is not an expression, it is returned as is.
1984
- * Memoised to minimize re-renders.
1985
- *
1986
- * @param {string} value
1987
- *
2279
+ /**
2280
+ * Evaluate a string reactively based on the expressionLanguage and form data.
2281
+ * If the string is not an expression, it is returned as is.
2282
+ * Memoised to minimize re-renders.
2283
+ *
2284
+ * @param {string} value
2285
+ *
1988
2286
  */
1989
2287
  function useExpressionEvaluation(value) {
1990
2288
  const formData = useFilteredFormData();
@@ -2013,16 +2311,16 @@ function useKeyDownAction(targetKey, action, listenerElement = window) {
2013
2311
  });
2014
2312
  }
2015
2313
 
2016
- /**
2017
- * Template a string reactively based on form data. If the string is not a template, it is returned as is.
2018
- * Memoised to minimize re-renders
2019
- *
2020
- * @param {string} value
2021
- * @param {Object} options
2022
- * @param {boolean} [options.debug = false]
2023
- * @param {boolean} [options.strict = false]
2024
- * @param {Function} [options.buildDebugString]
2025
- *
2314
+ /**
2315
+ * Template a string reactively based on form data. If the string is not a template, it is returned as is.
2316
+ * Memoised to minimize re-renders
2317
+ *
2318
+ * @param {string} value
2319
+ * @param {Object} options
2320
+ * @param {boolean} [options.debug = false]
2321
+ * @param {boolean} [options.strict = false]
2322
+ * @param {Function} [options.buildDebugString]
2323
+ *
2026
2324
  */
2027
2325
  function useTemplateEvaluation(value, options) {
2028
2326
  const filteredData = useFilteredFormData();
@@ -2041,9 +2339,6 @@ function FormField(props) {
2041
2339
  field,
2042
2340
  onChange
2043
2341
  } = props;
2044
- const {
2045
- _path
2046
- } = field;
2047
2342
  const formFields = useService('formFields'),
2048
2343
  form = useService('form');
2049
2344
  const {
@@ -2060,8 +2355,8 @@ function FormField(props) {
2060
2355
  if (!FormFieldComponent) {
2061
2356
  throw new Error(`cannot render field <${field.type}>`);
2062
2357
  }
2063
- const value = get(data, _path);
2064
- const fieldErrors = findErrors(errors, _path);
2358
+ const value = get(data, field._path);
2359
+ const fieldErrors = findErrors(errors, field._path);
2065
2360
  const disabled = properties.readOnly || field.disabled || false;
2066
2361
  const hidden = useCondition(field.conditional && field.conditional.hide || null);
2067
2362
  if (hidden) {
@@ -2128,14 +2423,16 @@ function Default(props) {
2128
2423
  }), components.length ? null : jsx(Empty, {})]
2129
2424
  });
2130
2425
  }
2131
- Default.create = (options = {}) => ({
2132
- components: [],
2133
- ...options
2134
- });
2135
- Default.type = 'default';
2136
- Default.keyed = false;
2137
- Default.label = null;
2138
- Default.group = null;
2426
+ Default.config = {
2427
+ type: 'default',
2428
+ keyed: false,
2429
+ label: null,
2430
+ group: null,
2431
+ create: (options = {}) => ({
2432
+ components: [],
2433
+ ...options
2434
+ })
2435
+ };
2139
2436
 
2140
2437
  function _extends$j() { _extends$j = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$j.apply(this, arguments); }
2141
2438
  var CalendarIcon = (({
@@ -2311,16 +2608,17 @@ function Datepicker(props) {
2311
2608
  ref: dateInputRef,
2312
2609
  type: "text",
2313
2610
  id: fullId,
2314
- class: 'fjs-input',
2611
+ class: "fjs-input",
2315
2612
  disabled: disabled,
2316
2613
  placeholder: "mm/dd/yyyy",
2317
2614
  autoComplete: "off",
2318
2615
  onFocus: onInputFocus,
2319
2616
  onKeyDown: onInputKeyDown,
2320
- onMouseDown: e => !flatpickrInstance.isOpen && flatpickrInstance.open(),
2617
+ onMouseDown: () => !flatpickrInstance.isOpen && flatpickrInstance.open(),
2321
2618
  onBlur: onInputBlur,
2322
- onInput: e => setIsInputDirty(true),
2323
- "data-input": true
2619
+ onInput: () => setIsInputDirty(true),
2620
+ "data-input": true,
2621
+ "aria-describedby": props['aria-describedby']
2324
2622
  })
2325
2623
  })
2326
2624
  })]
@@ -2577,7 +2875,8 @@ function Timepicker(props) {
2577
2875
  },
2578
2876
  onBlur: onInputBlur,
2579
2877
  onKeyDown: onInputKeyDown,
2580
- "data-input": true
2878
+ "data-input": true,
2879
+ "aria-describedby": props['aria-describedby']
2581
2880
  }), dropdownIsOpen && jsx(DropdownList, {
2582
2881
  values: timeOptions,
2583
2882
  height: 150,
@@ -2713,6 +3012,7 @@ function Datetime(props) {
2713
3012
  time
2714
3013
  });
2715
3014
  }, []);
3015
+ const errorMessageId = allErrors.length === 0 ? undefined : `${prefixId(id, formId)}-error-message`;
2716
3016
  const datePickerProps = {
2717
3017
  id,
2718
3018
  label: dateLabel,
@@ -2722,7 +3022,8 @@ function Datetime(props) {
2722
3022
  disabled,
2723
3023
  disallowPassedDates,
2724
3024
  date: dateTime.date,
2725
- setDate
3025
+ setDate,
3026
+ 'aria-describedby': errorMessageId
2726
3027
  };
2727
3028
  const timePickerProps = {
2728
3029
  id,
@@ -2734,7 +3035,8 @@ function Datetime(props) {
2734
3035
  use24h,
2735
3036
  timeInterval,
2736
3037
  time: dateTime.time,
2737
- setTime
3038
+ setTime,
3039
+ 'aria-describedby': errorMessageId
2738
3040
  };
2739
3041
  return jsxs("div", {
2740
3042
  class: formFieldClasses(type$8, {
@@ -2753,30 +3055,33 @@ function Datetime(props) {
2753
3055
  }), jsx(Description, {
2754
3056
  description: description
2755
3057
  }), jsx(Errors, {
2756
- errors: allErrors
3058
+ errors: allErrors,
3059
+ id: errorMessageId
2757
3060
  })]
2758
3061
  });
2759
3062
  }
2760
- Datetime.create = (options = {}) => {
2761
- const defaults = {};
2762
- set(defaults, DATETIME_SUBTYPE_PATH, DATETIME_SUBTYPES.DATE);
2763
- set(defaults, DATE_LABEL_PATH, 'Date');
2764
- return {
2765
- ...defaults,
2766
- ...options
2767
- };
3063
+ Datetime.config = {
3064
+ type: type$8,
3065
+ keyed: true,
3066
+ label: 'Date time',
3067
+ group: 'basic-input',
3068
+ emptyValue: null,
3069
+ sanitizeValue: sanitizeDateTimePickerValue,
3070
+ create: (options = {}) => {
3071
+ const defaults = {};
3072
+ set(defaults, DATETIME_SUBTYPE_PATH, DATETIME_SUBTYPES.DATE);
3073
+ set(defaults, DATE_LABEL_PATH, 'Date');
3074
+ return {
3075
+ ...defaults,
3076
+ ...options
3077
+ };
3078
+ }
2768
3079
  };
2769
- Datetime.type = type$8;
2770
- Datetime.keyed = true;
2771
- Datetime.emptyValue = null;
2772
- Datetime.sanitizeValue = sanitizeDateTimePickerValue;
2773
- Datetime.label = 'Date time';
2774
- Datetime.group = 'basic-input';
2775
3080
 
2776
- /**
2777
- * This file must not be changed or exchanged.
2778
- *
2779
- * @see http://bpmn.io/license for more information.
3081
+ /**
3082
+ * This file must not be changed or exchanged.
3083
+ *
3084
+ * @see http://bpmn.io/license for more information.
2780
3085
  */
2781
3086
  function Logo() {
2782
3087
  return jsxs("svg", {
@@ -2815,7 +3120,7 @@ function Lightbox(props) {
2815
3120
  href: "https://bpmn.io",
2816
3121
  target: "_blank",
2817
3122
  rel: "noopener",
2818
- style: "margin: 15px 20px 15px 10px; align-self: center; color: #404040",
3123
+ style: "margin: 15px 20px 15px 10px; align-self: center; color: var(--cds-icon-primary, #404040)",
2819
3124
  children: jsx(Logo, {})
2820
3125
  }), jsxs("span", {
2821
3126
  children: ["Web-based tooling for BPMN, DMN, and forms powered by ", jsx("a", {
@@ -2838,7 +3143,7 @@ function Link(props) {
2838
3143
  rel: "noopener",
2839
3144
  class: "fjs-powered-by-link",
2840
3145
  title: "Powered by bpmn.io",
2841
- style: "color: #404040",
3146
+ style: "color: var(--cds-text-primary, #404040)",
2842
3147
  onClick: props.onClick,
2843
3148
  children: jsx(Logo, {})
2844
3149
  })
@@ -2866,8 +3171,12 @@ const noop = () => {};
2866
3171
  function FormComponent(props) {
2867
3172
  const form = useService('form');
2868
3173
  const {
2869
- schema
3174
+ schema,
3175
+ properties
2870
3176
  } = form._getState();
3177
+ const {
3178
+ ariaLabel
3179
+ } = properties;
2871
3180
  const {
2872
3181
  onSubmit = noop,
2873
3182
  onReset = noop,
@@ -2885,6 +3194,7 @@ function FormComponent(props) {
2885
3194
  class: "fjs-form",
2886
3195
  onSubmit: handleSubmit,
2887
3196
  onReset: handleReset,
3197
+ "aria-label": ariaLabel,
2888
3198
  noValidate: true,
2889
3199
  children: [jsx(FormField, {
2890
3200
  field: schema,
@@ -2895,7 +3205,7 @@ function FormComponent(props) {
2895
3205
 
2896
3206
  const NODE_TYPE_TEXT = 3,
2897
3207
  NODE_TYPE_ELEMENT = 1;
2898
- const ALLOWED_NODES = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'span', 'em', 'a', 'p', 'div', 'ul', 'ol', 'li', 'hr', 'blockquote', 'img', 'pre', 'code', 'br', 'strong'];
3208
+ const ALLOWED_NODES = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'span', 'em', 'a', 'p', 'div', 'ul', 'ol', 'li', 'hr', 'blockquote', 'img', 'pre', 'code', 'br', 'strong', 'table', 'thead', 'tbody', 'tr', 'th', 'td'];
2899
3209
  const ALLOWED_ATTRIBUTES = ['align', 'alt', 'class', 'href', 'id', 'name', 'rel', 'target', 'src'];
2900
3210
  const ALLOWED_URI_PATTERN = /^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i; // eslint-disable-line no-useless-escape
2901
3211
  const ALLOWED_IMAGE_SRC_PATTERN = /^(https?|data):.*/i; // eslint-disable-line no-useless-escape
@@ -2903,11 +3213,11 @@ const ATTR_WHITESPACE_PATTERN = /[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u
2903
3213
 
2904
3214
  const FORM_ELEMENT = document.createElement('form');
2905
3215
 
2906
- /**
2907
- * Sanitize a HTML string and return the cleaned, safe version.
2908
- *
2909
- * @param {string} html
2910
- * @return {string}
3216
+ /**
3217
+ * Sanitize a HTML string and return the cleaned, safe version.
3218
+ *
3219
+ * @param {string} html
3220
+ * @return {string}
2911
3221
  */
2912
3222
 
2913
3223
  // see https://github.com/developit/snarkdown/issues/70
@@ -2925,29 +3235,29 @@ function sanitizeHTML(html) {
2925
3235
  }
2926
3236
  }
2927
3237
 
2928
- /**
2929
- * Sanitizes an image source to ensure we only allow for data URI and links
2930
- * that start with http(s).
2931
- *
2932
- * Note: Most browsers anyway do not support script execution in <img> elements.
2933
- *
2934
- * @param {string} src
2935
- * @returns {string}
3238
+ /**
3239
+ * Sanitizes an image source to ensure we only allow for data URI and links
3240
+ * that start with http(s).
3241
+ *
3242
+ * Note: Most browsers anyway do not support script execution in <img> elements.
3243
+ *
3244
+ * @param {string} src
3245
+ * @returns {string}
2936
3246
  */
2937
3247
  function sanitizeImageSource(src) {
2938
3248
  const valid = ALLOWED_IMAGE_SRC_PATTERN.test(src);
2939
3249
  return valid ? src : '';
2940
3250
  }
2941
3251
 
2942
- /**
2943
- * Recursively sanitize a HTML node, potentially
2944
- * removing it, its children or attributes.
2945
- *
2946
- * Inspired by https://github.com/developit/snarkdown/issues/70
2947
- * and https://github.com/cure53/DOMPurify. Simplified
2948
- * for our use-case.
2949
- *
2950
- * @param {Element} node
3252
+ /**
3253
+ * Recursively sanitize a HTML node, potentially
3254
+ * removing it, its children or attributes.
3255
+ *
3256
+ * Inspired by https://github.com/developit/snarkdown/issues/70
3257
+ * and https://github.com/cure53/DOMPurify. Simplified
3258
+ * for our use-case.
3259
+ *
3260
+ * @param {Element} node
2951
3261
  */
2952
3262
  function sanitizeNode(node) {
2953
3263
  // allow text nodes
@@ -2991,13 +3301,13 @@ function sanitizeNode(node) {
2991
3301
  }
2992
3302
  }
2993
3303
 
2994
- /**
2995
- * Validates attributes for validity.
2996
- *
2997
- * @param {string} lcTag
2998
- * @param {string} lcName
2999
- * @param {string} value
3000
- * @return {boolean}
3304
+ /**
3305
+ * Validates attributes for validity.
3306
+ *
3307
+ * @param {string} lcTag
3308
+ * @param {string} lcName
3309
+ * @param {string} value
3310
+ * @return {boolean}
3001
3311
  */
3002
3312
  function isValidAttribute(lcTag, lcName, value) {
3003
3313
  // disallow most attributes based on whitelist
@@ -3084,13 +3394,15 @@ function Image(props) {
3084
3394
  })
3085
3395
  });
3086
3396
  }
3087
- Image.create = (options = {}) => ({
3088
- ...options
3089
- });
3090
- Image.type = type$7;
3091
- Image.keyed = false;
3092
- Image.label = 'Image view';
3093
- Image.group = 'presentation';
3397
+ Image.config = {
3398
+ type: type$7,
3399
+ keyed: false,
3400
+ label: 'Image view',
3401
+ group: 'presentation',
3402
+ create: (options = {}) => ({
3403
+ ...options
3404
+ })
3405
+ };
3094
3406
 
3095
3407
  function _extends$g() { _extends$g = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$g.apply(this, arguments); }
3096
3408
  var AngelDownIcon = (({
@@ -3157,10 +3469,10 @@ function Numberfield(props) {
3157
3469
 
3158
3470
  // checks whether the value currently in the form data is practically different from the one in the input field cache
3159
3471
  // this allows us to guarantee the field always displays valid form data, but without auto-simplifying values like 1.000 to 1
3160
- const cacheValueMatchesState = useMemo(() => Numberfield.sanitizeValue({
3472
+ const cacheValueMatchesState = useMemo(() => Numberfield.config.sanitizeValue({
3161
3473
  value,
3162
3474
  formField: field
3163
- }) === Numberfield.sanitizeValue({
3475
+ }) === Numberfield.config.sanitizeValue({
3164
3476
  value: stringValueCache,
3165
3477
  formField: field
3166
3478
  }), [stringValueCache, value, field]);
@@ -3254,6 +3566,7 @@ function Numberfield(props) {
3254
3566
  const {
3255
3567
  formId
3256
3568
  } = useContext(FormContext$1);
3569
+ const errorMessageId = errors.length === 0 ? undefined : `${prefixId(id, formId)}-error-message`;
3257
3570
  return jsxs("div", {
3258
3571
  class: formFieldClasses(type$6, {
3259
3572
  errors,
@@ -3287,7 +3600,8 @@ function Numberfield(props) {
3287
3600
  type: "text",
3288
3601
  autoComplete: "off",
3289
3602
  step: arrowIncrementValue,
3290
- value: displayValue
3603
+ value: displayValue,
3604
+ "aria-describedby": errorMessageId
3291
3605
  }), jsxs("div", {
3292
3606
  class: classNames('fjs-number-arrow-container', {
3293
3607
  'fjs-disabled': disabled
@@ -3314,31 +3628,34 @@ function Numberfield(props) {
3314
3628
  }), jsx(Description, {
3315
3629
  description: description
3316
3630
  }), jsx(Errors, {
3317
- errors: errors
3631
+ errors: errors,
3632
+ id: errorMessageId
3318
3633
  })]
3319
3634
  });
3320
3635
  }
3321
- Numberfield.create = (options = {}) => ({
3322
- ...options
3323
- });
3324
- Numberfield.sanitizeValue = ({
3325
- value,
3326
- formField
3327
- }) => {
3328
- // null state is allowed
3329
- if (isNullEquivalentValue(value)) return null;
3330
-
3331
- // if data cannot be parsed as a valid number, go into invalid NaN state
3332
- if (!isValidNumber(value)) return 'NaN';
3333
-
3334
- // otherwise parse to formatting type
3335
- return formField.serializeToString ? value.toString() : Number(value);
3636
+ Numberfield.config = {
3637
+ type: type$6,
3638
+ keyed: true,
3639
+ label: 'Number',
3640
+ group: 'basic-input',
3641
+ emptyValue: null,
3642
+ sanitizeValue: ({
3643
+ value,
3644
+ formField
3645
+ }) => {
3646
+ // null state is allowed
3647
+ if (isNullEquivalentValue(value)) return null;
3648
+
3649
+ // if data cannot be parsed as a valid number, go into invalid NaN state
3650
+ if (!isValidNumber(value)) return 'NaN';
3651
+
3652
+ // otherwise parse to formatting type
3653
+ return formField.serializeToString ? value.toString() : Number(value);
3654
+ },
3655
+ create: (options = {}) => ({
3656
+ ...options
3657
+ })
3336
3658
  };
3337
- Numberfield.type = type$6;
3338
- Numberfield.keyed = true;
3339
- Numberfield.label = 'Number';
3340
- Numberfield.emptyValue = null;
3341
- Numberfield.group = 'basic-input';
3342
3659
 
3343
3660
  const type$5 = 'radio';
3344
3661
  function Radio(props) {
@@ -3370,6 +3687,7 @@ function Radio(props) {
3370
3687
  const {
3371
3688
  formId
3372
3689
  } = useContext(FormContext$1);
3690
+ const errorMessageId = errors.length === 0 ? undefined : `${prefixId(id, formId)}-error-message`;
3373
3691
  return jsxs("div", {
3374
3692
  class: formFieldClasses(type$5, {
3375
3693
  errors,
@@ -3392,37 +3710,41 @@ function Radio(props) {
3392
3710
  disabled: disabled,
3393
3711
  id: prefixId(`${id}-${index}`, formId),
3394
3712
  type: "radio",
3395
- onClick: () => onChange(option.value)
3713
+ onClick: () => onChange(option.value),
3714
+ "aria-describedby": errorMessageId
3396
3715
  })
3397
3716
  }, `${id}-${index}`);
3398
3717
  }), jsx(Description, {
3399
3718
  description: description
3400
3719
  }), jsx(Errors, {
3401
- errors: errors
3720
+ errors: errors,
3721
+ id: errorMessageId
3402
3722
  })]
3403
3723
  });
3404
3724
  }
3405
- Radio.create = function (options = {}) {
3406
- const defaults = {};
3407
-
3408
- // provide default values if valuesKey isn't set
3409
- if (!options.valuesKey) {
3410
- defaults.values = [{
3411
- label: 'Value',
3412
- value: 'value'
3413
- }];
3725
+ Radio.config = {
3726
+ type: type$5,
3727
+ keyed: true,
3728
+ label: 'Radio',
3729
+ group: 'selection',
3730
+ emptyValue: null,
3731
+ sanitizeValue: sanitizeSingleSelectValue,
3732
+ create: (options = {}) => {
3733
+ const defaults = {};
3734
+
3735
+ // provide default values if valuesKey isn't set
3736
+ if (!options.valuesKey) {
3737
+ defaults.values = [{
3738
+ label: 'Value',
3739
+ value: 'value'
3740
+ }];
3741
+ }
3742
+ return {
3743
+ ...defaults,
3744
+ ...options
3745
+ };
3414
3746
  }
3415
- return {
3416
- ...defaults,
3417
- ...options
3418
- };
3419
3747
  };
3420
- Radio.type = type$5;
3421
- Radio.label = 'Radio';
3422
- Radio.keyed = true;
3423
- Radio.emptyValue = null;
3424
- Radio.sanitizeValue = sanitizeSingleSelectValue;
3425
- Radio.group = 'selection';
3426
3748
 
3427
3749
  function _extends$e() { _extends$e = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$e.apply(this, arguments); }
3428
3750
  var XMarkIcon = (({
@@ -3562,7 +3884,8 @@ function SearchableSelect(props) {
3562
3884
  onBlur: () => {
3563
3885
  setIsDropdownExpanded(false);
3564
3886
  setFilter(valueLabel);
3565
- }
3887
+ },
3888
+ "aria-describedby": props['aria-describedby']
3566
3889
  }), displayState.displayCross && jsxs("span", {
3567
3890
  class: "fjs-select-cross",
3568
3891
  onMouseDown: e => {
@@ -3648,14 +3971,20 @@ function SimpleSelect(props) {
3648
3971
  }),
3649
3972
  onFocus: () => setIsDropdownExpanded(true),
3650
3973
  onBlur: () => setIsDropdownExpanded(false),
3651
- onMouseDown: e => onMouseDown(e),
3652
- tabIndex: disabled ? undefined : 0,
3974
+ onMouseDown: onMouseDown,
3653
3975
  children: [jsx("div", {
3654
3976
  class: classNames('fjs-select-display', {
3655
3977
  'fjs-select-placeholder': !value
3656
3978
  }),
3657
3979
  id: prefixId(`${id}-display`, formId),
3658
3980
  children: valueLabel || 'Select'
3981
+ }), !disabled && jsx("input", {
3982
+ id: prefixId(`${id}-search`, formId),
3983
+ class: "fjs-select-hidden-input",
3984
+ value: valueLabel,
3985
+ onFocus: () => setIsDropdownExpanded(true),
3986
+ onBlur: () => setIsDropdownExpanded(false),
3987
+ "aria-describedby": props['aria-describedby']
3659
3988
  }), displayState.displayCross && jsx("span", {
3660
3989
  class: "fjs-select-cross",
3661
3990
  onMouseDown: e => {
@@ -3705,21 +4034,29 @@ function Select(props) {
3705
4034
  const {
3706
4035
  formId
3707
4036
  } = useContext(FormContext$1);
4037
+ const errorMessageId = errors.length === 0 ? undefined : `${prefixId(id, formId)}-error-message`;
3708
4038
  const selectProps = useMemo(() => ({
3709
4039
  id,
3710
4040
  disabled,
3711
4041
  errors,
3712
4042
  field,
3713
4043
  value,
3714
- onChange
3715
- }), [disabled, errors, field, id, value, onChange]);
4044
+ onChange,
4045
+ 'aria-describedby': errorMessageId
4046
+ }), [disabled, errors, field, id, value, onChange, errorMessageId]);
3716
4047
  return jsxs("div", {
3717
4048
  class: formFieldClasses(type$4, {
3718
4049
  errors,
3719
4050
  disabled
3720
4051
  }),
4052
+ onKeyDown: event => {
4053
+ if (event.key === 'Enter') {
4054
+ event.preventDefault();
4055
+ event.stopPropagation();
4056
+ }
4057
+ },
3721
4058
  children: [jsx(Label, {
3722
- id: prefixId(id, formId),
4059
+ id: prefixId(`${id}-search`, formId),
3723
4060
  label: label,
3724
4061
  required: required
3725
4062
  }), searchable ? jsx(SearchableSelect, {
@@ -3729,31 +4066,34 @@ function Select(props) {
3729
4066
  }), jsx(Description, {
3730
4067
  description: description
3731
4068
  }), jsx(Errors, {
3732
- errors: errors
4069
+ errors: errors,
4070
+ id: errorMessageId
3733
4071
  })]
3734
4072
  });
3735
4073
  }
3736
- Select.create = (options = {}) => {
3737
- const defaults = {};
3738
-
3739
- // provide default values if valuesKey isn't set
3740
- if (!options.valuesKey) {
3741
- defaults.values = [{
3742
- label: 'Value',
3743
- value: 'value'
3744
- }];
4074
+ Select.config = {
4075
+ type: type$4,
4076
+ keyed: true,
4077
+ label: 'Select',
4078
+ group: 'selection',
4079
+ emptyValue: null,
4080
+ sanitizeValue: sanitizeSingleSelectValue,
4081
+ create: (options = {}) => {
4082
+ const defaults = {};
4083
+
4084
+ // provide default values if valuesKey isn't set
4085
+ if (!options.valuesKey) {
4086
+ defaults.values = [{
4087
+ label: 'Value',
4088
+ value: 'value'
4089
+ }];
4090
+ }
4091
+ return {
4092
+ ...defaults,
4093
+ ...options
4094
+ };
3745
4095
  }
3746
- return {
3747
- ...defaults,
3748
- ...options
3749
- };
3750
4096
  };
3751
- Select.type = type$4;
3752
- Select.label = 'Select';
3753
- Select.keyed = true;
3754
- Select.emptyValue = null;
3755
- Select.sanitizeValue = sanitizeSingleSelectValue;
3756
- Select.group = 'selection';
3757
4097
 
3758
4098
  const type$3 = 'taglist';
3759
4099
  function Taglist(props) {
@@ -3775,6 +4115,7 @@ function Taglist(props) {
3775
4115
  const {
3776
4116
  formId
3777
4117
  } = useContext(FormContext$1);
4118
+ const errorMessageId = errors.length === 0 ? undefined : `${prefixId(id, formId)}-error-message`;
3778
4119
  const [filter, setFilter] = useState('');
3779
4120
  const [filteredOptions, setFilteredOptions] = useState([]);
3780
4121
  const [isDropdownExpanded, setIsDropdownExpanded] = useState(false);
@@ -3868,6 +4209,12 @@ function Taglist(props) {
3868
4209
  errors,
3869
4210
  disabled
3870
4211
  }),
4212
+ onKeyDown: event => {
4213
+ if (event.key === 'Enter') {
4214
+ event.stopPropagation();
4215
+ event.preventDefault();
4216
+ }
4217
+ },
3871
4218
  children: [jsx(Label, {
3872
4219
  label: label,
3873
4220
  required: required,
@@ -3904,15 +4251,16 @@ function Taglist(props) {
3904
4251
  onChange: onFilterChange,
3905
4252
  type: "text",
3906
4253
  value: filter,
3907
- placeholder: disabled ? '' : 'Search',
4254
+ placeholder: disabled ? undefined : 'Search',
3908
4255
  autoComplete: "off",
3909
- onKeyDown: e => onInputKeyDown(e),
4256
+ onKeyDown: onInputKeyDown,
3910
4257
  onMouseDown: () => setIsEscapeClose(false),
3911
4258
  onFocus: () => setIsDropdownExpanded(true),
3912
4259
  onBlur: () => {
3913
4260
  setIsDropdownExpanded(false);
3914
4261
  setFilter('');
3915
- }
4262
+ },
4263
+ "aria-describedby": errorMessageId
3916
4264
  })]
3917
4265
  }), jsx("div", {
3918
4266
  class: "fjs-taglist-anchor",
@@ -3926,34 +4274,41 @@ function Taglist(props) {
3926
4274
  }), jsx(Description, {
3927
4275
  description: description
3928
4276
  }), jsx(Errors, {
3929
- errors: errors
4277
+ errors: errors,
4278
+ id: errorMessageId
3930
4279
  })]
3931
4280
  });
3932
4281
  }
3933
- Taglist.create = (options = {}) => {
3934
- const defaults = {};
3935
-
3936
- // provide default values if valuesKey isn't set
3937
- if (!options.valuesKey) {
3938
- defaults.values = [{
3939
- label: 'Value',
3940
- value: 'value'
3941
- }];
4282
+ Taglist.config = {
4283
+ type: type$3,
4284
+ keyed: true,
4285
+ label: 'Tag list',
4286
+ group: 'selection',
4287
+ emptyValue: [],
4288
+ sanitizeValue: sanitizeMultiSelectValue,
4289
+ create: (options = {}) => {
4290
+ const defaults = {};
4291
+
4292
+ // provide default values if valuesKey isn't set
4293
+ if (!options.valuesKey) {
4294
+ defaults.values = [{
4295
+ label: 'Value',
4296
+ value: 'value'
4297
+ }];
4298
+ }
4299
+ return {
4300
+ ...defaults,
4301
+ ...options
4302
+ };
3942
4303
  }
3943
- return {
3944
- ...defaults,
3945
- ...options
3946
- };
3947
4304
  };
3948
- Taglist.type = type$3;
3949
- Taglist.label = 'Tag list';
3950
- Taglist.keyed = true;
3951
- Taglist.emptyValue = [];
3952
- Taglist.sanitizeValue = sanitizeMultiSelectValue;
3953
- Taglist.group = 'selection';
3954
4305
 
3955
4306
  const type$2 = 'text';
3956
4307
  function Text(props) {
4308
+ const form = useService('form');
4309
+ const {
4310
+ textLinkTarget
4311
+ } = form._getState().properties;
3957
4312
  const {
3958
4313
  field,
3959
4314
  disableLinks
@@ -3975,9 +4330,20 @@ function Text(props) {
3975
4330
  const html = markdownRenderer.render(markdown);
3976
4331
  return sanitizeHTML(html);
3977
4332
  }, [markdownRenderer, markdown]);
3978
- const componentOverrides = useMemo(() => disableLinks ? {
3979
- 'a': DisabledLink
3980
- } : {}, [disableLinks]);
4333
+ const OverridenTargetLink = useMemo(() => BuildOverridenTargetLink(textLinkTarget), [textLinkTarget]);
4334
+ const componentOverrides = useMemo(() => {
4335
+ if (disableLinks) {
4336
+ return {
4337
+ 'a': DisabledLink
4338
+ };
4339
+ }
4340
+ if (textLinkTarget) {
4341
+ return {
4342
+ 'a': OverridenTargetLink
4343
+ };
4344
+ }
4345
+ return {};
4346
+ }, [disableLinks, OverridenTargetLink, textLinkTarget]);
3981
4347
  return jsx("div", {
3982
4348
  class: formFieldClasses(type$2),
3983
4349
  children: jsx(Markup, {
@@ -3987,21 +4353,35 @@ function Text(props) {
3987
4353
  })
3988
4354
  });
3989
4355
  }
3990
- Text.create = (options = {}) => ({
3991
- text: '# Text',
3992
- ...options
3993
- });
3994
- Text.type = type$2;
3995
- Text.keyed = false;
3996
- Text.group = 'presentation';
3997
- Text.label = 'Text view';
4356
+ Text.config = {
4357
+ type: type$2,
4358
+ keyed: false,
4359
+ label: 'Text view',
4360
+ group: 'presentation',
4361
+ create: (options = {}) => ({
4362
+ text: '# Text',
4363
+ ...options
4364
+ })
4365
+ };
4366
+ function BuildOverridenTargetLink(target) {
4367
+ return function ({
4368
+ children,
4369
+ ...rest
4370
+ }) {
4371
+ return jsx("a", {
4372
+ ...rest,
4373
+ target: target,
4374
+ children: children
4375
+ });
4376
+ };
4377
+ }
3998
4378
  function DisabledLink({
3999
- href,
4000
- children
4379
+ children,
4380
+ ...rest
4001
4381
  }) {
4002
4382
  return jsx("a", {
4383
+ ...rest,
4003
4384
  class: "fjs-disabled-link",
4004
- href: href,
4005
4385
  tabIndex: -1,
4006
4386
  children: children
4007
4387
  });
@@ -4040,6 +4420,7 @@ function Textfield(props) {
4040
4420
  const {
4041
4421
  formId
4042
4422
  } = useContext(FormContext$1);
4423
+ const errorMessageId = errors.length === 0 ? undefined : `${prefixId(id, formId)}-error-message`;
4043
4424
  return jsxs("div", {
4044
4425
  class: formFieldClasses(type$1, {
4045
4426
  errors,
@@ -4059,26 +4440,40 @@ function Textfield(props) {
4059
4440
  id: prefixId(id, formId),
4060
4441
  onInput: onChange,
4061
4442
  type: "text",
4062
- value: value
4443
+ value: value,
4444
+ "aria-describedby": errorMessageId
4063
4445
  })
4064
4446
  }), jsx(Description, {
4065
4447
  description: description
4066
4448
  }), jsx(Errors, {
4067
- errors: errors
4449
+ errors: errors,
4450
+ id: errorMessageId
4068
4451
  })]
4069
4452
  });
4070
4453
  }
4071
- Textfield.create = (options = {}) => ({
4072
- ...options
4073
- });
4074
- Textfield.type = type$1;
4075
- Textfield.label = 'Text field';
4076
- Textfield.keyed = true;
4077
- Textfield.emptyValue = '';
4078
- Textfield.sanitizeValue = ({
4079
- value
4080
- }) => isArray(value) || isObject(value) ? '' : String(value);
4081
- Textfield.group = 'basic-input';
4454
+ Textfield.config = {
4455
+ type: type$1,
4456
+ keyed: true,
4457
+ label: 'Text field',
4458
+ group: 'basic-input',
4459
+ emptyValue: '',
4460
+ sanitizeValue: ({
4461
+ value
4462
+ }) => {
4463
+ if (isArray(value) || isObject(value)) {
4464
+ return '';
4465
+ }
4466
+
4467
+ // sanitize newlines to spaces
4468
+ if (typeof value === 'string') {
4469
+ return value.replace(/[\r\n\t]/g, ' ');
4470
+ }
4471
+ return String(value);
4472
+ },
4473
+ create: (options = {}) => ({
4474
+ ...options
4475
+ })
4476
+ };
4082
4477
 
4083
4478
  const type = 'textarea';
4084
4479
  function Textarea(props) {
@@ -4125,6 +4520,7 @@ function Textarea(props) {
4125
4520
  const {
4126
4521
  formId
4127
4522
  } = useContext(FormContext$1);
4523
+ const errorMessageId = errors.length === 0 ? undefined : `${prefixId(id, formId)}-error-message`;
4128
4524
  return jsxs("div", {
4129
4525
  class: formFieldClasses(type, {
4130
4526
  errors,
@@ -4140,25 +4536,29 @@ function Textarea(props) {
4140
4536
  id: prefixId(id, formId),
4141
4537
  onInput: onInput,
4142
4538
  value: value,
4143
- ref: textareaRef
4539
+ ref: textareaRef,
4540
+ "aria-describedby": errorMessageId
4144
4541
  }), jsx(Description, {
4145
4542
  description: description
4146
4543
  }), jsx(Errors, {
4147
- errors: errors
4544
+ errors: errors,
4545
+ id: errorMessageId
4148
4546
  })]
4149
4547
  });
4150
4548
  }
4151
- Textarea.create = (options = {}) => ({
4152
- ...options
4153
- });
4154
- Textarea.type = type;
4155
- Textarea.label = 'Text area';
4156
- Textarea.keyed = true;
4157
- Textarea.emptyValue = '';
4158
- Textarea.sanitizeValue = ({
4159
- value
4160
- }) => isArray(value) || isObject(value) ? '' : String(value);
4161
- Textarea.group = 'basic-input';
4549
+ Textarea.config = {
4550
+ type,
4551
+ keyed: true,
4552
+ label: 'Text area',
4553
+ group: 'basic-input',
4554
+ emptyValue: '',
4555
+ sanitizeValue: ({
4556
+ value
4557
+ }) => isArray(value) || isObject(value) ? '' : String(value),
4558
+ create: (options = {}) => ({
4559
+ ...options
4560
+ })
4561
+ };
4162
4562
 
4163
4563
  function _extends$d() { _extends$d = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$d.apply(this, arguments); }
4164
4564
  var ButtonIcon = (({
@@ -4167,10 +4567,11 @@ var ButtonIcon = (({
4167
4567
  }) => /*#__PURE__*/React.createElement("svg", _extends$d({
4168
4568
  xmlns: "http://www.w3.org/2000/svg",
4169
4569
  width: "54",
4170
- height: "54"
4570
+ height: "54",
4571
+ fill: "currentcolor"
4171
4572
  }, props), /*#__PURE__*/React.createElement("path", {
4172
4573
  fillRule: "evenodd",
4173
- d: "M45 17a3 3 0 013 3v14a3 3 0 01-3 3H9a3 3 0 01-3-3V20a3 3 0 013-3h36zm-9 8.889H18v2.222h18V25.89z"
4574
+ d: "M45 17a3 3 0 013 3v14a3 3 0 01-3 3H9a3 3 0 01-3-3V20a3 3 0 013-3h36zm-9 8.889H18v2.222h18v-2.222z"
4174
4575
  })));
4175
4576
 
4176
4577
  function _extends$c() { _extends$c = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$c.apply(this, arguments); }
@@ -4180,7 +4581,8 @@ var CheckboxIcon = (({
4180
4581
  }) => /*#__PURE__*/React.createElement("svg", _extends$c({
4181
4582
  xmlns: "http://www.w3.org/2000/svg",
4182
4583
  width: "54",
4183
- height: "54"
4584
+ height: "54",
4585
+ fill: "currentcolor"
4184
4586
  }, props), /*#__PURE__*/React.createElement("path", {
4185
4587
  d: "M34 18H20a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2V20a2 2 0 00-2-2zm-9 14l-5-5 1.41-1.41L25 29.17l7.59-7.59L34 23l-9 9z"
4186
4588
  })));
@@ -4191,18 +4593,35 @@ var ChecklistIcon = (({
4191
4593
  ...props
4192
4594
  }) => /*#__PURE__*/React.createElement("svg", _extends$b({
4193
4595
  xmlns: "http://www.w3.org/2000/svg",
4596
+ xmlnsXlink: "http://www.w3.org/1999/xlink",
4194
4597
  width: "54",
4195
4598
  height: "54",
4196
- fill: "none"
4197
- }, props), /*#__PURE__*/React.createElement("path", {
4198
- fillRule: "evenodd",
4199
- clipRule: "evenodd",
4200
- d: "M18 12h-6v6h6v-6zm-6-2a2 2 0 00-2 2v6a2 2 0 002 2h6a2 2 0 002-2v-6a2 2 0 00-2-2h-6zM18 36h-6v6h6v-6zm-6-2a2 2 0 00-2 2v6a2 2 0 002 2h6a2 2 0 002-2v-6a2 2 0 00-2-2h-6zM18 24h-6v6h6v-6zm-6-2a2 2 0 00-2 2v6a2 2 0 002 2h6a2 2 0 002-2v-6a2 2 0 00-2-2h-6z",
4201
- fill: "#161616"
4599
+ fill: "currentcolor"
4600
+ }, props), /*#__PURE__*/React.createElement("g", {
4601
+ fillRule: "evenodd"
4602
+ }, /*#__PURE__*/React.createElement("use", {
4603
+ xlinkHref: "#a"
4604
+ }), /*#__PURE__*/React.createElement("use", {
4605
+ xlinkHref: "#a",
4606
+ y: "24"
4607
+ }), /*#__PURE__*/React.createElement("use", {
4608
+ xlinkHref: "#a",
4609
+ y: "12"
4610
+ })), /*#__PURE__*/React.createElement("use", {
4611
+ xlinkHref: "#b"
4612
+ }), /*#__PURE__*/React.createElement("use", {
4613
+ xlinkHref: "#b",
4614
+ y: "12"
4615
+ }), /*#__PURE__*/React.createElement("use", {
4616
+ xlinkHref: "#b",
4617
+ y: "24"
4618
+ }), /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("path", {
4619
+ id: "a",
4620
+ d: "M18 12h-6v6h6v-6zm-6-2a2 2 0 00-2 2v6a2 2 0 002 2h6a2 2 0 002-2v-6a2 2 0 00-2-2h-6z"
4202
4621
  }), /*#__PURE__*/React.createElement("path", {
4203
- d: "M23 14.5a1 1 0 011-1h19a1 1 0 011 1v1a1 1 0 01-1 1H24a1 1 0 01-1-1v-1zM23 26.5a1 1 0 011-1h19a1 1 0 011 1v1a1 1 0 01-1 1H24a1 1 0 01-1-1v-1zM23 38.5a1 1 0 011-1h19a1 1 0 011 1v1a1 1 0 01-1 1H24a1 1 0 01-1-1v-1z",
4204
- fill: "#161616"
4205
- })));
4622
+ id: "b",
4623
+ d: "M23 14.5a1 1 0 011-1h19a1 1 0 011 1v1a1 1 0 01-1 1H24a1 1 0 01-1-1v-1z"
4624
+ }))));
4206
4625
 
4207
4626
  function _extends$a() { _extends$a = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$a.apply(this, arguments); }
4208
4627
  var DatetimeIcon = (({
@@ -4212,20 +4631,15 @@ var DatetimeIcon = (({
4212
4631
  xmlns: "http://www.w3.org/2000/svg",
4213
4632
  width: "54",
4214
4633
  height: "54",
4215
- fill: "none"
4634
+ fill: "currentcolor"
4216
4635
  }, props), /*#__PURE__*/React.createElement("path", {
4217
- fill: "#000",
4218
4636
  fillRule: "evenodd",
4219
- d: "M37.908 13.418h-5.004v-2.354h-1.766v2.354H21.13v-2.354h-1.766v2.354H14.36c-1.132 0-2.06.928-2.06 2.06v23.549c0 1.132.928 2.06 2.06 2.06h6.77v-1.766h-6.358a.707.707 0 01-.706-.706V15.89c0-.39.316-.707.706-.707h4.592v2.355h1.766v-2.355h10.008v2.355h1.766v-2.355h4.592c.39 0 .707.317.707.707v6.358h1.765v-6.77c0-1.133-.927-2.06-2.06-2.06z",
4220
- clipRule: "evenodd"
4637
+ d: "M37.908 13.418h-5.004v-2.354h-1.766v2.354H21.13v-2.354h-1.766v2.354H14.36a2.07 2.07 0 00-2.06 2.06v23.549a2.07 2.07 0 002.06 2.06h6.77v-1.766h-6.358a.707.707 0 01-.706-.706V15.89c0-.39.316-.707.706-.707h4.592v2.355h1.766v-2.355h10.008v2.355h1.766v-2.355h4.592a.71.71 0 01.707.707v6.358h1.765v-6.77c0-1.133-.927-2.06-2.06-2.06z"
4221
4638
  }), /*#__PURE__*/React.createElement("path", {
4222
- fill: "#000",
4223
4639
  d: "M35.13 37.603l1.237-1.237-3.468-3.475v-5.926h-1.754v6.654l3.984 3.984z"
4224
4640
  }), /*#__PURE__*/React.createElement("path", {
4225
- fill: "#000",
4226
4641
  fillRule: "evenodd",
4227
- d: "M23.08 36.962a9.678 9.678 0 1017.883-7.408 9.678 9.678 0 00-17.882 7.408zm4.54-10.292a7.924 7.924 0 118.805 13.177A7.924 7.924 0 0127.62 26.67z",
4228
- clipRule: "evenodd"
4642
+ d: "M23.08 36.962a9.678 9.678 0 1017.883-7.408 9.678 9.678 0 00-17.882 7.408zm4.54-10.292a7.924 7.924 0 118.805 13.177A7.924 7.924 0 0127.62 26.67z"
4229
4643
  })));
4230
4644
 
4231
4645
  function _extends$9() { _extends$9 = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$9.apply(this, arguments); }
@@ -4233,18 +4647,15 @@ var TaglistIcon = (({
4233
4647
  styles = {},
4234
4648
  ...props
4235
4649
  }) => /*#__PURE__*/React.createElement("svg", _extends$9({
4650
+ xmlns: "http://www.w3.org/2000/svg",
4236
4651
  width: "54",
4237
4652
  height: "54",
4238
- fill: "none",
4239
- xmlns: "http://www.w3.org/2000/svg"
4653
+ fill: "currentcolor"
4240
4654
  }, props), /*#__PURE__*/React.createElement("path", {
4241
4655
  fillRule: "evenodd",
4242
- clipRule: "evenodd",
4243
- d: "M45 16a3 3 0 013 3v16a3 3 0 01-3 3H9a3 3 0 01-3-3V19a3 3 0 013-3h36zm0 2H9a1 1 0 00-1 1v16a1 1 0 001 1h36a1 1 0 001-1V19a1 1 0 00-1-1z",
4244
- fill: "#000"
4656
+ d: "M45 16a3 3 0 013 3v16a3 3 0 01-3 3H9a3 3 0 01-3-3V19a3 3 0 013-3h36zm0 2H9a1 1 0 00-1 1v16a1 1 0 001 1h36a1 1 0 001-1V19a1 1 0 00-1-1z"
4245
4657
  }), /*#__PURE__*/React.createElement("path", {
4246
- d: "M11 22a1 1 0 011-1h19a1 1 0 011 1v10a1 1 0 01-1 1H12a1 1 0 01-1-1V22z",
4247
- fill: "#505562"
4658
+ d: "M11 22a1 1 0 011-1h19a1 1 0 011 1v10a1 1 0 01-1 1H12a1 1 0 01-1-1V22z"
4248
4659
  })));
4249
4660
 
4250
4661
  function _extends$8() { _extends$8 = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$8.apply(this, arguments); }
@@ -4256,22 +4667,22 @@ var FormIcon = (({
4256
4667
  width: "54",
4257
4668
  height: "54"
4258
4669
  }, props), /*#__PURE__*/React.createElement("rect", {
4259
- x: "15",
4260
- y: "17",
4261
4670
  width: "24",
4262
4671
  height: "4",
4672
+ x: "15",
4673
+ y: "17",
4263
4674
  rx: "1"
4264
4675
  }), /*#__PURE__*/React.createElement("rect", {
4265
- x: "15",
4266
- y: "25",
4267
4676
  width: "24",
4268
4677
  height: "4",
4678
+ x: "15",
4679
+ y: "25",
4269
4680
  rx: "1"
4270
4681
  }), /*#__PURE__*/React.createElement("rect", {
4271
- x: "15",
4272
- y: "33",
4273
4682
  width: "13",
4274
4683
  height: "4",
4684
+ x: "15",
4685
+ y: "33",
4275
4686
  rx: "1"
4276
4687
  })));
4277
4688
 
@@ -4295,7 +4706,8 @@ var NumberIcon = (({
4295
4706
  }) => /*#__PURE__*/React.createElement("svg", _extends$6({
4296
4707
  xmlns: "http://www.w3.org/2000/svg",
4297
4708
  width: "54",
4298
- height: "54"
4709
+ height: "54",
4710
+ fill: "currentcolor"
4299
4711
  }, props), /*#__PURE__*/React.createElement("path", {
4300
4712
  fillRule: "evenodd",
4301
4713
  d: "M45 16a3 3 0 013 3v16a3 3 0 01-3 3H9a3 3 0 01-3-3V19a3 3 0 013-3h36zm0 2H9a1 1 0 00-1 1v16a1 1 0 001 1h36a1 1 0 001-1V19a1 1 0 00-1-1zM35 28.444h7l-3.5 4-3.5-4zM35 26h7l-3.5-4-3.5 4z"
@@ -4308,9 +4720,10 @@ var RadioIcon = (({
4308
4720
  }) => /*#__PURE__*/React.createElement("svg", _extends$5({
4309
4721
  xmlns: "http://www.w3.org/2000/svg",
4310
4722
  width: "54",
4311
- height: "54"
4723
+ height: "54",
4724
+ fill: "currentcolor"
4312
4725
  }, props), /*#__PURE__*/React.createElement("path", {
4313
- d: "M27 22c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5zm0-5c-5.52 0-10 4.48-10 10s4.48 10 10 10 10-4.48 10-10-4.48-10-10-10zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"
4726
+ d: "M27 22c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5zm0-5c-5.52 0-10 4.48-10 10s4.48 10 10 10 10-4.48 10-10-4.48-10-10-10zm0 18a8 8 0 110-16 8 8 0 110 16z"
4314
4727
  })));
4315
4728
 
4316
4729
  function _extends$4() { _extends$4 = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$4.apply(this, arguments); }
@@ -4320,7 +4733,8 @@ var SelectIcon = (({
4320
4733
  }) => /*#__PURE__*/React.createElement("svg", _extends$4({
4321
4734
  xmlns: "http://www.w3.org/2000/svg",
4322
4735
  width: "54",
4323
- height: "54"
4736
+ height: "54",
4737
+ fill: "currentcolor"
4324
4738
  }, props), /*#__PURE__*/React.createElement("path", {
4325
4739
  fillRule: "evenodd",
4326
4740
  d: "M45 16a3 3 0 013 3v16a3 3 0 01-3 3H9a3 3 0 01-3-3V19a3 3 0 013-3h36zm0 2H9a1 1 0 00-1 1v16a1 1 0 001 1h36a1 1 0 001-1V19a1 1 0 00-1-1zm-12 7h9l-4.5 6-4.5-6z"
@@ -4333,9 +4747,10 @@ var TextIcon = (({
4333
4747
  }) => /*#__PURE__*/React.createElement("svg", _extends$3({
4334
4748
  xmlns: "http://www.w3.org/2000/svg",
4335
4749
  width: "54",
4336
- height: "54"
4750
+ height: "54",
4751
+ fill: "currentcolor"
4337
4752
  }, props), /*#__PURE__*/React.createElement("path", {
4338
- d: "M20.58 33.77h-3l-1.18-3.08H11l-1.1 3.08H7l5.27-13.54h2.89zm-5-5.36l-1.86-5-1.83 5zM22 20.23h5.41a15.47 15.47 0 012.4.14 3.42 3.42 0 011.41.55 3.47 3.47 0 011 1.14 3 3 0 01.42 1.58 3.26 3.26 0 01-1.91 2.94 3.63 3.63 0 011.91 1.22 3.28 3.28 0 01.66 2 4 4 0 01-.43 1.8 3.63 3.63 0 01-1.09 1.4 3.89 3.89 0 01-1.83.65q-.69.07-3.3.09H22zm2.73 2.25v3.13h3.8a1.79 1.79 0 001.1-.49 1.41 1.41 0 00.41-1 1.49 1.49 0 00-.35-1 1.54 1.54 0 00-1-.48c-.27 0-1.05-.05-2.34-.05zm0 5.39v3.62h2.57a11.52 11.52 0 001.88-.09 1.65 1.65 0 001-.54 1.6 1.6 0 00.38-1.14 1.75 1.75 0 00-.29-1 1.69 1.69 0 00-.86-.62 9.28 9.28 0 00-2.41-.23zM44.35 28.79l2.65.84a5.94 5.94 0 01-2 3.29A5.74 5.74 0 0141.38 34a5.87 5.87 0 01-4.44-1.84 7.09 7.09 0 01-1.73-5A7.43 7.43 0 0137 21.87 6 6 0 0141.54 20a5.64 5.64 0 014 1.47A5.33 5.33 0 0147 24l-2.7.65a2.8 2.8 0 00-2.86-2.27A3.09 3.09 0 0039 23.42a5.31 5.31 0 00-.93 3.5 5.62 5.62 0 00.93 3.65 3 3 0 002.4 1.09 2.72 2.72 0 001.82-.66 4 4 0 001.13-2.21z"
4753
+ d: "M20.58 33.77h-3l-1.18-3.08H11l-1.1 3.08H7l5.27-13.54h2.89zm-5-5.36l-1.86-5-1.83 5zM22 20.23h5.41a15.47 15.47 0 012.4.14 3.42 3.42 0 011.41.55 3.47 3.47 0 011 1.14 3 3 0 01.42 1.58 3.26 3.26 0 01-1.91 2.94 3.63 3.63 0 011.91 1.22 3.28 3.28 0 01.66 2 4 4 0 01-.43 1.8 3.63 3.63 0 01-1.09 1.4 3.89 3.89 0 01-1.83.65q-.69.07-3.3.09H22zm2.73 2.25v3.13h3.8a1.79 1.79 0 001.1-.49 1.41 1.41 0 00.41-1 1.49 1.49 0 00-.35-1 1.54 1.54 0 00-1-.48c-.27 0-1.05-.05-2.34-.05zm0 5.39v3.62h2.57a11.52 11.52 0 001.88-.09 1.65 1.65 0 001-.54 1.6 1.6 0 00.38-1.14 1.75 1.75 0 00-.29-1 1.69 1.69 0 00-.86-.62 9.28 9.28 0 00-2.41-.23zm19.62.92l2.65.84a5.94 5.94 0 01-2 3.29A5.74 5.74 0 0141.38 34a5.87 5.87 0 01-4.44-1.84 7.09 7.09 0 01-1.73-5A7.43 7.43 0 0137 21.87 6 6 0 0141.54 20a5.64 5.64 0 014 1.47A5.33 5.33 0 0147 24l-2.7.65a2.8 2.8 0 00-2.86-2.27A3.09 3.09 0 0039 23.42a5.31 5.31 0 00-.93 3.5 5.62 5.62 0 00.93 3.65 3 3 0 002.4 1.09 2.72 2.72 0 001.82-.66 4 4 0 001.13-2.21z"
4339
4754
  })));
4340
4755
 
4341
4756
  function _extends$2() { _extends$2 = 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$2.apply(this, arguments); }
@@ -4345,7 +4760,8 @@ var TextfieldIcon = (({
4345
4760
  }) => /*#__PURE__*/React.createElement("svg", _extends$2({
4346
4761
  xmlns: "http://www.w3.org/2000/svg",
4347
4762
  width: "54",
4348
- height: "54"
4763
+ height: "54",
4764
+ fill: "currentcolor"
4349
4765
  }, props), /*#__PURE__*/React.createElement("path", {
4350
4766
  fillRule: "evenodd",
4351
4767
  d: "M45 16a3 3 0 013 3v16a3 3 0 01-3 3H9a3 3 0 01-3-3V19a3 3 0 013-3h36zm0 2H9a1 1 0 00-1 1v16a1 1 0 001 1h36a1 1 0 001-1V19a1 1 0 00-1-1zm-32 4v10h-2V22h2z"
@@ -4358,10 +4774,11 @@ var TextareaIcon = (({
4358
4774
  }) => /*#__PURE__*/React.createElement("svg", _extends$1({
4359
4775
  xmlns: "http://www.w3.org/2000/svg",
4360
4776
  width: "54",
4361
- height: "54"
4777
+ height: "54",
4778
+ fill: "currentcolor"
4362
4779
  }, props), /*#__PURE__*/React.createElement("path", {
4363
4780
  fillRule: "evenodd",
4364
- d: "M45 13a3 3 0 013 3v22a3 3 0 01-3 3H9a3 3 0 01-3-3V16a3 3 0 013-3h36zm0 2H9a1 1 0 00-1 1v22a1 1 0 001 1h36a1 1 0 001-1V16a1 1 0 00-1-1zm-1.136 15.5l.848.849-6.363 6.363-.849-.848 6.364-6.364zm.264 3.5l.849.849-2.828 2.828-.849-.849L44.128 34zM13 19v10h-2V19h2z"
4781
+ d: "M45 13a3 3 0 013 3v22a3 3 0 01-3 3H9a3 3 0 01-3-3V16a3 3 0 013-3h36zm0 2H9a1 1 0 00-1 1v22a1 1 0 001 1h36a1 1 0 001-1V16a1 1 0 00-1-1zm-1.136 15.5l.849.849-6.364 6.364-.849-.849 6.364-6.364zm.264 3.5l.849.849-2.828 2.828-.849-.849L44.128 34zM13 19v10h-2V19h2z"
4365
4782
  })));
4366
4783
 
4367
4784
  function _extends() { _extends = 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.apply(this, arguments); }
@@ -4369,20 +4786,18 @@ var ImageIcon = (({
4369
4786
  styles = {},
4370
4787
  ...props
4371
4788
  }) => /*#__PURE__*/React.createElement("svg", _extends({
4789
+ xmlns: "http://www.w3.org/2000/svg",
4372
4790
  width: "54",
4373
4791
  height: "54",
4374
- fill: "none",
4375
- xmlns: "http://www.w3.org/2000/svg"
4792
+ fill: "currentcolor"
4376
4793
  }, props), /*#__PURE__*/React.createElement("path", {
4377
4794
  fillRule: "evenodd",
4378
- clipRule: "evenodd",
4379
4795
  d: "M34.636 21.91A3.818 3.818 0 1127 21.908a3.818 3.818 0 017.636 0zm-2 0A1.818 1.818 0 1129 21.908a1.818 1.818 0 013.636 0z",
4380
- fill: "#000"
4796
+ clipRule: "evenodd"
4381
4797
  }), /*#__PURE__*/React.createElement("path", {
4382
4798
  fillRule: "evenodd",
4383
- clipRule: "evenodd",
4384
- d: "M15 13a2 2 0 00-2 2v24a2 2 0 002 2h24a2 2 0 002-2V15a2 2 0 00-2-2H15zm24 2H15v12.45l4.71-4.709a1.91 1.91 0 012.702 0l6.695 6.695 2.656-1.77a1.91 1.91 0 012.411.239L39 32.73V15zM15 39v-8.754c.06-.038.116-.083.168-.135l5.893-5.893 6.684 6.685a1.911 1.911 0 002.41.238l2.657-1.77 6.02 6.02c.052.051.108.097.168.135V39H15z",
4385
- fill: "#000"
4799
+ d: "M15 13a2 2 0 00-2 2v24a2 2 0 002 2h24a2 2 0 002-2V15a2 2 0 00-2-2H15zm24 2H15v12.45l4.71-4.709a1.91 1.91 0 012.702 0l6.695 6.695 2.656-1.77a1.91 1.91 0 012.411.239L39 32.73V15zM15 39v-8.754a.975.975 0 00.168-.135l5.893-5.893 6.684 6.685a1.911 1.911 0 002.41.238l2.657-1.77 6.02 6.02c.052.051.108.097.168.135V39H15z",
4800
+ clipRule: "evenodd"
4386
4801
  })));
4387
4802
 
4388
4803
  const iconsByType = type => {
@@ -4410,7 +4825,7 @@ class FormFields {
4410
4825
  constructor() {
4411
4826
  this._formFields = {};
4412
4827
  formFields.forEach(formField => {
4413
- this.register(formField.type, formField);
4828
+ this.register(formField.config.type, formField);
4414
4829
  });
4415
4830
  }
4416
4831
  register(type, formField) {