@bpmn-io/form-js-editor 1.0.0 → 1.2.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.
package/dist/index.es.js CHANGED
@@ -8,7 +8,7 @@ import { useContext, useState, useMemo, useEffect, useCallback, useRef as useRef
8
8
  import { createContext, Fragment, render, createElement } from 'preact';
9
9
  import * as React from 'preact/compat';
10
10
  import { createPortal, useRef, useContext as useContext$1, useEffect as useEffect$1, forwardRef } from 'preact/compat';
11
- import dragula from 'dragula';
11
+ import dragula from '@bpmn-io/draggle';
12
12
  import { classes, query, closest, event, matches, domify } from 'min-dom';
13
13
  import { mutate } from 'array-move';
14
14
  import { FeelersEditor } from 'feelers';
@@ -515,10 +515,10 @@ function invokeFunction(fn, args) {
515
515
  return fn.apply(null, args);
516
516
  }
517
517
 
518
- /**
519
- * A factory to create a configurable debouncer.
520
- *
521
- * @param {number|boolean} [config=true]
518
+ /**
519
+ * A factory to create a configurable debouncer.
520
+ *
521
+ * @param {number|boolean} [config=true]
522
522
  */
523
523
  function DebounceFactory(config = true) {
524
524
  const timeout = typeof config === 'number' ? config : config ? 300 : 0;
@@ -531,11 +531,11 @@ function DebounceFactory(config = true) {
531
531
  DebounceFactory.$inject = ['config.debounce'];
532
532
 
533
533
  class FieldFactory {
534
- /**
535
- * @constructor
536
- *
537
- * @param { import('./FormFieldRegistry').default } formFieldRegistry
538
- * @param { import('@bpmn-io/form-js-viewer').FormFields } formFields
534
+ /**
535
+ * @constructor
536
+ *
537
+ * @param { import('./FormFieldRegistry').default } formFieldRegistry
538
+ * @param { import('@bpmn-io/form-js-viewer').FormFields } formFields
539
539
  */
540
540
  constructor(formFieldRegistry, formFields) {
541
541
  this._formFieldRegistry = formFieldRegistry;
@@ -598,11 +598,11 @@ class FieldFactory {
598
598
  FieldFactory.$inject = ['formFieldRegistry', 'formFields'];
599
599
 
600
600
  class FormFieldRegistry extends FormFieldRegistry$1 {
601
- /**
602
- * Updates a form fields id.
603
- *
604
- * @param {Object} formField
605
- * @param {string} newId
601
+ /**
602
+ * Updates a form fields id.
603
+ *
604
+ * @param {Object} formField
605
+ * @param {string} newId
606
606
  */
607
607
  updateId(formField, newId) {
608
608
  this._validateId(newId);
@@ -623,13 +623,13 @@ class FormFieldRegistry extends FormFieldRegistry$1 {
623
623
  }
624
624
  }
625
625
 
626
- /**
627
- * Validate the suitability of the given id and signals a problem
628
- * with an exception.
629
- *
630
- * @param {string} id
631
- *
632
- * @throws {Error} if id is empty or already assigned
626
+ /**
627
+ * Validate the suitability of the given id and signals a problem
628
+ * with an exception.
629
+ *
630
+ * @param {string} id
631
+ *
632
+ * @throws {Error} if id is empty or already assigned
633
633
  */
634
634
  _validateId(id) {
635
635
  if (!id) {
@@ -646,11 +646,11 @@ const MAX_COLUMNS = 16;
646
646
  const MIN_COLUMNS = 2;
647
647
  const MAX_FIELDS_PER_ROW = 4;
648
648
  class FormLayoutValidator {
649
- /**
650
- * @constructor
651
- *
652
- * @param { import('./FormLayouter').default } formLayouter
653
- * @param { import('./FormFieldRegistry').default } formFieldRegistry
649
+ /**
650
+ * @constructor
651
+ *
652
+ * @param { import('./FormLayouter').default } formLayouter
653
+ * @param { import('./FormFieldRegistry').default } formFieldRegistry
654
654
  */
655
655
  constructor(formLayouter, formFieldRegistry) {
656
656
  this._formLayouter = formLayouter;
@@ -710,11 +710,11 @@ function calculateMaxColumnsWithAuto(autoCols) {
710
710
  }
711
711
 
712
712
  class Importer {
713
- /**
714
- * @constructor
715
- * @param { import('../core/FormFieldRegistry').default } formFieldRegistry
716
- * @param { import('../core/FieldFactory').default } fieldFactory
717
- * @param { import('../core/FormLayouter').default } formLayouter
713
+ /**
714
+ * @constructor
715
+ * @param { import('../core/FormFieldRegistry').default } formFieldRegistry
716
+ * @param { import('../core/FieldFactory').default } fieldFactory
717
+ * @param { import('../core/FormLayouter').default } formLayouter
718
718
  */
719
719
  constructor(formFieldRegistry, fieldFactory, formLayouter) {
720
720
  this._formFieldRegistry = formFieldRegistry;
@@ -722,21 +722,21 @@ class Importer {
722
722
  this._formLayouter = formLayouter;
723
723
  }
724
724
 
725
- /**
726
- * Import schema creating rows, fields, attaching additional
727
- * information to each field and adding fields to the
728
- * field registry.
729
- *
730
- * Additional information attached:
731
- *
732
- * * `id` (unless present)
733
- * * `_parent`
734
- * * `_path`
735
- *
736
- * @param {any} schema
737
- *
738
- * @typedef {{ warnings: Error[], schema: any }} ImportResult
739
- * @returns {ImportResult}
725
+ /**
726
+ * Import schema creating rows, fields, attaching additional
727
+ * information to each field and adding fields to the
728
+ * field registry.
729
+ *
730
+ * Additional information attached:
731
+ *
732
+ * * `id` (unless present)
733
+ * * `_parent`
734
+ * * `_path`
735
+ *
736
+ * @param {any} schema
737
+ *
738
+ * @typedef {{ warnings: Error[], schema: any }} ImportResult
739
+ * @returns {ImportResult}
740
740
  */
741
741
  importSchema(schema) {
742
742
  // TODO: Add warnings
@@ -754,12 +754,12 @@ class Importer {
754
754
  }
755
755
  }
756
756
 
757
- /**
758
- * @param {{[x: string]: any}} fieldAttrs
759
- * @param {String} [parentId]
760
- * @param {number} [index]
761
- *
762
- * @return {any} field
757
+ /**
758
+ * @param {{[x: string]: any}} fieldAttrs
759
+ * @param {String} [parentId]
760
+ * @param {number} [index]
761
+ *
762
+ * @return {any} field
763
763
  */
764
764
  importFormField(fieldAttrs, parentId, index) {
765
765
  const {
@@ -796,11 +796,11 @@ class Importer {
796
796
  return field;
797
797
  }
798
798
 
799
- /**
800
- * @param {Array<any>} components
801
- * @param {string} parentId
802
- *
803
- * @return {Array<any>} imported components
799
+ /**
800
+ * @param {Array<any>} components
801
+ * @param {string} parentId
802
+ *
803
+ * @return {Array<any>} imported components
804
804
  */
805
805
  importFormFields(components, parentId) {
806
806
  return components.map((component, index) => {
@@ -825,22 +825,22 @@ function editorFormFieldClasses(type, {
825
825
  });
826
826
  }
827
827
 
828
- /**
829
- * Add a dragger that calls back the passed function with
830
- * { event, delta } on drag.
831
- *
832
- * @example
833
- *
834
- * function dragMove(event, delta) {
835
- * // we are dragging (!!)
836
- * }
837
- *
838
- * domElement.addEventListener('dragstart', dragger(dragMove));
839
- *
840
- * @param {Function} fn
841
- * @param {Element} dragPreview
842
- *
843
- * @return {Function} drag start callback function
828
+ /**
829
+ * Add a dragger that calls back the passed function with
830
+ * { event, delta } on drag.
831
+ *
832
+ * @example
833
+ *
834
+ * function dragMove(event, delta) {
835
+ * // we are dragging (!!)
836
+ * }
837
+ *
838
+ * domElement.addEventListener('dragstart', dragger(dragMove));
839
+ *
840
+ * @param {Function} fn
841
+ * @param {Element} dragPreview
842
+ *
843
+ * @return {Function} drag start callback function
844
844
  */
845
845
  function createDragger(fn, dragPreview) {
846
846
  let self;
@@ -881,12 +881,12 @@ function createDragger(fn, dragPreview) {
881
881
  return onDragStart;
882
882
  }
883
883
 
884
- /**
885
- * Throttle function call according UI update cycle.
886
- *
887
- * @param {Function} fn
888
- *
889
- * @return {Function} throttled fn
884
+ /**
885
+ * Throttle function call according UI update cycle.
886
+ *
887
+ * @param {Function} fn
888
+ *
889
+ * @return {Function} throttled fn
890
890
  */
891
891
  function throttle(fn) {
892
892
  let active = false;
@@ -915,11 +915,11 @@ const DragAndDropContext = createContext({
915
915
  });
916
916
  var DragAndDropContext$1 = DragAndDropContext;
917
917
 
918
- /**
919
- * @param {string} type
920
- * @param {boolean} [strict]
921
- *
922
- * @returns {any}
918
+ /**
919
+ * @param {string} type
920
+ * @param {boolean} [strict]
921
+ *
922
+ * @returns {any}
923
923
  */
924
924
  function getService$1(type, strict) {}
925
925
  const FormEditorContext = createContext({
@@ -934,15 +934,15 @@ function useService$1 (type, strict) {
934
934
  return getService(type, strict);
935
935
  }
936
936
 
937
- var _path$3;
938
- function _extends$3() { _extends$3 = 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$3.apply(this, arguments); }
937
+ var _path$4;
938
+ function _extends$4() { _extends$4 = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$4.apply(this, arguments); }
939
939
  var SvgClose = function SvgClose(props) {
940
- return /*#__PURE__*/React.createElement("svg", _extends$3({
940
+ return /*#__PURE__*/React.createElement("svg", _extends$4({
941
941
  xmlns: "http://www.w3.org/2000/svg",
942
942
  width: 16,
943
943
  height: 16,
944
944
  fill: "currentColor"
945
- }, props), _path$3 || (_path$3 = /*#__PURE__*/React.createElement("path", {
945
+ }, props), _path$4 || (_path$4 = /*#__PURE__*/React.createElement("path", {
946
946
  fillRule: "evenodd",
947
947
  d: "m12 4.7-.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",
948
948
  clipRule: "evenodd"
@@ -950,10 +950,10 @@ var SvgClose = function SvgClose(props) {
950
950
  };
951
951
  var CloseIcon = SvgClose;
952
952
 
953
- var _path$2, _path2;
954
- 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); }
953
+ var _path$3, _path2$1;
954
+ function _extends$3() { _extends$3 = 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$3.apply(this, arguments); }
955
955
  var SvgDelete = function SvgDelete(props) {
956
- return /*#__PURE__*/React.createElement("svg", _extends$2({
956
+ return /*#__PURE__*/React.createElement("svg", _extends$3({
957
957
  xmlns: "http://www.w3.org/2000/svg",
958
958
  width: 16,
959
959
  height: 16,
@@ -974,27 +974,27 @@ var SvgDelete = function SvgDelete(props) {
974
974
  mixBlendMode: "multiply"
975
975
  },
976
976
  transform: "translate(.536)"
977
- }), _path$2 || (_path$2 = /*#__PURE__*/React.createElement("path", {
977
+ }), _path$3 || (_path$3 = /*#__PURE__*/React.createElement("path", {
978
978
  fill: "currentcolor",
979
979
  d: "M7.536 6h-1v6h1V6Zm3 0h-1v6h1V6Z"
980
- })), _path2 || (_path2 = /*#__PURE__*/React.createElement("path", {
980
+ })), _path2$1 || (_path2$1 = /*#__PURE__*/React.createElement("path", {
981
981
  fill: "currentcolor",
982
982
  d: "M2.536 3v1h1v10a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4h1V3h-12Zm2 11V4h8v10h-8Zm6-13h-4v1h4V1Z"
983
983
  })));
984
984
  };
985
985
  var DeleteIcon$1 = SvgDelete;
986
986
 
987
- var _path$1;
988
- 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); }
987
+ var _path$2;
988
+ 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); }
989
989
  var SvgDraggable = function SvgDraggable(props) {
990
- return /*#__PURE__*/React.createElement("svg", _extends$1({
990
+ return /*#__PURE__*/React.createElement("svg", _extends$2({
991
991
  xmlns: "http://www.w3.org/2000/svg",
992
992
  xmlSpace: "preserve",
993
993
  width: 16,
994
994
  height: 16,
995
995
  fill: "currentcolor",
996
996
  viewBox: "0 0 32 32"
997
- }, props), _path$1 || (_path$1 = /*#__PURE__*/React.createElement("path", {
997
+ }, props), _path$2 || (_path$2 = /*#__PURE__*/React.createElement("path", {
998
998
  d: "M10 6h4v4h-4zm8 0h4v4h-4zm-8 8h4v4h-4zm8 0h4v4h-4zm-8 8h4v4h-4zm8 0h4v4h-4z"
999
999
  })), /*#__PURE__*/React.createElement("path", {
1000
1000
  d: "M0 0h32v32H0z",
@@ -1005,21 +1005,76 @@ var SvgDraggable = function SvgDraggable(props) {
1005
1005
  };
1006
1006
  var DraggableIcon = SvgDraggable;
1007
1007
 
1008
- var _path;
1009
- 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); }
1008
+ var _path$1;
1009
+ 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); }
1010
1010
  var SvgSearch = function SvgSearch(props) {
1011
- return /*#__PURE__*/React.createElement("svg", _extends({
1011
+ return /*#__PURE__*/React.createElement("svg", _extends$1({
1012
1012
  xmlns: "http://www.w3.org/2000/svg",
1013
1013
  width: 15,
1014
1014
  height: 15,
1015
1015
  fill: "none"
1016
- }, props), _path || (_path = /*#__PURE__*/React.createElement("path", {
1016
+ }, props), _path$1 || (_path$1 = /*#__PURE__*/React.createElement("path", {
1017
1017
  fill: "currentColor",
1018
1018
  d: "m14.5 13.793-3.776-3.776a5.508 5.508 0 1 0-.707.707l3.776 3.776.707-.707ZM2 6.5a4.5 4.5 0 1 1 9 0 4.5 4.5 0 0 1-9 0Z"
1019
1019
  })));
1020
1020
  };
1021
1021
  var SearchIcon = SvgSearch;
1022
1022
 
1023
+ var _path, _rect, _mask, _path2, _path3, _path4, _path5, _path6;
1024
+ 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); }
1025
+ var SvgEmptyForm = function SvgEmptyForm(props) {
1026
+ return /*#__PURE__*/React.createElement("svg", _extends({
1027
+ xmlns: "http://www.w3.org/2000/svg",
1028
+ width: 126,
1029
+ height: 96,
1030
+ fill: "none"
1031
+ }, props), _path || (_path = /*#__PURE__*/React.createElement("path", {
1032
+ fill: "#FF832B",
1033
+ fillRule: "evenodd",
1034
+ d: "M70 78v8a3 3 0 0 1-3 3h-8v-5h6v-6h5Zm0-16h-5V46h5v16Zm0-32h-5v-6h-6v-5h8a3 3 0 0 1 3 3v8ZM43 19v5H27v-5h16Zm-32 0v5H5v6H0v-8a3 3 0 0 1 3-3h8ZM0 46h5v16H0V46Zm0 32h5v6h6v5H3a3 3 0 0 1-3-3v-8Zm27 11v-5h16v5H27Z",
1035
+ clipRule: "evenodd"
1036
+ })), _rect || (_rect = /*#__PURE__*/React.createElement("rect", {
1037
+ width: 70,
1038
+ height: 70,
1039
+ fill: "#E5E5E5",
1040
+ rx: 3,
1041
+ transform: "matrix(-1 0 0 1 94 0)"
1042
+ })), _mask || (_mask = /*#__PURE__*/React.createElement("mask", {
1043
+ id: "EmptyForm_svg__a",
1044
+ fill: "#fff"
1045
+ }, /*#__PURE__*/React.createElement("path", {
1046
+ fillRule: "evenodd",
1047
+ d: "M87.085 88.684 75.43 45.185l43.499 11.656-11.044 8.072 8.557 8.556-12.728 12.728-8.557-8.556-8.072 11.043Z",
1048
+ clipRule: "evenodd"
1049
+ }))), _path2 || (_path2 = /*#__PURE__*/React.createElement("path", {
1050
+ fill: "#393939",
1051
+ fillRule: "evenodd",
1052
+ d: "M87.085 88.684 75.43 45.185l43.499 11.656-11.044 8.072 8.557 8.556-12.728 12.728-8.557-8.556-8.072 11.043Z",
1053
+ clipRule: "evenodd"
1054
+ })), _path3 || (_path3 = /*#__PURE__*/React.createElement("path", {
1055
+ fill: "#393939",
1056
+ d: "M75.43 45.185 70.6 46.48l-2.241-8.365 8.365 2.242-1.294 4.83Zm11.655 43.499 4.037 2.95-6.163 8.432-2.704-10.088 4.83-1.294Zm31.844-31.843 1.294-4.83 10.088 2.703-8.432 6.163-2.95-4.036Zm-11.044 8.072-3.535 3.535-4.128-4.127 4.713-3.445 2.95 4.037Zm8.557 8.556 3.535-3.535 3.536 3.535-3.536 3.536-3.535-3.536Zm-12.728 12.728 3.536 3.536-3.536 3.535-3.536-3.535 3.536-3.536Zm-8.557-8.556-4.036-2.951 3.444-4.713 4.128 4.128-3.536 3.535ZM80.26 43.89 91.915 87.39l-9.66 2.588L70.6 46.48l9.66-2.588Zm37.375 17.78L74.136 50.014l2.588-9.66 43.499 11.656-2.589 9.66Zm-12.699-.795 11.043-8.072 5.901 8.073-11.043 8.072-5.901-8.073Zm7.971 16.129-8.556-8.557 7.071-7.07 8.556 8.556-7.071 7.07Zm-12.728 5.657 12.728-12.728 7.071 7.07-12.727 12.729-7.072-7.071Zm-1.485-8.557 8.557 8.557-7.072 7.07-8.556-8.556 7.07-7.071ZM83.049 85.733 91.12 74.69l8.073 5.901-8.072 11.044-8.073-5.902Z",
1057
+ mask: "url(#EmptyForm_svg__a)"
1058
+ })), _path4 || (_path4 = /*#__PURE__*/React.createElement("path", {
1059
+ stroke: "#000",
1060
+ strokeLinecap: "round",
1061
+ strokeWidth: 3,
1062
+ d: "m69.431 39.163-9.192-9.192"
1063
+ })), _path5 || (_path5 = /*#__PURE__*/React.createElement("path", {
1064
+ stroke: "#000",
1065
+ strokeLinecap: "round",
1066
+ strokeWidth: 3,
1067
+ d: "M1.5-1.5h8",
1068
+ transform: "matrix(-1 0 0 1 68.213 50.123)"
1069
+ })), _path6 || (_path6 = /*#__PURE__*/React.createElement("path", {
1070
+ stroke: "#000",
1071
+ strokeLinecap: "round",
1072
+ strokeWidth: 3,
1073
+ d: "M78.969 36.367v-8"
1074
+ })));
1075
+ };
1076
+ var EmptyFormIcon = SvgEmptyForm;
1077
+
1023
1078
  function EditorText(props) {
1024
1079
  const {
1025
1080
  type,
@@ -1028,7 +1083,7 @@ function EditorText(props) {
1028
1083
  const Icon = iconsByType('text');
1029
1084
  const templating = useService$1('templating');
1030
1085
  const expressionLanguage = useService$1('expressionLanguage');
1031
- if (!text) {
1086
+ if (!text || !text.trim()) {
1032
1087
  return jsx("div", {
1033
1088
  class: editorFormFieldClasses(type),
1034
1089
  children: jsxs("div", {
@@ -1214,23 +1269,23 @@ var Slot = (props => {
1214
1269
  return fillsAndSeparators;
1215
1270
  });
1216
1271
 
1217
- /**
1218
- * Creates a Fragment for a fill.
1219
- *
1220
- * @param {Object} fill Fill to be rendered
1221
- * @returns {Object} Preact Fragment containing fill's children
1272
+ /**
1273
+ * Creates a Fragment for a fill.
1274
+ *
1275
+ * @param {Object} fill Fill to be rendered
1276
+ * @returns {Object} Preact Fragment containing fill's children
1222
1277
  */
1223
1278
  const FillFragment = fill => jsx(Fragment, {
1224
1279
  children: fill.children
1225
1280
  }, fill.id);
1226
1281
 
1227
- /**
1228
- * Creates an array of fills, with separators inserted between groups.
1229
- *
1230
- * @param {Array} groups Groups of fills
1231
- * @param {Function} fillRenderer Function to create a fill
1232
- * @param {Function} separatorRenderer Function to create a separator
1233
- * @returns {Array} Array of fills and separators
1282
+ /**
1283
+ * Creates an array of fills, with separators inserted between groups.
1284
+ *
1285
+ * @param {Array} groups Groups of fills
1286
+ * @param {Function} fillRenderer Function to create a fill
1287
+ * @param {Function} separatorRenderer Function to create a separator
1288
+ * @returns {Array} Array of fills and separators
1234
1289
  */
1235
1290
  const buildFills = (groups, fillRenderer, separatorRenderer) => {
1236
1291
  const result = [];
@@ -1248,8 +1303,8 @@ const buildFills = (groups, fillRenderer, separatorRenderer) => {
1248
1303
  return result;
1249
1304
  };
1250
1305
 
1251
- /**
1252
- * Groups fills by group name property.
1306
+ /**
1307
+ * Groups fills by group name property.
1253
1308
  */
1254
1309
  const _groupByGroupName = fills => {
1255
1310
  const groups = [];
@@ -1269,8 +1324,8 @@ const _groupByGroupName = fills => {
1269
1324
  return Object.keys(groupsById).sort().map(id => groupsById[id]);
1270
1325
  };
1271
1326
 
1272
- /**
1273
- * Compares fills by priority.
1327
+ /**
1328
+ * Compares fills by priority.
1274
1329
  */
1275
1330
  const _comparePriority = (a, b) => {
1276
1331
  return (b.priority || 0) - (a.priority || 0);
@@ -1498,19 +1553,19 @@ const DRAG_NO_DROP_CLS = 'fjs-no-drop';
1498
1553
  const DRAG_NO_MOVE_CLS = 'fjs-no-move';
1499
1554
  const ERROR_DROP_CLS = 'fjs-error-drop';
1500
1555
 
1501
- /**
1502
- * @typedef { { id: String, components: Array<any> } } FormRow
1556
+ /**
1557
+ * @typedef { { id: String, components: Array<any> } } FormRow
1503
1558
  */
1504
1559
 
1505
1560
  class Dragging {
1506
- /**
1507
- * @constructor
1508
- *
1509
- * @param { import('../../core/FormFieldRegistry').default } formFieldRegistry
1510
- * @param { import('../../core/FormLayouter').default } formLayouter
1511
- * @param { import('../../core/FormLayoutValidator').default } formLayoutValidator
1512
- * @param { import('../../core/EventBus').default } eventBus
1513
- * @param { import('../modeling/Modeling').default } modeling
1561
+ /**
1562
+ * @constructor
1563
+ *
1564
+ * @param { import('../../core/FormFieldRegistry').default } formFieldRegistry
1565
+ * @param { import('../../core/FormLayouter').default } formLayouter
1566
+ * @param { import('../../core/FormLayoutValidator').default } formLayoutValidator
1567
+ * @param { import('../../core/EventBus').default } eventBus
1568
+ * @param { import('../modeling/Modeling').default } modeling
1514
1569
  */
1515
1570
  constructor(formFieldRegistry, formLayouter, formLayoutValidator, eventBus, modeling) {
1516
1571
  this._formFieldRegistry = formFieldRegistry;
@@ -1520,13 +1575,13 @@ class Dragging {
1520
1575
  this._modeling = modeling;
1521
1576
  }
1522
1577
 
1523
- /**
1524
- * Calculcates position in form schema given the dropped place.
1525
- *
1526
- * @param { FormRow } targetRow
1527
- * @param { any } targetFormField
1528
- * @param { HTMLElement } sibling
1529
- * @returns { number }
1578
+ /**
1579
+ * Calculcates position in form schema given the dropped place.
1580
+ *
1581
+ * @param { FormRow } targetRow
1582
+ * @param { any } targetFormField
1583
+ * @param { HTMLElement } sibling
1584
+ * @returns { number }
1530
1585
  */
1531
1586
  getTargetIndex(targetRow, targetFormField, sibling) {
1532
1587
  /** @type HTMLElement */
@@ -1628,17 +1683,21 @@ class Dragging {
1628
1683
  }
1629
1684
  }
1630
1685
 
1631
- /**
1632
- * @param { { container: Array<string>, direction: string, mirrorContainer: string } } options
1686
+ /**
1687
+ * @param { { container: Array<string>, direction: string, mirrorContainer: string } } options
1633
1688
  */
1634
1689
  createDragulaInstance(options) {
1635
1690
  const {
1636
1691
  container,
1637
- direction,
1638
1692
  mirrorContainer
1639
1693
  } = options || {};
1640
- const dragulaInstance = dragula({
1641
- direction,
1694
+ let dragulaOptions = {
1695
+ direction: function (el, target) {
1696
+ if (isRow(target)) {
1697
+ return 'horizontal';
1698
+ }
1699
+ return 'vertical';
1700
+ },
1642
1701
  mirrorContainer,
1643
1702
  isContainer(el) {
1644
1703
  return container.some(cls => el.classList.contains(cls));
@@ -1669,7 +1728,8 @@ class Dragging {
1669
1728
  },
1670
1729
  slideFactorX: 10,
1671
1730
  slideFactorY: 5
1672
- });
1731
+ };
1732
+ const dragulaInstance = dragula(dragulaOptions);
1673
1733
 
1674
1734
  // bind life cycle events
1675
1735
  dragulaInstance.on('drag', (element, source) => {
@@ -1929,7 +1989,19 @@ function ContextPad(props) {
1929
1989
  });
1930
1990
  }
1931
1991
  function Empty(props) {
1932
- return null;
1992
+ return jsx("div", {
1993
+ class: "fjs-empty-editor",
1994
+ children: jsxs("div", {
1995
+ class: "fjs-empty-editor-card",
1996
+ children: [jsx(EmptyFormIcon, {}), jsx("h2", {
1997
+ children: "Build your form"
1998
+ }), jsx("span", {
1999
+ children: "Drag and drop components here to start designing."
2000
+ }), jsx("span", {
2001
+ children: "Use the preview window to test your form."
2002
+ })]
2003
+ })
2004
+ });
1933
2005
  }
1934
2006
  function Element$1(props) {
1935
2007
  const eventBus = useService$1('eventBus'),
@@ -2026,7 +2098,7 @@ function DebugColumns(props) {
2026
2098
  return null;
2027
2099
  }
2028
2100
  return jsx("div", {
2029
- style: "width: fit-content; padding: 2px 6px; height: 16px; background: var(--color-blue-205-100-95); display: flex; justify-content: center; align-items: center; position: absolute; bottom: -2px; z-index: 2; font-size: 10px; right: 3px;",
2101
+ style: "width: fit-content;\r padding: 2px 6px;\r height: 16px;\r background: var(--color-blue-205-100-95);\r display: flex;\r justify-content: center;\r align-items: center;\r position: absolute;\r bottom: -2px;\r z-index: 2;\r font-size: 10px;\r right: 3px;",
2030
2102
  class: "fjs-debug-columns",
2031
2103
  children: (field.layout || {}).columns || 'auto'
2032
2104
  });
@@ -2123,7 +2195,6 @@ function FormEditor$1(props) {
2123
2195
  useEffect(() => {
2124
2196
  let dragulaInstance = dragging.createDragulaInstance({
2125
2197
  container: [DRAG_CONTAINER_CLS, DROP_CONTAINER_VERTICAL_CLS, DROP_CONTAINER_HORIZONTAL_CLS],
2126
- direction: 'vertical',
2127
2198
  mirrorContainer: formContainerRef.current
2128
2199
  });
2129
2200
  setDrake(dragulaInstance);
@@ -2137,7 +2208,6 @@ function FormEditor$1(props) {
2137
2208
  onDetach();
2138
2209
  dragulaInstance = dragging.createDragulaInstance({
2139
2210
  container: [DRAG_CONTAINER_CLS, DROP_CONTAINER_VERTICAL_CLS, DROP_CONTAINER_HORIZONTAL_CLS],
2140
- direction: 'vertical',
2141
2211
  mirrorContainer: formContainerRef.current
2142
2212
  });
2143
2213
  setDrake(dragulaInstance);
@@ -3085,10 +3155,10 @@ function updateRow(formField, rowId) {
3085
3155
  }
3086
3156
 
3087
3157
  class AddFormFieldHandler {
3088
- /**
3089
- * @constructor
3090
- * @param { import('../../../FormEditor').default } formEditor
3091
- * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3158
+ /**
3159
+ * @constructor
3160
+ * @param { import('../../../FormEditor').default } formEditor
3161
+ * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3092
3162
  */
3093
3163
  constructor(formEditor, formFieldRegistry) {
3094
3164
  this._formEditor = formEditor;
@@ -3149,10 +3219,10 @@ class AddFormFieldHandler {
3149
3219
  AddFormFieldHandler.$inject = ['formEditor', 'formFieldRegistry'];
3150
3220
 
3151
3221
  class EditFormFieldHandler {
3152
- /**
3153
- * @constructor
3154
- * @param { import('../../../FormEditor').default } formEditor
3155
- * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3222
+ /**
3223
+ * @constructor
3224
+ * @param { import('../../../FormEditor').default } formEditor
3225
+ * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3156
3226
  */
3157
3227
  constructor(formEditor, formFieldRegistry) {
3158
3228
  this._formEditor = formEditor;
@@ -3215,10 +3285,10 @@ class EditFormFieldHandler {
3215
3285
  EditFormFieldHandler.$inject = ['formEditor', 'formFieldRegistry'];
3216
3286
 
3217
3287
  class MoveFormFieldHandler {
3218
- /**
3219
- * @constructor
3220
- * @param { import('../../../FormEditor').default } formEditor
3221
- * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3288
+ /**
3289
+ * @constructor
3290
+ * @param { import('../../../FormEditor').default } formEditor
3291
+ * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3222
3292
  */
3223
3293
  constructor(formEditor, formFieldRegistry) {
3224
3294
  this._formEditor = formEditor;
@@ -3307,10 +3377,10 @@ class MoveFormFieldHandler {
3307
3377
  MoveFormFieldHandler.$inject = ['formEditor', 'formFieldRegistry'];
3308
3378
 
3309
3379
  class RemoveFormFieldHandler {
3310
- /**
3311
- * @constructor
3312
- * @param { import('../../../FormEditor').default } formEditor
3313
- * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3380
+ /**
3381
+ * @constructor
3382
+ * @param { import('../../../FormEditor').default } formEditor
3383
+ * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3314
3384
  */
3315
3385
  constructor(formEditor, formFieldRegistry) {
3316
3386
  this._formEditor = formEditor;
@@ -3370,9 +3440,9 @@ class RemoveFormFieldHandler {
3370
3440
  RemoveFormFieldHandler.$inject = ['formEditor', 'formFieldRegistry'];
3371
3441
 
3372
3442
  class UpdateIdClaimHandler {
3373
- /**
3374
- * @constructor
3375
- * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3443
+ /**
3444
+ * @constructor
3445
+ * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3376
3446
  */
3377
3447
  constructor(formFieldRegistry) {
3378
3448
  this._formFieldRegistry = formFieldRegistry;
@@ -3405,9 +3475,9 @@ class UpdateIdClaimHandler {
3405
3475
  UpdateIdClaimHandler.$inject = ['formFieldRegistry'];
3406
3476
 
3407
3477
  class UpdateKeyClaimHandler {
3408
- /**
3409
- * @constructor
3410
- * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3478
+ /**
3479
+ * @constructor
3480
+ * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3411
3481
  */
3412
3482
  constructor(formFieldRegistry) {
3413
3483
  this._formFieldRegistry = formFieldRegistry;
@@ -3873,8 +3943,8 @@ class ValidateBehavior extends CommandInterceptor {
3873
3943
  constructor(eventBus) {
3874
3944
  super(eventBus);
3875
3945
 
3876
- /**
3877
- * Remove custom validation if <validationType> is about to be added.
3946
+ /**
3947
+ * Remove custom validation if <validationType> is about to be added.
3878
3948
  */
3879
3949
  // @ts-ignore-next-line
3880
3950
  this.preExecute('formField.edit', function (context) {
@@ -4454,22 +4524,22 @@ var SelectionModule = {
4454
4524
  selectionBehavior: ['type', SelectionBehavior]
4455
4525
  };
4456
4526
 
4457
- /**
4458
- * Base class for sectionable UI modules.
4459
- *
4460
- * @property {EventBus} _eventBus - EventBus instance used for event handling.
4461
- * @property {string} managerType - Type of the render manager. Used to form event names.
4462
- *
4463
- * @class SectionModuleBase
4527
+ /**
4528
+ * Base class for sectionable UI modules.
4529
+ *
4530
+ * @property {EventBus} _eventBus - EventBus instance used for event handling.
4531
+ * @property {string} managerType - Type of the render manager. Used to form event names.
4532
+ *
4533
+ * @class SectionModuleBase
4464
4534
  */
4465
4535
  class SectionModuleBase {
4466
- /**
4467
- * Create a SectionModuleBase instance.
4468
- *
4469
- * @param {any} eventBus - The EventBus instance used for event handling.
4470
- * @param {string} sectionKey - The type of render manager. Used to form event names.
4471
- *
4472
- * @constructor
4536
+ /**
4537
+ * Create a SectionModuleBase instance.
4538
+ *
4539
+ * @param {any} eventBus - The EventBus instance used for event handling.
4540
+ * @param {string} sectionKey - The type of render manager. Used to form event names.
4541
+ *
4542
+ * @constructor
4473
4543
  */
4474
4544
  constructor(eventBus, sectionKey) {
4475
4545
  this._eventBus = eventBus;
@@ -4482,10 +4552,10 @@ class SectionModuleBase {
4482
4552
  });
4483
4553
  }
4484
4554
 
4485
- /**
4486
- * Attach the managed section to a parent node.
4487
- *
4488
- * @param {HTMLElement} container - The parent node to attach to.
4555
+ /**
4556
+ * Attach the managed section to a parent node.
4557
+ *
4558
+ * @param {HTMLElement} container - The parent node to attach to.
4489
4559
  */
4490
4560
  attachTo(container) {
4491
4561
  this._onceSectionRendered(() => this._eventBus.fire(`${this._sectionKey}.attach`, {
@@ -4493,22 +4563,22 @@ class SectionModuleBase {
4493
4563
  }));
4494
4564
  }
4495
4565
 
4496
- /**
4497
- * Detach the managed section from its parent node.
4566
+ /**
4567
+ * Detach the managed section from its parent node.
4498
4568
  */
4499
4569
  detach() {
4500
4570
  this._onceSectionRendered(() => this._eventBus.fire(`${this._sectionKey}.detach`));
4501
4571
  }
4502
4572
 
4503
- /**
4504
- * Reset the managed section to its initial state.
4573
+ /**
4574
+ * Reset the managed section to its initial state.
4505
4575
  */
4506
4576
  reset() {
4507
4577
  this._onceSectionRendered(() => this._eventBus.fire(`${this._sectionKey}.reset`));
4508
4578
  }
4509
4579
 
4510
- /**
4511
- * Circumvents timing issues.
4580
+ /**
4581
+ * Circumvents timing issues.
4512
4582
  */
4513
4583
  _onceSectionRendered(callback) {
4514
4584
  if (this.isSectionRendered) {
@@ -4683,6 +4753,166 @@ const LayoutContext = createContext({
4683
4753
  getLayoutForKey: () => {},
4684
4754
  setLayoutForKey: () => {}
4685
4755
  });
4756
+ const TooltipContext = createContext({
4757
+ tooltip: {},
4758
+ getTooltipForId: () => {}
4759
+ });
4760
+
4761
+ /**
4762
+ * Accesses the global TooltipContext and returns a tooltip for a given id and element.
4763
+ *
4764
+ * @example
4765
+ * ```jsx
4766
+ * function TextField(props) {
4767
+ * const tooltip = useTooltipContext('input1', element);
4768
+ * }
4769
+ * ```
4770
+ *
4771
+ * @param {string} id
4772
+ * @param {object} element
4773
+ *
4774
+ * @returns {string}
4775
+ */
4776
+ function useTooltipContext(id, element) {
4777
+ const {
4778
+ getTooltipForId
4779
+ } = useContext(TooltipContext);
4780
+ return getTooltipForId(id, element);
4781
+ }
4782
+ function TooltipWrapper(props) {
4783
+ const {
4784
+ forId,
4785
+ element
4786
+ } = props;
4787
+ const contextDescription = useTooltipContext(forId, element);
4788
+ const value = props.value || contextDescription;
4789
+ if (!value) {
4790
+ return props.children;
4791
+ }
4792
+ return jsx(Tooltip, {
4793
+ ...props,
4794
+ value: value,
4795
+ forId: prefixId$8(forId)
4796
+ });
4797
+ }
4798
+ function Tooltip(props) {
4799
+ const {
4800
+ forId,
4801
+ value,
4802
+ parent
4803
+ } = props;
4804
+ const [visible, setShow] = useState(false);
4805
+ let timeout = null;
4806
+ const wrapperRef = useRef$1(null);
4807
+ const tooltipRef = useRef$1(null);
4808
+ const showTooltip = async event => {
4809
+ const show = () => !visible && setShow(true);
4810
+ if (event instanceof MouseEvent) {
4811
+ timeout = setTimeout(show, 200);
4812
+ } else {
4813
+ show();
4814
+ }
4815
+ };
4816
+ const hideTooltip = () => setShow(false);
4817
+ const hideTooltipViaEscape = e => {
4818
+ e.code === 'Escape' && hideTooltip();
4819
+ };
4820
+ const isTooltipHovered = ({
4821
+ x,
4822
+ y
4823
+ }) => {
4824
+ const tooltip = tooltipRef.current;
4825
+ const wrapper = wrapperRef.current;
4826
+ return tooltip && (inBounds(x, y, wrapper.getBoundingClientRect()) || inBounds(x, y, tooltip.getBoundingClientRect()));
4827
+ };
4828
+ useEffect(() => {
4829
+ const {
4830
+ current
4831
+ } = wrapperRef;
4832
+ if (!current) {
4833
+ return;
4834
+ }
4835
+ const hideHoveredTooltip = e => {
4836
+ const isFocused = document.activeElement === wrapperRef.current || document.activeElement.closest('.bio-properties-panel-tooltip');
4837
+ if (visible && !isTooltipHovered({
4838
+ x: e.x,
4839
+ y: e.y
4840
+ }) && !isFocused) {
4841
+ hideTooltip();
4842
+ }
4843
+ };
4844
+ const hideFocusedTooltip = e => {
4845
+ const {
4846
+ relatedTarget
4847
+ } = e;
4848
+ const isTooltipChild = el => el && !!el.closest('.bio-properties-panel-tooltip');
4849
+ if (visible && !isHovered(wrapperRef.current) && !isTooltipChild(relatedTarget)) {
4850
+ hideTooltip();
4851
+ }
4852
+ };
4853
+ document.addEventListener('wheel', hideHoveredTooltip);
4854
+ document.addEventListener('focusout', hideFocusedTooltip);
4855
+ document.addEventListener('mousemove', hideHoveredTooltip);
4856
+ return () => {
4857
+ document.removeEventListener('wheel', hideHoveredTooltip);
4858
+ document.removeEventListener('mousemove', hideHoveredTooltip);
4859
+ document.removeEventListener('focusout', hideFocusedTooltip);
4860
+ };
4861
+ }, [wrapperRef.current, visible]);
4862
+ const renderTooltip = () => {
4863
+ return jsxs("div", {
4864
+ class: "bio-properties-panel-tooltip",
4865
+ role: "tooltip",
4866
+ id: "bio-properties-panel-tooltip",
4867
+ "aria-labelledby": forId,
4868
+ style: getTooltipPosition(wrapperRef.current),
4869
+ ref: tooltipRef,
4870
+ onClick: e => e.stopPropagation(),
4871
+ children: [jsx("div", {
4872
+ class: "bio-properties-panel-tooltip-content",
4873
+ children: value
4874
+ }), jsx("div", {
4875
+ class: "bio-properties-panel-tooltip-arrow"
4876
+ })]
4877
+ });
4878
+ };
4879
+ return jsxs("div", {
4880
+ class: "bio-properties-panel-tooltip-wrapper",
4881
+ tabIndex: "0",
4882
+ ref: wrapperRef,
4883
+ onMouseEnter: showTooltip,
4884
+ onMouseLeave: () => clearTimeout(timeout),
4885
+ onFocus: showTooltip,
4886
+ onKeyDown: hideTooltipViaEscape,
4887
+ onMouseDown: e => {
4888
+ e.preventDefault();
4889
+ },
4890
+ children: [props.children, visible ? parent ? createPortal(renderTooltip(), parent.current) : renderTooltip() : null]
4891
+ });
4892
+ }
4893
+
4894
+ // helper
4895
+ function inBounds(x, y, bounds) {
4896
+ const {
4897
+ top,
4898
+ right,
4899
+ bottom,
4900
+ left
4901
+ } = bounds;
4902
+ return x >= left && x <= right && y >= top && y <= bottom;
4903
+ }
4904
+ function getTooltipPosition(refElement) {
4905
+ const refPosition = refElement.getBoundingClientRect();
4906
+ const right = `calc(100% - ${refPosition.x}px)`;
4907
+ const top = `${refPosition.top - 10}px`;
4908
+ return `right: ${right}; top: ${top};`;
4909
+ }
4910
+ function isHovered(element) {
4911
+ return element.matches(':hover');
4912
+ }
4913
+ function prefixId$8(id) {
4914
+ return `bio-properties-panel-${id}`;
4915
+ }
4686
4916
 
4687
4917
  /**
4688
4918
  * Accesses the global DescriptionContext and returns a description for a given id and element.
@@ -4711,6 +4941,12 @@ function useError(id) {
4711
4941
  } = useContext(ErrorsContext);
4712
4942
  return errors[id];
4713
4943
  }
4944
+ function useErrors() {
4945
+ const {
4946
+ errors
4947
+ } = useContext(ErrorsContext);
4948
+ return errors;
4949
+ }
4714
4950
 
4715
4951
  /**
4716
4952
  * Subscribe to an event immediately. Update subscription after inputs changed.
@@ -4942,6 +5178,10 @@ function Group(props) {
4942
5178
  setEdited(hasOneEditedEntry);
4943
5179
  }, [entries]);
4944
5180
 
5181
+ // set error state depending on all entries
5182
+ const allErrors = useErrors();
5183
+ const hasErrors = entries.some(entry => allErrors[entry.id]);
5184
+
4945
5185
  // set css class when group is sticky to top
4946
5186
  useStickyIntersectionObserver(groupRef, 'div.bio-properties-panel-scroll-container', setSticky);
4947
5187
  const propertiesPanelContext = {
@@ -4958,10 +5198,19 @@ function Group(props) {
4958
5198
  children: [jsx("div", {
4959
5199
  title: label,
4960
5200
  class: "bio-properties-panel-group-header-title",
4961
- children: label
5201
+ children: jsx(TooltipWrapper, {
5202
+ value: props.tooltip,
5203
+ forId: 'group-' + id,
5204
+ element: element,
5205
+ parent: groupRef,
5206
+ children: label
5207
+ })
4962
5208
  }), jsxs("div", {
4963
5209
  class: "bio-properties-panel-group-header-buttons",
4964
- children: [edited && jsx(DataMarker, {}), jsx("button", {
5210
+ children: [jsx(DataMarker, {
5211
+ edited: edited,
5212
+ hasErrors: hasErrors
5213
+ }), jsx("button", {
4965
5214
  title: "Toggle section",
4966
5215
  class: "bio-properties-panel-group-header-button bio-properties-panel-arrow",
4967
5216
  children: jsx(ArrowIcon, {
@@ -4988,11 +5237,24 @@ function Group(props) {
4988
5237
  })]
4989
5238
  });
4990
5239
  }
4991
- function DataMarker() {
4992
- return jsx("div", {
4993
- title: "Section contains data",
4994
- class: "bio-properties-panel-dot"
4995
- });
5240
+ function DataMarker(props) {
5241
+ const {
5242
+ edited,
5243
+ hasErrors
5244
+ } = props;
5245
+ if (hasErrors) {
5246
+ return jsx("div", {
5247
+ title: "Section contains an error",
5248
+ class: "bio-properties-panel-dot bio-properties-panel-dot--error"
5249
+ });
5250
+ }
5251
+ if (edited) {
5252
+ return jsx("div", {
5253
+ title: "Section contains data",
5254
+ class: "bio-properties-panel-dot"
5255
+ });
5256
+ }
5257
+ return null;
4996
5258
  }
4997
5259
 
4998
5260
  /**
@@ -5023,6 +5285,7 @@ function Placeholder(props) {
5023
5285
  }
5024
5286
  const DEFAULT_LAYOUT = {};
5025
5287
  const DEFAULT_DESCRIPTION = {};
5288
+ const DEFAULT_TOOLTIP = {};
5026
5289
 
5027
5290
  /**
5028
5291
  * @typedef { {
@@ -5063,12 +5326,22 @@ const DEFAULT_DESCRIPTION = {};
5063
5326
  * [id: String]: GetDescriptionFunction
5064
5327
  * } } DescriptionConfig
5065
5328
  *
5329
+ * @typedef { {
5330
+ * [id: String]: GetTooltipFunction
5331
+ * } } TooltipConfig
5332
+ *
5066
5333
  * @callback { {
5067
5334
  * @param {string} id
5068
5335
  * @param {Object} element
5069
5336
  * @returns {string}
5070
5337
  * } } GetDescriptionFunction
5071
5338
  *
5339
+ * @callback { {
5340
+ * @param {string} id
5341
+ * @param {Object} element
5342
+ * @returns {string}
5343
+ * } } GetTooltipFunction
5344
+ *
5072
5345
  * @typedef { {
5073
5346
  * getEmpty: (element: object) => import('./components/Placeholder').PlaceholderDefinition,
5074
5347
  * getMultiple: (element: Object) => import('./components/Placeholder').PlaceholderDefinition
@@ -5089,6 +5362,8 @@ const DEFAULT_DESCRIPTION = {};
5089
5362
  * @param {Function} [props.layoutChanged]
5090
5363
  * @param {DescriptionConfig} [props.descriptionConfig]
5091
5364
  * @param {Function} [props.descriptionLoaded]
5365
+ * @param {TooltipConfig} [props.tooltipConfig]
5366
+ * @param {Function} [props.tooltipLoaded]
5092
5367
  * @param {Object} [props.eventBus]
5093
5368
  */
5094
5369
  function PropertiesPanel(props) {
@@ -5101,6 +5376,8 @@ function PropertiesPanel(props) {
5101
5376
  layoutChanged,
5102
5377
  descriptionConfig,
5103
5378
  descriptionLoaded,
5379
+ tooltipConfig,
5380
+ tooltipLoaded,
5104
5381
  eventBus
5105
5382
  } = props;
5106
5383
 
@@ -5146,6 +5423,21 @@ function PropertiesPanel(props) {
5146
5423
  description,
5147
5424
  getDescriptionForId
5148
5425
  };
5426
+
5427
+ // set-up tooltip context
5428
+ const tooltip = useMemo(() => createTooltipContext(tooltipConfig), [tooltipConfig]);
5429
+ useEffect(() => {
5430
+ if (typeof tooltipLoaded === 'function') {
5431
+ tooltipLoaded(tooltip);
5432
+ }
5433
+ }, [tooltip, tooltipLoaded]);
5434
+ const getTooltipForId = (id, element) => {
5435
+ return tooltip[id] && tooltip[id](element);
5436
+ };
5437
+ const tooltipContext = {
5438
+ tooltip,
5439
+ getTooltipForId
5440
+ };
5149
5441
  const [errors, setErrors] = useState({});
5150
5442
  const onSetErrors = ({
5151
5443
  errors
@@ -5180,29 +5472,32 @@ function PropertiesPanel(props) {
5180
5472
  value: errorsContext,
5181
5473
  children: jsx(DescriptionContext.Provider, {
5182
5474
  value: descriptionContext,
5183
- children: jsx(LayoutContext.Provider, {
5184
- value: layoutContext,
5185
- children: jsx(EventContext.Provider, {
5186
- value: eventContext,
5187
- children: jsxs("div", {
5188
- class: "bio-properties-panel",
5189
- children: [jsx(Header, {
5190
- element: element,
5191
- headerProvider: headerProvider
5192
- }), jsx("div", {
5193
- class: "bio-properties-panel-scroll-container",
5194
- children: groups.map(group => {
5195
- const {
5196
- component: Component = Group,
5197
- id
5198
- } = group;
5199
- return createElement(Component, {
5200
- ...group,
5201
- key: id,
5202
- element: element
5203
- });
5204
- })
5205
- })]
5475
+ children: jsx(TooltipContext.Provider, {
5476
+ value: tooltipContext,
5477
+ children: jsx(LayoutContext.Provider, {
5478
+ value: layoutContext,
5479
+ children: jsx(EventContext.Provider, {
5480
+ value: eventContext,
5481
+ children: jsxs("div", {
5482
+ class: "bio-properties-panel",
5483
+ children: [jsx(Header, {
5484
+ element: element,
5485
+ headerProvider: headerProvider
5486
+ }), jsx("div", {
5487
+ class: "bio-properties-panel-scroll-container",
5488
+ children: groups.map(group => {
5489
+ const {
5490
+ component: Component = Group,
5491
+ id
5492
+ } = group;
5493
+ return createElement(Component, {
5494
+ ...group,
5495
+ key: id,
5496
+ element: element
5497
+ });
5498
+ })
5499
+ })]
5500
+ })
5206
5501
  })
5207
5502
  })
5208
5503
  })
@@ -5225,6 +5520,12 @@ function createDescriptionContext(overrides = {}) {
5225
5520
  ...overrides
5226
5521
  };
5227
5522
  }
5523
+ function createTooltipContext(overrides = {}) {
5524
+ return {
5525
+ ...DEFAULT_TOOLTIP,
5526
+ ...overrides
5527
+ };
5528
+ }
5228
5529
 
5229
5530
  // hooks //////////////////
5230
5531
 
@@ -5455,6 +5756,18 @@ function ListGroup(props) {
5455
5756
  setAddTriggered(true);
5456
5757
  add(e);
5457
5758
  };
5759
+ const allErrors = useErrors();
5760
+ const hasError = items.some(item => {
5761
+ if (allErrors[item.id]) {
5762
+ return true;
5763
+ }
5764
+ if (!item.entries) {
5765
+ return;
5766
+ }
5767
+
5768
+ // also check if the error is nested, e.g. for name-value entries
5769
+ return item.entries.some(entry => allErrors[entry.id]);
5770
+ });
5458
5771
  return jsxs("div", {
5459
5772
  class: "bio-properties-panel-group",
5460
5773
  "data-group-id": 'group-' + id,
@@ -5465,7 +5778,13 @@ function ListGroup(props) {
5465
5778
  children: [jsx("div", {
5466
5779
  title: label,
5467
5780
  class: "bio-properties-panel-group-header-title",
5468
- children: label
5781
+ children: jsx(TooltipWrapper, {
5782
+ value: props.tooltip,
5783
+ forId: 'group-' + id,
5784
+ element: element,
5785
+ parent: groupRef,
5786
+ children: label
5787
+ })
5469
5788
  }), jsxs("div", {
5470
5789
  class: "bio-properties-panel-group-header-buttons",
5471
5790
  children: [add ? jsxs("button", {
@@ -5478,7 +5797,7 @@ function ListGroup(props) {
5478
5797
  }) : null]
5479
5798
  }) : null, hasItems ? jsx("div", {
5480
5799
  title: `List contains ${items.length} item${items.length != 1 ? 's' : ''}`,
5481
- class: "bio-properties-panel-list-badge",
5800
+ class: classnames('bio-properties-panel-list-badge', hasError ? 'bio-properties-panel-list-badge--error' : ''),
5482
5801
  children: items.length
5483
5802
  }) : null, hasItems ? jsx("button", {
5484
5803
  title: "Toggle section",
@@ -5554,7 +5873,8 @@ function Checkbox(props) {
5554
5873
  disabled,
5555
5874
  value = false,
5556
5875
  onFocus,
5557
- onBlur
5876
+ onBlur,
5877
+ tooltip
5558
5878
  } = props;
5559
5879
  const [localValue, setLocalValue] = useState(value);
5560
5880
  const handleChangeCallback = ({
@@ -5589,7 +5909,12 @@ function Checkbox(props) {
5589
5909
  }), jsx("label", {
5590
5910
  for: prefixId$7(id),
5591
5911
  class: "bio-properties-panel-label",
5592
- children: label
5912
+ children: jsx(TooltipWrapper, {
5913
+ value: tooltip,
5914
+ forId: id,
5915
+ element: props.element,
5916
+ children: label
5917
+ })
5593
5918
  })]
5594
5919
  });
5595
5920
  }
@@ -5604,6 +5929,7 @@ function Checkbox(props) {
5604
5929
  * @param {Function} props.setValue
5605
5930
  * @param {Function} props.onFocus
5606
5931
  * @param {Function} props.onBlur
5932
+ * @param {string|import('preact').Component} props.tooltip
5607
5933
  * @param {boolean} [props.disabled]
5608
5934
  */
5609
5935
  function CheckboxEntry(props) {
@@ -5616,7 +5942,8 @@ function CheckboxEntry(props) {
5616
5942
  setValue,
5617
5943
  disabled,
5618
5944
  onFocus,
5619
- onBlur
5945
+ onBlur,
5946
+ tooltip
5620
5947
  } = props;
5621
5948
  const value = getValue(element);
5622
5949
  const error = useError(id);
@@ -5630,7 +5957,9 @@ function CheckboxEntry(props) {
5630
5957
  onChange: setValue,
5631
5958
  onFocus: onFocus,
5632
5959
  onBlur: onBlur,
5633
- value: value
5960
+ value: value,
5961
+ tooltip: tooltip,
5962
+ element: element
5634
5963
  }, element), error && jsx("div", {
5635
5964
  class: "bio-properties-panel-error",
5636
5965
  children: error
@@ -5887,7 +6216,8 @@ function ToggleSwitch(props) {
5887
6216
  inline,
5888
6217
  onFocus,
5889
6218
  onBlur,
5890
- inputRef
6219
+ inputRef,
6220
+ tooltip
5891
6221
  } = props;
5892
6222
  const [localValue, setLocalValue] = useState(value);
5893
6223
  const handleInputCallback = async () => {
@@ -5910,7 +6240,12 @@ function ToggleSwitch(props) {
5910
6240
  children: [jsx("label", {
5911
6241
  class: "bio-properties-panel-label",
5912
6242
  for: prefixId$6(id),
5913
- children: label
6243
+ children: jsx(TooltipWrapper, {
6244
+ value: tooltip,
6245
+ forId: id,
6246
+ element: props.element,
6247
+ children: label
6248
+ })
5914
6249
  }), jsxs("div", {
5915
6250
  class: "bio-properties-panel-field-wrapper",
5916
6251
  children: [jsxs("label", {
@@ -5948,6 +6283,7 @@ function ToggleSwitch(props) {
5948
6283
  * @param {Function} props.setValue
5949
6284
  * @param {Function} props.onFocus
5950
6285
  * @param {Function} props.onBlur
6286
+ * @param {string|import('preact').Component} props.tooltip
5951
6287
  */
5952
6288
  function ToggleSwitchEntry(props) {
5953
6289
  const {
@@ -5960,7 +6296,8 @@ function ToggleSwitchEntry(props) {
5960
6296
  getValue,
5961
6297
  setValue,
5962
6298
  onFocus,
5963
- onBlur
6299
+ onBlur,
6300
+ tooltip
5964
6301
  } = props;
5965
6302
  const value = getValue(element);
5966
6303
  return jsxs("div", {
@@ -5974,7 +6311,9 @@ function ToggleSwitchEntry(props) {
5974
6311
  onFocus: onFocus,
5975
6312
  onBlur: onBlur,
5976
6313
  switcherLabel: switcherLabel,
5977
- inline: inline
6314
+ inline: inline,
6315
+ tooltip: tooltip,
6316
+ element: element
5978
6317
  }), jsx(Description$1, {
5979
6318
  forId: id,
5980
6319
  element: element,
@@ -6089,11 +6428,9 @@ function NumberFieldEntry(props) {
6089
6428
  onBlur,
6090
6429
  validate
6091
6430
  } = props;
6092
- const [cachedInvalidValue, setCachedInvalidValue] = useState(null);
6093
6431
  const globalError = useError(id);
6094
6432
  const [localError, setLocalError] = useState(null);
6095
6433
  let value = getValue(element);
6096
- const previousValue = usePrevious(value);
6097
6434
  useEffect(() => {
6098
6435
  if (isFunction(validate)) {
6099
6436
  const newValidationError = validate(value) || null;
@@ -6105,16 +6442,9 @@ function NumberFieldEntry(props) {
6105
6442
  if (isFunction(validate)) {
6106
6443
  newValidationError = validate(newValue) || null;
6107
6444
  }
6108
- if (newValidationError) {
6109
- setCachedInvalidValue(newValue);
6110
- } else {
6111
- setValue(newValue);
6112
- }
6445
+ setValue(newValue, newValidationError);
6113
6446
  setLocalError(newValidationError);
6114
6447
  };
6115
- if (previousValue === value && localError) {
6116
- value = cachedInvalidValue;
6117
- }
6118
6448
  const error = globalError || localError;
6119
6449
  return jsxs("div", {
6120
6450
  class: classnames('bio-properties-panel-entry', error ? 'has-error' : ''),
@@ -6163,7 +6493,8 @@ function FeelTextfield(props) {
6163
6493
  disabled = false,
6164
6494
  variables,
6165
6495
  tooltipContainer,
6166
- OptionalComponent = OptionalFeelInput
6496
+ OptionalComponent = OptionalFeelInput,
6497
+ tooltip
6167
6498
  } = props;
6168
6499
  const [localValue, _setLocalValue] = useState(value);
6169
6500
  const editorRef = useShowEntryEvent(id);
@@ -6279,7 +6610,12 @@ function FeelTextfield(props) {
6279
6610
  for: prefixId$4(id),
6280
6611
  class: "bio-properties-panel-label",
6281
6612
  onClick: () => setFocus(),
6282
- children: [label, jsx(FeelIcon, {
6613
+ children: [jsx(TooltipWrapper, {
6614
+ value: tooltip,
6615
+ forId: id,
6616
+ element: props.element,
6617
+ children: label
6618
+ }), jsx(FeelIcon, {
6283
6619
  label: label,
6284
6620
  feel: feel,
6285
6621
  onClick: handleFeelToggle,
@@ -6539,6 +6875,7 @@ forwardRef((props, ref) => {
6539
6875
  * @param {Function} props.variables
6540
6876
  * @param {Function} props.onFocus
6541
6877
  * @param {Function} props.onBlur
6878
+ * @param {string|import('preact').Component} props.tooltip
6542
6879
  */
6543
6880
  function FeelEntry(props) {
6544
6881
  const {
@@ -6559,13 +6896,12 @@ function FeelEntry(props) {
6559
6896
  example,
6560
6897
  variables,
6561
6898
  onFocus,
6562
- onBlur
6899
+ onBlur,
6900
+ tooltip
6563
6901
  } = props;
6564
- const [cachedInvalidValue, setCachedInvalidValue] = useState(null);
6565
6902
  const [validationError, setValidationError] = useState(null);
6566
6903
  const [localError, setLocalError] = useState(null);
6567
6904
  let value = getValue(element);
6568
- const previousValue = usePrevious(value);
6569
6905
  useEffect(() => {
6570
6906
  if (isFunction(validate)) {
6571
6907
  const newValidationError = validate(value) || null;
@@ -6577,22 +6913,16 @@ function FeelEntry(props) {
6577
6913
  if (isFunction(validate)) {
6578
6914
  newValidationError = validate(newValue) || null;
6579
6915
  }
6580
- if (newValidationError) {
6581
- setCachedInvalidValue(newValue);
6582
- } else {
6583
- // don't create multiple commandStack entries for the same value
6584
- if (newValue !== value) {
6585
- setValue(newValue);
6586
- }
6916
+
6917
+ // don't create multiple commandStack entries for the same value
6918
+ if (newValue !== value) {
6919
+ setValue(newValue, newValidationError);
6587
6920
  }
6588
6921
  setValidationError(newValidationError);
6589
6922
  });
6590
6923
  const onError = useCallback(err => {
6591
6924
  setLocalError(err);
6592
6925
  }, []);
6593
- if (previousValue === value && validationError) {
6594
- value = cachedInvalidValue;
6595
- }
6596
6926
  const temporaryError = useError(id);
6597
6927
  const error = localError || temporaryError || validationError;
6598
6928
  return jsxs("div", {
@@ -6617,7 +6947,8 @@ function FeelEntry(props) {
6617
6947
  value: value,
6618
6948
  variables: variables,
6619
6949
  tooltipContainer: tooltipContainer,
6620
- OptionalComponent: props.OptionalComponent
6950
+ OptionalComponent: props.OptionalComponent,
6951
+ tooltip: tooltip
6621
6952
  }), error && jsx("div", {
6622
6953
  class: "bio-properties-panel-error",
6623
6954
  children: error
@@ -6738,7 +7069,8 @@ function Select(props) {
6738
7069
  value = '',
6739
7070
  disabled,
6740
7071
  onFocus,
6741
- onBlur
7072
+ onBlur,
7073
+ tooltip
6742
7074
  } = props;
6743
7075
  const ref = useShowEntryEvent(id);
6744
7076
  const [localValue, setLocalValue] = useState(value);
@@ -6762,7 +7094,12 @@ function Select(props) {
6762
7094
  children: [jsx("label", {
6763
7095
  for: prefixId$3(id),
6764
7096
  class: "bio-properties-panel-label",
6765
- children: label
7097
+ children: jsx(TooltipWrapper, {
7098
+ value: tooltip,
7099
+ forId: id,
7100
+ element: props.element,
7101
+ children: label
7102
+ })
6766
7103
  }), jsx("select", {
6767
7104
  ref: ref,
6768
7105
  id: prefixId$3(id),
@@ -6807,6 +7144,7 @@ function Select(props) {
6807
7144
  * @param {Function} props.getOptions
6808
7145
  * @param {boolean} [props.disabled]
6809
7146
  * @param {Function} [props.validate]
7147
+ * @param {string|import('preact').Component} props.tooltip
6810
7148
  */
6811
7149
  function SelectEntry(props) {
6812
7150
  const {
@@ -6820,14 +7158,13 @@ function SelectEntry(props) {
6820
7158
  disabled,
6821
7159
  onFocus,
6822
7160
  onBlur,
6823
- validate
7161
+ validate,
7162
+ tooltip
6824
7163
  } = props;
6825
7164
  const options = getOptions(element);
6826
- const [cachedInvalidValue, setCachedInvalidValue] = useState(null);
6827
7165
  const globalError = useError(id);
6828
7166
  const [localError, setLocalError] = useState(null);
6829
7167
  let value = getValue(element);
6830
- const previousValue = usePrevious(value);
6831
7168
  useEffect(() => {
6832
7169
  if (isFunction(validate)) {
6833
7170
  const newValidationError = validate(value) || null;
@@ -6839,16 +7176,9 @@ function SelectEntry(props) {
6839
7176
  if (isFunction(validate)) {
6840
7177
  newValidationError = validate(newValue) || null;
6841
7178
  }
6842
- if (newValidationError) {
6843
- setCachedInvalidValue(newValue);
6844
- } else {
6845
- setValue(newValue);
6846
- }
7179
+ setValue(newValue, newValidationError);
6847
7180
  setLocalError(newValidationError);
6848
7181
  };
6849
- if (previousValue === value && localError) {
6850
- value = cachedInvalidValue;
6851
- }
6852
7182
  const error = globalError || localError;
6853
7183
  return jsxs("div", {
6854
7184
  class: classnames('bio-properties-panel-entry', error ? 'has-error' : ''),
@@ -6861,7 +7191,9 @@ function SelectEntry(props) {
6861
7191
  onFocus: onFocus,
6862
7192
  onBlur: onBlur,
6863
7193
  options: options,
6864
- disabled: disabled
7194
+ disabled: disabled,
7195
+ tooltip: tooltip,
7196
+ element: element
6865
7197
  }, element), error && jsx("div", {
6866
7198
  class: "bio-properties-panel-error",
6867
7199
  children: error
@@ -6900,7 +7232,8 @@ function TextArea(props) {
6900
7232
  onFocus,
6901
7233
  onBlur,
6902
7234
  autoResize,
6903
- rows = autoResize ? 1 : 2
7235
+ rows = autoResize ? 1 : 2,
7236
+ tooltip
6904
7237
  } = props;
6905
7238
  const [localValue, setLocalValue] = useState(value);
6906
7239
  const ref = useShowEntryEvent(id);
@@ -6928,7 +7261,12 @@ function TextArea(props) {
6928
7261
  children: [jsx("label", {
6929
7262
  for: prefixId$1(id),
6930
7263
  class: "bio-properties-panel-label",
6931
- children: label
7264
+ children: jsx(TooltipWrapper, {
7265
+ value: tooltip,
7266
+ forId: id,
7267
+ element: props.element,
7268
+ children: label
7269
+ })
6932
7270
  }), jsx("textarea", {
6933
7271
  ref: ref,
6934
7272
  id: prefixId$1(id),
@@ -6977,13 +7315,12 @@ function TextAreaEntry(props) {
6977
7315
  validate,
6978
7316
  onFocus,
6979
7317
  onBlur,
6980
- autoResize
7318
+ autoResize,
7319
+ tooltip
6981
7320
  } = props;
6982
- const [cachedInvalidValue, setCachedInvalidValue] = useState(null);
6983
7321
  const globalError = useError(id);
6984
7322
  const [localError, setLocalError] = useState(null);
6985
7323
  let value = getValue(element);
6986
- const previousValue = usePrevious(value);
6987
7324
  useEffect(() => {
6988
7325
  if (isFunction(validate)) {
6989
7326
  const newValidationError = validate(value) || null;
@@ -6995,16 +7332,9 @@ function TextAreaEntry(props) {
6995
7332
  if (isFunction(validate)) {
6996
7333
  newValidationError = validate(newValue) || null;
6997
7334
  }
6998
- if (newValidationError) {
6999
- setCachedInvalidValue(newValue);
7000
- } else {
7001
- setValue(newValue);
7002
- }
7335
+ setValue(newValue, newValidationError);
7003
7336
  setLocalError(newValidationError);
7004
7337
  };
7005
- if (previousValue === value && localError) {
7006
- value = cachedInvalidValue;
7007
- }
7008
7338
  const error = globalError || localError;
7009
7339
  return jsxs("div", {
7010
7340
  class: classnames('bio-properties-panel-entry', error ? 'has-error' : ''),
@@ -7020,7 +7350,9 @@ function TextAreaEntry(props) {
7020
7350
  debounce: debounce,
7021
7351
  monospace: monospace,
7022
7352
  disabled: disabled,
7023
- autoResize: autoResize
7353
+ autoResize: autoResize,
7354
+ tooltip: tooltip,
7355
+ element: element
7024
7356
  }, element), error && jsx("div", {
7025
7357
  class: "bio-properties-panel-error",
7026
7358
  children: error
@@ -7049,7 +7381,8 @@ function Textfield(props) {
7049
7381
  onInput,
7050
7382
  onFocus,
7051
7383
  onBlur,
7052
- value = ''
7384
+ value = '',
7385
+ tooltip
7053
7386
  } = props;
7054
7387
  const [localValue, setLocalValue] = useState(value || '');
7055
7388
  const ref = useShowEntryEvent(id);
@@ -7073,7 +7406,12 @@ function Textfield(props) {
7073
7406
  children: [jsx("label", {
7074
7407
  for: prefixId(id),
7075
7408
  class: "bio-properties-panel-label",
7076
- children: label
7409
+ children: jsx(TooltipWrapper, {
7410
+ value: tooltip,
7411
+ forId: id,
7412
+ element: props.element,
7413
+ children: label
7414
+ })
7077
7415
  }), jsx("input", {
7078
7416
  ref: ref,
7079
7417
  id: prefixId(id),
@@ -7103,6 +7441,7 @@ function Textfield(props) {
7103
7441
  * @param {Function} props.setValue
7104
7442
  * @param {Function} props.onFocus
7105
7443
  * @param {Function} props.onBlur
7444
+ * @param {string|import('preact').Component} props.tooltip
7106
7445
  * @param {Function} props.validate
7107
7446
  */
7108
7447
  function TextfieldEntry(props) {
@@ -7117,13 +7456,12 @@ function TextfieldEntry(props) {
7117
7456
  setValue,
7118
7457
  validate,
7119
7458
  onFocus,
7120
- onBlur
7459
+ onBlur,
7460
+ tooltip
7121
7461
  } = props;
7122
- const [cachedInvalidValue, setCachedInvalidValue] = useState(null);
7123
7462
  const globalError = useError(id);
7124
7463
  const [localError, setLocalError] = useState(null);
7125
7464
  let value = getValue(element);
7126
- const previousValue = usePrevious(value);
7127
7465
  useEffect(() => {
7128
7466
  if (isFunction(validate)) {
7129
7467
  const newValidationError = validate(value) || null;
@@ -7135,16 +7473,9 @@ function TextfieldEntry(props) {
7135
7473
  if (isFunction(validate)) {
7136
7474
  newValidationError = validate(newValue) || null;
7137
7475
  }
7138
- if (newValidationError) {
7139
- setCachedInvalidValue(newValue);
7140
- } else {
7141
- setValue(newValue);
7142
- }
7476
+ setValue(newValue, newValidationError);
7143
7477
  setLocalError(newValidationError);
7144
7478
  };
7145
- if (previousValue === value && localError) {
7146
- value = cachedInvalidValue;
7147
- }
7148
7479
  const error = globalError || localError;
7149
7480
  return jsxs("div", {
7150
7481
  class: classnames('bio-properties-panel-entry', error ? 'has-error' : ''),
@@ -7157,7 +7488,9 @@ function TextfieldEntry(props) {
7157
7488
  onInput: onInput,
7158
7489
  onFocus: onFocus,
7159
7490
  onBlur: onBlur,
7160
- value: value
7491
+ value: value,
7492
+ tooltip: tooltip,
7493
+ element: element
7161
7494
  }, element), error && jsx("div", {
7162
7495
  class: "bio-properties-panel-error",
7163
7496
  children: error
@@ -7178,11 +7511,11 @@ function prefixId(id) {
7178
7511
  return `bio-properties-panel-${id}`;
7179
7512
  }
7180
7513
 
7181
- /**
7182
- * @param {string} type
7183
- * @param {boolean} [strict]
7184
- *
7185
- * @returns {any}
7514
+ /**
7515
+ * @param {string} type
7516
+ * @param {boolean} [strict]
7517
+ *
7518
+ * @returns {any}
7186
7519
  */
7187
7520
  function getService(type, strict) {}
7188
7521
  const PropertiesPanelContext = createContext({
@@ -7229,6 +7562,7 @@ const labelsByType = {
7229
7562
  number: 'NUMBER',
7230
7563
  radio: 'RADIO',
7231
7564
  select: 'SELECT',
7565
+ spacer: 'SPACER',
7232
7566
  taglist: 'TAGLIST',
7233
7567
  text: 'TEXT VIEW',
7234
7568
  textfield: 'TEXT FIELD',
@@ -7271,8 +7605,8 @@ const PropertiesPanelHeaderProvider = {
7271
7605
  }
7272
7606
  };
7273
7607
 
7274
- /**
7275
- * Provide placeholders for empty and multiple state.
7608
+ /**
7609
+ * Provide placeholders for empty and multiple state.
7276
7610
  */
7277
7611
  const PropertiesPanelPlaceholderProvider = {
7278
7612
  getEmpty: () => {
@@ -7344,10 +7678,10 @@ function useService (type, strict) {
7344
7678
  return getService(type, strict);
7345
7679
  }
7346
7680
 
7347
- /**
7348
- * Retrieve list of variables from the form schema.
7349
- *
7350
- * @returns { string[] } list of variables used in form schema
7681
+ /**
7682
+ * Retrieve list of variables from the form schema.
7683
+ *
7684
+ * @returns { string[] } list of variables used in form schema
7351
7685
  */
7352
7686
  function useVariables() {
7353
7687
  const form = useService('formEditor');
@@ -7399,6 +7733,7 @@ function AltText(props) {
7399
7733
  getValue,
7400
7734
  id,
7401
7735
  label: 'Alternative text',
7736
+ tooltip: 'Descriptive text for screen reader accessibility.',
7402
7737
  setValue,
7403
7738
  singleLine: true,
7404
7739
  variables
@@ -7431,7 +7766,10 @@ function Columns(props) {
7431
7766
  const validate = value => {
7432
7767
  return formLayoutValidator.validateField(field, value ? parseInt(value) : null);
7433
7768
  };
7434
- const setValue = value => {
7769
+ const setValue = (value, error) => {
7770
+ if (error) {
7771
+ return;
7772
+ }
7435
7773
  const layout = get(field, ['layout'], {});
7436
7774
  const newValue = value ? parseInt(value) : null;
7437
7775
  editField(field, ['layout'], set$1(layout, ['columns'], newValue));
@@ -7639,7 +7977,10 @@ function DefaultValueNumber(props) {
7639
7977
  // Enforces decimal notation so that we do not submit defaults in exponent form
7640
7978
  return serializeToString ? Big(value).toFixed() : value;
7641
7979
  };
7642
- const setValue = value => {
7980
+ const setValue = (value, error) => {
7981
+ if (error) {
7982
+ return;
7983
+ }
7643
7984
  let newValue;
7644
7985
  if (isValidNumber(value)) {
7645
7986
  newValue = serializeToString ? value : Number(value);
@@ -7796,6 +8137,7 @@ function Disabled(props) {
7796
8137
  getValue,
7797
8138
  id,
7798
8139
  label: 'Disabled',
8140
+ tooltip: 'Field cannot be edited by the end-user, and the data is not submitted.',
7799
8141
  inline: true,
7800
8142
  setValue
7801
8143
  });
@@ -7830,7 +8172,10 @@ function Id(props) {
7830
8172
  const getValue = () => {
7831
8173
  return get(field, path, '');
7832
8174
  };
7833
- const setValue = value => {
8175
+ const setValue = (value, error) => {
8176
+ if (error) {
8177
+ return;
8178
+ }
7834
8179
  return editField(field, path, value);
7835
8180
  };
7836
8181
  const validate = value => {
@@ -7910,7 +8255,10 @@ function Key$1(props) {
7910
8255
  const getValue = () => {
7911
8256
  return get(field, path, '');
7912
8257
  };
7913
- const setValue = value => {
8258
+ const setValue = (value, error) => {
8259
+ if (error) {
8260
+ return;
8261
+ }
7914
8262
  return editField(field, path, value);
7915
8263
  };
7916
8264
  const validate = value => {
@@ -7933,6 +8281,7 @@ function Key$1(props) {
7933
8281
  getValue,
7934
8282
  id,
7935
8283
  label: 'Key',
8284
+ tooltip: 'Use a unique "key" to link the form element and the related input/output data. When dealing with nested data, break it down in the user task\'s input mapping before using it.',
7936
8285
  setValue,
7937
8286
  validate
7938
8287
  });
@@ -7993,7 +8342,7 @@ function Label$1(props) {
7993
8342
  return get(field, path, '');
7994
8343
  };
7995
8344
  const setValue = value => {
7996
- return editField(field, path, value);
8345
+ return editField(field, path, value || '');
7997
8346
  };
7998
8347
  return FeelTemplatingEntry({
7999
8348
  debounce,
@@ -8021,7 +8370,7 @@ function DateLabel(props) {
8021
8370
  return get(field, path, '');
8022
8371
  };
8023
8372
  const setValue = value => {
8024
- return editField(field, path, value);
8373
+ return editField(field, path, value || '');
8025
8374
  };
8026
8375
  return FeelTemplatingEntry({
8027
8376
  debounce,
@@ -8049,7 +8398,7 @@ function TimeLabel(props) {
8049
8398
  return get(field, path, '');
8050
8399
  };
8051
8400
  const setValue = value => {
8052
- return editField(field, path, value);
8401
+ return editField(field, path, value || '');
8053
8402
  };
8054
8403
  return FeelTemplatingEntry({
8055
8404
  debounce,
@@ -8108,6 +8457,7 @@ function Source(props) {
8108
8457
  getValue,
8109
8458
  id,
8110
8459
  label: 'Image source',
8460
+ tooltip: 'Link referring to a hosted image, or use a data URI directly to embed image data into the form.',
8111
8461
  setValue,
8112
8462
  singleLine: true,
8113
8463
  variables
@@ -8165,7 +8515,7 @@ function Text(props) {
8165
8515
  return get(field, path, '');
8166
8516
  };
8167
8517
  const setValue = value => {
8168
- return editField(field, path, value);
8518
+ return editField(field, path, value || '');
8169
8519
  };
8170
8520
  const description = useMemo(() => jsxs(Fragment$1, {
8171
8521
  children: ["Supports markdown and templating. ", jsx("a", {
@@ -8187,6 +8537,57 @@ function Text(props) {
8187
8537
  });
8188
8538
  }
8189
8539
 
8540
+ function SpacerEntry(props) {
8541
+ const {
8542
+ editField,
8543
+ field,
8544
+ id
8545
+ } = props;
8546
+ const {
8547
+ type
8548
+ } = field;
8549
+ if (type !== 'spacer') {
8550
+ return [];
8551
+ }
8552
+ const entries = [];
8553
+ entries.push({
8554
+ id: id + '-height',
8555
+ component: SpacerHeight,
8556
+ isEdited: isEdited$6,
8557
+ editField,
8558
+ field
8559
+ });
8560
+ return entries;
8561
+ }
8562
+ function SpacerHeight(props) {
8563
+ const {
8564
+ editField,
8565
+ field,
8566
+ id
8567
+ } = props;
8568
+ const debounce = useService('debounce');
8569
+ const getValue = e => get(field, ['height']);
8570
+ const setValue = (value, error) => {
8571
+ if (error) {
8572
+ return;
8573
+ }
8574
+ editField(field, ['height'], value);
8575
+ };
8576
+ return NumberFieldEntry({
8577
+ debounce,
8578
+ label: 'Height',
8579
+ element: field,
8580
+ id,
8581
+ getValue,
8582
+ setValue,
8583
+ validate: value => {
8584
+ if (value === undefined || value === null) return;
8585
+ if (value < 1) return 'Should be greater than zero.';
8586
+ if (!Number.isInteger(value)) return 'Should be an integer.';
8587
+ }
8588
+ });
8589
+ }
8590
+
8190
8591
  function NumberEntries(props) {
8191
8592
  const {
8192
8593
  editField,
@@ -8224,7 +8625,12 @@ function NumberDecimalDigits(props) {
8224
8625
  } = props;
8225
8626
  const debounce = useService('debounce');
8226
8627
  const getValue = e => get(field, ['decimalDigits']);
8227
- const setValue = value => editField(field, ['decimalDigits'], value);
8628
+ const setValue = (value, error) => {
8629
+ if (error) {
8630
+ return;
8631
+ }
8632
+ editField(field, ['decimalDigits'], value);
8633
+ };
8228
8634
  return NumberFieldEntry({
8229
8635
  debounce,
8230
8636
  label: 'Decimal digits',
@@ -8260,7 +8666,12 @@ function NumberArrowStep(props) {
8260
8666
  const trimmed = value.replace(/^0+/g, '');
8261
8667
  return (trimmed.startsWith('.') ? '0' : '') + trimmed;
8262
8668
  };
8263
- const setValue = value => editField(field, ['increment'], clearLeadingZeroes(value));
8669
+ const setValue = (value, error) => {
8670
+ if (error) {
8671
+ return;
8672
+ }
8673
+ editField(field, ['increment'], clearLeadingZeroes(value));
8674
+ };
8264
8675
  const decimalDigitsSet = decimalDigits || decimalDigits === 0;
8265
8676
  return TextfieldEntry({
8266
8677
  debounce,
@@ -8669,7 +9080,10 @@ function Label(props) {
8669
9080
  validateFactory
8670
9081
  } = props;
8671
9082
  const debounce = useService('debounce');
8672
- const setValue = value => {
9083
+ const setValue = (value, error) => {
9084
+ if (error) {
9085
+ return;
9086
+ }
8673
9087
  const values = get(field, ['values']);
8674
9088
  return editField(field, 'values', set$1(values, [index, 'label'], value));
8675
9089
  };
@@ -8695,7 +9109,10 @@ function Value$1(props) {
8695
9109
  validateFactory
8696
9110
  } = props;
8697
9111
  const debounce = useService('debounce');
8698
- const setValue = value => {
9112
+ const setValue = (value, error) => {
9113
+ if (error) {
9114
+ return;
9115
+ }
8699
9116
  const values = get(field, ['values']);
8700
9117
  return editField(field, 'values', set$1(values, [index, 'value'], value));
8701
9118
  };
@@ -8749,7 +9166,10 @@ function Key(props) {
8749
9166
  validateFactory
8750
9167
  } = props;
8751
9168
  const debounce = useService('debounce');
8752
- const setValue = value => {
9169
+ const setValue = (value, error) => {
9170
+ if (error) {
9171
+ return;
9172
+ }
8753
9173
  const properties = get(field, ['properties']);
8754
9174
  const key = Object.keys(properties)[index];
8755
9175
  return editField(field, 'properties', updateKey(properties, key, value));
@@ -8799,14 +9219,14 @@ function Value(props) {
8799
9219
 
8800
9220
  // helpers //////////
8801
9221
 
8802
- /**
8803
- * Returns copy of object with updated value.
8804
- *
8805
- * @param {Object} properties
8806
- * @param {string} key
8807
- * @param {string} value
8808
- *
8809
- * @returns {Object}
9222
+ /**
9223
+ * Returns copy of object with updated value.
9224
+ *
9225
+ * @param {Object} properties
9226
+ * @param {string} key
9227
+ * @param {string} value
9228
+ *
9229
+ * @returns {Object}
8810
9230
  */
8811
9231
  function updateValue(properties, key, value) {
8812
9232
  return {
@@ -8815,14 +9235,14 @@ function updateValue(properties, key, value) {
8815
9235
  };
8816
9236
  }
8817
9237
 
8818
- /**
8819
- * Returns copy of object with updated key.
8820
- *
8821
- * @param {Object} properties
8822
- * @param {string} oldKey
8823
- * @param {string} newKey
8824
- *
8825
- * @returns {Object}
9238
+ /**
9239
+ * Returns copy of object with updated key.
9240
+ *
9241
+ * @param {Object} properties
9242
+ * @param {string} oldKey
9243
+ * @param {string} newKey
9244
+ *
9245
+ * @returns {Object}
8826
9246
  */
8827
9247
  function updateKey(properties, oldKey, newKey) {
8828
9248
  return Object.entries(properties).reduce((newProperties, entry) => {
@@ -8960,7 +9380,12 @@ function InputValuesKey(props) {
8960
9380
  const debounce = useService('debounce');
8961
9381
  const path = VALUES_SOURCES_PATHS[VALUES_SOURCES.INPUT];
8962
9382
  const getValue = () => get(field, path, '');
8963
- const setValue = value => editField(field, path, value || '');
9383
+ const setValue = (value, error) => {
9384
+ if (error) {
9385
+ return;
9386
+ }
9387
+ editField(field, path, value || '');
9388
+ };
8964
9389
  const validate = value => {
8965
9390
  if (isUndefined(value) || !value.length) {
8966
9391
  return 'Must not be empty.';
@@ -9189,6 +9614,7 @@ function Readonly(props) {
9189
9614
  getValue,
9190
9615
  id,
9191
9616
  label: 'Read only',
9617
+ tooltip: 'Field cannot be edited by the end-user, but the data will still be submitted.',
9192
9618
  setValue,
9193
9619
  variables
9194
9620
  });
@@ -9317,6 +9743,9 @@ function GeneralGroup(field, editField, getService) {
9317
9743
  field,
9318
9744
  editField,
9319
9745
  getService
9746
+ }), ...SpacerEntry({
9747
+ field,
9748
+ editField
9320
9749
  }), ...NumberEntries({
9321
9750
  field,
9322
9751
  editField
@@ -9639,12 +10068,13 @@ function ValuesGroups(field, editField) {
9639
10068
  };
9640
10069
  const valuesSourceId = `${fieldId}-valuesSource`;
9641
10070
 
9642
- /**
9643
- * @type {Array<Group|ListGroup>}
10071
+ /**
10072
+ * @type {Array<Group|ListGroup>}
9644
10073
  */
9645
10074
  const groups = [{
9646
10075
  id: valuesSourceId,
9647
10076
  label: 'Options source',
10077
+ tooltip: '"Static" defines a constant, predefined set of form options.\n"Dynamic" defines options that are populated dynamically, adjusting based on variable data for flexible responses to different conditions or inputs.',
9648
10078
  component: Group,
9649
10079
  entries: ValuesSourceSelectEntry({
9650
10080
  ...context,
@@ -9689,7 +10119,7 @@ function ValuesGroups(field, editField) {
9689
10119
  return groups;
9690
10120
  }
9691
10121
 
9692
- function CustomValuesGroup(field, editField) {
10122
+ function CustomPropertiesGroup(field, editField) {
9693
10123
  const {
9694
10124
  properties = {},
9695
10125
  type
@@ -9747,19 +10177,20 @@ function CustomValuesGroup(field, editField) {
9747
10177
  id: 'custom-values',
9748
10178
  items,
9749
10179
  label: 'Custom properties',
10180
+ tooltip: 'Add properties directly to the form schema, useful to configure functionality in custom-built task applications and form renderers.',
9750
10181
  shouldSort: false
9751
10182
  };
9752
10183
  }
9753
10184
 
9754
10185
  // helpers //////////
9755
10186
 
9756
- /**
9757
- * Returns copy of object without key.
9758
- *
9759
- * @param {Object} properties
9760
- * @param {string} oldKey
9761
- *
9762
- * @returns {Object}
10187
+ /**
10188
+ * Returns copy of object without key.
10189
+ *
10190
+ * @param {Object} properties
10191
+ * @param {string} oldKey
10192
+ *
10193
+ * @returns {Object}
9763
10194
  */
9764
10195
  function removeKey(properties, oldKey) {
9765
10196
  return Object.entries(properties).reduce((newProperties, entry) => {
@@ -9832,7 +10263,7 @@ function getGroups(field, editField, getService) {
9832
10263
  if (!field) {
9833
10264
  return [];
9834
10265
  }
9835
- const groups = [GeneralGroup(field, editField, getService), ConditionGroup(field, editField), LayoutGroup(field, editField), AppearanceGroup(field, editField), SerializationGroup(field, editField), ...ValuesGroups(field, editField), ConstraintsGroup(field, editField), ValidationGroup(field, editField), CustomValuesGroup(field, editField)];
10266
+ const groups = [GeneralGroup(field, editField, getService), ConditionGroup(field, editField), LayoutGroup(field, editField), AppearanceGroup(field, editField), SerializationGroup(field, editField), ...ValuesGroups(field, editField), ConstraintsGroup(field, editField), ValidationGroup(field, editField), CustomPropertiesGroup(field, editField)];
9836
10267
 
9837
10268
  // contract: if a group returns null, it should not be displayed at all
9838
10269
  return groups.filter(group => group !== null);
@@ -9862,9 +10293,9 @@ function FormPropertiesPanel(props) {
9862
10293
  });
9863
10294
  }, [eventBus, formEditor, selectionModule]);
9864
10295
  useLayoutEffect(() => {
9865
- /**
9866
- * TODO(pinussilvestrus): update with actual updated element,
9867
- * once we have a proper updater/change support
10296
+ /**
10297
+ * TODO(pinussilvestrus): update with actual updated element,
10298
+ * once we have a proper updater/change support
9868
10299
  */
9869
10300
  eventBus.on('changed', refresh);
9870
10301
  eventBus.on('import.done', refresh);
@@ -9916,10 +10347,10 @@ class PropertiesPanelRenderer {
9916
10347
  });
9917
10348
  }
9918
10349
 
9919
- /**
9920
- * Attach the properties panel to a parent node.
9921
- *
9922
- * @param {HTMLElement} container
10350
+ /**
10351
+ * Attach the properties panel to a parent node.
10352
+ *
10353
+ * @param {HTMLElement} container
9923
10354
  */
9924
10355
  attachTo(container) {
9925
10356
  if (!container) {
@@ -9939,8 +10370,8 @@ class PropertiesPanelRenderer {
9939
10370
  this._eventBus.fire('propertiesPanel.attach');
9940
10371
  }
9941
10372
 
9942
- /**
9943
- * Detach the properties panel from its parent node.
10373
+ /**
10374
+ * Detach the properties panel from its parent node.
9944
10375
  */
9945
10376
  detach() {
9946
10377
  const parentNode = this._container.parentNode;
@@ -9970,10 +10401,10 @@ var PropertiesPanelModule = {
9970
10401
  propertiesPanel: ['type', PropertiesPanelRenderer]
9971
10402
  };
9972
10403
 
9973
- /**
9974
- * Manages the rendering of visual plugins.
9975
- * @constructor
9976
- * @param {Object} eventBus - Event bus for the application.
10404
+ /**
10405
+ * Manages the rendering of visual plugins.
10406
+ * @constructor
10407
+ * @param {Object} eventBus - Event bus for the application.
9977
10408
  */
9978
10409
  class RenderInjector extends SectionModuleBase {
9979
10410
  constructor(eventBus) {
@@ -9982,10 +10413,10 @@ class RenderInjector extends SectionModuleBase {
9982
10413
  this.registeredRenderers = [];
9983
10414
  }
9984
10415
 
9985
- /**
9986
- * Inject a new renderer into the injector.
9987
- * @param {string} identifier - Identifier for the renderer.
9988
- * @param {Function} Renderer - The renderer function.
10416
+ /**
10417
+ * Inject a new renderer into the injector.
10418
+ * @param {string} identifier - Identifier for the renderer.
10419
+ * @param {Function} Renderer - The renderer function.
9989
10420
  */
9990
10421
  attachRenderer(identifier, Renderer) {
9991
10422
  this.registeredRenderers = [...this.registeredRenderers, {
@@ -9994,17 +10425,17 @@ class RenderInjector extends SectionModuleBase {
9994
10425
  }];
9995
10426
  }
9996
10427
 
9997
- /**
9998
- * Detach a renderer from the by key injector.
9999
- * @param {string} identifier - Identifier for the renderer.
10428
+ /**
10429
+ * Detach a renderer from the by key injector.
10430
+ * @param {string} identifier - Identifier for the renderer.
10000
10431
  */
10001
10432
  detachRenderer(identifier) {
10002
10433
  this.registeredRenderers = this.registeredRenderers.filter(r => r.identifier !== identifier);
10003
10434
  }
10004
10435
 
10005
- /**
10006
- * Returns the registered renderers.
10007
- * @returns {Array} Array of registered renderers.
10436
+ /**
10437
+ * Returns the registered renderers.
10438
+ * @returns {Array} Array of registered renderers.
10008
10439
  */
10009
10440
  fetchRenderers() {
10010
10441
  return this.registeredRenderers;
@@ -10038,48 +10469,48 @@ var ExpressionLanguageModule = {
10038
10469
 
10039
10470
  const ids = new Ids([32, 36, 1]);
10040
10471
 
10041
- /**
10042
- * @typedef { import('./types').Injector } Injector
10043
- * @typedef { import('./types').Module } Module
10044
- * @typedef { import('./types').Schema } Schema
10045
- *
10046
- * @typedef { import('./types').FormEditorOptions } FormEditorOptions
10047
- * @typedef { import('./types').FormEditorProperties } FormEditorProperties
10048
- *
10049
- * @typedef { {
10050
- * properties: FormEditorProperties,
10051
- * schema: Schema
10052
- * } } State
10053
- *
10054
- * @typedef { (type:string, priority:number, handler:Function) => void } OnEventWithPriority
10055
- * @typedef { (type:string, handler:Function) => void } OnEventWithOutPriority
10056
- * @typedef { OnEventWithPriority & OnEventWithOutPriority } OnEventType
10472
+ /**
10473
+ * @typedef { import('./types').Injector } Injector
10474
+ * @typedef { import('./types').Module } Module
10475
+ * @typedef { import('./types').Schema } Schema
10476
+ *
10477
+ * @typedef { import('./types').FormEditorOptions } FormEditorOptions
10478
+ * @typedef { import('./types').FormEditorProperties } FormEditorProperties
10479
+ *
10480
+ * @typedef { {
10481
+ * properties: FormEditorProperties,
10482
+ * schema: Schema
10483
+ * } } State
10484
+ *
10485
+ * @typedef { (type:string, priority:number, handler:Function) => void } OnEventWithPriority
10486
+ * @typedef { (type:string, handler:Function) => void } OnEventWithOutPriority
10487
+ * @typedef { OnEventWithPriority & OnEventWithOutPriority } OnEventType
10057
10488
  */
10058
10489
 
10059
- /**
10060
- * The form editor.
10490
+ /**
10491
+ * The form editor.
10061
10492
  */
10062
10493
  class FormEditor {
10063
- /**
10064
- * @constructor
10065
- * @param {FormEditorOptions} options
10494
+ /**
10495
+ * @constructor
10496
+ * @param {FormEditorOptions} options
10066
10497
  */
10067
10498
  constructor(options = {}) {
10068
- /**
10069
- * @public
10070
- * @type {OnEventType}
10499
+ /**
10500
+ * @public
10501
+ * @type {OnEventType}
10071
10502
  */
10072
10503
  this.on = this._onEvent;
10073
10504
 
10074
- /**
10075
- * @public
10076
- * @type {String}
10505
+ /**
10506
+ * @public
10507
+ * @type {String}
10077
10508
  */
10078
10509
  this._id = ids.next();
10079
10510
 
10080
- /**
10081
- * @private
10082
- * @type {Element}
10511
+ /**
10512
+ * @private
10513
+ * @type {Element}
10083
10514
  */
10084
10515
  this._container = createFormContainer();
10085
10516
  this._container.setAttribute('input-handle-modified-keys', 'z,y');
@@ -10090,15 +10521,15 @@ class FormEditor {
10090
10521
  properties = {}
10091
10522
  } = options;
10092
10523
 
10093
- /**
10094
- * @private
10095
- * @type {any}
10524
+ /**
10525
+ * @private
10526
+ * @type {any}
10096
10527
  */
10097
10528
  this.exporter = exporter;
10098
10529
 
10099
- /**
10100
- * @private
10101
- * @type {State}
10530
+ /**
10531
+ * @private
10532
+ * @type {State}
10102
10533
  */
10103
10534
  this._state = {
10104
10535
  properties,
@@ -10127,10 +10558,10 @@ class FormEditor {
10127
10558
  this._detach(false);
10128
10559
  }
10129
10560
 
10130
- /**
10131
- * @param {Schema} schema
10132
- *
10133
- * @return {Promise<{ warnings: Array<any> }>}
10561
+ /**
10562
+ * @param {Schema} schema
10563
+ *
10564
+ * @return {Promise<{ warnings: Array<any> }>}
10134
10565
  */
10135
10566
  importSchema(schema) {
10136
10567
  return new Promise((resolve, reject) => {
@@ -10159,15 +10590,15 @@ class FormEditor {
10159
10590
  });
10160
10591
  }
10161
10592
 
10162
- /**
10163
- * @returns {Schema}
10593
+ /**
10594
+ * @returns {Schema}
10164
10595
  */
10165
10596
  saveSchema() {
10166
10597
  return this.getSchema();
10167
10598
  }
10168
10599
 
10169
- /**
10170
- * @returns {Schema}
10600
+ /**
10601
+ * @returns {Schema}
10171
10602
  */
10172
10603
  getSchema() {
10173
10604
  const {
@@ -10176,8 +10607,8 @@ class FormEditor {
10176
10607
  return exportSchema(schema, this.exporter, schemaVersion);
10177
10608
  }
10178
10609
 
10179
- /**
10180
- * @param {Element|string} parentNode
10610
+ /**
10611
+ * @param {Element|string} parentNode
10181
10612
  */
10182
10613
  attachTo(parentNode) {
10183
10614
  if (!parentNode) {
@@ -10195,10 +10626,10 @@ class FormEditor {
10195
10626
  this._detach();
10196
10627
  }
10197
10628
 
10198
- /**
10199
- * @internal
10200
- *
10201
- * @param {boolean} [emit]
10629
+ /**
10630
+ * @internal
10631
+ *
10632
+ * @param {boolean} [emit]
10202
10633
  */
10203
10634
  _detach(emit = true) {
10204
10635
  const container = this._container,
@@ -10212,9 +10643,9 @@ class FormEditor {
10212
10643
  parentNode.removeChild(container);
10213
10644
  }
10214
10645
 
10215
- /**
10216
- * @param {any} property
10217
- * @param {any} value
10646
+ /**
10647
+ * @param {any} property
10648
+ * @param {any} value
10218
10649
  */
10219
10650
  setProperty(property, value) {
10220
10651
  const properties = set$1(this._getState().properties, [property], value);
@@ -10223,21 +10654,21 @@ class FormEditor {
10223
10654
  });
10224
10655
  }
10225
10656
 
10226
- /**
10227
- * @param {string} type
10228
- * @param {Function} handler
10657
+ /**
10658
+ * @param {string} type
10659
+ * @param {Function} handler
10229
10660
  */
10230
10661
  off(type, handler) {
10231
10662
  this.get('eventBus').off(type, handler);
10232
10663
  }
10233
10664
 
10234
- /**
10235
- * @internal
10236
- *
10237
- * @param {FormEditorOptions} options
10238
- * @param {Element} container
10239
- *
10240
- * @returns {Injector}
10665
+ /**
10666
+ * @internal
10667
+ *
10668
+ * @param {FormEditorOptions} options
10669
+ * @param {Element} container
10670
+ *
10671
+ * @returns {Injector}
10241
10672
  */
10242
10673
  _createInjector(options, container) {
10243
10674
  const {
@@ -10259,22 +10690,22 @@ class FormEditor {
10259
10690
  }, core, ...modules, ...additionalModules]);
10260
10691
  }
10261
10692
 
10262
- /**
10263
- * @internal
10693
+ /**
10694
+ * @internal
10264
10695
  */
10265
10696
  _emit(type, data) {
10266
10697
  this.get('eventBus').fire(type, data);
10267
10698
  }
10268
10699
 
10269
- /**
10270
- * @internal
10700
+ /**
10701
+ * @internal
10271
10702
  */
10272
10703
  _getState() {
10273
10704
  return this._state;
10274
10705
  }
10275
10706
 
10276
- /**
10277
- * @internal
10707
+ /**
10708
+ * @internal
10278
10709
  */
10279
10710
  _setState(state) {
10280
10711
  this._state = {
@@ -10284,15 +10715,15 @@ class FormEditor {
10284
10715
  this._emit('changed', this._getState());
10285
10716
  }
10286
10717
 
10287
- /**
10288
- * @internal
10718
+ /**
10719
+ * @internal
10289
10720
  */
10290
10721
  _getModules() {
10291
10722
  return [ModelingModule, EditorActionsModule, DraggingModule, KeyboardModule, SelectionModule, PaletteModule, ExpressionLanguageModule, MarkdownModule, PropertiesPanelModule, RenderInjectionModule];
10292
10723
  }
10293
10724
 
10294
- /**
10295
- * @internal
10725
+ /**
10726
+ * @internal
10296
10727
  */
10297
10728
  _onEvent(type, priority, handler) {
10298
10729
  this.get('eventBus').on(type, priority, handler);