@bpmn-io/form-js-viewer 0.9.8 → 0.10.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 (48) hide show
  1. package/README.md +6 -0
  2. package/dist/assets/form-js.css +13 -5
  3. package/dist/index.cjs +318 -427
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.es.js +317 -427
  6. package/dist/index.es.js.map +1 -1
  7. package/dist/types/Form.d.ts +140 -136
  8. package/dist/types/core/EventBus.d.ts +1 -1
  9. package/dist/types/core/FormFieldRegistry.d.ts +17 -17
  10. package/dist/types/core/Validator.d.ts +7 -7
  11. package/dist/types/core/index.d.ts +16 -16
  12. package/dist/types/import/Importer.d.ts +43 -43
  13. package/dist/types/import/index.d.ts +5 -5
  14. package/dist/types/index.d.ts +18 -18
  15. package/dist/types/render/FormFields.d.ts +5 -5
  16. package/dist/types/render/Renderer.d.ts +23 -23
  17. package/dist/types/render/components/Description.d.ts +1 -1
  18. package/dist/types/render/components/Errors.d.ts +1 -1
  19. package/dist/types/render/components/FormComponent.d.ts +1 -1
  20. package/dist/types/render/components/FormField.d.ts +1 -1
  21. package/dist/types/render/components/Label.d.ts +1 -1
  22. package/dist/types/render/components/PoweredBy.d.ts +1 -1
  23. package/dist/types/render/components/Sanitizer.d.ts +7 -7
  24. package/dist/types/render/components/Util.d.ts +9 -6
  25. package/dist/types/render/components/form-fields/Button.d.ts +11 -11
  26. package/dist/types/render/components/form-fields/Checkbox.d.ts +13 -13
  27. package/dist/types/render/components/form-fields/Checklist.d.ts +12 -12
  28. package/dist/types/render/components/form-fields/Default.d.ts +9 -9
  29. package/dist/types/render/components/form-fields/Number.d.ts +13 -13
  30. package/dist/types/render/components/form-fields/Radio.d.ts +12 -12
  31. package/dist/types/render/components/form-fields/Select.d.ts +12 -12
  32. package/dist/types/render/components/form-fields/Taglist.d.ts +12 -12
  33. package/dist/types/render/components/form-fields/Text.d.ts +10 -10
  34. package/dist/types/render/components/form-fields/Textarea.d.ts +13 -0
  35. package/dist/types/render/components/form-fields/Textfield.d.ts +13 -13
  36. package/dist/types/render/components/form-fields/parts/DropdownList.d.ts +1 -1
  37. package/dist/types/render/components/index.d.ts +14 -13
  38. package/dist/types/render/context/FormContext.d.ts +12 -12
  39. package/dist/types/render/context/FormRenderContext.d.ts +6 -6
  40. package/dist/types/render/context/index.d.ts +2 -2
  41. package/dist/types/render/hooks/useKeyDownAction.d.ts +1 -1
  42. package/dist/types/render/hooks/useService.d.ts +1 -1
  43. package/dist/types/render/hooks/useValuesAsync.d.ts +28 -28
  44. package/dist/types/render/index.d.ts +11 -11
  45. package/dist/types/util/form.d.ts +6 -6
  46. package/dist/types/util/index.d.ts +24 -24
  47. package/dist/types/util/injector.d.ts +2 -2
  48. package/package.json +2 -2
package/dist/index.cjs CHANGED
@@ -5,11 +5,11 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  var Ids = require('ids');
6
6
  var minDash = require('min-dash');
7
7
  var snarkdown = require('@bpmn-io/snarkdown');
8
+ var classNames = require('classnames');
8
9
  var jsxRuntime = require('preact/jsx-runtime');
9
10
  var hooks = require('preact/hooks');
10
11
  var preact = require('preact');
11
12
  var React = require('preact/compat');
12
- var classNames = require('classnames');
13
13
  var Markup = require('preact-markup');
14
14
  var didi = require('didi');
15
15
 
@@ -17,13 +17,14 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau
17
17
 
18
18
  var Ids__default = /*#__PURE__*/_interopDefaultLegacy(Ids);
19
19
  var snarkdown__default = /*#__PURE__*/_interopDefaultLegacy(snarkdown);
20
- var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
21
20
  var classNames__default = /*#__PURE__*/_interopDefaultLegacy(classNames);
21
+ var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
22
22
  var Markup__default = /*#__PURE__*/_interopDefaultLegacy(Markup);
23
23
 
24
24
  var FN_REF = '__fn';
25
25
  var DEFAULT_PRIORITY = 1000;
26
26
  var slice = Array.prototype.slice;
27
+
27
28
  /**
28
29
  * A general purpose event bus.
29
30
  *
@@ -107,13 +108,14 @@ var slice = Array.prototype.slice;
107
108
  * console.log(sum); // 3
108
109
  * ```
109
110
  */
110
-
111
111
  function EventBus() {
112
- this._listeners = {}; // cleanup on destroy on lowest priority to allow
113
- // message passing until the bitter end
112
+ this._listeners = {};
114
113
 
114
+ // cleanup on destroy on lowest priority to allow
115
+ // message passing until the bitter end
115
116
  this.on('diagram.destroy', 1, this._destroy, this);
116
117
  }
118
+
117
119
  /**
118
120
  * Register an event listener for events with the given name.
119
121
  *
@@ -131,30 +133,25 @@ function EventBus() {
131
133
  * @param {Function} callback
132
134
  * @param {Object} [that] Pass context (`this`) to the callback
133
135
  */
134
-
135
136
  EventBus.prototype.on = function (events, priority, callback, that) {
136
137
  events = minDash.isArray(events) ? events : [events];
137
-
138
138
  if (minDash.isFunction(priority)) {
139
139
  that = callback;
140
140
  callback = priority;
141
141
  priority = DEFAULT_PRIORITY;
142
142
  }
143
-
144
143
  if (!minDash.isNumber(priority)) {
145
144
  throw new Error('priority must be a number');
146
145
  }
147
-
148
146
  var actualCallback = callback;
149
-
150
147
  if (that) {
151
- actualCallback = minDash.bind(callback, that); // make sure we remember and are able to remove
148
+ actualCallback = minDash.bind(callback, that);
149
+
150
+ // make sure we remember and are able to remove
152
151
  // bound callbacks via {@link #off} using the original
153
152
  // callback
154
-
155
153
  actualCallback[FN_REF] = callback[FN_REF] || callback;
156
154
  }
157
-
158
155
  var self = this;
159
156
  events.forEach(function (e) {
160
157
  self._addListener(e, {
@@ -164,6 +161,7 @@ EventBus.prototype.on = function (events, priority, callback, that) {
164
161
  });
165
162
  });
166
163
  };
164
+
167
165
  /**
168
166
  * Register an event listener that is executed only once.
169
167
  *
@@ -172,34 +170,30 @@ EventBus.prototype.on = function (events, priority, callback, that) {
172
170
  * @param {Function} callback the callback to execute
173
171
  * @param {Object} [that] Pass context (`this`) to the callback
174
172
  */
175
-
176
-
177
173
  EventBus.prototype.once = function (event, priority, callback, that) {
178
174
  var self = this;
179
-
180
175
  if (minDash.isFunction(priority)) {
181
176
  that = callback;
182
177
  callback = priority;
183
178
  priority = DEFAULT_PRIORITY;
184
179
  }
185
-
186
180
  if (!minDash.isNumber(priority)) {
187
181
  throw new Error('priority must be a number');
188
182
  }
189
-
190
183
  function wrappedCallback() {
191
184
  wrappedCallback.__isTomb = true;
192
185
  var result = callback.apply(that, arguments);
193
186
  self.off(event, wrappedCallback);
194
187
  return result;
195
- } // make sure we remember and are able to remove
188
+ }
189
+
190
+ // make sure we remember and are able to remove
196
191
  // bound callbacks via {@link #off} using the original
197
192
  // callback
198
-
199
-
200
193
  wrappedCallback[FN_REF] = callback;
201
194
  this.on(event, priority, wrappedCallback);
202
195
  };
196
+
203
197
  /**
204
198
  * Removes event listeners by event and callback.
205
199
  *
@@ -208,8 +202,6 @@ EventBus.prototype.once = function (event, priority, callback, that) {
208
202
  * @param {string|Array<string>} events
209
203
  * @param {Function} [callback]
210
204
  */
211
-
212
-
213
205
  EventBus.prototype.off = function (events, callback) {
214
206
  events = minDash.isArray(events) ? events : [events];
215
207
  var self = this;
@@ -217,6 +209,7 @@ EventBus.prototype.off = function (events, callback) {
217
209
  self._removeListener(event, callback);
218
210
  });
219
211
  };
212
+
220
213
  /**
221
214
  * Create an EventBus event.
222
215
  *
@@ -224,13 +217,12 @@ EventBus.prototype.off = function (events, callback) {
224
217
  *
225
218
  * @return {Object} event, recognized by the eventBus
226
219
  */
227
-
228
-
229
220
  EventBus.prototype.createEvent = function (data) {
230
221
  var event = new InternalEvent();
231
222
  event.init(data);
232
223
  return event;
233
224
  };
225
+
234
226
  /**
235
227
  * Fires a named event.
236
228
  *
@@ -261,45 +253,40 @@ EventBus.prototype.createEvent = function (data) {
261
253
  * @return {boolean} the events return value, if specified or false if the
262
254
  * default action was prevented by listeners
263
255
  */
264
-
265
-
266
256
  EventBus.prototype.fire = function (type, data) {
267
257
  var event, firstListener, returnValue, args;
268
258
  args = slice.call(arguments);
269
-
270
259
  if (typeof type === 'object') {
271
260
  data = type;
272
261
  type = data.type;
273
262
  }
274
-
275
263
  if (!type) {
276
264
  throw new Error('no event type specified');
277
265
  }
278
-
279
266
  firstListener = this._listeners[type];
280
-
281
267
  if (!firstListener) {
282
268
  return;
283
- } // we make sure we fire instances of our home made
284
- // events here. We wrap them only once, though
285
-
269
+ }
286
270
 
271
+ // we make sure we fire instances of our home made
272
+ // events here. We wrap them only once, though
287
273
  if (data instanceof InternalEvent) {
288
274
  // we are fine, we alread have an event
289
275
  event = data;
290
276
  } else {
291
277
  event = this.createEvent(data);
292
- } // ensure we pass the event as the first parameter
293
-
278
+ }
294
279
 
295
- args[0] = event; // original event type (in case we delegate)
280
+ // ensure we pass the event as the first parameter
281
+ args[0] = event;
296
282
 
297
- var originalType = event.type; // update event type before delegation
283
+ // original event type (in case we delegate)
284
+ var originalType = event.type;
298
285
 
286
+ // update event type before delegation
299
287
  if (type !== originalType) {
300
288
  event.type = type;
301
289
  }
