@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.cjs CHANGED
@@ -15,30 +15,179 @@ var flatpickr = require('flatpickr');
15
15
  var Markup = require('preact-markup');
16
16
  var didi = require('didi');
17
17
 
18
+ const getFlavouredFeelVariableNames = (feelString, feelFlavour, options = {}) => {
19
+ const {
20
+ depth = 0,
21
+ specialDepthAccessors = {}
22
+ } = options;
23
+ if (!['expression', 'unaryTest'].includes(feelFlavour)) return [];
24
+ const tree = feelFlavour === 'expression' ? feelin.parseExpressions(feelString) : feelin.parseUnaryTests(feelString);
25
+ const simpleExpressionTree = _buildSimpleFeelStructureTree(tree, feelString);
26
+ return function _unfoldVariables(node) {
27
+ if (node.name === 'PathExpression') {
28
+ if (Object.keys(specialDepthAccessors).length === 0) {
29
+ return depth === 0 ? [_getVariableNameAtPathIndex(node, 0)] : [];
30
+ }
31
+
32
+ // if using special depth accessors, use a more complex extraction
33
+ return Array.from(_smartExtractVariableNames(node, depth, specialDepthAccessors));
34
+ }
35
+ if (depth === 0 && node.name === 'VariableName') return [node.variableName];
36
+
37
+ // for any other kind of node, traverse its children and flatten the result
38
+ if (node.children) {
39
+ return node.children.reduce((acc, child) => {
40
+ return acc.concat(_unfoldVariables(child));
41
+ }, []);
42
+ }
43
+ return [];
44
+ }(simpleExpressionTree);
45
+ };
46
+
47
+ /**
48
+ * Get the variable name at the specified index in a given path expression.
49
+ *
50
+ * @param {Object} root - The root node of the path expression tree.
51
+ * @param {number} index - The index of the variable name to retrieve.
52
+ * @returns {string|null} The variable name at the specified index or null if index is out of bounds.
53
+ */
54
+ const _getVariableNameAtPathIndex = (root, index) => {
55
+ const accessors = _deconstructPathExpression(root);
56
+ return accessors[index] || null;
57
+ };
58
+
59
+ /**
60
+ * Extracts the variables which are required of the external context for a given path expression.
61
+ * This is done by traversing the path expression tree and keeping track of the current depth relative to the external context.
62
+ *
63
+ * @param {Object} node - The root node of the path expression tree.
64
+ * @param {number} initialDepth - The depth at which the root node is located in the outer context.
65
+ * @param {Object} specialDepthAccessors - Definitions of special keywords which represent more complex accesses of the outer context.
66
+ * @returns {Set} - A set containing the extracted variable names.
67
+ */
68
+ const _smartExtractVariableNames = (node, initialDepth, specialDepthAccessors) => {
69
+ // depth info represents the previous (initialised as null) and current depth of the current accessor in the path expression
70
+ // we track multiple of these to account for the fact that a path expression may be ambiguous due to special keywords
71
+ let accessorDepthInfos = [{
72
+ previous: null,
73
+ current: initialDepth - 1
74
+ }];
75
+ const extractedVariables = new Set();
76
+ const nodeAccessors = _deconstructPathExpression(node);
77
+ for (let i = 0; i < nodeAccessors.length; i++) {
78
+ const currentAccessor = nodeAccessors[i];
79
+ if (currentAccessor in specialDepthAccessors) {
80
+ const depthOffsets = specialDepthAccessors[currentAccessor];
81
+
82
+ // if the current accessor is a special keyword, we need to expand the current depth info set
83
+ // this is done to account for the ambiguity of keywords like parent, which may be used to access
84
+ // the parent of the current node, or a child variable of the same name
85
+ accessorDepthInfos = depthOffsets.reduce((accumulator, offset) => {
86
+ return [...accumulator, ...accessorDepthInfos.map(depthInfo => ({
87
+ previous: depthInfo.current,
88
+ current: depthInfo.current + offset
89
+ }))];
90
+ }, []).filter(depthInfo => depthInfo.current >= -1); // discard all depth infos which are out of bounds
91
+ } else {
92
+ // if the current accessor is not a special keyword, we know it's simply accessing a child
93
+ // hence we are now one level deeper in the tree and simply increment
94
+ accessorDepthInfos = accessorDepthInfos.map(depthInfo => ({
95
+ previous: depthInfo.current,
96
+ current: depthInfo.current + 1
97
+ }));
98
+ }
99
+
100
+ // finally, we check if for the current accessor, there is a scenario where:
101
+ // previous it was at depth -1 (i.e. the root context), and is now at depth 0 (i.e. a variable)
102
+ // these are the variables we need to request, so we add them to the set
103
+ if (accessorDepthInfos.some(depthInfo => depthInfo.previous === -1 && depthInfo.current === 0)) {
104
+ extractedVariables.add(currentAccessor);
105
+ }
106
+ }
107
+
108
+ // we return a set to avoid duplicates
109
+ return new Set(extractedVariables);
110
+ };
111
+
112
+ /**
113
+ * Deconstructs a path expression tree into an array of components.
114
+ *
115
+ * @param {Object} root - The root node of the path expression tree.
116
+ * @returns {Array<string>} An array of components in the path expression, in the correct order.
117
+ */
118
+ const _deconstructPathExpression = root => {
119
+ let node = root;
120
+ let parts = [];
121
+
122
+ // Traverse the tree and collect path components
123
+ while (node.name === 'PathExpression') {
124
+ parts.push(node.children[1].variableName);
125
+ node = node.children[0];
126
+ }
127
+
128
+ // Add the last component to the array
129
+ parts.push(node.variableName);
130
+
131
+ // Reverse and return the array to get the correct order
132
+ return parts.reverse();
133
+ };
134
+
135
+ /**
136
+ * Builds a simplified feel structure tree from the given parse tree and feel string.
137
+ * The nodes follow this structure: `{ name: string, children: Array, variableName?: string }`
138
+ *
139
+ * @param {Object} parseTree - The parse tree generated by a parser.
140
+ * @param {string} feelString - The feel string used for parsing.
141
+ * @returns {Object} The simplified feel structure tree.
142
+ */
143
+ const _buildSimpleFeelStructureTree = (parseTree, feelString) => {
144
+ const stack = [{
145
+ children: []
146
+ }];
147
+ parseTree.iterate({
148
+ enter: node => {
149
+ const nodeRepresentation = {
150
+ name: node.type.name,
151
+ children: []
152
+ };
153
+ if (node.type.name === 'VariableName') {
154
+ nodeRepresentation.variableName = feelString.slice(node.from, node.to);
155
+ }
156
+ stack.push(nodeRepresentation);
157
+ },
158
+ leave: () => {
159
+ const result = stack.pop();
160
+ const parent = stack[stack.length - 1];
161
+ parent.children.push(result);
162
+ }
163
+ });
164
+ return stack[0].children[0];
165
+ };
166
+
18
167
  class FeelExpressionLanguage {
19
168
  constructor(eventBus) {
20
169
  this._eventBus = eventBus;
21
170
  }
22
171
 
23
- /**
24
- * Determines if the given string is a FEEL expression.
25
- *
26
- * @param {string} value
27
- * @returns {boolean}
28
- *
172
+ /**
173
+ * Determines if the given value is a FEEL expression.
174
+ *
175
+ * @param {any} value
176
+ * @returns {boolean}
177
+ *
29
178
  */
30
179
  isExpression(value) {
31
180
  return minDash.isString(value) && value.startsWith('=');
32
181
  }
33
182
 
34
- /**
35
- * Retrieve variable names from a given FEEL expression.
36
- *
37
- * @param {string} expression
38
- * @param {object} [options]
39
- * @param {string} [options.type]
40
- *
41
- * @returns {string[]}
183
+ /**
184
+ * Retrieve variable names from a given FEEL expression.
185
+ *
186
+ * @param {string} expression
187
+ * @param {object} [options]
188
+ * @param {string} [options.type]
189
+ *
190
+ * @returns {string[]}
42
191
  */
43
192
  getVariableNames(expression, options = {}) {
44
193
  const {
@@ -47,21 +196,19 @@ class FeelExpressionLanguage {
47
196
  if (!this.isExpression(expression)) {
48
197
  return [];
49
198
  }
50
- if (type === 'unaryTest') {
51
- return this._getUnaryVariableNames(expression);
52
- } else if (type === 'expression') {
53
- return this._getExpressionVariableNames(expression);
199
+ if (!['unaryTest', 'expression'].includes(type)) {
200
+ throw new Error('Unknown expression type: ' + type);
54
201
  }
55
- throw new Error('Unknown expression type: ' + options.type);
202
+ return getFlavouredFeelVariableNames(expression, type);
56
203
  }
57
204
 
58
- /**
59
- * Evaluate an expression.
60
- *
61
- * @param {string} expression
62
- * @param {import('../../types').Data} [data]
63
- *
64
- * @returns {any}
205
+ /**
206
+ * Evaluate an expression.
207
+ *
208
+ * @param {string} expression
209
+ * @param {import('../../types').Data} [data]
210
+ *
211
+ * @returns {any}
65
212
  */
66
213
  evaluate(expression, data = {}) {
67
214
  if (!expression) {
@@ -80,50 +227,65 @@ class FeelExpressionLanguage {
80
227
  return null;
81
228
  }
82
229
  }
83
- _getExpressionVariableNames(expression) {
84
- const tree = feelin.parseExpressions(expression);
85
- const cursor = tree.cursor();
86
- const variables = new Set();
87
- do {
88
- const node = cursor.node;
89
- if (node.type.name === 'VariableName') {
90
- variables.add(expression.slice(node.from, node.to));
91
- }
92
- } while (cursor.next());
93
- return Array.from(variables);
94
- }
95
- _getUnaryVariableNames(unaryTest) {
96
- const tree = feelin.parseUnaryTests(unaryTest);
97
- const cursor = tree.cursor();
98
- const variables = new Set();
99
- do {
100
- const node = cursor.node;
101
- if (node.type.name === 'VariableName') {
102
- variables.add(unaryTest.slice(node.from, node.to));
103
- }
104
- } while (cursor.next());
105
- return Array.from(variables);
106
- }
107
230
  }
108
231
  FeelExpressionLanguage.$inject = ['eventBus'];
109
232
 
110
233
  class FeelersTemplating {
111
234
  constructor() {}
235
+
236
+ /**
237
+ * Determines if the given value is a feelers template.
238
+ *
239
+ * @param {any} value
240
+ * @returns {boolean}
241
+ *
242
+ */
112
243
  isTemplate(value) {
113
- return minDash.isString(value) && (value.startsWith('=') || /{{/.test(value));
244
+ return minDash.isString(value) && (value.startsWith('=') || /{{.*?}}/.test(value));
114
245
  }
115
246
 
116
- /**
117
- * Evaluate a template.
118
- *
119
- * @param {string} template
120
- * @param {Object<string, any>} context
121
- * @param {Object} options
122
- * @param {boolean} [options.debug = false]
123
- * @param {boolean} [options.strict = false]
124
- * @param {Function} [options.buildDebugString]
125
- *
126
- * @returns
247
+ /**
248
+ * Retrieve variable names from a given feelers template.
249
+ *
250
+ * @param {string} template
251
+ *
252
+ * @returns {string[]}
253
+ */
254
+ getVariableNames(template) {
255
+ if (!this.isTemplate(template)) {
256
+ return [];
257
+ }
258
+ const expressions = this._extractExpressionsWithDepth(template);
259
+
260
+ // 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)
261
+ const specialDepthAccessors = {
262
+ parent: [-1, 1],
263
+ _parent_: [-1],
264
+ this: [0, 1],
265
+ _this_: [0]
266
+ };
267
+ return expressions.reduce((variables, {
268
+ expression,
269
+ depth
270
+ }) => {
271
+ return variables.concat(getFlavouredFeelVariableNames(expression, 'expression', {
272
+ depth,
273
+ specialDepthAccessors
274
+ }));
275
+ }, []);
276
+ }
277
+
278
+ /**
279
+ * Evaluate a template.
280
+ *
281
+ * @param {string} template
282
+ * @param {Object<string, any>} context
283
+ * @param {Object} options
284
+ * @param {boolean} [options.debug = false]
285
+ * @param {boolean} [options.strict = false]
286
+ * @param {Function} [options.buildDebugString]
287
+ *
288
+ * @returns
127
289
  */
128
290
  evaluate(template, context = {}, options = {}) {
129
291
  const {
@@ -137,12 +299,56 @@ class FeelersTemplating {
137
299
  buildDebugString
138
300
  });
139
301
  }
302
+
303
+ /**
304
+ * @typedef {Object} ExpressionWithDepth
305
+ * @property {number} depth - The depth of the expression in the syntax tree.
306
+ * @property {string} expression - The extracted expression
307
+ */
308
+
309
+ /**
310
+ * Extracts all feel expressions in the template along with their depth in the syntax tree.
311
+ * The depth is incremented for child expressions of loops to account for context drilling.
312
+ * @name extractExpressionsWithDepth
313
+ * @param {string} template - A feelers template string.
314
+ * @returns {Array<ExpressionWithDepth>} An array of objects, each containing the depth and the extracted expression.
315
+ *
316
+ * @example
317
+ * const template = "Hello {{user}}, you have:{{#loop items}}\n- {{amount}} {{name}}{{/loop}}.";
318
+ * const extractedExpressions = _extractExpressionsWithDepth(template);
319
+ */
320
+ _extractExpressionsWithDepth(template) {
321
+ // build simplified feelers syntax tree
322
+ const parseTree = feelers.parser.parse(template);
323
+ const tree = feelers.buildSimpleTree(parseTree, template);
324
+ return function _traverse(n, depth = 0) {
325
+ if (['Feel', 'FeelBlock'].includes(n.name)) {
326
+ return [{
327
+ depth,
328
+ expression: n.content
329
+ }];
330
+ }
331
+ if (n.name === 'LoopSpanner') {
332
+ const loopExpression = n.children[0].content;
333
+ const childResults = n.children.slice(1).reduce((acc, child) => {
334
+ return acc.concat(_traverse(child, depth + 1));
335
+ }, []);
336
+ return [{
337
+ depth,
338
+ expression: loopExpression
339
+ }, ...childResults];
340
+ }
341
+ return n.children.reduce((acc, child) => {
342
+ return acc.concat(_traverse(child, depth));
343
+ }, []);
344
+ }(tree);
345
+ }
140
346
  }
141
347
  FeelersTemplating.$inject = [];
142
348
 
143
- /**
144
- * @typedef {object} Condition
145
- * @property {string} [hide]
349
+ /**
350
+ * @typedef {object} Condition
351
+ * @property {string} [hide]
146
352
  */
147
353
 
148
354
  class ConditionChecker {
@@ -151,11 +357,11 @@ class ConditionChecker {
151
357
  this._eventBus = eventBus;
152
358
  }
153
359
 
154
- /**
155
- * For given data, remove properties based on condition.
156
- *
157
- * @param {Object<string, any>} properties
158
- * @param {Object<string, any>} data
360
+ /**
361
+ * For given data, remove properties based on condition.
362
+ *
363
+ * @param {Object<string, any>} properties
364
+ * @param {Object<string, any>} data
159
365
  */
160
366
  applyConditions(properties, data = {}) {
161
367
  const conditions = this._getConditions();
@@ -174,13 +380,13 @@ class ConditionChecker {
174
380
  return newProperties;
175
381
  }
176
382
 
177
- /**
178
- * Check if given condition is met. Returns null for invalid/missing conditions.
179
- *
180
- * @param {string} condition
181
- * @param {import('../../types').Data} [data]
182
- *
183
- * @returns {boolean|null}
383
+ /**
384
+ * Check if given condition is met. Returns null for invalid/missing conditions.
385
+ *
386
+ * @param {string} condition
387
+ * @param {import('../../types').Data} [data]
388
+ *
389
+ * @returns {boolean|null}
184
390
  */
185
391
  check(condition, data = {}) {
186
392
  if (!condition) {
@@ -201,12 +407,12 @@ class ConditionChecker {
201
407
  }
202
408
  }
203
409
 
204
- /**
205
- * Check if hide condition is met.
206
- *
207
- * @param {Condition} condition
208
- * @param {Object<string, any>} data
209
- * @returns {boolean}
410
+ /**
411
+ * Check if hide condition is met.
412
+ *
413
+ * @param {Condition} condition
414
+ * @param {Object<string, any>} data
415
+ * @returns {boolean}
210
416
  */
211
417
  _checkHideCondition(condition, data) {
212
418
  if (!condition.hide) {
@@ -248,12 +454,12 @@ class MarkdownRenderer {
248
454
  this._converter = new showdown.Converter();
249
455
  }
250
456
 
251
- /**
252
- * Render markdown to HTML.
253
- *
254
- * @param {string} markdown - The markdown to render
255
- *
256
- * @returns {string} HTML
457
+ /**
458
+ * Render markdown to HTML.
459
+ *
460
+ * @param {string} markdown - The markdown to render
461
+ *
462
+ * @returns {string} HTML
257
463
  */
258
464
  render(markdown) {
259
465
  return this._converter.makeHtml(markdown);
@@ -270,6 +476,30 @@ var FN_REF = '__fn';
270
476
  var DEFAULT_PRIORITY = 1000;
271
477
  var slice = Array.prototype.slice;
272
478
 
479
+ /**
480
+ * @typedef { {
481
+ * stopPropagation(): void;
482
+ * preventDefault(): void;
483
+ * cancelBubble: boolean;
484
+ * defaultPrevented: boolean;
485
+ * returnValue: any;
486
+ * } } Event
487
+ */
488
+
489
+ /**
490
+ * @template E
491
+ *
492
+ * @typedef { (event: E & Event, ...any) => any } EventBusEventCallback
493
+ */
494
+
495
+ /**
496
+ * @typedef { {
497
+ * priority: number;
498
+ * next: EventBusListener | null;
499
+ * callback: EventBusEventCallback<any>;
500
+ * } } EventBusListener
501
+ */
502
+
273
503
  /**
274
504
  * A general purpose event bus.
275
505
  *
@@ -354,6 +584,9 @@ var slice = Array.prototype.slice;
354
584
  * ```
355
585
  */
356
586
  function EventBus() {
587
+ /**
588
+ * @type { Record<string, EventBusListener> }
589
+ */
357
590
  this._listeners = {};
358
591
 
359
592
  // cleanup on destroy on lowest priority to allow
@@ -373,10 +606,12 @@ function EventBus() {
373
606
  *
374
607
  * Returning anything but `undefined` from a listener will stop the listener propagation.
375
608
  *
376
- * @param {string|Array<string>} events
377
- * @param {number} [priority=1000] the priority in which this listener is called, larger is higher
378
- * @param {Function} callback
379
- * @param {Object} [that] Pass context (`this`) to the callback
609
+ * @template T
610
+ *
611
+ * @param {string|string[]} events to subscribe to
612
+ * @param {number} [priority=1000] listen priority
613
+ * @param {EventBusEventCallback<T>} callback
614
+ * @param {any} [that] callback context
380
615
  */
381
616
  EventBus.prototype.on = function (events, priority, callback, that) {
382
617
  events = minDash.isArray(events) ? events : [events];
@@ -408,14 +643,16 @@ EventBus.prototype.on = function (events, priority, callback, that) {
408
643
  };
409
644
 
410
645
  /**
411
- * Register an event listener that is executed only once.
646
+ * Register an event listener that is called only once.
412
647
  *
413
- * @param {string} event the event name to register for
414
- * @param {number} [priority=1000] the priority in which this listener is called, larger is higher
415
- * @param {Function} callback the callback to execute
416
- * @param {Object} [that] Pass context (`this`) to the callback
648
+ * @template T
649
+ *
650
+ * @param {string|string[]} events to subscribe to
651
+ * @param {number} [priority=1000] the listen priority
652
+ * @param {EventBusEventCallback<T>} callback
653
+ * @param {any} [that] callback context
417
654
  */
418
- EventBus.prototype.once = function (event, priority, callback, that) {
655
+ EventBus.prototype.once = function (events, priority, callback, that) {
419
656
  var self = this;
420
657
  if (minDash.isFunction(priority)) {
421
658
  that = callback;
@@ -428,7 +665,7 @@ EventBus.prototype.once = function (event, priority, callback, that) {
428
665
  function wrappedCallback() {
429
666
  wrappedCallback.__isTomb = true;
430
667
  var result = callback.apply(that, arguments);
431
- self.off(event, wrappedCallback);
668
+ self.off(events, wrappedCallback);
432
669
  return result;
433
670
  }
434
671
 
@@ -436,7 +673,7 @@ EventBus.prototype.once = function (event, priority, callback, that) {
436
673
  // bound callbacks via {@link #off} using the original
437
674
  // callback
438
675
  wrappedCallback[FN_REF] = callback;
439
- this.on(event, priority, wrappedCallback);
676
+ this.on(events, priority, wrappedCallback);
440
677
  };
441
678
 
442
679
  /**
@@ -444,8 +681,8 @@ EventBus.prototype.once = function (event, priority, callback, that) {
444
681
  *
445
682
  * If no callback is given, all listeners for a given event name are being removed.
446
683
  *
447
- * @param {string|Array<string>} events
448
- * @param {Function} [callback]
684
+ * @param {string|string[]} events
685
+ * @param {EventBusEventCallback} [callback]
449
686
  */
450
687
  EventBus.prototype.off = function (events, callback) {
451
688
  events = minDash.isArray(events) ? events : [events];
@@ -456,11 +693,11 @@ EventBus.prototype.off = function (events, callback) {
456
693
  };
457
694
 
458
695
  /**
459
- * Create an EventBus event.
696
+ * Create an event recognized be the event bus.
460
697
  *
461
- * @param {Object} data
698
+ * @param {Object} data Event data.
462
699
  *
463
- * @return {Object} event, recognized by the eventBus
700
+ * @return {Event} An event that will be recognized by the event bus.
464
701
  */
465
702
  EventBus.prototype.createEvent = function (data) {
466
703
  var event = new InternalEvent();
@@ -469,10 +706,11 @@ EventBus.prototype.createEvent = function (data) {
469
706
  };
470
707
 
471
708
  /**
472
- * Fires a named event.
709
+ * Fires an event.
473
710
  *
474
711
  * @example
475
712
  *
713
+ * ```javascript
476
714
  * // fire event by name
477
715
  * events.fire('foo');
478
716
  *
@@ -490,13 +728,13 @@ EventBus.prototype.createEvent = function (data) {
490
728
  * });
491
729
  *
492
730
  * events.fire({ type: 'foo' }, 'I am bar!');
731
+ * ```
493
732
  *
494
- * @param {string} [name] the optional event name
495
- * @param {Object} [event] the event object
496
- * @param {...Object} additional arguments to be passed to the callback functions
733
+ * @param {string} [type] event type
734
+ * @param {Object} [data] event or event data
735
+ * @param {...any} [args] additional arguments the callback will be called with.
497
736
  *
498
- * @return {boolean} the events return value, if specified or false if the
499
- * default action was prevented by listeners
737
+ * @return {any} The return value. Will be set to `false` if the default was prevented.
500
738
  */
501
739
  EventBus.prototype.fire = function (type, data) {
502
740
  var event, firstListener, returnValue, args;
@@ -548,6 +786,14 @@ EventBus.prototype.fire = function (type, data) {
548
786
  }
549
787
  return returnValue;
550
788
  };
789
+
790
+ /**
791
+ * Handle an error by firing an event.
792
+ *
793
+ * @param {Error} error The error to be handled.
794
+ *
795
+ * @return {boolean} Whether the error was handled.
796
+ */
551
797
  EventBus.prototype.handleError = function (error) {
552
798
  return this.fire('error', {
553
799
  error: error
@@ -556,6 +802,14 @@ EventBus.prototype.handleError = function (error) {
556
802
  EventBus.prototype._destroy = function () {
557
803
  this._listeners = {};
558
804
  };
805
+
806
+ /**
807
+ * @param {Event} event
808
+ * @param {any[]} args
809
+ * @param {EventBusListener} listener
810
+ *
811
+ * @return {any}
812
+ */
559
813
  EventBus.prototype._invokeListeners = function (event, args, listener) {
560
814
  var returnValue;
561
815
  while (listener) {
@@ -568,6 +822,14 @@ EventBus.prototype._invokeListeners = function (event, args, listener) {
568
822
  }
569
823
  return returnValue;
570
824
  };
825
+
826
+ /**
827
+ * @param {Event} event
828
+ * @param {any[]} args
829
+ * @param {EventBusListener} listener
830
+ *
831
+ * @return {any}
832
+ */
571
833
  EventBus.prototype._invokeListener = function (event, args, listener) {
572
834
  var returnValue;
573
835
  if (listener.callback.__isTomb) {
@@ -596,7 +858,7 @@ EventBus.prototype._invokeListener = function (event, args, listener) {
596
858
  return returnValue;
597
859
  };
598
860
 
599
- /*
861
+ /**
600
862
  * Add new listener with a certain priority to the list
601
863
  * of listeners (for the given event).
602
864
  *
@@ -610,7 +872,7 @@ EventBus.prototype._invokeListener = function (event, args, listener) {
610
872
  * * after: [ 1500, 1500, (new=1300), 1000, 1000, (new=1000) ]
611
873
  *
612
874
  * @param {string} event
613
- * @param {Object} listener { priority, callback }
875
+ * @param {EventBusListener} listener
614
876
  */
615
877
  EventBus.prototype._addListener = function (event, newListener) {
616
878
  var listener = this._getListeners(event),
@@ -641,9 +903,20 @@ EventBus.prototype._addListener = function (event, newListener) {
641
903
  // add new listener to back
642
904
  previousListener.next = newListener;
643
905
  };
906
+
907
+ /**
908
+ * @param {string} name
909
+ *
910
+ * @return {EventBusListener}
911
+ */
644
912
  EventBus.prototype._getListeners = function (name) {
645
913
  return this._listeners[name];
646
914
  };
915
+
916
+ /**
917
+ * @param {string} name
918
+ * @param {EventBusListener} listener
919
+ */
647
920
  EventBus.prototype._setListeners = function (name, listener) {
648
921
  this._listeners[name] = listener;
649
922
  };
@@ -691,9 +964,9 @@ InternalEvent.prototype.init = function (data) {
691
964
  * Invoke function. Be fast...
692
965
  *
693
966
  * @param {Function} fn
694
- * @param {Array<Object>} args
967
+ * @param {any[]} args
695
968
  *
696
- * @return {Any}
969
+ * @return {any}
697
970
  */
698
971
  function invokeFunction(fn, args) {
699
972
  return fn.apply(null, args);
@@ -842,23 +1115,23 @@ class FormFieldRegistry {
842
1115
  }
843
1116
  FormFieldRegistry.$inject = ['eventBus'];
844
1117
 
845
- /**
846
- * @typedef { { id: String, components: Array<String> } } FormRow
847
- * @typedef { { formFieldId: String, rows: Array<FormRow> } } FormRows
1118
+ /**
1119
+ * @typedef { { id: String, components: Array<String> } } FormRow
1120
+ * @typedef { { formFieldId: String, rows: Array<FormRow> } } FormRows
848
1121
  */
849
1122
 
850
- /**
851
- * Maintains the Form layout in a given structure, for example
852
- *
853
- * [
854
- * {
855
- * formFieldId: 'FormField_1',
856
- * rows: [
857
- * { id: 'Row_1', components: [ 'Text_1', 'Textdield_1', ... ] }
858
- * ]
859
- * }
860
- * ]
861
- *
1123
+ /**
1124
+ * Maintains the Form layout in a given structure, for example
1125
+ *
1126
+ * [
1127
+ * {
1128
+ * formFieldId: 'FormField_1',
1129
+ * rows: [
1130
+ * { id: 'Row_1', components: [ 'Text_1', 'Textdield_1', ... ] }
1131
+ * ]
1132
+ * }
1133
+ * ]
1134
+ *
862
1135
  */
863
1136
  class FormLayouter {
864
1137
  constructor(eventBus) {
@@ -868,8 +1141,8 @@ class FormLayouter {
868
1141
  this._eventBus = eventBus;
869
1142
  }
870
1143
 
871
- /**
872
- * @param {FormRow} row
1144
+ /**
1145
+ * @param {FormRow} row
873
1146
  */
874
1147
  addRow(formFieldId, row) {
875
1148
  let rowsPerComponent = this._rows.find(r => r.formFieldId === formFieldId);
@@ -883,18 +1156,18 @@ class FormLayouter {
883
1156
  rowsPerComponent.rows.push(row);
884
1157
  }
885
1158
 
886
- /**
887
- * @param {String} id
888
- * @returns {FormRow}
1159
+ /**
1160
+ * @param {String} id
1161
+ * @returns {FormRow}
889
1162
  */
890
1163
  getRow(id) {
891
1164
  const rows = allRows(this._rows);
892
1165
  return rows.find(r => r.id === id);
893
1166
  }
894
1167
 
895
- /**
896
- * @param {any} formField
897
- * @returns {FormRow}
1168
+ /**
1169
+ * @param {any} formField
1170
+ * @returns {FormRow}
898
1171
  */
899
1172
  getRowForField(formField) {
900
1173
  return allRows(this._rows).find(r => {
@@ -905,9 +1178,9 @@ class FormLayouter {
905
1178
  });
906
1179
  }
907
1180
 
908
- /**
909
- * @param {String} formFieldId
910
- * @returns { Array<FormRow> }
1181
+ /**
1182
+ * @param {String} formFieldId
1183
+ * @returns { Array<FormRow> }
911
1184
  */
912
1185
  getRows(formFieldId) {
913
1186
  const rowsForField = this._rows.find(r => formFieldId === r.formFieldId);
@@ -917,15 +1190,15 @@ class FormLayouter {
917
1190
  return rowsForField.rows;
918
1191
  }
919
1192
 
920
- /**
921
- * @returns {string}
1193
+ /**
1194
+ * @returns {string}
922
1195
  */
923
1196
  nextRowId() {
924
1197
  return this._ids.nextPrefixed('Row_');
925
1198
  }
926
1199
 
927
- /**
928
- * @param {any} formField
1200
+ /**
1201
+ * @param {any} formField
929
1202
  */
930
1203
  calculateLayout(formField) {
931
1204
  const {
@@ -979,9 +1252,9 @@ function groupByRow(components, ids) {
979
1252
  });
980
1253
  }
981
1254
 
982
- /**
983
- * @param {Array<FormRows>} formRows
984
- * @returns {Array<FormRow>}
1255
+ /**
1256
+ * @param {Array<FormRows>} formRows
1257
+ * @returns {Array<FormRow>}
985
1258
  */
986
1259
  function allRows(formRows) {
987
1260
  return minDash.flatten(formRows.map(c => c.rows));
@@ -1058,10 +1331,10 @@ function createInjector(bootstrapModules) {
1058
1331
  return injector;
1059
1332
  }
1060
1333
 
1061
- /**
1062
- * @param {string?} prefix
1063
- *
1064
- * @returns Element
1334
+ /**
1335
+ * @param {string?} prefix
1336
+ *
1337
+ * @returns Element
1065
1338
  */
1066
1339
  function createFormContainer(prefix = 'fjs') {
1067
1340
  const container = document.createElement('div');
@@ -1070,6 +1343,7 @@ function createFormContainer(prefix = 'fjs') {
1070
1343
  }
1071
1344
 
1072
1345
  const EXPRESSION_PROPERTIES = ['alt', 'source', 'text'];
1346
+ const TEMPLATE_PROPERTIES = ['text'];
1073
1347
  function findErrors(errors, path) {
1074
1348
  return errors[pathStringify(path)];
1075
1349
  }
@@ -1106,24 +1380,24 @@ function generateIdForType(type) {
1106
1380
  return `${type}${generateIndexForType(type)}`;
1107
1381
  }
1108
1382
 
1109
- /**
1110
- * @template T
1111
- * @param {T} data
1112
- * @param {(this: any, key: string, value: any) => any} [replacer]
1113
- * @return {T}
1383
+ /**
1384
+ * @template T
1385
+ * @param {T} data
1386
+ * @param {(this: any, key: string, value: any) => any} [replacer]
1387
+ * @return {T}
1114
1388
  */
1115
1389
  function clone(data, replacer) {
1116
1390
  return JSON.parse(JSON.stringify(data, replacer));
1117
1391
  }
1118
1392
 
1119
- /**
1120
- * Parse the schema for input variables a form might make use of
1121
- *
1122
- * @param {any} schema
1123
- *
1124
- * @return {string[]}
1393
+ /**
1394
+ * Parse the schema for input variables a form might make use of
1395
+ *
1396
+ * @param {any} schema
1397
+ *
1398
+ * @return {string[]}
1125
1399
  */
1126
- function getSchemaVariables(schema, expressionLanguage = new FeelExpressionLanguage(null)) {
1400
+ function getSchemaVariables(schema, expressionLanguage = new FeelExpressionLanguage(null), templating = new FeelersTemplating()) {
1127
1401
  if (!schema.components) {
1128
1402
  return [];
1129
1403
  }
@@ -1158,6 +1432,13 @@ function getSchemaVariables(schema, expressionLanguage = new FeelExpressionLangu
1158
1432
  variables = [...variables, ...expressionVariables];
1159
1433
  }
1160
1434
  });
1435
+ TEMPLATE_PROPERTIES.forEach(prop => {
1436
+ const property = component[prop];
1437
+ if (property && !expressionLanguage.isExpression(property) && templating.isTemplate(property)) {
1438
+ const templateVariables = templating.getVariableNames(property);
1439
+ variables = [...variables, ...templateVariables];
1440
+ }
1441
+ });
1161
1442
  return variables;
1162
1443
  }, []);
1163
1444
 
@@ -1166,11 +1447,11 @@ function getSchemaVariables(schema, expressionLanguage = new FeelExpressionLangu
1166
1447
  }
1167
1448
 
1168
1449
  class Importer {
1169
- /**
1170
- * @constructor
1171
- * @param { import('../core').FormFieldRegistry } formFieldRegistry
1172
- * @param { import('../render/FormFields').default } formFields
1173
- * @param { import('../core').FormLayouter } formLayouter
1450
+ /**
1451
+ * @constructor
1452
+ * @param { import('../core').FormFieldRegistry } formFieldRegistry
1453
+ * @param { import('../render/FormFields').default } formFields
1454
+ * @param { import('../core').FormLayouter } formLayouter
1174
1455
  */
1175
1456
  constructor(formFieldRegistry, formFields, formLayouter) {
1176
1457
  this._formFieldRegistry = formFieldRegistry;
@@ -1178,15 +1459,15 @@ class Importer {
1178
1459
  this._formLayouter = formLayouter;
1179
1460
  }
1180
1461
 
1181
- /**
1182
- * Import schema adding `id`, `_parent` and `_path`
1183
- * information to each field and adding it to the
1184
- * form field registry.
1185
- *
1186
- * @param {any} schema
1187
- * @param {any} [data]
1188
- *
1189
- * @return { { warnings: Array<any>, schema: any, data: any } }
1462
+ /**
1463
+ * Import schema adding `id`, `_parent` and `_path`
1464
+ * information to each field and adding it to the
1465
+ * form field registry.
1466
+ *
1467
+ * @param {any} schema
1468
+ * @param {any} [data]
1469
+ *
1470
+ * @return { { warnings: Array<any>, schema: any, data: any } }
1190
1471
  */
1191
1472
  importSchema(schema, data = {}) {
1192
1473
  // TODO: Add warnings - https://github.com/bpmn-io/form-js/issues/289
@@ -1207,11 +1488,11 @@ class Importer {
1207
1488
  }
1208
1489
  }
1209
1490
 
1210
- /**
1211
- * @param {any} formField
1212
- * @param {string} [parentId]
1213
- *
1214
- * @return {any} importedField
1491
+ /**
1492
+ * @param {any} formField
1493
+ * @param {string} [parentId]
1494
+ *
1495
+ * @return {any} importedField
1215
1496
  */
1216
1497
  importFormField(formField, parentId) {
1217
1498
  const {
@@ -1262,10 +1543,10 @@ class Importer {
1262
1543
  });
1263
1544
  }
1264
1545
 
1265
- /**
1266
- * @param {Object} data
1267
- *
1268
- * @return {Object} initializedData
1546
+ /**
1547
+ * @param {Object} data
1548
+ *
1549
+ * @return {Object} initializedData
1269
1550
  */
1270
1551
  initializeFieldValues(data) {
1271
1552
  return this._formFieldRegistry.getAll().reduce((initializedData, formField) => {
@@ -1280,16 +1561,18 @@ class Importer {
1280
1561
  // if unavailable - get empty value from form field
1281
1562
 
1282
1563
  if (_path) {
1283
- const fieldImplementation = this._formFields.get(type);
1564
+ const {
1565
+ config: fieldConfig
1566
+ } = this._formFields.get(type);
1284
1567
  let valueData = minDash.get(data, _path);
1285
- if (!minDash.isUndefined(valueData) && fieldImplementation.sanitizeValue) {
1286
- valueData = fieldImplementation.sanitizeValue({
1568
+ if (!minDash.isUndefined(valueData) && fieldConfig.sanitizeValue) {
1569
+ valueData = fieldConfig.sanitizeValue({
1287
1570
  formField,
1288
1571
  data,
1289
1572
  value: valueData
1290
1573
  });
1291
1574
  }
1292
- const initializedFieldValue = !minDash.isUndefined(valueData) ? valueData : !minDash.isUndefined(defaultValue) ? defaultValue : fieldImplementation.emptyValue;
1575
+ const initializedFieldValue = !minDash.isUndefined(valueData) ? valueData : !minDash.isUndefined(defaultValue) ? defaultValue : fieldConfig.emptyValue;
1293
1576
  initializedData = {
1294
1577
  ...initializedData,
1295
1578
  [_path[0]]: initializedFieldValue
@@ -1354,14 +1637,16 @@ function Button(props) {
1354
1637
  })
1355
1638
  });
1356
1639
  }
1357
- Button.create = (options = {}) => ({
1358
- action: 'submit',
1359
- ...options
1360
- });
1361
- Button.type = type$b;
1362
- Button.label = 'Button';
1363
- Button.keyed = true;
1364
- Button.group = 'action';
1640
+ Button.config = {
1641
+ type: type$b,
1642
+ keyed: true,
1643
+ label: 'Button',
1644
+ group: 'action',
1645
+ create: (options = {}) => ({
1646
+ action: 'submit',
1647
+ ...options
1648
+ })
1649
+ };
1365
1650
 
1366
1651
  const FormRenderContext = preact.createContext({
1367
1652
  Empty: props => {
@@ -1397,11 +1682,11 @@ const FormRenderContext = preact.createContext({
1397
1682
  });
1398
1683
  var FormRenderContext$1 = FormRenderContext;
1399
1684
 
1400
- /**
1401
- * @param {string} type
1402
- * @param {boolean} [strict]
1403
- *
1404
- * @returns {any}
1685
+ /**
1686
+ * @param {string} type
1687
+ * @param {boolean} [strict]
1688
+ *
1689
+ * @returns {any}
1405
1690
  */
1406
1691
  function getService(type, strict) {}
1407
1692
  const FormContext = preact.createContext({
@@ -1425,13 +1710,16 @@ function Description(props) {
1425
1710
 
1426
1711
  function Errors(props) {
1427
1712
  const {
1428
- errors
1713
+ errors,
1714
+ id
1429
1715
  } = props;
1430
1716
  if (!errors.length) {
1431
1717
  return null;
1432
1718
  }
1433
1719
  return jsxRuntime.jsx("div", {
1434
1720
  class: "fjs-form-field-error",
1721
+ "aria-live": "polite",
1722
+ id: id,
1435
1723
  children: jsxRuntime.jsx("ul", {
1436
1724
  children: errors.map(error => {
1437
1725
  return jsxRuntime.jsx("li", {
@@ -1489,6 +1777,7 @@ function Checkbox(props) {
1489
1777
  const {
1490
1778
  formId
1491
1779
  } = hooks.useContext(FormContext$1);
1780
+ const errorMessageId = errors.length === 0 ? undefined : `${prefixId(id, formId)}-error-message`;
1492
1781
  return jsxRuntime.jsxs("div", {
1493
1782
  class: classNames(formFieldClasses(type$a, {
1494
1783
  errors,
@@ -1506,26 +1795,30 @@ function Checkbox(props) {
1506
1795
  disabled: disabled,
1507
1796
  id: prefixId(id, formId),
1508
1797
  type: "checkbox",
1509
- onChange: onChange
1798
+ onChange: onChange,
1799
+ "aria-describedby": errorMessageId
1510
1800
  })
1511
1801
  }), jsxRuntime.jsx(Description, {
1512
1802
  description: description
1513
1803
  }), jsxRuntime.jsx(Errors, {
1514
- errors: errors
1804
+ errors: errors,
1805
+ id: errorMessageId
1515
1806
  })]
1516
1807
  });
1517
1808
  }
1518
- Checkbox.create = (options = {}) => ({
1519
- ...options
1520
- });
1521
- Checkbox.type = type$a;
1522
- Checkbox.label = 'Checkbox';
1523
- Checkbox.keyed = true;
1524
- Checkbox.emptyValue = false;
1525
- Checkbox.sanitizeValue = ({
1526
- value
1527
- }) => value === true;
1528
- Checkbox.group = 'selection';
1809
+ Checkbox.config = {
1810
+ type: type$a,
1811
+ keyed: true,
1812
+ label: 'Checkbox',
1813
+ group: 'selection',
1814
+ emptyValue: false,
1815
+ sanitizeValue: ({
1816
+ value
1817
+ }) => value === true,
1818
+ create: (options = {}) => ({
1819
+ ...options
1820
+ })
1821
+ };
1529
1822
 
1530
1823
  // parses the options data from the provided form field and form data
1531
1824
  function getValuesData(formField, formData) {
@@ -1580,8 +1873,8 @@ function useService(type, strict) {
1580
1873
  return getService(type, strict);
1581
1874
  }
1582
1875
 
1583
- /**
1584
- * @enum { String }
1876
+ /**
1877
+ * @enum { String }
1585
1878
  */
1586
1879
  const LOAD_STATES = {
1587
1880
  LOADING: 'loading',
@@ -1589,17 +1882,17 @@ const LOAD_STATES = {
1589
1882
  ERROR: 'error'
1590
1883
  };
1591
1884
 
1592
- /**
1593
- * @typedef {Object} ValuesGetter
1594
- * @property {Object[]} values - The values data
1595
- * @property {(LOAD_STATES)} state - The values data's loading state, to use for conditional rendering
1885
+ /**
1886
+ * @typedef {Object} ValuesGetter
1887
+ * @property {Object[]} values - The values data
1888
+ * @property {(LOAD_STATES)} state - The values data's loading state, to use for conditional rendering
1596
1889
  */
1597
1890
 
1598
- /**
1599
- * A hook to load values for single and multiselect components.
1600
- *
1601
- * @param {Object} field - The form field to handle values for
1602
- * @return {ValuesGetter} valuesGetter - A values getter object providing loading state and values
1891
+ /**
1892
+ * A hook to load values for single and multiselect components.
1893
+ *
1894
+ * @param {Object} field - The form field to handle values for
1895
+ * @return {ValuesGetter} valuesGetter - A values getter object providing loading state and values
1603
1896
  */
1604
1897
  function useValuesAsync (field) {
1605
1898
  const {
@@ -1891,6 +2184,7 @@ function Checklist(props) {
1891
2184
  const {
1892
2185
  formId
1893
2186
  } = hooks.useContext(FormContext$1);
2187
+ const errorMessageId = errors.length === 0 ? undefined : `${prefixId(id, formId)}-error-message`;
1894
2188
  return jsxRuntime.jsxs("div", {
1895
2189
  class: classNames(formFieldClasses(type$9, {
1896
2190
  errors,
@@ -1913,42 +2207,46 @@ function Checklist(props) {
1913
2207
  disabled: disabled,
1914
2208
  id: prefixId(`${id}-${index}`, formId),
1915
2209
  type: "checkbox",
1916
- onClick: () => toggleCheckbox(v.value)
2210
+ onClick: () => toggleCheckbox(v.value),
2211
+ "aria-describedby": errorMessageId
1917
2212
  })
1918
2213
  }, `${id}-${index}`);
1919
2214
  }), jsxRuntime.jsx(Description, {
1920
2215
  description: description
1921
2216
  }), jsxRuntime.jsx(Errors, {
1922
- errors: errors
2217
+ errors: errors,
2218
+ id: errorMessageId
1923
2219
  })]
1924
2220
  });
1925
2221
  }
1926
- Checklist.create = (options = {}) => {
1927
- const defaults = {};
1928
-
1929
- // provide default values if valuesKey isn't set
1930
- if (!options.valuesKey) {
1931
- defaults.values = [{
1932
- label: 'Value',
1933
- value: 'value'
1934
- }];
2222
+ Checklist.config = {
2223
+ type: type$9,
2224
+ keyed: true,
2225
+ label: 'Checklist',
2226
+ group: 'selection',
2227
+ emptyValue: [],
2228
+ sanitizeValue: sanitizeMultiSelectValue,
2229
+ create: (options = {}) => {
2230
+ const defaults = {};
2231
+
2232
+ // provide default values if valuesKey isn't set
2233
+ if (!options.valuesKey) {
2234
+ defaults.values = [{
2235
+ label: 'Value',
2236
+ value: 'value'
2237
+ }];
2238
+ }
2239
+ return {
2240
+ ...defaults,
2241
+ ...options
2242
+ };
1935
2243
  }
1936
- return {
1937
- ...defaults,
1938
- ...options
1939
- };
1940
2244
  };
1941
- Checklist.type = type$9;
1942
- Checklist.label = 'Checklist';
1943
- Checklist.keyed = true;
1944
- Checklist.emptyValue = [];
1945
- Checklist.sanitizeValue = sanitizeMultiSelectValue;
1946
- Checklist.group = 'selection';
1947
2245
 
1948
- /**
1949
- * Returns the conditionally filtered data of a form reactively.
1950
- * Memoised to minimize re-renders
1951
- *
2246
+ /**
2247
+ * Returns the conditionally filtered data of a form reactively.
2248
+ * Memoised to minimize re-renders
2249
+ *
1952
2250
  */
1953
2251
  function useFilteredFormData() {
1954
2252
  const {
@@ -1965,12 +2263,12 @@ function useFilteredFormData() {
1965
2263
  }, [conditionChecker, data, initialData]);
1966
2264
  }
1967
2265
 
1968
- /**
1969
- * Evaluate if condition is met reactively based on the conditionChecker and form data.
1970
- *
1971
- * @param {string | undefined} condition
1972
- *
1973
- * @returns {boolean} true if condition is met or no condition or condition checker exists
2266
+ /**
2267
+ * Evaluate if condition is met reactively based on the conditionChecker and form data.
2268
+ *
2269
+ * @param {string | undefined} condition
2270
+ *
2271
+ * @returns {boolean} true if condition is met or no condition or condition checker exists
1974
2272
  */
1975
2273
  function useCondition(condition) {
1976
2274
  const conditionChecker = useService('conditionChecker', false);
@@ -1980,13 +2278,13 @@ function useCondition(condition) {
1980
2278
  }, [conditionChecker, condition, filteredData]);
1981
2279
  }
1982
2280
 
1983
- /**
1984
- * Evaluate a string reactively based on the expressionLanguage and form data.
1985
- * If the string is not an expression, it is returned as is.
1986
- * Memoised to minimize re-renders.
1987
- *
1988
- * @param {string} value
1989
- *
2281
+ /**
2282
+ * Evaluate a string reactively based on the expressionLanguage and form data.
2283
+ * If the string is not an expression, it is returned as is.
2284
+ * Memoised to minimize re-renders.
2285
+ *
2286
+ * @param {string} value
2287
+ *
1990
2288
  */
1991
2289
  function useExpressionEvaluation(value) {
1992
2290
  const formData = useFilteredFormData();
@@ -2015,16 +2313,16 @@ function useKeyDownAction(targetKey, action, listenerElement = window) {
2015
2313
  });
2016
2314
  }
2017
2315
 
2018
- /**
2019
- * Template a string reactively based on form data. If the string is not a template, it is returned as is.
2020
- * Memoised to minimize re-renders
2021
- *
2022
- * @param {string} value
2023
- * @param {Object} options
2024
- * @param {boolean} [options.debug = false]
2025
- * @param {boolean} [options.strict = false]
2026
- * @param {Function} [options.buildDebugString]
2027
- *
2316
+ /**
2317
+ * Template a string reactively based on form data. If the string is not a template, it is returned as is.
2318
+ * Memoised to minimize re-renders
2319
+ *
2320
+ * @param {string} value
2321
+ * @param {Object} options
2322
+ * @param {boolean} [options.debug = false]
2323
+ * @param {boolean} [options.strict = false]
2324
+ * @param {Function} [options.buildDebugString]
2325
+ *
2028
2326
  */
2029
2327
  function useTemplateEvaluation(value, options) {
2030
2328
  const filteredData = useFilteredFormData();
@@ -2043,9 +2341,6 @@ function FormField(props) {
2043
2341
  field,
2044
2342
  onChange
2045
2343
  } = props;
2046
- const {
2047
- _path
2048
- } = field;
2049
2344
  const formFields = useService('formFields'),
2050
2345
  form = useService('form');
2051
2346
  const {
@@ -2062,8 +2357,8 @@ function FormField(props) {
2062
2357
  if (!FormFieldComponent) {
2063
2358
  throw new Error(`cannot render field <${field.type}>`);
2064
2359
  }
2065
- const value = minDash.get(data, _path);
2066
- const fieldErrors = findErrors(errors, _path);
2360
+ const value = minDash.get(data, field._path);
2361
+ const fieldErrors = findErrors(errors, field._path);
2067
2362
  const disabled = properties.readOnly || field.disabled || false;
2068
2363
  const hidden = useCondition(field.conditional && field.conditional.hide || null);
2069
2364
  if (hidden) {
@@ -2130,14 +2425,16 @@ function Default(props) {
2130
2425
  }), components.length ? null : jsxRuntime.jsx(Empty, {})]
2131
2426
  });
2132
2427
  }
2133
- Default.create = (options = {}) => ({
2134
- components: [],
2135
- ...options
2136
- });
2137
- Default.type = 'default';
2138
- Default.keyed = false;
2139
- Default.label = null;
2140
- Default.group = null;
2428
+ Default.config = {
2429
+ type: 'default',
2430
+ keyed: false,
2431
+ label: null,
2432
+ group: null,
2433
+ create: (options = {}) => ({
2434
+ components: [],
2435
+ ...options
2436
+ })
2437
+ };
2141
2438
 
2142
2439
  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); }
2143
2440
  var CalendarIcon = (({
@@ -2313,16 +2610,17 @@ function Datepicker(props) {
2313
2610
  ref: dateInputRef,
2314
2611
  type: "text",
2315
2612
  id: fullId,
2316
- class: 'fjs-input',
2613
+ class: "fjs-input",
2317
2614
  disabled: disabled,
2318
2615
  placeholder: "mm/dd/yyyy",
2319
2616
  autoComplete: "off",
2320
2617
  onFocus: onInputFocus,
2321
2618
  onKeyDown: onInputKeyDown,
2322
- onMouseDown: e => !flatpickrInstance.isOpen && flatpickrInstance.open(),
2619
+ onMouseDown: () => !flatpickrInstance.isOpen && flatpickrInstance.open(),
2323
2620
  onBlur: onInputBlur,
2324
- onInput: e => setIsInputDirty(true),
2325
- "data-input": true
2621
+ onInput: () => setIsInputDirty(true),
2622
+ "data-input": true,
2623
+ "aria-describedby": props['aria-describedby']
2326
2624
  })
2327
2625
  })
2328
2626
  })]
@@ -2579,7 +2877,8 @@ function Timepicker(props) {
2579
2877
  },
2580
2878
  onBlur: onInputBlur,
2581
2879
  onKeyDown: onInputKeyDown,
2582
- "data-input": true
2880
+ "data-input": true,
2881
+ "aria-describedby": props['aria-describedby']
2583
2882
  }), dropdownIsOpen && jsxRuntime.jsx(DropdownList, {
2584
2883
  values: timeOptions,
2585
2884
  height: 150,
@@ -2715,6 +3014,7 @@ function Datetime(props) {
2715
3014
  time
2716
3015
  });
2717
3016
  }, []);
3017
+ const errorMessageId = allErrors.length === 0 ? undefined : `${prefixId(id, formId)}-error-message`;
2718
3018
  const datePickerProps = {
2719
3019
  id,
2720
3020
  label: dateLabel,
@@ -2724,7 +3024,8 @@ function Datetime(props) {
2724
3024
  disabled,
2725
3025
  disallowPassedDates,
2726
3026
  date: dateTime.date,
2727
- setDate
3027
+ setDate,
3028
+ 'aria-describedby': errorMessageId
2728
3029
  };
2729
3030
  const timePickerProps = {
2730
3031
  id,
@@ -2736,7 +3037,8 @@ function Datetime(props) {
2736
3037
  use24h,
2737
3038
  timeInterval,
2738
3039
  time: dateTime.time,
2739
- setTime
3040
+ setTime,
3041
+ 'aria-describedby': errorMessageId
2740
3042
  };
2741
3043
  return jsxRuntime.jsxs("div", {
2742
3044
  class: formFieldClasses(type$8, {
@@ -2755,30 +3057,33 @@ function Datetime(props) {
2755
3057
  }), jsxRuntime.jsx(Description, {
2756
3058
  description: description
2757
3059
  }), jsxRuntime.jsx(Errors, {
2758
- errors: allErrors
3060
+ errors: allErrors,
3061
+ id: errorMessageId
2759
3062
  })]
2760
3063
  });
2761
3064
  }
2762
- Datetime.create = (options = {}) => {
2763
- const defaults = {};
2764
- minDash.set(defaults, DATETIME_SUBTYPE_PATH, DATETIME_SUBTYPES.DATE);
2765
- minDash.set(defaults, DATE_LABEL_PATH, 'Date');
2766
- return {
2767
- ...defaults,
2768
- ...options
2769
- };
3065
+ Datetime.config = {
3066
+ type: type$8,
3067
+ keyed: true,
3068
+ label: 'Date time',
3069
+ group: 'basic-input',
3070
+ emptyValue: null,
3071
+ sanitizeValue: sanitizeDateTimePickerValue,
3072
+ create: (options = {}) => {
3073
+ const defaults = {};
3074
+ minDash.set(defaults, DATETIME_SUBTYPE_PATH, DATETIME_SUBTYPES.DATE);
3075
+ minDash.set(defaults, DATE_LABEL_PATH, 'Date');
3076
+ return {
3077
+ ...defaults,
3078
+ ...options
3079
+ };
3080
+ }
2770
3081
  };
2771
- Datetime.type = type$8;
2772
- Datetime.keyed = true;
2773
- Datetime.emptyValue = null;
2774
- Datetime.sanitizeValue = sanitizeDateTimePickerValue;
2775
- Datetime.label = 'Date time';
2776
- Datetime.group = 'basic-input';
2777
3082
 
2778
- /**
2779
- * This file must not be changed or exchanged.
2780
- *
2781
- * @see http://bpmn.io/license for more information.
3083
+ /**
3084
+ * This file must not be changed or exchanged.
3085
+ *
3086
+ * @see http://bpmn.io/license for more information.
2782
3087
  */
2783
3088
  function Logo() {
2784
3089
  return jsxRuntime.jsxs("svg", {
@@ -2817,7 +3122,7 @@ function Lightbox(props) {
2817
3122
  href: "https://bpmn.io",
2818
3123
  target: "_blank",
2819
3124
  rel: "noopener",
2820
- style: "margin: 15px 20px 15px 10px; align-self: center; color: #404040",
3125
+ style: "margin: 15px 20px 15px 10px; align-self: center; color: var(--cds-icon-primary, #404040)",
2821
3126
  children: jsxRuntime.jsx(Logo, {})
2822
3127
  }), jsxRuntime.jsxs("span", {
2823
3128
  children: ["Web-based tooling for BPMN, DMN, and forms powered by ", jsxRuntime.jsx("a", {
@@ -2840,7 +3145,7 @@ function Link(props) {
2840
3145
  rel: "noopener",
2841
3146
  class: "fjs-powered-by-link",
2842
3147
  title: "Powered by bpmn.io",
2843
- style: "color: #404040",
3148
+ style: "color: var(--cds-text-primary, #404040)",
2844
3149
  onClick: props.onClick,
2845
3150
  children: jsxRuntime.jsx(Logo, {})
2846
3151
  })
@@ -2868,8 +3173,12 @@ const noop = () => {};
2868
3173
  function FormComponent(props) {
2869
3174
  const form = useService('form');
2870
3175
  const {
2871
- schema
3176
+ schema,
3177
+ properties
2872
3178
  } = form._getState();
3179
+ const {
3180
+ ariaLabel
3181
+ } = properties;
2873
3182
  const {
2874
3183
  onSubmit = noop,
2875
3184
  onReset = noop,
@@ -2887,6 +3196,7 @@ function FormComponent(props) {
2887
3196
  class: "fjs-form",
2888
3197
  onSubmit: handleSubmit,
2889
3198
  onReset: handleReset,
3199
+ "aria-label": ariaLabel,
2890
3200
  noValidate: true,
2891
3201
  children: [jsxRuntime.jsx(FormField, {
2892
3202
  field: schema,
@@ -2897,7 +3207,7 @@ function FormComponent(props) {
2897
3207
 
2898
3208
  const NODE_TYPE_TEXT = 3,
2899
3209
  NODE_TYPE_ELEMENT = 1;
2900
- const ALLOWED_NODES = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'span', 'em', 'a', 'p', 'div', 'ul', 'ol', 'li', 'hr', 'blockquote', 'img', 'pre', 'code', 'br', 'strong'];
3210
+ 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'];
2901
3211
  const ALLOWED_ATTRIBUTES = ['align', 'alt', 'class', 'href', 'id', 'name', 'rel', 'target', 'src'];
2902
3212
  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
2903
3213
  const ALLOWED_IMAGE_SRC_PATTERN = /^(https?|data):.*/i; // eslint-disable-line no-useless-escape
@@ -2905,11 +3215,11 @@ const ATTR_WHITESPACE_PATTERN = /[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u
2905
3215
 
2906
3216
  const FORM_ELEMENT = document.createElement('form');
2907
3217
 
2908
- /**
2909
- * Sanitize a HTML string and return the cleaned, safe version.
2910
- *
2911
- * @param {string} html
2912
- * @return {string}
3218
+ /**
3219
+ * Sanitize a HTML string and return the cleaned, safe version.
3220
+ *
3221
+ * @param {string} html
3222
+ * @return {string}
2913
3223
  */
2914
3224
 
2915
3225
  // see https://github.com/developit/snarkdown/issues/70
@@ -2927,29 +3237,29 @@ function sanitizeHTML(html) {
2927
3237
  }
2928
3238
  }
2929
3239
 
2930
- /**
2931
- * Sanitizes an image source to ensure we only allow for data URI and links
2932
- * that start with http(s).
2933
- *
2934
- * Note: Most browsers anyway do not support script execution in <img> elements.
2935
- *
2936
- * @param {string} src
2937
- * @returns {string}
3240
+ /**
3241
+ * Sanitizes an image source to ensure we only allow for data URI and links
3242
+ * that start with http(s).
3243
+ *
3244
+ * Note: Most browsers anyway do not support script execution in <img> elements.
3245
+ *
3246
+ * @param {string} src
3247
+ * @returns {string}
2938
3248
  */
2939
3249
  function sanitizeImageSource(src) {
2940
3250
  const valid = ALLOWED_IMAGE_SRC_PATTERN.test(src);
2941
3251
  return valid ? src : '';
2942
3252
  }
2943
3253
 
2944
- /**
2945
- * Recursively sanitize a HTML node, potentially
2946
- * removing it, its children or attributes.
2947
- *
2948
- * Inspired by https://github.com/developit/snarkdown/issues/70
2949
- * and https://github.com/cure53/DOMPurify. Simplified
2950
- * for our use-case.
2951
- *
2952
- * @param {Element} node
3254
+ /**
3255
+ * Recursively sanitize a HTML node, potentially
3256
+ * removing it, its children or attributes.
3257
+ *
3258
+ * Inspired by https://github.com/developit/snarkdown/issues/70
3259
+ * and https://github.com/cure53/DOMPurify. Simplified
3260
+ * for our use-case.
3261
+ *
3262
+ * @param {Element} node
2953
3263
  */
2954
3264
  function sanitizeNode(node) {
2955
3265
  // allow text nodes
@@ -2993,13 +3303,13 @@ function sanitizeNode(node) {
2993
3303
  }
2994
3304
  }
2995
3305
 
2996
- /**
2997
- * Validates attributes for validity.
2998
- *
2999
- * @param {string} lcTag
3000
- * @param {string} lcName
3001
- * @param {string} value
3002
- * @return {boolean}
3306
+ /**
3307
+ * Validates attributes for validity.
3308
+ *
3309
+ * @param {string} lcTag
3310
+ * @param {string} lcName
3311
+ * @param {string} value
3312
+ * @return {boolean}
3003
3313
  */
3004
3314
  function isValidAttribute(lcTag, lcName, value) {
3005
3315
  // disallow most attributes based on whitelist
@@ -3086,13 +3396,15 @@ function Image(props) {
3086
3396
  })
3087
3397
  });
3088
3398
  }
3089
- Image.create = (options = {}) => ({
3090
- ...options
3091
- });
3092
- Image.type = type$7;
3093
- Image.keyed = false;
3094
- Image.label = 'Image view';
3095
- Image.group = 'presentation';
3399
+ Image.config = {
3400
+ type: type$7,
3401
+ keyed: false,
3402
+ label: 'Image view',
3403
+ group: 'presentation',
3404
+ create: (options = {}) => ({
3405
+ ...options
3406
+ })
3407
+ };
3096
3408
 
3097
3409
  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); }
3098
3410
  var AngelDownIcon = (({
@@ -3159,10 +3471,10 @@ function Numberfield(props) {
3159
3471
 
3160
3472
  // checks whether the value currently in the form data is practically different from the one in the input field cache
3161
3473
  // this allows us to guarantee the field always displays valid form data, but without auto-simplifying values like 1.000 to 1
3162
- const cacheValueMatchesState = hooks.useMemo(() => Numberfield.sanitizeValue({
3474
+ const cacheValueMatchesState = hooks.useMemo(() => Numberfield.config.sanitizeValue({
3163
3475
  value,
3164
3476
  formField: field
3165
- }) === Numberfield.sanitizeValue({
3477
+ }) === Numberfield.config.sanitizeValue({
3166
3478
  value: stringValueCache,
3167
3479
  formField: field
3168
3480
  }), [stringValueCache, value, field]);
@@ -3256,6 +3568,7 @@ function Numberfield(props) {
3256
3568
  const {
3257
3569
  formId
3258
3570
  } = hooks.useContext(FormContext$1);
3571
+ const errorMessageId = errors.length === 0 ? undefined : `${prefixId(id, formId)}-error-message`;
3259
3572
  return jsxRuntime.jsxs("div", {
3260
3573
  class: formFieldClasses(type$6, {
3261
3574
  errors,
@@ -3289,7 +3602,8 @@ function Numberfield(props) {
3289
3602
  type: "text",
3290
3603
  autoComplete: "off",
3291
3604
  step: arrowIncrementValue,
3292
- value: displayValue
3605
+ value: displayValue,
3606
+ "aria-describedby": errorMessageId
3293
3607
  }), jsxRuntime.jsxs("div", {
3294
3608
  class: classNames('fjs-number-arrow-container', {
3295
3609
  'fjs-disabled': disabled
@@ -3316,31 +3630,34 @@ function Numberfield(props) {
3316
3630
  }), jsxRuntime.jsx(Description, {
3317
3631
  description: description
3318
3632
  }), jsxRuntime.jsx(Errors, {
3319
- errors: errors
3633
+ errors: errors,
3634
+ id: errorMessageId
3320
3635
  })]
3321
3636
  });
3322
3637
  }
3323
- Numberfield.create = (options = {}) => ({
3324
- ...options
3325
- });
3326
- Numberfield.sanitizeValue = ({
3327
- value,
3328
- formField
3329
- }) => {
3330
- // null state is allowed
3331
- if (isNullEquivalentValue(value)) return null;
3332
-
3333
- // if data cannot be parsed as a valid number, go into invalid NaN state
3334
- if (!isValidNumber(value)) return 'NaN';
3335
-
3336
- // otherwise parse to formatting type
3337
- return formField.serializeToString ? value.toString() : Number(value);
3638
+ Numberfield.config = {
3639
+ type: type$6,
3640
+ keyed: true,
3641
+ label: 'Number',
3642
+ group: 'basic-input',
3643
+ emptyValue: null,
3644
+ sanitizeValue: ({
3645
+ value,
3646
+ formField
3647
+ }) => {
3648
+ // null state is allowed
3649
+ if (isNullEquivalentValue(value)) return null;
3650
+
3651
+ // if data cannot be parsed as a valid number, go into invalid NaN state
3652
+ if (!isValidNumber(value)) return 'NaN';
3653
+
3654
+ // otherwise parse to formatting type
3655
+ return formField.serializeToString ? value.toString() : Number(value);
3656
+ },
3657
+ create: (options = {}) => ({
3658
+ ...options
3659
+ })
3338
3660
  };
3339
- Numberfield.type = type$6;
3340
- Numberfield.keyed = true;
3341
- Numberfield.label = 'Number';
3342
- Numberfield.emptyValue = null;
3343
- Numberfield.group = 'basic-input';
3344
3661
 
3345
3662
  const type$5 = 'radio';
3346
3663
  function Radio(props) {
@@ -3372,6 +3689,7 @@ function Radio(props) {
3372
3689
  const {
3373
3690
  formId
3374
3691
  } = hooks.useContext(FormContext$1);
3692
+ const errorMessageId = errors.length === 0 ? undefined : `${prefixId(id, formId)}-error-message`;
3375
3693
  return jsxRuntime.jsxs("div", {
3376
3694
  class: formFieldClasses(type$5, {
3377
3695
  errors,
@@ -3394,37 +3712,41 @@ function Radio(props) {
3394
3712
  disabled: disabled,
3395
3713
  id: prefixId(`${id}-${index}`, formId),
3396
3714
  type: "radio",
3397
- onClick: () => onChange(option.value)
3715
+ onClick: () => onChange(option.value),
3716
+ "aria-describedby": errorMessageId
3398
3717
  })
3399
3718
  }, `${id}-${index}`);
3400
3719
  }), jsxRuntime.jsx(Description, {
3401
3720
  description: description
3402
3721
  }), jsxRuntime.jsx(Errors, {
3403
- errors: errors
3722
+ errors: errors,
3723
+ id: errorMessageId
3404
3724
  })]
3405
3725
  });
3406
3726
  }
3407
- Radio.create = function (options = {}) {
3408
- const defaults = {};
3409
-
3410
- // provide default values if valuesKey isn't set
3411
- if (!options.valuesKey) {
3412
- defaults.values = [{
3413
- label: 'Value',
3414
- value: 'value'
3415
- }];
3727
+ Radio.config = {
3728
+ type: type$5,
3729
+ keyed: true,
3730
+ label: 'Radio',
3731
+ group: 'selection',
3732
+ emptyValue: null,
3733
+ sanitizeValue: sanitizeSingleSelectValue,
3734
+ create: (options = {}) => {
3735
+ const defaults = {};
3736
+
3737
+ // provide default values if valuesKey isn't set
3738
+ if (!options.valuesKey) {
3739
+ defaults.values = [{
3740
+ label: 'Value',
3741
+ value: 'value'
3742
+ }];
3743
+ }
3744
+ return {
3745
+ ...defaults,
3746
+ ...options
3747
+ };
3416
3748
  }
3417
- return {
3418
- ...defaults,
3419
- ...options
3420
- };
3421
3749
  };
3422
- Radio.type = type$5;
3423
- Radio.label = 'Radio';
3424
- Radio.keyed = true;
3425
- Radio.emptyValue = null;
3426
- Radio.sanitizeValue = sanitizeSingleSelectValue;
3427
- Radio.group = 'selection';
3428
3750
 
3429
3751
  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); }
3430
3752
  var XMarkIcon = (({
@@ -3564,7 +3886,8 @@ function SearchableSelect(props) {
3564
3886
  onBlur: () => {
3565
3887
  setIsDropdownExpanded(false);
3566
3888
  setFilter(valueLabel);
3567
- }
3889
+ },
3890
+ "aria-describedby": props['aria-describedby']
3568
3891
  }), displayState.displayCross && jsxRuntime.jsxs("span", {
3569
3892
  class: "fjs-select-cross",
3570
3893
  onMouseDown: e => {
@@ -3650,14 +3973,20 @@ function SimpleSelect(props) {
3650
3973
  }),
3651
3974
  onFocus: () => setIsDropdownExpanded(true),
3652
3975
  onBlur: () => setIsDropdownExpanded(false),
3653
- onMouseDown: e => onMouseDown(e),
3654
- tabIndex: disabled ? undefined : 0,
3976
+ onMouseDown: onMouseDown,
3655
3977
  children: [jsxRuntime.jsx("div", {
3656
3978
  class: classNames('fjs-select-display', {
3657
3979
  'fjs-select-placeholder': !value
3658
3980
  }),
3659
3981
  id: prefixId(`${id}-display`, formId),
3660
3982
  children: valueLabel || 'Select'
3983
+ }), !disabled && jsxRuntime.jsx("input", {
3984
+ id: prefixId(`${id}-search`, formId),
3985
+ class: "fjs-select-hidden-input",
3986
+ value: valueLabel,
3987
+ onFocus: () => setIsDropdownExpanded(true),
3988
+ onBlur: () => setIsDropdownExpanded(false),
3989
+ "aria-describedby": props['aria-describedby']
3661
3990
  }), displayState.displayCross && jsxRuntime.jsx("span", {
3662
3991
  class: "fjs-select-cross",
3663
3992
  onMouseDown: e => {
@@ -3707,21 +4036,29 @@ function Select(props) {
3707
4036
  const {
3708
4037
  formId
3709
4038
  } = hooks.useContext(FormContext$1);
4039
+ const errorMessageId = errors.length === 0 ? undefined : `${prefixId(id, formId)}-error-message`;
3710
4040
  const selectProps = hooks.useMemo(() => ({
3711
4041
  id,
3712
4042
  disabled,
3713
4043
  errors,
3714
4044
  field,
3715
4045
  value,
3716
- onChange
3717
- }), [disabled, errors, field, id, value, onChange]);
4046
+ onChange,
4047
+ 'aria-describedby': errorMessageId
4048
+ }), [disabled, errors, field, id, value, onChange, errorMessageId]);
3718
4049
  return jsxRuntime.jsxs("div", {
3719
4050
  class: formFieldClasses(type$4, {
3720
4051
  errors,
3721
4052
  disabled
3722
4053
  }),
4054
+ onKeyDown: event => {
4055
+ if (event.key === 'Enter') {
4056
+ event.preventDefault();
4057
+ event.stopPropagation();
4058
+ }
4059
+ },
3723
4060
  children: [jsxRuntime.jsx(Label, {
3724
- id: prefixId(id, formId),
4061
+ id: prefixId(`${id}-search`, formId),
3725
4062
  label: label,
3726
4063
  required: required
3727
4064
  }), searchable ? jsxRuntime.jsx(SearchableSelect, {
@@ -3731,31 +4068,34 @@ function Select(props) {
3731
4068
  }), jsxRuntime.jsx(Description, {
3732
4069
  description: description
3733
4070
  }), jsxRuntime.jsx(Errors, {
3734
- errors: errors
4071
+ errors: errors,
4072
+ id: errorMessageId
3735
4073
  })]
3736
4074
  });
3737
4075
  }
3738
- Select.create = (options = {}) => {
3739
- const defaults = {};
3740
-
3741
- // provide default values if valuesKey isn't set
3742
- if (!options.valuesKey) {
3743
- defaults.values = [{
3744
- label: 'Value',
3745
- value: 'value'
3746
- }];
4076
+ Select.config = {
4077
+ type: type$4,
4078
+ keyed: true,
4079
+ label: 'Select',
4080
+ group: 'selection',
4081
+ emptyValue: null,
4082
+ sanitizeValue: sanitizeSingleSelectValue,
4083
+ create: (options = {}) => {
4084
+ const defaults = {};
4085
+
4086
+ // provide default values if valuesKey isn't set
4087
+ if (!options.valuesKey) {
4088
+ defaults.values = [{
4089
+ label: 'Value',
4090
+ value: 'value'
4091
+ }];
4092
+ }
4093
+ return {
4094
+ ...defaults,
4095
+ ...options
4096
+ };
3747
4097
  }
3748
- return {
3749
- ...defaults,
3750
- ...options
3751
- };
3752
4098
  };
3753
- Select.type = type$4;
3754
- Select.label = 'Select';
3755
- Select.keyed = true;
3756
- Select.emptyValue = null;
3757
- Select.sanitizeValue = sanitizeSingleSelectValue;
3758
- Select.group = 'selection';
3759
4099
 
3760
4100
  const type$3 = 'taglist';
3761
4101
  function Taglist(props) {
@@ -3777,6 +4117,7 @@ function Taglist(props) {
3777
4117
  const {
3778
4118
  formId
3779
4119
  } = hooks.useContext(FormContext$1);
4120
+ const errorMessageId = errors.length === 0 ? undefined : `${prefixId(id, formId)}-error-message`;
3780
4121
  const [filter, setFilter] = hooks.useState('');
3781
4122
  const [filteredOptions, setFilteredOptions] = hooks.useState([]);
3782
4123
  const [isDropdownExpanded, setIsDropdownExpanded] = hooks.useState(false);
@@ -3870,6 +4211,12 @@ function Taglist(props) {
3870
4211
  errors,
3871
4212
  disabled
3872
4213
  }),
4214
+ onKeyDown: event => {
4215
+ if (event.key === 'Enter') {
4216
+ event.stopPropagation();
4217
+ event.preventDefault();
4218
+ }
4219
+ },
3873
4220
  children: [jsxRuntime.jsx(Label, {
3874
4221
  label: label,
3875
4222
  required: required,
@@ -3906,15 +4253,16 @@ function Taglist(props) {
3906
4253
  onChange: onFilterChange,
3907
4254
  type: "text",
3908
4255
  value: filter,
3909
- placeholder: disabled ? '' : 'Search',
4256
+ placeholder: disabled ? undefined : 'Search',
3910
4257
  autoComplete: "off",
3911
- onKeyDown: e => onInputKeyDown(e),
4258
+ onKeyDown: onInputKeyDown,
3912
4259
  onMouseDown: () => setIsEscapeClose(false),
3913
4260
  onFocus: () => setIsDropdownExpanded(true),
3914
4261
  onBlur: () => {
3915
4262
  setIsDropdownExpanded(false);
3916
4263
  setFilter('');
3917
- }
4264
+ },
4265
+ "aria-describedby": errorMessageId
3918
4266
  })]
3919
4267
  }), jsxRuntime.jsx("div", {
3920
4268
  class: "fjs-taglist-anchor",
@@ -3928,34 +4276,41 @@ function Taglist(props) {
3928
4276
  }), jsxRuntime.jsx(Description, {
3929
4277
  description: description
3930
4278
  }), jsxRuntime.jsx(Errors, {
3931
- errors: errors
4279
+ errors: errors,
4280
+ id: errorMessageId
3932
4281
  })]
3933
4282
  });
3934
4283
  }
3935
- Taglist.create = (options = {}) => {
3936
- const defaults = {};
3937
-
3938
- // provide default values if valuesKey isn't set
3939
- if (!options.valuesKey) {
3940
- defaults.values = [{
3941
- label: 'Value',
3942
- value: 'value'
3943
- }];
4284
+ Taglist.config = {
4285
+ type: type$3,
4286
+ keyed: true,
4287
+ label: 'Tag list',
4288
+ group: 'selection',
4289
+ emptyValue: [],
4290
+ sanitizeValue: sanitizeMultiSelectValue,
4291
+ create: (options = {}) => {
4292
+ const defaults = {};
4293
+
4294
+ // provide default values if valuesKey isn't set
4295
+ if (!options.valuesKey) {
4296
+ defaults.values = [{
4297
+ label: 'Value',
4298
+ value: 'value'
4299
+ }];
4300
+ }
4301
+ return {
4302
+ ...defaults,
4303
+ ...options
4304
+ };
3944
4305
  }
3945
- return {
3946
- ...defaults,
3947
- ...options
3948
- };
3949
4306
  };
3950
- Taglist.type = type$3;
3951
- Taglist.label = 'Tag list';
3952
- Taglist.keyed = true;
3953
- Taglist.emptyValue = [];
3954
- Taglist.sanitizeValue = sanitizeMultiSelectValue;
3955
- Taglist.group = 'selection';
3956
4307
 
3957
4308
  const type$2 = 'text';
3958
4309
  function Text(props) {
4310
+ const form = useService('form');
4311
+ const {
4312
+ textLinkTarget
4313
+ } = form._getState().properties;
3959
4314
  const {
3960
4315
  field,
3961
4316
  disableLinks
@@ -3977,9 +4332,20 @@ function Text(props) {
3977
4332
  const html = markdownRenderer.render(markdown);
3978
4333
  return sanitizeHTML(html);
3979
4334
  }, [markdownRenderer, markdown]);
3980
- const componentOverrides = hooks.useMemo(() => disableLinks ? {
3981
- 'a': DisabledLink
3982
- } : {}, [disableLinks]);
4335
+ const OverridenTargetLink = hooks.useMemo(() => BuildOverridenTargetLink(textLinkTarget), [textLinkTarget]);
4336
+ const componentOverrides = hooks.useMemo(() => {
4337
+ if (disableLinks) {
4338
+ return {
4339
+ 'a': DisabledLink
4340
+ };
4341
+ }
4342
+ if (textLinkTarget) {
4343
+ return {
4344
+ 'a': OverridenTargetLink
4345
+ };
4346
+ }
4347
+ return {};
4348
+ }, [disableLinks, OverridenTargetLink, textLinkTarget]);
3983
4349
  return jsxRuntime.jsx("div", {
3984
4350
  class: formFieldClasses(type$2),
3985
4351
  children: jsxRuntime.jsx(Markup, {
@@ -3989,21 +4355,35 @@ function Text(props) {
3989
4355
  })
3990
4356
  });
3991
4357
  }
3992
- Text.create = (options = {}) => ({
3993
- text: '# Text',
3994
- ...options
3995
- });
3996
- Text.type = type$2;
3997
- Text.keyed = false;
3998
- Text.group = 'presentation';
3999
- Text.label = 'Text view';
4358
+ Text.config = {
4359
+ type: type$2,
4360
+ keyed: false,
4361
+ label: 'Text view',
4362
+ group: 'presentation',
4363
+ create: (options = {}) => ({
4364
+ text: '# Text',
4365
+ ...options
4366
+ })
4367
+ };
4368
+ function BuildOverridenTargetLink(target) {
4369
+ return function ({
4370
+ children,
4371
+ ...rest
4372
+ }) {
4373
+ return jsxRuntime.jsx("a", {
4374
+ ...rest,
4375
+ target: target,
4376
+ children: children
4377
+ });
4378
+ };
4379
+ }
4000
4380
  function DisabledLink({
4001
- href,
4002
- children
4381
+ children,
4382
+ ...rest
4003
4383
  }) {
4004
4384
  return jsxRuntime.jsx("a", {
4385
+ ...rest,
4005
4386
  class: "fjs-disabled-link",
4006
- href: href,
4007
4387
  tabIndex: -1,
4008
4388
  children: children
4009
4389
  });
@@ -4042,6 +4422,7 @@ function Textfield(props) {
4042
4422
  const {
4043
4423
  formId
4044
4424
  } = hooks.useContext(FormContext$1);
4425
+ const errorMessageId = errors.length === 0 ? undefined : `${prefixId(id, formId)}-error-message`;
4045
4426
  return jsxRuntime.jsxs("div", {
4046
4427
  class: formFieldClasses(type$1, {
4047
4428
  errors,
@@ -4061,26 +4442,40 @@ function Textfield(props) {
4061
4442
  id: prefixId(id, formId),
4062
4443
  onInput: onChange,
4063
4444
  type: "text",
4064
- value: value
4445
+ value: value,
4446
+ "aria-describedby": errorMessageId
4065
4447
  })
4066
4448
  }), jsxRuntime.jsx(Description, {
4067
4449
  description: description
4068
4450
  }), jsxRuntime.jsx(Errors, {
4069
- errors: errors
4451
+ errors: errors,
4452
+ id: errorMessageId
4070
4453
  })]
4071
4454
  });
4072
4455
  }
4073
- Textfield.create = (options = {}) => ({
4074
- ...options
4075
- });
4076
- Textfield.type = type$1;
4077
- Textfield.label = 'Text field';
4078
- Textfield.keyed = true;
4079
- Textfield.emptyValue = '';
4080
- Textfield.sanitizeValue = ({
4081
- value
4082
- }) => minDash.isArray(value) || minDash.isObject(value) ? '' : String(value);
4083
- Textfield.group = 'basic-input';
4456
+ Textfield.config = {
4457
+ type: type$1,
4458
+ keyed: true,
4459
+ label: 'Text field',
4460
+ group: 'basic-input',
4461
+ emptyValue: '',
4462
+ sanitizeValue: ({
4463
+ value
4464
+ }) => {
4465
+ if (minDash.isArray(value) || minDash.isObject(value)) {
4466
+ return '';
4467
+ }
4468
+
4469
+ // sanitize newlines to spaces
4470
+ if (typeof value === 'string') {
4471
+ return value.replace(/[\r\n\t]/g, ' ');
4472
+ }
4473
+ return String(value);
4474
+ },
4475
+ create: (options = {}) => ({
4476
+ ...options
4477
+ })
4478
+ };
4084
4479
 
4085
4480
  const type = 'textarea';
4086
4481
  function Textarea(props) {
@@ -4127,6 +4522,7 @@ function Textarea(props) {
4127
4522
  const {
4128
4523
  formId
4129
4524
  } = hooks.useContext(FormContext$1);
4525
+ const errorMessageId = errors.length === 0 ? undefined : `${prefixId(id, formId)}-error-message`;
4130
4526
  return jsxRuntime.jsxs("div", {
4131
4527
  class: formFieldClasses(type, {
4132
4528
  errors,
@@ -4142,25 +4538,29 @@ function Textarea(props) {
4142
4538
  id: prefixId(id, formId),
4143
4539
  onInput: onInput,
4144
4540
  value: value,
4145
- ref: textareaRef
4541
+ ref: textareaRef,
4542
+ "aria-describedby": errorMessageId
4146
4543
  }), jsxRuntime.jsx(Description, {
4147
4544
  description: description
4148
4545
  }), jsxRuntime.jsx(Errors, {
4149
- errors: errors
4546
+ errors: errors,
4547
+ id: errorMessageId
4150
4548
  })]
4151
4549
  });
4152
4550
  }
4153
- Textarea.create = (options = {}) => ({
4154
- ...options
4155
- });
4156
- Textarea.type = type;
4157
- Textarea.label = 'Text area';
4158
- Textarea.keyed = true;
4159
- Textarea.emptyValue = '';
4160
- Textarea.sanitizeValue = ({
4161
- value
4162
- }) => minDash.isArray(value) || minDash.isObject(value) ? '' : String(value);
4163
- Textarea.group = 'basic-input';
4551
+ Textarea.config = {
4552
+ type,
4553
+ keyed: true,
4554
+ label: 'Text area',
4555
+ group: 'basic-input',
4556
+ emptyValue: '',
4557
+ sanitizeValue: ({
4558
+ value
4559
+ }) => minDash.isArray(value) || minDash.isObject(value) ? '' : String(value),
4560
+ create: (options = {}) => ({
4561
+ ...options
4562
+ })
4563
+ };
4164
4564
 
4165
4565
  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); }
4166
4566
  var ButtonIcon = (({
@@ -4169,10 +4569,11 @@ var ButtonIcon = (({
4169
4569
  }) => /*#__PURE__*/React.createElement("svg", _extends$d({
4170
4570
  xmlns: "http://www.w3.org/2000/svg",
4171
4571
  width: "54",
4172
- height: "54"
4572
+ height: "54",
4573
+ fill: "currentcolor"
4173
4574
  }, props), /*#__PURE__*/React.createElement("path", {
4174
4575
  fillRule: "evenodd",
4175
- 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"
4576
+ 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"
4176
4577
  })));
4177
4578
 
4178
4579
  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); }
@@ -4182,7 +4583,8 @@ var CheckboxIcon = (({
4182
4583
  }) => /*#__PURE__*/React.createElement("svg", _extends$c({
4183
4584
  xmlns: "http://www.w3.org/2000/svg",
4184
4585
  width: "54",
4185
- height: "54"
4586
+ height: "54",
4587
+ fill: "currentcolor"
4186
4588
  }, props), /*#__PURE__*/React.createElement("path", {
4187
4589
  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"
4188
4590
  })));
@@ -4193,18 +4595,35 @@ var ChecklistIcon = (({
4193
4595
  ...props
4194
4596
  }) => /*#__PURE__*/React.createElement("svg", _extends$b({
4195
4597
  xmlns: "http://www.w3.org/2000/svg",
4598
+ xmlnsXlink: "http://www.w3.org/1999/xlink",
4196
4599
  width: "54",
4197
4600
  height: "54",
4198
- fill: "none"
4199
- }, props), /*#__PURE__*/React.createElement("path", {
4200
- fillRule: "evenodd",
4201
- clipRule: "evenodd",
4202
- 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",
4203
- fill: "#161616"
4601
+ fill: "currentcolor"
4602
+ }, props), /*#__PURE__*/React.createElement("g", {
4603
+ fillRule: "evenodd"
4604
+ }, /*#__PURE__*/React.createElement("use", {
4605
+ xlinkHref: "#a"
4606
+ }), /*#__PURE__*/React.createElement("use", {
4607
+ xlinkHref: "#a",
4608
+ y: "24"
4609
+ }), /*#__PURE__*/React.createElement("use", {
4610
+ xlinkHref: "#a",
4611
+ y: "12"
4612
+ })), /*#__PURE__*/React.createElement("use", {
4613
+ xlinkHref: "#b"
4614
+ }), /*#__PURE__*/React.createElement("use", {
4615
+ xlinkHref: "#b",
4616
+ y: "12"
4617
+ }), /*#__PURE__*/React.createElement("use", {
4618
+ xlinkHref: "#b",
4619
+ y: "24"
4620
+ }), /*#__PURE__*/React.createElement("defs", null, /*#__PURE__*/React.createElement("path", {
4621
+ id: "a",
4622
+ 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"
4204
4623
  }), /*#__PURE__*/React.createElement("path", {
4205
- 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",
4206
- fill: "#161616"
4207
- })));
4624
+ id: "b",
4625
+ d: "M23 14.5a1 1 0 011-1h19a1 1 0 011 1v1a1 1 0 01-1 1H24a1 1 0 01-1-1v-1z"
4626
+ }))));
4208
4627
 
4209
4628
  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); }
4210
4629
  var DatetimeIcon = (({
@@ -4214,20 +4633,15 @@ var DatetimeIcon = (({
4214
4633
  xmlns: "http://www.w3.org/2000/svg",
4215
4634
  width: "54",
4216
4635
  height: "54",
4217
- fill: "none"
4636
+ fill: "currentcolor"
4218
4637
  }, props), /*#__PURE__*/React.createElement("path", {
4219
- fill: "#000",
4220
4638
  fillRule: "evenodd",
4221
- 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",
4222
- clipRule: "evenodd"
4639
+ 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"
4223
4640
  }), /*#__PURE__*/React.createElement("path", {
4224
- fill: "#000",
4225
4641
  d: "M35.13 37.603l1.237-1.237-3.468-3.475v-5.926h-1.754v6.654l3.984 3.984z"
4226
4642
  }), /*#__PURE__*/React.createElement("path", {
4227
- fill: "#000",
4228
4643
  fillRule: "evenodd",
4229
- 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",
4230
- clipRule: "evenodd"
4644
+ 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"
4231
4645
  })));
4232
4646
 
4233
4647
  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); }
@@ -4235,18 +4649,15 @@ var TaglistIcon = (({
4235
4649
  styles = {},
4236
4650
  ...props
4237
4651
  }) => /*#__PURE__*/React.createElement("svg", _extends$9({
4652
+ xmlns: "http://www.w3.org/2000/svg",
4238
4653
  width: "54",
4239
4654
  height: "54",
4240
- fill: "none",
4241
- xmlns: "http://www.w3.org/2000/svg"
4655
+ fill: "currentcolor"
4242
4656
  }, props), /*#__PURE__*/React.createElement("path", {
4243
4657
  fillRule: "evenodd",
4244
- clipRule: "evenodd",
4245
- 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",
4246
- fill: "#000"
4658
+ 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"
4247
4659
  }), /*#__PURE__*/React.createElement("path", {
4248
- d: "M11 22a1 1 0 011-1h19a1 1 0 011 1v10a1 1 0 01-1 1H12a1 1 0 01-1-1V22z",
4249
- fill: "#505562"
4660
+ d: "M11 22a1 1 0 011-1h19a1 1 0 011 1v10a1 1 0 01-1 1H12a1 1 0 01-1-1V22z"
4250
4661
  })));
4251
4662
 
4252
4663
  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); }
@@ -4258,22 +4669,22 @@ var FormIcon = (({
4258
4669
  width: "54",
4259
4670
  height: "54"
4260
4671
  }, props), /*#__PURE__*/React.createElement("rect", {
4261
- x: "15",
4262
- y: "17",
4263
4672
  width: "24",
4264
4673
  height: "4",
4674
+ x: "15",
4675
+ y: "17",
4265
4676
  rx: "1"
4266
4677
  }), /*#__PURE__*/React.createElement("rect", {
4267
- x: "15",
4268
- y: "25",
4269
4678
  width: "24",
4270
4679
  height: "4",
4680
+ x: "15",
4681
+ y: "25",
4271
4682
  rx: "1"
4272
4683
  }), /*#__PURE__*/React.createElement("rect", {
4273
- x: "15",
4274
- y: "33",
4275
4684
  width: "13",
4276
4685
  height: "4",
4686
+ x: "15",
4687
+ y: "33",
4277
4688
  rx: "1"
4278
4689
  })));
4279
4690
 
@@ -4297,7 +4708,8 @@ var NumberIcon = (({
4297
4708
  }) => /*#__PURE__*/React.createElement("svg", _extends$6({
4298
4709
  xmlns: "http://www.w3.org/2000/svg",
4299
4710
  width: "54",
4300
- height: "54"
4711
+ height: "54",
4712
+ fill: "currentcolor"
4301
4713
  }, props), /*#__PURE__*/React.createElement("path", {
4302
4714
  fillRule: "evenodd",
4303
4715
  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"
@@ -4310,9 +4722,10 @@ var RadioIcon = (({
4310
4722
  }) => /*#__PURE__*/React.createElement("svg", _extends$5({
4311
4723
  xmlns: "http://www.w3.org/2000/svg",
4312
4724
  width: "54",
4313
- height: "54"
4725
+ height: "54",
4726
+ fill: "currentcolor"
4314
4727
  }, props), /*#__PURE__*/React.createElement("path", {
4315
- 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"
4728
+ 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"
4316
4729
  })));
4317
4730
 
4318
4731
  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); }
@@ -4322,7 +4735,8 @@ var SelectIcon = (({
4322
4735
  }) => /*#__PURE__*/React.createElement("svg", _extends$4({
4323
4736
  xmlns: "http://www.w3.org/2000/svg",
4324
4737
  width: "54",
4325
- height: "54"
4738
+ height: "54",
4739
+ fill: "currentcolor"
4326
4740
  }, props), /*#__PURE__*/React.createElement("path", {
4327
4741
  fillRule: "evenodd",
4328
4742
  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"
@@ -4335,9 +4749,10 @@ var TextIcon = (({
4335
4749
  }) => /*#__PURE__*/React.createElement("svg", _extends$3({
4336
4750
  xmlns: "http://www.w3.org/2000/svg",
4337
4751
  width: "54",
4338
- height: "54"
4752
+ height: "54",
4753
+ fill: "currentcolor"
4339
4754
  }, props), /*#__PURE__*/React.createElement("path", {
4340
- 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"
4755
+ 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"
4341
4756
  })));
4342
4757
 
4343
4758
  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); }
@@ -4347,7 +4762,8 @@ var TextfieldIcon = (({
4347
4762
  }) => /*#__PURE__*/React.createElement("svg", _extends$2({
4348
4763
  xmlns: "http://www.w3.org/2000/svg",
4349
4764
  width: "54",
4350
- height: "54"
4765
+ height: "54",
4766
+ fill: "currentcolor"
4351
4767
  }, props), /*#__PURE__*/React.createElement("path", {
4352
4768
  fillRule: "evenodd",
4353
4769
  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"
@@ -4360,10 +4776,11 @@ var TextareaIcon = (({
4360
4776
  }) => /*#__PURE__*/React.createElement("svg", _extends$1({
4361
4777
  xmlns: "http://www.w3.org/2000/svg",
4362
4778
  width: "54",
4363
- height: "54"
4779
+ height: "54",
4780
+ fill: "currentcolor"
4364
4781
  }, props), /*#__PURE__*/React.createElement("path", {
4365
4782
  fillRule: "evenodd",
4366
- 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"
4783
+ 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"
4367
4784
  })));
4368
4785
 
4369
4786
  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); }
@@ -4371,20 +4788,18 @@ var ImageIcon = (({
4371
4788
  styles = {},
4372
4789
  ...props
4373
4790
  }) => /*#__PURE__*/React.createElement("svg", _extends({
4791
+ xmlns: "http://www.w3.org/2000/svg",
4374
4792
  width: "54",
4375
4793
  height: "54",
4376
- fill: "none",
4377
- xmlns: "http://www.w3.org/2000/svg"
4794
+ fill: "currentcolor"
4378
4795
  }, props), /*#__PURE__*/React.createElement("path", {
4379
4796
  fillRule: "evenodd",
4380
- clipRule: "evenodd",
4381
4797
  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",
4382
- fill: "#000"
4798
+ clipRule: "evenodd"
4383
4799
  }), /*#__PURE__*/React.createElement("path", {
4384
4800
  fillRule: "evenodd",
4385
- clipRule: "evenodd",
4386
- 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",
4387
- fill: "#000"
4801
+ 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",
4802
+ clipRule: "evenodd"
4388
4803
  })));
4389
4804
 
4390
4805
  const iconsByType = type => {
@@ -4412,7 +4827,7 @@ class FormFields {
4412
4827
  constructor() {
4413
4828
  this._formFields = {};
4414
4829
  formFields.forEach(formField => {
4415
- this.register(formField.type, formField);
4830
+ this.register(formField.config.type, formField);
4416
4831
  });
4417
4832
  }
4418
4833
  register(type, formField) {