@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.cjs CHANGED
@@ -15,6 +15,25 @@ var feelers = require('feelers');
15
15
  var FeelEditor = require('@bpmn-io/feel-editor');
16
16
  var Big = require('big.js');
17
17
 
18
+ function _interopNamespaceDefault(e) {
19
+ var n = Object.create(null);
20
+ if (e) {
21
+ Object.keys(e).forEach(function (k) {
22
+ if (k !== 'default') {
23
+ var d = Object.getOwnPropertyDescriptor(e, k);
24
+ Object.defineProperty(n, k, d.get ? d : {
25
+ enumerable: true,
26
+ get: function () { return e[k]; }
27
+ });
28
+ }
29
+ });
30
+ }
31
+ n.default = e;
32
+ return Object.freeze(n);
33
+ }
34
+
35
+ var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
36
+
18
37
  var FN_REF = '__fn';
19
38
  var DEFAULT_PRIORITY$2 = 1000;
20
39
  var slice = Array.prototype.slice;
@@ -515,10 +534,10 @@ function invokeFunction(fn, args) {
515
534
  return fn.apply(null, args);
516
535
  }
517
536
 
518
- /**
519
- * A factory to create a configurable debouncer.
520
- *
521
- * @param {number|boolean} [config=true]
537
+ /**
538
+ * A factory to create a configurable debouncer.
539
+ *
540
+ * @param {number|boolean} [config=true]
522
541
  */