302
-
303
290
  try {
304
291
  returnValue = this._invokeListeners(event, args, firstListener);
305
292
  } finally {
@@ -307,60 +294,51 @@ EventBus.prototype.fire = function (type, data) {
307
294
  if (type !== originalType) {
308
295
  event.type = originalType;
309
296
  }
310
- } // set the return value to false if the event default
311
- // got prevented and no other return value exists
312
-
297
+ }
313
298
 
299
+ // set the return value to false if the event default
300
+ // got prevented and no other return value exists
314
301
  if (returnValue === undefined && event.defaultPrevented) {
315
302
  returnValue = false;
316
303
  }
317
-
318
304
  return returnValue;
319
305
  };
320
-
321
306
  EventBus.prototype.handleError = function (error) {
322
307
  return this.fire('error', {
323
308
  error: error
324
309
  }) === false;
325
310
  };
326
-
327
311
  EventBus.prototype._destroy = function () {
328
312
  this._listeners = {};
329
313
  };
330
-
331
314
  EventBus.prototype._invokeListeners = function (event, args, listener) {
332
315
  var returnValue;
333
-
334
316
  while (listener) {
335
317
  // handle stopped propagation
336
318
  if (event.cancelBubble) {
337
319
  break;
338
320
  }
339
-
340
321
  returnValue = this._invokeListener(event, args, listener);
341
322
  listener = listener.next;
342
323
  }
343
-
344
324
  return returnValue;
345
325
  };
346
-
347
326
  EventBus.prototype._invokeListener = function (event, args, listener) {
348
327
  var returnValue;
349
-
350
328
  if (listener.callback.__isTomb) {
351
329
  return returnValue;
352
330
  }
353
-
354
331
  try {
355
332
  // returning false prevents the default action
356
- returnValue = invokeFunction(listener.callback, args); // stop propagation on return value
333
+ returnValue = invokeFunction(listener.callback, args);
357
334
 
335
+ // stop propagation on return value
358
336
  if (returnValue !== undefined) {
359
337
  event.returnValue = returnValue;
360
338
  event.stopPropagation();
361
- } // prevent default on return false
362
-
339
+ }
363
340
 
341
+ // prevent default on return false
364
342
  if (returnValue === false) {
365
343
  event.preventDefault();
366
344
  }
@@ -370,9 +348,9 @@ EventBus.prototype._invokeListener = function (event, args, listener) {
370
348
  throw error;
371
349
  }
372
350
  }
373
-
374
351
  return returnValue;
375
352
  };
353
+
376
354
  /*
377
355
  * Add new listener with a certain priority to the list
378
356
  * of listeners (for the given event).
@@ -389,67 +367,54 @@ EventBus.prototype._invokeListener = function (event, args, listener) {
389
367
  * @param {string} event
390
368
  * @param {Object} listener { priority, callback }
391
369
  */
392
-
393
-
394
370
  EventBus.prototype._addListener = function (event, newListener) {
395
371
  var listener = this._getListeners(event),
396
- previousListener; // no prior listeners
397
-
372
+ previousListener;
398
373
 
374
+ // no prior listeners
399
375
  if (!listener) {
400
376
  this._setListeners(event, newListener);
401
-
402
377
  return;
403
- } // ensure we order listeners by priority from
404
- // 0 (high) to n > 0 (low)
405
-
378
+ }
406
379
 
380
+ // ensure we order listeners by priority from
381
+ // 0 (high) to n > 0 (low)
407
382
  while (listener) {
408
383
  if (listener.priority < newListener.priority) {
409
384
  newListener.next = listener;
410
-
411
385
  if (previousListener) {
412
386
  previousListener.next = newListener;
413
387
  } else {
414
388
  this._setListeners(event, newListener);
415
389
  }
416
-
417
390
  return;
418
391
  }
419
-
420
392
  previousListener = listener;
421
393
  listener = listener.next;
422
- } // add new listener to back
423
-
394
+ }
424
395
 
396
+ // add new listener to back
425
397
  previousListener.next = newListener;
426
398
  };
427
-
428
399
  EventBus.prototype._getListeners = function (name) {
429
400
  return this._listeners[name];
430
401
  };
431
-
432
402
  EventBus.prototype._setListeners = function (name, listener) {
433
403
  this._listeners[name] = listener;
434
404
  };
435
-
436
405
  EventBus.prototype._removeListener = function (event, callback) {
437
406
  var listener = this._getListeners(event),
438
- nextListener,
439
- previousListener,
440
- listenerCallback;
441
-
407
+ nextListener,
408
+ previousListener,
409
+ listenerCallback;
442
410
  if (!callback) {
443
411
  // clear listeners
444
412
  this._setListeners(event, null);
445
-
446
413
  return;
447
414
  }
448
-
449
415
  while (listener) {
450
416
  nextListener = listener.next;
451
417
  listenerCallback = listener.callback;
452
-
453
418
  if (listenerCallback === callback || listenerCallback[FN_REF] === callback) {
454
419
  if (previousListener) {
455
420
  previousListener.next = nextListener;
@@ -458,29 +423,25 @@ EventBus.prototype._removeListener = function (event, callback) {
458
423
  this._setListeners(event, nextListener);
459
424
  }
460
425
  }
461
-
462
426
  previousListener = listener;
463
427
  listener = nextListener;
464
428
  }
465
429
  };
430
+
466
431
  /**
467
432
  * A event that is emitted via the event bus.
468
433
  */
469
-
470
-
471
434
  function InternalEvent() {}
472
-
473
435
  InternalEvent.prototype.stopPropagation = function () {
474
436
  this.cancelBubble = true;
475
437
  };
476
-
477
438
  InternalEvent.prototype.preventDefault = function () {
478
439
  this.defaultPrevented = true;
479
440
  };
480
-
481
441
  InternalEvent.prototype.init = function (data) {
482
442
  minDash.assign(this, data || {});
483
443
  };
444
+
484
445
  /**
485
446
  * Invoke function. Be fast...
486
447
  *
@@ -489,50 +450,47 @@ InternalEvent.prototype.init = function (data) {
489
450
  *
490
451
  * @return {Any}
491
452
  */
492
-
493
-
494
453
  function invokeFunction(fn, args) {
495
454
  return fn.apply(null, args);
496
455
  }
497
456
 
457
+ const EMAIL_PATTERN = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
458
+ const PHONE_PATTERN = /(\+|00)(297|93|244|1264|358|355|376|971|54|374|1684|1268|61|43|994|257|32|229|226|880|359|973|1242|387|590|375|501|1441|591|55|1246|673|975|267|236|1|61|41|56|86|225|237|243|242|682|57|269|238|506|53|5999|61|1345|357|420|49|253|1767|45|1809|1829|1849|213|593|20|291|212|34|372|251|358|679|500|33|298|691|241|44|995|44|233|350|224|590|220|245|240|30|1473|299|502|594|1671|592|852|504|385|509|36|62|44|91|246|353|98|964|354|972|39|1876|44|962|81|76|77|254|996|855|686|1869|82|383|965|856|961|231|218|1758|423|94|266|370|352|371|853|590|212|377|373|261|960|52|692|389|223|356|95|382|976|1670|258|222|1664|596|230|265|60|262|264|687|227|672|234|505|683|31|47|977|674|64|968|92|507|64|51|63|680|675|48|1787|1939|850|351|595|970|689|974|262|40|7|250|966|249|221|65|500|4779|677|232|503|378|252|508|381|211|239|597|421|386|46|268|1721|248|963|1649|235|228|66|992|690|993|670|676|1868|216|90|688|886|255|256|380|598|1|998|3906698|379|1784|58|1284|1340|84|678|681|685|967|27|260|263)(9[976]\d|8[987530]\d|6[987]\d|5[90]\d|42\d|3[875]\d|2[98654321]\d|9[8543210]|8[6421]|6[6543210]|5[87654321]|4[987654310]|3[9643210]|2[70]|7|1)\d{4,20}$/;
498
459
  class Validator {
499
460
  validateField(field, value) {
500
461
  const {
501
462
  validate
502
463
  } = field;
503
464
  let errors = [];
504
-
505
465
  if (!validate) {
506
466
  return errors;
507
467
  }
508
-
509
468
  if (validate.pattern && value && !new RegExp(validate.pattern).test(value)) {
510
469
  errors = [...errors, `Field must match pattern ${validate.pattern}.`];
511
470
  }
512
-
513
471
  if (validate.required && (minDash.isNil(value) || value === '')) {
514
472
  errors = [...errors, 'Field is required.'];
515
473
  }
516
-
517
474
  if ('min' in validate && value && value < validate.min) {
518
475
  errors = [...errors, `Field must have minimum value of ${validate.min}.`];
519
476
  }
520
-
521
477
  if ('max' in validate && value && value > validate.max) {
522
478
  errors = [...errors, `Field must have maximum value of ${validate.max}.`];
523
479
  }
524
-
525
480
  if ('minLength' in validate && value && value.trim().length < validate.minLength) {
526
481
  errors = [...errors, `Field must have minimum length of ${validate.minLength}.`];
527
482
  }
528
-
529
483
  if ('maxLength' in validate && value && value.trim().length > validate.maxLength) {
530
484
  errors = [...errors, `Field must have maximum length of ${validate.maxLength}.`];
531
485
  }
532
-
486
+ if ('validationType' in validate && value && validate.validationType === 'phone' && !PHONE_PATTERN.test(value)) {
487
+ errors = [...errors, 'Field must be a valid international phone number. (e.g. +4930664040900)'];
488
+ }
489
+ if ('validationType' in validate && value && validate.validationType === 'email' && !EMAIL_PATTERN.test(value)) {
490
+ errors = [...errors, 'Field must be a valid email.'];
491
+ }
533
492
  return errors;
534
493
  }
535
-
536
494
  }
537
495
  Validator.$inject = [];
538
496
 
@@ -544,59 +502,44 @@ class FormFieldRegistry {
544
502
  this._ids = new Ids__default['default']([32, 36, 1]);
545
503
  this._keys = new Ids__default['default']([32, 36, 1]);
546
504
  }
547
-
548
505
  add(formField) {
549
506
  const {
550
507
  id
551
508
  } = formField;
552
-
553
509
  if (this._formFields[id]) {
554
510
  throw new Error(`form field with ID ${id} already exists`);
555
511
  }
556
-
557
512
  this._eventBus.fire('formField.add', {
558
513
  formField
559
514
  });
560
-
561
515
  this._formFields[id] = formField;
562
516
  }
563
-
564
517
  remove(formField) {
565
518
  const {
566
519
  id
567
520
  } = formField;
568
-
569
521
  if (!this._formFields[id]) {
570
522
  return;
571
523
  }
572
-
573
524
  this._eventBus.fire('formField.remove', {
574
525
  formField
575
526
  });
576
-
577
527
  delete this._formFields[id];
578
528
  }
579
-
580
529
  get(id) {
581
530
  return this._formFields[id];
582
531
  }
583
-
584
532
  getAll() {
585
533
  return Object.values(this._formFields);
586
534
  }
587
-
588
535
  forEach(callback) {
589
536
  this.getAll().forEach(formField => callback(formField));
590
537
  }
591
-
592
538
  clear() {
593
539
  this._formFields = {};
594
-
595
540
  this._ids.clear();
596
-
597
541
  this._keys.clear();
598
542
  }
599
-
600
543
  }
