@bpmn-io/form-js-editor 0.14.1 → 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 (34) hide show
  1. package/dist/assets/form-js-editor-base.css +251 -36
  2. package/dist/assets/form-js-editor.css +229 -35
  3. package/dist/index.cjs +802 -283
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.es.js +673 -154
  6. package/dist/index.es.js.map +1 -1
  7. package/dist/types/FormEditor.d.ts +9 -4
  8. package/dist/types/core/EventBus.d.ts +1 -1
  9. package/dist/types/core/FormLayoutValidator.d.ts +5 -1
  10. package/dist/types/core/index.d.ts +2 -1
  11. package/dist/types/features/dragging/Dragging.d.ts +3 -3
  12. package/dist/types/features/editor-actions/FormEditorActions.d.ts +2 -1
  13. package/dist/types/features/editor-actions/index.d.ts +1 -1
  14. package/dist/types/features/keyboard/index.d.ts +1 -1
  15. package/dist/types/features/modeling/FormLayoutUpdater.d.ts +2 -1
  16. package/dist/types/features/modeling/behavior/IdBehavior.d.ts +2 -1
  17. package/dist/types/features/modeling/behavior/KeyBehavior.d.ts +2 -1
  18. package/dist/types/features/modeling/behavior/ValidateBehavior.d.ts +2 -1
  19. package/dist/types/features/modeling/index.d.ts +6 -1
  20. package/dist/types/features/palette/PaletteRenderer.d.ts +1 -1
  21. package/dist/types/features/palette/components/Palette.d.ts +1 -1
  22. package/dist/types/features/properties-panel/PropertiesPanel.d.ts +1 -1
  23. package/dist/types/features/properties-panel/PropertiesPanelHeaderProvider.d.ts +1 -1
  24. package/dist/types/features/properties-panel/PropertiesPanelRenderer.d.ts +1 -1
  25. package/dist/types/features/properties-panel/entries/InputKeyValuesSourceEntry.d.ts +1 -1
  26. package/dist/types/render/Renderer.d.ts +1 -1
  27. package/dist/types/render/components/FieldDragPreview.d.ts +1 -1
  28. package/dist/types/render/components/FieldResizer.d.ts +1 -0
  29. package/dist/types/render/components/FormEditor.d.ts +1 -1
  30. package/dist/types/render/components/Util.d.ts +27 -1
  31. package/dist/types/render/components/editor-form-fields/EditorText.d.ts +2 -4
  32. package/dist/types/render/components/icons/index.d.ts +1 -1
  33. package/package.json +3 -3
  34. package/dist/types/features/properties-panel/icons/index.d.ts +0 -1
package/dist/index.es.js CHANGED
@@ -4,11 +4,11 @@ import Ids from 'ids';
4
4
  import { isArray, isFunction, isNumber, bind, assign, debounce, forEach, get, isObject, uniqueBy, sortBy, find, set as set$1, isUndefined, without, has, isString } from 'min-dash';
5
5
  import classnames from 'classnames';
6
6
  import { jsx, jsxs, Fragment } from 'preact/jsx-runtime';
7
- import { useContext, useState, useRef, useEffect, useCallback, useMemo, useLayoutEffect } from 'preact/hooks';
7
+ import { useContext, useState, useRef, useCallback, useEffect, useMemo, useLayoutEffect } from 'preact/hooks';
8
8
  import { createContext, render, createElement } from 'preact';
9
9
  import React, { forwardRef } from 'preact/compat';
10
10
  import dragula from 'dragula';
11
- import { classes, closest, event, matches, domify, query } from 'min-dom';
11
+ import { classes, query, closest, event, matches, domify } from 'min-dom';
12
12
  import { mutate } from 'array-move';
13
13
  import { FeelersEditor } from 'feelers';
14
14
  import FeelEditor from '@bpmn-io/feel-editor';
@@ -18,6 +18,30 @@ var FN_REF = '__fn';
18
18
  var DEFAULT_PRIORITY$2 = 1000;
19
19
  var slice = Array.prototype.slice;
20
20
 
21
+ /**
22
+ * @typedef { {
23
+ * stopPropagation(): void;
24
+ * preventDefault(): void;
25
+ * cancelBubble: boolean;
26
+ * defaultPrevented: boolean;
27
+ * returnValue: any;
28
+ * } } Event
29
+ */
30
+
31
+ /**
32
+ * @template E
33
+ *
34
+ * @typedef { (event: E & Event, ...any) => any } EventBusEventCallback
35
+ */
36
+
37
+ /**
38
+ * @typedef { {
39
+ * priority: number;
40
+ * next: EventBusListener | null;
41
+ * callback: EventBusEventCallback<any>;
42
+ * } } EventBusListener
43
+ */
44
+
21
45
  /**
22
46
  * A general purpose event bus.
23
47
  *
@@ -102,6 +126,9 @@ var slice = Array.prototype.slice;
102
126
  * ```
103
127
  */
