@bpmn-io/form-js-editor 1.0.0-alpha.9 → 1.1.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
@@ -6,7 +6,8 @@ import classnames from 'classnames';
6
6
  import { jsx, jsxs, Fragment as Fragment$1 } from 'preact/jsx-runtime';
7
7
  import { useContext, useState, useMemo, useEffect, useCallback, useRef as useRef$1, useLayoutEffect } from 'preact/hooks';
8
8
  import { createContext, Fragment, render, createElement } from 'preact';
9
- import React, { createPortal, useRef, useContext as useContext$1, useEffect as useEffect$1, forwardRef } from 'preact/compat';
9
+ import * as React from 'preact/compat';
10
+ import { createPortal, useRef, useContext as useContext$1, useEffect as useEffect$1, forwardRef } from 'preact/compat';
10
11
  import dragula from 'dragula';
11
12
  import { classes, query, closest, event, matches, domify } from 'min-dom';
12
13
  import { mutate } from 'array-move';
@@ -514,10 +515,10 @@ function invokeFunction(fn, args) {
514
515
  return fn.apply(null, args);
515
516
  }
516
517
 
517
- /**
518
- * A factory to create a configurable debouncer.
519
- *
520
- * @param {number|boolean} [config=true]
518
+ /**
519
+ * A factory to create a configurable debouncer.
520
+ *
521
+ * @param {number|boolean} [config=true]
521
522
  */