601
544
  FormFieldRegistry.$inject = ['eventBus'];
602
545
 
@@ -627,7 +570,6 @@ function pathParse(path) {
627
570
  if (!path) {
628
571
  return [];
629
572
  }
630
-
631
573
  return path.split('.').map(key => {
632
574
  return isNaN(parseInt(key)) ? key : parseInt(key);
633
575
  });
@@ -639,7 +581,6 @@ function pathStringify(path) {
639
581
  if (!path) {
640
582
  return '';
641
583
  }
642
-
643
584
  return path.join('.');
644
585
  }
645
586
  const indices = {};
@@ -649,22 +590,22 @@ function generateIndexForType(type) {
649
590
  } else {
650
591
  indices[type] = 1;
651
592
  }
652
-
653
593
  return indices[type];
654
594
  }
655
595
  function generateIdForType(type) {
656
596
  return `${type}${generateIndexForType(type)}`;
657
597
  }
598
+
658
599
  /**
659
600
  * @template T
660
601
  * @param {T} data
661
602
  * @param {(this: any, key: string, value: any) => any} [replacer]
662
603
  * @return {T}
663
604
  */
664
-
665
605
  function clone(data, replacer) {
666
606
  return JSON.parse(JSON.stringify(data, replacer));
667
607
  }
608
+
668
609
  /**
669
610
  * Parse the schema for input variables a form might make use of
670
611
  *
@@ -677,26 +618,21 @@ function getSchemaVariables(schema) {
677
618
  if (!schema.components) {
678
619
  return [];
679
620
  }
680
-
681
621
  return schema.components.reduce((variables, component) => {
682
622
  const {
683
623
  key,
684
624
  valuesKey,
685
625
  type
686
626
  } = component;
687
-
688
627
  if (['text', 'button'].includes(type)) {
689
628
  return variables;
690
629
  }
691
-
692
630
  if (key) {
693
631
  variables = [...variables, key];
694
632
  }
695
-
696
633
  if (valuesKey && !variables.includes(valuesKey)) {
697
634
  variables = [...variables, valuesKey];
698
635
  }
699
-
700
636
  return variables;
701
637
  }, []);
702
638
  }
@@ -711,6 +647,7 @@ class Importer {
711
647
  this._formFieldRegistry = formFieldRegistry;
712
648
  this._formFields = formFields;
713
649
  }
650
+
714
651
  /**
715
652
  * Import schema adding `id`, `_parent` and `_path`
716
653
  * information to each field and adding it to the
@@ -721,15 +658,12 @@ class Importer {
721
658
  *
722
659
  * @return { { warnings: Array<any>, schema: any, data: any } }
723
660
  */
