@bpmn-io/form-js-editor 1.0.0-alpha.8 → 1.0.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;
@@ -934,83 +953,91 @@ function useService$1 (type, strict) {
934
953
  return getService(type, strict);
935
954
  }
936
955
 
956
+ var _path$3;
937
957
  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
- })));
958
+ var SvgClose = function SvgClose(props) {
959
+ return /*#__PURE__*/React__namespace.createElement("svg", _extends$3({
960
+ xmlns: "http://www.w3.org/2000/svg",
961
+ width: 16,
962
+ height: 16,
963
+ fill: "currentColor"
964
+ }, props), _path$3 || (_path$3 = /*#__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;
951
971
 
972
+ var _path$2, _path2;
952
973
  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
- })));
974
+ var SvgDelete = function SvgDelete(props) {
975
+ return /*#__PURE__*/React__namespace.createElement("svg", _extends$2({
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$2 || (_path$2 = /*#__PURE__*/React__namespace.createElement("path", {
997
+ fill: "currentcolor",
998
+ d: "M7.536 6h-1v6h1V6Zm3 0h-1v6h1V6Z"
999
+ })), _path2 || (_path2 = /*#__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;
983
1005
 
1006
+ var _path$1;
984
1007
  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
- })));
1008
+ var SvgDraggable = function SvgDraggable(props) {
1009
+ return /*#__PURE__*/React__namespace.createElement("svg", _extends$1({
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$1 || (_path$1 = /*#__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;
1000
1026
 
1027
+ var _path;
1001
1028
  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
- })));
1029
+ var SvgSearch = function SvgSearch(props) {
1030
+ return /*#__PURE__*/React__namespace.createElement("svg", _extends({
1031
+ xmlns: "http://www.w3.org/2000/svg",
1032
+ width: 15,
1033
+ height: 15,
1034
+ fill: "none"
1035
+ }, props), _path || (_path = /*#__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;
1014
1041
 
1015
1042
  function EditorText(props) {
1016
1043
  const {
@@ -5983,6 +6010,165 @@ function isEdited$7(node) {
5983
6010
  function prefixId$6(id) {
5984
6011
  return `bio-properties-panel-${id}`;
5985
6012
  }
6013
+ function NumberField(props) {
6014
+ const {
6015
+ debounce,
6016
+ disabled,
6017
+ displayLabel = true,
6018
+ id,
6019
+ inputRef,
6020
+ label,
6021
+ max,
6022
+ min,
6023
+ onInput,
6024
+ step,
6025
+ value = '',
6026
+ onFocus,
6027
+ onBlur
6028
+ } = props;
6029
+ const [localValue, setLocalValue] = hooks.useState(value);
6030
+ const handleInputCallback = hooks.useMemo(() => {
6031
+ return debounce(event => {
6032
+ const {
6033
+ validity,
6034
+ value
6035
+ } = event.target;
6036
+ if (validity.valid) {
6037
+ onInput(value ? parseFloat(value) : undefined);
6038
+ }
6039
+ });
6040
+ }, [onInput, debounce]);
6041
+ const handleInput = e => {
6042
+ handleInputCallback(e);
6043
+ setLocalValue(e.target.value);
6044
+ };
6045
+ hooks.useEffect(() => {
6046
+ if (value === localValue) {
6047
+ return;
6048
+ }
6049
+ setLocalValue(value);
6050
+ }, [value]);
6051
+ return jsxRuntime.jsxs("div", {
6052
+ class: "bio-properties-panel-numberfield",
6053
+ children: [displayLabel && jsxRuntime.jsx("label", {
6054
+ for: prefixId$5(id),
6055
+ class: "bio-properties-panel-label",
6056
+ children: label
6057
+ }), jsxRuntime.jsx("input", {
6058
+ id: prefixId$5(id),
6059
+ ref: inputRef,
6060
+ type: "number",
6061
+ name: id,
6062
+ spellCheck: "false",
6063
+ autoComplete: "off",
6064
+ disabled: disabled,
6065
+ class: "bio-properties-panel-input",
6066
+ max: max,
6067
+ min: min,
6068
+ onInput: handleInput,
6069
+ onFocus: onFocus,
6070
+ onBlur: onBlur,
6071
+ step: step,
6072
+ value: localValue
6073
+ })]
6074
+ });
6075
+ }
6076
+
6077
+ /**
6078
+ * @param {Object} props
6079
+ * @param {Boolean} props.debounce
6080
+ * @param {String} props.description
6081
+ * @param {Boolean} props.disabled
6082
+ * @param {Object} props.element
6083
+ * @param {Function} props.getValue
6084
+ * @param {String} props.id
6085
+ * @param {String} props.label
6086
+ * @param {String} props.max
6087
+ * @param {String} props.min
6088
+ * @param {Function} props.setValue
6089
+ * @param {Function} props.onFocus
6090
+ * @param {Function} props.onBlur
6091
+ * @param {String} props.step
6092
+ * @param {Function} props.validate
6093
+ */
6094
+ function NumberFieldEntry(props) {
6095
+ const {
6096
+ debounce,
6097
+ description,
6098
+ disabled,
6099
+ element,
6100
+ getValue,
6101
+ id,
6102
+ label,
6103
+ max,
6104
+ min,
6105
+ setValue,
6106
+ step,
6107
+ onFocus,
6108
+ onBlur,
6109
+ validate
6110
+ } = props;
6111
+ const [cachedInvalidValue, setCachedInvalidValue] = hooks.useState(null);
6112
+ const globalError = useError(id);
6113
+ const [localError, setLocalError] = hooks.useState(null);
6114
+ let value = getValue(element);
6115
+ const previousValue = usePrevious(value);
6116
+ hooks.useEffect(() => {
6117
+ if (minDash.isFunction(validate)) {
6118
+ const newValidationError = validate(value) || null;
6119
+ setLocalError(newValidationError);
6120
+ }
6121
+ }, [value]);
6122
+ const onInput = newValue => {
6123
+ let newValidationError = null;
6124
+ if (minDash.isFunction(validate)) {
6125
+ newValidationError = validate(newValue) || null;
6126
+ }
6127
+ if (newValidationError) {
6128
+ setCachedInvalidValue(newValue);
6129
+ } else {
6130
+ setValue(newValue);
6131
+ }
6132
+ setLocalError(newValidationError);
6133
+ };
6134
+ if (previousValue === value && localError) {
6135
+ value = cachedInvalidValue;
6136
+ }
6137
+ const error = globalError || localError;
6138
+ return jsxRuntime.jsxs("div", {
6139
+ class: classnames('bio-properties-panel-entry', error ? 'has-error' : ''),
6140
+ "data-entry-id": id,
6141
+ children: [jsxRuntime.jsx(NumberField, {
6142
+ debounce: debounce,
6143
+ disabled: disabled,
6144
+ id: id,
6145
+ label: label,
6146
+ onFocus: onFocus,
6147
+ onBlur: onBlur,
6148
+ onInput: onInput,
6149
+ max: max,
6150
+ min: min,
6151
+ step: step,
6152
+ value: value
6153
+ }, element), error && jsxRuntime.jsx("div", {
6154
+ class: "bio-properties-panel-error",
6155
+ children: error
6156
+ }), jsxRuntime.jsx(Description$1, {
6157
+ forId: id,
6158
+ element: element,
6159
+ value: description
6160
+ })]
6161
+ });
6162
+ }
6163
+ function isEdited$6(node) {
6164
+ return node && !!node.value;
6165
+ }
6166
+
6167
+ // helpers /////////////////
6168
+
6169
+ function prefixId$5(id) {
6170
+ return `bio-properties-panel-${id}`;
6171
+ }
5986
6172
  const noop$1 = () => {};
5987
6173
  function FeelTextfield(props) {
5988
6174
  const {
@@ -6109,7 +6295,7 @@ function FeelTextfield(props) {
6109
6295
  'feel-active': feelActive
6110
6296
  }),
6111
6297
  children: [jsxRuntime.jsxs("label", {
6112
- for: prefixId$5(id),
6298
+ for: prefixId$4(id),
6113
6299
  class: "bio-properties-panel-label",
6114
6300
  onClick: () => setFocus(),
6115
6301
  children: [label, jsxRuntime.jsx(FeelIcon, {
@@ -6126,7 +6312,7 @@ function FeelTextfield(props) {
6126
6312
  disabled: feel !== 'optional' || disabled,
6127
6313
  onClick: handleFeelToggle
6128
6314
  }), feelActive ? jsxRuntime.jsx(CodeEditor, {
6129
- id: prefixId$5(id),
6315
+ id: prefixId$4(id),
6130
6316
  name: id,
6131
6317
  onInput: handleLocalInput,
6132
6318
  disabled: disabled,
@@ -6143,7 +6329,7 @@ function FeelTextfield(props) {
6143
6329
  ...props,
6144
6330
  onInput: handleLocalInput,
6145
6331
  contentAttributes: {
6146
- 'id': prefixId$5(id),
6332
+ 'id': prefixId$4(id),
6147
6333
  'aria-label': label
6148
6334
  },
6149
6335
  value: localValue,
@@ -6181,7 +6367,7 @@ const OptionalFeelInput = React.forwardRef((props, ref) => {
6181
6367
  }
6182
6368
  };
6183
6369
  return jsxRuntime.jsx("input", {
6184
- id: prefixId$5(id),
6370
+ id: prefixId$4(id),
6185
6371
  type: "text",
6186
6372
  ref: inputRef,
6187
6373
  name: id,
@@ -6195,6 +6381,53 @@ const OptionalFeelInput = React.forwardRef((props, ref) => {
6195
6381
  value: value || ''
6196
6382
  });
6197
6383
  });
6384
+ const OptionalFeelNumberField = React.forwardRef((props, ref) => {
6385
+ const {
6386
+ id,
6387
+ debounce,
6388
+ disabled,
6389
+ onInput,
6390
+ value,
6391
+ min,
6392
+ max,
6393
+ step,
6394
+ onFocus,
6395
+ onBlur
6396
+ } = props;
6397
+ const inputRef = hooks.useRef();
6398
+
6399
+ // To be consistent with the FEEL editor, set focus at start of input
6400
+ // this ensures clean editing experience when switching with the keyboard
6401
+ ref.current = {
6402
+ focus: position => {
6403
+ const input = inputRef.current;
6404
+ if (!input) {
6405
+ return;
6406
+ }
6407
+ input.focus();
6408
+ if (typeof position === 'number' && position !== Infinity) {
6409
+ if (position > value.length) {
6410
+ position = value.length;
6411
+ }
6412
+ input.setSelectionRange(position, position);
6413
+ }
6414
+ }
6415
+ };
6416
+ return jsxRuntime.jsx(NumberField, {
6417
+ id: id,
6418
+ debounce: debounce,
6419
+ disabled: disabled,
6420
+ displayLabel: false,
6421
+ inputRef: inputRef,
6422
+ max: max,
6423
+ min: min,
6424
+ onInput: onInput,
6425
+ step: step,
6426
+ value: value,
6427
+ onFocus: onFocus,
6428
+ onBlur: onBlur
6429
+ });
6430
+ });
6198
6431
  React.forwardRef((props, ref) => {
6199
6432
  const {
6200
6433
  id,
@@ -6219,7 +6452,7 @@ React.forwardRef((props, ref) => {
6219
6452
  }
6220
6453
  };
6221
6454
  return jsxRuntime.jsx("textarea", {
6222
- id: prefixId$5(id),
6455
+ id: prefixId$4(id),
6223
6456
  type: "text",
6224
6457
  ref: inputRef,
6225
6458
  name: id,
@@ -6295,7 +6528,7 @@ React.forwardRef((props, ref) => {
6295
6528
  };
6296
6529
  return jsxRuntime.jsx("input", {
6297
6530
  ref: inputRef,
6298
- id: prefixId$5(id),
6531
+ id: prefixId$4(id),
6299
6532
  name: id,
6300
6533
  onFocus: onFocus,
6301
6534
  onBlur: onBlur,
@@ -6384,11 +6617,13 @@ function FeelEntry(props) {
6384
6617
  return jsxRuntime.jsxs("div", {
6385
6618
  class: classnames(props.class, 'bio-properties-panel-entry', error ? 'has-error' : ''),
6386
6619
  "data-entry-id": id,
6387
- children: [jsxRuntime.jsx(FeelTextfield, {
6620
+ children: [preact.createElement(FeelTextfield, {
6621
+ ...props,
6388
6622
  debounce: debounce,
6389
6623
  disabled: disabled,
6390
6624
  feel: feel,
6391
6625
  id: id,
6626
+ key: element,
6392
6627
  label: label,
6393
6628
  onInput: onInput,
6394
6629
  onError: onError,
@@ -6402,7 +6637,7 @@ function FeelEntry(props) {
6402
6637
  variables: variables,
6403
6638
  tooltipContainer: tooltipContainer,
6404
6639
  OptionalComponent: props.OptionalComponent
6405
- }, element), error && jsxRuntime.jsx("div", {
6640
+ }), error && jsxRuntime.jsx("div", {
6406
6641
  class: "bio-properties-panel-error",
6407
6642
  children: error
6408
6643
  }), jsxRuntime.jsx(Description$1, {
@@ -6413,6 +6648,36 @@ function FeelEntry(props) {
6413
6648
  });
6414
6649
  }
6415
6650
 
6651
+ /**
6652
+ * @param {Object} props
6653
+ * @param {Object} props.element
6654
+ * @param {String} props.id
6655
+ * @param {String} props.description
6656
+ * @param {Boolean} props.debounce
6657
+ * @param {Boolean} props.disabled
6658
+ * @param {String} props.max
6659
+ * @param {String} props.min
6660
+ * @param {String} props.step
6661
+ * @param {Boolean} props.feel
6662
+ * @param {String} props.label
6663
+ * @param {Function} props.getValue
6664
+ * @param {Function} props.setValue
6665
+ * @param {Function} props.tooltipContainer
6666
+ * @param {Function} props.validate
6667
+ * @param {Function} props.show
6668
+ * @param {Function} props.example
6669
+ * @param {Function} props.variables
6670
+ * @param {Function} props.onFocus
6671
+ * @param {Function} props.onBlur
6672
+ */
6673
+ function FeelNumberEntry(props) {
6674
+ return jsxRuntime.jsx(FeelEntry, {
6675
+ class: "bio-properties-panel-feel-number",
6676
+ OptionalComponent: OptionalFeelNumberField,
6677
+ ...props
6678
+ });
6679
+ }
6680
+
6416
6681
  /**
6417
6682
  * @param {Object} props
6418
6683
  * @param {Object} props.element
@@ -6468,7 +6733,7 @@ function FeelTemplatingEntry(props) {
6468
6733
  ...props
6469
6734
  });
6470
6735
  }
6471
- function isEdited$6(node) {
6736
+ function isEdited$5(node) {
6472
6737
  if (!node) {
6473
6738
  return false;
6474
6739
  }
@@ -6480,166 +6745,10 @@ function isEdited$6(node) {
6480
6745
 
6481
6746
  // helpers /////////////////
6482
6747
 
6483
- function prefixId$5(id) {
6748
+ function prefixId$4(id) {
6484
6749
  return `bio-properties-panel-${id}`;
6485
6750
  }
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
- function prefixId$4(id) {
6640
- return `bio-properties-panel-${id}`;
6641
- }
6642
- function Select(props) {
6751
+ function Select(props) {
6643
6752
  const {
6644
6753
  id,
6645
6754
  label,
@@ -7280,7 +7389,7 @@ function AltTextEntry(props) {
7280
7389
  component: AltText,
7281
7390
  editField: editField,
7282
7391
  field: field,
7283
- isEdited: isEdited$6
7392
+ isEdited: isEdited$5
7284
7393
  });
7285
7394
  }
7286
7395
  return entries;
@@ -7302,7 +7411,7 @@ function AltText(props) {
7302
7411
  const setValue = value => {
7303
7412
  return editField(field, path, value);
7304
7413
  };
7305
- return FeelEntry({
7414
+ return FeelTemplatingEntry({
7306
7415
  debounce,
7307
7416
  element: field,
7308
7417
  feel: 'optional',
@@ -7310,6 +7419,7 @@ function AltText(props) {
7310
7419
  id,
7311
7420
  label: 'Alternative text',
7312
7421
  setValue,
7422
+ singleLine: true,
7313
7423
  variables
7314
7424
  });
7315
7425
  }
@@ -7398,7 +7508,7 @@ function DescriptionEntry(props) {
7398
7508
  component: Description,
7399
7509
  editField: editField,
7400
7510
  field: field,
7401
- isEdited: isEdited$6
7511
+ isEdited: isEdited$5
7402
7512
  });
7403
7513
  }
7404
7514
  return entries;
@@ -7864,7 +7974,7 @@ function LabelEntry(props) {
7864
7974
  component: DateLabel,
7865
7975
  editField,
7866
7976
  field,
7867
- isEdited: isEdited$6
7977
+ isEdited: isEdited$5
7868
7978
  });
7869
7979
  }
7870
7980
  if (subtype === formJsViewer.DATETIME_SUBTYPES.TIME || subtype === formJsViewer.DATETIME_SUBTYPES.DATETIME) {
@@ -7873,7 +7983,7 @@ function LabelEntry(props) {
7873
7983
  component: TimeLabel,
7874
7984
  editField,
7875
7985
  field,
7876
- isEdited: isEdited$6
7986
+ isEdited: isEdited$5
7877
7987
  });
7878
7988
  }
7879
7989
  } else if (INPUTS.includes(type) || type === 'button') {
@@ -7882,7 +7992,7 @@ function LabelEntry(props) {
7882
7992
  component: Label$1,
7883
7993
  editField,
7884
7994
  field,
7885
- isEdited: isEdited$6
7995
+ isEdited: isEdited$5
7886
7996
  });
7887
7997
  }
7888
7998
  return entries;
@@ -7987,7 +8097,7 @@ function SourceEntry(props) {
7987
8097
  component: Source,
7988
8098
  editField: editField,
7989
8099
  field: field,
7990
- isEdited: isEdited$6
8100
+ isEdited: isEdited$5
7991
8101
  });
7992
8102
  }
7993
8103
  return entries;
@@ -8009,7 +8119,7 @@ function Source(props) {
8009
8119
  const setValue = value => {
8010
8120
  return editField(field, path, value);
8011
8121
  };
8012
- return FeelEntry({
8122
+ return FeelTemplatingEntry({
8013
8123
  debounce,
8014
8124
  description: 'Expression or static value (link/data URI)',
8015
8125
  element: field,
@@ -8018,6 +8128,7 @@ function Source(props) {
8018
8128
  id,
8019
8129
  label: 'Image source',
8020
8130
  setValue,
8131
+ singleLine: true,
8021
8132
  variables
8022
8133
  });
8023
8134
  }
@@ -8042,7 +8153,7 @@ function TextEntry(props) {
8042
8153
  component: Text,
8043
8154
  editField: editField,
8044
8155
  field: field,
8045
- isEdited: isEdited$6
8156
+ isEdited: isEdited$5
8046
8157
  }];
8047
8158
 
8048
8159
  // todo: skipped to make the release without too much risk
@@ -8111,7 +8222,7 @@ function NumberEntries(props) {
8111
8222
  entries.push({
8112
8223
  id: id + '-decimalDigits',
8113
8224
  component: NumberDecimalDigits,
8114
- isEdited: isEdited$4,
8225
+ isEdited: isEdited$6,
8115
8226
  editField,
8116
8227
  field
8117
8228
  });
@@ -8742,6 +8853,34 @@ function updateKey(properties, oldKey, newKey) {
8742
8853
  }, {});
8743
8854
  }
8744
8855
 
8856
+ function AutoFocusSelectEntry(props) {
8857
+ const {
8858
+ autoFocusEntry,
8859
+ element,
8860
+ getValue
8861
+ } = props;
8862
+ const value = getValue(element);
8863
+ const prevValue = usePrevious(value);
8864
+ const eventBus = useService('eventBus');
8865
+
8866
+ // auto focus specifc other entry when selected value changed
8867
+ hooks.useEffect(() => {
8868
+ if (autoFocusEntry && prevValue && value !== prevValue) {
8869
+ // @Note(pinussilvestrus): There is an issue in the properties
8870
+ // panel so we have to wait a bit before showing the entry.
8871
+ // Cf. https://github.com/camunda/linting/blob/4f5328e2722f73ae60ae584c5f576eaec3999cb2/lib/modeler/Linting.js#L37
8872
+ setTimeout(() => {
8873
+ eventBus.fire('propertiesPanel.showEntry', {
8874
+ id: autoFocusEntry
8875
+ });
8876
+ });
8877
+ }
8878
+ }, [value, autoFocusEntry, prevValue, eventBus]);
8879
+ return jsxRuntime.jsx(SelectEntry, {
8880
+ ...props
8881
+ });
8882
+ }
8883
+
8745
8884
  function ValuesSourceSelectEntry(props) {
8746
8885
  const {
8747
8886
  editField,
@@ -8780,7 +8919,8 @@ function ValuesSourceSelect(props) {
8780
8919
  value: valueSource
8781
8920
  }));
8782
8921
  };
8783
- return SelectEntry({
8922
+ return AutoFocusSelectEntry({
8923
+ autoFocusEntry: getAutoFocusEntryId(field),
8784
8924
  label: 'Type',
8785
8925
  element: field,
8786
8926
  getOptions: getValuesSourceOptions,
@@ -8790,6 +8930,20 @@ function ValuesSourceSelect(props) {
8790
8930
  });
8791
8931
  }
8792
8932
 
8933
+ // helpers //////////
8934
+
8935
+ function getAutoFocusEntryId(field) {
8936
+ const valuesSource = formJsViewer.getValuesSource(field);
8937
+ if (valuesSource === formJsViewer.VALUES_SOURCES.EXPRESSION) {
8938
+ return `${field.id}-valuesExpression-expression`;
8939
+ } else if (valuesSource === formJsViewer.VALUES_SOURCES.INPUT) {
8940
+ return `${field.id}-dynamicValues-key`;
8941
+ } else if (valuesSource === formJsViewer.VALUES_SOURCES.STATIC) {
8942
+ return `${field.id}-staticValues-0-label`;
8943
+ }
8944
+ return null;
8945
+ }
8946
+
8793
8947
  function InputKeyValuesSourceEntry(props) {
8794
8948
  const {
8795
8949
  editField,
@@ -8946,7 +9100,7 @@ function AdornerEntry(props) {
8946
9100
  entries.push({
8947
9101
  id: 'prefix-adorner',
8948
9102
  component: PrefixAdorner,
8949
- isEdited: isEdited,
9103
+ isEdited: isEdited$5,
8950
9104
  editField,
8951
9105
  field,
8952
9106
  onChange,
@@ -8955,7 +9109,7 @@ function AdornerEntry(props) {
8955
9109
  entries.push({
8956
9110
  id: 'suffix-adorner',
8957
9111
  component: SuffixAdorner,
8958
- isEdited: isEdited,
9112
+ isEdited: isEdited$5,
8959
9113
  editField,
8960
9114
  field,
8961
9115
  onChange,
@@ -8972,13 +9126,19 @@ function PrefixAdorner(props) {
8972
9126
  getValue
8973
9127
  } = props;
8974
9128
  const debounce = useService('debounce');
8975
- return TextfieldEntry({
9129
+ const variables = useVariables().map(name => ({
9130
+ name
9131
+ }));
9132
+ return FeelTemplatingEntry({
8976
9133
  debounce,
8977
9134
  element: field,
9135
+ feel: 'optional',
8978
9136
  getValue: getValue('prefixAdorner'),
8979
9137
  id,
8980
9138
  label: 'Prefix',
8981
- setValue: onChange('prefixAdorner')
9139
+ setValue: onChange('prefixAdorner'),
9140
+ singleLine: true,
9141
+ variables
8982
9142
  });
8983
9143
  }
8984
9144
  function SuffixAdorner(props) {
@@ -8989,13 +9149,18 @@ function SuffixAdorner(props) {
8989
9149
  getValue
8990
9150
  } = props;
8991
9151
  const debounce = useService('debounce');
8992
- return TextfieldEntry({
9152
+ const variables = useVariables().map(name => ({
9153
+ name
9154
+ }));
9155
+ return FeelTemplatingEntry({
8993
9156
  debounce,
8994
9157
  element: field,
8995
9158
  getValue: getValue('suffixAdorner'),
8996
9159
  id,
8997
9160
  label: 'Suffix',
8998
- setValue: onChange('suffixAdorner')
9161
+ setValue: onChange('suffixAdorner'),
9162
+ singleLine: true,
9163
+ variables
8999
9164
  });
9000
9165
  }
9001
9166
 
@@ -9014,7 +9179,7 @@ function ReadonlyEntry(props) {
9014
9179
  component: Readonly,
9015
9180
  editField: editField,
9016
9181
  field: field,
9017
- isEdited: isEdited$6
9182
+ isEdited: isEdited$5
9018
9183
  });
9019
9184
  }
9020
9185
  return entries;
@@ -9058,7 +9223,7 @@ function ConditionEntry(props) {
9058
9223
  component: Condition,
9059
9224
  editField: editField,
9060
9225
  field: field,
9061
- isEdited: isEdited$6
9226
+ isEdited: isEdited$5
9062
9227
  }];
9063
9228
  }
9064
9229
  function Condition(props) {
@@ -9096,6 +9261,55 @@ function Condition(props) {
9096
9261
  });
9097
9262
  }
9098
9263
 
9264
+ function ValuesExpressionEntry(props) {
9265
+ const {
9266
+ editField,
9267
+ field,
9268
+ id
9269
+ } = props;
9270
+ return [{
9271
+ id: id + '-expression',
9272
+ component: ValuesExpression,
9273
+ label: 'Values expression',
9274
+ isEdited: isEdited$5,
9275
+ editField,
9276
+ field
9277
+ }];
9278
+ }
9279
+ function ValuesExpression(props) {
9280
+ const {
9281
+ editField,
9282
+ field,
9283
+ id
9284
+ } = props;
9285
+ const debounce = useService('debounce');
9286
+ const variables = useVariables().map(name => ({
9287
+ name
9288
+ }));
9289
+ const path = formJsViewer.VALUES_SOURCES_PATHS[formJsViewer.VALUES_SOURCES.EXPRESSION];
9290
+ const schema = '[\n {\n "label": "dollar",\n "value": "$"\n }\n]';
9291
+ const description = jsxRuntime.jsxs("div", {
9292
+ 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", {
9293
+ children: jsxRuntime.jsx("code", {
9294
+ children: schema
9295
+ })
9296
+ })]
9297
+ });
9298
+ const getValue = () => minDash.get(field, path, '');
9299
+ const setValue = value => editField(field, path, value || '');
9300
+ return FeelEntry({
9301
+ debounce,
9302
+ description,
9303
+ element: field,
9304
+ feel: 'required',
9305
+ getValue,
9306
+ id,
9307
+ label: 'Options expression',
9308
+ setValue,
9309
+ variables
9310
+ });
9311
+ }
9312
+
9099
9313
  function GeneralGroup(field, editField, getService) {
9100
9314
  const entries = [...IdEntry({
9101
9315
  field,
@@ -9240,14 +9454,14 @@ function ValidationGroup(field, editField) {
9240
9454
  component: MinLength,
9241
9455
  getValue,
9242
9456
  field,
9243
- isEdited: isEdited$4,
9457
+ isEdited: isEdited$5,
9244
9458
  onChange
9245
9459
  }, {
9246
9460
  id: 'maxLength',
9247
9461
  component: MaxLength,
9248
9462
  getValue,
9249
9463
  field,
9250
- isEdited: isEdited$4,
9464
+ isEdited: isEdited$5,
9251
9465
  onChange
9252
9466
  });
9253
9467
  }
@@ -9267,14 +9481,14 @@ function ValidationGroup(field, editField) {
9267
9481
  component: Min,
9268
9482
  getValue,
9269
9483
  field,
9270
- isEdited: isEdited$4,
9484
+ isEdited: isEdited$5,
9271
9485
  onChange
9272
9486
  }, {
9273
9487
  id: 'max',
9274
9488
  component: Max,
9275
9489
  getValue,
9276
9490
  field,
9277
- isEdited: isEdited$4,
9491
+ isEdited: isEdited$5,
9278
9492
  onChange
9279
9493
  });
9280
9494
  }
@@ -9307,14 +9521,19 @@ function MinLength(props) {
9307
9521
  onChange
9308
9522
  } = props;
9309
9523
  const debounce = useService('debounce');
9310
- return NumberFieldEntry({
9524
+ const variables = useVariables().map(name => ({
9525
+ name
9526
+ }));
9527
+ return FeelNumberEntry({
9311
9528
  debounce,
9312
9529
  element: field,
9530
+ feel: 'optional',
9313
9531
  getValue: getValue('minLength'),
9314
9532
  id,
9315
9533
  label: 'Minimum length',
9316
9534
  min: 0,
9317
- setValue: onChange('minLength')
9535
+ setValue: onChange('minLength'),
9536
+ variables
9318
9537
  });
9319
9538
  }
9320
9539
  function MaxLength(props) {
@@ -9325,14 +9544,19 @@ function MaxLength(props) {
9325
9544
  onChange
9326
9545
  } = props;
9327
9546
  const debounce = useService('debounce');
9328
- return NumberFieldEntry({
9547
+ const variables = useVariables().map(name => ({
9548
+ name
9549
+ }));
9550
+ return FeelNumberEntry({
9329
9551
  debounce,
9330
9552
  element: field,
9553
+ feel: 'optional',
9331
9554
  getValue: getValue('maxLength'),
9332
9555
  id,
9333
9556
  label: 'Maximum length',
9334
9557
  min: 0,
9335
- setValue: onChange('maxLength')
9558
+ setValue: onChange('maxLength'),
9559
+ variables
9336
9560
  });
9337
9561
  }
9338
9562
  function Pattern(props) {
@@ -9360,14 +9584,19 @@ function Min(props) {
9360
9584
  onChange
9361
9585
  } = props;
9362
9586
  const debounce = useService('debounce');
9363
- return NumberFieldEntry({
9587
+ const variables = useVariables().map(name => ({
9588
+ name
9589
+ }));
9590
+ return FeelNumberEntry({
9364
9591
  debounce,
9365
9592
  element: field,
9593
+ feel: 'optional',
9366
9594
  id,
9367
9595
  label: 'Minimum',
9368
9596
  step: 'any',
9369
9597
  getValue: getValue('min'),
9370
- setValue: onChange('min')
9598
+ setValue: onChange('min'),
9599
+ variables
9371
9600
  });
9372
9601
  }
9373
9602
  function Max(props) {
@@ -9378,14 +9607,19 @@ function Max(props) {
9378
9607
  onChange
9379
9608
  } = props;
9380
9609
  const debounce = useService('debounce');
9381
- return NumberFieldEntry({
9610
+ const variables = useVariables().map(name => ({
9611
+ name
9612
+ }));
9613
+ return FeelNumberEntry({
9382
9614
  debounce,
9383
9615
  element: field,
9616
+ feel: 'optional',
9384
9617
  id,
9385
9618
  label: 'Maximum',
9386
9619
  step: 'any',
9387
9620
  getValue: getValue('max'),
9388
- setValue: onChange('max')
9621
+ setValue: onChange('max'),
9622
+ variables
9389
9623
  });
9390
9624
  }
9391
9625
  function ValidationType(props) {
@@ -9459,6 +9693,17 @@ function ValuesGroups(field, editField) {
9459
9693
  id: staticValuesId
9460
9694
  })
9461
9695
  });
9696
+ } else if (valuesSource === formJsViewer.VALUES_SOURCES.EXPRESSION) {
9697
+ const valuesExpressionId = `${fieldId}-valuesExpression`;
9698
+ groups.push({
9699
+ id: valuesExpressionId,
9700
+ label: 'Options expression',
9701
+ component: Group,
9702
+ entries: ValuesExpressionEntry({
9703
+ ...context,
9704
+ id: valuesExpressionId
9705
+ })
9706
+ });
9462
9707
  }
9463
9708
  return groups;
9464
9709
  }
@@ -9618,47 +9863,37 @@ function FormPropertiesPanel(props) {
9618
9863
  } = props;
9619
9864
  const formEditor = injector.get('formEditor');
9620
9865
  const modeling = injector.get('modeling');
9621
- const selection = injector.get('selection');
9622
- const {
9623
- schema
9624
- } = formEditor._getState();
9866
+ const selectionModule = injector.get('selection');
9625
9867
  const [state, setState] = hooks.useState({
9626
- selectedFormField: selection.get() || schema
9868
+ selectedFormField: selectionModule.get() || formEditor._getState().schema
9627
9869
  });
9628
- const _update = field => {
9870
+ const selectedFormField = state.selectedFormField;
9871
+ const refresh = hooks.useCallback(field => {
9872
+ // TODO(skaiir): rework state management, re-rendering the whole properties panel is not the way to go
9873
+ // https://github.com/bpmn-io/form-js/issues/686
9629
9874
  setState({
9630
- ...state,
9631
- selectedFormField: field
9875
+ selectedFormField: selectionModule.get() || formEditor._getState().schema
9632
9876
  });
9633
9877
 
9634
9878
  // notify interested parties on property panel updates
9635
9879
  eventBus.fire('propertiesPanel.updated', {
9636
9880
  formField: field
9637
9881
  });
9638
- };
9882
+ }, [eventBus, formEditor, selectionModule]);
9639
9883
  hooks.useLayoutEffect(() => {
9640
- function onSelectionChange(event) {
9641
- _update(event.selection || schema);
9642
- }
9643
- eventBus.on('selection.changed', onSelectionChange);
9644
- return () => {
9645
- eventBus.off('selection.changed', onSelectionChange);
9646
- };
9647
- }, []);
9648
- hooks.useLayoutEffect(() => {
9649
- const onFieldChanged = () => {
9650
- /**
9651
- * TODO(pinussilvestrus): update with actual updated element,
9652
- * once we have a proper updater/change support
9653
- */
9654
- _update(selection.get() || schema);
9655
- };
9656
- eventBus.on('changed', onFieldChanged);
9884
+ /**
9885
+ * TODO(pinussilvestrus): update with actual updated element,
9886
+ * once we have a proper updater/change support
9887
+ */
9888
+ eventBus.on('changed', refresh);
9889
+ eventBus.on('import.done', refresh);
9890
+ eventBus.on('selection.changed', refresh);
9657
9891
  return () => {
9658
- eventBus.off('changed', onFieldChanged);
9892
+ eventBus.off('changed', refresh);
9893
+ eventBus.off('import.done', refresh);
9894
+ eventBus.off('selection.changed', refresh);
9659
9895
  };
9660
- }, []);
9661
- const selectedFormField = state.selectedFormField;
9896
+ }, [eventBus, refresh]);
9662
9897
  const getService = (type, strict = true) => injector.get(type, strict);
9663
9898
  const propertiesPanelContext = {
9664
9899
  getService