523
542
  function DebounceFactory(config = true) {
524
543
  const timeout = typeof config === 'number' ? config : config ? 300 : 0;
@@ -531,11 +550,11 @@ function DebounceFactory(config = true) {
531
550
  DebounceFactory.$inject = ['config.debounce'];
532
551
 
533
552
  class FieldFactory {
534
- /**
535
- * @constructor
536
- *
537
- * @param { import('./FormFieldRegistry').default } formFieldRegistry
538
- * @param { import('@bpmn-io/form-js-viewer').FormFields } formFields
553
+ /**
554
+ * @constructor
555
+ *
556
+ * @param { import('./FormFieldRegistry').default } formFieldRegistry
557
+ * @param { import('@bpmn-io/form-js-viewer').FormFields } formFields
539
558
  */
540
559
  constructor(formFieldRegistry, formFields) {
541
560
  this._formFieldRegistry = formFieldRegistry;
@@ -598,11 +617,11 @@ class FieldFactory {
598
617
  FieldFactory.$inject = ['formFieldRegistry', 'formFields'];
599
618
 
600
619
  class FormFieldRegistry extends formJsViewer.FormFieldRegistry {
601
- /**
602
- * Updates a form fields id.
603
- *
604
- * @param {Object} formField
605
- * @param {string} newId
620
+ /**
621
+ * Updates a form fields id.
622
+ *
623
+ * @param {Object} formField
624
+ * @param {string} newId
606
625
  */
607
626
  updateId(formField, newId) {
608
627
  this._validateId(newId);
@@ -623,13 +642,13 @@ class FormFieldRegistry extends formJsViewer.FormFieldRegistry {
623
642
  }
624
643
  }
625
644
 
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
645
+ /**
646
+ * Validate the suitability of the given id and signals a problem
647
+ * with an exception.
648
+ *
649
+ * @param {string} id
650
+ *
651
+ * @throws {Error} if id is empty or already assigned
633
652
  */
634
653
  _validateId(id) {
635
654
  if (!id) {
@@ -646,11 +665,11 @@ const MAX_COLUMNS = 16;
646
665
  const MIN_COLUMNS = 2;
647
666
  const MAX_FIELDS_PER_ROW = 4;
648
667
  class FormLayoutValidator {
649
- /**
650
- * @constructor
651
- *
652
- * @param { import('./FormLayouter').default } formLayouter
653
- * @param { import('./FormFieldRegistry').default } formFieldRegistry
668
+ /**
669
+ * @constructor
670
+ *
671
+ * @param { import('./FormLayouter').default } formLayouter
672
+ * @param { import('./FormFieldRegistry').default } formFieldRegistry
654
673
  */
655
674
  constructor(formLayouter, formFieldRegistry) {
656
675
  this._formLayouter = formLayouter;
@@ -710,11 +729,11 @@ function calculateMaxColumnsWithAuto(autoCols) {
710
729
  }
711
730
 
712
731
  class Importer {
713
- /**
714
- * @constructor
715
- * @param { import('../core/FormFieldRegistry').default } formFieldRegistry
716
- * @param { import('../core/FieldFactory').default } fieldFactory
717
- * @param { import('../core/FormLayouter').default } formLayouter
732
+ /**
733
+ * @constructor
734
+ * @param { import('../core/FormFieldRegistry').default } formFieldRegistry
735
+ * @param { import('../core/FieldFactory').default } fieldFactory
736
+ * @param { import('../core/FormLayouter').default } formLayouter
718
737
  */
719
738
  constructor(formFieldRegistry, fieldFactory, formLayouter) {
720
739
  this._formFieldRegistry = formFieldRegistry;
@@ -722,21 +741,21 @@ class Importer {
722
741
  this._formLayouter = formLayouter;
723
742
  }
724
743
 
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}
744
+ /**
745
+ * Import schema creating rows, fields, attaching additional
746
+ * information to each field and adding fields to the
747
+ * field registry.
748
+ *
749
+ * Additional information attached:
750
+ *
751
+ * * `id` (unless present)
752
+ * * `_parent`
753
+ * * `_path`
754
+ *
755
+ * @param {any} schema
756
+ *
757
+ * @typedef {{ warnings: Error[], schema: any }} ImportResult
758
+ * @returns {ImportResult}
740
759
  */
741
760
  importSchema(schema) {
742
761
  // TODO: Add warnings
@@ -754,12 +773,12 @@ class Importer {
754
773
  }
755
774
  }
756
775
 
757
- /**
758
- * @param {{[x: string]: any}} fieldAttrs
759
- * @param {String} [parentId]
760
- * @param {number} [index]
761
- *
762
- * @return {any} field
776
+ /**
777
+ * @param {{[x: string]: any}} fieldAttrs
778
+ * @param {String} [parentId]
779
+ * @param {number} [index]
780
+ *
781
+ * @return {any} field
763
782
  */
764
783
  importFormField(fieldAttrs, parentId, index) {
765
784
  const {
@@ -796,11 +815,11 @@ class Importer {
796
815
  return field;
797
816
  }
798
817
 
799
- /**
800
- * @param {Array<any>} components
801
- * @param {string} parentId
802
- *
803
- * @return {Array<any>} imported components
818
+ /**
819
+ * @param {Array<any>} components
820
+ * @param {string} parentId
821
+ *
822
+ * @return {Array<any>} imported components
804
823
  */
805
824
  importFormFields(components, parentId) {
806
825
  return components.map((component, index) => {
@@ -825,22 +844,22 @@ function editorFormFieldClasses(type, {
825
844
  });
826
845
  }
827
846
 
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
847
+ /**
848
+ * Add a dragger that calls back the passed function with
849
+ * { event, delta } on drag.
850
+ *
851
+ * @example
852
+ *
853
+ * function dragMove(event, delta) {
854
+ * // we are dragging (!!)
855
+ * }
856
+ *
857
+ * domElement.addEventListener('dragstart', dragger(dragMove));
858
+ *
859
+ * @param {Function} fn
860
+ * @param {Element} dragPreview
861
+ *
862
+ * @return {Function} drag start callback function
844
863
  */
845
864
  function createDragger(fn, dragPreview) {
846
865
  let self;
@@ -881,12 +900,12 @@ function createDragger(fn, dragPreview) {
881
900
  return onDragStart;
882
901
  }
883
902
 
884
- /**
885
- * Throttle function call according UI update cycle.
886
- *
887
- * @param {Function} fn
888
- *
889
- * @return {Function} throttled fn
903
+ /**
904
+ * Throttle function call according UI update cycle.
905
+ *
906
+ * @param {Function} fn
907
+ *
908
+ * @return {Function} throttled fn
890
909
  */
891
910
  function throttle(fn) {
892
911
  let active = false;
@@ -915,11 +934,11 @@ const DragAndDropContext = preact.createContext({
915
934
  });
916
935
  var DragAndDropContext$1 = DragAndDropContext;
917
936
 
918
- /**
919
- * @param {string} type
920
- * @param {boolean} [strict]
921
- *
922
- * @returns {any}
937
+ /**
938
+ * @param {string} type
939
+ * @param {boolean} [strict]
940
+ *
941
+ * @returns {any}
923
942
  */
924
943
  function getService$1(type, strict) {}
925
944
  const FormEditorContext = preact.createContext({
@@ -934,83 +953,146 @@ function useService$1 (type, strict) {
934
953
  return getService(type, strict);
935
954
  }
936
955
 
956
+ var _path$4;
957
+ 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); }
958
+ var SvgClose = function SvgClose(props) {
959
+ return /*#__PURE__*/React__namespace.createElement("svg", _extends$4({
960
+ xmlns: "http://www.w3.org/2000/svg",
961
+ width: 16,
962
+ height: 16,
963
+ fill: "currentColor"
964
+ }, props), _path$4 || (_path$4 = /*#__PURE__*/React__namespace.createElement("path", {
965
+ fillRule: "evenodd",
966
+ 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",
967
+ clipRule: "evenodd"
968
+ })));
969
+ };
970
+ var CloseIcon = SvgClose;
971
+
972
+ var _path$3, _path2$1;
937
973
  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); }
938
- var CloseIcon = (({
939
- styles = {},
940
- ...props
941
- }) => /*#__PURE__*/React.createElement("svg", _extends$3({
942
- width: "16",
943
- height: "16",
944
- fill: "currentColor",
945
- xmlns: "http://www.w3.org/2000/svg"
946
- }, props), /*#__PURE__*/React.createElement("path", {
947
- fillRule: "evenodd",
948
- clipRule: "evenodd",
949
- 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"
950
- })));
974
+ var SvgDelete = function SvgDelete(props) {
975
+ return /*#__PURE__*/React__namespace.createElement("svg", _extends$3({
976
+ xmlns: "http://www.w3.org/2000/svg",
977
+ width: 16,
978
+ height: 16,
979
+ fill: "none"
980
+ }, props), /*#__PURE__*/React__namespace.createElement("rect", {
981
+ width: 16,
982
+ height: 16,
983
+ x: 0.536,
984
+ fill: "#fff",
985
+ rx: 3,
986
+ style: {
987
+ mixBlendMode: "multiply"
988
+ }
989
+ }), /*#__PURE__*/React__namespace.createElement("path", {
990
+ fill: "#fff",
991
+ d: "M0 0h16v16H0z",
992
+ style: {
993
+ mixBlendMode: "multiply"
994
+ },
995
+ transform: "translate(.536)"
996
+ }), _path$3 || (_path$3 = /*#__PURE__*/React__namespace.createElement("path", {
997
+ fill: "currentcolor",
998
+ d: "M7.536 6h-1v6h1V6Zm3 0h-1v6h1V6Z"
999
+ })), _path2$1 || (_path2$1 = /*#__PURE__*/React__namespace.createElement("path", {
1000
+ fill: "currentcolor",
1001
+ d: "M2.536 3v1h1v10a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4h1V3h-12Zm2 11V4h8v10h-8Zm6-13h-4v1h4V1Z"
1002
+ })));
1003
+ };
1004
+ var DeleteIcon$1 = SvgDelete;
951
1005
 
1006
+ var _path$2;
952
1007
  function _extends$2() { _extends$2 = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$2.apply(this, arguments); }
953
- var DeleteIcon$1 = (({
954
- styles = {},
955
- ...props
956
- }) => /*#__PURE__*/React.createElement("svg", _extends$2({
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: ".536",
965
- fill: "#fff",
966
- rx: "3",
967
- style: {
968
- mixBlendMode: "multiply"
969
- }
970
- }), /*#__PURE__*/React.createElement("path", {
971
- fill: "#fff",
972
- d: "M.536 0h16v16h-16z",
973
- style: {
974
- mixBlendMode: "multiply"
975
- }
976
- }), /*#__PURE__*/React.createElement("path", {
977
- fill: "currentcolor",
978
- d: "M7.536 6h-1v6h1V6zm3 0h-1v6h1V6z"
979
- }), /*#__PURE__*/React.createElement("path", {
980
- fill: "currentcolor",
981
- d: "M2.536 3v1h1v10a1 1 0 001 1h8a1 1 0 001-1V4h1V3h-12zm2 11V4h8v10h-8zm6-13h-4v1h4V1z"
982
- })));
1008
+ var SvgDraggable = function SvgDraggable(props) {
1009
+ return /*#__PURE__*/React__namespace.createElement("svg", _extends$2({
1010
+ xmlns: "http://www.w3.org/2000/svg",
1011
+ xmlSpace: "preserve",
1012
+ width: 16,
1013
+ height: 16,
1014
+ fill: "currentcolor",
1015
+ viewBox: "0 0 32 32"
1016
+ }, props), _path$2 || (_path$2 = /*#__PURE__*/React__namespace.createElement("path", {
1017
+ d: "M10 6h4v4h-4zm8 0h4v4h-4zm-8 8h4v4h-4zm8 0h4v4h-4zm-8 8h4v4h-4zm8 0h4v4h-4z"
1018
+ })), /*#__PURE__*/React__namespace.createElement("path", {
1019
+ d: "M0 0h32v32H0z",
1020
+ style: {
1021
+ fill: "none"
1022
+ }
1023
+ }));
1024
+ };
1025
+ var DraggableIcon = SvgDraggable;
983
1026
 
1027
+ var _path$1;
984
1028
  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); }
985
- var DraggableIcon = (({
986
- styles = {},
987
- ...props
988
- }) => /*#__PURE__*/React.createElement("svg", _extends$1({
989
- xmlns: "http://www.w3.org/2000/svg",
990
- width: "16",
991
- height: "16",
992
- fill: "currentcolor",
993
- viewBox: "0 0 32 32"
994
- }, props), /*#__PURE__*/React.createElement("path", {
995
- d: "M10 6h4v4h-4zm8 0h4v4h-4zm-8 8h4v4h-4zm8 0h4v4h-4zm-8 8h4v4h-4zm8 0h4v4h-4z"
996
- }), /*#__PURE__*/React.createElement("path", {
997
- d: "M0 0h32v32H0z",
998
- fill: "none"
999
- })));
1029
+ var SvgSearch = function SvgSearch(props) {
1030
+ return /*#__PURE__*/React__namespace.createElement("svg", _extends$1({
1031
+ xmlns: "http://www.w3.org/2000/svg",
1032
+ width: 15,
1033
+ height: 15,
1034
+ fill: "none"
1035
+ }, props), _path$1 || (_path$1 = /*#__PURE__*/React__namespace.createElement("path", {
1036
+ fill: "currentColor",
1037
+ 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"
1038
+ })));
1039
+ };
1040
+ var SearchIcon = SvgSearch;
1000
1041
 
1042
+ var _path, _rect, _mask, _path2, _path3, _path4, _path5, _path6;
1001
1043
  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); }
1002
- var SearchIcon = (({
1003
- styles = {},
1004
- ...props
1005
- }) => /*#__PURE__*/React.createElement("svg", _extends({
1006
- width: "15",
1007
- height: "15",
1008
- fill: "none",
1009
- xmlns: "http://www.w3.org/2000/svg"
1010
- }, props), /*#__PURE__*/React.createElement("path", {
1011
- 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",
1012
- fill: "currentColor"
1013
- })));
1044
+ var SvgEmptyForm = function SvgEmptyForm(props) {
1045
+ return /*#__PURE__*/React__namespace.createElement("svg", _extends({
1046
+ xmlns: "http://www.w3.org/2000/svg",
1047
+ width: 126,
1048
+ height: 96,
1049
+ fill: "none"
1050
+ }, props), _path || (_path = /*#__PURE__*/React__namespace.createElement("path", {
1051
+ fill: "#FF832B",
1052
+ fillRule: "evenodd",
1053
+ 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",
1054
+ clipRule: "evenodd"
1055
+ })), _rect || (_rect = /*#__PURE__*/React__namespace.createElement("rect", {
1056
+ width: 70,
1057
+ height: 70,
1058
+ fill: "#E5E5E5",
1059
+ rx: 3,
1060
+ transform: "matrix(-1 0 0 1 94 0)"
1061
+ })), _mask || (_mask = /*#__PURE__*/React__namespace.createElement("mask", {
1062
+ id: "EmptyForm_svg__a",
1063
+ fill: "#fff"
1064
+ }, /*#__PURE__*/React__namespace.createElement("path", {
1065
+ fillRule: "evenodd",
1066
+ 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",
1067
+ clipRule: "evenodd"
1068
+ }))), _path2 || (_path2 = /*#__PURE__*/React__namespace.createElement("path", {
1069
+ fill: "#393939",
1070
+ fillRule: "evenodd",
1071
+ 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",
1072
+ clipRule: "evenodd"
1073
+ })), _path3 || (_path3 = /*#__PURE__*/React__namespace.createElement("path", {
1074
+ fill: "#393939",
1075
+ 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",
1076
+ mask: "url(#EmptyForm_svg__a)"
1077
+ })), _path4 || (_path4 = /*#__PURE__*/React__namespace.createElement("path", {
1078
+ stroke: "#000",
1079
+ strokeLinecap: "round",
1080
+ strokeWidth: 3,
1081
+ d: "m69.431 39.163-9.192-9.192"
1082
+ })), _path5 || (_path5 = /*#__PURE__*/React__namespace.createElement("path", {
1083
+ stroke: "#000",
1084
+ strokeLinecap: "round",
1085
+ strokeWidth: 3,
1086
+ d: "M1.5-1.5h8",
1087
+ transform: "matrix(-1 0 0 1 68.213 50.123)"
1088
+ })), _path6 || (_path6 = /*#__PURE__*/React__namespace.createElement("path", {
1089
+ stroke: "#000",
1090
+ strokeLinecap: "round",
1091
+ strokeWidth: 3,
1092
+ d: "M78.969 36.367v-8"
1093
+ })));
1094
+ };
1095
+ var EmptyFormIcon = SvgEmptyForm;
1014
1096
 
1015
1097
  function EditorText(props) {
1016
1098
  const {
@@ -1020,7 +1102,7 @@ function EditorText(props) {
1020
1102
  const Icon = formJsViewer.iconsByType('text');
1021
1103
  const templating = useService$1('templating');
1022
1104
  const expressionLanguage = useService$1('expressionLanguage');
1023
- if (!text) {
1105
+ if (!text || !text.trim()) {
1024
1106
  return jsxRuntime.jsx("div", {
1025
1107
  class: editorFormFieldClasses(type),
1026
1108
  children: jsxRuntime.jsxs("div", {
@@ -1206,23 +1288,23 @@ var Slot = (props => {
1206
1288
  return fillsAndSeparators;
1207
1289
  });
1208
1290
 
1209
- /**
1210
- * Creates a Fragment for a fill.
1211
- *
1212
- * @param {Object} fill Fill to be rendered
1213
- * @returns {Object} Preact Fragment containing fill's children
1291
+ /**
1292
+ * Creates a Fragment for a fill.
1293
+ *
1294
+ * @param {Object} fill Fill to be rendered
1295
+ * @returns {Object} Preact Fragment containing fill's children
1214
1296
  */
1215
1297
  const FillFragment = fill => jsxRuntime.jsx(preact.Fragment, {
1216
1298
  children: fill.children
1217
1299
  }, fill.id);
1218
1300
 
1219
- /**
1220
- * Creates an array of fills, with separators inserted between groups.
1221
- *
1222
- * @param {Array} groups Groups of fills
1223
- * @param {Function} fillRenderer Function to create a fill
1224
- * @param {Function} separatorRenderer Function to create a separator
1225
- * @returns {Array} Array of fills and separators
1301
+ /**
1302
+ * Creates an array of fills, with separators inserted between groups.
1303
+ *
1304
+ * @param {Array} groups Groups of fills
1305
+ * @param {Function} fillRenderer Function to create a fill
1306
+ * @param {Function} separatorRenderer Function to create a separator
1307
+ * @returns {Array} Array of fills and separators
1226
1308
  */
1227
1309
  const buildFills = (groups, fillRenderer, separatorRenderer) => {
1228
1310
  const result = [];
@@ -1240,8 +1322,8 @@ const buildFills = (groups, fillRenderer, separatorRenderer) => {
1240
1322
  return result;
1241
1323
  };
1242
1324
 
1243
- /**
1244
- * Groups fills by group name property.
1325
+ /**
1326
+ * Groups fills by group name property.
1245
1327
  */
1246
1328
  const _groupByGroupName = fills => {
1247
1329
  const groups = [];
@@ -1261,8 +1343,8 @@ const _groupByGroupName = fills => {
1261
1343
  return Object.keys(groupsById).sort().map(id => groupsById[id]);
1262
1344
  };
1263
1345
 
1264
- /**
1265
- * Compares fills by priority.
1346
+ /**
1347
+ * Compares fills by priority.
1266
1348
  */
1267
1349
  const _comparePriority = (a, b) => {
1268
1350
  return (b.priority || 0) - (a.priority || 0);
@@ -1490,19 +1572,19 @@ const DRAG_NO_DROP_CLS = 'fjs-no-drop';
1490
1572
  const DRAG_NO_MOVE_CLS = 'fjs-no-move';
1491
1573
  const ERROR_DROP_CLS = 'fjs-error-drop';
1492
1574
 
1493
- /**
1494
- * @typedef { { id: String, components: Array<any> } } FormRow
1575
+ /**
1576
+ * @typedef { { id: String, components: Array<any> } } FormRow
1495
1577
  */
1496
1578
 
1497
1579
  class Dragging {
1498
- /**
1499
- * @constructor
1500
- *
1501
- * @param { import('../../core/FormFieldRegistry').default } formFieldRegistry
1502
- * @param { import('../../core/FormLayouter').default } formLayouter
1503
- * @param { import('../../core/FormLayoutValidator').default } formLayoutValidator
1504
- * @param { import('../../core/EventBus').default } eventBus
1505
- * @param { import('../modeling/Modeling').default } modeling
1580
+ /**
1581
+ * @constructor
1582
+ *
1583
+ * @param { import('../../core/FormFieldRegistry').default } formFieldRegistry
1584
+ * @param { import('../../core/FormLayouter').default } formLayouter
1585
+ * @param { import('../../core/FormLayoutValidator').default } formLayoutValidator
1586
+ * @param { import('../../core/EventBus').default } eventBus
1587
+ * @param { import('../modeling/Modeling').default } modeling
1506
1588
  */
1507
1589
  constructor(formFieldRegistry, formLayouter, formLayoutValidator, eventBus, modeling) {
1508
1590
  this._formFieldRegistry = formFieldRegistry;
@@ -1512,13 +1594,13 @@ class Dragging {
1512
1594
  this._modeling = modeling;
1513
1595
  }
1514
1596
 
1515
- /**
1516
- * Calculcates position in form schema given the dropped place.
1517
- *
1518
- * @param { FormRow } targetRow
1519
- * @param { any } targetFormField
1520
- * @param { HTMLElement } sibling
1521
- * @returns { number }
1597
+ /**
1598
+ * Calculcates position in form schema given the dropped place.
1599
+ *
1600
+ * @param { FormRow } targetRow
1601
+ * @param { any } targetFormField
1602
+ * @param { HTMLElement } sibling
1603
+ * @returns { number }
1522
1604
  */
1523
1605
  getTargetIndex(targetRow, targetFormField, sibling) {
1524
1606
  /** @type HTMLElement */
@@ -1620,8 +1702,8 @@ class Dragging {
1620
1702
  }
1621
1703
  }
1622
1704
 
1623
- /**
1624
- * @param { { container: Array<string>, direction: string, mirrorContainer: string } } options
1705
+ /**
1706
+ * @param { { container: Array<string>, direction: string, mirrorContainer: string } } options
1625
1707
  */
1626
1708
  createDragulaInstance(options) {
1627
1709
  const {
@@ -1921,7 +2003,19 @@ function ContextPad(props) {
1921
2003
  });
1922
2004
  }
1923
2005
  function Empty(props) {
1924
- return null;
2006
+ return jsxRuntime.jsx("div", {
2007
+ class: "fjs-empty-editor",
2008
+ children: jsxRuntime.jsxs("div", {
2009
+ class: "fjs-empty-editor-card",
2010
+ children: [jsxRuntime.jsx(EmptyFormIcon, {}), jsxRuntime.jsx("h2", {
2011
+ children: "Build your form"
2012
+ }), jsxRuntime.jsx("span", {
2013
+ children: "Drag and drop components here to start designing."
2014
+ }), jsxRuntime.jsx("span", {
2015
+ children: "Use the preview window to test your form."
2016
+ })]
2017
+ })
2018
+ });
1925
2019
  }
1926
2020
  function Element$1(props) {
1927
2021
  const eventBus = useService$1('eventBus'),
@@ -2018,7 +2112,7 @@ function DebugColumns(props) {
2018
2112
  return null;
2019
2113
  }
2020
2114
  return jsxRuntime.jsx("div", {
2021
- 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;",
2115
+ 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;",
2022
2116
  class: "fjs-debug-columns",
2023
2117
  children: (field.layout || {}).columns || 'auto'
2024
2118
  });
@@ -3077,10 +3171,10 @@ function updateRow(formField, rowId) {
3077
3171
  }
3078
3172
 
3079
3173
  class AddFormFieldHandler {
3080
- /**
3081
- * @constructor
3082
- * @param { import('../../../FormEditor').default } formEditor
3083
- * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3174
+ /**
3175
+ * @constructor
3176
+ * @param { import('../../../FormEditor').default } formEditor
3177
+ * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3084
3178
  */
3085
3179
  constructor(formEditor, formFieldRegistry) {
3086
3180
  this._formEditor = formEditor;
@@ -3141,10 +3235,10 @@ class AddFormFieldHandler {
3141
3235
  AddFormFieldHandler.$inject = ['formEditor', 'formFieldRegistry'];
3142
3236
 
3143
3237
  class EditFormFieldHandler {
3144
- /**
3145
- * @constructor
3146
- * @param { import('../../../FormEditor').default } formEditor
3147
- * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3238
+ /**
3239
+ * @constructor
3240
+ * @param { import('../../../FormEditor').default } formEditor
3241
+ * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3148
3242
  */
3149
3243
  constructor(formEditor, formFieldRegistry) {
3150
3244
  this._formEditor = formEditor;
@@ -3207,10 +3301,10 @@ class EditFormFieldHandler {
3207
3301
  EditFormFieldHandler.$inject = ['formEditor', 'formFieldRegistry'];
3208
3302
 
3209
3303
  class MoveFormFieldHandler {
3210
- /**
3211
- * @constructor
3212
- * @param { import('../../../FormEditor').default } formEditor
3213
- * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3304
+ /**
3305
+ * @constructor
3306
+ * @param { import('../../../FormEditor').default } formEditor
3307
+ * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3214
3308
  */
3215
3309
  constructor(formEditor, formFieldRegistry) {
3216
3310
  this._formEditor = formEditor;
@@ -3299,10 +3393,10 @@ class MoveFormFieldHandler {
3299
3393
  MoveFormFieldHandler.$inject = ['formEditor', 'formFieldRegistry'];
3300
3394
 
3301
3395
  class RemoveFormFieldHandler {
3302
- /**
3303
- * @constructor
3304
- * @param { import('../../../FormEditor').default } formEditor
3305
- * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3396
+ /**
3397
+ * @constructor
3398
+ * @param { import('../../../FormEditor').default } formEditor
3399
+ * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3306
3400
  */
3307
3401
  constructor(formEditor, formFieldRegistry) {
3308
3402
  this._formEditor = formEditor;
@@ -3362,9 +3456,9 @@ class RemoveFormFieldHandler {
3362
3456
  RemoveFormFieldHandler.$inject = ['formEditor', 'formFieldRegistry'];
3363
3457
 
3364
3458
  class UpdateIdClaimHandler {
3365
- /**
3366
- * @constructor
3367
- * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3459
+ /**
3460
+ * @constructor
3461
+ * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3368
3462
  */
3369
3463
  constructor(formFieldRegistry) {
3370
3464
  this._formFieldRegistry = formFieldRegistry;
@@ -3397,9 +3491,9 @@ class UpdateIdClaimHandler {
3397
3491
  UpdateIdClaimHandler.$inject = ['formFieldRegistry'];
3398
3492
 
3399
3493
  class UpdateKeyClaimHandler {
3400
- /**
3401
- * @constructor
3402
- * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3494
+ /**
3495
+ * @constructor
3496
+ * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3403
3497
  */
3404
3498
  constructor(formFieldRegistry) {
3405
3499
  this._formFieldRegistry = formFieldRegistry;
@@ -3865,8 +3959,8 @@ class ValidateBehavior extends CommandInterceptor {
3865
3959
  constructor(eventBus) {
3866
3960
  super(eventBus);
3867
3961
 
3868
- /**
3869
- * Remove custom validation if <validationType> is about to be added.
3962
+ /**
3963
+ * Remove custom validation if <validationType> is about to be added.
3870
3964
  */
3871
3965
  // @ts-ignore-next-line
3872
3966
  this.preExecute('formField.edit', function (context) {
@@ -4446,22 +4540,22 @@ var SelectionModule = {
4446
4540
  selectionBehavior: ['type', SelectionBehavior]
4447
4541
  };
4448
4542
 
4449
- /**
4450
- * Base class for sectionable UI modules.
4451
- *
4452
- * @property {EventBus} _eventBus - EventBus instance used for event handling.
4453
- * @property {string} managerType - Type of the render manager. Used to form event names.
4454
- *
4455
- * @class SectionModuleBase
4543
+ /**
4544
+ * Base class for sectionable UI modules.
4545
+ *
4546
+ * @property {EventBus} _eventBus - EventBus instance used for event handling.
4547
+ * @property {string} managerType - Type of the render manager. Used to form event names.
4548
+ *
4549
+ * @class SectionModuleBase
4456
4550
  */
4457
4551
  class SectionModuleBase {
4458
- /**
4459
- * Create a SectionModuleBase instance.
4460
- *
4461
- * @param {any} eventBus - The EventBus instance used for event handling.
4462
- * @param {string} sectionKey - The type of render manager. Used to form event names.
4463
- *
4464
- * @constructor
4552
+ /**
4553
+ * Create a SectionModuleBase instance.
4554
+ *
4555
+ * @param {any} eventBus - The EventBus instance used for event handling.
4556
+ * @param {string} sectionKey - The type of render manager. Used to form event names.
4557
+ *
4558
+ * @constructor
4465
4559
  */
4466
4560
  constructor(eventBus, sectionKey) {
4467
4561
  this._eventBus = eventBus;
@@ -4474,10 +4568,10 @@ class SectionModuleBase {
4474
4568
  });
4475
4569
  }
4476
4570
 
4477
- /**
4478
- * Attach the managed section to a parent node.
4479
- *
4480
- * @param {HTMLElement} container - The parent node to attach to.
4571
+ /**
4572
+ * Attach the managed section to a parent node.
4573
+ *
4574
+ * @param {HTMLElement} container - The parent node to attach to.
4481
4575
  */
4482
4576
  attachTo(container) {
4483
4577
  this._onceSectionRendered(() => this._eventBus.fire(`${this._sectionKey}.attach`, {
@@ -4485,22 +4579,22 @@ class SectionModuleBase {
4485
4579
  }));
4486
4580
  }
4487
4581
 
4488
- /**
4489
- * Detach the managed section from its parent node.
4582
+ /**
4583
+ * Detach the managed section from its parent node.
4490
4584
  */
4491
4585
  detach() {
4492
4586
  this._onceSectionRendered(() => this._eventBus.fire(`${this._sectionKey}.detach`));
4493
4587
  }
4494
4588
 
4495
- /**
4496
- * Reset the managed section to its initial state.
4589
+ /**
4590
+ * Reset the managed section to its initial state.
4497
4591
  */
4498
4592
  reset() {
4499
4593
  this._onceSectionRendered(() => this._eventBus.fire(`${this._sectionKey}.reset`));
4500
4594
  }
4501
4595
 
4502
- /**
4503
- * Circumvents timing issues.
4596
+ /**
4597
+ * Circumvents timing issues.
4504
4598
  */
4505
4599
  _onceSectionRendered(callback) {
4506
4600
  if (this.isSectionRendered) {
@@ -5983,140 +6077,290 @@ function isEdited$7(node) {
5983
6077
  function prefixId$6(id) {
5984
6078
  return `bio-properties-panel-${id}`;
5985
6079
  }
5986
- const noop$1 = () => {};
5987
- function FeelTextfield(props) {
6080
+ function NumberField(props) {
5988
6081
  const {
5989
6082
  debounce,
6083
+ disabled,
6084
+ displayLabel = true,
5990
6085
  id,
6086
+ inputRef,
5991
6087
  label,
6088
+ max,
6089
+ min,
5992
6090
  onInput,
5993
- onError,
5994
- feel,
6091
+ step,
5995
6092
  value = '',
5996
- disabled = false,
5997
- variables,
5998
- tooltipContainer,
5999
- OptionalComponent = OptionalFeelInput
6093
+ onFocus,
6094
+ onBlur
6000
6095
  } = props;
6001
- const [localValue, _setLocalValue] = hooks.useState(value);
6002
- const editorRef = useShowEntryEvent(id);
6003
- const containerRef = hooks.useRef();
6004
- const feelActive = minDash.isString(localValue) && localValue.startsWith('=') || feel === 'required';
6005
- const feelOnlyValue = minDash.isString(localValue) && localValue.startsWith('=') ? localValue.substring(1) : localValue;
6006
- const [focus, _setFocus] = hooks.useState(undefined);
6007
- const setFocus = (offset = 0) => {
6008
- const hasFocus = containerRef.current.contains(document.activeElement);
6009
-
6010
- // Keep caret position if it is already focused, otherwise focus at the end
6011
- const position = hasFocus ? document.activeElement.selectionStart : Infinity;
6012
- _setFocus(position + offset);
6013
- };
6096
+ const [localValue, setLocalValue] = hooks.useState(value);
6014
6097
  const handleInputCallback = hooks.useMemo(() => {
6015
- return debounce(newValue => {
6016
- onInput(newValue);
6098
+ return debounce(event => {
6099
+ const {
6100
+ validity,
6101
+ value
6102
+ } = event.target;
6103
+ if (validity.valid) {
6104
+ onInput(value ? parseFloat(value) : undefined);
6105
+ }
6017
6106
  });
6018
6107
  }, [onInput, debounce]);
6019
- const setLocalValue = newValue => {
6020
- _setLocalValue(newValue);
6021
- if (!newValue || newValue === '=') {
6022
- handleInputCallback(undefined);
6023
- } else {
6024
- handleInputCallback(newValue);
6025
- }
6026
- };
6027
- const handleFeelToggle = useStaticCallback(() => {
6028
- if (feel === 'required') {
6029
- return;
6030
- }
6031
- if (!feelActive) {
6032
- setLocalValue('=' + localValue);
6033
- } else {
6034
- setLocalValue(feelOnlyValue);
6035
- }
6036
- });
6037
- const handleLocalInput = newValue => {
6038
- if (feelActive) {
6039
- newValue = '=' + newValue;
6040
- }
6041
- if (newValue === localValue) {
6042
- return;
6043
- }
6044
- setLocalValue(newValue);
6045
- if (!feelActive && minDash.isString(newValue) && newValue.startsWith('=')) {
6046
- // focus is behind `=` sign that will be removed
6047
- setFocus(-1);
6048
- }
6108
+ const handleInput = e => {
6109
+ handleInputCallback(e);
6110
+ setLocalValue(e.target.value);
6049
6111
  };
6050
- const handleLint = useStaticCallback(lint => {
6051
- if (!(lint && lint.length)) {
6052
- onError(undefined);
6053
- return;
6054
- }
6055
- const error = lint[0];
6056
- const message = `${error.source}: ${error.message}`;
6057
- onError(message);
6058
- });
6059
- hooks.useEffect(() => {
6060
- if (typeof focus !== 'undefined') {
6061
- editorRef.current.focus(focus);
6062
- _setFocus(undefined);
6063
- }
6064
- }, [focus]);
6065
6112
  hooks.useEffect(() => {
6066
6113
  if (value === localValue) {
6067
6114
  return;
6068
6115
  }
6069
-
6070
- // External value change removed content => keep FEEL configuration
6071
- if (!value) {
6072
- setLocalValue(feelActive ? '=' : '');
6073
- return;
6074
- }
6075
6116
  setLocalValue(value);
6076
6117
  }, [value]);
6077
-
6078
- // copy-paste integration
6079
- hooks.useEffect(() => {
6080
- const copyHandler = event => {
6081
- if (!feelActive) {
6082
- return;
6083
- }
6084
- event.clipboardData.setData('application/FEEL', event.clipboardData.getData('text'));
6085
- };
6086
- const pasteHandler = event => {
6087
- if (feelActive) {
6088
- return;
6089
- }
6090
- const data = event.clipboardData.getData('application/FEEL');
6091
- if (data) {
6092
- setTimeout(() => {
6093
- handleFeelToggle();
6094
- setFocus();
6095
- });
6096
- }
6097
- };
6098
- containerRef.current.addEventListener('copy', copyHandler);
6099
- containerRef.current.addEventListener('cut', copyHandler);
6100
- containerRef.current.addEventListener('paste', pasteHandler);
6101
- return () => {
6102
- containerRef.current.removeEventListener('copy', copyHandler);
6103
- containerRef.current.removeEventListener('cut', copyHandler);
6104
- containerRef.current.removeEventListener('paste', pasteHandler);
6105
- };
6106
- }, [containerRef, feelActive, handleFeelToggle, setFocus]);
6107
6118
  return jsxRuntime.jsxs("div", {
6108
- class: classnames('bio-properties-panel-feel-entry', {
6109
- 'feel-active': feelActive
6110
- }),
6111
- children: [jsxRuntime.jsxs("label", {
6119
+ class: "bio-properties-panel-numberfield",
6120
+ children: [displayLabel && jsxRuntime.jsx("label", {
6112
6121
  for: prefixId$5(id),
6113
6122
  class: "bio-properties-panel-label",
6114
- onClick: () => setFocus(),
6115
- children: [label, jsxRuntime.jsx(FeelIcon, {
6116
- label: label,
6117
- feel: feel,
6118
- onClick: handleFeelToggle,
6119
- active: feelActive
6123
+ children: label
6124
+ }), jsxRuntime.jsx("input", {
6125
+ id: prefixId$5(id),
6126
+ ref: inputRef,
6127
+ type: "number",
6128
+ name: id,
6129
+ spellCheck: "false",
6130
+ autoComplete: "off",
6131
+ disabled: disabled,
6132
+ class: "bio-properties-panel-input",
6133
+ max: max,
6134
+ min: min,
6135
+ onInput: handleInput,
6136
+ onFocus: onFocus,
6137
+ onBlur: onBlur,
6138
+ step: step,
6139
+ value: localValue
6140
+ })]
6141
+ });
6142
+ }
6143
+
6144
+ /**
6145
+ * @param {Object} props
6146
+ * @param {Boolean} props.debounce
6147
+ * @param {String} props.description
6148
+ * @param {Boolean} props.disabled
6149
+ * @param {Object} props.element
6150
+ * @param {Function} props.getValue
6151
+ * @param {String} props.id
6152
+ * @param {String} props.label
6153
+ * @param {String} props.max
6154
+ * @param {String} props.min
6155
+ * @param {Function} props.setValue
6156
+ * @param {Function} props.onFocus
6157
+ * @param {Function} props.onBlur
6158
+ * @param {String} props.step
6159
+ * @param {Function} props.validate
6160
+ */
6161
+ function NumberFieldEntry(props) {
6162
+ const {
6163
+ debounce,
6164
+ description,
6165
+ disabled,
6166
+ element,
6167
+ getValue,
6168
+ id,
6169
+ label,
6170
+ max,
6171
+ min,
6172
+ setValue,
6173
+ step,
6174
+ onFocus,
6175
+ onBlur,
6176
+ validate
6177
+ } = props;
6178
+ const globalError = useError(id);
6179
+ const [localError, setLocalError] = hooks.useState(null);
6180
+ let value = getValue(element);
6181
+ hooks.useEffect(() => {
6182
+ if (minDash.isFunction(validate)) {
6183
+ const newValidationError = validate(value) || null;
6184
+ setLocalError(newValidationError);
6185
+ }
6186
+ }, [value]);
6187
+ const onInput = newValue => {
6188
+ let newValidationError = null;
6189
+ if (minDash.isFunction(validate)) {
6190
+ newValidationError = validate(newValue) || null;
6191
+ }
6192
+ setValue(newValue, newValidationError);
6193
+ setLocalError(newValidationError);
6194
+ };
6195
+ const error = globalError || localError;
6196
+ return jsxRuntime.jsxs("div", {
6197
+ class: classnames('bio-properties-panel-entry', error ? 'has-error' : ''),
6198
+ "data-entry-id": id,
6199
+ children: [jsxRuntime.jsx(NumberField, {
6200
+ debounce: debounce,
6201
+ disabled: disabled,
6202
+ id: id,
6203
+ label: label,
6204
+ onFocus: onFocus,
6205
+ onBlur: onBlur,
6206
+ onInput: onInput,
6207
+ max: max,
6208
+ min: min,
6209
+ step: step,
6210
+ value: value
6211
+ }, element), error && jsxRuntime.jsx("div", {
6212
+ class: "bio-properties-panel-error",
6213
+ children: error
6214
+ }), jsxRuntime.jsx(Description$1, {
6215
+ forId: id,
6216
+ element: element,
6217
+ value: description
6218
+ })]
6219
+ });
6220
+ }
6221
+ function isEdited$6(node) {
6222
+ return node && !!node.value;
6223
+ }
6224
+
6225
+ // helpers /////////////////
6226
+
6227
+ function prefixId$5(id) {
6228
+ return `bio-properties-panel-${id}`;
6229
+ }
6230
+ const noop$1 = () => {};
6231
+ function FeelTextfield(props) {
6232
+ const {
6233
+ debounce,
6234
+ id,
6235
+ label,
6236
+ onInput,
6237
+ onError,
6238
+ feel,
6239
+ value = '',
6240
+ disabled = false,
6241
+ variables,
6242
+ tooltipContainer,
6243
+ OptionalComponent = OptionalFeelInput
6244
+ } = props;
6245
+ const [localValue, _setLocalValue] = hooks.useState(value);
6246
+ const editorRef = useShowEntryEvent(id);
6247
+ const containerRef = hooks.useRef();
6248
+ const feelActive = minDash.isString(localValue) && localValue.startsWith('=') || feel === 'required';
6249
+ const feelOnlyValue = minDash.isString(localValue) && localValue.startsWith('=') ? localValue.substring(1) : localValue;
6250
+ const [focus, _setFocus] = hooks.useState(undefined);
6251
+ const setFocus = (offset = 0) => {
6252
+ const hasFocus = containerRef.current.contains(document.activeElement);
6253
+
6254
+ // Keep caret position if it is already focused, otherwise focus at the end
6255
+ const position = hasFocus ? document.activeElement.selectionStart : Infinity;
6256
+ _setFocus(position + offset);
6257
+ };
6258
+ const handleInputCallback = hooks.useMemo(() => {
6259
+ return debounce(newValue => {
6260
+ onInput(newValue);
6261
+ });
6262
+ }, [onInput, debounce]);
6263
+ const setLocalValue = newValue => {
6264
+ _setLocalValue(newValue);
6265
+ if (!newValue || newValue === '=') {
6266
+ handleInputCallback(undefined);
6267
+ } else {
6268
+ handleInputCallback(newValue);
6269
+ }
6270
+ };
6271
+ const handleFeelToggle = useStaticCallback(() => {
6272
+ if (feel === 'required') {
6273
+ return;
6274
+ }
6275
+ if (!feelActive) {
6276
+ setLocalValue('=' + localValue);
6277
+ } else {
6278
+ setLocalValue(feelOnlyValue);
6279
+ }
6280
+ });
6281
+ const handleLocalInput = newValue => {
6282
+ if (feelActive) {
6283
+ newValue = '=' + newValue;
6284
+ }
6285
+ if (newValue === localValue) {
6286
+ return;
6287
+ }
6288
+ setLocalValue(newValue);
6289
+ if (!feelActive && minDash.isString(newValue) && newValue.startsWith('=')) {
6290
+ // focus is behind `=` sign that will be removed
6291
+ setFocus(-1);
6292
+ }
6293
+ };
6294
+ const handleLint = useStaticCallback(lint => {
6295
+ if (!(lint && lint.length)) {
6296
+ onError(undefined);
6297
+ return;
6298
+ }
6299
+ const error = lint[0];
6300
+ const message = `${error.source}: ${error.message}`;
6301
+ onError(message);
6302
+ });
6303
+ hooks.useEffect(() => {
6304
+ if (typeof focus !== 'undefined') {
6305
+ editorRef.current.focus(focus);
6306
+ _setFocus(undefined);
6307
+ }
6308
+ }, [focus]);
6309
+ hooks.useEffect(() => {
6310
+ if (value === localValue) {
6311
+ return;
6312
+ }
6313
+
6314
+ // External value change removed content => keep FEEL configuration
6315
+ if (!value) {
6316
+ setLocalValue(feelActive ? '=' : '');
6317
+ return;
6318
+ }
6319
+ setLocalValue(value);
6320
+ }, [value]);
6321
+
6322
+ // copy-paste integration
6323
+ hooks.useEffect(() => {
6324
+ const copyHandler = event => {
6325
+ if (!feelActive) {
6326
+ return;
6327
+ }
6328
+ event.clipboardData.setData('application/FEEL', event.clipboardData.getData('text'));
6329
+ };
6330
+ const pasteHandler = event => {
6331
+ if (feelActive) {
6332
+ return;
6333
+ }
6334
+ const data = event.clipboardData.getData('application/FEEL');
6335
+ if (data) {
6336
+ setTimeout(() => {
6337
+ handleFeelToggle();
6338
+ setFocus();
6339
+ });
6340
+ }
6341
+ };
6342
+ containerRef.current.addEventListener('copy', copyHandler);
6343
+ containerRef.current.addEventListener('cut', copyHandler);
6344
+ containerRef.current.addEventListener('paste', pasteHandler);
6345
+ return () => {
6346
+ containerRef.current.removeEventListener('copy', copyHandler);
6347
+ containerRef.current.removeEventListener('cut', copyHandler);
6348
+ containerRef.current.removeEventListener('paste', pasteHandler);
6349
+ };
6350
+ }, [containerRef, feelActive, handleFeelToggle, setFocus]);
6351
+ return jsxRuntime.jsxs("div", {
6352
+ class: classnames('bio-properties-panel-feel-entry', {
6353
+ 'feel-active': feelActive
6354
+ }),
6355
+ children: [jsxRuntime.jsxs("label", {
6356
+ for: prefixId$4(id),
6357
+ class: "bio-properties-panel-label",
6358
+ onClick: () => setFocus(),
6359
+ children: [label, jsxRuntime.jsx(FeelIcon, {
6360
+ label: label,
6361
+ feel: feel,
6362
+ onClick: handleFeelToggle,
6363
+ active: feelActive
6120
6364
  })]
6121
6365
  }), jsxRuntime.jsxs("div", {
6122
6366
  class: "bio-properties-panel-feel-container",
@@ -6126,7 +6370,7 @@ function FeelTextfield(props) {
6126
6370
  disabled: feel !== 'optional' || disabled,
6127
6371
  onClick: handleFeelToggle
6128
6372
  }), feelActive ? jsxRuntime.jsx(CodeEditor, {
6129
- id: prefixId$5(id),
6373
+ id: prefixId$4(id),
6130
6374
  name: id,
6131
6375
  onInput: handleLocalInput,
6132
6376
  disabled: disabled,
@@ -6143,7 +6387,7 @@ function FeelTextfield(props) {
6143
6387
  ...props,
6144
6388
  onInput: handleLocalInput,
6145
6389
  contentAttributes: {
6146
- 'id': prefixId$5(id),
6390
+ 'id': prefixId$4(id),
6147
6391
  'aria-label': label
6148
6392
  },
6149
6393
  value: localValue,
@@ -6181,7 +6425,7 @@ const OptionalFeelInput = React.forwardRef((props, ref) => {
6181
6425
  }
6182
6426
  };
6183
6427
  return jsxRuntime.jsx("input", {
6184
- id: prefixId$5(id),
6428
+ id: prefixId$4(id),
6185
6429
  type: "text",
6186
6430
  ref: inputRef,
6187
6431
  name: id,
@@ -6195,6 +6439,53 @@ const OptionalFeelInput = React.forwardRef((props, ref) => {
6195
6439
  value: value || ''
6196
6440
  });
6197
6441
  });
6442
+ const OptionalFeelNumberField = React.forwardRef((props, ref) => {
6443
+ const {
6444
+ id,
6445
+ debounce,
6446
+ disabled,
6447
+ onInput,
6448
+ value,
6449
+ min,
6450
+ max,
6451
+ step,
6452
+ onFocus,
6453
+ onBlur
6454
+ } = props;
6455
+ const inputRef = hooks.useRef();
6456
+
6457
+ // To be consistent with the FEEL editor, set focus at start of input
6458
+ // this ensures clean editing experience when switching with the keyboard
6459
+ ref.current = {
6460
+ focus: position => {
6461
+ const input = inputRef.current;
6462
+ if (!input) {
6463
+ return;
6464
+ }
6465
+ input.focus();
6466
+ if (typeof position === 'number' && position !== Infinity) {
6467
+ if (position > value.length) {
6468
+ position = value.length;
6469
+ }
6470
+ input.setSelectionRange(position, position);
6471
+ }
6472
+ }
6473
+ };
6474
+ return jsxRuntime.jsx(NumberField, {
6475
+ id: id,
6476
+ debounce: debounce,
6477
+ disabled: disabled,
6478
+ displayLabel: false,
6479
+ inputRef: inputRef,
6480
+ max: max,
6481
+ min: min,
6482
+ onInput: onInput,
6483
+ step: step,
6484
+ value: value,
6485
+ onFocus: onFocus,
6486
+ onBlur: onBlur
6487
+ });
6488
+ });
6198
6489
  React.forwardRef((props, ref) => {
6199
6490
  const {
6200
6491
  id,
@@ -6219,7 +6510,7 @@ React.forwardRef((props, ref) => {
6219
6510
  }
6220
6511
  };
6221
6512
  return jsxRuntime.jsx("textarea", {
6222
- id: prefixId$5(id),
6513
+ id: prefixId$4(id),
6223
6514
  type: "text",
6224
6515
  ref: inputRef,
6225
6516
  name: id,
@@ -6295,7 +6586,7 @@ React.forwardRef((props, ref) => {
6295
6586
  };
6296
6587
  return jsxRuntime.jsx("input", {
6297
6588
  ref: inputRef,
6298
- id: prefixId$5(id),
6589
+ id: prefixId$4(id),
6299
6590
  name: id,
6300
6591
  onFocus: onFocus,
6301
6592
  onBlur: onBlur,
@@ -6347,11 +6638,9 @@ function FeelEntry(props) {
6347
6638
  onFocus,
6348
6639
  onBlur
6349
6640
  } = props;
6350
- const [cachedInvalidValue, setCachedInvalidValue] = hooks.useState(null);
6351
6641
  const [validationError, setValidationError] = hooks.useState(null);
6352
6642
  const [localError, setLocalError] = hooks.useState(null);
6353
6643
  let value = getValue(element);
6354
- const previousValue = usePrevious(value);
6355
6644
  hooks.useEffect(() => {
6356
6645
  if (minDash.isFunction(validate)) {
6357
6646
  const newValidationError = validate(value) || null;
@@ -6363,32 +6652,28 @@ function FeelEntry(props) {
6363
6652
  if (minDash.isFunction(validate)) {
6364
6653
  newValidationError = validate(newValue) || null;
6365
6654
  }
6366
- if (newValidationError) {
6367
- setCachedInvalidValue(newValue);
6368
- } else {
6369
- // don't create multiple commandStack entries for the same value
6370
- if (newValue !== value) {
6371
- setValue(newValue);
6372
- }
6655
+
6656
+ // don't create multiple commandStack entries for the same value
6657
+ if (newValue !== value) {
6658
+ setValue(newValue, newValidationError);
6373
6659
  }
6374
6660
  setValidationError(newValidationError);
6375
6661
  });
6376
6662
  const onError = hooks.useCallback(err => {
6377
6663
  setLocalError(err);
6378
6664
  }, []);
6379
- if (previousValue === value && validationError) {
6380
- value = cachedInvalidValue;
6381
- }
6382
6665
  const temporaryError = useError(id);
6383
6666
  const error = localError || temporaryError || validationError;
6384
6667
  return jsxRuntime.jsxs("div", {
6385
6668
  class: classnames(props.class, 'bio-properties-panel-entry', error ? 'has-error' : ''),
6386
6669
  "data-entry-id": id,
6387
- children: [jsxRuntime.jsx(FeelTextfield, {
6670
+ children: [preact.createElement(FeelTextfield, {
6671
+ ...props,
6388
6672
  debounce: debounce,
6389
6673
  disabled: disabled,
6390
6674
  feel: feel,
6391
6675
  id: id,
6676
+ key: element,
6392
6677
  label: label,
6393
6678
  onInput: onInput,
6394
6679
  onError: onError,
@@ -6402,7 +6687,7 @@ function FeelEntry(props) {
6402
6687
  variables: variables,
6403
6688
  tooltipContainer: tooltipContainer,
6404
6689
  OptionalComponent: props.OptionalComponent
6405
- }, element), error && jsxRuntime.jsx("div", {
6690
+ }), error && jsxRuntime.jsx("div", {
6406
6691
  class: "bio-properties-panel-error",
6407
6692
  children: error
6408
6693
  }), jsxRuntime.jsx(Description$1, {
@@ -6413,6 +6698,36 @@ function FeelEntry(props) {
6413
6698
  });
6414
6699
  }
6415
6700
 
6701
+ /**
6702
+ * @param {Object} props
6703
+ * @param {Object} props.element
6704
+ * @param {String} props.id
6705
+ * @param {String} props.description
6706
+ * @param {Boolean} props.debounce
6707
+ * @param {Boolean} props.disabled
6708
+ * @param {String} props.max
6709
+ * @param {String} props.min
6710
+ * @param {String} props.step
6711
+ * @param {Boolean} props.feel
6712
+ * @param {String} props.label
6713
+ * @param {Function} props.getValue
6714
+ * @param {Function} props.setValue
6715
+ * @param {Function} props.tooltipContainer
6716
+ * @param {Function} props.validate
6717
+ * @param {Function} props.show
6718
+ * @param {Function} props.example
6719
+ * @param {Function} props.variables
6720
+ * @param {Function} props.onFocus
6721
+ * @param {Function} props.onBlur
6722
+ */
6723
+ function FeelNumberEntry(props) {
6724
+ return jsxRuntime.jsx(FeelEntry, {
6725
+ class: "bio-properties-panel-feel-number",
6726
+ OptionalComponent: OptionalFeelNumberField,
6727
+ ...props
6728
+ });
6729
+ }
6730
+
6416
6731
  /**
6417
6732
  * @param {Object} props
6418
6733
  * @param {Object} props.element
@@ -6468,7 +6783,7 @@ function FeelTemplatingEntry(props) {
6468
6783
  ...props
6469
6784
  });
6470
6785
  }
6471
- function isEdited$6(node) {
6786
+ function isEdited$5(node) {
6472
6787
  if (!node) {
6473
6788
  return false;
6474
6789
  }
@@ -6480,162 +6795,6 @@ function isEdited$6(node) {
6480
6795
 
6481
6796
  // helpers /////////////////
6482
6797
 
6483
- function prefixId$5(id) {
6484
- return `bio-properties-panel-${id}`;
6485
- }
6486
- function NumberField(props) {
6487
- const {
6488
- debounce,
6489
- disabled,
6490
- id,
6491
- label,
6492
- max,
6493
- min,
6494
- onInput,
6495
- step,
6496
- value = '',
6497
- onFocus,
6498
- onBlur
6499
- } = props;
6500
- const [localValue, setLocalValue] = hooks.useState(value);
6501
- const handleInputCallback = hooks.useMemo(() => {
6502
- return debounce(event => {
6503
- const {
6504
- validity,
6505
- value
6506
- } = event.target;
6507
- if (validity.valid) {
6508
- onInput(value ? parseFloat(value) : undefined);
6509
- }
6510
- });
6511
- }, [onInput, debounce]);
6512
- const handleInput = e => {
6513
- handleInputCallback(e);
6514
- setLocalValue(e.target.value);
6515
- };
6516
- hooks.useEffect(() => {
6517
- if (value === localValue) {
6518
- return;
6519
- }
6520
- setLocalValue(value);
6521
- }, [value]);
6522
- return jsxRuntime.jsxs("div", {
6523
- class: "bio-properties-panel-numberfield",
6524
- children: [jsxRuntime.jsx("label", {
6525
- for: prefixId$4(id),
6526
- class: "bio-properties-panel-label",
6527
- children: label
6528
- }), jsxRuntime.jsx("input", {
6529
- id: prefixId$4(id),
6530
- type: "number",
6531
- name: id,
6532
- spellCheck: "false",
6533
- autoComplete: "off",
6534
- disabled: disabled,
6535
- class: "bio-properties-panel-input",
6536
- max: max,
6537
- min: min,
6538
- onInput: handleInput,
6539
- onFocus: onFocus,
6540
- onBlur: onBlur,
6541
- step: step,
6542
- value: localValue
6543
- })]
6544
- });
6545
- }
6546
-
6547
- /**
6548
- * @param {Object} props
6549
- * @param {Boolean} props.debounce
6550
- * @param {String} props.description
6551
- * @param {Boolean} props.disabled
6552
- * @param {Object} props.element
6553
- * @param {Function} props.getValue
6554
- * @param {String} props.id
6555
- * @param {String} props.label
6556
- * @param {String} props.max
6557
- * @param {String} props.min
6558
- * @param {Function} props.setValue
6559
- * @param {Function} props.onFocus
6560
- * @param {Function} props.onBlur
6561
- * @param {String} props.step
6562
- * @param {Function} props.validate
6563
- */
6564
- function NumberFieldEntry(props) {
6565
- const {
6566
- debounce,
6567
- description,
6568
- disabled,
6569
- element,
6570
- getValue,
6571
- id,
6572
- label,
6573
- max,
6574
- min,
6575
- setValue,
6576
- step,
6577
- onFocus,
6578
- onBlur,
6579
- validate
6580
- } = props;
6581
- const [cachedInvalidValue, setCachedInvalidValue] = hooks.useState(null);
6582
- const globalError = useError(id);
6583
- const [localError, setLocalError] = hooks.useState(null);
6584
- let value = getValue(element);
6585
- const previousValue = usePrevious(value);
6586
- hooks.useEffect(() => {
6587
- if (minDash.isFunction(validate)) {
6588
- const newValidationError = validate(value) || null;
6589
- setLocalError(newValidationError);
6590
- }
6591
- }, [value]);
6592
- const onInput = newValue => {
6593
- let newValidationError = null;
6594
- if (minDash.isFunction(validate)) {
6595
- newValidationError = validate(newValue) || null;
6596
- }
6597
- if (newValidationError) {
6598
- setCachedInvalidValue(newValue);
6599
- } else {
6600
- setValue(newValue);
6601
- }
6602
- setLocalError(newValidationError);
6603
- };
6604
- if (previousValue === value && localError) {
6605
- value = cachedInvalidValue;
6606
- }
6607
- const error = globalError || localError;
6608
- return jsxRuntime.jsxs("div", {
6609
- class: classnames('bio-properties-panel-entry', error ? 'has-error' : ''),
6610
- "data-entry-id": id,
6611
- children: [jsxRuntime.jsx(NumberField, {
6612
- debounce: debounce,
6613
- disabled: disabled,
6614
- id: id,
6615
- label: label,
6616
- onFocus: onFocus,
6617
- onBlur: onBlur,
6618
- onInput: onInput,
6619
- max: max,
6620
- min: min,
6621
- step: step,
6622
- value: value
6623
- }, element), error && jsxRuntime.jsx("div", {
6624
- class: "bio-properties-panel-error",
6625
- children: error
6626
- }), jsxRuntime.jsx(Description$1, {
6627
- forId: id,
6628
- element: element,
6629
- value: description
6630
- })]
6631
- });
6632
- }
6633
- function isEdited$4(node) {
6634
- return node && !!node.value;
6635
- }
6636
-
6637
- // helpers /////////////////
6638
-
6639
6798
  function prefixId$4(id) {
6640
6799
  return `bio-properties-panel-${id}`;
6641
6800
  }
@@ -6733,11 +6892,9 @@ function SelectEntry(props) {
6733
6892
  validate
6734
6893
  } = props;
6735
6894
  const options = getOptions(element);
6736
- const [cachedInvalidValue, setCachedInvalidValue] = hooks.useState(null);
6737
6895
  const globalError = useError(id);
6738
6896
  const [localError, setLocalError] = hooks.useState(null);
6739
6897
  let value = getValue(element);
6740
- const previousValue = usePrevious(value);
6741
6898
  hooks.useEffect(() => {
6742
6899
  if (minDash.isFunction(validate)) {
6743
6900
  const newValidationError = validate(value) || null;
@@ -6749,16 +6906,9 @@ function SelectEntry(props) {
6749
6906
  if (minDash.isFunction(validate)) {
6750
6907
  newValidationError = validate(newValue) || null;
6751
6908
  }
6752
- if (newValidationError) {
6753
- setCachedInvalidValue(newValue);
6754
- } else {
6755
- setValue(newValue);
6756
- }
6909
+ setValue(newValue, newValidationError);
6757
6910
  setLocalError(newValidationError);
6758
6911
  };
6759
- if (previousValue === value && localError) {
6760
- value = cachedInvalidValue;
6761
- }
6762
6912
  const error = globalError || localError;
6763
6913
  return jsxRuntime.jsxs("div", {
6764
6914
  class: classnames('bio-properties-panel-entry', error ? 'has-error' : ''),
@@ -6889,11 +7039,9 @@ function TextAreaEntry(props) {
6889
7039
  onBlur,
6890
7040
  autoResize
6891
7041
  } = props;
6892
- const [cachedInvalidValue, setCachedInvalidValue] = hooks.useState(null);
6893
7042
  const globalError = useError(id);
6894
7043
  const [localError, setLocalError] = hooks.useState(null);
6895
7044
  let value = getValue(element);
6896
- const previousValue = usePrevious(value);
6897
7045
  hooks.useEffect(() => {
6898
7046
  if (minDash.isFunction(validate)) {
6899
7047
  const newValidationError = validate(value) || null;
@@ -6905,16 +7053,9 @@ function TextAreaEntry(props) {
6905
7053
  if (minDash.isFunction(validate)) {
6906
7054
  newValidationError = validate(newValue) || null;
6907
7055
  }
6908
- if (newValidationError) {
6909
- setCachedInvalidValue(newValue);
6910
- } else {
6911
- setValue(newValue);
6912
- }
7056
+ setValue(newValue, newValidationError);
6913
7057
  setLocalError(newValidationError);
6914
7058
  };
6915
- if (previousValue === value && localError) {
6916
- value = cachedInvalidValue;
6917
- }
6918
7059
  const error = globalError || localError;
6919
7060
  return jsxRuntime.jsxs("div", {
6920
7061
  class: classnames('bio-properties-panel-entry', error ? 'has-error' : ''),
@@ -7029,11 +7170,9 @@ function TextfieldEntry(props) {
7029
7170
  onFocus,
7030
7171
  onBlur
7031
7172
  } = props;
7032
- const [cachedInvalidValue, setCachedInvalidValue] = hooks.useState(null);
7033
7173
  const globalError = useError(id);
7034
7174
  const [localError, setLocalError] = hooks.useState(null);
7035
7175
  let value = getValue(element);
7036
- const previousValue = usePrevious(value);
7037
7176
  hooks.useEffect(() => {
7038
7177
  if (minDash.isFunction(validate)) {
7039
7178
  const newValidationError = validate(value) || null;
@@ -7045,16 +7184,9 @@ function TextfieldEntry(props) {
7045
7184
  if (minDash.isFunction(validate)) {
7046
7185
  newValidationError = validate(newValue) || null;
7047
7186
  }
7048
- if (newValidationError) {
7049
- setCachedInvalidValue(newValue);
7050
- } else {
7051
- setValue(newValue);
7052
- }
7187
+ setValue(newValue, newValidationError);
7053
7188
  setLocalError(newValidationError);
7054
7189
  };
7055
- if (previousValue === value && localError) {
7056
- value = cachedInvalidValue;
7057
- }
7058
7190
  const error = globalError || localError;
7059
7191
  return jsxRuntime.jsxs("div", {
7060
7192
  class: classnames('bio-properties-panel-entry', error ? 'has-error' : ''),
@@ -7087,12 +7219,12 @@ function isEdited(node) {
7087
7219
  function prefixId(id) {
7088
7220
  return `bio-properties-panel-${id}`;
7089
7221
  }
7090
-
7091
- /**
7092
- * @param {string} type
7093
- * @param {boolean} [strict]
7094
- *
7095
- * @returns {any}
7222
+
7223
+ /**
7224
+ * @param {string} type
7225
+ * @param {boolean} [strict]
7226
+ *
7227
+ * @returns {any}
7096
7228
  */
7097
7229
  function getService(type, strict) {}
7098
7230
  const PropertiesPanelContext = preact.createContext({
@@ -7139,6 +7271,7 @@ const labelsByType = {
7139
7271
  number: 'NUMBER',
7140
7272
  radio: 'RADIO',
7141
7273
  select: 'SELECT',
7274
+ spacer: 'SPACER',
7142
7275
  taglist: 'TAGLIST',
7143
7276
  text: 'TEXT VIEW',
7144
7277
  textfield: 'TEXT FIELD',
@@ -7181,8 +7314,8 @@ const PropertiesPanelHeaderProvider = {
7181
7314
  }
7182
7315
  };
7183
7316
 
7184
- /**
7185
- * Provide placeholders for empty and multiple state.
7317
+ /**
7318
+ * Provide placeholders for empty and multiple state.
7186
7319
  */
7187
7320
  const PropertiesPanelPlaceholderProvider = {
7188
7321
  getEmpty: () => {
@@ -7254,10 +7387,10 @@ function useService (type, strict) {
7254
7387
  return getService(type, strict);
7255
7388
  }
7256
7389
 
7257
- /**
7258
- * Retrieve list of variables from the form schema.
7259
- *
7260
- * @returns { string[] } list of variables used in form schema
7390
+ /**
7391
+ * Retrieve list of variables from the form schema.
7392
+ *
7393
+ * @returns { string[] } list of variables used in form schema
7261
7394
  */
7262
7395
  function useVariables() {
7263
7396
  const form = useService('formEditor');
@@ -7280,7 +7413,7 @@ function AltTextEntry(props) {
7280
7413
  component: AltText,
7281
7414
  editField: editField,
7282
7415
  field: field,
7283
- isEdited: isEdited$6
7416
+ isEdited: isEdited$5
7284
7417
  });
7285
7418
  }
7286
7419
  return entries;
@@ -7302,7 +7435,7 @@ function AltText(props) {
7302
7435
  const setValue = value => {
7303
7436
  return editField(field, path, value);
7304
7437
  };
7305
- return FeelEntry({
7438
+ return FeelTemplatingEntry({
7306
7439
  debounce,
7307
7440
  element: field,
7308
7441
  feel: 'optional',
@@ -7310,6 +7443,7 @@ function AltText(props) {
7310
7443
  id,
7311
7444
  label: 'Alternative text',
7312
7445
  setValue,
7446
+ singleLine: true,
7313
7447
  variables
7314
7448
  });
7315
7449
  }
@@ -7340,7 +7474,10 @@ function Columns(props) {
7340
7474
  const validate = value => {
7341
7475
  return formLayoutValidator.validateField(field, value ? parseInt(value) : null);
7342
7476
  };
7343
- const setValue = value => {
7477
+ const setValue = (value, error) => {
7478
+ if (error) {
7479
+ return;
7480
+ }
7344
7481
  const layout = minDash.get(field, ['layout'], {});
7345
7482
  const newValue = value ? parseInt(value) : null;
7346
7483
  editField(field, ['layout'], minDash.set(layout, ['columns'], newValue));
@@ -7398,7 +7535,7 @@ function DescriptionEntry(props) {
7398
7535
  component: Description,
7399
7536
  editField: editField,
7400
7537
  field: field,
7401
- isEdited: isEdited$6
7538
+ isEdited: isEdited$5
7402
7539
  });
7403
7540
  }
7404
7541
  return entries;
@@ -7548,7 +7685,10 @@ function DefaultValueNumber(props) {
7548
7685
  // Enforces decimal notation so that we do not submit defaults in exponent form
7549
7686
  return serializeToString ? Big(value).toFixed() : value;
7550
7687
  };
7551
- const setValue = value => {
7688
+ const setValue = (value, error) => {
7689
+ if (error) {
7690
+ return;
7691
+ }
7552
7692
  let newValue;
7553
7693
  if (isValidNumber(value)) {
7554
7694
  newValue = serializeToString ? value : Number(value);
@@ -7739,7 +7879,10 @@ function Id(props) {
7739
7879
  const getValue = () => {
7740
7880
  return minDash.get(field, path, '');
7741
7881
  };
7742
- const setValue = value => {
7882
+ const setValue = (value, error) => {
7883
+ if (error) {
7884
+ return;
7885
+ }
7743
7886
  return editField(field, path, value);
7744
7887
  };
7745
7888
  const validate = value => {
@@ -7819,7 +7962,10 @@ function Key$1(props) {
7819
7962
  const getValue = () => {
7820
7963
  return minDash.get(field, path, '');
7821
7964
  };
7822
- const setValue = value => {
7965
+ const setValue = (value, error) => {
7966
+ if (error) {
7967
+ return;
7968
+ }
7823
7969
  return editField(field, path, value);
7824
7970
  };
7825
7971
  const validate = value => {
@@ -7864,7 +8010,7 @@ function LabelEntry(props) {
7864
8010
  component: DateLabel,
7865
8011
  editField,
7866
8012
  field,
7867
- isEdited: isEdited$6
8013
+ isEdited: isEdited$5
7868
8014
  });
7869
8015
  }
7870
8016
  if (subtype === formJsViewer.DATETIME_SUBTYPES.TIME || subtype === formJsViewer.DATETIME_SUBTYPES.DATETIME) {
@@ -7873,7 +8019,7 @@ function LabelEntry(props) {
7873
8019
  component: TimeLabel,
7874
8020
  editField,
7875
8021
  field,
7876
- isEdited: isEdited$6
8022
+ isEdited: isEdited$5
7877
8023
  });
7878
8024
  }
7879
8025
  } else if (INPUTS.includes(type) || type === 'button') {
@@ -7882,7 +8028,7 @@ function LabelEntry(props) {
7882
8028
  component: Label$1,
7883
8029
  editField,
7884
8030
  field,
7885
- isEdited: isEdited$6
8031
+ isEdited: isEdited$5
7886
8032
  });
7887
8033
  }
7888
8034
  return entries;
@@ -7987,7 +8133,7 @@ function SourceEntry(props) {
7987
8133
  component: Source,
7988
8134
  editField: editField,
7989
8135
  field: field,
7990
- isEdited: isEdited$6
8136
+ isEdited: isEdited$5
7991
8137
  });
7992
8138
  }
7993
8139
  return entries;
@@ -8009,7 +8155,7 @@ function Source(props) {
8009
8155
  const setValue = value => {
8010
8156
  return editField(field, path, value);
8011
8157
  };
8012
- return FeelEntry({
8158
+ return FeelTemplatingEntry({
8013
8159
  debounce,
8014
8160
  description: 'Expression or static value (link/data URI)',
8015
8161
  element: field,
@@ -8018,6 +8164,7 @@ function Source(props) {
8018
8164
  id,
8019
8165
  label: 'Image source',
8020
8166
  setValue,
8167
+ singleLine: true,
8021
8168
  variables
8022
8169
  });
8023
8170
  }
@@ -8042,7 +8189,7 @@ function TextEntry(props) {
8042
8189
  component: Text,
8043
8190
  editField: editField,
8044
8191
  field: field,
8045
- isEdited: isEdited$6
8192
+ isEdited: isEdited$5
8046
8193
  }];
8047
8194
 
8048
8195
  // todo: skipped to make the release without too much risk
@@ -8073,7 +8220,7 @@ function Text(props) {
8073
8220
  return minDash.get(field, path, '');
8074
8221
  };
8075
8222
  const setValue = value => {
8076
- return editField(field, path, value);
8223
+ return editField(field, path, value || '');
8077
8224
  };
8078
8225
  const description = hooks.useMemo(() => jsxRuntime.jsxs(jsxRuntime.Fragment, {
8079
8226
  children: ["Supports markdown and templating. ", jsxRuntime.jsx("a", {
@@ -8095,6 +8242,57 @@ function Text(props) {
8095
8242
  });
8096
8243
  }
8097
8244
 
8245
+ function SpacerEntry(props) {
8246
+ const {
8247
+ editField,
8248
+ field,
8249
+ id
8250
+ } = props;
8251
+ const {
8252
+ type
8253
+ } = field;
8254
+ if (type !== 'spacer') {
8255
+ return [];
8256
+ }
8257
+ const entries = [];
8258
+ entries.push({
8259
+ id: id + '-height',
8260
+ component: SpacerHeight,
8261
+ isEdited: isEdited$6,
8262
+ editField,
8263
+ field
8264
+ });
8265
+ return entries;
8266
+ }
8267
+ function SpacerHeight(props) {
8268
+ const {
8269
+ editField,
8270
+ field,
8271
+ id
8272
+ } = props;
8273
+ const debounce = useService('debounce');
8274
+ const getValue = e => minDash.get(field, ['height']);
8275
+ const setValue = (value, error) => {
8276
+ if (error) {
8277
+ return;
8278
+ }
8279
+ editField(field, ['height'], value);
8280
+ };
8281
+ return NumberFieldEntry({
8282
+ debounce,
8283
+ label: 'Height',
8284
+ element: field,
8285
+ id,
8286
+ getValue,
8287
+ setValue,
8288
+ validate: value => {
8289
+ if (value === undefined || value === null) return;
8290
+ if (value < 1) return 'Should be greater than zero.';
8291
+ if (!Number.isInteger(value)) return 'Should be an integer.';
8292
+ }
8293
+ });
8294
+ }
8295
+
8098
8296
  function NumberEntries(props) {
8099
8297
  const {
8100
8298
  editField,
@@ -8111,7 +8309,7 @@ function NumberEntries(props) {
8111
8309
  entries.push({
8112
8310
  id: id + '-decimalDigits',
8113
8311
  component: NumberDecimalDigits,
8114
- isEdited: isEdited$4,
8312
+ isEdited: isEdited$6,
8115
8313
  editField,
8116
8314
  field
8117
8315
  });
@@ -8132,7 +8330,12 @@ function NumberDecimalDigits(props) {
8132
8330
  } = props;
8133
8331
  const debounce = useService('debounce');
8134
8332
  const getValue = e => minDash.get(field, ['decimalDigits']);
8135
- const setValue = value => editField(field, ['decimalDigits'], value);
8333
+ const setValue = (value, error) => {
8334
+ if (error) {
8335
+ return;
8336
+ }
8337
+ editField(field, ['decimalDigits'], value);
8338
+ };
8136
8339
  return NumberFieldEntry({
8137
8340
  debounce,
8138
8341
  label: 'Decimal digits',
@@ -8168,7 +8371,12 @@ function NumberArrowStep(props) {
8168
8371
  const trimmed = value.replace(/^0+/g, '');
8169
8372
  return (trimmed.startsWith('.') ? '0' : '') + trimmed;
8170
8373
  };
8171
- const setValue = value => editField(field, ['increment'], clearLeadingZeroes(value));
8374
+ const setValue = (value, error) => {
8375
+ if (error) {
8376
+ return;
8377
+ }
8378
+ editField(field, ['increment'], clearLeadingZeroes(value));
8379
+ };
8172
8380
  const decimalDigitsSet = decimalDigits || decimalDigits === 0;
8173
8381
  return TextfieldEntry({
8174
8382
  debounce,
@@ -8577,7 +8785,10 @@ function Label(props) {
8577
8785
  validateFactory
8578
8786
  } = props;
8579
8787
  const debounce = useService('debounce');
8580
- const setValue = value => {
8788
+ const setValue = (value, error) => {
8789
+ if (error) {
8790
+ return;
8791
+ }
8581
8792
  const values = minDash.get(field, ['values']);
8582
8793
  return editField(field, 'values', minDash.set(values, [index, 'label'], value));
8583
8794
  };
@@ -8603,7 +8814,10 @@ function Value$1(props) {
8603
8814
  validateFactory
8604
8815
  } = props;
8605
8816
  const debounce = useService('debounce');
8606
- const setValue = value => {
8817
+ const setValue = (value, error) => {
8818
+ if (error) {
8819
+ return;
8820
+ }
8607
8821
  const values = minDash.get(field, ['values']);
8608
8822
  return editField(field, 'values', minDash.set(values, [index, 'value'], value));
8609
8823
  };
@@ -8657,7 +8871,10 @@ function Key(props) {
8657
8871
  validateFactory
8658
8872
  } = props;
8659
8873
  const debounce = useService('debounce');
8660
- const setValue = value => {
8874
+ const setValue = (value, error) => {
8875
+ if (error) {
8876
+ return;
8877
+ }
8661
8878
  const properties = minDash.get(field, ['properties']);
8662
8879
  const key = Object.keys(properties)[index];
8663
8880
  return editField(field, 'properties', updateKey(properties, key, value));
@@ -8707,14 +8924,14 @@ function Value(props) {
8707
8924
 
8708
8925
  // helpers //////////
8709
8926
 
8710
- /**
8711
- * Returns copy of object with updated value.
8712
- *
8713
- * @param {Object} properties
8714
- * @param {string} key
8715
- * @param {string} value
8716
- *
8717
- * @returns {Object}
8927
+ /**
8928
+ * Returns copy of object with updated value.
8929
+ *
8930
+ * @param {Object} properties
8931
+ * @param {string} key
8932
+ * @param {string} value
8933
+ *
8934
+ * @returns {Object}
8718
8935
  */
8719
8936
  function updateValue(properties, key, value) {
8720
8937
  return {
@@ -8723,14 +8940,14 @@ function updateValue(properties, key, value) {
8723
8940
  };
8724
8941
  }
8725
8942
 
8726
- /**
8727
- * Returns copy of object with updated key.
8728
- *
8729
- * @param {Object} properties
8730
- * @param {string} oldKey
8731
- * @param {string} newKey
8732
- *
8733
- * @returns {Object}
8943
+ /**
8944
+ * Returns copy of object with updated key.
8945
+ *
8946
+ * @param {Object} properties
8947
+ * @param {string} oldKey
8948
+ * @param {string} newKey
8949
+ *
8950
+ * @returns {Object}
8734
8951
  */
8735
8952
  function updateKey(properties, oldKey, newKey) {
8736
8953
  return Object.entries(properties).reduce((newProperties, entry) => {
@@ -8742,6 +8959,34 @@ function updateKey(properties, oldKey, newKey) {
8742
8959
  }, {});
8743
8960
  }
8744
8961
 
8962
+ function AutoFocusSelectEntry(props) {
8963
+ const {
8964
+ autoFocusEntry,
8965
+ element,
8966
+ getValue
8967
+ } = props;
8968
+ const value = getValue(element);
8969
+ const prevValue = usePrevious(value);
8970
+ const eventBus = useService('eventBus');
8971
+
8972
+ // auto focus specifc other entry when selected value changed
8973
+ hooks.useEffect(() => {
8974
+ if (autoFocusEntry && prevValue && value !== prevValue) {
8975
+ // @Note(pinussilvestrus): There is an issue in the properties
8976
+ // panel so we have to wait a bit before showing the entry.
8977
+ // Cf. https://github.com/camunda/linting/blob/4f5328e2722f73ae60ae584c5f576eaec3999cb2/lib/modeler/Linting.js#L37
8978
+ setTimeout(() => {
8979
+ eventBus.fire('propertiesPanel.showEntry', {
8980
+ id: autoFocusEntry
8981
+ });
8982
+ });
8983
+ }
8984
+ }, [value, autoFocusEntry, prevValue, eventBus]);
8985
+ return jsxRuntime.jsx(SelectEntry, {
8986
+ ...props
8987
+ });
8988
+ }
8989
+
8745
8990
  function ValuesSourceSelectEntry(props) {
8746
8991
  const {
8747
8992
  editField,
@@ -8780,7 +9025,8 @@ function ValuesSourceSelect(props) {
8780
9025
  value: valueSource
8781
9026
  }));
8782
9027
  };
8783
- return SelectEntry({
9028
+ return AutoFocusSelectEntry({
9029
+ autoFocusEntry: getAutoFocusEntryId(field),
8784
9030
  label: 'Type',
8785
9031
  element: field,
8786
9032
  getOptions: getValuesSourceOptions,
@@ -8790,6 +9036,20 @@ function ValuesSourceSelect(props) {
8790
9036
  });
8791
9037
  }
8792
9038
 
9039
+ // helpers //////////
9040
+
9041
+ function getAutoFocusEntryId(field) {
9042
+ const valuesSource = formJsViewer.getValuesSource(field);
9043
+ if (valuesSource === formJsViewer.VALUES_SOURCES.EXPRESSION) {
9044
+ return `${field.id}-valuesExpression-expression`;
9045
+ } else if (valuesSource === formJsViewer.VALUES_SOURCES.INPUT) {
9046
+ return `${field.id}-dynamicValues-key`;
9047
+ } else if (valuesSource === formJsViewer.VALUES_SOURCES.STATIC) {
9048
+ return `${field.id}-staticValues-0-label`;
9049
+ }
9050
+ return null;
9051
+ }
9052
+
8793
9053
  function InputKeyValuesSourceEntry(props) {
8794
9054
  const {
8795
9055
  editField,
@@ -8825,7 +9085,12 @@ function InputValuesKey(props) {
8825
9085
  const debounce = useService('debounce');
8826
9086
  const path = formJsViewer.VALUES_SOURCES_PATHS[formJsViewer.VALUES_SOURCES.INPUT];
8827
9087
  const getValue = () => minDash.get(field, path, '');
8828
- const setValue = value => editField(field, path, value || '');
9088
+ const setValue = (value, error) => {
9089
+ if (error) {
9090
+ return;
9091
+ }
9092
+ editField(field, path, value || '');
9093
+ };
8829
9094
  const validate = value => {
8830
9095
  if (minDash.isUndefined(value) || !value.length) {
8831
9096
  return 'Must not be empty.';
@@ -8946,7 +9211,7 @@ function AdornerEntry(props) {
8946
9211
  entries.push({
8947
9212
  id: 'prefix-adorner',
8948
9213
  component: PrefixAdorner,
8949
- isEdited: isEdited,
9214
+ isEdited: isEdited$5,
8950
9215
  editField,
8951
9216
  field,
8952
9217
  onChange,
@@ -8955,7 +9220,7 @@ function AdornerEntry(props) {
8955
9220
  entries.push({
8956
9221
  id: 'suffix-adorner',
8957
9222
  component: SuffixAdorner,
8958
- isEdited: isEdited,
9223
+ isEdited: isEdited$5,
8959
9224
  editField,
8960
9225
  field,
8961
9226
  onChange,
@@ -8972,13 +9237,19 @@ function PrefixAdorner(props) {
8972
9237
  getValue
8973
9238
  } = props;
8974
9239
  const debounce = useService('debounce');
8975
- return TextfieldEntry({
9240
+ const variables = useVariables().map(name => ({
9241
+ name
9242
+ }));
9243
+ return FeelTemplatingEntry({
8976
9244
  debounce,
8977
9245
  element: field,
9246
+ feel: 'optional',
8978
9247
  getValue: getValue('prefixAdorner'),
8979
9248
  id,
8980
9249
  label: 'Prefix',
8981
- setValue: onChange('prefixAdorner')
9250
+ setValue: onChange('prefixAdorner'),
9251
+ singleLine: true,
9252
+ variables
8982
9253
  });
8983
9254
  }
8984
9255
  function SuffixAdorner(props) {
@@ -8989,13 +9260,18 @@ function SuffixAdorner(props) {
8989
9260
  getValue
8990
9261
  } = props;
8991
9262
  const debounce = useService('debounce');
8992
- return TextfieldEntry({
9263
+ const variables = useVariables().map(name => ({
9264
+ name
9265
+ }));
9266
+ return FeelTemplatingEntry({
8993
9267
  debounce,
8994
9268
  element: field,
8995
9269
  getValue: getValue('suffixAdorner'),
8996
9270
  id,
8997
9271
  label: 'Suffix',
8998
- setValue: onChange('suffixAdorner')
9272
+ setValue: onChange('suffixAdorner'),
9273
+ singleLine: true,
9274
+ variables
8999
9275
  });
9000
9276
  }
9001
9277
 
@@ -9014,7 +9290,7 @@ function ReadonlyEntry(props) {
9014
9290
  component: Readonly,
9015
9291
  editField: editField,
9016
9292
  field: field,
9017
- isEdited: isEdited$6
9293
+ isEdited: isEdited$5
9018
9294
  });
9019
9295
  }
9020
9296
  return entries;
@@ -9058,7 +9334,7 @@ function ConditionEntry(props) {
9058
9334
  component: Condition,
9059
9335
  editField: editField,
9060
9336
  field: field,
9061
- isEdited: isEdited$6
9337
+ isEdited: isEdited$5
9062
9338
  }];
9063
9339
  }
9064
9340
  function Condition(props) {
@@ -9096,6 +9372,55 @@ function Condition(props) {
9096
9372
  });
9097
9373
  }
9098
9374
 
9375
+ function ValuesExpressionEntry(props) {
9376
+ const {
9377
+ editField,
9378
+ field,
9379
+ id
9380
+ } = props;
9381
+ return [{
9382
+ id: id + '-expression',
9383
+ component: ValuesExpression,
9384
+ label: 'Values expression',
9385
+ isEdited: isEdited$5,
9386
+ editField,
9387
+ field
9388
+ }];
9389
+ }
9390
+ function ValuesExpression(props) {
9391
+ const {
9392
+ editField,
9393
+ field,
9394
+ id
9395
+ } = props;
9396
+ const debounce = useService('debounce');
9397
+ const variables = useVariables().map(name => ({
9398
+ name
9399
+ }));
9400
+ const path = formJsViewer.VALUES_SOURCES_PATHS[formJsViewer.VALUES_SOURCES.EXPRESSION];
9401
+ const schema = '[\n {\n "label": "dollar",\n "value": "$"\n }\n]';
9402
+ const description = jsxRuntime.jsxs("div", {
9403
+ children: ["Define an expression to populate the options from.", jsxRuntime.jsx("br", {}), jsxRuntime.jsx("br", {}), "The expression may result in an array of simple values or alternatively follow this schema:", jsxRuntime.jsx("pre", {
9404
+ children: jsxRuntime.jsx("code", {
9405
+ children: schema
9406
+ })
9407
+ })]
9408
+ });
9409
+ const getValue = () => minDash.get(field, path, '');
9410
+ const setValue = value => editField(field, path, value || '');
9411
+ return FeelEntry({
9412
+ debounce,
9413
+ description,
9414
+ element: field,
9415
+ feel: 'required',
9416
+ getValue,
9417
+ id,
9418
+ label: 'Options expression',
9419
+ setValue,
9420
+ variables
9421
+ });
9422
+ }
9423
+
9099
9424
  function GeneralGroup(field, editField, getService) {
9100
9425
  const entries = [...IdEntry({
9101
9426
  field,
@@ -9122,6 +9447,9 @@ function GeneralGroup(field, editField, getService) {
9122
9447
  field,
9123
9448
  editField,
9124
9449
  getService
9450
+ }), ...SpacerEntry({
9451
+ field,
9452
+ editField
9125
9453
  }), ...NumberEntries({
9126
9454
  field,
9127
9455
  editField
@@ -9240,14 +9568,14 @@ function ValidationGroup(field, editField) {
9240
9568
  component: MinLength,
9241
9569
  getValue,
9242
9570
  field,
9243
- isEdited: isEdited$4,
9571
+ isEdited: isEdited$5,
9244
9572
  onChange
9245
9573
  }, {
9246
9574
  id: 'maxLength',
9247
9575
  component: MaxLength,
9248
9576
  getValue,
9249
9577
  field,
9250
- isEdited: isEdited$4,
9578
+ isEdited: isEdited$5,
9251
9579
  onChange
9252
9580
  });
9253
9581
  }
@@ -9267,14 +9595,14 @@ function ValidationGroup(field, editField) {
9267
9595
  component: Min,
9268
9596
  getValue,
9269
9597
  field,
9270
- isEdited: isEdited$4,
9598
+ isEdited: isEdited$5,
9271
9599
  onChange
9272
9600
  }, {
9273
9601
  id: 'max',
9274
9602
  component: Max,
9275
9603
  getValue,
9276
9604
  field,
9277
- isEdited: isEdited$4,
9605
+ isEdited: isEdited$5,
9278
9606
  onChange
9279
9607
  });
9280
9608
  }
@@ -9307,14 +9635,19 @@ function MinLength(props) {
9307
9635
  onChange
9308
9636
  } = props;
9309
9637
  const debounce = useService('debounce');
9310
- return NumberFieldEntry({
9638
+ const variables = useVariables().map(name => ({
9639
+ name
9640
+ }));
9641
+ return FeelNumberEntry({
9311
9642
  debounce,
9312
9643
  element: field,
9644
+ feel: 'optional',
9313
9645
  getValue: getValue('minLength'),
9314
9646
  id,
9315
9647
  label: 'Minimum length',
9316
9648
  min: 0,
9317
- setValue: onChange('minLength')
9649
+ setValue: onChange('minLength'),
9650
+ variables
9318
9651
  });
9319
9652
  }
9320
9653
  function MaxLength(props) {
@@ -9325,14 +9658,19 @@ function MaxLength(props) {
9325
9658
  onChange
9326
9659
  } = props;
9327
9660
  const debounce = useService('debounce');
9328
- return NumberFieldEntry({
9661
+ const variables = useVariables().map(name => ({
9662
+ name
9663
+ }));
9664
+ return FeelNumberEntry({
9329
9665
  debounce,
9330
9666
  element: field,
9667
+ feel: 'optional',
9331
9668
  getValue: getValue('maxLength'),
9332
9669
  id,
9333
9670
  label: 'Maximum length',
9334
9671
  min: 0,
9335
- setValue: onChange('maxLength')
9672
+ setValue: onChange('maxLength'),
9673
+ variables
9336
9674
  });
9337
9675
  }
9338
9676
  function Pattern(props) {
@@ -9360,14 +9698,19 @@ function Min(props) {
9360
9698
  onChange
9361
9699
  } = props;
9362
9700
  const debounce = useService('debounce');
9363
- return NumberFieldEntry({
9701
+ const variables = useVariables().map(name => ({
9702
+ name
9703
+ }));
9704
+ return FeelNumberEntry({
9364
9705
  debounce,
9365
9706
  element: field,
9707
+ feel: 'optional',
9366
9708
  id,
9367
9709
  label: 'Minimum',
9368
9710
  step: 'any',
9369
9711
  getValue: getValue('min'),
9370
- setValue: onChange('min')
9712
+ setValue: onChange('min'),
9713
+ variables
9371
9714
  });
9372
9715
  }
9373
9716
  function Max(props) {
@@ -9378,14 +9721,19 @@ function Max(props) {
9378
9721
  onChange
9379
9722
  } = props;
9380
9723
  const debounce = useService('debounce');
9381
- return NumberFieldEntry({
9724
+ const variables = useVariables().map(name => ({
9725
+ name
9726
+ }));
9727
+ return FeelNumberEntry({
9382
9728
  debounce,
9383
9729
  element: field,
9730
+ feel: 'optional',
9384
9731
  id,
9385
9732
  label: 'Maximum',
9386
9733
  step: 'any',
9387
9734
  getValue: getValue('max'),
9388
- setValue: onChange('max')
9735
+ setValue: onChange('max'),
9736
+ variables
9389
9737
  });
9390
9738
  }
9391
9739
  function ValidationType(props) {
@@ -9424,8 +9772,8 @@ function ValuesGroups(field, editField) {
9424
9772
  };
9425
9773
  const valuesSourceId = `${fieldId}-valuesSource`;
9426
9774
 
9427
- /**
9428
- * @type {Array<Group|ListGroup>}
9775
+ /**
9776
+ * @type {Array<Group|ListGroup>}
9429
9777
  */
9430
9778
  const groups = [{
9431
9779
  id: valuesSourceId,
@@ -9459,6 +9807,17 @@ function ValuesGroups(field, editField) {
9459
9807
  id: staticValuesId
9460
9808
  })
9461
9809
  });
9810
+ } else if (valuesSource === formJsViewer.VALUES_SOURCES.EXPRESSION) {
9811
+ const valuesExpressionId = `${fieldId}-valuesExpression`;
9812
+ groups.push({
9813
+ id: valuesExpressionId,
9814
+ label: 'Options expression',
9815
+ component: Group,
9816
+ entries: ValuesExpressionEntry({
9817
+ ...context,
9818
+ id: valuesExpressionId
9819
+ })
9820
+ });
9462
9821
  }
9463
9822
  return groups;
9464
9823
  }
@@ -9527,13 +9886,13 @@ function CustomValuesGroup(field, editField) {
9527
9886
 
9528
9887
  // helpers //////////
9529
9888
 
9530
- /**
9531
- * Returns copy of object without key.
9532
- *
9533
- * @param {Object} properties
9534
- * @param {string} oldKey
9535
- *
9536
- * @returns {Object}
9889
+ /**
9890
+ * Returns copy of object without key.
9891
+ *
9892
+ * @param {Object} properties
9893
+ * @param {string} oldKey
9894
+ *
9895
+ * @returns {Object}
9537
9896
  */
9538
9897
  function removeKey(properties, oldKey) {
9539
9898
  return Object.entries(properties).reduce((newProperties, entry) => {
@@ -9636,9 +9995,9 @@ function FormPropertiesPanel(props) {
9636
9995
  });
9637
9996
  }, [eventBus, formEditor, selectionModule]);
9638
9997
  hooks.useLayoutEffect(() => {
9639
- /**
9640
- * TODO(pinussilvestrus): update with actual updated element,
9641
- * once we have a proper updater/change support
9998
+ /**
9999
+ * TODO(pinussilvestrus): update with actual updated element,
10000
+ * once we have a proper updater/change support
9642
10001
  */
9643
10002
  eventBus.on('changed', refresh);
9644
10003
  eventBus.on('import.done', refresh);
@@ -9690,10 +10049,10 @@ class PropertiesPanelRenderer {
9690
10049
  });
9691
10050
  }
9692
10051
 
9693
- /**
9694
- * Attach the properties panel to a parent node.
9695
- *
9696
- * @param {HTMLElement} container
10052
+ /**
10053
+ * Attach the properties panel to a parent node.
10054
+ *
10055
+ * @param {HTMLElement} container
9697
10056
  */
9698
10057
  attachTo(container) {
9699
10058
  if (!container) {
@@ -9713,8 +10072,8 @@ class PropertiesPanelRenderer {
9713
10072
  this._eventBus.fire('propertiesPanel.attach');
9714
10073
  }
9715
10074
 
9716
- /**
9717
- * Detach the properties panel from its parent node.
10075
+ /**
10076
+ * Detach the properties panel from its parent node.
9718
10077
  */
9719
10078
  detach() {
9720
10079
  const parentNode = this._container.parentNode;
@@ -9744,10 +10103,10 @@ var PropertiesPanelModule = {
9744
10103
  propertiesPanel: ['type', PropertiesPanelRenderer]
9745
10104
  };
9746
10105
 
9747
- /**
9748
- * Manages the rendering of visual plugins.
9749
- * @constructor
9750
- * @param {Object} eventBus - Event bus for the application.
10106
+ /**
10107
+ * Manages the rendering of visual plugins.
10108
+ * @constructor
10109
+ * @param {Object} eventBus - Event bus for the application.
9751
10110
  */
9752
10111
  class RenderInjector extends SectionModuleBase {
9753
10112
  constructor(eventBus) {
@@ -9756,10 +10115,10 @@ class RenderInjector extends SectionModuleBase {
9756
10115
  this.registeredRenderers = [];
9757
10116
  }
9758
10117
 
9759
- /**
9760
- * Inject a new renderer into the injector.
9761
- * @param {string} identifier - Identifier for the renderer.
9762
- * @param {Function} Renderer - The renderer function.
10118
+ /**
10119
+ * Inject a new renderer into the injector.
10120
+ * @param {string} identifier - Identifier for the renderer.
10121
+ * @param {Function} Renderer - The renderer function.
9763
10122
  */
9764
10123
  attachRenderer(identifier, Renderer) {
9765
10124
  this.registeredRenderers = [...this.registeredRenderers, {
@@ -9768,17 +10127,17 @@ class RenderInjector extends SectionModuleBase {
9768
10127
  }];
9769
10128
  }
9770
10129
 
9771
- /**
9772
- * Detach a renderer from the by key injector.
9773
- * @param {string} identifier - Identifier for the renderer.
10130
+ /**
10131
+ * Detach a renderer from the by key injector.
10132
+ * @param {string} identifier - Identifier for the renderer.
9774
10133
  */
9775
10134
  detachRenderer(identifier) {
9776
10135
  this.registeredRenderers = this.registeredRenderers.filter(r => r.identifier !== identifier);
9777
10136
  }
9778
10137
 
9779
- /**
9780
- * Returns the registered renderers.
9781
- * @returns {Array} Array of registered renderers.
10138
+ /**
10139
+ * Returns the registered renderers.
10140
+ * @returns {Array} Array of registered renderers.
9782
10141
  */
9783
10142
  fetchRenderers() {
9784
10143
  return this.registeredRenderers;
@@ -9812,48 +10171,48 @@ var ExpressionLanguageModule = {
9812
10171
 
9813
10172
  const ids = new Ids([32, 36, 1]);
9814
10173
 
9815
- /**
9816
- * @typedef { import('./types').Injector } Injector
9817
- * @typedef { import('./types').Module } Module
9818
- * @typedef { import('./types').Schema } Schema
9819
- *
9820
- * @typedef { import('./types').FormEditorOptions } FormEditorOptions
9821
- * @typedef { import('./types').FormEditorProperties } FormEditorProperties
9822
- *
9823
- * @typedef { {
9824
- * properties: FormEditorProperties,
9825
- * schema: Schema
9826
- * } } State
9827
- *
9828
- * @typedef { (type:string, priority:number, handler:Function) => void } OnEventWithPriority
9829
- * @typedef { (type:string, handler:Function) => void } OnEventWithOutPriority
9830
- * @typedef { OnEventWithPriority & OnEventWithOutPriority } OnEventType
10174
+ /**
10175
+ * @typedef { import('./types').Injector } Injector
10176
+ * @typedef { import('./types').Module } Module
10177
+ * @typedef { import('./types').Schema } Schema
10178
+ *
10179
+ * @typedef { import('./types').FormEditorOptions } FormEditorOptions
10180
+ * @typedef { import('./types').FormEditorProperties } FormEditorProperties
10181
+ *
10182
+ * @typedef { {
10183
+ * properties: FormEditorProperties,
10184
+ * schema: Schema
10185
+ * } } State
10186
+ *
10187
+ * @typedef { (type:string, priority:number, handler:Function) => void } OnEventWithPriority
10188
+ * @typedef { (type:string, handler:Function) => void } OnEventWithOutPriority
10189
+ * @typedef { OnEventWithPriority & OnEventWithOutPriority } OnEventType
9831
10190
  */
9832
10191
 
9833
- /**
9834
- * The form editor.
10192
+ /**
10193
+ * The form editor.
9835
10194
  */
9836
10195
  class FormEditor {
9837
- /**
9838
- * @constructor
9839
- * @param {FormEditorOptions} options
10196
+ /**
10197
+ * @constructor
10198
+ * @param {FormEditorOptions} options
9840
10199
  */
9841
10200
  constructor(options = {}) {
9842
- /**
9843
- * @public
9844
- * @type {OnEventType}
10201
+ /**
10202
+ * @public
10203
+ * @type {OnEventType}
9845
10204
  */
9846
10205
  this.on = this._onEvent;
9847
10206
 
9848
- /**
9849
- * @public
9850
- * @type {String}
10207
+ /**
10208
+ * @public
10209
+ * @type {String}
9851
10210
  */
9852
10211
  this._id = ids.next();
9853
10212
 
9854
- /**
9855
- * @private
9856
- * @type {Element}
10213
+ /**
10214
+ * @private
10215
+ * @type {Element}
9857
10216
  */
9858
10217
  this._container = formJsViewer.createFormContainer();
9859
10218
  this._container.setAttribute('input-handle-modified-keys', 'z,y');
@@ -9864,15 +10223,15 @@ class FormEditor {
9864
10223
  properties = {}
9865
10224
  } = options;
9866
10225
 
9867
- /**
9868
- * @private
9869
- * @type {any}
10226
+ /**
10227
+ * @private
10228
+ * @type {any}
9870
10229
  */
9871
10230
  this.exporter = exporter;
9872
10231
 
9873
- /**
9874
- * @private
9875
- * @type {State}
10232
+ /**
10233
+ * @private
10234
+ * @type {State}
9876
10235
  */
9877
10236
  this._state = {
9878
10237
  properties,
@@ -9901,10 +10260,10 @@ class FormEditor {
9901
10260
  this._detach(false);
9902
10261
  }
9903
10262
 
9904
- /**
9905
- * @param {Schema} schema
9906
- *
9907
- * @return {Promise<{ warnings: Array<any> }>}
10263
+ /**
10264
+ * @param {Schema} schema
10265
+ *
10266
+ * @return {Promise<{ warnings: Array<any> }>}
9908
10267
  */
9909
10268
  importSchema(schema) {
9910
10269
  return new Promise((resolve, reject) => {
@@ -9933,15 +10292,15 @@ class FormEditor {
9933
10292
  });
9934
10293
  }
9935
10294
 
9936
- /**
9937
- * @returns {Schema}
10295
+ /**
10296
+ * @returns {Schema}
9938
10297
  */
9939
10298
  saveSchema() {
9940
10299
  return this.getSchema();
9941
10300
  }
9942
10301
 
9943
- /**
9944
- * @returns {Schema}
10302
+ /**
10303
+ * @returns {Schema}
9945
10304
  */
9946
10305
  getSchema() {
9947
10306
  const {
@@ -9950,8 +10309,8 @@ class FormEditor {
9950
10309
  return exportSchema(schema, this.exporter, formJsViewer.schemaVersion);
9951
10310
  }
9952
10311
 
9953
- /**
9954
- * @param {Element|string} parentNode
10312
+ /**
10313
+ * @param {Element|string} parentNode
9955
10314
  */
9956
10315
  attachTo(parentNode) {
9957
10316
  if (!parentNode) {
@@ -9969,10 +10328,10 @@ class FormEditor {
9969
10328
  this._detach();
9970
10329
  }
9971
10330
 
9972
- /**
9973
- * @internal
9974
- *
9975
- * @param {boolean} [emit]
10331
+ /**
10332
+ * @internal
10333
+ *
10334
+ * @param {boolean} [emit]
9976
10335
  */
9977
10336
  _detach(emit = true) {
9978
10337
  const container = this._container,
@@ -9986,9 +10345,9 @@ class FormEditor {
9986
10345
  parentNode.removeChild(container);
9987
10346
  }
9988
10347
 
9989
- /**
9990
- * @param {any} property
9991
- * @param {any} value
10348
+ /**
10349
+ * @param {any} property
10350
+ * @param {any} value
9992
10351
  */
9993
10352
  setProperty(property, value) {
9994
10353
  const properties = minDash.set(this._getState().properties, [property], value);
@@ -9997,21 +10356,21 @@ class FormEditor {
9997
10356
  });
9998
10357
  }
9999
10358
 
10000
- /**
10001
- * @param {string} type
10002
- * @param {Function} handler
10359
+ /**
10360
+ * @param {string} type
10361
+ * @param {Function} handler
10003
10362
  */
10004
10363
  off(type, handler) {
10005
10364
  this.get('eventBus').off(type, handler);
10006
10365
  }
10007
10366
 
10008
- /**
10009
- * @internal
10010
- *
10011
- * @param {FormEditorOptions} options
10012
- * @param {Element} container
10013
- *
10014
- * @returns {Injector}
10367
+ /**
10368
+ * @internal
10369
+ *
10370
+ * @param {FormEditorOptions} options
10371
+ * @param {Element} container
10372
+ *
10373
+ * @returns {Injector}
10015
10374
  */
10016
10375
  _createInjector(options, container) {
10017
10376
  const {
@@ -10033,22 +10392,22 @@ class FormEditor {
10033
10392
  }, core, ...modules, ...additionalModules]);
10034
10393
  }
10035
10394
 
10036
- /**
10037
- * @internal
10395
+ /**
10396
+ * @internal
10038
10397
  */
10039
10398
  _emit(type, data) {
10040
10399
  this.get('eventBus').fire(type, data);
10041
10400
  }
10042
10401
 
10043
- /**
10044
- * @internal
10402
+ /**
10403
+ * @internal
10045
10404
  */
10046
10405
  _getState() {
10047
10406
  return this._state;
10048
10407
  }
10049
10408
 
10050
- /**
10051
- * @internal
10409
+ /**
10410
+ * @internal
10052
10411
  */
10053
10412
  _setState(state) {
10054
10413
  this._state = {
@@ -10058,15 +10417,15 @@ class FormEditor {
10058
10417
  this._emit('changed', this._getState());
10059
10418
  }
10060
10419
 
10061
- /**
10062
- * @internal
10420
+ /**
10421
+ * @internal
10063
10422
  */
10064
10423
  _getModules() {
10065
10424
  return [ModelingModule, EditorActionsModule, DraggingModule, KeyboardModule, SelectionModule, PaletteModule, ExpressionLanguageModule, formJsViewer.MarkdownModule, PropertiesPanelModule, RenderInjectionModule];
10066
10425
  }
10067
10426
 
10068
- /**
10069
- * @internal
10427
+ /**
10428
+ * @internal
10070
10429
  */
10071
10430
  _onEvent(type, priority, handler) {
10072
10431
  this.get('eventBus').on(type, priority, handler);