724
-
725
-
726
661
  importSchema(schema, data = {}) {
727
662
  // TODO: Add warnings - https://github.com/bpmn-io/form-js/issues/289
728
663
  const warnings = [];
729
-
730
664
  try {
731
665
  const importedSchema = this.importFormField(clone(schema)),
732
- importedData = this.importData(clone(data));
666
+ importedData = this.importData(clone(data));
733
667
  return {
734
668
  warnings,
735
669
  schema: importedSchema,
@@ -740,14 +674,13 @@ class Importer {
740
674
  throw err;
741
675
  }
742
676
  }
677
+
743
678
  /**
744
679
  * @param {any} formField
745
680
  * @param {string} [parentId]
746
681
  *
747
682
  * @return {any} importedField
748
683
  */
749
-
750
-
751
684
  importFormField(formField, parentId) {
752
685
  const {
753
686
  components,
@@ -755,64 +688,53 @@ class Importer {
755
688
  type,
756
689
  id = generateIdForType(type)
757
690
  } = formField;
758
-
759
691
  if (parentId) {
760
692
  // set form field parent
761
693
  formField._parent = parentId;
762
694
  }
763
-
764
695
  if (!this._formFields.get(type)) {
765
696
  throw new Error(`form field of type <${type}> not supported`);
766
697
  }
767
-
768
698
  if (key) {
769
699
  // validate <key> uniqueness
770
700
  if (this._formFieldRegistry._keys.assigned(key)) {
771
701
  throw new Error(`form field with key <${key}> already exists`);
772
702
  }
703
+ this._formFieldRegistry._keys.claim(key, formField);
773
704
 
774
- this._formFieldRegistry._keys.claim(key, formField); // TODO: buttons should not have key
775
-
776
-
705
+ // TODO: buttons should not have key
777
706
  if (type !== 'button') {
778
707
  // set form field path
779
708
  formField._path = [key];
780
709
  }
781
710
  }
782
-
783
711
  if (id) {
784
712
  // validate <id> uniqueness
785
713
  if (this._formFieldRegistry._ids.assigned(id)) {
786
714
  throw new Error(`form field with id <${id}> already exists`);
787
715
  }
788
-
789
716
  this._formFieldRegistry._ids.claim(id, formField);
790
- } // set form field ID
791
-
717
+ }
792
718
 
719
+ // set form field ID
793
720
  formField.id = id;
794
-
795
721
  this._formFieldRegistry.add(formField);
796
-
797
722
  if (components) {
798
723
  this.importFormFields(components, id);
799
724
  }
800
-
801
725
  return formField;
802
726
  }
803
-
804
727
  importFormFields(components, parentId) {
805
728
  components.forEach(component => {
806
729
  this.importFormField(component, parentId);
807
730
  });
808
731
  }
732
+
809
733
  /**
810
734
  * @param {Object} data
811
735
  *
812
736
  * @return {Object} importedData
813
737
  */
814
-
815
-
816
738
  importData(data) {
817
739
  return this._formFieldRegistry.getAll().reduce((importedData, formField) => {
818
740
  const {
@@ -820,22 +742,24 @@ class Importer {
820
742
  _path,
821
743
  type,
822
744
  valuesKey
823
- } = formField; // get values defined via valuesKey
745
+ } = formField;
746
+
747
+ // get values defined via valuesKey
824
748
 
825
749
  if (valuesKey) {
826
- importedData = { ...importedData,
750
+ importedData = {
751
+ ...importedData,
827
752
  [valuesKey]: minDash.get(data, [valuesKey])
828
753
  };
829
- } // try to get value from data
754
+ }
755
+
756
+ // try to get value from data
830
757
  // if unavailable - try to get default value from form field
831
758
  // if unavailable - get empty value from form field
832
759
 
833
-
834
760
  if (_path) {
835
761
  const fieldImplementation = this._formFields.get(type);
836
-
837
762
  let valueData = minDash.get(data, _path);
838
-
839
763
  if (!minDash.isUndefined(valueData) && fieldImplementation.sanitizeValue) {
840
764
  valueData = fieldImplementation.sanitizeValue({
841
765
  formField,
@@ -843,17 +767,15 @@ class Importer {
843
767
  value: valueData
844
768
  });
845
769
  }
846
-
847
770
  const initialFieldValue = !minDash.isUndefined(valueData) ? valueData : !minDash.isUndefined(defaultValue) ? defaultValue : fieldImplementation.emptyValue;
848
- importedData = { ...importedData,
771
+ importedData = {
772
+ ...importedData,
849
773
  [_path[0]]: initialFieldValue
850
774
  };
851
775
  }
852
-
853
776
  return importedData;
854
777
  }, {});
855
778
  }
856
-
857
779
  }
858
780
  Importer.$inject = ['formFieldRegistry', 'formFields'];
859
781
 
@@ -862,30 +784,26 @@ var importModule = {
862
784
  };
863
785
 
864
786
  const NODE_TYPE_TEXT = 3,
865
- NODE_TYPE_ELEMENT = 1;
787
+ NODE_TYPE_ELEMENT = 1;
866
788
  const ALLOWED_NODES = ['h1', 'h2', 'h3', 'h4', 'h5', 'span', 'em', 'a', 'p', 'div', 'ul', 'ol', 'li', 'hr', 'blockquote', 'img', 'pre', 'code', 'br', 'strong'];
867
789
  const ALLOWED_ATTRIBUTES = ['align', 'alt', 'class', 'href', 'id', 'name', 'rel', 'target', 'src'];
868
790
  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
869
-
870
791
  const ATTR_WHITESPACE_PATTERN = /[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g; // eslint-disable-line no-control-regex
871
792
 
872
793
  const FORM_ELEMENT = document.createElement('form');
794
+
873
795
  /**
874
796
  * Sanitize a HTML string and return the cleaned, safe version.
875
797
  *
876
798
  * @param {string} html
877
799
  * @return {string}
878
800
  */
879
-
880
801
  function sanitizeHTML(html) {
881
802
  const doc = new DOMParser().parseFromString(`<!DOCTYPE html>\n<html><body><div>${html}`, 'text/html');
882
803
  doc.normalize();
883
804
  const element = doc.body.firstChild;
884
-
885
805
  if (element) {
886
- sanitizeNode(
887
- /** @type Element */
888
- element);
806
+ sanitizeNode( /** @type Element */element);
889
807
  return new XMLSerializer().serializeToString(element);
890
808
  } else {
891
809
  // handle the case that document parsing
@@ -893,6 +811,7 @@ function sanitizeHTML(html) {
893
811
  return '';
894
812
  }
895
813
  }
814
+
896
815
  /**
897
816
  * Recursively sanitize a HTML node, potentially
898
817
  * removing it, its children or attributes.
@@ -903,51 +822,48 @@ function sanitizeHTML(html) {
903
822
  *
904
823
  * @param {Element} node
905
824
  */
906
-
907
825
  function sanitizeNode(node) {
908
826
  // allow text nodes
909
827
  if (node.nodeType === NODE_TYPE_TEXT) {
910
828
  return;
911
- } // disallow all other nodes but Element
912
-
829
+ }
913
830
 
831
+ // disallow all other nodes but Element
914
832
  if (node.nodeType !== NODE_TYPE_ELEMENT) {
915
833
  return node.remove();
916
834
  }
835
+ const lcTag = node.tagName.toLowerCase();
917
836
 
918
- const lcTag = node.tagName.toLowerCase(); // disallow non-whitelisted tags
919
-
837
+ // disallow non-whitelisted tags
920
838
  if (!ALLOWED_NODES.includes(lcTag)) {
921
839
  return node.remove();
922
840
  }
841
+ const attributes = node.attributes;
923
842
 
924
- const attributes = node.attributes; // clean attributes
925
-
843
+ // clean attributes
926
844
  for (let i = attributes.length; i--;) {
927
845
  const attribute = attributes[i];
928
846
  const name = attribute.name;
929
- const lcName = name.toLowerCase(); // normalize node value
847
+ const lcName = name.toLowerCase();
930
848
 
849
+ // normalize node value
931
850
  const value = attribute.value.trim();
932
851
  node.removeAttribute(name);
933
852
  const valid = isValidAttribute(lcTag, lcName, value);
934
-
935
853
  if (valid) {
936
854
  node.setAttribute(name, value);
937
855
  }
938
- } // force noopener on target="_blank" links
939
-
856
+ }
940
857
 
858
+ // force noopener on target="_blank" links
941
859
  if (lcTag === 'a' && node.getAttribute('target') === '_blank' && node.getAttribute('rel') !== 'noopener') {
942
860
  node.setAttribute('rel', 'noopener');
943
861
  }
944
-
945
862
  for (let i = node.childNodes.length; i--;) {
946
- sanitizeNode(
947
- /** @type Element */
948
- node.childNodes[i]);
863
+ sanitizeNode( /** @type Element */node.childNodes[i]);
949
864
  }
950
865
  }
866
+
951
867
  /**
952
868
  * Validates attributes for validity.
953
869
  *
@@ -956,56 +872,51 @@ function sanitizeNode(node) {
956
872
  * @param {string} value
957
873
  * @return {boolean}
958
874
  */
959
-
960
-
961
875
  function isValidAttribute(lcTag, lcName, value) {
962
876
  // disallow most attributes based on whitelist
963
877
  if (!ALLOWED_ATTRIBUTES.includes(lcName)) {
964
878
  return false;
965
- } // disallow "DOM clobbering" / polution of document and wrapping form elements
966
-
879
+ }
967
880
 
881
+ // disallow "DOM clobbering" / polution of document and wrapping form elements
968
882
  if ((lcName === 'id' || lcName === 'name') && (value in document || value in FORM_ELEMENT)) {
969
883
  return false;
970
884
  }
971
-
972
885
  if (lcName === 'target' && value !== '_blank') {
973
886
  return false;
974
- } // allow valid url links only
975
-
887
+ }
976
888
 
889
+ // allow valid url links only
977
890
  if (lcName === 'href' && !ALLOWED_URI_PATTERN.test(value.replace(ATTR_WHITESPACE_PATTERN, ''))) {
978
891
  return false;
979
892
  }
980
-
981
893
  return true;
982
894
  }
983
895
 
984
- function formFieldClasses(type, errors = []) {
896
+ function formFieldClasses(type, {
897
+ errors = [],
898
+ disabled = false
899
+ } = {}) {
985
900
  if (!type) {
986
901
  throw new Error('type required');
987
902
  }
988
-
989
- const classes = ['fjs-form-field', `fjs-form-field-${type}`];
990
-
991
- if (errors.length) {
992
- classes.push('fjs-has-errors');
993
- }
994
-
995
- return classes.join(' ');
903
+ return classNames__default['default']('fjs-form-field', `fjs-form-field-${type}`, {
904
+ 'fjs-has-errors': errors.length > 0,
905
+ 'fjs-disabled': disabled
906
+ });
996
907
  }
997
908
  function prefixId(id, formId) {
998
909
  if (formId) {
999
910
  return `fjs-form-${formId}-${id}`;
1000
911
  }
1001
-
1002
912
  return `fjs-form-${id}`;
1003
913
  }
1004
914
  function markdownToHTML(markdown) {
1005
915
  const htmls = markdown.split(/(?:\r?\n){2,}/).map(line => /^((\d+.)|[><\s#-*])/.test(line) ? snarkdown__default['default'](line) : `<p>${snarkdown__default['default'](line)}</p>`);
1006
916
  return htmls.join('\n\n');
1007
- } // see https://github.com/developit/snarkdown/issues/70
917
+ }
1008
918
 
919
+ // see https://github.com/developit/snarkdown/issues/70
1009
920
  function safeMarkdown(markdown) {
1010
921
  const html = markdownToHTML(markdown);
1011
922
  return sanitizeHTML(html);
@@ -1020,7 +931,6 @@ function sanitizeSingleSelectValue(options) {
1020
931
  valuesKey,
1021
932
  values
1022
933
  } = formField;
1023
-
1024
934
  try {
1025
935
  const validValues = (valuesKey ? minDash.get(data, [valuesKey]) : values).map(v => v.value) || [];
1026
936
  return validValues.includes(value) ? value : null;
@@ -1040,7 +950,6 @@ function sanitizeMultiSelectValue(options) {
1040
950
  valuesKey,
1041
951
  values
1042
952
  } = formField;
1043
-
1044
953
  try {
1045
954
  const validValues = (valuesKey ? minDash.get(data, [valuesKey]) : values).map(v => v.value) || [];
1046
955
  return value.filter(v => validValues.includes(v));
@@ -1051,7 +960,7 @@ function sanitizeMultiSelectValue(options) {
1051
960
  }
1052
961
  }
1053
962
 
1054
- const type$8 = 'button';
963
+ const type$9 = 'button';
1055
964
  function Button(props) {
1056
965
  const {
1057
966
  disabled,
@@ -1061,7 +970,7 @@ function Button(props) {
1061
970
  action = 'submit'
1062
971
  } = field;
1063
972
  return jsxRuntime.jsx("div", {
1064
- class: formFieldClasses(type$8),
973
+ class: formFieldClasses(type$9),
1065
974
  children: jsxRuntime.jsx("button", {
1066
975
  class: "fjs-button",
1067
976
  type: action,
@@ -1070,15 +979,13 @@ function Button(props) {
1070
979
  })
1071
980
  });
1072
981
  }
1073
-
1074
982
  Button.create = function (options = {}) {
1075
983
  return {
1076
984
  action: 'submit',
1077
985
  ...options
1078
986
  };
1079
987
  };
1080
-
1081
- Button.type = type$8;
988
+ Button.type = type$9;
1082
989
  Button.label = 'Button';
1083
990
  Button.keyed = true;
1084
991
 
@@ -1100,9 +1007,7 @@ const FormRenderContext = preact.createContext({
1100
1007
  *
1101
1008
  * @returns {any}
1102
1009
  */
1103
-
1104
1010
  function getService(type, strict) {}
1105
-
1106
1011
  const FormContext = preact.createContext({
1107
1012
  getService,
1108
1013
  formId: null
@@ -1112,11 +1017,9 @@ function Description(props) {
1112
1017
  const {
1113
1018
  description
1114
1019
  } = props;
1115
-
1116
1020
  if (!description) {
1117
1021
  return null;
1118
1022
  }
1119
-
1120
1023
  return jsxRuntime.jsx("div", {
1121
1024
  class: "fjs-form-field-description",
1122
1025
  children: description
@@ -1127,11 +1030,9 @@ function Errors(props) {
1127
1030
  const {
1128
1031
  errors
1129
1032
  } = props;
1130
-
1131
1033
  if (!errors.length) {
1132
1034
  return null;
1133
1035
  }
1134
-
1135
1036
  return jsxRuntime.jsx("div", {
1136
1037
  class: "fjs-form-field-error",
1137
1038
  children: jsxRuntime.jsx("ul", {
@@ -1152,7 +1053,7 @@ function Label(props) {
1152
1053
  } = props;
1153
1054
  return jsxRuntime.jsxs("label", {
1154
1055
  for: id,
1155
- class: "fjs-form-field-label",
1056
+ class: classNames__default['default']('fjs-form-field-label', props['class']),
1156
1057
  children: [props.children, label || '', required && jsxRuntime.jsx("span", {
1157
1058
  class: "fjs-asterix",
1158
1059
  children: "*"
@@ -1160,7 +1061,7 @@ function Label(props) {
1160
1061
  });
1161
1062
  }
1162
1063
 
1163
- const type$7 = 'checkbox';
1064
+ const type$8 = 'checkbox';
1164
1065
  function Checkbox(props) {
1165
1066
  const {
1166
1067
  disabled,
@@ -1173,7 +1074,6 @@ function Checkbox(props) {
1173
1074
  id,
1174
1075
  label
1175
1076
  } = field;
1176
-
1177
1077
  const onChange = ({
1178
1078
  target
1179
1079
  }) => {
@@ -1182,12 +1082,16 @@ function Checkbox(props) {
1182
1082
  value: target.checked
1183
1083
  });
1184
1084
  };
1185
-
1186
1085
  const {
1187
1086
  formId
1188
1087
  } = hooks.useContext(FormContext);
1189
1088
  return jsxRuntime.jsxs("div", {
1190
- class: formFieldClasses(type$7, errors),
1089
+ class: classNames__default['default'](formFieldClasses(type$8, {
1090
+ errors,
1091
+ disabled
1092
+ }), {
1093
+ 'fjs-checked': value
1094
+ }),
1191
1095
  children: [jsxRuntime.jsx(Label, {
1192
1096
  id: prefixId(id, formId),
1193
1097
  label: label,
@@ -1207,17 +1111,15 @@ function Checkbox(props) {
1207
1111
  })]
1208
1112
  });
1209
1113
  }
1210
-
1211
1114
  Checkbox.create = function (options = {}) {
1212
- return { ...options
1115
+ return {
1116
+ ...options
1213
1117
  };
1214
1118
  };
1215
-
1216
- Checkbox.type = type$7;
1119
+ Checkbox.type = type$8;
1217
1120
  Checkbox.label = 'Checkbox';
1218
1121
  Checkbox.keyed = true;
1219
1122
  Checkbox.emptyValue = false;
1220
-
1221
1123
  Checkbox.sanitizeValue = ({
1222
1124
  value
1223
1125
  }) => value === true;
@@ -1232,12 +1134,12 @@ function useService (type, strict) {
1232
1134
  /**
1233
1135
  * @enum { String }
1234
1136
  */
1235
-
1236
1137
  const LOAD_STATES = {
1237
1138
  LOADING: 'loading',
1238
1139
  LOADED: 'loaded',
1239
1140
  ERROR: 'error'
1240
1141
  };
1142
+
1241
1143
  /**
1242
1144
  * @typedef {Object} ValuesGetter
1243
1145
  * @property {Object[]} values - The values data
@@ -1250,7 +1152,6 @@ const LOAD_STATES = {
1250
1152
  * @param {Object} field - The form field to handle values for
1251
1153
  * @return {ValuesGetter} valuesGetter - A values getter object providing loading state and values
1252
1154
  */
1253
-
1254
1155
  function useValuesAsync (field) {
1255
1156
  const {
1256
1157
  valuesKey,
@@ -1261,15 +1162,11 @@ function useValuesAsync (field) {
1261
1162
  error: undefined,
1262
1163
  state: LOAD_STATES.LOADING
1263
1164
  });
1264
-
1265
1165
  const initialData = useService('form')._getState().initialData;
1266
-
1267
1166
  hooks.useEffect(() => {
1268
1167
  let values = [];
1269
-
1270
1168
  if (valuesKey !== undefined) {
1271
1169
  const keyedValues = (initialData || {})[valuesKey];
1272
-
1273
1170
  if (keyedValues && Array.isArray(keyedValues)) {
1274
1171
  values = keyedValues;
1275
1172
  }
@@ -1279,25 +1176,22 @@ function useValuesAsync (field) {
1279
1176
  setValuesGetter(getErrorState('No values source defined in the form definition'));
1280
1177
  return;
1281
1178
  }
1282
-
1283
1179
  setValuesGetter(buildLoadedState(values));
1284
1180
  }, [valuesKey, staticValues, initialData]);
1285
1181
  return valuesGetter;
1286
1182
  }
1287
-
1288
1183
  const getErrorState = error => ({
1289
1184
  values: [],
1290
1185
  error,
1291
1186
  state: LOAD_STATES.ERROR
1292
1187
  });
1293
-
1294
1188
  const buildLoadedState = values => ({
1295
1189
  values,
1296
1190
  error: undefined,
1297
1191
  state: LOAD_STATES.LOADED
1298
1192
  });
1299
1193
 
1300
- const type$6 = 'checklist';
1194
+ const type$7 = 'checklist';
1301
1195
  function Checklist(props) {
1302
1196
  const {
1303
1197
  disabled,
@@ -1310,22 +1204,18 @@ function Checklist(props) {
1310
1204
  id,
1311
1205
  label
1312
1206
  } = field;
1313
-
1314
1207
  const toggleCheckbox = v => {
1315
1208
  let newValue = [...value];
1316
-
1317
1209
  if (!newValue.includes(v)) {
1318
1210
  newValue.push(v);
1319
1211
  } else {
1320
1212
  newValue = newValue.filter(x => x != v);
1321
1213
  }
1322
-
1323
1214
  props.onChange({
1324
1215
  field,
1325
1216
  value: newValue
1326
1217
  });
1327
1218
  };
1328
-
1329
1219
  const {
1330
1220
  state: loadState,
1331
1221
  values: options
@@ -1334,13 +1224,19 @@ function Checklist(props) {
1334
1224
  formId
1335
1225
  } = hooks.useContext(FormContext);
1336
1226
  return jsxRuntime.jsxs("div", {
1337
- class: formFieldClasses(type$6, errors),
1227
+ class: classNames__default['default'](formFieldClasses(type$7, {
1228
+ errors,
1229
+ disabled
1230
+ })),
1338
1231
  children: [jsxRuntime.jsx(Label, {
1339
1232
  label: label
1340
1233
  }), loadState == LOAD_STATES.LOADED && options.map((v, index) => {
1341
1234
  return jsxRuntime.jsx(Label, {
1342
1235
  id: prefixId(`${id}-${index}`, formId),
1343
1236
  label: v.label,
1237
+ class: classNames__default['default']({
1238
+ 'fjs-checked': value.includes(v.value)
1239
+ }),
1344
1240
  required: false,
1345
1241
  children: jsxRuntime.jsx("input", {
1346
1242
  checked: value.includes(v.value),
@@ -1358,7 +1254,6 @@ function Checklist(props) {
1358
1254
  })]
1359
1255
  });
1360
1256
  }
1361
-
1362
1257
  Checklist.create = function (options = {}) {
1363
1258
  if (options.valuesKey) return options;
1364
1259
  return {
@@ -1369,15 +1264,13 @@ Checklist.create = function (options = {}) {
1369
1264
  ...options
1370
1265
  };
1371
1266
  };
1372
-
1373
- Checklist.type = type$6;
1267
+ Checklist.type = type$7;
1374
1268
  Checklist.label = 'Checklist';
1375
1269
  Checklist.keyed = true;
1376
1270
  Checklist.emptyValue = [];
1377
1271
  Checklist.sanitizeValue = sanitizeMultiSelectValue;
1378
1272
 
1379
1273
  const noop$1 = () => false;
1380
-
1381
1274
  function FormField(props) {
1382
1275
  const {
1383
1276
  field,
@@ -1387,29 +1280,26 @@ function FormField(props) {
1387
1280
  _path
1388
1281
  } = field;
1389
1282
  const formFields = useService('formFields'),
1390
- form = useService('form');
1391
-
1283
+ form = useService('form');
1392
1284
  const {
1393
1285
  data,
1394
1286
  errors,
1395
1287
  properties
1396
1288
  } = form._getState();
1397
-
1398
1289
  const {
1399
1290
  Element
1400
1291
  } = hooks.useContext(FormRenderContext);
1401
1292
  const FormFieldComponent = formFields.get(field.type);
1402
-
1403
1293
  if (!FormFieldComponent) {
1404
1294
  throw new Error(`cannot render field <${field.type}>`);
1405
1295
  }
1406
-
1407
1296
  const value = minDash.get(data, _path);
1408
1297
  const fieldErrors = findErrors(errors, _path);
1409
1298
  const disabled = properties.readOnly || field.disabled || false;
1410
1299
  return jsxRuntime.jsx(Element, {
1411
1300
  field: field,
1412
- children: jsxRuntime.jsx(FormFieldComponent, { ...props,
1301
+ children: jsxRuntime.jsx(FormFieldComponent, {
1302
+ ...props,
1413
1303
  disabled: disabled,
1414
1304
  errors: fieldErrors,
1415
1305
  onChange: disabled ? noop$1 : onChange,
@@ -1433,21 +1323,20 @@ function Default(props) {
1433
1323
  class: "fjs-vertical-layout",
1434
1324
  field: field,
1435
1325
  children: [components.map(childField => {
1436
- return preact.createElement(FormField, { ...props,
1326
+ return preact.createElement(FormField, {
1327
+ ...props,
1437
1328
  key: childField.id,
1438
1329
  field: childField
1439
1330
  });
1440
1331
  }), components.length ? null : jsxRuntime.jsx(Empty, {})]
1441
1332
  });
1442
1333
  }
1443
-
1444
1334
  Default.create = function (options = {}) {
1445
1335
  return {
1446
1336
  components: [],
1447
1337
  ...options
1448
1338
  };
1449
1339
  };
1450
-
1451
1340
  Default.type = 'default';
1452
1341
  Default.keyed = false;
1453
1342
 
@@ -1456,7 +1345,6 @@ Default.keyed = false;
1456
1345
  *
1457
1346
  * @see http://bpmn.io/license for more information.
1458
1347
  */
1459
-
1460
1348
  function Logo() {
1461
1349
  return jsxRuntime.jsxs("svg", {
1462
1350
  xmlns: "http://www.w3.org/2000/svg",
@@ -1473,16 +1361,13 @@ function Logo() {
1473
1361
  })]
1474
1362
  });
1475
1363
  }
1476
-
1477
1364
  function Lightbox(props) {
1478
1365
  const {
1479
1366
  open
1480
1367
  } = props;
1481
-
1482
1368
  if (!open) {
1483
1369
  return null;
1484
1370
  }
1485
-
1486
1371
  return jsxRuntime.jsxs("div", {
1487
1372
  class: "fjs-powered-by-lightbox",
1488
1373
  style: "z-index: 100; position: fixed; top: 0; left: 0;right: 0; bottom: 0",
@@ -1510,7 +1395,6 @@ function Lightbox(props) {
1510
1395
  })]
1511
1396
  });
1512
1397
  }
1513
-
1514
1398
  function Link(props) {
1515
1399
  return jsxRuntime.jsx("div", {
1516
1400
  class: "fjs-powered-by fjs-form-field",
@@ -1527,17 +1411,14 @@ function Link(props) {
1527
1411
  })
1528
1412
  });
1529
1413
  }
1530
-
1531
1414
  function PoweredBy(props) {
1532
1415
  const [open, setOpen] = hooks.useState(false);
1533
-
1534
1416
  function toggleOpen(open) {
1535
1417
  return event => {
1536
1418
  event.preventDefault();
1537
1419
  setOpen(open);
1538
1420
  };
1539
1421
  }
1540
-
1541
1422
  return jsxRuntime.jsxs(preact.Fragment, {
1542
1423
  children: [React.createPortal(jsxRuntime.jsx(Lightbox, {
1543
1424
  open: open,
@@ -1549,30 +1430,24 @@ function PoweredBy(props) {
1549
1430
  }
1550
1431
 
1551
1432
  const noop = () => {};
1552
-
1553
1433
  function FormComponent(props) {
1554
1434
  const form = useService('form');
1555
-
1556
1435
  const {
1557
1436
  schema
1558
1437
  } = form._getState();
1559
-
1560
1438
  const {
1561
1439
  onSubmit = noop,
1562
1440
  onReset = noop,
1563
1441
  onChange = noop
1564
1442
  } = props;
1565
-
1566
1443
  const handleSubmit = event => {
1567
1444
  event.preventDefault();
1568
1445
  onSubmit();
1569
1446
  };
1570
-
1571
1447
  const handleReset = event => {
1572
1448
  event.preventDefault();
1573
1449
  onReset();
1574
1450
  };
1575
-
1576
1451
  return jsxRuntime.jsxs("form", {
1577
1452
  class: "fjs-form",
1578
1453
  onSubmit: handleSubmit,
@@ -1584,7 +1459,7 @@ function FormComponent(props) {
1584
1459
  });
1585
1460
  }
1586
1461
 
1587
- const type$5 = 'number';
1462
+ const type$6 = 'number';
1588
1463
  function Number(props) {
1589
1464
  const {
1590
1465
  disabled,
@@ -1601,7 +1476,6 @@ function Number(props) {
1601
1476
  const {
1602
1477
  required
1603
1478
  } = validate;
1604
-
1605
1479
  const onChange = ({
1606
1480
  target
1607
1481
  }) => {
@@ -1612,12 +1486,14 @@ function Number(props) {
1612
1486
  })
1613
1487
  });
1614
1488
  };
1615
-
1616
1489
  const {
1617
1490
  formId
1618
1491
  } = hooks.useContext(FormContext);
1619
1492
  return jsxRuntime.jsxs("div", {
1620
- class: formFieldClasses(type$5, errors),
1493
+ class: formFieldClasses(type$6, {
1494
+ errors,
1495
+ disabled
1496
+ }),
1621
1497
  children: [jsxRuntime.jsx(Label, {
1622
1498
  id: prefixId(id, formId),
1623
1499
  label: label,
@@ -1636,25 +1512,23 @@ function Number(props) {
1636
1512
  })]
1637
1513
  });
1638
1514
  }
1639
-
1640
1515
  Number.create = function (options = {}) {
1641
- return { ...options
1516
+ return {
1517
+ ...options
1642
1518
  };
1643
1519
  };
1644
-
1645
1520
  Number.sanitizeValue = ({
1646
1521
  value
1647
1522
  }) => {
1648
1523
  const parsedValue = parseInt(value, 10);
1649
1524
  return isNaN(parsedValue) ? null : parsedValue;
1650
1525
  };
1651
-
1652
- Number.type = type$5;
1526
+ Number.type = type$6;
1653
1527
  Number.keyed = true;
1654
1528
  Number.label = 'Number';
1655
1529
  Number.emptyValue = null;
1656
1530
 
1657
- const type$4 = 'radio';
1531
+ const type$5 = 'radio';
1658
1532
  function Radio(props) {
1659
1533
  const {
1660
1534
  disabled,
@@ -1671,14 +1545,12 @@ function Radio(props) {
1671
1545
  const {
1672
1546
  required
1673
1547
  } = validate;
1674
-
1675
1548
  const onChange = v => {
1676
1549
  props.onChange({
1677
1550
  field,
1678
1551
  value: v
1679
1552
  });
1680
1553
  };
1681
-
1682
1554
  const {
1683
1555
  state: loadState,
1684
1556
  values: options
@@ -1687,7 +1559,10 @@ function Radio(props) {
1687
1559
  formId
1688
1560
  } = hooks.useContext(FormContext);
1689
1561
  return jsxRuntime.jsxs("div", {
1690
- class: formFieldClasses(type$4, errors),
1562
+ class: formFieldClasses(type$5, {
1563
+ errors,
1564
+ disabled
1565
+ }),
1691
1566
  children: [jsxRuntime.jsx(Label, {
1692
1567
  label: label,
1693
1568
  required: required
@@ -1695,6 +1570,9 @@ function Radio(props) {
1695
1570
  return jsxRuntime.jsx(Label, {
1696
1571
  id: prefixId(`${id}-${index}`, formId),
1697
1572
  label: option.label,
1573
+ class: classNames__default['default']({
1574
+ 'fjs-checked': option.value === value
1575
+ }),
1698
1576
  required: false,
1699
1577
  children: jsxRuntime.jsx("input", {
1700
1578
  checked: option.value === value,
@@ -1712,7 +1590,6 @@ function Radio(props) {
1712
1590
  })]
1713
1591
  });
1714
1592
  }
1715
-
1716
1593
  Radio.create = function (options = {}) {
1717
1594
  if (options.valuesKey) return options;
1718
1595
  return {
@@ -1723,14 +1600,13 @@ Radio.create = function (options = {}) {
1723
1600
  ...options
1724
1601
  };
1725
1602
  };
1726
-
1727
- Radio.type = type$4;
1603
+ Radio.type = type$5;
1728
1604
  Radio.label = 'Radio';
1729
1605
  Radio.keyed = true;
1730
1606
  Radio.emptyValue = null;
1731
1607
  Radio.sanitizeValue = sanitizeSingleSelectValue;
1732
1608
 
1733
- const type$3 = 'select';
1609
+ const type$4 = 'select';
1734
1610
  function Select(props) {
1735
1611
  const {
1736
1612
  disabled,
@@ -1747,7 +1623,6 @@ function Select(props) {
1747
1623
  const {
1748
1624
  required
1749
1625
  } = validate;
1750
-
1751
1626
  const onChange = ({
1752
1627
  target
1753
1628
  }) => {
@@ -1756,7 +1631,6 @@ function Select(props) {
1756
1631
  value: target.value === '' ? null : target.value
1757
1632
  });
1758
1633
  };
1759
-
1760
1634
  const {
1761
1635
  state: loadState,
1762
1636
  values: options
@@ -1765,7 +1639,10 @@ function Select(props) {
1765
1639
  formId
1766
1640
  } = hooks.useContext(FormContext);
1767
1641
  return jsxRuntime.jsxs("div", {
1768
- class: formFieldClasses(type$3, errors),
1642
+ class: formFieldClasses(type$4, {
1643
+ errors,
1644
+ disabled
1645
+ }),
1769
1646
  children: [jsxRuntime.jsx(Label, {
1770
1647
  id: prefixId(id, formId),
1771
1648
  label: label,
@@ -1791,7 +1668,6 @@ function Select(props) {
1791
1668
  })]
1792
1669
  });
1793
1670
  }
1794
-
1795
1671
  Select.create = function (options = {}) {
1796
1672
  if (options.valuesKey) return options;
1797
1673
  return {
@@ -1802,8 +1678,7 @@ Select.create = function (options = {}) {
1802
1678
  ...options
1803
1679
  };
1804
1680
  };
1805
-
1806
- Select.type = type$3;
1681
+ Select.type = type$4;
1807
1682
  Select.label = 'Select';
1808
1683
  Select.keyed = true;
1809
1684
  Select.emptyValue = null;
@@ -1822,7 +1697,7 @@ var CloseIcon = (({
1822
1697
  fillRule: "evenodd",
1823
1698
  clipRule: "evenodd",
1824
1699
  d: "M12 4.7l-.7-.7L8 7.3 4.7 4l-.7.7L7.3 8 4 11.3l.7.7L8 8.7l3.3 3.3.7-.7L8.7 8 12 4.7z",
1825
- fill: "#000"
1700
+ fill: "currentColor"
1826
1701
  })));
1827
1702
 
1828
1703
  function useKeyDownAction(targetKey, action, listenerElement = window) {
@@ -1833,7 +1708,6 @@ function useKeyDownAction(targetKey, action, listenerElement = window) {
1833
1708
  action();
1834
1709
  }
1835
1710
  }
1836
-
1837
1711
  hooks.useEffect(() => {
1838
1712
  listenerElement.addEventListener('keydown', downHandler);
1839
1713
  return () => {
@@ -1843,9 +1717,7 @@ function useKeyDownAction(targetKey, action, listenerElement = window) {
1843
1717
  }
1844
1718
 
1845
1719
  const DEFAULT_LABEL_GETTER = value => value;
1846
-
1847
1720
  const NOOP = () => {};
1848
-
1849
1721
  function DropdownList(props) {
1850
1722
  const {
1851
1723
  keyEventsListener = window,
@@ -1865,7 +1737,6 @@ function DropdownList(props) {
1865
1737
  }, [values.length]);
1866
1738
  hooks.useEffect(() => {
1867
1739
  if (focusedValueIndex === 0) return;
1868
-
1869
1740
  if (!focusedValueIndex || !values.length) {
1870
1741
  setFocusedValueIndex(0);
1871
1742
  } else if (focusedValueIndex >= values.length) {
@@ -1891,7 +1762,6 @@ function DropdownList(props) {
1891
1762
  }, keyEventsListener);
1892
1763
  hooks.useEffect(() => {
1893
1764
  const individualEntries = dropdownContainer.current.children;
1894
-
1895
1765
  if (individualEntries.length && !mouseControl) {
1896
1766
  individualEntries[focusedValueIndex].scrollIntoView({
1897
1767
  block: 'nearest',
@@ -1899,23 +1769,19 @@ function DropdownList(props) {
1899
1769
  });
1900
1770
  }
1901
1771
  }, [focusedValueIndex, mouseControl]);
1902
-
1903
1772
  const mouseMove = (e, i) => {
1904
1773
  const userMoved = !mouseScreenPos.current || mouseScreenPos.current.x !== e.screenX && mouseScreenPos.current.y !== e.screenY;
1905
-
1906
1774
  if (userMoved) {
1907
1775
  mouseScreenPos.current = {
1908
1776
  x: e.screenX,
1909
1777
  y: e.screenY
1910
1778
  };
1911
-
1912
1779
  if (!mouseControl) {
1913
1780
  setMouseControl(true);
1914
1781
  setFocusedValueIndex(i);
1915
1782
  }
1916
1783
  }
1917
1784
  };
1918
-
1919
1785
  return jsxRuntime.jsxs("div", {
1920
1786
  ref: dropdownContainer,
1921
1787
  tabIndex: -1,
@@ -1941,7 +1807,7 @@ function DropdownList(props) {
1941
1807
  });
1942
1808
  }
1943
1809
 
1944
- const type$2 = 'taglist';
1810
+ const type$3 = 'taglist';
1945
1811
  function Taglist(props) {
1946
1812
  const {
1947
1813
  disabled,
@@ -1966,12 +1832,14 @@ function Taglist(props) {
1966
1832
  const {
1967
1833
  state: loadState,
1968
1834
  values: options
1969
- } = useValuesAsync(field); // We cache a map of option values to their index so that we don't need to search the whole options array every time to correlate the label
1835
+ } = useValuesAsync(field);
1970
1836
 
1837
+ // We cache a map of option values to their index so that we don't need to search the whole options array every time to correlate the label
1971
1838
  const valueToOptionMap = hooks.useMemo(() => Object.assign({}, ...options.map((o, x) => ({
1972
1839
  [o.value]: options[x]
1973
- }))), [options]); // Usage of stringify is necessary here because we want this effect to only trigger when there is a value change to the array
1840
+ }))), [options]);
1974
1841
 
1842
+ // Usage of stringify is necessary here because we want this effect to only trigger when there is a value change to the array
1975
1843
  hooks.useEffect(() => {
1976
1844
  if (loadState === LOAD_STATES.LOADED) {
1977
1845
  setFilteredOptions(options.filter(o => o.label && o.value && o.label.toLowerCase().includes(filter.toLowerCase()) && !values.includes(o.value)));
@@ -1982,37 +1850,32 @@ function Taglist(props) {
1982
1850
  hooks.useEffect(() => {
1983
1851
  setHasOptionsLeft(options.length > values.length);
1984
1852
  }, [options.length, values.length]);
1985
-
1986
1853
  const onFilterChange = ({
1987
1854
  target
1988
1855
  }) => {
1989
1856
  setIsEscapeClose(false);
1990
1857
  setFilter(target.value);
1991
1858
  };
1992
-
1993
1859
  const selectValue = value => {
1994
1860
  if (filter) {
1995
1861
  setFilter('');
1996
- } // Ensure values cannot be double selected due to latency
1997
-
1862
+ }
1998
1863
 
1864
+ // Ensure values cannot be double selected due to latency
1999
1865
  if (values.at(-1) === value) {
2000
1866
  return;
2001
1867
  }
2002
-
2003
1868
  props.onChange({
2004
1869
  value: [...values, value],
2005
1870
  field
2006
1871
  });
2007
1872
  };
2008
-
2009
1873
  const deselectValue = value => {
2010
1874
  props.onChange({
2011
1875
  value: values.filter(v => v != value),
2012
1876
  field
2013
1877
  });
2014
1878
  };
2015
-
2016
1879
  const onInputKeyDown = e => {
2017
1880
  switch (e.key) {
2018
1881
  case 'ArrowUp':
@@ -2020,32 +1883,29 @@ function Taglist(props) {
2020
1883
  // We do not want the cursor to seek in the search field when we press up and down
2021
1884
  e.preventDefault();
2022
1885
  break;
2023
-
2024
1886
  case 'Backspace':
2025
1887
  if (!filter && values.length) {
2026
1888
  deselectValue(values[values.length - 1]);
2027
1889
  }
2028
-
2029
1890
  break;
2030
-
2031
1891
  case 'Escape':
2032
1892
  setIsEscapeClose(true);
2033
1893
  break;
2034
-
2035
1894
  case 'Enter':
2036
1895
  if (isEscapeClosed) {
2037
1896
  setIsEscapeClose(false);
2038
1897
  }
2039
-
2040
1898
  break;
2041
1899
  }
2042
1900
  };
2043
-
2044
1901
  return jsxRuntime.jsxs("div", {
2045
- class: formFieldClasses(type$2, errors),
1902
+ class: formFieldClasses(type$3, {
1903
+ errors,
1904
+ disabled
1905
+ }),
2046
1906
  children: [jsxRuntime.jsx(Label, {
2047
1907
  label: label,
2048
- id: prefixId(id, formId)
1908
+ id: prefixId(`${id}-search`, formId)
2049
1909
  }), jsxRuntime.jsxs("div", {
2050
1910
  class: classNames__default['default']('fjs-taglist', {
2051
1911
  'disabled': disabled
@@ -2097,7 +1957,6 @@ function Taglist(props) {
2097
1957
  })]
2098
1958
  });
2099
1959
  }
2100
-
2101
1960
  Taglist.create = function (options = {}) {
2102
1961
  if (options.valuesKey) return options;
2103
1962
  return {
@@ -2108,14 +1967,13 @@ Taglist.create = function (options = {}) {
2108
1967
  ...options
2109
1968
  };
2110
1969
  };
2111
-
2112
- Taglist.type = type$2;
1970
+ Taglist.type = type$3;
2113
1971
  Taglist.label = 'Taglist';
2114
1972
  Taglist.keyed = true;
2115
1973
  Taglist.emptyValue = [];
2116
1974
  Taglist.sanitizeValue = sanitizeMultiSelectValue;
2117
1975
 
2118
- const type$1 = 'text';
1976
+ const type$2 = 'text';
2119
1977
  function Text(props) {
2120
1978
  const {
2121
1979
  field
@@ -2124,25 +1982,23 @@ function Text(props) {
2124
1982
  text = ''
2125
1983
  } = field;
2126
1984
  return jsxRuntime.jsx("div", {
2127
- class: formFieldClasses(type$1),
1985
+ class: formFieldClasses(type$2),
2128
1986
  children: jsxRuntime.jsx(Markup__default['default'], {
2129
1987
  markup: safeMarkdown(text),
2130
1988
  trim: false
2131
1989
  })
2132
1990
  });
2133
1991
  }
2134
-
2135
1992
  Text.create = function (options = {}) {
2136
1993
  return {
2137
1994
  text: '# Text',
2138
1995
  ...options
2139
1996
  };
2140
1997
  };
2141
-
2142
- Text.type = type$1;
1998
+ Text.type = type$2;
2143
1999
  Text.keyed = false;
2144
2000
 
2145
- const type = 'textfield';
2001
+ const type$1 = 'textfield';
2146
2002
  function Textfield(props) {
2147
2003
  const {
2148
2004
  disabled,
@@ -2159,7 +2015,6 @@ function Textfield(props) {
2159
2015
  const {
2160
2016
  required
2161
2017
  } = validate;
2162
-
2163
2018
  const onChange = ({
2164
2019
  target
2165
2020
  }) => {
@@ -2168,12 +2023,14 @@ function Textfield(props) {
2168
2023
  value: target.value
2169
2024
  });
2170
2025
  };
2171
-
2172
2026
  const {
2173
2027
  formId
2174
2028
  } = hooks.useContext(FormContext);
2175
2029
  return jsxRuntime.jsxs("div", {
2176
- class: formFieldClasses(type, errors),
2030
+ class: formFieldClasses(type$1, {
2031
+ errors,
2032
+ disabled
2033
+ }),
2177
2034
  children: [jsxRuntime.jsx(Label, {
2178
2035
  id: prefixId(id, formId),
2179
2036
  label: label,
@@ -2192,22 +2049,101 @@ function Textfield(props) {
2192
2049
  })]
2193
2050
  });
2194
2051
  }
2195
-
2196
2052
  Textfield.create = function (options = {}) {
2197
- return { ...options
2053
+ return {
2054
+ ...options
2198
2055
  };
2199
2056
  };
2200
-
2201
- Textfield.type = type;
2202
- Textfield.label = 'Text Field';
2057
+ Textfield.type = type$1;
2058
+ Textfield.label = 'Text field';
2203
2059
  Textfield.keyed = true;
2204
2060
  Textfield.emptyValue = '';
2205
-
2206
2061
  Textfield.sanitizeValue = ({
2207
2062
  value
2208
- }) => minDash.isArray(value) || minDash.isObject(value) ? null : String(value);
2063
+ }) => minDash.isArray(value) || minDash.isObject(value) ? '' : String(value);
2209
2064
 
2210
- const formFields = [Button, Checkbox, Checklist, Default, Number, Radio, Select, Taglist, Text, Textfield];
2065
+ const type = 'textarea';
2066
+ function Textarea(props) {
2067
+ const {
2068
+ disabled,
2069
+ errors = [],
2070
+ field,
2071
+ value = ''
2072
+ } = props;
2073
+ const {
2074
+ description,
2075
+ id,
2076
+ label,
2077
+ validate = {}
2078
+ } = field;
2079
+ const {
2080
+ required
2081
+ } = validate;
2082
+ const textareaRef = hooks.useRef();
2083
+ const onInput = ({
2084
+ target
2085
+ }) => {
2086
+ props.onChange({
2087
+ field,
2088
+ value: target.value
2089
+ });
2090
+ };
2091
+ const autoSizeTextarea = hooks.useCallback(textarea => {
2092
+ // Ensures the textarea shrinks back, and improves resizing behavior consistency
2093
+ textarea.style.height = '0px';
2094
+ const computed = window.getComputedStyle(textarea);
2095
+ const calculatedHeight = parseInt(computed.getPropertyValue('border-top-width')) + parseInt(computed.getPropertyValue('padding-top')) + textarea.scrollHeight + parseInt(computed.getPropertyValue('padding-bottom')) + parseInt(computed.getPropertyValue('border-bottom-width'));
2096
+ const minHeight = 75;
2097
+ const maxHeight = 350;
2098
+ const displayHeight = Math.max(Math.min(calculatedHeight, maxHeight), minHeight);
2099
+ textarea.style.height = `${displayHeight}px`;
2100
+
2101
+ // Overflow is hidden by default to hide scrollbar flickering
2102
+ textarea.style.overflow = calculatedHeight > maxHeight ? 'visible' : 'hidden';
2103
+ }, []);
2104
+ hooks.useEffect(() => {
2105
+ autoSizeTextarea(textareaRef.current);
2106
+ }, [autoSizeTextarea, value]);
2107
+ const {
2108
+ formId
2109
+ } = hooks.useContext(FormContext);
2110
+ return jsxRuntime.jsxs("div", {
2111
+ class: formFieldClasses(type, {
2112
+ errors,
2113
+ disabled
2114
+ }),
2115
+ children: [jsxRuntime.jsx(Label, {
2116
+ id: prefixId(id, formId),
2117
+ label: label,
2118
+ required: required
2119
+ }), jsxRuntime.jsx("textarea", {
2120
+ class: "fjs-textarea",
2121
+ disabled: disabled,
2122
+ id: prefixId(id, formId),
2123
+ onInput: onInput,
2124
+ value: value,
2125
+ ref: textareaRef
2126
+ }), jsxRuntime.jsx(Description, {
2127
+ description: description
2128
+ }), jsxRuntime.jsx(Errors, {
2129
+ errors: errors
2130
+ })]
2131
+ });
2132
+ }
2133
+ Textarea.create = function (options = {}) {
2134
+ return {
2135
+ ...options
2136
+ };
2137
+ };
2138
+ Textarea.type = type;
2139
+ Textarea.label = 'Text area';
2140
+ Textarea.keyed = true;
2141
+ Textarea.emptyValue = '';
2142
+ Textarea.sanitizeValue = ({
2143
+ value
2144
+ }) => minDash.isArray(value) || minDash.isObject(value) ? '' : String(value);
2145
+
2146
+ const formFields = [Button, Checkbox, Checklist, Default, Number, Radio, Select, Taglist, Text, Textfield, Textarea];
2211
2147
 
2212
2148
  class FormFields {
2213
2149
  constructor() {
@@ -2219,15 +2155,12 @@ class FormFields {
2219
2155
  this.register(type, formField);
2220
2156
  });
2221
2157
  }
2222
-
2223
2158
  register(type, formField) {
2224
2159
  this._formFields[type] = formField;
2225
2160
  }
2226
-
2227
2161
  get(type) {
2228
2162
  return this._formFields[type];
2229
2163
  }
2230
-
2231
2164
  }
2232
2165
 
2233
2166
  function Renderer(config, eventBus, form, injector) {
@@ -2237,7 +2170,6 @@ function Renderer(config, eventBus, form, injector) {
2237
2170
  getService(type, strict = true) {
2238
2171
  return injector.get(type, strict);
2239
2172
  },
2240
-
2241
2173
  formId: form._id
2242
2174
  };
2243
2175
  eventBus.on('changed', newState => {
@@ -2259,11 +2191,9 @@ function Renderer(config, eventBus, form, injector) {
2259
2191
  const {
2260
2192
  schema
2261
2193
  } = state;
2262
-
2263
2194
  if (!schema) {
2264
2195
  return null;
2265
2196
  }
2266
-
2267
2197
  return jsxRuntime.jsx(FormContext.Provider, {
2268
2198
  value: formContext,
2269
2199
  children: jsxRuntime.jsx(FormComponent, {
@@ -2273,7 +2203,6 @@ function Renderer(config, eventBus, form, injector) {
2273
2203
  })
2274
2204
  });
2275
2205
  };
2276
-
2277
2206
  const {
2278
2207
  container
2279
2208
  } = config;
@@ -2323,10 +2252,10 @@ var core = {
2323
2252
  */
2324
2253
 
2325
2254
  const ids = new Ids__default['default']([32, 36, 1]);
2255
+
2326
2256
  /**
2327
2257
  * The form.
2328
2258
  */
2329
-
2330
2259
  class Form {
2331
2260
  /**
2332
2261
  * @constructor
@@ -2338,28 +2267,28 @@ class Form {
2338
2267
  * @type {OnEventType}
2339
2268
  */
2340
2269
  this.on = this._onEvent;
2270
+
2341
2271
  /**
2342
2272
  * @public
2343
2273
  * @type {String}
2344
2274
  */
2345
-
2346
2275
  this._id = ids.next();
2276
+
2347
2277
  /**
2348
2278
  * @private
2349
2279
  * @type {Element}
2350
2280
  */
2351
-
2352
2281
  this._container = createFormContainer();
2353
2282
  const {
2354
2283
  container,
2355
2284
  injector = this._createInjector(options, this._container),
2356
2285
  properties = {}
2357
2286
  } = options;
2287
+
2358
2288
  /**
2359
2289
  * @private
2360
2290
  * @type {State}
2361
2291
  */
2362
-
2363
2292
  this._state = {
2364
2293
  initialData: null,
2365
2294
  data: null,
@@ -2370,33 +2299,31 @@ class Form {
2370
2299
  this.get = injector.get;
2371
2300
  this.invoke = injector.invoke;
2372
2301
  this.get('eventBus').fire('form.init');
2373
-
2374
2302
  if (container) {
2375
2303
  this.attachTo(container);
2376
2304
  }
2377
2305
  }
2378
-
2379
2306
  clear() {
2380
2307
  // clear form services
2381
- this._emit('diagram.clear'); // clear diagram services (e.g. EventBus)
2382
-
2308
+ this._emit('diagram.clear');
2383
2309
 
2310
+ // clear diagram services (e.g. EventBus)
2384
2311
  this._emit('form.clear');
2385
2312
  }
2313
+
2386
2314
  /**
2387
2315
  * Destroy the form, removing it from DOM,
2388
2316
  * if attached.
2389
2317
  */
2390
-
2391
-
2392
2318
  destroy() {
2393
2319
  // destroy form services
2394
- this.get('eventBus').fire('form.destroy'); // destroy diagram services (e.g. EventBus)
2320
+ this.get('eventBus').fire('form.destroy');
2395
2321
 
2322
+ // destroy diagram services (e.g. EventBus)
2396
2323
  this.get('eventBus').fire('diagram.destroy');
2397
-
2398
2324
  this._detach(false);
2399
2325
  }
2326
+
2400
2327
  /**
2401
2328
  * Open a form schema with the given initial data.
2402
2329
  *
@@ -2405,8 +2332,6 @@ class Form {
2405
2332
  *
2406
2333
  * @return Promise<{ warnings: Array<any> }>
2407
2334
  */
2408
-
2409
-
2410
2335
  importSchema(schema, data = {}) {
2411
2336
  return new Promise((resolve, reject) => {
2412
2337
  try {
@@ -2416,18 +2341,15 @@ class Form {
2416
2341
  data: importedData,
2417
2342
  warnings
2418
2343
  } = this.get('importer').importSchema(schema, data);
2419
-
2420
2344
  this._setState({
2421
2345
  data: importedData,
2422
2346
  errors: {},
2423
2347
  schema: importedSchema,
2424
2348
  initialData: clone(importedData)
2425
2349
  });
2426
-
2427
2350
  this._emit('import.done', {
2428
2351
  warnings
2429
2352
  });
2430
-
2431
2353
  return resolve({
2432
2354
  warnings
2433
2355
  });
@@ -2436,168 +2358,124 @@ class Form {
2436
2358
  error,
2437
2359
  warnings: error.warnings || []
2438
2360
  });
2439
-
2440
2361
  return reject(error);
2441
2362
  }
2442
2363
  });
2443
2364
  }
2365
+
2444
2366
  /**
2445
2367
  * Submit the form, triggering all field validations.
2446
2368
  *
2447
2369
  * @returns { { data: Data, errors: Errors } }
2448
2370
  */
2449
-
2450
-
2451
2371
  submit() {
2452
2372
  const {
2453
2373
  properties
2454
2374
  } = this._getState();
2455
-
2456
2375
  if (properties.readOnly) {
2457
2376
  throw new Error('form is read-only');
2458
2377
  }
2459
-
2460
- const formFieldRegistry = this.get('formFieldRegistry');
2461
- const data = formFieldRegistry.getAll().reduce((data, field) => {
2462
- const {
2463
- disabled,
2464
- _path
2465
- } = field; // do not submit disabled form fields
2466
-
2467
- if (disabled || !_path) {
2468
- return data;
2469
- }
2470
-
2471
- const value = minDash.get(this._getState().data, _path);
2472
- return { ...data,
2473
- [_path[0]]: value
2474
- };
2475
- }, {});
2378
+ const data = this._getSubmitData();
2476
2379
  const errors = this.validate();
2477
-
2478
2380
  this._emit('submit', {
2479
2381
  data,
2480
2382
  errors
2481
2383
  });
2482
-
2483
2384
  return {
2484
2385
  data,
2485
2386
  errors
2486
2387
  };
2487
2388
  }
2488
-
2489
2389
  reset() {
2490
2390
  this._emit('reset');
2491
-
2492
2391
  this._setState({
2493
2392
  data: clone(this._state.initialData),
2494
2393
  errors: {}
2495
2394
  });
2496
2395
  }
2396
+
2497
2397
  /**
2498
2398
  * @returns {Errors}
2499
2399
  */
2500
-
2501
-
2502
2400
  validate() {
2503
2401
  const formFieldRegistry = this.get('formFieldRegistry'),
2504
- validator = this.get('validator');
2505
-
2402
+ validator = this.get('validator');
2506
2403
  const {
2507
2404
  data
2508
2405
  } = this._getState();
2509
-
2510
2406
  const errors = formFieldRegistry.getAll().reduce((errors, field) => {
2511
2407
  const {
2512
2408
  disabled,
2513
2409
  _path
2514
2410
  } = field;
2515
-
2516
2411
  if (disabled) {
2517
2412
  return errors;
2518
2413
  }
2519
-
2520
2414
  const value = minDash.get(data, _path);
2521
2415
  const fieldErrors = validator.validateField(field, value);
2522
2416
  return minDash.set(errors, [pathStringify(_path)], fieldErrors.length ? fieldErrors : undefined);
2523
- },
2524
- /** @type {Errors} */
2525
- {});
2526
-
2417
+ }, /** @type {Errors} */{});
2527
2418
  this._setState({
2528
2419
  errors
2529
2420
  });
2530
-
2531
2421
  return errors;
2532
2422
  }
2423
+
2533
2424
  /**
2534
2425
  * @param {Element|string} parentNode
2535
2426
  */
2536
-
2537
-
2538
2427
  attachTo(parentNode) {
2539
2428
  if (!parentNode) {
2540
2429
  throw new Error('parentNode required');
2541
2430
  }
2542
-
2543
2431
  this.detach();
2544
-
2545
2432
  if (minDash.isString(parentNode)) {
2546
2433
  parentNode = document.querySelector(parentNode);
2547
2434
  }
2548
-
2549
2435
  const container = this._container;
2550
2436
  parentNode.appendChild(container);
2551
-
2552
2437
  this._emit('attach');
2553
2438
  }
2554
-
2555
2439
  detach() {
2556
2440
  this._detach();
2557
2441
  }
2442
+
2558
2443
  /**
2559
2444
  * @private
2560
2445
  *
2561
2446
  * @param {boolean} [emit]
2562
2447
  */
2563
-
2564
-
2565
2448
  _detach(emit = true) {
2566
2449
  const container = this._container,
2567
- parentNode = container.parentNode;
2568
-
2450
+ parentNode = container.parentNode;
2569
2451
  if (!parentNode) {
2570
2452
  return;
2571
2453
  }
2572
-
2573
2454
  if (emit) {
2574
2455
  this._emit('detach');
2575
2456
  }
2576
-
2577
2457
  parentNode.removeChild(container);
2578
2458
  }
2459
+
2579
2460
  /**
2580
2461
  * @param {FormProperty} property
2581
2462
  * @param {any} value
2582
2463
  */
2583
-
2584
-
2585
2464
  setProperty(property, value) {
2586
2465
  const properties = minDash.set(this._getState().properties, [property], value);
2587
-
2588
2466
  this._setState({
2589
2467
  properties
2590
2468
  });
2591
2469
  }
2470
+
2592
2471
  /**
2593
2472
  * @param {FormEvent} type
2594
2473
  * @param {Function} handler
2595
2474
  */
2596
-
2597
-
2598
2475
  off(type, handler) {
2599
2476
  this.get('eventBus').off(type, handler);
2600
2477
  }
2478
+
2601
2479
  /**
2602
2480
  * @private
2603
2481
  *
@@ -2606,8 +2484,6 @@ class Form {
2606
2484
  *
2607
2485
  * @returns {Injector}
2608
2486
  */
2609
-
2610
-
2611
2487
  _createInjector(options, container) {
2612
2488
  const {
2613
2489
  additionalModules = [],
@@ -2624,21 +2500,19 @@ class Form {
2624
2500
  form: ['value', this]
2625
2501
  }, core, ...modules, ...additionalModules]);
2626
2502
  }
2503
+
2627
2504
  /**
2628
2505
  * @private
2629
2506
  */
2630
-
2631
-
2632
2507
  _emit(type, data) {
2633
2508
  this.get('eventBus').fire(type, data);
2634
2509
  }
2510
+
2635
2511
  /**
2636
2512
  * @internal
2637
2513
  *
2638
2514
  * @param { { add?: boolean, field: any, remove?: number, value?: any } } update
2639
2515
  */
2640
-
2641
-
2642
2516
  _update(update) {
2643
2517
  const {
2644
2518
  field,
@@ -2647,54 +2521,71 @@ class Form {
2647
2521
  const {
2648
2522
  _path
2649
2523
  } = field;
2650
-
2651
2524
  let {
2652
2525
  data,
2653
2526
  errors
2654
2527
  } = this._getState();
2655
-
2656
2528
  const validator = this.get('validator');
2657
2529
  const fieldErrors = validator.validateField(field, value);
2658
2530
  minDash.set(data, _path, value);
2659
2531
  minDash.set(errors, [pathStringify(_path)], fieldErrors.length ? fieldErrors : undefined);
2660
-
2661
2532
  this._setState({
2662
2533
  data: clone(data),
2663
2534
  errors: clone(errors)
2664
2535
  });
2665
2536
  }
2537
+
2666
2538
  /**
2667
2539
  * @internal
2668
2540
  */
2669
-
2670
-
2671
2541
  _getState() {
2672
2542
  return this._state;
2673
2543
  }
2544
+
2674
2545
  /**
2675
2546
  * @internal
2676
2547
  */
2677
-
2678
-
2679
2548
  _setState(state) {
2680
- this._state = { ...this._state,
2549
+ this._state = {
2550
+ ...this._state,
2681
2551
  ...state
2682
2552
  };
2683
-
2684
2553
  this._emit('changed', this._getState());
2685
2554
  }
2555
+
2686
2556
  /**
2687
2557
  * @internal
2688
2558
  */
2689
-
2690
-
2691
2559
  _onEvent(type, priority, handler) {
2692
2560
  this.get('eventBus').on(type, priority, handler);
2693
2561
  }
2694
2562
 
2563
+ /**
2564
+ * @internal
2565
+ */
2566
+ _getSubmitData() {
2567
+ const formFieldRegistry = this.get('formFieldRegistry');
2568
+ return formFieldRegistry.getAll().reduce((data, field) => {
2569
+ const {
2570
+ disabled,
2571
+ _path
2572
+ } = field;
2573
+
2574
+ // do not submit disabled form fields
2575
+ if (disabled || !_path) {
2576
+ return data;
2577
+ }
2578
+ const value = minDash.get(this._getState().data, _path);
2579
+ return {
2580
+ ...data,
2581
+ [_path[0]]: value
2582
+ };
2583
+ }, {});
2584
+ }
2695
2585
  }
2696
2586
 
2697
- const schemaVersion = 5;
2587
+ const schemaVersion = 6;
2588
+
2698
2589
  /**
2699
2590
  * @typedef { import('./types').CreateFormOptions } CreateFormOptions
2700
2591
  */
@@ -2706,7 +2597,6 @@ const schemaVersion = 5;
2706
2597
  *
2707
2598
  * @return {Promise<Form>}
2708
2599
  */
2709
-
2710
2600
  function createForm(options) {
2711
2601
  const {
2712
2602
  data,
@@ -2734,6 +2624,7 @@ exports.Radio = Radio;
2734
2624
  exports.Select = Select;
2735
2625
  exports.Taglist = Taglist;
2736
2626
  exports.Text = Text;
2627
+ exports.Textarea = Textarea;
2737
2628
  exports.Textfield = Textfield;
2738
2629
  exports.clone = clone;
2739
2630
  exports.createForm = createForm;