522
523
  function DebounceFactory(config = true) {
523
524
  const timeout = typeof config === 'number' ? config : config ? 300 : 0;
@@ -530,11 +531,11 @@ function DebounceFactory(config = true) {
530
531
  DebounceFactory.$inject = ['config.debounce'];
531
532
 
532
533
  class FieldFactory {
533
- /**
534
- * @constructor
535
- *
536
- * @param { import('./FormFieldRegistry').default } formFieldRegistry
537
- * @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
538
539
  */
539
540
  constructor(formFieldRegistry, formFields) {
540
541
  this._formFieldRegistry = formFieldRegistry;
@@ -597,11 +598,11 @@ class FieldFactory {
597
598
  FieldFactory.$inject = ['formFieldRegistry', 'formFields'];
598
599
 
599
600
  class FormFieldRegistry extends FormFieldRegistry$1 {
600
- /**
601
- * Updates a form fields id.
602
- *
603
- * @param {Object} formField
604
- * @param {string} newId
601
+ /**
602
+ * Updates a form fields id.
603
+ *
604
+ * @param {Object} formField
605
+ * @param {string} newId
605
606
  */
606
607
  updateId(formField, newId) {
607
608
  this._validateId(newId);
@@ -622,13 +623,13 @@ class FormFieldRegistry extends FormFieldRegistry$1 {
622
623
  }
623
624
  }
624
625
 
625
- /**
626
- * Validate the suitability of the given id and signals a problem
627
- * with an exception.
628
- *
629
- * @param {string} id
630
- *
631
- * @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
632
633
  */
633
634
  _validateId(id) {
634
635
  if (!id) {
@@ -645,11 +646,11 @@ const MAX_COLUMNS = 16;
645
646
  const MIN_COLUMNS = 2;
646
647
  const MAX_FIELDS_PER_ROW = 4;
647
648
  class FormLayoutValidator {
648
- /**
649
- * @constructor
650
- *
651
- * @param { import('./FormLayouter').default } formLayouter
652
- * @param { import('./FormFieldRegistry').default } formFieldRegistry
649
+ /**
650
+ * @constructor
651
+ *
652
+ * @param { import('./FormLayouter').default } formLayouter
653
+ * @param { import('./FormFieldRegistry').default } formFieldRegistry
653
654
  */
654
655
  constructor(formLayouter, formFieldRegistry) {
655
656
  this._formLayouter = formLayouter;
@@ -709,11 +710,11 @@ function calculateMaxColumnsWithAuto(autoCols) {
709
710
  }
710
711
 
711
712
  class Importer {
712
- /**
713
- * @constructor
714
- * @param { import('../core/FormFieldRegistry').default } formFieldRegistry
715
- * @param { import('../core/FieldFactory').default } fieldFactory
716
- * @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
717
718
  */
718
719
  constructor(formFieldRegistry, fieldFactory, formLayouter) {
719
720
  this._formFieldRegistry = formFieldRegistry;
@@ -721,21 +722,21 @@ class Importer {
721
722
  this._formLayouter = formLayouter;
722
723
  }
723
724
 
724
- /**
725
- * Import schema creating rows, fields, attaching additional
726
- * information to each field and adding fields to the
727
- * field registry.
728
- *
729
- * Additional information attached:
730
- *
731
- * * `id` (unless present)
732
- * * `_parent`
733
- * * `_path`
734
- *
735
- * @param {any} schema
736
- *
737
- * @typedef {{ warnings: Error[], schema: any }} ImportResult
738
- * @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}
739
740
  */
740
741
  importSchema(schema) {
741
742
  // TODO: Add warnings
@@ -753,12 +754,12 @@ class Importer {
753
754
  }
754
755
  }
755
756
 
756
- /**
757
- * @param {{[x: string]: any}} fieldAttrs
758
- * @param {String} [parentId]
759
- * @param {number} [index]
760
- *
761
- * @return {any} field
757
+ /**
758
+ * @param {{[x: string]: any}} fieldAttrs
759
+ * @param {String} [parentId]
760
+ * @param {number} [index]
761
+ *
762
+ * @return {any} field
762
763
  */
763
764
  importFormField(fieldAttrs, parentId, index) {
764
765
  const {
@@ -795,11 +796,11 @@ class Importer {
795
796
  return field;
796
797
  }
797
798
 
798
- /**
799
- * @param {Array<any>} components
800
- * @param {string} parentId
801
- *
802
- * @return {Array<any>} imported components
799
+ /**
800
+ * @param {Array<any>} components
801
+ * @param {string} parentId
802
+ *
803
+ * @return {Array<any>} imported components
803
804
  */
804
805
  importFormFields(components, parentId) {
805
806
  return components.map((component, index) => {
@@ -824,22 +825,22 @@ function editorFormFieldClasses(type, {
824
825
  });
825
826
  }
826
827
 
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
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
843
844
  */
844
845
  function createDragger(fn, dragPreview) {
845
846
  let self;
@@ -880,12 +881,12 @@ function createDragger(fn, dragPreview) {
880
881
  return onDragStart;
881
882
  }
882
883
 
883
- /**
884
- * Throttle function call according UI update cycle.
885
- *
886
- * @param {Function} fn
887
- *
888
- * @return {Function} throttled fn
884
+ /**
885
+ * Throttle function call according UI update cycle.
886
+ *
887
+ * @param {Function} fn
888
+ *
889
+ * @return {Function} throttled fn
889
890
  */
890
891
  function throttle(fn) {
891
892
  let active = false;
@@ -914,11 +915,11 @@ const DragAndDropContext = createContext({
914
915
  });
915
916
  var DragAndDropContext$1 = DragAndDropContext;
916
917
 
917
- /**
918
- * @param {string} type
919
- * @param {boolean} [strict]
920
- *
921
- * @returns {any}
918
+ /**
919
+ * @param {string} type
920
+ * @param {boolean} [strict]
921
+ *
922
+ * @returns {any}
922
923
  */
923
924
  function getService$1(type, strict) {}
924
925
  const FormEditorContext = createContext({
@@ -933,83 +934,146 @@ function useService$1 (type, strict) {
933
934
  return getService(type, strict);
934
935
  }
935
936
 
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
+ var SvgClose = function SvgClose(props) {
940
+ return /*#__PURE__*/React.createElement("svg", _extends$4({
941
+ xmlns: "http://www.w3.org/2000/svg",
942
+ width: 16,
943
+ height: 16,
944
+ fill: "currentColor"
945
+ }, props), _path$4 || (_path$4 = /*#__PURE__*/React.createElement("path", {
946
+ fillRule: "evenodd",
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
+ clipRule: "evenodd"
949
+ })));
950
+ };
951
+ var CloseIcon = SvgClose;
952
+
953
+ var _path$3, _path2$1;
936
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); }
937
- var CloseIcon = (({
938
- styles = {},
939
- ...props
940
- }) => /*#__PURE__*/React.createElement("svg", _extends$3({
941
- width: "16",
942
- height: "16",
943
- fill: "currentColor",
944
- xmlns: "http://www.w3.org/2000/svg"
945
- }, props), /*#__PURE__*/React.createElement("path", {
946
- fillRule: "evenodd",
947
- clipRule: "evenodd",
948
- d: "M12 4.7l-.7-.7L8 7.3 4.7 4l-.7.7L7.3 8 4 11.3l.7.7L8 8.7l3.3 3.3.7-.7L8.7 8 12 4.7z"
949
- })));
955
+ var SvgDelete = function SvgDelete(props) {
956
+ return /*#__PURE__*/React.createElement("svg", _extends$3({
957
+ xmlns: "http://www.w3.org/2000/svg",
958
+ width: 16,
959
+ height: 16,
960
+ fill: "none"
961
+ }, props), /*#__PURE__*/React.createElement("rect", {
962
+ width: 16,
963
+ height: 16,
964
+ x: 0.536,
965
+ fill: "#fff",
966
+ rx: 3,
967
+ style: {
968
+ mixBlendMode: "multiply"
969
+ }
970
+ }), /*#__PURE__*/React.createElement("path", {
971
+ fill: "#fff",
972
+ d: "M0 0h16v16H0z",
973
+ style: {
974
+ mixBlendMode: "multiply"
975
+ },
976
+ transform: "translate(.536)"
977
+ }), _path$3 || (_path$3 = /*#__PURE__*/React.createElement("path", {
978
+ fill: "currentcolor",
979
+ d: "M7.536 6h-1v6h1V6Zm3 0h-1v6h1V6Z"
980
+ })), _path2$1 || (_path2$1 = /*#__PURE__*/React.createElement("path", {
981
+ fill: "currentcolor",
982
+ d: "M2.536 3v1h1v10a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4h1V3h-12Zm2 11V4h8v10h-8Zm6-13h-4v1h4V1Z"
983
+ })));
984
+ };
985
+ var DeleteIcon$1 = SvgDelete;
950
986
 
987
+ var _path$2;
951
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); }
952
- var DeleteIcon$1 = (({
953
- styles = {},
954
- ...props
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
- })));
989
+ var SvgDraggable = function SvgDraggable(props) {
990
+ return /*#__PURE__*/React.createElement("svg", _extends$2({
991
+ xmlns: "http://www.w3.org/2000/svg",
992
+ xmlSpace: "preserve",
993
+ width: 16,
994
+ height: 16,
995
+ fill: "currentcolor",
996
+ viewBox: "0 0 32 32"
997
+ }, props), _path$2 || (_path$2 = /*#__PURE__*/React.createElement("path", {
998
+ d: "M10 6h4v4h-4zm8 0h4v4h-4zm-8 8h4v4h-4zm8 0h4v4h-4zm-8 8h4v4h-4zm8 0h4v4h-4z"
999
+ })), /*#__PURE__*/React.createElement("path", {
1000
+ d: "M0 0h32v32H0z",
1001
+ style: {
1002
+ fill: "none"
1003
+ }
1004
+ }));
1005
+ };
1006
+ var DraggableIcon = SvgDraggable;
982
1007
 
1008
+ var _path$1;
983
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); }
984
- var DraggableIcon = (({
985
- styles = {},
986
- ...props
987
- }) => /*#__PURE__*/React.createElement("svg", _extends$1({
988
- xmlns: "http://www.w3.org/2000/svg",
989
- width: "16",
990
- height: "16",
991
- fill: "currentcolor",
992
- viewBox: "0 0 32 32"
993
- }, props), /*#__PURE__*/React.createElement("path", {
994
- d: "M10 6h4v4h-4zm8 0h4v4h-4zm-8 8h4v4h-4zm8 0h4v4h-4zm-8 8h4v4h-4zm8 0h4v4h-4z"
995
- }), /*#__PURE__*/React.createElement("path", {
996
- d: "M0 0h32v32H0z",
997
- fill: "none"
998
- })));
1010
+ var SvgSearch = function SvgSearch(props) {
1011
+ return /*#__PURE__*/React.createElement("svg", _extends$1({
1012
+ xmlns: "http://www.w3.org/2000/svg",
1013
+ width: 15,
1014
+ height: 15,
1015
+ fill: "none"
1016
+ }, props), _path$1 || (_path$1 = /*#__PURE__*/React.createElement("path", {
1017
+ fill: "currentColor",
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
+ })));
1020
+ };
1021
+ var SearchIcon = SvgSearch;
999
1022
 
1023
+ var _path, _rect, _mask, _path2, _path3, _path4, _path5, _path6;
1000
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); }
1001
- var SearchIcon = (({
1002
- styles = {},
1003
- ...props
1004
- }) => /*#__PURE__*/React.createElement("svg", _extends({
1005
- width: "15",
1006
- height: "15",
1007
- fill: "none",
1008
- xmlns: "http://www.w3.org/2000/svg"
1009
- }, props), /*#__PURE__*/React.createElement("path", {
1010
- d: "M14.5 13.793l-3.776-3.776a5.508 5.508 0 10-.707.707l3.776 3.776.707-.707zM2 6.5a4.5 4.5 0 119 0 4.5 4.5 0 01-9 0z",
1011
- fill: "currentColor"
1012
- })));
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;
1013
1077
 
1014
1078
  function EditorText(props) {
1015
1079
  const {
@@ -1019,7 +1083,7 @@ function EditorText(props) {
1019
1083
  const Icon = iconsByType('text');
1020
1084
  const templating = useService$1('templating');
1021
1085
  const expressionLanguage = useService$1('expressionLanguage');
1022
- if (!text) {
1086
+ if (!text || !text.trim()) {
1023
1087
  return jsx("div", {
1024
1088
  class: editorFormFieldClasses(type),
1025
1089
  children: jsxs("div", {
@@ -1205,23 +1269,23 @@ var Slot = (props => {
1205
1269
  return fillsAndSeparators;
1206
1270
  });
1207
1271
 
1208
- /**
1209
- * Creates a Fragment for a fill.
1210
- *
1211
- * @param {Object} fill Fill to be rendered
1212
- * @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
1213
1277
  */
1214
1278
  const FillFragment = fill => jsx(Fragment, {
1215
1279
  children: fill.children
1216
1280
  }, fill.id);
1217
1281
 
1218
- /**
1219
- * Creates an array of fills, with separators inserted between groups.
1220
- *
1221
- * @param {Array} groups Groups of fills
1222
- * @param {Function} fillRenderer Function to create a fill
1223
- * @param {Function} separatorRenderer Function to create a separator
1224
- * @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
1225
1289
  */
1226
1290
  const buildFills = (groups, fillRenderer, separatorRenderer) => {
1227
1291
  const result = [];
@@ -1239,8 +1303,8 @@ const buildFills = (groups, fillRenderer, separatorRenderer) => {
1239
1303
  return result;
1240
1304
  };
1241
1305
 
1242
- /**
1243
- * Groups fills by group name property.
1306
+ /**
1307
+ * Groups fills by group name property.
1244
1308
  */
1245
1309
  const _groupByGroupName = fills => {
1246
1310
  const groups = [];
@@ -1260,8 +1324,8 @@ const _groupByGroupName = fills => {
1260
1324
  return Object.keys(groupsById).sort().map(id => groupsById[id]);
1261
1325
  };
1262
1326
 
1263
- /**
1264
- * Compares fills by priority.
1327
+ /**
1328
+ * Compares fills by priority.
1265
1329
  */
1266
1330
  const _comparePriority = (a, b) => {
1267
1331
  return (b.priority || 0) - (a.priority || 0);
@@ -1489,19 +1553,19 @@ const DRAG_NO_DROP_CLS = 'fjs-no-drop';
1489
1553
  const DRAG_NO_MOVE_CLS = 'fjs-no-move';
1490
1554
  const ERROR_DROP_CLS = 'fjs-error-drop';
1491
1555
 
1492
- /**
1493
- * @typedef { { id: String, components: Array<any> } } FormRow
1556
+ /**
1557
+ * @typedef { { id: String, components: Array<any> } } FormRow
1494
1558
  */
1495
1559
 
1496
1560
  class Dragging {
1497
- /**
1498
- * @constructor
1499
- *
1500
- * @param { import('../../core/FormFieldRegistry').default } formFieldRegistry
1501
- * @param { import('../../core/FormLayouter').default } formLayouter
1502
- * @param { import('../../core/FormLayoutValidator').default } formLayoutValidator
1503
- * @param { import('../../core/EventBus').default } eventBus
1504
- * @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
1505
1569
  */
1506
1570
  constructor(formFieldRegistry, formLayouter, formLayoutValidator, eventBus, modeling) {
1507
1571
  this._formFieldRegistry = formFieldRegistry;
@@ -1511,13 +1575,13 @@ class Dragging {
1511
1575
  this._modeling = modeling;
1512
1576
  }
1513
1577
 
1514
- /**
1515
- * Calculcates position in form schema given the dropped place.
1516
- *
1517
- * @param { FormRow } targetRow
1518
- * @param { any } targetFormField
1519
- * @param { HTMLElement } sibling
1520
- * @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 }
1521
1585
  */
1522
1586
  getTargetIndex(targetRow, targetFormField, sibling) {
1523
1587
  /** @type HTMLElement */
@@ -1619,8 +1683,8 @@ class Dragging {
1619
1683
  }
1620
1684
  }
1621
1685
 
1622
- /**
1623
- * @param { { container: Array<string>, direction: string, mirrorContainer: string } } options
1686
+ /**
1687
+ * @param { { container: Array<string>, direction: string, mirrorContainer: string } } options
1624
1688
  */
1625
1689
  createDragulaInstance(options) {
1626
1690
  const {
@@ -1920,7 +1984,19 @@ function ContextPad(props) {
1920
1984
  });
1921
1985
  }
1922
1986
  function Empty(props) {
1923
- return null;
1987
+ return jsx("div", {
1988
+ class: "fjs-empty-editor",
1989
+ children: jsxs("div", {
1990
+ class: "fjs-empty-editor-card",
1991
+ children: [jsx(EmptyFormIcon, {}), jsx("h2", {
1992
+ children: "Build your form"
1993
+ }), jsx("span", {
1994
+ children: "Drag and drop components here to start designing."
1995
+ }), jsx("span", {
1996
+ children: "Use the preview window to test your form."
1997
+ })]
1998
+ })
1999
+ });
1924
2000
  }
1925
2001
  function Element$1(props) {
1926
2002
  const eventBus = useService$1('eventBus'),
@@ -2017,7 +2093,7 @@ function DebugColumns(props) {
2017
2093
  return null;
2018
2094
  }
2019
2095
  return jsx("div", {
2020
- 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;",
2096
+ 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;",
2021
2097
  class: "fjs-debug-columns",
2022
2098
  children: (field.layout || {}).columns || 'auto'
2023
2099
  });
@@ -3076,10 +3152,10 @@ function updateRow(formField, rowId) {
3076
3152
  }
3077
3153
 
3078
3154
  class AddFormFieldHandler {
3079
- /**
3080
- * @constructor
3081
- * @param { import('../../../FormEditor').default } formEditor
3082
- * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3155
+ /**
3156
+ * @constructor
3157
+ * @param { import('../../../FormEditor').default } formEditor
3158
+ * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3083
3159
  */
3084
3160
  constructor(formEditor, formFieldRegistry) {
3085
3161
  this._formEditor = formEditor;
@@ -3140,10 +3216,10 @@ class AddFormFieldHandler {
3140
3216
  AddFormFieldHandler.$inject = ['formEditor', 'formFieldRegistry'];
3141
3217
 
3142
3218
  class EditFormFieldHandler {
3143
- /**
3144
- * @constructor
3145
- * @param { import('../../../FormEditor').default } formEditor
3146
- * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3219
+ /**
3220
+ * @constructor
3221
+ * @param { import('../../../FormEditor').default } formEditor
3222
+ * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3147
3223
  */
3148
3224
  constructor(formEditor, formFieldRegistry) {
3149
3225
  this._formEditor = formEditor;
@@ -3206,10 +3282,10 @@ class EditFormFieldHandler {
3206
3282
  EditFormFieldHandler.$inject = ['formEditor', 'formFieldRegistry'];
3207
3283
 
3208
3284
  class MoveFormFieldHandler {
3209
- /**
3210
- * @constructor
3211
- * @param { import('../../../FormEditor').default } formEditor
3212
- * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3285
+ /**
3286
+ * @constructor
3287
+ * @param { import('../../../FormEditor').default } formEditor
3288
+ * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3213
3289
  */
3214
3290
  constructor(formEditor, formFieldRegistry) {
3215
3291
  this._formEditor = formEditor;
@@ -3298,10 +3374,10 @@ class MoveFormFieldHandler {
3298
3374
  MoveFormFieldHandler.$inject = ['formEditor', 'formFieldRegistry'];
3299
3375
 
3300
3376
  class RemoveFormFieldHandler {
3301
- /**
3302
- * @constructor
3303
- * @param { import('../../../FormEditor').default } formEditor
3304
- * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3377
+ /**
3378
+ * @constructor
3379
+ * @param { import('../../../FormEditor').default } formEditor
3380
+ * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3305
3381
  */
3306
3382
  constructor(formEditor, formFieldRegistry) {
3307
3383
  this._formEditor = formEditor;
@@ -3361,9 +3437,9 @@ class RemoveFormFieldHandler {
3361
3437
  RemoveFormFieldHandler.$inject = ['formEditor', 'formFieldRegistry'];
3362
3438
 
3363
3439
  class UpdateIdClaimHandler {
3364
- /**
3365
- * @constructor
3366
- * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3440
+ /**
3441
+ * @constructor
3442
+ * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3367
3443
  */
3368
3444
  constructor(formFieldRegistry) {
3369
3445
  this._formFieldRegistry = formFieldRegistry;
@@ -3396,9 +3472,9 @@ class UpdateIdClaimHandler {
3396
3472
  UpdateIdClaimHandler.$inject = ['formFieldRegistry'];
3397
3473
 
3398
3474
  class UpdateKeyClaimHandler {
3399
- /**
3400
- * @constructor
3401
- * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3475
+ /**
3476
+ * @constructor
3477
+ * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3402
3478
  */
3403
3479
  constructor(formFieldRegistry) {
3404
3480
  this._formFieldRegistry = formFieldRegistry;
@@ -3864,8 +3940,8 @@ class ValidateBehavior extends CommandInterceptor {
3864
3940
  constructor(eventBus) {
3865
3941
  super(eventBus);
3866
3942
 
3867
- /**
3868
- * Remove custom validation if <validationType> is about to be added.
3943
+ /**
3944
+ * Remove custom validation if <validationType> is about to be added.
3869
3945
  */
3870
3946
  // @ts-ignore-next-line
3871
3947
  this.preExecute('formField.edit', function (context) {
@@ -4445,22 +4521,22 @@ var SelectionModule = {
4445
4521
  selectionBehavior: ['type', SelectionBehavior]
4446
4522
  };
4447
4523
 
4448
- /**
4449
- * Base class for sectionable UI modules.
4450
- *
4451
- * @property {EventBus} _eventBus - EventBus instance used for event handling.
4452
- * @property {string} managerType - Type of the render manager. Used to form event names.
4453
- *
4454
- * @class SectionModuleBase
4524
+ /**
4525
+ * Base class for sectionable UI modules.
4526
+ *
4527
+ * @property {EventBus} _eventBus - EventBus instance used for event handling.
4528
+ * @property {string} managerType - Type of the render manager. Used to form event names.
4529
+ *
4530
+ * @class SectionModuleBase
4455
4531
  */
4456
4532
  class SectionModuleBase {
4457
- /**
4458
- * Create a SectionModuleBase instance.
4459
- *
4460
- * @param {any} eventBus - The EventBus instance used for event handling.
4461
- * @param {string} sectionKey - The type of render manager. Used to form event names.
4462
- *
4463
- * @constructor
4533
+ /**
4534
+ * Create a SectionModuleBase instance.
4535
+ *
4536
+ * @param {any} eventBus - The EventBus instance used for event handling.
4537
+ * @param {string} sectionKey - The type of render manager. Used to form event names.
4538
+ *
4539
+ * @constructor
4464
4540
  */
4465
4541
  constructor(eventBus, sectionKey) {
4466
4542
  this._eventBus = eventBus;
@@ -4473,10 +4549,10 @@ class SectionModuleBase {
4473
4549
  });
4474
4550
  }
4475
4551
 
4476
- /**
4477
- * Attach the managed section to a parent node.
4478
- *
4479
- * @param {HTMLElement} container - The parent node to attach to.
4552
+ /**
4553
+ * Attach the managed section to a parent node.
4554
+ *
4555
+ * @param {HTMLElement} container - The parent node to attach to.
4480
4556
  */
4481
4557
  attachTo(container) {
4482
4558
  this._onceSectionRendered(() => this._eventBus.fire(`${this._sectionKey}.attach`, {
@@ -4484,22 +4560,22 @@ class SectionModuleBase {
4484
4560
  }));
4485
4561
  }
4486
4562
 
4487
- /**
4488
- * Detach the managed section from its parent node.
4563
+ /**
4564
+ * Detach the managed section from its parent node.
4489
4565
  */
4490
4566
  detach() {
4491
4567
  this._onceSectionRendered(() => this._eventBus.fire(`${this._sectionKey}.detach`));
4492
4568
  }
4493
4569
 
4494
- /**
4495
- * Reset the managed section to its initial state.
4570
+ /**
4571
+ * Reset the managed section to its initial state.
4496
4572
  */
4497
4573
  reset() {
4498
4574
  this._onceSectionRendered(() => this._eventBus.fire(`${this._sectionKey}.reset`));
4499
4575
  }
4500
4576
 
4501
- /**
4502
- * Circumvents timing issues.
4577
+ /**
4578
+ * Circumvents timing issues.
4503
4579
  */
4504
4580
  _onceSectionRendered(callback) {
4505
4581
  if (this.isSectionRendered) {
@@ -5982,150 +6058,300 @@ function isEdited$7(node) {
5982
6058
  function prefixId$6(id) {
5983
6059
  return `bio-properties-panel-${id}`;
5984
6060
  }
5985
- const noop$1 = () => {};
5986
- function FeelTextfield(props) {
6061
+ function NumberField(props) {
5987
6062
  const {
5988
6063
  debounce,
6064
+ disabled,
6065
+ displayLabel = true,
5989
6066
  id,
6067
+ inputRef,
5990
6068
  label,
6069
+ max,
6070
+ min,
5991
6071
  onInput,
5992
- onError,
5993
- feel,
6072
+ step,
5994
6073
  value = '',
5995
- disabled = false,
5996
- variables,
5997
- tooltipContainer,
5998
- OptionalComponent = OptionalFeelInput
6074
+ onFocus,
6075
+ onBlur
5999
6076
  } = props;
6000
- const [localValue, _setLocalValue] = useState(value);
6001
- const editorRef = useShowEntryEvent(id);
6002
- const containerRef = useRef$1();
6003
- const feelActive = isString(localValue) && localValue.startsWith('=') || feel === 'required';
6004
- const feelOnlyValue = isString(localValue) && localValue.startsWith('=') ? localValue.substring(1) : localValue;
6005
- const [focus, _setFocus] = useState(undefined);
6006
- const setFocus = (offset = 0) => {
6007
- const hasFocus = containerRef.current.contains(document.activeElement);
6008
-
6009
- // Keep caret position if it is already focused, otherwise focus at the end
6010
- const position = hasFocus ? document.activeElement.selectionStart : Infinity;
6011
- _setFocus(position + offset);
6012
- };
6077
+ const [localValue, setLocalValue] = useState(value);
6013
6078
  const handleInputCallback = useMemo(() => {
6014
- return debounce(newValue => {
6015
- onInput(newValue);
6079
+ return debounce(event => {
6080
+ const {
6081
+ validity,
6082
+ value
6083
+ } = event.target;
6084
+ if (validity.valid) {
6085
+ onInput(value ? parseFloat(value) : undefined);
6086
+ }
6016
6087
  });
6017
6088
  }, [onInput, debounce]);
6018
- const setLocalValue = newValue => {
6019
- _setLocalValue(newValue);
6020
- if (!newValue || newValue === '=') {
6021
- handleInputCallback(undefined);
6022
- } else {
6023
- handleInputCallback(newValue);
6024
- }
6025
- };
6026
- const handleFeelToggle = useStaticCallback(() => {
6027
- if (feel === 'required') {
6028
- return;
6029
- }
6030
- if (!feelActive) {
6031
- setLocalValue('=' + localValue);
6032
- } else {
6033
- setLocalValue(feelOnlyValue);
6034
- }
6035
- });
6036
- const handleLocalInput = newValue => {
6037
- if (feelActive) {
6038
- newValue = '=' + newValue;
6039
- }
6040
- if (newValue === localValue) {
6041
- return;
6042
- }
6043
- setLocalValue(newValue);
6044
- if (!feelActive && isString(newValue) && newValue.startsWith('=')) {
6045
- // focus is behind `=` sign that will be removed
6046
- setFocus(-1);
6047
- }
6089
+ const handleInput = e => {
6090
+ handleInputCallback(e);
6091
+ setLocalValue(e.target.value);
6048
6092
  };
6049
- const handleLint = useStaticCallback(lint => {
6050
- if (!(lint && lint.length)) {
6051
- onError(undefined);
6052
- return;
6053
- }
6054
- const error = lint[0];
6055
- const message = `${error.source}: ${error.message}`;
6056
- onError(message);
6057
- });
6058
- useEffect(() => {
6059
- if (typeof focus !== 'undefined') {
6060
- editorRef.current.focus(focus);
6061
- _setFocus(undefined);
6062
- }
6063
- }, [focus]);
6064
6093
  useEffect(() => {
6065
6094
  if (value === localValue) {
6066
6095
  return;
6067
6096
  }
6068
-
6069
- // External value change removed content => keep FEEL configuration
6070
- if (!value) {
6071
- setLocalValue(feelActive ? '=' : '');
6072
- return;
6073
- }
6074
6097
  setLocalValue(value);
6075
6098
  }, [value]);
6076
-
6077
- // copy-paste integration
6078
- useEffect(() => {
6079
- const copyHandler = event => {
6080
- if (!feelActive) {
6081
- return;
6082
- }
6083
- event.clipboardData.setData('application/FEEL', event.clipboardData.getData('text'));
6084
- };
6085
- const pasteHandler = event => {
6086
- if (feelActive) {
6087
- return;
6088
- }
6089
- const data = event.clipboardData.getData('application/FEEL');
6090
- if (data) {
6091
- setTimeout(() => {
6092
- handleFeelToggle();
6093
- setFocus();
6094
- });
6095
- }
6096
- };
6097
- containerRef.current.addEventListener('copy', copyHandler);
6098
- containerRef.current.addEventListener('cut', copyHandler);
6099
- containerRef.current.addEventListener('paste', pasteHandler);
6100
- return () => {
6101
- containerRef.current.removeEventListener('copy', copyHandler);
6102
- containerRef.current.removeEventListener('cut', copyHandler);
6103
- containerRef.current.removeEventListener('paste', pasteHandler);
6104
- };
6105
- }, [containerRef, feelActive, handleFeelToggle, setFocus]);
6106
6099
  return jsxs("div", {
6107
- class: classnames('bio-properties-panel-feel-entry', {
6108
- 'feel-active': feelActive
6109
- }),
6110
- children: [jsxs("label", {
6100
+ class: "bio-properties-panel-numberfield",
6101
+ children: [displayLabel && jsx("label", {
6111
6102
  for: prefixId$5(id),
6112
6103
  class: "bio-properties-panel-label",
6113
- onClick: () => setFocus(),
6114
- children: [label, jsx(FeelIcon, {
6115
- label: label,
6116
- feel: feel,
6117
- onClick: handleFeelToggle,
6118
- active: feelActive
6119
- })]
6120
- }), jsxs("div", {
6121
- class: "bio-properties-panel-feel-container",
6122
- ref: containerRef,
6123
- children: [jsx(FeelIndicator, {
6124
- active: feelActive,
6125
- disabled: feel !== 'optional' || disabled,
6104
+ children: label
6105
+ }), jsx("input", {
6106
+ id: prefixId$5(id),
6107
+ ref: inputRef,
6108
+ type: "number",
6109
+ name: id,
6110
+ spellCheck: "false",
6111
+ autoComplete: "off",
6112
+ disabled: disabled,
6113
+ class: "bio-properties-panel-input",
6114
+ max: max,
6115
+ min: min,
6116
+ onInput: handleInput,
6117
+ onFocus: onFocus,
6118
+ onBlur: onBlur,
6119
+ step: step,
6120
+ value: localValue
6121
+ })]
6122
+ });
6123
+ }
6124
+
6125
+ /**
6126
+ * @param {Object} props
6127
+ * @param {Boolean} props.debounce
6128
+ * @param {String} props.description
6129
+ * @param {Boolean} props.disabled
6130
+ * @param {Object} props.element
6131
+ * @param {Function} props.getValue
6132
+ * @param {String} props.id
6133
+ * @param {String} props.label
6134
+ * @param {String} props.max
6135
+ * @param {String} props.min
6136
+ * @param {Function} props.setValue
6137
+ * @param {Function} props.onFocus
6138
+ * @param {Function} props.onBlur
6139
+ * @param {String} props.step
6140
+ * @param {Function} props.validate
6141
+ */
6142
+ function NumberFieldEntry(props) {
6143
+ const {
6144
+ debounce,
6145
+ description,
6146
+ disabled,
6147
+ element,
6148
+ getValue,
6149
+ id,
6150
+ label,
6151
+ max,
6152
+ min,
6153
+ setValue,
6154
+ step,
6155
+ onFocus,
6156
+ onBlur,
6157
+ validate
6158
+ } = props;
6159
+ const globalError = useError(id);
6160
+ const [localError, setLocalError] = useState(null);
6161
+ let value = getValue(element);
6162
+ useEffect(() => {
6163
+ if (isFunction(validate)) {
6164
+ const newValidationError = validate(value) || null;
6165
+ setLocalError(newValidationError);
6166
+ }
6167
+ }, [value]);
6168
+ const onInput = newValue => {
6169
+ let newValidationError = null;
6170
+ if (isFunction(validate)) {
6171
+ newValidationError = validate(newValue) || null;
6172
+ }
6173
+ setValue(newValue, newValidationError);
6174
+ setLocalError(newValidationError);
6175
+ };
6176
+ const error = globalError || localError;
6177
+ return jsxs("div", {
6178
+ class: classnames('bio-properties-panel-entry', error ? 'has-error' : ''),
6179
+ "data-entry-id": id,
6180
+ children: [jsx(NumberField, {
6181
+ debounce: debounce,
6182
+ disabled: disabled,
6183
+ id: id,
6184
+ label: label,
6185
+ onFocus: onFocus,
6186
+ onBlur: onBlur,
6187
+ onInput: onInput,
6188
+ max: max,
6189
+ min: min,
6190
+ step: step,
6191
+ value: value
6192
+ }, element), error && jsx("div", {
6193
+ class: "bio-properties-panel-error",
6194
+ children: error
6195
+ }), jsx(Description$1, {
6196
+ forId: id,
6197
+ element: element,
6198
+ value: description
6199
+ })]
6200
+ });
6201
+ }
6202
+ function isEdited$6(node) {
6203
+ return node && !!node.value;
6204
+ }
6205
+
6206
+ // helpers /////////////////
6207
+
6208
+ function prefixId$5(id) {
6209
+ return `bio-properties-panel-${id}`;
6210
+ }
6211
+ const noop$1 = () => {};
6212
+ function FeelTextfield(props) {
6213
+ const {
6214
+ debounce,
6215
+ id,
6216
+ label,
6217
+ onInput,
6218
+ onError,
6219
+ feel,
6220
+ value = '',
6221
+ disabled = false,
6222
+ variables,
6223
+ tooltipContainer,
6224
+ OptionalComponent = OptionalFeelInput
6225
+ } = props;
6226
+ const [localValue, _setLocalValue] = useState(value);
6227
+ const editorRef = useShowEntryEvent(id);
6228
+ const containerRef = useRef$1();
6229
+ const feelActive = isString(localValue) && localValue.startsWith('=') || feel === 'required';
6230
+ const feelOnlyValue = isString(localValue) && localValue.startsWith('=') ? localValue.substring(1) : localValue;
6231
+ const [focus, _setFocus] = useState(undefined);
6232
+ const setFocus = (offset = 0) => {
6233
+ const hasFocus = containerRef.current.contains(document.activeElement);
6234
+
6235
+ // Keep caret position if it is already focused, otherwise focus at the end
6236
+ const position = hasFocus ? document.activeElement.selectionStart : Infinity;
6237
+ _setFocus(position + offset);
6238
+ };
6239
+ const handleInputCallback = useMemo(() => {
6240
+ return debounce(newValue => {
6241
+ onInput(newValue);
6242
+ });
6243
+ }, [onInput, debounce]);
6244
+ const setLocalValue = newValue => {
6245
+ _setLocalValue(newValue);
6246
+ if (!newValue || newValue === '=') {
6247
+ handleInputCallback(undefined);
6248
+ } else {
6249
+ handleInputCallback(newValue);
6250
+ }
6251
+ };
6252
+ const handleFeelToggle = useStaticCallback(() => {
6253
+ if (feel === 'required') {
6254
+ return;
6255
+ }
6256
+ if (!feelActive) {
6257
+ setLocalValue('=' + localValue);
6258
+ } else {
6259
+ setLocalValue(feelOnlyValue);
6260
+ }
6261
+ });
6262
+ const handleLocalInput = newValue => {
6263
+ if (feelActive) {
6264
+ newValue = '=' + newValue;
6265
+ }
6266
+ if (newValue === localValue) {
6267
+ return;
6268
+ }
6269
+ setLocalValue(newValue);
6270
+ if (!feelActive && isString(newValue) && newValue.startsWith('=')) {
6271
+ // focus is behind `=` sign that will be removed
6272
+ setFocus(-1);
6273
+ }
6274
+ };
6275
+ const handleLint = useStaticCallback(lint => {
6276
+ if (!(lint && lint.length)) {
6277
+ onError(undefined);
6278
+ return;
6279
+ }
6280
+ const error = lint[0];
6281
+ const message = `${error.source}: ${error.message}`;
6282
+ onError(message);
6283
+ });
6284
+ useEffect(() => {
6285
+ if (typeof focus !== 'undefined') {
6286
+ editorRef.current.focus(focus);
6287
+ _setFocus(undefined);
6288
+ }
6289
+ }, [focus]);
6290
+ useEffect(() => {
6291
+ if (value === localValue) {
6292
+ return;
6293
+ }
6294
+
6295
+ // External value change removed content => keep FEEL configuration
6296
+ if (!value) {
6297
+ setLocalValue(feelActive ? '=' : '');
6298
+ return;
6299
+ }
6300
+ setLocalValue(value);
6301
+ }, [value]);
6302
+
6303
+ // copy-paste integration
6304
+ useEffect(() => {
6305
+ const copyHandler = event => {
6306
+ if (!feelActive) {
6307
+ return;
6308
+ }
6309
+ event.clipboardData.setData('application/FEEL', event.clipboardData.getData('text'));
6310
+ };
6311
+ const pasteHandler = event => {
6312
+ if (feelActive) {
6313
+ return;
6314
+ }
6315
+ const data = event.clipboardData.getData('application/FEEL');
6316
+ if (data) {
6317
+ setTimeout(() => {
6318
+ handleFeelToggle();
6319
+ setFocus();
6320
+ });
6321
+ }
6322
+ };
6323
+ containerRef.current.addEventListener('copy', copyHandler);
6324
+ containerRef.current.addEventListener('cut', copyHandler);
6325
+ containerRef.current.addEventListener('paste', pasteHandler);
6326
+ return () => {
6327
+ containerRef.current.removeEventListener('copy', copyHandler);
6328
+ containerRef.current.removeEventListener('cut', copyHandler);
6329
+ containerRef.current.removeEventListener('paste', pasteHandler);
6330
+ };
6331
+ }, [containerRef, feelActive, handleFeelToggle, setFocus]);
6332
+ return jsxs("div", {
6333
+ class: classnames('bio-properties-panel-feel-entry', {
6334
+ 'feel-active': feelActive
6335
+ }),
6336
+ children: [jsxs("label", {
6337
+ for: prefixId$4(id),
6338
+ class: "bio-properties-panel-label",
6339
+ onClick: () => setFocus(),
6340
+ children: [label, jsx(FeelIcon, {
6341
+ label: label,
6342
+ feel: feel,
6343
+ onClick: handleFeelToggle,
6344
+ active: feelActive
6345
+ })]
6346
+ }), jsxs("div", {
6347
+ class: "bio-properties-panel-feel-container",
6348
+ ref: containerRef,
6349
+ children: [jsx(FeelIndicator, {
6350
+ active: feelActive,
6351
+ disabled: feel !== 'optional' || disabled,
6126
6352
  onClick: handleFeelToggle
6127
6353
  }), feelActive ? jsx(CodeEditor, {
6128
- id: prefixId$5(id),
6354
+ id: prefixId$4(id),
6129
6355
  name: id,
6130
6356
  onInput: handleLocalInput,
6131
6357
  disabled: disabled,
@@ -6142,7 +6368,7 @@ function FeelTextfield(props) {
6142
6368
  ...props,
6143
6369
  onInput: handleLocalInput,
6144
6370
  contentAttributes: {
6145
- 'id': prefixId$5(id),
6371
+ 'id': prefixId$4(id),
6146
6372
  'aria-label': label
6147
6373
  },
6148
6374
  value: localValue,
@@ -6180,7 +6406,7 @@ const OptionalFeelInput = forwardRef((props, ref) => {
6180
6406
  }
6181
6407
  };
6182
6408
  return jsx("input", {
6183
- id: prefixId$5(id),
6409
+ id: prefixId$4(id),
6184
6410
  type: "text",
6185
6411
  ref: inputRef,
6186
6412
  name: id,
@@ -6194,6 +6420,53 @@ const OptionalFeelInput = forwardRef((props, ref) => {
6194
6420
  value: value || ''
6195
6421
  });
6196
6422
  });
6423
+ const OptionalFeelNumberField = forwardRef((props, ref) => {
6424
+ const {
6425
+ id,
6426
+ debounce,
6427
+ disabled,
6428
+ onInput,
6429
+ value,
6430
+ min,
6431
+ max,
6432
+ step,
6433
+ onFocus,
6434
+ onBlur
6435
+ } = props;
6436
+ const inputRef = useRef$1();
6437
+
6438
+ // To be consistent with the FEEL editor, set focus at start of input
6439
+ // this ensures clean editing experience when switching with the keyboard
6440
+ ref.current = {
6441
+ focus: position => {
6442
+ const input = inputRef.current;
6443
+ if (!input) {
6444
+ return;
6445
+ }
6446
+ input.focus();
6447
+ if (typeof position === 'number' && position !== Infinity) {
6448
+ if (position > value.length) {
6449
+ position = value.length;
6450
+ }
6451
+ input.setSelectionRange(position, position);
6452
+ }
6453
+ }
6454
+ };
6455
+ return jsx(NumberField, {
6456
+ id: id,
6457
+ debounce: debounce,
6458
+ disabled: disabled,
6459
+ displayLabel: false,
6460
+ inputRef: inputRef,
6461
+ max: max,
6462
+ min: min,
6463
+ onInput: onInput,
6464
+ step: step,
6465
+ value: value,
6466
+ onFocus: onFocus,
6467
+ onBlur: onBlur
6468
+ });
6469
+ });
6197
6470
  forwardRef((props, ref) => {
6198
6471
  const {
6199
6472
  id,
@@ -6218,7 +6491,7 @@ forwardRef((props, ref) => {
6218
6491
  }
6219
6492
  };
6220
6493
  return jsx("textarea", {
6221
- id: prefixId$5(id),
6494
+ id: prefixId$4(id),
6222
6495
  type: "text",
6223
6496
  ref: inputRef,
6224
6497
  name: id,
@@ -6294,7 +6567,7 @@ forwardRef((props, ref) => {
6294
6567
  };
6295
6568
  return jsx("input", {
6296
6569
  ref: inputRef,
6297
- id: prefixId$5(id),
6570
+ id: prefixId$4(id),
6298
6571
  name: id,
6299
6572
  onFocus: onFocus,
6300
6573
  onBlur: onBlur,
@@ -6346,11 +6619,9 @@ function FeelEntry(props) {
6346
6619
  onFocus,
6347
6620
  onBlur
6348
6621
  } = props;
6349
- const [cachedInvalidValue, setCachedInvalidValue] = useState(null);
6350
6622
  const [validationError, setValidationError] = useState(null);
6351
6623
  const [localError, setLocalError] = useState(null);
6352
6624
  let value = getValue(element);
6353
- const previousValue = usePrevious(value);
6354
6625
  useEffect(() => {
6355
6626
  if (isFunction(validate)) {
6356
6627
  const newValidationError = validate(value) || null;
@@ -6362,32 +6633,28 @@ function FeelEntry(props) {
6362
6633
  if (isFunction(validate)) {
6363
6634
  newValidationError = validate(newValue) || null;
6364
6635
  }
6365
- if (newValidationError) {
6366
- setCachedInvalidValue(newValue);
6367
- } else {
6368
- // don't create multiple commandStack entries for the same value
6369
- if (newValue !== value) {
6370
- setValue(newValue);
6371
- }
6636
+
6637
+ // don't create multiple commandStack entries for the same value
6638
+ if (newValue !== value) {
6639
+ setValue(newValue, newValidationError);
6372
6640
  }
6373
6641
  setValidationError(newValidationError);
6374
6642
  });
6375
6643
  const onError = useCallback(err => {
6376
6644
  setLocalError(err);
6377
6645
  }, []);
6378
- if (previousValue === value && validationError) {
6379
- value = cachedInvalidValue;
6380
- }
6381
6646
  const temporaryError = useError(id);
6382
6647
  const error = localError || temporaryError || validationError;
6383
6648
  return jsxs("div", {
6384
6649
  class: classnames(props.class, 'bio-properties-panel-entry', error ? 'has-error' : ''),
6385
6650
  "data-entry-id": id,
6386
- children: [jsx(FeelTextfield, {
6651
+ children: [createElement(FeelTextfield, {
6652
+ ...props,
6387
6653
  debounce: debounce,
6388
6654
  disabled: disabled,
6389
6655
  feel: feel,
6390
6656
  id: id,
6657
+ key: element,
6391
6658
  label: label,
6392
6659
  onInput: onInput,
6393
6660
  onError: onError,
@@ -6401,7 +6668,7 @@ function FeelEntry(props) {
6401
6668
  variables: variables,
6402
6669
  tooltipContainer: tooltipContainer,
6403
6670
  OptionalComponent: props.OptionalComponent
6404
- }, element), error && jsx("div", {
6671
+ }), error && jsx("div", {
6405
6672
  class: "bio-properties-panel-error",
6406
6673
  children: error
6407
6674
  }), jsx(Description$1, {
@@ -6412,6 +6679,36 @@ function FeelEntry(props) {
6412
6679
  });
6413
6680
  }
6414
6681
 
6682
+ /**
6683
+ * @param {Object} props
6684
+ * @param {Object} props.element
6685
+ * @param {String} props.id
6686
+ * @param {String} props.description
6687
+ * @param {Boolean} props.debounce
6688
+ * @param {Boolean} props.disabled
6689
+ * @param {String} props.max
6690
+ * @param {String} props.min
6691
+ * @param {String} props.step
6692
+ * @param {Boolean} props.feel
6693
+ * @param {String} props.label
6694
+ * @param {Function} props.getValue
6695
+ * @param {Function} props.setValue
6696
+ * @param {Function} props.tooltipContainer
6697
+ * @param {Function} props.validate
6698
+ * @param {Function} props.show
6699
+ * @param {Function} props.example
6700
+ * @param {Function} props.variables
6701
+ * @param {Function} props.onFocus
6702
+ * @param {Function} props.onBlur
6703
+ */
6704
+ function FeelNumberEntry(props) {
6705
+ return jsx(FeelEntry, {
6706
+ class: "bio-properties-panel-feel-number",
6707
+ OptionalComponent: OptionalFeelNumberField,
6708
+ ...props
6709
+ });
6710
+ }
6711
+
6415
6712
  /**
6416
6713
  * @param {Object} props
6417
6714
  * @param {Object} props.element
@@ -6467,7 +6764,7 @@ function FeelTemplatingEntry(props) {
6467
6764
  ...props
6468
6765
  });
6469
6766
  }
6470
- function isEdited$6(node) {
6767
+ function isEdited$5(node) {
6471
6768
  if (!node) {
6472
6769
  return false;
6473
6770
  }
@@ -6479,162 +6776,6 @@ function isEdited$6(node) {
6479
6776
 
6480
6777
  // helpers /////////////////
6481
6778
 
6482
- function prefixId$5(id) {
6483
- return `bio-properties-panel-${id}`;
6484
- }
6485
- function NumberField(props) {
6486
- const {
6487
- debounce,
6488
- disabled,
6489
- id,
6490
- label,
6491
- max,
6492
- min,
6493
- onInput,
6494
- step,
6495
- value = '',
6496
- onFocus,
6497
- onBlur
6498
- } = props;
6499
- const [localValue, setLocalValue] = useState(value);
6500
- const handleInputCallback = useMemo(() => {
6501
- return debounce(event => {
6502
- const {
6503
- validity,
6504
- value
6505
- } = event.target;
6506
- if (validity.valid) {
6507
- onInput(value ? parseFloat(value) : undefined);
6508
- }
6509
- });
6510
- }, [onInput, debounce]);
6511
- const handleInput = e => {
6512
- handleInputCallback(e);
6513
- setLocalValue(e.target.value);
6514
- };
6515
- useEffect(() => {
6516
- if (value === localValue) {
6517
- return;
6518
- }
6519
- setLocalValue(value);
6520
- }, [value]);
6521
- return jsxs("div", {
6522
- class: "bio-properties-panel-numberfield",
6523
- children: [jsx("label", {
6524
- for: prefixId$4(id),
6525
- class: "bio-properties-panel-label",
6526
- children: label
6527
- }), jsx("input", {
6528
- id: prefixId$4(id),
6529
- type: "number",
6530
- name: id,
6531
- spellCheck: "false",
6532
- autoComplete: "off",
6533
- disabled: disabled,
6534
- class: "bio-properties-panel-input",
6535
- max: max,
6536
- min: min,
6537
- onInput: handleInput,
6538
- onFocus: onFocus,
6539
- onBlur: onBlur,
6540
- step: step,
6541
- value: localValue
6542
- })]
6543
- });
6544
- }
6545
-
6546
- /**
6547
- * @param {Object} props
6548
- * @param {Boolean} props.debounce
6549
- * @param {String} props.description
6550
- * @param {Boolean} props.disabled
6551
- * @param {Object} props.element
6552
- * @param {Function} props.getValue
6553
- * @param {String} props.id
6554
- * @param {String} props.label
6555
- * @param {String} props.max
6556
- * @param {String} props.min
6557
- * @param {Function} props.setValue
6558
- * @param {Function} props.onFocus
6559
- * @param {Function} props.onBlur
6560
- * @param {String} props.step
6561
- * @param {Function} props.validate
6562
- */
6563
- function NumberFieldEntry(props) {
6564
- const {
6565
- debounce,
6566
- description,
6567
- disabled,
6568
- element,
6569
- getValue,
6570
- id,
6571
- label,
6572
- max,
6573
- min,
6574
- setValue,
6575
- step,
6576
- onFocus,
6577
- onBlur,
6578
- validate
6579
- } = props;
6580
- const [cachedInvalidValue, setCachedInvalidValue] = useState(null);
6581
- const globalError = useError(id);
6582
- const [localError, setLocalError] = useState(null);
6583
- let value = getValue(element);
6584
- const previousValue = usePrevious(value);
6585
- useEffect(() => {
6586
- if (isFunction(validate)) {
6587
- const newValidationError = validate(value) || null;
6588
- setLocalError(newValidationError);
6589
- }
6590
- }, [value]);
6591
- const onInput = newValue => {
6592
- let newValidationError = null;
6593
- if (isFunction(validate)) {
6594
- newValidationError = validate(newValue) || null;
6595
- }
6596
- if (newValidationError) {
6597
- setCachedInvalidValue(newValue);
6598
- } else {
6599
- setValue(newValue);
6600
- }
6601
- setLocalError(newValidationError);
6602
- };
6603
- if (previousValue === value && localError) {
6604
- value = cachedInvalidValue;
6605
- }
6606
- const error = globalError || localError;
6607
- return jsxs("div", {
6608
- class: classnames('bio-properties-panel-entry', error ? 'has-error' : ''),
6609
- "data-entry-id": id,
6610
- children: [jsx(NumberField, {
6611
- debounce: debounce,
6612
- disabled: disabled,
6613
- id: id,
6614
- label: label,
6615
- onFocus: onFocus,
6616
- onBlur: onBlur,
6617
- onInput: onInput,
6618
- max: max,
6619
- min: min,
6620
- step: step,
6621
- value: value
6622
- }, element), error && jsx("div", {
6623
- class: "bio-properties-panel-error",
6624
- children: error
6625
- }), jsx(Description$1, {
6626
- forId: id,
6627
- element: element,
6628
- value: description
6629
- })]
6630
- });
6631
- }
6632
- function isEdited$4(node) {
6633
- return node && !!node.value;
6634
- }
6635
-
6636
- // helpers /////////////////
6637
-
6638
6779
  function prefixId$4(id) {
6639
6780
  return `bio-properties-panel-${id}`;
6640
6781
  }
@@ -6732,11 +6873,9 @@ function SelectEntry(props) {
6732
6873
  validate
6733
6874
  } = props;
6734
6875
  const options = getOptions(element);
6735
- const [cachedInvalidValue, setCachedInvalidValue] = useState(null);
6736
6876
  const globalError = useError(id);
6737
6877
  const [localError, setLocalError] = useState(null);
6738
6878
  let value = getValue(element);
6739
- const previousValue = usePrevious(value);
6740
6879
  useEffect(() => {
6741
6880
  if (isFunction(validate)) {
6742
6881
  const newValidationError = validate(value) || null;
@@ -6748,16 +6887,9 @@ function SelectEntry(props) {
6748
6887
  if (isFunction(validate)) {
6749
6888
  newValidationError = validate(newValue) || null;
6750
6889
  }
6751
- if (newValidationError) {
6752
- setCachedInvalidValue(newValue);
6753
- } else {
6754
- setValue(newValue);
6755
- }
6890
+ setValue(newValue, newValidationError);
6756
6891
  setLocalError(newValidationError);
6757
6892
  };
6758
- if (previousValue === value && localError) {
6759
- value = cachedInvalidValue;
6760
- }
6761
6893
  const error = globalError || localError;
6762
6894
  return jsxs("div", {
6763
6895
  class: classnames('bio-properties-panel-entry', error ? 'has-error' : ''),
@@ -6888,11 +7020,9 @@ function TextAreaEntry(props) {
6888
7020
  onBlur,
6889
7021
  autoResize
6890
7022
  } = props;
6891
- const [cachedInvalidValue, setCachedInvalidValue] = useState(null);
6892
7023
  const globalError = useError(id);
6893
7024
  const [localError, setLocalError] = useState(null);
6894
7025
  let value = getValue(element);
6895
- const previousValue = usePrevious(value);
6896
7026
  useEffect(() => {
6897
7027
  if (isFunction(validate)) {
6898
7028
  const newValidationError = validate(value) || null;
@@ -6904,16 +7034,9 @@ function TextAreaEntry(props) {
6904
7034
  if (isFunction(validate)) {
6905
7035
  newValidationError = validate(newValue) || null;
6906
7036
  }
6907
- if (newValidationError) {
6908
- setCachedInvalidValue(newValue);
6909
- } else {
6910
- setValue(newValue);
6911
- }
7037
+ setValue(newValue, newValidationError);
6912
7038
  setLocalError(newValidationError);
6913
7039
  };
6914
- if (previousValue === value && localError) {
6915
- value = cachedInvalidValue;
6916
- }
6917
7040
  const error = globalError || localError;
6918
7041
  return jsxs("div", {
6919
7042
  class: classnames('bio-properties-panel-entry', error ? 'has-error' : ''),
@@ -7028,11 +7151,9 @@ function TextfieldEntry(props) {
7028
7151
  onFocus,
7029
7152
  onBlur
7030
7153
  } = props;
7031
- const [cachedInvalidValue, setCachedInvalidValue] = useState(null);
7032
7154
  const globalError = useError(id);
7033
7155
  const [localError, setLocalError] = useState(null);
7034
7156
  let value = getValue(element);
7035
- const previousValue = usePrevious(value);
7036
7157
  useEffect(() => {
7037
7158
  if (isFunction(validate)) {
7038
7159
  const newValidationError = validate(value) || null;
@@ -7044,16 +7165,9 @@ function TextfieldEntry(props) {
7044
7165
  if (isFunction(validate)) {
7045
7166
  newValidationError = validate(newValue) || null;
7046
7167
  }
7047
- if (newValidationError) {
7048
- setCachedInvalidValue(newValue);
7049
- } else {
7050
- setValue(newValue);
7051
- }
7168
+ setValue(newValue, newValidationError);
7052
7169
  setLocalError(newValidationError);
7053
7170
  };
7054
- if (previousValue === value && localError) {
7055
- value = cachedInvalidValue;
7056
- }
7057
7171
  const error = globalError || localError;
7058
7172
  return jsxs("div", {
7059
7173
  class: classnames('bio-properties-panel-entry', error ? 'has-error' : ''),
@@ -7086,12 +7200,12 @@ function isEdited(node) {
7086
7200
  function prefixId(id) {
7087
7201
  return `bio-properties-panel-${id}`;
7088
7202
  }
7089
-
7090
- /**
7091
- * @param {string} type
7092
- * @param {boolean} [strict]
7093
- *
7094
- * @returns {any}
7203
+
7204
+ /**
7205
+ * @param {string} type
7206
+ * @param {boolean} [strict]
7207
+ *
7208
+ * @returns {any}
7095
7209
  */
7096
7210
  function getService(type, strict) {}
7097
7211
  const PropertiesPanelContext = createContext({
@@ -7138,6 +7252,7 @@ const labelsByType = {
7138
7252
  number: 'NUMBER',
7139
7253
  radio: 'RADIO',
7140
7254
  select: 'SELECT',
7255
+ spacer: 'SPACER',
7141
7256
  taglist: 'TAGLIST',
7142
7257
  text: 'TEXT VIEW',
7143
7258
  textfield: 'TEXT FIELD',
@@ -7180,8 +7295,8 @@ const PropertiesPanelHeaderProvider = {
7180
7295
  }
7181
7296
  };
7182
7297
 
7183
- /**
7184
- * Provide placeholders for empty and multiple state.
7298
+ /**
7299
+ * Provide placeholders for empty and multiple state.
7185
7300
  */
7186
7301
  const PropertiesPanelPlaceholderProvider = {
7187
7302
  getEmpty: () => {
@@ -7253,10 +7368,10 @@ function useService (type, strict) {
7253
7368
  return getService(type, strict);
7254
7369
  }
7255
7370
 
7256
- /**
7257
- * Retrieve list of variables from the form schema.
7258
- *
7259
- * @returns { string[] } list of variables used in form schema
7371
+ /**
7372
+ * Retrieve list of variables from the form schema.
7373
+ *
7374
+ * @returns { string[] } list of variables used in form schema
7260
7375
  */
7261
7376
  function useVariables() {
7262
7377
  const form = useService('formEditor');
@@ -7279,7 +7394,7 @@ function AltTextEntry(props) {
7279
7394
  component: AltText,
7280
7395
  editField: editField,
7281
7396
  field: field,
7282
- isEdited: isEdited$6
7397
+ isEdited: isEdited$5
7283
7398
  });
7284
7399
  }
7285
7400
  return entries;
@@ -7301,7 +7416,7 @@ function AltText(props) {
7301
7416
  const setValue = value => {
7302
7417
  return editField(field, path, value);
7303
7418
  };
7304
- return FeelEntry({
7419
+ return FeelTemplatingEntry({
7305
7420
  debounce,
7306
7421
  element: field,
7307
7422
  feel: 'optional',
@@ -7309,6 +7424,7 @@ function AltText(props) {
7309
7424
  id,
7310
7425
  label: 'Alternative text',
7311
7426
  setValue,
7427
+ singleLine: true,
7312
7428
  variables
7313
7429
  });
7314
7430
  }
@@ -7339,7 +7455,10 @@ function Columns(props) {
7339
7455
  const validate = value => {
7340
7456
  return formLayoutValidator.validateField(field, value ? parseInt(value) : null);
7341
7457
  };
7342
- const setValue = value => {
7458
+ const setValue = (value, error) => {
7459
+ if (error) {
7460
+ return;
7461
+ }
7343
7462
  const layout = get(field, ['layout'], {});
7344
7463
  const newValue = value ? parseInt(value) : null;
7345
7464
  editField(field, ['layout'], set$1(layout, ['columns'], newValue));
@@ -7397,7 +7516,7 @@ function DescriptionEntry(props) {
7397
7516
  component: Description,
7398
7517
  editField: editField,
7399
7518
  field: field,
7400
- isEdited: isEdited$6
7519
+ isEdited: isEdited$5
7401
7520
  });
7402
7521
  }
7403
7522
  return entries;
@@ -7547,7 +7666,10 @@ function DefaultValueNumber(props) {
7547
7666
  // Enforces decimal notation so that we do not submit defaults in exponent form
7548
7667
  return serializeToString ? Big(value).toFixed() : value;
7549
7668
  };
7550
- const setValue = value => {
7669
+ const setValue = (value, error) => {
7670
+ if (error) {
7671
+ return;
7672
+ }
7551
7673
  let newValue;
7552
7674
  if (isValidNumber(value)) {
7553
7675
  newValue = serializeToString ? value : Number(value);
@@ -7738,7 +7860,10 @@ function Id(props) {
7738
7860
  const getValue = () => {
7739
7861
  return get(field, path, '');
7740
7862
  };
7741
- const setValue = value => {
7863
+ const setValue = (value, error) => {
7864
+ if (error) {
7865
+ return;
7866
+ }
7742
7867
  return editField(field, path, value);
7743
7868
  };
7744
7869
  const validate = value => {
@@ -7818,7 +7943,10 @@ function Key$1(props) {
7818
7943
  const getValue = () => {
7819
7944
  return get(field, path, '');
7820
7945
  };
7821
- const setValue = value => {
7946
+ const setValue = (value, error) => {
7947
+ if (error) {
7948
+ return;
7949
+ }
7822
7950
  return editField(field, path, value);
7823
7951
  };
7824
7952
  const validate = value => {
@@ -7863,7 +7991,7 @@ function LabelEntry(props) {
7863
7991
  component: DateLabel,
7864
7992
  editField,
7865
7993
  field,
7866
- isEdited: isEdited$6
7994
+ isEdited: isEdited$5
7867
7995
  });
7868
7996
  }
7869
7997
  if (subtype === DATETIME_SUBTYPES.TIME || subtype === DATETIME_SUBTYPES.DATETIME) {
@@ -7872,7 +8000,7 @@ function LabelEntry(props) {
7872
8000
  component: TimeLabel,
7873
8001
  editField,
7874
8002
  field,
7875
- isEdited: isEdited$6
8003
+ isEdited: isEdited$5
7876
8004
  });
7877
8005
  }
7878
8006
  } else if (INPUTS.includes(type) || type === 'button') {
@@ -7881,7 +8009,7 @@ function LabelEntry(props) {
7881
8009
  component: Label$1,
7882
8010
  editField,
7883
8011
  field,
7884
- isEdited: isEdited$6
8012
+ isEdited: isEdited$5
7885
8013
  });
7886
8014
  }
7887
8015
  return entries;
@@ -7986,7 +8114,7 @@ function SourceEntry(props) {
7986
8114
  component: Source,
7987
8115
  editField: editField,
7988
8116
  field: field,
7989
- isEdited: isEdited$6
8117
+ isEdited: isEdited$5
7990
8118
  });
7991
8119
  }
7992
8120
  return entries;
@@ -8008,7 +8136,7 @@ function Source(props) {
8008
8136
  const setValue = value => {
8009
8137
  return editField(field, path, value);
8010
8138
  };
8011
- return FeelEntry({
8139
+ return FeelTemplatingEntry({
8012
8140
  debounce,
8013
8141
  description: 'Expression or static value (link/data URI)',
8014
8142
  element: field,
@@ -8017,6 +8145,7 @@ function Source(props) {
8017
8145
  id,
8018
8146
  label: 'Image source',
8019
8147
  setValue,
8148
+ singleLine: true,
8020
8149
  variables
8021
8150
  });
8022
8151
  }
@@ -8041,7 +8170,7 @@ function TextEntry(props) {
8041
8170
  component: Text,
8042
8171
  editField: editField,
8043
8172
  field: field,
8044
- isEdited: isEdited$6
8173
+ isEdited: isEdited$5
8045
8174
  }];
8046
8175
 
8047
8176
  // todo: skipped to make the release without too much risk
@@ -8072,7 +8201,7 @@ function Text(props) {
8072
8201
  return get(field, path, '');
8073
8202
  };
8074
8203
  const setValue = value => {
8075
- return editField(field, path, value);
8204
+ return editField(field, path, value || '');
8076
8205
  };
8077
8206
  const description = useMemo(() => jsxs(Fragment$1, {
8078
8207
  children: ["Supports markdown and templating. ", jsx("a", {
@@ -8094,6 +8223,57 @@ function Text(props) {
8094
8223
  });
8095
8224
  }
8096
8225
 
8226
+ function SpacerEntry(props) {
8227
+ const {
8228
+ editField,
8229
+ field,
8230
+ id
8231
+ } = props;
8232
+ const {
8233
+ type
8234
+ } = field;
8235
+ if (type !== 'spacer') {
8236
+ return [];
8237
+ }
8238
+ const entries = [];
8239
+ entries.push({
8240
+ id: id + '-height',
8241
+ component: SpacerHeight,
8242
+ isEdited: isEdited$6,
8243
+ editField,
8244
+ field
8245
+ });
8246
+ return entries;
8247
+ }
8248
+ function SpacerHeight(props) {
8249
+ const {
8250
+ editField,
8251
+ field,
8252
+ id
8253
+ } = props;
8254
+ const debounce = useService('debounce');
8255
+ const getValue = e => get(field, ['height']);
8256
+ const setValue = (value, error) => {
8257
+ if (error) {
8258
+ return;
8259
+ }
8260
+ editField(field, ['height'], value);
8261
+ };
8262
+ return NumberFieldEntry({
8263
+ debounce,
8264
+ label: 'Height',
8265
+ element: field,
8266
+ id,
8267
+ getValue,
8268
+ setValue,
8269
+ validate: value => {
8270
+ if (value === undefined || value === null) return;
8271
+ if (value < 1) return 'Should be greater than zero.';
8272
+ if (!Number.isInteger(value)) return 'Should be an integer.';
8273
+ }
8274
+ });
8275
+ }
8276
+
8097
8277
  function NumberEntries(props) {
8098
8278
  const {
8099
8279
  editField,
@@ -8110,7 +8290,7 @@ function NumberEntries(props) {
8110
8290
  entries.push({
8111
8291
  id: id + '-decimalDigits',
8112
8292
  component: NumberDecimalDigits,
8113
- isEdited: isEdited$4,
8293
+ isEdited: isEdited$6,
8114
8294
  editField,
8115
8295
  field
8116
8296
  });
@@ -8131,7 +8311,12 @@ function NumberDecimalDigits(props) {
8131
8311
  } = props;
8132
8312
  const debounce = useService('debounce');
8133
8313
  const getValue = e => get(field, ['decimalDigits']);
8134
- const setValue = value => editField(field, ['decimalDigits'], value);
8314
+ const setValue = (value, error) => {
8315
+ if (error) {
8316
+ return;
8317
+ }
8318
+ editField(field, ['decimalDigits'], value);
8319
+ };
8135
8320
  return NumberFieldEntry({
8136
8321
  debounce,
8137
8322
  label: 'Decimal digits',
@@ -8167,7 +8352,12 @@ function NumberArrowStep(props) {
8167
8352
  const trimmed = value.replace(/^0+/g, '');
8168
8353
  return (trimmed.startsWith('.') ? '0' : '') + trimmed;
8169
8354
  };
8170
- const setValue = value => editField(field, ['increment'], clearLeadingZeroes(value));
8355
+ const setValue = (value, error) => {
8356
+ if (error) {
8357
+ return;
8358
+ }
8359
+ editField(field, ['increment'], clearLeadingZeroes(value));
8360
+ };
8171
8361
  const decimalDigitsSet = decimalDigits || decimalDigits === 0;
8172
8362
  return TextfieldEntry({
8173
8363
  debounce,
@@ -8576,7 +8766,10 @@ function Label(props) {
8576
8766
  validateFactory
8577
8767
  } = props;
8578
8768
  const debounce = useService('debounce');
8579
- const setValue = value => {
8769
+ const setValue = (value, error) => {
8770
+ if (error) {
8771
+ return;
8772
+ }
8580
8773
  const values = get(field, ['values']);
8581
8774
  return editField(field, 'values', set$1(values, [index, 'label'], value));
8582
8775
  };
@@ -8602,7 +8795,10 @@ function Value$1(props) {
8602
8795
  validateFactory
8603
8796
  } = props;
8604
8797
  const debounce = useService('debounce');
8605
- const setValue = value => {
8798
+ const setValue = (value, error) => {
8799
+ if (error) {
8800
+ return;
8801
+ }
8606
8802
  const values = get(field, ['values']);
8607
8803
  return editField(field, 'values', set$1(values, [index, 'value'], value));
8608
8804
  };
@@ -8656,7 +8852,10 @@ function Key(props) {
8656
8852
  validateFactory
8657
8853
  } = props;
8658
8854
  const debounce = useService('debounce');
8659
- const setValue = value => {
8855
+ const setValue = (value, error) => {
8856
+ if (error) {
8857
+ return;
8858
+ }
8660
8859
  const properties = get(field, ['properties']);
8661
8860
  const key = Object.keys(properties)[index];
8662
8861
  return editField(field, 'properties', updateKey(properties, key, value));
@@ -8706,14 +8905,14 @@ function Value(props) {
8706
8905
 
8707
8906
  // helpers //////////
8708
8907
 
8709
- /**
8710
- * Returns copy of object with updated value.
8711
- *
8712
- * @param {Object} properties
8713
- * @param {string} key
8714
- * @param {string} value
8715
- *
8716
- * @returns {Object}
8908
+ /**
8909
+ * Returns copy of object with updated value.
8910
+ *
8911
+ * @param {Object} properties
8912
+ * @param {string} key
8913
+ * @param {string} value
8914
+ *
8915
+ * @returns {Object}
8717
8916
  */
8718
8917
  function updateValue(properties, key, value) {
8719
8918
  return {
@@ -8722,14 +8921,14 @@ function updateValue(properties, key, value) {
8722
8921
  };
8723
8922
  }
8724
8923
 
8725
- /**
8726
- * Returns copy of object with updated key.
8727
- *
8728
- * @param {Object} properties
8729
- * @param {string} oldKey
8730
- * @param {string} newKey
8731
- *
8732
- * @returns {Object}
8924
+ /**
8925
+ * Returns copy of object with updated key.
8926
+ *
8927
+ * @param {Object} properties
8928
+ * @param {string} oldKey
8929
+ * @param {string} newKey
8930
+ *
8931
+ * @returns {Object}
8733
8932
  */
8734
8933
  function updateKey(properties, oldKey, newKey) {
8735
8934
  return Object.entries(properties).reduce((newProperties, entry) => {
@@ -8741,6 +8940,34 @@ function updateKey(properties, oldKey, newKey) {
8741
8940
  }, {});
8742
8941
  }
8743
8942
 
8943
+ function AutoFocusSelectEntry(props) {
8944
+ const {
8945
+ autoFocusEntry,
8946
+ element,
8947
+ getValue
8948
+ } = props;
8949
+ const value = getValue(element);
8950
+ const prevValue = usePrevious(value);
8951
+ const eventBus = useService('eventBus');
8952
+
8953
+ // auto focus specifc other entry when selected value changed
8954
+ useEffect(() => {
8955
+ if (autoFocusEntry && prevValue && value !== prevValue) {
8956
+ // @Note(pinussilvestrus): There is an issue in the properties
8957
+ // panel so we have to wait a bit before showing the entry.
8958
+ // Cf. https://github.com/camunda/linting/blob/4f5328e2722f73ae60ae584c5f576eaec3999cb2/lib/modeler/Linting.js#L37
8959
+ setTimeout(() => {
8960
+ eventBus.fire('propertiesPanel.showEntry', {
8961
+ id: autoFocusEntry
8962
+ });
8963
+ });
8964
+ }
8965
+ }, [value, autoFocusEntry, prevValue, eventBus]);
8966
+ return jsx(SelectEntry, {
8967
+ ...props
8968
+ });
8969
+ }
8970
+
8744
8971
  function ValuesSourceSelectEntry(props) {
8745
8972
  const {
8746
8973
  editField,
@@ -8779,7 +9006,8 @@ function ValuesSourceSelect(props) {
8779
9006
  value: valueSource
8780
9007
  }));
8781
9008
  };
8782
- return SelectEntry({
9009
+ return AutoFocusSelectEntry({
9010
+ autoFocusEntry: getAutoFocusEntryId(field),
8783
9011
  label: 'Type',
8784
9012
  element: field,
8785
9013
  getOptions: getValuesSourceOptions,
@@ -8789,6 +9017,20 @@ function ValuesSourceSelect(props) {
8789
9017
  });
8790
9018
  }
8791
9019
 
9020
+ // helpers //////////
9021
+
9022
+ function getAutoFocusEntryId(field) {
9023
+ const valuesSource = getValuesSource(field);
9024
+ if (valuesSource === VALUES_SOURCES.EXPRESSION) {
9025
+ return `${field.id}-valuesExpression-expression`;
9026
+ } else if (valuesSource === VALUES_SOURCES.INPUT) {
9027
+ return `${field.id}-dynamicValues-key`;
9028
+ } else if (valuesSource === VALUES_SOURCES.STATIC) {
9029
+ return `${field.id}-staticValues-0-label`;
9030
+ }
9031
+ return null;
9032
+ }
9033
+
8792
9034
  function InputKeyValuesSourceEntry(props) {
8793
9035
  const {
8794
9036
  editField,
@@ -8824,7 +9066,12 @@ function InputValuesKey(props) {
8824
9066
  const debounce = useService('debounce');
8825
9067
  const path = VALUES_SOURCES_PATHS[VALUES_SOURCES.INPUT];
8826
9068
  const getValue = () => get(field, path, '');
8827
- const setValue = value => editField(field, path, value || '');
9069
+ const setValue = (value, error) => {
9070
+ if (error) {
9071
+ return;
9072
+ }
9073
+ editField(field, path, value || '');
9074
+ };
8828
9075
  const validate = value => {
8829
9076
  if (isUndefined(value) || !value.length) {
8830
9077
  return 'Must not be empty.';
@@ -8945,7 +9192,7 @@ function AdornerEntry(props) {
8945
9192
  entries.push({
8946
9193
  id: 'prefix-adorner',
8947
9194
  component: PrefixAdorner,
8948
- isEdited: isEdited,
9195
+ isEdited: isEdited$5,
8949
9196
  editField,
8950
9197
  field,
8951
9198
  onChange,
@@ -8954,7 +9201,7 @@ function AdornerEntry(props) {
8954
9201
  entries.push({
8955
9202
  id: 'suffix-adorner',
8956
9203
  component: SuffixAdorner,
8957
- isEdited: isEdited,
9204
+ isEdited: isEdited$5,
8958
9205
  editField,
8959
9206
  field,
8960
9207
  onChange,
@@ -8971,13 +9218,19 @@ function PrefixAdorner(props) {
8971
9218
  getValue
8972
9219
  } = props;
8973
9220
  const debounce = useService('debounce');
8974
- return TextfieldEntry({
9221
+ const variables = useVariables().map(name => ({
9222
+ name
9223
+ }));
9224
+ return FeelTemplatingEntry({
8975
9225
  debounce,
8976
9226
  element: field,
9227
+ feel: 'optional',
8977
9228
  getValue: getValue('prefixAdorner'),
8978
9229
  id,
8979
9230
  label: 'Prefix',
8980
- setValue: onChange('prefixAdorner')
9231
+ setValue: onChange('prefixAdorner'),
9232
+ singleLine: true,
9233
+ variables
8981
9234
  });
8982
9235
  }
8983
9236
  function SuffixAdorner(props) {
@@ -8988,13 +9241,18 @@ function SuffixAdorner(props) {
8988
9241
  getValue
8989
9242
  } = props;
8990
9243
  const debounce = useService('debounce');
8991
- return TextfieldEntry({
9244
+ const variables = useVariables().map(name => ({
9245
+ name
9246
+ }));
9247
+ return FeelTemplatingEntry({
8992
9248
  debounce,
8993
9249
  element: field,
8994
9250
  getValue: getValue('suffixAdorner'),
8995
9251
  id,
8996
9252
  label: 'Suffix',
8997
- setValue: onChange('suffixAdorner')
9253
+ setValue: onChange('suffixAdorner'),
9254
+ singleLine: true,
9255
+ variables
8998
9256
  });
8999
9257
  }
9000
9258
 
@@ -9013,7 +9271,7 @@ function ReadonlyEntry(props) {
9013
9271
  component: Readonly,
9014
9272
  editField: editField,
9015
9273
  field: field,
9016
- isEdited: isEdited$6
9274
+ isEdited: isEdited$5
9017
9275
  });
9018
9276
  }
9019
9277
  return entries;
@@ -9057,7 +9315,7 @@ function ConditionEntry(props) {
9057
9315
  component: Condition,
9058
9316
  editField: editField,
9059
9317
  field: field,
9060
- isEdited: isEdited$6
9318
+ isEdited: isEdited$5
9061
9319
  }];
9062
9320
  }
9063
9321
  function Condition(props) {
@@ -9095,6 +9353,55 @@ function Condition(props) {
9095
9353
  });
9096
9354
  }
9097
9355
 
9356
+ function ValuesExpressionEntry(props) {
9357
+ const {
9358
+ editField,
9359
+ field,
9360
+ id
9361
+ } = props;
9362
+ return [{
9363
+ id: id + '-expression',
9364
+ component: ValuesExpression,
9365
+ label: 'Values expression',
9366
+ isEdited: isEdited$5,
9367
+ editField,
9368
+ field
9369
+ }];
9370
+ }
9371
+ function ValuesExpression(props) {
9372
+ const {
9373
+ editField,
9374
+ field,
9375
+ id
9376
+ } = props;
9377
+ const debounce = useService('debounce');
9378
+ const variables = useVariables().map(name => ({
9379
+ name
9380
+ }));
9381
+ const path = VALUES_SOURCES_PATHS[VALUES_SOURCES.EXPRESSION];
9382
+ const schema = '[\n {\n "label": "dollar",\n "value": "$"\n }\n]';
9383
+ const description = jsxs("div", {
9384
+ children: ["Define an expression to populate the options from.", jsx("br", {}), jsx("br", {}), "The expression may result in an array of simple values or alternatively follow this schema:", jsx("pre", {
9385
+ children: jsx("code", {
9386
+ children: schema
9387
+ })
9388
+ })]
9389
+ });
9390
+ const getValue = () => get(field, path, '');
9391
+ const setValue = value => editField(field, path, value || '');
9392
+ return FeelEntry({
9393
+ debounce,
9394
+ description,
9395
+ element: field,
9396
+ feel: 'required',
9397
+ getValue,
9398
+ id,
9399
+ label: 'Options expression',
9400
+ setValue,
9401
+ variables
9402
+ });
9403
+ }
9404
+
9098
9405
  function GeneralGroup(field, editField, getService) {
9099
9406
  const entries = [...IdEntry({
9100
9407
  field,
@@ -9121,6 +9428,9 @@ function GeneralGroup(field, editField, getService) {
9121
9428
  field,
9122
9429
  editField,
9123
9430
  getService
9431
+ }), ...SpacerEntry({
9432
+ field,
9433
+ editField
9124
9434
  }), ...NumberEntries({
9125
9435
  field,
9126
9436
  editField
@@ -9239,14 +9549,14 @@ function ValidationGroup(field, editField) {
9239
9549
  component: MinLength,
9240
9550
  getValue,
9241
9551
  field,
9242
- isEdited: isEdited$4,
9552
+ isEdited: isEdited$5,
9243
9553
  onChange
9244
9554
  }, {
9245
9555
  id: 'maxLength',
9246
9556
  component: MaxLength,
9247
9557
  getValue,
9248
9558
  field,
9249
- isEdited: isEdited$4,
9559
+ isEdited: isEdited$5,
9250
9560
  onChange
9251
9561
  });
9252
9562
  }
@@ -9266,14 +9576,14 @@ function ValidationGroup(field, editField) {
9266
9576
  component: Min,
9267
9577
  getValue,
9268
9578
  field,
9269
- isEdited: isEdited$4,
9579
+ isEdited: isEdited$5,
9270
9580
  onChange
9271
9581
  }, {
9272
9582
  id: 'max',
9273
9583
  component: Max,
9274
9584
  getValue,
9275
9585
  field,
9276
- isEdited: isEdited$4,
9586
+ isEdited: isEdited$5,
9277
9587
  onChange
9278
9588
  });
9279
9589
  }
@@ -9306,14 +9616,19 @@ function MinLength(props) {
9306
9616
  onChange
9307
9617
  } = props;
9308
9618
  const debounce = useService('debounce');
9309
- return NumberFieldEntry({
9619
+ const variables = useVariables().map(name => ({
9620
+ name
9621
+ }));
9622
+ return FeelNumberEntry({
9310
9623
  debounce,
9311
9624
  element: field,
9625
+ feel: 'optional',
9312
9626
  getValue: getValue('minLength'),
9313
9627
  id,
9314
9628
  label: 'Minimum length',
9315
9629
  min: 0,
9316
- setValue: onChange('minLength')
9630
+ setValue: onChange('minLength'),
9631
+ variables
9317
9632
  });
9318
9633
  }
9319
9634
  function MaxLength(props) {
@@ -9324,14 +9639,19 @@ function MaxLength(props) {
9324
9639
  onChange
9325
9640
  } = props;
9326
9641
  const debounce = useService('debounce');
9327
- return NumberFieldEntry({
9642
+ const variables = useVariables().map(name => ({
9643
+ name
9644
+ }));
9645
+ return FeelNumberEntry({
9328
9646
  debounce,
9329
9647
  element: field,
9648
+ feel: 'optional',
9330
9649
  getValue: getValue('maxLength'),
9331
9650
  id,
9332
9651
  label: 'Maximum length',
9333
9652
  min: 0,
9334
- setValue: onChange('maxLength')
9653
+ setValue: onChange('maxLength'),
9654
+ variables
9335
9655
  });
9336
9656
  }
9337
9657
  function Pattern(props) {
@@ -9359,14 +9679,19 @@ function Min(props) {
9359
9679
  onChange
9360
9680
  } = props;
9361
9681
  const debounce = useService('debounce');
9362
- return NumberFieldEntry({
9682
+ const variables = useVariables().map(name => ({
9683
+ name
9684
+ }));
9685
+ return FeelNumberEntry({
9363
9686
  debounce,
9364
9687
  element: field,
9688
+ feel: 'optional',
9365
9689
  id,
9366
9690
  label: 'Minimum',
9367
9691
  step: 'any',
9368
9692
  getValue: getValue('min'),
9369
- setValue: onChange('min')
9693
+ setValue: onChange('min'),
9694
+ variables
9370
9695
  });
9371
9696
  }
9372
9697
  function Max(props) {
@@ -9377,14 +9702,19 @@ function Max(props) {
9377
9702
  onChange
9378
9703
  } = props;
9379
9704
  const debounce = useService('debounce');
9380
- return NumberFieldEntry({
9705
+ const variables = useVariables().map(name => ({
9706
+ name
9707
+ }));
9708
+ return FeelNumberEntry({
9381
9709
  debounce,
9382
9710
  element: field,
9711
+ feel: 'optional',
9383
9712
  id,
9384
9713
  label: 'Maximum',
9385
9714
  step: 'any',
9386
9715
  getValue: getValue('max'),
9387
- setValue: onChange('max')
9716
+ setValue: onChange('max'),
9717
+ variables
9388
9718
  });
9389
9719
  }
9390
9720
  function ValidationType(props) {
@@ -9423,8 +9753,8 @@ function ValuesGroups(field, editField) {
9423
9753
  };
9424
9754
  const valuesSourceId = `${fieldId}-valuesSource`;
9425
9755
 
9426
- /**
9427
- * @type {Array<Group|ListGroup>}
9756
+ /**
9757
+ * @type {Array<Group|ListGroup>}
9428
9758
  */
9429
9759
  const groups = [{
9430
9760
  id: valuesSourceId,
@@ -9458,6 +9788,17 @@ function ValuesGroups(field, editField) {
9458
9788
  id: staticValuesId
9459
9789
  })
9460
9790
  });
9791
+ } else if (valuesSource === VALUES_SOURCES.EXPRESSION) {
9792
+ const valuesExpressionId = `${fieldId}-valuesExpression`;
9793
+ groups.push({
9794
+ id: valuesExpressionId,
9795
+ label: 'Options expression',
9796
+ component: Group,
9797
+ entries: ValuesExpressionEntry({
9798
+ ...context,
9799
+ id: valuesExpressionId
9800
+ })
9801
+ });
9461
9802
  }
9462
9803
  return groups;
9463
9804
  }
@@ -9526,13 +9867,13 @@ function CustomValuesGroup(field, editField) {
9526
9867
 
9527
9868
  // helpers //////////
9528
9869
 
9529
- /**
9530
- * Returns copy of object without key.
9531
- *
9532
- * @param {Object} properties
9533
- * @param {string} oldKey
9534
- *
9535
- * @returns {Object}
9870
+ /**
9871
+ * Returns copy of object without key.
9872
+ *
9873
+ * @param {Object} properties
9874
+ * @param {string} oldKey
9875
+ *
9876
+ * @returns {Object}
9536
9877
  */
9537
9878
  function removeKey(properties, oldKey) {
9538
9879
  return Object.entries(properties).reduce((newProperties, entry) => {
@@ -9635,9 +9976,9 @@ function FormPropertiesPanel(props) {
9635
9976
  });
9636
9977
  }, [eventBus, formEditor, selectionModule]);
9637
9978
  useLayoutEffect(() => {
9638
- /**
9639
- * TODO(pinussilvestrus): update with actual updated element,
9640
- * once we have a proper updater/change support
9979
+ /**
9980
+ * TODO(pinussilvestrus): update with actual updated element,
9981
+ * once we have a proper updater/change support
9641
9982
  */
9642
9983
  eventBus.on('changed', refresh);
9643
9984
  eventBus.on('import.done', refresh);
@@ -9689,10 +10030,10 @@ class PropertiesPanelRenderer {
9689
10030
  });
9690
10031
  }
9691
10032
 
9692
- /**
9693
- * Attach the properties panel to a parent node.
9694
- *
9695
- * @param {HTMLElement} container
10033
+ /**
10034
+ * Attach the properties panel to a parent node.
10035
+ *
10036
+ * @param {HTMLElement} container
9696
10037
  */
9697
10038
  attachTo(container) {
9698
10039
  if (!container) {
@@ -9712,8 +10053,8 @@ class PropertiesPanelRenderer {
9712
10053
  this._eventBus.fire('propertiesPanel.attach');
9713
10054
  }
9714
10055
 
9715
- /**
9716
- * Detach the properties panel from its parent node.
10056
+ /**
10057
+ * Detach the properties panel from its parent node.
9717
10058
  */
9718
10059
  detach() {
9719
10060
  const parentNode = this._container.parentNode;
@@ -9743,10 +10084,10 @@ var PropertiesPanelModule = {
9743
10084
  propertiesPanel: ['type', PropertiesPanelRenderer]
9744
10085
  };
9745
10086
 
9746
- /**
9747
- * Manages the rendering of visual plugins.
9748
- * @constructor
9749
- * @param {Object} eventBus - Event bus for the application.
10087
+ /**
10088
+ * Manages the rendering of visual plugins.
10089
+ * @constructor
10090
+ * @param {Object} eventBus - Event bus for the application.
9750
10091
  */
9751
10092
  class RenderInjector extends SectionModuleBase {
9752
10093
  constructor(eventBus) {
@@ -9755,10 +10096,10 @@ class RenderInjector extends SectionModuleBase {
9755
10096
  this.registeredRenderers = [];
9756
10097
  }
9757
10098
 
9758
- /**
9759
- * Inject a new renderer into the injector.
9760
- * @param {string} identifier - Identifier for the renderer.
9761
- * @param {Function} Renderer - The renderer function.
10099
+ /**
10100
+ * Inject a new renderer into the injector.
10101
+ * @param {string} identifier - Identifier for the renderer.
10102
+ * @param {Function} Renderer - The renderer function.
9762
10103
  */
9763
10104
  attachRenderer(identifier, Renderer) {
9764
10105
  this.registeredRenderers = [...this.registeredRenderers, {
@@ -9767,17 +10108,17 @@ class RenderInjector extends SectionModuleBase {
9767
10108
  }];
9768
10109
  }
9769
10110
 
9770
- /**
9771
- * Detach a renderer from the by key injector.
9772
- * @param {string} identifier - Identifier for the renderer.
10111
+ /**
10112
+ * Detach a renderer from the by key injector.
10113
+ * @param {string} identifier - Identifier for the renderer.
9773
10114
  */
9774
10115
  detachRenderer(identifier) {
9775
10116
  this.registeredRenderers = this.registeredRenderers.filter(r => r.identifier !== identifier);
9776
10117
  }
9777
10118
 
9778
- /**
9779
- * Returns the registered renderers.
9780
- * @returns {Array} Array of registered renderers.
10119
+ /**
10120
+ * Returns the registered renderers.
10121
+ * @returns {Array} Array of registered renderers.
9781
10122
  */
9782
10123
  fetchRenderers() {
9783
10124
  return this.registeredRenderers;
@@ -9811,48 +10152,48 @@ var ExpressionLanguageModule = {
9811
10152
 
9812
10153
  const ids = new Ids([32, 36, 1]);
9813
10154
 
9814
- /**
9815
- * @typedef { import('./types').Injector } Injector
9816
- * @typedef { import('./types').Module } Module
9817
- * @typedef { import('./types').Schema } Schema
9818
- *
9819
- * @typedef { import('./types').FormEditorOptions } FormEditorOptions
9820
- * @typedef { import('./types').FormEditorProperties } FormEditorProperties
9821
- *
9822
- * @typedef { {
9823
- * properties: FormEditorProperties,
9824
- * schema: Schema
9825
- * } } State
9826
- *
9827
- * @typedef { (type:string, priority:number, handler:Function) => void } OnEventWithPriority
9828
- * @typedef { (type:string, handler:Function) => void } OnEventWithOutPriority
9829
- * @typedef { OnEventWithPriority & OnEventWithOutPriority } OnEventType
10155
+ /**
10156
+ * @typedef { import('./types').Injector } Injector
10157
+ * @typedef { import('./types').Module } Module
10158
+ * @typedef { import('./types').Schema } Schema
10159
+ *
10160
+ * @typedef { import('./types').FormEditorOptions } FormEditorOptions
10161
+ * @typedef { import('./types').FormEditorProperties } FormEditorProperties
10162
+ *
10163
+ * @typedef { {
10164
+ * properties: FormEditorProperties,
10165
+ * schema: Schema
10166
+ * } } State
10167
+ *
10168
+ * @typedef { (type:string, priority:number, handler:Function) => void } OnEventWithPriority
10169
+ * @typedef { (type:string, handler:Function) => void } OnEventWithOutPriority
10170
+ * @typedef { OnEventWithPriority & OnEventWithOutPriority } OnEventType
9830
10171
  */
9831
10172
 
9832
- /**
9833
- * The form editor.
10173
+ /**
10174
+ * The form editor.
9834
10175
  */
9835
10176
  class FormEditor {
9836
- /**
9837
- * @constructor
9838
- * @param {FormEditorOptions} options
10177
+ /**
10178
+ * @constructor
10179
+ * @param {FormEditorOptions} options
9839
10180
  */
9840
10181
  constructor(options = {}) {
9841
- /**
9842
- * @public
9843
- * @type {OnEventType}
10182
+ /**
10183
+ * @public
10184
+ * @type {OnEventType}
9844
10185
  */
9845
10186
  this.on = this._onEvent;
9846
10187
 
9847
- /**
9848
- * @public
9849
- * @type {String}
10188
+ /**
10189
+ * @public
10190
+ * @type {String}
9850
10191
  */
9851
10192
  this._id = ids.next();
9852
10193
 
9853
- /**
9854
- * @private
9855
- * @type {Element}
10194
+ /**
10195
+ * @private
10196
+ * @type {Element}
9856
10197
  */
9857
10198
  this._container = createFormContainer();
9858
10199
  this._container.setAttribute('input-handle-modified-keys', 'z,y');
@@ -9863,15 +10204,15 @@ class FormEditor {
9863
10204
  properties = {}
9864
10205
  } = options;
9865
10206
 
9866
- /**
9867
- * @private
9868
- * @type {any}
10207
+ /**
10208
+ * @private
10209
+ * @type {any}
9869
10210
  */
9870
10211
  this.exporter = exporter;
9871
10212
 
9872
- /**
9873
- * @private
9874
- * @type {State}
10213
+ /**
10214
+ * @private
10215
+ * @type {State}
9875
10216
  */
9876
10217
  this._state = {
9877
10218
  properties,
@@ -9900,10 +10241,10 @@ class FormEditor {
9900
10241
  this._detach(false);
9901
10242
  }
9902
10243
 
9903
- /**
9904
- * @param {Schema} schema
9905
- *
9906
- * @return {Promise<{ warnings: Array<any> }>}
10244
+ /**
10245
+ * @param {Schema} schema
10246
+ *
10247
+ * @return {Promise<{ warnings: Array<any> }>}
9907
10248
  */
9908
10249
  importSchema(schema) {
9909
10250
  return new Promise((resolve, reject) => {
@@ -9932,15 +10273,15 @@ class FormEditor {
9932
10273
  });
9933
10274
  }
9934
10275
 
9935
- /**
9936
- * @returns {Schema}
10276
+ /**
10277
+ * @returns {Schema}
9937
10278
  */
9938
10279
  saveSchema() {
9939
10280
  return this.getSchema();
9940
10281
  }
9941
10282
 
9942
- /**
9943
- * @returns {Schema}
10283
+ /**
10284
+ * @returns {Schema}
9944
10285
  */
9945
10286
  getSchema() {
9946
10287
  const {
@@ -9949,8 +10290,8 @@ class FormEditor {
9949
10290
  return exportSchema(schema, this.exporter, schemaVersion);
9950
10291
  }
9951
10292
 
9952
- /**
9953
- * @param {Element|string} parentNode
10293
+ /**
10294
+ * @param {Element|string} parentNode
9954
10295
  */
9955
10296
  attachTo(parentNode) {
9956
10297
  if (!parentNode) {
@@ -9968,10 +10309,10 @@ class FormEditor {
9968
10309
  this._detach();
9969
10310
  }
9970
10311
 
9971
- /**
9972
- * @internal
9973
- *
9974
- * @param {boolean} [emit]
10312
+ /**
10313
+ * @internal
10314
+ *
10315
+ * @param {boolean} [emit]
9975
10316
  */
9976
10317
  _detach(emit = true) {
9977
10318
  const container = this._container,
@@ -9985,9 +10326,9 @@ class FormEditor {
9985
10326
  parentNode.removeChild(container);
9986
10327
  }
9987
10328
 
9988
- /**
9989
- * @param {any} property
9990
- * @param {any} value
10329
+ /**
10330
+ * @param {any} property
10331
+ * @param {any} value
9991
10332
  */
9992
10333
  setProperty(property, value) {
9993
10334
  const properties = set$1(this._getState().properties, [property], value);
@@ -9996,21 +10337,21 @@ class FormEditor {
9996
10337
  });
9997
10338
  }
9998
10339
 
9999
- /**
10000
- * @param {string} type
10001
- * @param {Function} handler
10340
+ /**
10341
+ * @param {string} type
10342
+ * @param {Function} handler
10002
10343
  */
10003
10344
  off(type, handler) {
10004
10345
  this.get('eventBus').off(type, handler);
10005
10346
  }
10006
10347
 
10007
- /**
10008
- * @internal
10009
- *
10010
- * @param {FormEditorOptions} options
10011
- * @param {Element} container
10012
- *
10013
- * @returns {Injector}
10348
+ /**
10349
+ * @internal
10350
+ *
10351
+ * @param {FormEditorOptions} options
10352
+ * @param {Element} container
10353
+ *
10354
+ * @returns {Injector}
10014
10355
  */
10015
10356
  _createInjector(options, container) {
10016
10357
  const {
@@ -10032,22 +10373,22 @@ class FormEditor {
10032
10373
  }, core, ...modules, ...additionalModules]);
10033
10374
  }
10034
10375
 
10035
- /**
10036
- * @internal
10376
+ /**
10377
+ * @internal
10037
10378
  */
10038
10379
  _emit(type, data) {
10039
10380
  this.get('eventBus').fire(type, data);
10040
10381
  }
10041
10382
 
10042
- /**
10043
- * @internal
10383
+ /**
10384
+ * @internal
10044
10385
  */
10045
10386
  _getState() {
10046
10387
  return this._state;
10047
10388
  }
10048
10389
 
10049
- /**
10050
- * @internal
10390
+ /**
10391
+ * @internal
10051
10392
  */
10052
10393
  _setState(state) {
10053
10394
  this._state = {
@@ -10057,15 +10398,15 @@ class FormEditor {
10057
10398
  this._emit('changed', this._getState());
10058
10399
  }
10059
10400
 
10060
- /**
10061
- * @internal
10401
+ /**
10402
+ * @internal
10062
10403
  */
10063
10404
  _getModules() {
10064
10405
  return [ModelingModule, EditorActionsModule, DraggingModule, KeyboardModule, SelectionModule, PaletteModule, ExpressionLanguageModule, MarkdownModule, PropertiesPanelModule, RenderInjectionModule];
10065
10406
  }
10066
10407
 
10067
- /**
10068
- * @internal
10408
+ /**
10409
+ * @internal
10069
10410
  */
10070
10411
  _onEvent(type, priority, handler) {
10071
10412
  this.get('eventBus').on(type, priority, handler);