104
128
  function EventBus() {
129
+ /**
130
+ * @type { Record<string, EventBusListener> }
131
+ */
105
132
  this._listeners = {};
106
133
 
107
134
  // cleanup on destroy on lowest priority to allow
@@ -121,10 +148,12 @@ function EventBus() {
121
148
  *
122
149
  * Returning anything but `undefined` from a listener will stop the listener propagation.
123
150
  *
124
- * @param {string|Array<string>} events
125
- * @param {number} [priority=1000] the priority in which this listener is called, larger is higher
126
- * @param {Function} callback
127
- * @param {Object} [that] Pass context (`this`) to the callback
151
+ * @template T
152
+ *
153
+ * @param {string|string[]} events to subscribe to
154
+ * @param {number} [priority=1000] listen priority
155
+ * @param {EventBusEventCallback<T>} callback
156
+ * @param {any} [that] callback context
128
157
  */
129
158
  EventBus.prototype.on = function (events, priority, callback, that) {
130
159
  events = isArray(events) ? events : [events];
@@ -156,14 +185,16 @@ EventBus.prototype.on = function (events, priority, callback, that) {
156
185
  };
157
186
 
158
187
  /**
159
- * Register an event listener that is executed only once.
188
+ * Register an event listener that is called only once.
189
+ *
190
+ * @template T
160
191
  *
161
- * @param {string} event the event name to register for
162
- * @param {number} [priority=1000] the priority in which this listener is called, larger is higher
163
- * @param {Function} callback the callback to execute
164
- * @param {Object} [that] Pass context (`this`) to the callback
192
+ * @param {string|string[]} events to subscribe to
193
+ * @param {number} [priority=1000] the listen priority
194
+ * @param {EventBusEventCallback<T>} callback
195
+ * @param {any} [that] callback context
165
196
  */
166
- EventBus.prototype.once = function (event, priority, callback, that) {
197
+ EventBus.prototype.once = function (events, priority, callback, that) {
167
198
  var self = this;
168
199
  if (isFunction(priority)) {
169
200
  that = callback;
@@ -176,7 +207,7 @@ EventBus.prototype.once = function (event, priority, callback, that) {
176
207
  function wrappedCallback() {
177
208
  wrappedCallback.__isTomb = true;
178
209
  var result = callback.apply(that, arguments);
179
- self.off(event, wrappedCallback);
210
+ self.off(events, wrappedCallback);
180
211
  return result;
181
212
  }
182
213
 
@@ -184,7 +215,7 @@ EventBus.prototype.once = function (event, priority, callback, that) {
184
215
  // bound callbacks via {@link #off} using the original
185
216
  // callback
186
217
  wrappedCallback[FN_REF] = callback;
187
- this.on(event, priority, wrappedCallback);
218
+ this.on(events, priority, wrappedCallback);
188
219
  };
189
220
 
190
221
  /**
@@ -192,8 +223,8 @@ EventBus.prototype.once = function (event, priority, callback, that) {
192
223
  *
193
224
  * If no callback is given, all listeners for a given event name are being removed.
194
225
  *
195
- * @param {string|Array<string>} events
196
- * @param {Function} [callback]
226
+ * @param {string|string[]} events
227
+ * @param {EventBusEventCallback} [callback]
197
228
  */
198
229
  EventBus.prototype.off = function (events, callback) {
199
230
  events = isArray(events) ? events : [events];
@@ -204,11 +235,11 @@ EventBus.prototype.off = function (events, callback) {
204
235
  };
205
236
 
206
237
  /**
207
- * Create an EventBus event.
238
+ * Create an event recognized be the event bus.
208
239
  *
209
- * @param {Object} data
240
+ * @param {Object} data Event data.
210
241
  *
211
- * @return {Object} event, recognized by the eventBus
242
+ * @return {Event} An event that will be recognized by the event bus.
212
243
  */
213
244
  EventBus.prototype.createEvent = function (data) {
214
245
  var event = new InternalEvent();
@@ -217,10 +248,11 @@ EventBus.prototype.createEvent = function (data) {
217
248
  };
218
249
 
219
250
  /**
220
- * Fires a named event.
251
+ * Fires an event.
221
252
  *
222
253
  * @example
223
254
  *
255
+ * ```javascript
224
256
  * // fire event by name
225
257
  * events.fire('foo');
226
258
  *
@@ -238,13 +270,13 @@ EventBus.prototype.createEvent = function (data) {
238
270
  * });
239
271
  *
240
272
  * events.fire({ type: 'foo' }, 'I am bar!');
273
+ * ```
241
274
  *
242
- * @param {string} [name] the optional event name
243
- * @param {Object} [event] the event object
244
- * @param {...Object} additional arguments to be passed to the callback functions
275
+ * @param {string} [type] event type
276
+ * @param {Object} [data] event or event data
277
+ * @param {...any} [args] additional arguments the callback will be called with.
245
278
  *
246
- * @return {boolean} the events return value, if specified or false if the
247
- * default action was prevented by listeners
279
+ * @return {any} The return value. Will be set to `false` if the default was prevented.
248
280
  */
249
281
  EventBus.prototype.fire = function (type, data) {
250
282
  var event, firstListener, returnValue, args;
@@ -296,6 +328,14 @@ EventBus.prototype.fire = function (type, data) {
296
328
  }
297
329
  return returnValue;
298
330
  };
331
+
332
+ /**
333
+ * Handle an error by firing an event.
334
+ *
335
+ * @param {Error} error The error to be handled.
336
+ *
337
+ * @return {boolean} Whether the error was handled.
338
+ */
299
339
  EventBus.prototype.handleError = function (error) {
300
340
  return this.fire('error', {
301
341
  error: error
@@ -304,6 +344,14 @@ EventBus.prototype.handleError = function (error) {
304
344
  EventBus.prototype._destroy = function () {
305
345
  this._listeners = {};
306
346
  };
347
+
348
+ /**
349
+ * @param {Event} event
350
+ * @param {any[]} args
351
+ * @param {EventBusListener} listener
352
+ *
353
+ * @return {any}
354
+ */
307
355
  EventBus.prototype._invokeListeners = function (event, args, listener) {
308
356
  var returnValue;
309
357
  while (listener) {
@@ -316,6 +364,14 @@ EventBus.prototype._invokeListeners = function (event, args, listener) {
316
364
  }
317
365
  return returnValue;
318
366
  };
367
+
368
+ /**
369
+ * @param {Event} event
370
+ * @param {any[]} args
371
+ * @param {EventBusListener} listener
372
+ *
373
+ * @return {any}
374
+ */
319
375
  EventBus.prototype._invokeListener = function (event, args, listener) {
320
376
  var returnValue;
321
377
  if (listener.callback.__isTomb) {
@@ -344,7 +400,7 @@ EventBus.prototype._invokeListener = function (event, args, listener) {
344
400
  return returnValue;
345
401
  };
346
402
 
347
- /*
403
+ /**
348
404
  * Add new listener with a certain priority to the list
349
405
  * of listeners (for the given event).
350
406
  *
@@ -358,7 +414,7 @@ EventBus.prototype._invokeListener = function (event, args, listener) {
358
414
  * * after: [ 1500, 1500, (new=1300), 1000, 1000, (new=1000) ]
359
415
  *
360
416
  * @param {string} event
361
- * @param {Object} listener { priority, callback }
417
+ * @param {EventBusListener} listener
362
418
  */
363
419
  EventBus.prototype._addListener = function (event, newListener) {
364
420
  var listener = this._getListeners(event),
@@ -389,9 +445,20 @@ EventBus.prototype._addListener = function (event, newListener) {
389
445
  // add new listener to back
390
446
  previousListener.next = newListener;
391
447
  };
448
+
449
+ /**
450
+ * @param {string} name
451
+ *
452
+ * @return {EventBusListener}
453
+ */
392
454
  EventBus.prototype._getListeners = function (name) {
393
455
  return this._listeners[name];
394
456
  };
457
+
458
+ /**
459
+ * @param {string} name
460
+ * @param {EventBusListener} listener
461
+ */
395
462
  EventBus.prototype._setListeners = function (name, listener) {
396
463
  this._listeners[name] = listener;
397
464
  };
@@ -439,9 +506,9 @@ InternalEvent.prototype.init = function (data) {
439
506
  * Invoke function. Be fast...
440
507
  *
441
508
  * @param {Function} fn
442
- * @param {Array<Object>} args
509
+ * @param {any[]} args
443
510
  *
444
- * @return {Any}
511
+ * @return {any}
445
512
  */
446
513
  function invokeFunction(fn, args) {
447
514
  return fn.apply(null, args);
@@ -483,21 +550,24 @@ class FieldFactory {
483
550
  if (!fieldDefinition) {
484
551
  throw new Error(`form field of type <${type}> not supported`);
485
552
  }
553
+ const {
554
+ config
555
+ } = fieldDefinition;
486
556
  if (id && this._formFieldRegistry._ids.assigned(id)) {
487
557
  throw new Error(`ID <${id}> already assigned`);
488
558
  }
489
559
  if (key && this._formFieldRegistry._keys.assigned(key)) {
490
560
  throw new Error(`key <${key}> already assigned`);
491
561
  }
492
- const labelAttrs = applyDefaults && fieldDefinition.label ? {
493
- label: fieldDefinition.label
562
+ const labelAttrs = applyDefaults && config.label ? {
563
+ label: config.label
494
564
  } : {};
495
- const field = fieldDefinition.create({
565
+ const field = config.create({
496
566
  ...labelAttrs,
497
567
  ...attrs
498
568
  });
499
569
  this._ensureId(field);
500
- if (fieldDefinition.keyed) {
570
+ if (config.keyed) {
501
571
  this._ensureKey(field, applyDefaults);
502
572
  }
503
573
  return field;
@@ -570,6 +640,10 @@ class FormFieldRegistry extends FormFieldRegistry$1 {
570
640
  }
571
641
  }
572
642
 
643
+ const MAX_COLUMNS_PER_ROW = 16;
644
+ const MAX_COLUMNS = 16;
645
+ const MIN_COLUMNS = 2;
646
+ const MAX_FIELDS_PER_ROW = 4;
573
647
  class FormLayoutValidator {
574
648
  /**
575
649
  * @constructor
@@ -583,15 +657,15 @@ class FormLayoutValidator {
583
657
  }
584
658
  validateField(field = {}, columns, row) {
585
659
  // allow empty (auto columns)
586
- if (columns) {
587
- // allow minimum 2 cols
588
- if (columns < 2) {
589
- return 'Minimum 2 columns are allowed';
660
+ if (Number.isInteger(columns)) {
661
+ // allow minimum cols
662
+ if (columns < MIN_COLUMNS) {
663
+ return `Minimum ${MIN_COLUMNS} columns are allowed`;
590
664
  }
591
665
 
592
- // allow maximum 16 cols
593
- if (columns > 16) {
594
- return 'Maximum 16 columns are allowed';
666
+ // allow maximum cols
667
+ if (columns > MAX_COLUMNS) {
668
+ return `Maximum ${MAX_COLUMNS} columns are allowed`;
595
669
  }
596
670
  }
597
671
  if (!row) {
@@ -616,17 +690,24 @@ class FormLayoutValidator {
616
690
  });
617
691
 
618
692
  // do not allow overflows
619
- if (sumColumns > 16 || sumColumns === 16 && sumAutoCols > 0 || columns === 16 && sumFields > 1) {
620
- return 'New value exceeds the maximum of 16 columns per row';
693
+ if (sumColumns > MAX_COLUMNS_PER_ROW || sumAutoCols > 0 && sumColumns > calculateMaxColumnsWithAuto(sumAutoCols) || columns === MAX_COLUMNS_PER_ROW && sumFields > 1) {
694
+ return `New value exceeds the maximum of ${MAX_COLUMNS_PER_ROW} columns per row`;
621
695
  }
622
- if (sumFields > 4) {
623
- return 'Maximum 4 fields per row are allowed';
696
+ if (sumFields > MAX_FIELDS_PER_ROW) {
697
+ return `Maximum ${MAX_FIELDS_PER_ROW} fields per row are allowed`;
624
698
  }
625
699
  return null;
626
700
  }
627
701
  }
628
702
  FormLayoutValidator.$inject = ['formLayouter', 'formFieldRegistry'];
629
703
 
704
+ // helper //////////////////////
705
+
706
+ // on normal screen sizes, auto columns take minimum 2 columns
707
+ function calculateMaxColumnsWithAuto(autoCols) {
708
+ return MAX_COLUMNS_PER_ROW - autoCols * 2;
709
+ }
710
+
630
711
  class Importer {
631
712
  /**
632
713
  * @constructor
@@ -743,6 +824,91 @@ function editorFormFieldClasses(type, {
743
824
  });
744
825
  }
745
826
 
827
+ /**
828
+ * Add a dragger that calls back the passed function with
829
+ * { event, delta } on drag.
830
+ *
831
+ * @example
832
+ *
833
+ * function dragMove(event, delta) {
834
+ * // we are dragging (!!)
835
+ * }
836
+ *
837
+ * domElement.addEventListener('dragstart', dragger(dragMove));
838
+ *
839
+ * @param {Function} fn
840
+ * @param {Element} dragPreview
841
+ *
842
+ * @return {Function} drag start callback function
843
+ */
844
+ function createDragger(fn, dragPreview) {
845
+ let self;
846
+ let startX, startY;
847
+
848
+ /** drag start */
849
+ function onDragStart(event) {
850
+ self = this;
851
+ startX = event.clientX;
852
+ startY = event.clientY;
853
+
854
+ // (1) prevent preview image
855
+ if (event.dataTransfer) {
856
+ event.dataTransfer.setDragImage(dragPreview, 0, 0);
857
+ }
858
+
859
+ // (2) setup drag listeners
860
+
861
+ // attach drag + cleanup event
862
+ document.addEventListener('dragover', onDrag);
863
+ document.addEventListener('dragend', onEnd);
864
+ document.addEventListener('drop', preventDefault);
865
+ }
866
+ function onDrag(event) {
867
+ const delta = {
868
+ x: event.clientX - startX,
869
+ y: event.clientY - startY
870
+ };
871
+
872
+ // call provided fn with event, delta
873
+ return fn.call(self, event, delta);
874
+ }
875
+ function onEnd() {
876
+ document.removeEventListener('dragover', onDrag);
877
+ document.removeEventListener('dragend', onEnd);
878
+ document.removeEventListener('drop', preventDefault);
879
+ }
880
+ return onDragStart;
881
+ }
882
+
883
+ /**
884
+ * Throttle function call according UI update cycle.
885
+ *
886
+ * @param {Function} fn
887
+ *
888
+ * @return {Function} throttled fn
889
+ */
890
+ function throttle(fn) {
891
+ let active = false;
892
+ let lastArgs = [];
893
+ let lastThis = undefined;
894
+ return function (...args) {
895
+ lastArgs = args;
896
+ lastThis = this;
897
+ if (active) {
898
+ return;
899
+ }
900
+ active = true;
901
+ fn.apply(lastThis, lastArgs);
902
+ window.requestAnimationFrame(function () {
903
+ lastArgs = lastThis = active = undefined;
904
+ });
905
+ };
906
+ }
907
+ function preventDefault(event) {
908
+ event.preventDefault();
909
+ event.stopPropagation();
910
+ }
911
+
746
912
  const DragAndDropContext = createContext({
747
913
  drake: null
748
914
  });
@@ -783,10 +949,42 @@ var CloseIcon = (({
783
949
  })));
784
950
 
785
951
  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); }
786
- var DraggableIcon = (({
952
+ var DeleteIcon$1 = (({
787
953
  styles = {},
788
954
  ...props
789
955
  }) => /*#__PURE__*/React.createElement("svg", _extends$2({
956
+ xmlns: "http://www.w3.org/2000/svg",
957
+ width: "16",
958
+ height: "16",
959
+ fill: "none"
960
+ }, props), /*#__PURE__*/React.createElement("rect", {
961
+ width: "16",
962
+ height: "16",
963
+ x: ".536",
964
+ fill: "#fff",
965
+ rx: "3",
966
+ style: {
967
+ mixBlendMode: "multiply"
968
+ }
969
+ }), /*#__PURE__*/React.createElement("path", {
970
+ fill: "#fff",
971
+ d: "M.536 0h16v16h-16z",
972
+ style: {
973
+ mixBlendMode: "multiply"
974
+ }
975
+ }), /*#__PURE__*/React.createElement("path", {
976
+ fill: "currentcolor",
977
+ d: "M7.536 6h-1v6h1V6zm3 0h-1v6h1V6z"
978
+ }), /*#__PURE__*/React.createElement("path", {
979
+ fill: "currentcolor",
980
+ d: "M2.536 3v1h1v10a1 1 0 001 1h8a1 1 0 001-1V4h1V3h-12zm2 11V4h8v10h-8zm6-13h-4v1h4V1z"
981
+ })));
982
+
983
+ function _extends$1() { _extends$1 = 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$1.apply(this, arguments); }
984
+ var DraggableIcon = (({
985
+ styles = {},
986
+ ...props
987
+ }) => /*#__PURE__*/React.createElement("svg", _extends$1({
790
988
  xmlns: "http://www.w3.org/2000/svg",
791
989
  width: "16",
792
990
  height: "16",
@@ -799,11 +997,11 @@ var DraggableIcon = (({
799
997
  fill: "none"
800
998
  })));
801
999
 
802
- function _extends$1() { _extends$1 = 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$1.apply(this, arguments); }
1000
+ 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); }
803
1001
  var SearchIcon = (({
804
1002
  styles = {},
805
1003
  ...props
806
- }) => /*#__PURE__*/React.createElement("svg", _extends$1({
1004
+ }) => /*#__PURE__*/React.createElement("svg", _extends({
807
1005
  width: "15",
808
1006
  height: "15",
809
1007
  fill: "none",
@@ -859,9 +1057,7 @@ function EditorText(props) {
859
1057
  disableLinks: true
860
1058
  });
861
1059
  }
862
- EditorText.create = Text$1.create;
863
- EditorText.type = Text$1.type;
864
- EditorText.keyed = Text$1.keyed;
1060
+ EditorText.config = Text$1.config;
865
1061
 
866
1062
  const editorFormFields = [EditorText];
867
1063
 
@@ -869,28 +1065,20 @@ class EditorFormFields extends FormFields {
869
1065
  constructor() {
870
1066
  super();
871
1067
  editorFormFields.forEach(formField => {
872
- this.register(formField.type, formField);
1068
+ this.register(formField.config.type, formField);
873
1069
  });
874
1070
  }
875
1071
  }
876
1072
 
877
- 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); }
878
- var ListDeleteIcon = (({
879
- styles = {},
880
- ...props
881
- }) => /*#__PURE__*/React.createElement("svg", _extends({
882
- xmlns: "http://www.w3.org/2000/svg",
883
- width: "11",
884
- height: "14"
885
- }, props), /*#__PURE__*/React.createElement("path", {
886
- d: "M10 4v8c0 1.1-.9 2-2 2H3c-1.1 0-2-.9-2-2V4h9zM8 6H3v4.8c0 .66.5 1.2 1.111 1.2H6.89C7.5 12 8 11.46 8 10.8V6zm3-5H8.5l-1-1h-4l-1 1H0v1.5h11V1z"
887
- })));
888
-
889
- const PALETTE_ENTRIES = formFields.filter(f => f.type !== 'default').map(f => {
1073
+ const PALETTE_ENTRIES = formFields.filter(({
1074
+ config: fieldConfig
1075
+ }) => fieldConfig.type !== 'default').map(({
1076
+ config: fieldConfig
1077
+ }) => {
890
1078
  return {
891
- label: f.label,
892
- type: f.type,
893
- group: f.group
1079
+ label: fieldConfig.label,
1080
+ type: fieldConfig.type,
1081
+ group: fieldConfig.group
894
1082
  };
895
1083
  });
896
1084
  const PALETTE_GROUPS = [{
@@ -911,19 +1099,24 @@ function Palette(props) {
911
1099
  const [searchTerm, setSearchTerm] = useState('');
912
1100
  const inputRef = useRef();
913
1101
  const groups = groupEntries(entries);
1102
+ const simplifyString = useCallback(str => {
1103
+ return str.toLowerCase().replace(/\s+/g, '');
1104
+ }, []);
1105
+ const filter = useCallback(entry => {
1106
+ const simplifiedSearchTerm = simplifyString(searchTerm);
1107
+ if (!simplifiedSearchTerm) {
1108
+ return true;
1109
+ }
1110
+ const simplifiedEntryLabel = simplifyString(entry.label);
1111
+ const simplifiedEntryType = simplifyString(entry.type);
1112
+ return simplifiedEntryLabel.includes(simplifiedSearchTerm) || simplifiedEntryType.includes(simplifiedSearchTerm);
1113
+ }, [searchTerm, simplifyString]);
914
1114
 
915
1115
  // filter entries on search change
916
1116
  useEffect(() => {
917
- const filter = entry => {
918
- if (!searchTerm) {
919
- return true;
920
- }
921
- const search = entry.label.toLowerCase();
922
- return searchTerm.toLowerCase().split(/\s/g).every(term => search.includes(term));
923
- };
924
1117
  const entries = PALETTE_ENTRIES.filter(filter);
925
1118
  setEntries(entries);
926
- }, [searchTerm]);
1119
+ }, [filter, searchTerm]);
927
1120
  const handleInput = useCallback(event => {
928
1121
  setSearchTerm(() => event.target.value);
929
1122
  }, [setSearchTerm]);
@@ -1336,6 +1529,136 @@ function FieldDragPreview(props) {
1336
1529
  });
1337
1530
  }
1338
1531
 
1532
+ const COLUMNS_REGEX = /^cds--col(-lg)?/;
1533
+ const ELEMENT_RESIZING_CLS = 'fjs-element-resizing';
1534
+ const RESIZE_DRAG_PREVIEW_CLS = 'fjs-resize-drag-preview';
1535
+ const GRID_OFFSET_PX = 16;
1536
+ function FieldResizer(props) {
1537
+ const {
1538
+ field,
1539
+ position
1540
+ } = props;
1541
+ const ref = useRef(null);
1542
+ const formLayoutValidator = useService$1('formLayoutValidator');
1543
+ const modeling = useService$1('modeling');
1544
+
1545
+ // we can't use state as we need to
1546
+ // manipulate this inside dragging events
1547
+ const context = useRef({
1548
+ startColumns: 0,
1549
+ newColumns: 0
1550
+ });
1551
+ const onResize = throttle((_, delta) => {
1552
+ const {
1553
+ x: dx
1554
+ } = delta;
1555
+ const {
1556
+ layout = {}
1557
+ } = field;
1558
+ const newColumns = calculateNewColumns(ref.current, layout.columns || context.current.startColumns, dx, position);
1559
+ const errorMessage = formLayoutValidator.validateField(field, newColumns);
1560
+ if (!errorMessage) {
1561
+ context.current.newColumns = newColumns;
1562
+
1563
+ // make visual updates to preview change
1564
+ const columnNode = ref.current.closest('.fjs-layout-column');
1565
+ removeMatching(columnNode, COLUMNS_REGEX);
1566
+ columnNode.classList.add(`cds--col-lg-${newColumns}`);
1567
+ }
1568
+ });
1569
+ const onResizeStart = event => {
1570
+ const target = getElementNode(field);
1571
+ const parent = getParent(target);
1572
+
1573
+ // create a blank element to use as drag preview
1574
+ // ensure it was only created once
1575
+ let blankPreview = getDragPreviewImage(parent);
1576
+ if (!blankPreview) {
1577
+ blankPreview = document.createElement('div');
1578
+ blankPreview.classList.add(RESIZE_DRAG_PREVIEW_CLS);
1579
+ parent.appendChild(blankPreview);
1580
+ }
1581
+
1582
+ // initialize drag handler
1583
+ const onDragStart = createDragger(onResize, blankPreview);
1584
+ onDragStart(event);
1585
+
1586
+ // mitigate auto columns on the grid that
1587
+ // has a offset of 16px (1rem) to both side
1588
+ const columnNode = getColumnNode(target);
1589
+ const startWidth = columnNode.getBoundingClientRect().width + GRID_OFFSET_PX;
1590
+ context.current.startColumns = asColumns(startWidth, parent);
1591
+ setResizing(target, position);
1592
+ };
1593
+ const onResizeEnd = () => {
1594
+ const {
1595
+ layout = {}
1596
+ } = field;
1597
+ if (context.current.newColumns) {
1598
+ modeling.editFormField(field, 'layout', {
1599
+ ...layout,
1600
+ columns: context.current.newColumns
1601
+ });
1602
+ }
1603
+ const target = getElementNode(field);
1604
+ unsetResizing(target, position);
1605
+ context.current.newColumns = null;
1606
+
1607
+ // remove blank preview
1608
+ const blankPreview = getDragPreviewImage(getParent(target));
1609
+ blankPreview.remove();
1610
+ };
1611
+ if (field.type === 'default') {
1612
+ return null;
1613
+ }
1614
+ return jsx("div", {
1615
+ ref: ref,
1616
+ class: classnames('fjs-field-resize-handle', 'fjs-field-resize-handle-' + position, DRAG_NO_MOVE_CLS),
1617
+ draggable: true,
1618
+ onDragStart: onResizeStart,
1619
+ onDragEnd: onResizeEnd
1620
+ });
1621
+ }
1622
+
1623
+ // helper //////
1624
+
1625
+ function asColumns(width, parent) {
1626
+ const totalWidth = parent.getBoundingClientRect().width;
1627
+ const oneColumn = 1 / 16 * totalWidth;
1628
+ return Math.round(width / oneColumn);
1629
+ }
1630
+ function calculateNewColumns(node, currentColumns, deltaX, position) {
1631
+ const parent = getParent(node);
1632
+
1633
+ // invert delta if we are resizing from the left
1634
+ if (position === 'left') {
1635
+ deltaX = deltaX * -1;
1636
+ }
1637
+ const deltaColumns = asColumns(deltaX, parent);
1638
+ return currentColumns + deltaColumns;
1639
+ }
1640
+ function getParent(node) {
1641
+ return node.closest('.fjs-layout-row');
1642
+ }
1643
+ function removeMatching(node, regex) {
1644
+ return classes(node).removeMatching(regex);
1645
+ }
1646
+ function getColumnNode(node) {
1647
+ return node.closest('.fjs-layout-column');
1648
+ }
1649
+ function getElementNode(field) {
1650
+ return query('.fjs-element[data-id="' + field.id + '"]');
1651
+ }
1652
+ function getDragPreviewImage(node) {
1653
+ return query('.fjs-resize-drag-preview', node);
1654
+ }
1655
+ function setResizing(node, position) {
1656
+ classes(node).add(ELEMENT_RESIZING_CLS + '-' + position);
1657
+ }
1658
+ function unsetResizing(node, position) {
1659
+ classes(node).remove(ELEMENT_RESIZING_CLS + '-' + position);
1660
+ }
1661
+
1339
1662
  function ContextPad(props) {
1340
1663
  if (!props.children) {
1341
1664
  return null;
@@ -1407,9 +1730,15 @@ function Element(props) {
1407
1730
  children: selection.isSelected(field) && field.type !== 'default' ? jsx("button", {
1408
1731
  class: "fjs-context-pad-item",
1409
1732
  onClick: onRemove,
1410
- children: jsx(ListDeleteIcon, {})
1733
+ children: jsx(DeleteIcon$1, {})
1411
1734
  }) : null
1412
- }), props.children]
1735
+ }), props.children, jsx(FieldResizer, {
1736
+ position: "left",
1737
+ field: field
1738
+ }), jsx(FieldResizer, {
1739
+ position: "right",
1740
+ field: field
1741
+ })]
1413
1742
  });
1414
1743
  }
1415
1744
  function DebugColumns(props) {
@@ -1494,8 +1823,12 @@ function FormEditor$1(props) {
1494
1823
  propertiesPanel = useService$1('propertiesPanel'),
1495
1824
  propertiesPanelConfig = useService$1('config.propertiesPanel');
1496
1825
  const {
1497
- schema
1826
+ schema,
1827
+ properties
1498
1828
  } = formEditor._getState();
1829
+ const {
1830
+ ariaLabel
1831
+ } = properties;
1499
1832
  const formContainerRef = useRef(null);
1500
1833
  const paletteRef = useRef(null);
1501
1834
  const propertiesPanelRef = useRef(null);
@@ -1581,6 +1914,7 @@ function FormEditor$1(props) {
1581
1914
  data: {},
1582
1915
  errors: {},
1583
1916
  properties: {
1917
+ ariaLabel,
1584
1918
  readOnly: true
1585
1919
  },
1586
1920
  schema
@@ -1767,6 +2101,12 @@ var core = {
1767
2101
  fieldFactory: ['type', FieldFactory]
1768
2102
  };
1769
2103
 
2104
+ /**
2105
+ * @typedef {import('didi').Injector} Injector
2106
+ *
2107
+ * @typedef {import('../../core/EventBus').default} EventBus
2108
+ */
2109
+
1770
2110
  var NOT_REGISTERED_ERROR = 'is not a registered action',
1771
2111
  IS_REGISTERED_ERROR = 'is already registered';
1772
2112
 
@@ -1896,10 +2236,10 @@ EditorActions.prototype._registerDefaultActions = function (injector) {
1896
2236
  /**
1897
2237
  * Triggers a registered action
1898
2238
  *
1899
- * @param {string} action
1900
- * @param {Object} opts
2239
+ * @param {string} action
2240
+ * @param {Object} opts
1901
2241
  *
1902
- * @return {Unknown} Returns what the registered listener returns
2242
+ * @return {unknown} Returns what the registered listener returns
1903
2243
  */
1904
2244
  EditorActions.prototype.trigger = function (action, opts) {
1905
2245
  if (!this._actions[action]) {
@@ -1928,7 +2268,7 @@ EditorActions.prototype.trigger = function (action, opts) {
1928
2268
  * editorActions.isRegistered('spaceTool'); // true
1929
2269
  * ´´´
1930
2270
  *
1931
- * @param {Object} actions
2271
+ * @param {Object} actions
1932
2272
  */
1933
2273
  EditorActions.prototype.register = function (actions, listener) {
1934
2274
  var self = this;
@@ -1943,8 +2283,8 @@ EditorActions.prototype.register = function (actions, listener) {
1943
2283
  /**
1944
2284
  * Registers a listener to an action key
1945
2285
  *
1946
- * @param {string} action
1947
- * @param {Function} listener
2286
+ * @param {string} action
2287
+ * @param {Function} listener
1948
2288
  */
1949
2289
  EditorActions.prototype._registerAction = function (action, listener) {
1950
2290
  if (this.isRegistered(action)) {
@@ -1988,6 +2328,9 @@ function error(action, message) {
1988
2328
  return new Error(action + ' ' + message);
1989
2329
  }
1990
2330
 
2331
+ /**
2332
+ * @type { import('didi').ModuleDeclaration }
2333
+ */
1991
2334
  var EditorActionsModule$1 = {
1992
2335
  __init__: ['editorActions'],
1993
2336
  editorActions: ['type', EditorActions]
@@ -2047,10 +2390,10 @@ var DraggingModule = {
2047
2390
  dragging: ['type', Dragging]
2048
2391
  };
2049
2392
 
2050
- var KEYS_COPY = ['c', 'C', 'KeyC'];
2051
- var KEYS_PASTE = ['v', 'V', 'KeyV'];
2052
- var KEYS_REDO$1 = ['y', 'Y', 'KeyY'];
2053
- var KEYS_UNDO$1 = ['z', 'Z', 'KeyZ'];
2393
+ var KEYS_COPY = ['c', 'C'];
2394
+ var KEYS_PASTE = ['v', 'V'];
2395
+ var KEYS_REDO = ['y', 'Y'];
2396
+ var KEYS_UNDO = ['z', 'Z'];
2054
2397
 
2055
2398
  /**
2056
2399
  * Returns true if event was triggered with any modifier
@@ -2075,7 +2418,7 @@ function isCmd(event) {
2075
2418
  /**
2076
2419
  * Checks if key pressed is one of provided keys.
2077
2420
  *
2078
- * @param {string|Array<string>} keys
2421
+ * @param {string|string[]} keys
2079
2422
  * @param {KeyboardEvent} event
2080
2423
  */
2081
2424
  function isKey(keys, event) {
@@ -2096,12 +2439,16 @@ function isPaste(event) {
2096
2439
  return isCmd(event) && isKey(KEYS_PASTE, event);
2097
2440
  }
2098
2441
  function isUndo(event) {
2099
- return isCmd(event) && !isShift(event) && isKey(KEYS_UNDO$1, event);
2442
+ return isCmd(event) && !isShift(event) && isKey(KEYS_UNDO, event);
2100
2443
  }
2101
2444
  function isRedo(event) {
2102
- return isCmd(event) && (isKey(KEYS_REDO$1, event) || isKey(KEYS_UNDO$1, event) && isShift(event));
2445
+ return isCmd(event) && (isKey(KEYS_REDO, event) || isKey(KEYS_UNDO, event) && isShift(event));
2103
2446
  }
2104
2447
 
2448
+ /**
2449
+ * @typedef {import('../../core/EventBus').default} EventBus
2450
+ */
2451
+
2105
2452
  var KEYDOWN_EVENT = 'keyboard.keydown',
2106
2453
  KEYUP_EVENT = 'keyboard.keyup';
2107
2454
  var HANDLE_MODIFIER_ATTRIBUTE = 'input-handle-modified-keys';
@@ -2128,7 +2475,7 @@ var DEFAULT_PRIORITY$1 = 1000;
2128
2475
  * A default binding for the keyboard may be specified via the
2129
2476
  * `keyboard.bindTo` configuration option.
2130
2477
  *
2131
- * @param {Config} config
2478
+ * @param {Object} config
2132
2479
  * @param {EventBus} eventBus
2133
2480
  */
2134
2481
  function Keyboard(config, eventBus) {
@@ -2257,8 +2604,6 @@ function isInput(target) {
2257
2604
  }
2258
2605
 
2259
2606
  var LOW_PRIORITY$1 = 500;
2260
- var KEYS_REDO = ['y', 'Y', 'KeyY'];
2261
- var KEYS_UNDO = ['z', 'Z', 'KeyZ'];
2262
2607
 
2263
2608
  /**
2264
2609
  * Adds default keyboard bindings.
@@ -2389,6 +2734,9 @@ KeyboardBindings.prototype.registerBindings = function (keyboard, editorActions)
2389
2734
  });
2390
2735
  };
2391
2736
 
2737
+ /**
2738
+ * @type { import('didi').ModuleDeclaration }
2739
+ */
2392
2740
  var KeyboardModule$1 = {
2393
2741
  __init__: ['keyboard', 'keyboardBindings'],
2394
2742
  keyboard: ['type', Keyboard],
@@ -2924,32 +3272,46 @@ class Modeling {
2924
3272
  }
2925
3273
  Modeling.$inject = ['commandStack', 'eventBus', 'formEditor', 'formFieldRegistry', 'fieldFactory'];
2926
3274
 
3275
+ /**
3276
+ * @typedef {import('../core/Types').ElementLike} ElementLike
3277
+ * @typedef {import('../core/EventBus').default} EventBus
3278
+ * @typedef {import('./CommandStack').CommandContext} CommandContext
3279
+ *
3280
+ * @typedef {string|string[]} Events
3281
+ * @typedef { (context: CommandContext) => ElementLike[] | void } HandlerFunction
3282
+ * @typedef { (context: CommandContext) => void } ComposeHandlerFunction
3283
+ */
3284
+
2927
3285
  var DEFAULT_PRIORITY = 1000;
2928
3286
 
2929
3287
  /**
2930
- * A utility that can be used to plug-in into the command execution for
3288
+ * A utility that can be used to plug into the command execution for
2931
3289
  * extension and/or validation.
2932
3290
  *
2933
- * @param {EventBus} eventBus
3291
+ * @class
3292
+ * @constructor
2934
3293
  *
2935
3294
  * @example
2936
3295
  *
2937
- * import inherits from 'inherits-browser';
2938
- *
3296
+ * ```javascript
2939
3297
  * import CommandInterceptor from 'diagram-js/lib/command/CommandInterceptor';
2940
3298
  *
2941
- * function CommandLogger(eventBus) {
2942
- * CommandInterceptor.call(this, eventBus);
3299
+ * class CommandLogger extends CommandInterceptor {
3300
+ * constructor(eventBus) {
3301
+ * super(eventBus);
2943
3302
  *
2944
- * this.preExecute(function(event) {
2945
- * console.log('command pre-execute', event);
3303
+ * this.preExecute('shape.create', (event) => {
3304
+ * console.log('commandStack.shape-create.preExecute', event);
2946
3305
  * });
2947
3306
  * }
3307
+ * ```
2948
3308
  *
2949
- * inherits(CommandLogger, CommandInterceptor);
2950
- *
3309
+ * @param {EventBus} eventBus
2951
3310
  */
2952
3311
  function CommandInterceptor(eventBus) {
3312
+ /**
3313
+ * @type {EventBus}
3314
+ */
2953
3315
  this._eventBus = eventBus;
2954
3316
  }
2955
3317
  CommandInterceptor.$inject = ['eventBus'];
@@ -2960,15 +3322,14 @@ function unwrapEvent(fn, that) {
2960
3322
  }
2961
3323
 
2962
3324
  /**
2963
- * Register an interceptor for a command execution
2964
- *
2965
- * @param {string|Array<string>} [events] list of commands to register on
2966
- * @param {string} [hook] command hook, i.e. preExecute, executed to listen on
2967
- * @param {number} [priority] the priority on which to hook into the execution
2968
- * @param {Function} handlerFn interceptor to be invoked with (event)
2969
- * @param {boolean} unwrap if true, unwrap the event and pass (context, command, event) to the
2970
- * listener instead
2971
- * @param {Object} [that] Pass context (`this`) to the handler function
3325
+ * Intercept a command during one of the phases.
3326
+ *
3327
+ * @param {Events} [events] command(s) to intercept
3328
+ * @param {string} [hook] phase to intercept
3329
+ * @param {number} [priority]
3330
+ * @param {ComposeHandlerFunction|HandlerFunction} handlerFn
3331
+ * @param {boolean} [unwrap] whether the event should be unwrapped
3332
+ * @param {any} [that]
2972
3333
  */
2973
3334
  CommandInterceptor.prototype.on = function (events, hook, priority, handlerFn, unwrap, that) {
2974
3335
  if (isFunction(hook) || isNumber(hook)) {
@@ -3003,28 +3364,130 @@ CommandInterceptor.prototype.on = function (events, hook, priority, handlerFn, u
3003
3364
  eventBus.on(fullEvent, priority, unwrap ? unwrapEvent(handlerFn, that) : handlerFn, that);
3004
3365
  });
3005
3366
  };
3006
- var hooks = ['canExecute', 'preExecute', 'preExecuted', 'execute', 'executed', 'postExecute', 'postExecuted', 'revert', 'reverted'];
3367
+
3368
+ /**
3369
+ * Add a <canExecute> phase of command interceptor.
3370
+ *
3371
+ * @param {Events} [events] command(s) to intercept
3372
+ * @param {number} [priority]
3373
+ * @param {ComposeHandlerFunction|HandlerFunction} handlerFn
3374
+ * @param {boolean} [unwrap] whether the event should be unwrapped
3375
+ * @param {any} [that]
3376
+ */
3377
+ CommandInterceptor.prototype.canExecute = createHook('canExecute');
3378
+
3379
+ /**
3380
+ * Add a <preExecute> phase of command interceptor.
3381
+ *
3382
+ * @param {Events} [events] command(s) to intercept
3383
+ * @param {number} [priority]
3384
+ * @param {ComposeHandlerFunction|HandlerFunction} handlerFn
3385
+ * @param {boolean} [unwrap] whether the event should be unwrapped
3386
+ * @param {any} [that]
3387
+ */
3388
+ CommandInterceptor.prototype.preExecute = createHook('preExecute');
3389
+
3390
+ /**
3391
+ * Add a <preExecuted> phase of command interceptor.
3392
+ *
3393
+ * @param {Events} [events] command(s) to intercept
3394
+ * @param {number} [priority]
3395
+ * @param {ComposeHandlerFunction|HandlerFunction} handlerFn
3396
+ * @param {boolean} [unwrap] whether the event should be unwrapped
3397
+ * @param {any} [that]
3398
+ */
3399
+ CommandInterceptor.prototype.preExecuted = createHook('preExecuted');
3400
+
3401
+ /**
3402
+ * Add a <execute> phase of command interceptor.
3403
+ *
3404
+ * @param {Events} [events] command(s) to intercept
3405
+ * @param {number} [priority]
3406
+ * @param {ComposeHandlerFunction|HandlerFunction} handlerFn
3407
+ * @param {boolean} [unwrap] whether the event should be unwrapped
3408
+ * @param {any} [that]
3409
+ */
3410
+ CommandInterceptor.prototype.execute = createHook('execute');
3411
+
3412
+ /**
3413
+ * Add a <executed> phase of command interceptor.
3414
+ *
3415
+ * @param {Events} [events] command(s) to intercept
3416
+ * @param {number} [priority]
3417
+ * @param {ComposeHandlerFunction|HandlerFunction} handlerFn
3418
+ * @param {boolean} [unwrap] whether the event should be unwrapped
3419
+ * @param {any} [that]
3420
+ */
3421
+ CommandInterceptor.prototype.executed = createHook('executed');
3422
+
3423
+ /**
3424
+ * Add a <postExecute> phase of command interceptor.
3425
+ *
3426
+ * @param {Events} [events] command(s) to intercept
3427
+ * @param {number} [priority]
3428
+ * @param {ComposeHandlerFunction|HandlerFunction} handlerFn
3429
+ * @param {boolean} [unwrap] whether the event should be unwrapped
3430
+ * @param {any} [that]
3431
+ */
3432
+ CommandInterceptor.prototype.postExecute = createHook('postExecute');
3433
+
3434
+ /**
3435
+ * Add a <postExecuted> phase of command interceptor.
3436
+ *
3437
+ * @param {Events} [events] command(s) to intercept
3438
+ * @param {number} [priority]
3439
+ * @param {ComposeHandlerFunction|HandlerFunction} handlerFn
3440
+ * @param {boolean} [unwrap] whether the event should be unwrapped
3441
+ * @param {any} [that]
3442
+ */
3443
+ CommandInterceptor.prototype.postExecuted = createHook('postExecuted');
3444
+
3445
+ /**
3446
+ * Add a <revert> phase of command interceptor.
3447
+ *
3448
+ * @param {Events} [events] command(s) to intercept
3449
+ * @param {number} [priority]
3450
+ * @param {ComposeHandlerFunction|HandlerFunction} handlerFn
3451
+ * @param {boolean} [unwrap] whether the event should be unwrapped
3452
+ * @param {any} [that]
3453
+ */
3454
+ CommandInterceptor.prototype.revert = createHook('revert');
3455
+
3456
+ /**
3457
+ * Add a <reverted> phase of command interceptor.
3458
+ *
3459
+ * @param {Events} [events] command(s) to intercept
3460
+ * @param {number} [priority]
3461
+ * @param {ComposeHandlerFunction|HandlerFunction} handlerFn
3462
+ * @param {boolean} [unwrap] whether the event should be unwrapped
3463
+ * @param {any} [that]
3464
+ */
3465
+ CommandInterceptor.prototype.reverted = createHook('reverted');
3007
3466
 
3008
3467
  /*
3009
- * Install hook shortcuts
3468
+ * Add prototype methods for each phase of command execution (e.g. execute,
3469
+ * revert).
3010
3470
  *
3011
- * This will generate the CommandInterceptor#(preExecute|...|reverted) methods
3012
- * which will in term forward to CommandInterceptor#on.
3471
+ * @param {string} hook
3472
+ *
3473
+ * @return { (
3474
+ * events?: Events,
3475
+ * priority?: number,
3476
+ * handlerFn: ComposeHandlerFunction|HandlerFunction,
3477
+ * unwrap?: boolean
3478
+ * ) => any }
3013
3479
  */
3014
- forEach(hooks, function (hook) {
3480
+ function createHook(hook) {
3015
3481
  /**
3016
- * {canExecute|preExecute|preExecuted|execute|executed|postExecute|postExecuted|revert|reverted}
3017
- *
3018
- * A named hook for plugging into the command execution
3482
+ * @this {CommandInterceptor}
3019
3483
  *
3020
- * @param {string|Array<string>} [events] list of commands to register on
3021
- * @param {number} [priority] the priority on which to hook into the execution
3022
- * @param {Function} handlerFn interceptor to be invoked with (event)
3023
- * @param {boolean} [unwrap=false] if true, unwrap the event and pass (context, command, event) to the
3024
- * listener instead
3025
- * @param {Object} [that] Pass context (`this`) to the handler function
3484
+ * @param {Events} [events]
3485
+ * @param {number} [priority]
3486
+ * @param {ComposeHandlerFunction|HandlerFunction} handlerFn
3487
+ * @param {boolean} [unwrap]
3488
+ * @param {any} [that]
3026
3489
  */
3027
- CommandInterceptor.prototype[hook] = function (events, priority, handlerFn, unwrap, that) {
3490
+ const hookFn = function (events, priority, handlerFn, unwrap, that) {
3028
3491
  if (isFunction(events) || isNumber(events)) {
3029
3492
  that = unwrap;
3030
3493
  unwrap = handlerFn;
@@ -3034,7 +3497,8 @@ forEach(hooks, function (hook) {
3034
3497
  }
3035
3498
  this.on(events, hook, priority, handlerFn, unwrap, that);
3036
3499
  };
3037
- });
3500
+ return hookFn;
3501
+ }
3038
3502
 
3039
3503
  class FormLayoutUpdater extends CommandInterceptor {
3040
3504
  constructor(eventBus, formLayouter, modeling, formEditor) {
@@ -3172,6 +3636,34 @@ var behaviorModule = {
3172
3636
  validateBehavior: ['type', ValidateBehavior]
3173
3637
  };
3174
3638
 
3639
+ /**
3640
+ * @typedef {import('didi').Injector} Injector
3641
+ *
3642
+ * @typedef {import('../core/Types').ElementLike} ElementLike
3643
+ *
3644
+ * @typedef {import('../core/EventBus').default} EventBus
3645
+ * @typedef {import('./CommandHandler').default} CommandHandler
3646
+ *
3647
+ * @typedef { any } CommandContext
3648
+ * @typedef { {
3649
+ * new (...args: any[]) : CommandHandler
3650
+ * } } CommandHandlerConstructor
3651
+ * @typedef { {
3652
+ * [key: string]: CommandHandler;
3653
+ * } } CommandHandlerMap
3654
+ * @typedef { {
3655
+ * command: string;
3656
+ * context: any;
3657
+ * id?: any;
3658
+ * } } CommandStackAction
3659
+ * @typedef { {
3660
+ * actions: CommandStackAction[];
3661
+ * dirty: ElementLike[];
3662
+ * trigger: 'execute' | 'undo' | 'redo' | 'clear' | null;
3663
+ * atomic?: boolean;
3664
+ * } } CurrentExecution
3665
+ */
3666
+
3175
3667
  /**
3176
3668
  * A service that offers un- and redoable execution of commands.
3177
3669
  *
@@ -3222,7 +3714,7 @@ var behaviorModule = {
3222
3714
  * got changed during the `execute` and `revert` operations.
3223
3715
  *
3224
3716
  * Command handlers may execute other modeling operations (and thus
3225
- * commands) in their `preExecute` and `postExecute` phases. The command
3717
+ * commands) in their `preExecute(d)` and `postExecute(d)` phases. The command
3226
3718
  * stack will properly group all commands together into a logical unit
3227
3719
  * that may be re- and undone atomically.
3228
3720
  *
@@ -3252,14 +3744,14 @@ function CommandStack(eventBus, injector) {
3252
3744
  /**
3253
3745
  * A map of all registered command handlers.
3254
3746
  *
3255
- * @type {Object}
3747
+ * @type {CommandHandlerMap}
3256
3748
  */
3257
3749
  this._handlerMap = {};
3258
3750
 
3259
3751
  /**
3260
3752
  * A stack containing all re/undoable actions on the diagram
3261
3753
  *
3262
- * @type {Array<Object>}
3754
+ * @type {CommandStackAction[]}
3263
3755
  */
3264
3756
  this._stack = [];
3265
3757
 
@@ -3273,18 +3765,27 @@ function CommandStack(eventBus, injector) {
3273
3765
  /**
3274
3766
  * Current active commandStack execution
3275
3767
  *
3276
- * @type {Object}
3277
- * @property {Object[]} actions
3278
- * @property {Object[]} dirty
3279
- * @property { 'undo' | 'redo' | 'clear' | 'execute' | null } trigger the cause of the current excecution
3768
+ * @type {CurrentExecution}
3280
3769
  */
3281
3770
  this._currentExecution = {
3282
3771
  actions: [],
3283
3772
  dirty: [],
3284
3773
  trigger: null
3285
3774
  };
3775
+
3776
+ /**
3777
+ * @type {Injector}
3778
+ */
3286
3779
  this._injector = injector;
3780
+
3781
+ /**
3782
+ * @type EventBus
3783
+ */
3287
3784
  this._eventBus = eventBus;
3785
+
3786
+ /**
3787
+ * @type { number }
3788
+ */
3288
3789
  this._uid = 1;
3289
3790
  eventBus.on(['diagram.destroy', 'diagram.clear'], function () {
3290
3791
  this.clear(false);
@@ -3293,10 +3794,10 @@ function CommandStack(eventBus, injector) {
3293
3794
  CommandStack.$inject = ['eventBus', 'injector'];
3294
3795
 
3295
3796
  /**
3296
- * Execute a command
3797
+ * Execute a command.
3297
3798
  *
3298
- * @param {string} command the command to execute
3299
- * @param {Object} context the environment to execute the command in
3799
+ * @param {string} command The command to execute.
3800
+ * @param {CommandContext} context The context with which to execute the command.
3300
3801
  */
3301
3802
  CommandStack.prototype.execute = function (command, context) {
3302
3803
  if (!command) {
@@ -3309,11 +3810,11 @@ CommandStack.prototype.execute = function (command, context) {
3309
3810
  };
3310
3811
  this._pushAction(action);
3311
3812
  this._internalExecute(action);
3312
- this._popAction(action);
3813
+ this._popAction();
3313
3814
  };
3314
3815
 
3315
3816
  /**
3316
- * Ask whether a given command can be executed.
3817
+ * Check whether a command can be executed.
3317
3818
  *
3318
3819
  * Implementors may hook into the mechanism on two ways:
3319
3820
  *
@@ -3327,10 +3828,10 @@ CommandStack.prototype.execute = function (command, context) {
3327
3828
  * If the method {@link CommandHandler#canExecute} is implemented in a handler
3328
3829
  * it will be called to figure out whether the execution is allowed.
3329
3830
  *
3330
- * @param {string} command the command to execute
3331
- * @param {Object} context the environment to execute the command in
3831
+ * @param {string} command The command to execute.
3832
+ * @param {CommandContext} context The context with which to execute the command.
3332
3833
  *
3333
- * @return {boolean} true if the command can be executed
3834
+ * @return {boolean} Whether the command can be executed with the given context.
3334
3835
  */
3335
3836
  CommandStack.prototype.canExecute = function (command, context) {
3336
3837
  const action = {
@@ -3354,7 +3855,9 @@ CommandStack.prototype.canExecute = function (command, context) {
3354
3855
  };
3355
3856
 
3356
3857
  /**
3357
- * Clear the command stack, erasing all undo / redo history
3858
+ * Clear the command stack, erasing all undo / redo history.
3859
+ *
3860
+ * @param {boolean} [emit=true] Whether to fire an event. Defaults to `true`.
3358
3861
  */
3359
3862
  CommandStack.prototype.clear = function (emit) {
3360
3863
  this._stack.length = 0;
@@ -3409,21 +3912,21 @@ CommandStack.prototype.redo = function () {
3409
3912
  };
3410
3913
 
3411
3914
  /**
3412
- * Register a handler instance with the command stack
3915
+ * Register a handler instance with the command stack.
3413
3916
  *
3414
- * @param {string} command
3415
- * @param {CommandHandler} handler
3917
+ * @param {string} command Command to be executed.
3918
+ * @param {CommandHandler} handler Handler to execute the command.
3416
3919
  */
3417
3920
  CommandStack.prototype.register = function (command, handler) {
3418
3921
  this._setHandler(command, handler);
3419
3922
  };
3420
3923
 
3421
3924
  /**
3422
- * Register a handler type with the command stack
3423
- * by instantiating it and injecting its dependencies.
3925
+ * Register a handler type with the command stack by instantiating it and
3926
+ * injecting its dependencies.
3424
3927
  *
3425
- * @param {string} command
3426
- * @param {Function} a constructor for a {@link CommandHandler}
3928
+ * @param {string} command Command to be executed.
3929
+ * @param {CommandHandlerConstructor} handlerCls Constructor to instantiate a {@link CommandHandler}.
3427
3930
  */
3428
3931
  CommandStack.prototype.registerHandler = function (command, handlerCls) {
3429
3932
  if (!command || !handlerCls) {
@@ -3432,9 +3935,17 @@ CommandStack.prototype.registerHandler = function (command, handlerCls) {
3432
3935
  const handler = this._injector.instantiate(handlerCls);
3433
3936
  this.register(command, handler);
3434
3937
  };
3938
+
3939
+ /**
3940
+ * @return {boolean}
3941
+ */
3435
3942
  CommandStack.prototype.canUndo = function () {
3436
3943
  return !!this._getUndoAction();
3437
3944
  };
3945
+
3946
+ /**
3947
+ * @return {boolean}
3948
+ */
3438
3949
  CommandStack.prototype.canRedo = function () {
3439
3950
  return !!this._getRedoAction();
3440
3951
  };
@@ -3528,7 +4039,7 @@ CommandStack.prototype._internalExecute = function (action, redo) {
3528
4039
  }
3529
4040
  this._fire(command, 'postExecuted', action);
3530
4041
  }
3531
- this._popAction(action);
4042
+ this._popAction();
3532
4043
  };
3533
4044
  CommandStack.prototype._pushAction = function (action) {
3534
4045
  const execution = this._currentExecution,
@@ -3589,6 +4100,9 @@ CommandStack.prototype._setHandler = function (command, handler) {
3589
4100
  this._handlerMap[command] = handler;
3590
4101
  };
3591
4102
 
4103
+ /**
4104
+ * @type { import('didi').ModuleDeclaration }
4105
+ */
3592
4106
  var commandModule = {
3593
4107
  commandStack: ['type', CommandStack]
3594
4108
  };
@@ -6334,7 +6848,7 @@ function Columns(props) {
6334
6848
  },
6335
6849
  // todo(pinussilvestrus): make options dependant on field type
6336
6850
  // cf. https://github.com/bpmn-io/form-js/issues/575
6337
- ...[2, 4, 6, 8, 10, 12, 14, 16].map(asOption)];
6851
+ ...asArray(16).filter(i => i >= MIN_COLUMNS).map(asOption)];
6338
6852
  };
6339
6853
  return SelectEntry({
6340
6854
  debounce,
@@ -6356,6 +6870,11 @@ function asOption(number) {
6356
6870
  label: number.toString()
6357
6871
  };
6358
6872
  }
6873
+ function asArray(length) {
6874
+ return Array.from({
6875
+ length
6876
+ }).map((_, i) => i + 1);
6877
+ }
6359
6878
 
6360
6879
  function DescriptionEntry(props) {
6361
6880
  const {