@bpmn-io/form-js-editor 1.0.0-alpha.9 → 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.es.js CHANGED
@@ -6,7 +6,8 @@ import classnames from 'classnames';
6
6
  import { jsx, jsxs, Fragment as Fragment$1 } from 'preact/jsx-runtime';
7
7
  import { useContext, useState, useMemo, useEffect, useCallback, useRef as useRef$1, useLayoutEffect } from 'preact/hooks';
8
8
  import { createContext, Fragment, render, createElement } from 'preact';
9
- import React, { createPortal, useRef, useContext as useContext$1, useEffect as useEffect$1, forwardRef } from 'preact/compat';
9
+ import * as React from 'preact/compat';
10
+ import { createPortal, useRef, useContext as useContext$1, useEffect as useEffect$1, forwardRef } from 'preact/compat';
10
11
  import dragula from 'dragula';
11
12
  import { classes, query, closest, event, matches, domify } from 'min-dom';
12
13
  import { mutate } from 'array-move';
@@ -514,10 +515,10 @@ function invokeFunction(fn, args) {
514
515
  return fn.apply(null, args);
515
516
  }
516
517
 
517
- /**
518
- * A factory to create a configurable debouncer.
519
- *
520
- * @param {number|boolean} [config=true]
518
+ /**
519
+ * A factory to create a configurable debouncer.
520
+ *
521
+ * @param {number|boolean} [config=true]
521
522
  */
522
523
  function DebounceFactory(config = true) {
523
524
  const timeout = typeof config === 'number' ? config : config ? 300 : 0;
@@ -530,11 +531,11 @@ function DebounceFactory(config = true) {
530
531
  DebounceFactory.$inject = ['config.debounce'];
531
532
 
532
533
  class FieldFactory {
533
- /**
534
- * @constructor
535
- *
536
- * @param { import('./FormFieldRegistry').default } formFieldRegistry
537
- * @param { import('@bpmn-io/form-js-viewer').FormFields } formFields
534
+ /**
535
+ * @constructor
536
+ *
537
+ * @param { import('./FormFieldRegistry').default } formFieldRegistry
538
+ * @param { import('@bpmn-io/form-js-viewer').FormFields } formFields
538
539
  */
539
540
  constructor(formFieldRegistry, formFields) {
540
541
  this._formFieldRegistry = formFieldRegistry;
@@ -597,11 +598,11 @@ class FieldFactory {
597
598
  FieldFactory.$inject = ['formFieldRegistry', 'formFields'];
598
599
 
599
600
  class FormFieldRegistry extends FormFieldRegistry$1 {
600
- /**
601
- * Updates a form fields id.
602
- *
603
- * @param {Object} formField
604
- * @param {string} newId
601
+ /**
602
+ * Updates a form fields id.
603
+ *
604
+ * @param {Object} formField
605
+ * @param {string} newId
605
606
  */
606
607
  updateId(formField, newId) {
607
608
  this._validateId(newId);
@@ -622,13 +623,13 @@ class FormFieldRegistry extends FormFieldRegistry$1 {
622
623
  }
623
624
  }
624
625
 
625
- /**
626
- * Validate the suitability of the given id and signals a problem
627
- * with an exception.
628
- *
629
- * @param {string} id
630
- *
631
- * @throws {Error} if id is empty or already assigned
626
+ /**
627
+ * Validate the suitability of the given id and signals a problem
628
+ * with an exception.
629
+ *
630
+ * @param {string} id
631
+ *
632
+ * @throws {Error} if id is empty or already assigned
632
633
  */
633
634
  _validateId(id) {
634
635
  if (!id) {
@@ -645,11 +646,11 @@ const MAX_COLUMNS = 16;
645
646
  const MIN_COLUMNS = 2;
646
647
  const MAX_FIELDS_PER_ROW = 4;
647
648
  class FormLayoutValidator {
648
- /**
649
- * @constructor
650
- *
651
- * @param { import('./FormLayouter').default } formLayouter
652
- * @param { import('./FormFieldRegistry').default } formFieldRegistry
649
+ /**
650
+ * @constructor
651
+ *
652
+ * @param { import('./FormLayouter').default } formLayouter
653
+ * @param { import('./FormFieldRegistry').default } formFieldRegistry
653
654
  */
654
655
  constructor(formLayouter, formFieldRegistry) {
655
656
  this._formLayouter = formLayouter;
@@ -709,11 +710,11 @@ function calculateMaxColumnsWithAuto(autoCols) {
709
710
  }
710
711
 
711
712
  class Importer {
712
- /**
713
- * @constructor
714
- * @param { import('../core/FormFieldRegistry').default } formFieldRegistry
715
- * @param { import('../core/FieldFactory').default } fieldFactory
716
- * @param { import('../core/FormLayouter').default } formLayouter
713
+ /**
714
+ * @constructor
715
+ * @param { import('../core/FormFieldRegistry').default } formFieldRegistry
716
+ * @param { import('../core/FieldFactory').default } fieldFactory
717
+ * @param { import('../core/FormLayouter').default } formLayouter
717
718
  */
718
719
  constructor(formFieldRegistry, fieldFactory, formLayouter) {
719
720
  this._formFieldRegistry = formFieldRegistry;
@@ -721,21 +722,21 @@ class Importer {
721
722
  this._formLayouter = formLayouter;
722
723
  }
723
724
 
724
- /**
725
- * Import schema creating rows, fields, attaching additional
726
- * information to each field and adding fields to the
727
- * field registry.
728
- *
729
- * Additional information attached:
730
- *
731
- * * `id` (unless present)
732
- * * `_parent`
733
- * * `_path`
734
- *
735
- * @param {any} schema
736
- *
737
- * @typedef {{ warnings: Error[], schema: any }} ImportResult
738
- * @returns {ImportResult}
725
+ /**
726
+ * Import schema creating rows, fields, attaching additional
727
+ * information to each field and adding fields to the
728
+ * field registry.
729
+ *
730
+ * Additional information attached:
731
+ *
732
+ * * `id` (unless present)
733
+ * * `_parent`
734
+ * * `_path`
735
+ *
736
+ * @param {any} schema
737
+ *
738
+ * @typedef {{ warnings: Error[], schema: any }} ImportResult
739
+ * @returns {ImportResult}
739
740
  */
740
741
  importSchema(schema) {
741
742
  // TODO: Add warnings
@@ -753,12 +754,12 @@ class Importer {
753
754
  }
754
755
  }
755
756
 
756
- /**
757
- * @param {{[x: string]: any}} fieldAttrs
758
- * @param {String} [parentId]
759
- * @param {number} [index]
760
- *
761
- * @return {any} field
757
+ /**
758
+ * @param {{[x: string]: any}} fieldAttrs
759
+ * @param {String} [parentId]
760
+ * @param {number} [index]
761
+ *
762
+ * @return {any} field
762
763
  */
763
764
  importFormField(fieldAttrs, parentId, index) {
764
765
  const {
@@ -795,11 +796,11 @@ class Importer {
795
796
  return field;
796
797
  }
797
798
 
798
- /**
799
- * @param {Array<any>} components
800
- * @param {string} parentId
801
- *
802
- * @return {Array<any>} imported components
799
+ /**
800
+ * @param {Array<any>} components
801
+ * @param {string} parentId
802
+ *
803
+ * @return {Array<any>} imported components
803
804
  */
804
805
  importFormFields(components, parentId) {
805
806
  return components.map((component, index) => {
@@ -824,22 +825,22 @@ function editorFormFieldClasses(type, {
824
825
  });
825
826
  }
826
827
 
827
- /**
828
- * Add a dragger that calls back the passed function with
829
- * { event, delta } on drag.
830
- *
831
- * @example
832
- *
833
- * function dragMove(event, delta) {
834
- * // we are dragging (!!)
835
- * }
836
- *
837
- * domElement.addEventListener('dragstart', dragger(dragMove));
838
- *
839
- * @param {Function} fn
840
- * @param {Element} dragPreview
841
- *
842
- * @return {Function} drag start callback function
828
+ /**
829
+ * Add a dragger that calls back the passed function with
830
+ * { event, delta } on drag.
831
+ *
832
+ * @example
833
+ *
834
+ * function dragMove(event, delta) {
835
+ * // we are dragging (!!)
836
+ * }
837
+ *
838
+ * domElement.addEventListener('dragstart', dragger(dragMove));
839
+ *
840
+ * @param {Function} fn
841
+ * @param {Element} dragPreview
842
+ *
843
+ * @return {Function} drag start callback function
843
844
  */
844
845
  function createDragger(fn, dragPreview) {
845
846
  let self;
@@ -880,12 +881,12 @@ function createDragger(fn, dragPreview) {
880
881
  return onDragStart;
881
882
  }
882
883
 
883
- /**
884
- * Throttle function call according UI update cycle.
885
- *
886
- * @param {Function} fn
887
- *
888
- * @return {Function} throttled fn
884
+ /**
885
+ * Throttle function call according UI update cycle.
886
+ *
887
+ * @param {Function} fn
888
+ *
889
+ * @return {Function} throttled fn
889
890
  */
890
891
  function throttle(fn) {
891
892
  let active = false;
@@ -914,11 +915,11 @@ const DragAndDropContext = createContext({
914
915
  });
915
916
  var DragAndDropContext$1 = DragAndDropContext;
916
917
 
917
- /**
918
- * @param {string} type
919
- * @param {boolean} [strict]
920
- *
921
- * @returns {any}
918
+ /**
919
+ * @param {string} type
920
+ * @param {boolean} [strict]
921
+ *
922
+ * @returns {any}
922
923
  */
923
924
  function getService$1(type, strict) {}
924
925
  const FormEditorContext = createContext({
@@ -933,83 +934,91 @@ function useService$1 (type, strict) {
933
934
  return getService(type, strict);
934
935
  }
935
936
 
937
+ var _path$3;
936
938
  function _extends$3() { _extends$3 = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$3.apply(this, arguments); }
937
- var CloseIcon = (({
938
- styles = {},
939
- ...props
940
- }) => /*#__PURE__*/React.createElement("svg", _extends$3({
941
- width: "16",
942
- height: "16",
943
- fill: "currentColor",
944
- xmlns: "http://www.w3.org/2000/svg"
945
- }, props), /*#__PURE__*/React.createElement("path", {
946
- fillRule: "evenodd",
947
- clipRule: "evenodd",
948
- d: "M12 4.7l-.7-.7L8 7.3 4.7 4l-.7.7L7.3 8 4 11.3l.7.7L8 8.7l3.3 3.3.7-.7L8.7 8 12 4.7z"
949
- })));
939
+ var SvgClose = function SvgClose(props) {
940
+ return /*#__PURE__*/React.createElement("svg", _extends$3({
941
+ xmlns: "http://www.w3.org/2000/svg",
942
+ width: 16,
943
+ height: 16,
944
+ fill: "currentColor"
945
+ }, props), _path$3 || (_path$3 = /*#__PURE__*/React.createElement("path", {
946
+ fillRule: "evenodd",
947
+ d: "m12 4.7-.7-.7L8 7.3 4.7 4l-.7.7L7.3 8 4 11.3l.7.7L8 8.7l3.3 3.3.7-.7L8.7 8 12 4.7Z",
948
+ clipRule: "evenodd"
949
+ })));
950
+ };
951
+ var CloseIcon = SvgClose;
950
952
 
953
+ var _path$2, _path2;
951
954
  function _extends$2() { _extends$2 = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$2.apply(this, arguments); }
952
- var DeleteIcon$1 = (({
953
- styles = {},
954
- ...props
955
- }) => /*#__PURE__*/React.createElement("svg", _extends$2({
956
- xmlns: "http://www.w3.org/2000/svg",
957
- width: "16",
958
- height: "16",
959
- fill: "none"
960
- }, props), /*#__PURE__*/React.createElement("rect", {
961
- width: "16",
962
- height: "16",
963
- x: ".536",
964
- fill: "#fff",
965
- rx: "3",
966
- style: {
967
- mixBlendMode: "multiply"
968
- }
969
- }), /*#__PURE__*/React.createElement("path", {
970
- fill: "#fff",
971
- d: "M.536 0h16v16h-16z",
972
- style: {
973
- mixBlendMode: "multiply"
974
- }
975
- }), /*#__PURE__*/React.createElement("path", {
976
- fill: "currentcolor",
977
- d: "M7.536 6h-1v6h1V6zm3 0h-1v6h1V6z"
978
- }), /*#__PURE__*/React.createElement("path", {
979
- fill: "currentcolor",
980
- d: "M2.536 3v1h1v10a1 1 0 001 1h8a1 1 0 001-1V4h1V3h-12zm2 11V4h8v10h-8zm6-13h-4v1h4V1z"
981
- })));
955
+ var SvgDelete = function SvgDelete(props) {
956
+ return /*#__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: 0.536,
965
+ fill: "#fff",
966
+ rx: 3,
967
+ style: {
968
+ mixBlendMode: "multiply"
969
+ }
970
+ }), /*#__PURE__*/React.createElement("path", {
971
+ fill: "#fff",
972
+ d: "M0 0h16v16H0z",
973
+ style: {
974
+ mixBlendMode: "multiply"
975
+ },
976
+ transform: "translate(.536)"
977
+ }), _path$2 || (_path$2 = /*#__PURE__*/React.createElement("path", {
978
+ fill: "currentcolor",
979
+ d: "M7.536 6h-1v6h1V6Zm3 0h-1v6h1V6Z"
980
+ })), _path2 || (_path2 = /*#__PURE__*/React.createElement("path", {
981
+ fill: "currentcolor",
982
+ d: "M2.536 3v1h1v10a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4h1V3h-12Zm2 11V4h8v10h-8Zm6-13h-4v1h4V1Z"
983
+ })));
984
+ };
985
+ var DeleteIcon$1 = SvgDelete;
982
986
 
987
+ var _path$1;
983
988
  function _extends$1() { _extends$1 = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$1.apply(this, arguments); }
984
- var DraggableIcon = (({
985
- styles = {},
986
- ...props
987
- }) => /*#__PURE__*/React.createElement("svg", _extends$1({
988
- xmlns: "http://www.w3.org/2000/svg",
989
- width: "16",
990
- height: "16",
991
- fill: "currentcolor",
992
- viewBox: "0 0 32 32"
993
- }, props), /*#__PURE__*/React.createElement("path", {
994
- d: "M10 6h4v4h-4zm8 0h4v4h-4zm-8 8h4v4h-4zm8 0h4v4h-4zm-8 8h4v4h-4zm8 0h4v4h-4z"
995
- }), /*#__PURE__*/React.createElement("path", {
996
- d: "M0 0h32v32H0z",
997
- fill: "none"
998
- })));
989
+ var SvgDraggable = function SvgDraggable(props) {
990
+ return /*#__PURE__*/React.createElement("svg", _extends$1({
991
+ xmlns: "http://www.w3.org/2000/svg",
992
+ xmlSpace: "preserve",
993
+ width: 16,
994
+ height: 16,
995
+ fill: "currentcolor",
996
+ viewBox: "0 0 32 32"
997
+ }, props), _path$1 || (_path$1 = /*#__PURE__*/React.createElement("path", {
998
+ d: "M10 6h4v4h-4zm8 0h4v4h-4zm-8 8h4v4h-4zm8 0h4v4h-4zm-8 8h4v4h-4zm8 0h4v4h-4z"
999
+ })), /*#__PURE__*/React.createElement("path", {
1000
+ d: "M0 0h32v32H0z",
1001
+ style: {
1002
+ fill: "none"
1003
+ }
1004
+ }));
1005
+ };
1006
+ var DraggableIcon = SvgDraggable;
999
1007
 
1008
+ var _path;
1000
1009
  function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
1001
- var SearchIcon = (({
1002
- styles = {},
1003
- ...props
1004
- }) => /*#__PURE__*/React.createElement("svg", _extends({
1005
- width: "15",
1006
- height: "15",
1007
- fill: "none",
1008
- xmlns: "http://www.w3.org/2000/svg"
1009
- }, props), /*#__PURE__*/React.createElement("path", {
1010
- d: "M14.5 13.793l-3.776-3.776a5.508 5.508 0 10-.707.707l3.776 3.776.707-.707zM2 6.5a4.5 4.5 0 119 0 4.5 4.5 0 01-9 0z",
1011
- fill: "currentColor"
1012
- })));
1010
+ var SvgSearch = function SvgSearch(props) {
1011
+ return /*#__PURE__*/React.createElement("svg", _extends({
1012
+ xmlns: "http://www.w3.org/2000/svg",
1013
+ width: 15,
1014
+ height: 15,
1015
+ fill: "none"
1016
+ }, props), _path || (_path = /*#__PURE__*/React.createElement("path", {
1017
+ fill: "currentColor",
1018
+ d: "m14.5 13.793-3.776-3.776a5.508 5.508 0 1 0-.707.707l3.776 3.776.707-.707ZM2 6.5a4.5 4.5 0 1 1 9 0 4.5 4.5 0 0 1-9 0Z"
1019
+ })));
1020
+ };
1021
+ var SearchIcon = SvgSearch;
1013
1022
 
1014
1023
  function EditorText(props) {
1015
1024
  const {
@@ -1205,23 +1214,23 @@ var Slot = (props => {
1205
1214
  return fillsAndSeparators;
1206
1215
  });
1207
1216
 
1208
- /**
1209
- * Creates a Fragment for a fill.
1210
- *
1211
- * @param {Object} fill Fill to be rendered
1212
- * @returns {Object} Preact Fragment containing fill's children
1217
+ /**
1218
+ * Creates a Fragment for a fill.
1219
+ *
1220
+ * @param {Object} fill Fill to be rendered
1221
+ * @returns {Object} Preact Fragment containing fill's children
1213
1222
  */
1214
1223
  const FillFragment = fill => jsx(Fragment, {
1215
1224
  children: fill.children
1216
1225
  }, fill.id);
1217
1226
 
1218
- /**
1219
- * Creates an array of fills, with separators inserted between groups.
1220
- *
1221
- * @param {Array} groups Groups of fills
1222
- * @param {Function} fillRenderer Function to create a fill
1223
- * @param {Function} separatorRenderer Function to create a separator
1224
- * @returns {Array} Array of fills and separators
1227
+ /**
1228
+ * Creates an array of fills, with separators inserted between groups.
1229
+ *
1230
+ * @param {Array} groups Groups of fills
1231
+ * @param {Function} fillRenderer Function to create a fill
1232
+ * @param {Function} separatorRenderer Function to create a separator
1233
+ * @returns {Array} Array of fills and separators
1225
1234
  */
1226
1235
  const buildFills = (groups, fillRenderer, separatorRenderer) => {
1227
1236
  const result = [];
@@ -1239,8 +1248,8 @@ const buildFills = (groups, fillRenderer, separatorRenderer) => {
1239
1248
  return result;
1240
1249
  };
1241
1250
 
1242
- /**
1243
- * Groups fills by group name property.
1251
+ /**
1252
+ * Groups fills by group name property.
1244
1253
  */
1245
1254
  const _groupByGroupName = fills => {
1246
1255
  const groups = [];
@@ -1260,8 +1269,8 @@ const _groupByGroupName = fills => {
1260
1269
  return Object.keys(groupsById).sort().map(id => groupsById[id]);
1261
1270
  };
1262
1271
 
1263
- /**
1264
- * Compares fills by priority.
1272
+ /**
1273
+ * Compares fills by priority.
1265
1274
  */
1266
1275
  const _comparePriority = (a, b) => {
1267
1276
  return (b.priority || 0) - (a.priority || 0);
@@ -1489,19 +1498,19 @@ const DRAG_NO_DROP_CLS = 'fjs-no-drop';
1489
1498
  const DRAG_NO_MOVE_CLS = 'fjs-no-move';
1490
1499
  const ERROR_DROP_CLS = 'fjs-error-drop';
1491
1500
 
1492
- /**
1493
- * @typedef { { id: String, components: Array<any> } } FormRow
1501
+ /**
1502
+ * @typedef { { id: String, components: Array<any> } } FormRow
1494
1503
  */
1495
1504
 
1496
1505
  class Dragging {
1497
- /**
1498
- * @constructor
1499
- *
1500
- * @param { import('../../core/FormFieldRegistry').default } formFieldRegistry
1501
- * @param { import('../../core/FormLayouter').default } formLayouter
1502
- * @param { import('../../core/FormLayoutValidator').default } formLayoutValidator
1503
- * @param { import('../../core/EventBus').default } eventBus
1504
- * @param { import('../modeling/Modeling').default } modeling
1506
+ /**
1507
+ * @constructor
1508
+ *
1509
+ * @param { import('../../core/FormFieldRegistry').default } formFieldRegistry
1510
+ * @param { import('../../core/FormLayouter').default } formLayouter
1511
+ * @param { import('../../core/FormLayoutValidator').default } formLayoutValidator
1512
+ * @param { import('../../core/EventBus').default } eventBus
1513
+ * @param { import('../modeling/Modeling').default } modeling
1505
1514
  */
1506
1515
  constructor(formFieldRegistry, formLayouter, formLayoutValidator, eventBus, modeling) {
1507
1516
  this._formFieldRegistry = formFieldRegistry;
@@ -1511,13 +1520,13 @@ class Dragging {
1511
1520
  this._modeling = modeling;
1512
1521
  }
1513
1522
 
1514
- /**
1515
- * Calculcates position in form schema given the dropped place.
1516
- *
1517
- * @param { FormRow } targetRow
1518
- * @param { any } targetFormField
1519
- * @param { HTMLElement } sibling
1520
- * @returns { number }
1523
+ /**
1524
+ * Calculcates position in form schema given the dropped place.
1525
+ *
1526
+ * @param { FormRow } targetRow
1527
+ * @param { any } targetFormField
1528
+ * @param { HTMLElement } sibling
1529
+ * @returns { number }
1521
1530
  */
1522
1531
  getTargetIndex(targetRow, targetFormField, sibling) {
1523
1532
  /** @type HTMLElement */
@@ -1619,8 +1628,8 @@ class Dragging {
1619
1628
  }
1620
1629
  }
1621
1630
 
1622
- /**
1623
- * @param { { container: Array<string>, direction: string, mirrorContainer: string } } options
1631
+ /**
1632
+ * @param { { container: Array<string>, direction: string, mirrorContainer: string } } options
1624
1633
  */
1625
1634
  createDragulaInstance(options) {
1626
1635
  const {
@@ -2017,7 +2026,7 @@ function DebugColumns(props) {
2017
2026
  return null;
2018
2027
  }
2019
2028
  return jsx("div", {
2020
- style: "width: fit-content;\r padding: 2px 6px;\r height: 16px;\r background: var(--color-blue-205-100-95);\r display: flex;\r justify-content: center;\r align-items: center;\r position: absolute;\r bottom: -2px;\r z-index: 2;\r font-size: 10px;\r right: 3px;",
2029
+ style: "width: fit-content; padding: 2px 6px; height: 16px; background: var(--color-blue-205-100-95); display: flex; justify-content: center; align-items: center; position: absolute; bottom: -2px; z-index: 2; font-size: 10px; right: 3px;",
2021
2030
  class: "fjs-debug-columns",
2022
2031
  children: (field.layout || {}).columns || 'auto'
2023
2032
  });
@@ -3076,10 +3085,10 @@ function updateRow(formField, rowId) {
3076
3085
  }
3077
3086
 
3078
3087
  class AddFormFieldHandler {
3079
- /**
3080
- * @constructor
3081
- * @param { import('../../../FormEditor').default } formEditor
3082
- * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3088
+ /**
3089
+ * @constructor
3090
+ * @param { import('../../../FormEditor').default } formEditor
3091
+ * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3083
3092
  */
3084
3093
  constructor(formEditor, formFieldRegistry) {
3085
3094
  this._formEditor = formEditor;
@@ -3140,10 +3149,10 @@ class AddFormFieldHandler {
3140
3149
  AddFormFieldHandler.$inject = ['formEditor', 'formFieldRegistry'];
3141
3150
 
3142
3151
  class EditFormFieldHandler {
3143
- /**
3144
- * @constructor
3145
- * @param { import('../../../FormEditor').default } formEditor
3146
- * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3152
+ /**
3153
+ * @constructor
3154
+ * @param { import('../../../FormEditor').default } formEditor
3155
+ * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3147
3156
  */
3148
3157
  constructor(formEditor, formFieldRegistry) {
3149
3158
  this._formEditor = formEditor;
@@ -3206,10 +3215,10 @@ class EditFormFieldHandler {
3206
3215
  EditFormFieldHandler.$inject = ['formEditor', 'formFieldRegistry'];
3207
3216
 
3208
3217
  class MoveFormFieldHandler {
3209
- /**
3210
- * @constructor
3211
- * @param { import('../../../FormEditor').default } formEditor
3212
- * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3218
+ /**
3219
+ * @constructor
3220
+ * @param { import('../../../FormEditor').default } formEditor
3221
+ * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3213
3222
  */
3214
3223
  constructor(formEditor, formFieldRegistry) {
3215
3224
  this._formEditor = formEditor;
@@ -3298,10 +3307,10 @@ class MoveFormFieldHandler {
3298
3307
  MoveFormFieldHandler.$inject = ['formEditor', 'formFieldRegistry'];
3299
3308
 
3300
3309
  class RemoveFormFieldHandler {
3301
- /**
3302
- * @constructor
3303
- * @param { import('../../../FormEditor').default } formEditor
3304
- * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3310
+ /**
3311
+ * @constructor
3312
+ * @param { import('../../../FormEditor').default } formEditor
3313
+ * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3305
3314
  */
3306
3315
  constructor(formEditor, formFieldRegistry) {
3307
3316
  this._formEditor = formEditor;
@@ -3361,9 +3370,9 @@ class RemoveFormFieldHandler {
3361
3370
  RemoveFormFieldHandler.$inject = ['formEditor', 'formFieldRegistry'];
3362
3371
 
3363
3372
  class UpdateIdClaimHandler {
3364
- /**
3365
- * @constructor
3366
- * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3373
+ /**
3374
+ * @constructor
3375
+ * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3367
3376
  */
3368
3377
  constructor(formFieldRegistry) {
3369
3378
  this._formFieldRegistry = formFieldRegistry;
@@ -3396,9 +3405,9 @@ class UpdateIdClaimHandler {
3396
3405
  UpdateIdClaimHandler.$inject = ['formFieldRegistry'];
3397
3406
 
3398
3407
  class UpdateKeyClaimHandler {
3399
- /**
3400
- * @constructor
3401
- * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3408
+ /**
3409
+ * @constructor
3410
+ * @param { import('../../../core/FormFieldRegistry').default } formFieldRegistry
3402
3411
  */
3403
3412
  constructor(formFieldRegistry) {
3404
3413
  this._formFieldRegistry = formFieldRegistry;
@@ -3864,8 +3873,8 @@ class ValidateBehavior extends CommandInterceptor {
3864
3873
  constructor(eventBus) {
3865
3874
  super(eventBus);
3866
3875
 
3867
- /**
3868
- * Remove custom validation if <validationType> is about to be added.
3876
+ /**
3877
+ * Remove custom validation if <validationType> is about to be added.
3869
3878
  */
3870
3879
  // @ts-ignore-next-line
3871
3880
  this.preExecute('formField.edit', function (context) {
@@ -4445,22 +4454,22 @@ var SelectionModule = {
4445
4454
  selectionBehavior: ['type', SelectionBehavior]
4446
4455
  };
4447
4456
 
4448
- /**
4449
- * Base class for sectionable UI modules.
4450
- *
4451
- * @property {EventBus} _eventBus - EventBus instance used for event handling.
4452
- * @property {string} managerType - Type of the render manager. Used to form event names.
4453
- *
4454
- * @class SectionModuleBase
4457
+ /**
4458
+ * Base class for sectionable UI modules.
4459
+ *
4460
+ * @property {EventBus} _eventBus - EventBus instance used for event handling.
4461
+ * @property {string} managerType - Type of the render manager. Used to form event names.
4462
+ *
4463
+ * @class SectionModuleBase
4455
4464
  */
4456
4465
  class SectionModuleBase {
4457
- /**
4458
- * Create a SectionModuleBase instance.
4459
- *
4460
- * @param {any} eventBus - The EventBus instance used for event handling.
4461
- * @param {string} sectionKey - The type of render manager. Used to form event names.
4462
- *
4463
- * @constructor
4466
+ /**
4467
+ * Create a SectionModuleBase instance.
4468
+ *
4469
+ * @param {any} eventBus - The EventBus instance used for event handling.
4470
+ * @param {string} sectionKey - The type of render manager. Used to form event names.
4471
+ *
4472
+ * @constructor
4464
4473
  */
4465
4474
  constructor(eventBus, sectionKey) {
4466
4475
  this._eventBus = eventBus;
@@ -4473,10 +4482,10 @@ class SectionModuleBase {
4473
4482
  });
4474
4483
  }
4475
4484
 
4476
- /**
4477
- * Attach the managed section to a parent node.
4478
- *
4479
- * @param {HTMLElement} container - The parent node to attach to.
4485
+ /**
4486
+ * Attach the managed section to a parent node.
4487
+ *
4488
+ * @param {HTMLElement} container - The parent node to attach to.
4480
4489
  */
4481
4490
  attachTo(container) {
4482
4491
  this._onceSectionRendered(() => this._eventBus.fire(`${this._sectionKey}.attach`, {
@@ -4484,22 +4493,22 @@ class SectionModuleBase {
4484
4493
  }));
4485
4494
  }
4486
4495
 
4487
- /**
4488
- * Detach the managed section from its parent node.
4496
+ /**
4497
+ * Detach the managed section from its parent node.
4489
4498
  */
4490
4499
  detach() {
4491
4500
  this._onceSectionRendered(() => this._eventBus.fire(`${this._sectionKey}.detach`));
4492
4501
  }
4493
4502
 
4494
- /**
4495
- * Reset the managed section to its initial state.
4503
+ /**
4504
+ * Reset the managed section to its initial state.
4496
4505
  */
4497
4506
  reset() {
4498
4507
  this._onceSectionRendered(() => this._eventBus.fire(`${this._sectionKey}.reset`));
4499
4508
  }
4500
4509
 
4501
- /**
4502
- * Circumvents timing issues.
4510
+ /**
4511
+ * Circumvents timing issues.
4503
4512
  */
4504
4513
  _onceSectionRendered(callback) {
4505
4514
  if (this.isSectionRendered) {
@@ -5982,155 +5991,314 @@ function isEdited$7(node) {
5982
5991
  function prefixId$6(id) {
5983
5992
  return `bio-properties-panel-${id}`;
5984
5993
  }
5985
- const noop$1 = () => {};
5986
- function FeelTextfield(props) {
5994
+ function NumberField(props) {
5987
5995
  const {
5988
5996
  debounce,
5997
+ disabled,
5998
+ displayLabel = true,
5989
5999
  id,
6000
+ inputRef,
5990
6001
  label,
6002
+ max,
6003
+ min,
5991
6004
  onInput,
5992
- onError,
5993
- feel,
6005
+ step,
5994
6006
  value = '',
5995
- disabled = false,
5996
- variables,
5997
- tooltipContainer,
5998
- OptionalComponent = OptionalFeelInput
6007
+ onFocus,
6008
+ onBlur
5999
6009
  } = props;
6000
- const [localValue, _setLocalValue] = useState(value);
6001
- const editorRef = useShowEntryEvent(id);
6002
- const containerRef = useRef$1();
6003
- const feelActive = isString(localValue) && localValue.startsWith('=') || feel === 'required';
6004
- const feelOnlyValue = isString(localValue) && localValue.startsWith('=') ? localValue.substring(1) : localValue;
6005
- const [focus, _setFocus] = useState(undefined);
6006
- const setFocus = (offset = 0) => {
6007
- const hasFocus = containerRef.current.contains(document.activeElement);
6008
-
6009
- // Keep caret position if it is already focused, otherwise focus at the end
6010
- const position = hasFocus ? document.activeElement.selectionStart : Infinity;
6011
- _setFocus(position + offset);
6012
- };
6010
+ const [localValue, setLocalValue] = useState(value);
6013
6011
  const handleInputCallback = useMemo(() => {
6014
- return debounce(newValue => {
6015
- onInput(newValue);
6012
+ return debounce(event => {
6013
+ const {
6014
+ validity,
6015
+ value
6016
+ } = event.target;
6017
+ if (validity.valid) {
6018
+ onInput(value ? parseFloat(value) : undefined);
6019
+ }
6016
6020
  });
6017
6021
  }, [onInput, debounce]);
6018
- const setLocalValue = newValue => {
6019
- _setLocalValue(newValue);
6020
- if (!newValue || newValue === '=') {
6021
- handleInputCallback(undefined);
6022
- } else {
6023
- handleInputCallback(newValue);
6024
- }
6025
- };
6026
- const handleFeelToggle = useStaticCallback(() => {
6027
- if (feel === 'required') {
6028
- return;
6029
- }
6030
- if (!feelActive) {
6031
- setLocalValue('=' + localValue);
6032
- } else {
6033
- setLocalValue(feelOnlyValue);
6034
- }
6035
- });
6036
- const handleLocalInput = newValue => {
6037
- if (feelActive) {
6038
- newValue = '=' + newValue;
6039
- }
6040
- if (newValue === localValue) {
6041
- return;
6042
- }
6043
- setLocalValue(newValue);
6044
- if (!feelActive && isString(newValue) && newValue.startsWith('=')) {
6045
- // focus is behind `=` sign that will be removed
6046
- setFocus(-1);
6047
- }
6022
+ const handleInput = e => {
6023
+ handleInputCallback(e);
6024
+ setLocalValue(e.target.value);
6048
6025
  };
6049
- const handleLint = useStaticCallback(lint => {
6050
- if (!(lint && lint.length)) {
6051
- onError(undefined);
6052
- return;
6053
- }
6054
- const error = lint[0];
6055
- const message = `${error.source}: ${error.message}`;
6056
- onError(message);
6057
- });
6058
- useEffect(() => {
6059
- if (typeof focus !== 'undefined') {
6060
- editorRef.current.focus(focus);
6061
- _setFocus(undefined);
6062
- }
6063
- }, [focus]);
6064
6026
  useEffect(() => {
6065
6027
  if (value === localValue) {
6066
6028
  return;
6067
6029
  }
6068
-
6069
- // External value change removed content => keep FEEL configuration
6070
- if (!value) {
6071
- setLocalValue(feelActive ? '=' : '');
6072
- return;
6073
- }
6074
6030
  setLocalValue(value);
6075
6031
  }, [value]);
6076
-
6077
- // copy-paste integration
6078
- useEffect(() => {
6079
- const copyHandler = event => {
6080
- if (!feelActive) {
6081
- return;
6082
- }
6083
- event.clipboardData.setData('application/FEEL', event.clipboardData.getData('text'));
6084
- };
6085
- const pasteHandler = event => {
6086
- if (feelActive) {
6087
- return;
6088
- }
6089
- const data = event.clipboardData.getData('application/FEEL');
6090
- if (data) {
6091
- setTimeout(() => {
6092
- handleFeelToggle();
6093
- setFocus();
6094
- });
6095
- }
6096
- };
6097
- containerRef.current.addEventListener('copy', copyHandler);
6098
- containerRef.current.addEventListener('cut', copyHandler);
6099
- containerRef.current.addEventListener('paste', pasteHandler);
6100
- return () => {
6101
- containerRef.current.removeEventListener('copy', copyHandler);
6102
- containerRef.current.removeEventListener('cut', copyHandler);
6103
- containerRef.current.removeEventListener('paste', pasteHandler);
6104
- };
6105
- }, [containerRef, feelActive, handleFeelToggle, setFocus]);
6106
6032
  return jsxs("div", {
6107
- class: classnames('bio-properties-panel-feel-entry', {
6108
- 'feel-active': feelActive
6109
- }),
6110
- children: [jsxs("label", {
6033
+ class: "bio-properties-panel-numberfield",
6034
+ children: [displayLabel && jsx("label", {
6111
6035
  for: prefixId$5(id),
6112
6036
  class: "bio-properties-panel-label",
6113
- onClick: () => setFocus(),
6114
- children: [label, jsx(FeelIcon, {
6115
- label: label,
6116
- feel: feel,
6117
- onClick: handleFeelToggle,
6118
- active: feelActive
6119
- })]
6120
- }), jsxs("div", {
6121
- class: "bio-properties-panel-feel-container",
6122
- ref: containerRef,
6123
- children: [jsx(FeelIndicator, {
6124
- active: feelActive,
6125
- disabled: feel !== 'optional' || disabled,
6126
- onClick: handleFeelToggle
6127
- }), feelActive ? jsx(CodeEditor, {
6128
- id: prefixId$5(id),
6129
- name: id,
6130
- onInput: handleLocalInput,
6131
- disabled: disabled,
6132
- onFeelToggle: () => {
6133
- handleFeelToggle();
6037
+ children: label
6038
+ }), jsx("input", {
6039
+ id: prefixId$5(id),
6040
+ ref: inputRef,
6041
+ type: "number",
6042
+ name: id,
6043
+ spellCheck: "false",
6044
+ autoComplete: "off",
6045
+ disabled: disabled,
6046
+ class: "bio-properties-panel-input",
6047
+ max: max,
6048
+ min: min,
6049
+ onInput: handleInput,
6050
+ onFocus: onFocus,
6051
+ onBlur: onBlur,
6052
+ step: step,
6053
+ value: localValue
6054
+ })]
6055
+ });
6056
+ }
6057
+
6058
+ /**
6059
+ * @param {Object} props
6060
+ * @param {Boolean} props.debounce
6061
+ * @param {String} props.description
6062
+ * @param {Boolean} props.disabled
6063
+ * @param {Object} props.element
6064
+ * @param {Function} props.getValue
6065
+ * @param {String} props.id
6066
+ * @param {String} props.label
6067
+ * @param {String} props.max
6068
+ * @param {String} props.min
6069
+ * @param {Function} props.setValue
6070
+ * @param {Function} props.onFocus
6071
+ * @param {Function} props.onBlur
6072
+ * @param {String} props.step
6073
+ * @param {Function} props.validate
6074
+ */
6075
+ function NumberFieldEntry(props) {
6076
+ const {
6077
+ debounce,
6078
+ description,
6079
+ disabled,
6080
+ element,
6081
+ getValue,
6082
+ id,
6083
+ label,
6084
+ max,
6085
+ min,
6086
+ setValue,
6087
+ step,
6088
+ onFocus,
6089
+ onBlur,
6090
+ validate
6091
+ } = props;
6092
+ const [cachedInvalidValue, setCachedInvalidValue] = useState(null);
6093
+ const globalError = useError(id);
6094
+ const [localError, setLocalError] = useState(null);
6095
+ let value = getValue(element);
6096
+ const previousValue = usePrevious(value);
6097
+ useEffect(() => {
6098
+ if (isFunction(validate)) {
6099
+ const newValidationError = validate(value) || null;
6100
+ setLocalError(newValidationError);
6101
+ }
6102
+ }, [value]);
6103
+ const onInput = newValue => {
6104
+ let newValidationError = null;
6105
+ if (isFunction(validate)) {
6106
+ newValidationError = validate(newValue) || null;
6107
+ }
6108
+ if (newValidationError) {
6109
+ setCachedInvalidValue(newValue);
6110
+ } else {
6111
+ setValue(newValue);
6112
+ }
6113
+ setLocalError(newValidationError);
6114
+ };
6115
+ if (previousValue === value && localError) {
6116
+ value = cachedInvalidValue;
6117
+ }
6118
+ const error = globalError || localError;
6119
+ return jsxs("div", {
6120
+ class: classnames('bio-properties-panel-entry', error ? 'has-error' : ''),
6121
+ "data-entry-id": id,
6122
+ children: [jsx(NumberField, {
6123
+ debounce: debounce,
6124
+ disabled: disabled,
6125
+ id: id,
6126
+ label: label,
6127
+ onFocus: onFocus,
6128
+ onBlur: onBlur,
6129
+ onInput: onInput,
6130
+ max: max,
6131
+ min: min,
6132
+ step: step,
6133
+ value: value
6134
+ }, element), error && jsx("div", {
6135
+ class: "bio-properties-panel-error",
6136
+ children: error
6137
+ }), jsx(Description$1, {
6138
+ forId: id,
6139
+ element: element,
6140
+ value: description
6141
+ })]
6142
+ });
6143
+ }
6144
+ function isEdited$6(node) {
6145
+ return node && !!node.value;
6146
+ }
6147
+
6148
+ // helpers /////////////////
6149
+
6150
+ function prefixId$5(id) {
6151
+ return `bio-properties-panel-${id}`;
6152
+ }
6153
+ const noop$1 = () => {};
6154
+ function FeelTextfield(props) {
6155
+ const {
6156
+ debounce,
6157
+ id,
6158
+ label,
6159
+ onInput,
6160
+ onError,
6161
+ feel,
6162
+ value = '',
6163
+ disabled = false,
6164
+ variables,
6165
+ tooltipContainer,
6166
+ OptionalComponent = OptionalFeelInput
6167
+ } = props;
6168
+ const [localValue, _setLocalValue] = useState(value);
6169
+ const editorRef = useShowEntryEvent(id);
6170
+ const containerRef = useRef$1();
6171
+ const feelActive = isString(localValue) && localValue.startsWith('=') || feel === 'required';
6172
+ const feelOnlyValue = isString(localValue) && localValue.startsWith('=') ? localValue.substring(1) : localValue;
6173
+ const [focus, _setFocus] = useState(undefined);
6174
+ const setFocus = (offset = 0) => {
6175
+ const hasFocus = containerRef.current.contains(document.activeElement);
6176
+
6177
+ // Keep caret position if it is already focused, otherwise focus at the end
6178
+ const position = hasFocus ? document.activeElement.selectionStart : Infinity;
6179
+ _setFocus(position + offset);
6180
+ };
6181
+ const handleInputCallback = useMemo(() => {
6182
+ return debounce(newValue => {
6183
+ onInput(newValue);
6184
+ });
6185
+ }, [onInput, debounce]);
6186
+ const setLocalValue = newValue => {
6187
+ _setLocalValue(newValue);
6188
+ if (!newValue || newValue === '=') {
6189
+ handleInputCallback(undefined);
6190
+ } else {
6191
+ handleInputCallback(newValue);
6192
+ }
6193
+ };
6194
+ const handleFeelToggle = useStaticCallback(() => {
6195
+ if (feel === 'required') {
6196
+ return;
6197
+ }
6198
+ if (!feelActive) {
6199
+ setLocalValue('=' + localValue);
6200
+ } else {
6201
+ setLocalValue(feelOnlyValue);
6202
+ }
6203
+ });
6204
+ const handleLocalInput = newValue => {
6205
+ if (feelActive) {
6206
+ newValue = '=' + newValue;
6207
+ }
6208
+ if (newValue === localValue) {
6209
+ return;
6210
+ }
6211
+ setLocalValue(newValue);
6212
+ if (!feelActive && isString(newValue) && newValue.startsWith('=')) {
6213
+ // focus is behind `=` sign that will be removed
6214
+ setFocus(-1);
6215
+ }
6216
+ };
6217
+ const handleLint = useStaticCallback(lint => {
6218
+ if (!(lint && lint.length)) {
6219
+ onError(undefined);
6220
+ return;
6221
+ }
6222
+ const error = lint[0];
6223
+ const message = `${error.source}: ${error.message}`;
6224
+ onError(message);
6225
+ });
6226
+ useEffect(() => {
6227
+ if (typeof focus !== 'undefined') {
6228
+ editorRef.current.focus(focus);
6229
+ _setFocus(undefined);
6230
+ }
6231
+ }, [focus]);
6232
+ useEffect(() => {
6233
+ if (value === localValue) {
6234
+ return;
6235
+ }
6236
+
6237
+ // External value change removed content => keep FEEL configuration
6238
+ if (!value) {
6239
+ setLocalValue(feelActive ? '=' : '');
6240
+ return;
6241
+ }
6242
+ setLocalValue(value);
6243
+ }, [value]);
6244
+
6245
+ // copy-paste integration
6246
+ useEffect(() => {
6247
+ const copyHandler = event => {
6248
+ if (!feelActive) {
6249
+ return;
6250
+ }
6251
+ event.clipboardData.setData('application/FEEL', event.clipboardData.getData('text'));
6252
+ };
6253
+ const pasteHandler = event => {
6254
+ if (feelActive) {
6255
+ return;
6256
+ }
6257
+ const data = event.clipboardData.getData('application/FEEL');
6258
+ if (data) {
6259
+ setTimeout(() => {
6260
+ handleFeelToggle();
6261
+ setFocus();
6262
+ });
6263
+ }
6264
+ };
6265
+ containerRef.current.addEventListener('copy', copyHandler);
6266
+ containerRef.current.addEventListener('cut', copyHandler);
6267
+ containerRef.current.addEventListener('paste', pasteHandler);
6268
+ return () => {
6269
+ containerRef.current.removeEventListener('copy', copyHandler);
6270
+ containerRef.current.removeEventListener('cut', copyHandler);
6271
+ containerRef.current.removeEventListener('paste', pasteHandler);
6272
+ };
6273
+ }, [containerRef, feelActive, handleFeelToggle, setFocus]);
6274
+ return jsxs("div", {
6275
+ class: classnames('bio-properties-panel-feel-entry', {
6276
+ 'feel-active': feelActive
6277
+ }),
6278
+ children: [jsxs("label", {
6279
+ for: prefixId$4(id),
6280
+ class: "bio-properties-panel-label",
6281
+ onClick: () => setFocus(),
6282
+ children: [label, jsx(FeelIcon, {
6283
+ label: label,
6284
+ feel: feel,
6285
+ onClick: handleFeelToggle,
6286
+ active: feelActive
6287
+ })]
6288
+ }), jsxs("div", {
6289
+ class: "bio-properties-panel-feel-container",
6290
+ ref: containerRef,
6291
+ children: [jsx(FeelIndicator, {
6292
+ active: feelActive,
6293
+ disabled: feel !== 'optional' || disabled,
6294
+ onClick: handleFeelToggle
6295
+ }), feelActive ? jsx(CodeEditor, {
6296
+ id: prefixId$4(id),
6297
+ name: id,
6298
+ onInput: handleLocalInput,
6299
+ disabled: disabled,
6300
+ onFeelToggle: () => {
6301
+ handleFeelToggle();
6134
6302
  setFocus(true);
6135
6303
  },
6136
6304
  onLint: handleLint,
@@ -6142,7 +6310,7 @@ function FeelTextfield(props) {
6142
6310
  ...props,
6143
6311
  onInput: handleLocalInput,
6144
6312
  contentAttributes: {
6145
- 'id': prefixId$5(id),
6313
+ 'id': prefixId$4(id),
6146
6314
  'aria-label': label
6147
6315
  },
6148
6316
  value: localValue,
@@ -6180,7 +6348,7 @@ const OptionalFeelInput = forwardRef((props, ref) => {
6180
6348
  }
6181
6349
  };
6182
6350
  return jsx("input", {
6183
- id: prefixId$5(id),
6351
+ id: prefixId$4(id),
6184
6352
  type: "text",
6185
6353
  ref: inputRef,
6186
6354
  name: id,
@@ -6194,6 +6362,53 @@ const OptionalFeelInput = forwardRef((props, ref) => {
6194
6362
  value: value || ''
6195
6363
  });
6196
6364
  });
6365
+ const OptionalFeelNumberField = forwardRef((props, ref) => {
6366
+ const {
6367
+ id,
6368
+ debounce,
6369
+ disabled,
6370
+ onInput,
6371
+ value,
6372
+ min,
6373
+ max,
6374
+ step,
6375
+ onFocus,
6376
+ onBlur
6377
+ } = props;
6378
+ const inputRef = useRef$1();
6379
+
6380
+ // To be consistent with the FEEL editor, set focus at start of input
6381
+ // this ensures clean editing experience when switching with the keyboard
6382
+ ref.current = {
6383
+ focus: position => {
6384
+ const input = inputRef.current;
6385
+ if (!input) {
6386
+ return;
6387
+ }
6388
+ input.focus();
6389
+ if (typeof position === 'number' && position !== Infinity) {
6390
+ if (position > value.length) {
6391
+ position = value.length;
6392
+ }
6393
+ input.setSelectionRange(position, position);
6394
+ }
6395
+ }
6396
+ };
6397
+ return jsx(NumberField, {
6398
+ id: id,
6399
+ debounce: debounce,
6400
+ disabled: disabled,
6401
+ displayLabel: false,
6402
+ inputRef: inputRef,
6403
+ max: max,
6404
+ min: min,
6405
+ onInput: onInput,
6406
+ step: step,
6407
+ value: value,
6408
+ onFocus: onFocus,
6409
+ onBlur: onBlur
6410
+ });
6411
+ });
6197
6412
  forwardRef((props, ref) => {
6198
6413
  const {
6199
6414
  id,
@@ -6218,7 +6433,7 @@ forwardRef((props, ref) => {
6218
6433
  }
6219
6434
  };
6220
6435
  return jsx("textarea", {
6221
- id: prefixId$5(id),
6436
+ id: prefixId$4(id),
6222
6437
  type: "text",
6223
6438
  ref: inputRef,
6224
6439
  name: id,
@@ -6294,7 +6509,7 @@ forwardRef((props, ref) => {
6294
6509
  };
6295
6510
  return jsx("input", {
6296
6511
  ref: inputRef,
6297
- id: prefixId$5(id),
6512
+ id: prefixId$4(id),
6298
6513
  name: id,
6299
6514
  onFocus: onFocus,
6300
6515
  onBlur: onBlur,
@@ -6383,11 +6598,13 @@ function FeelEntry(props) {
6383
6598
  return jsxs("div", {
6384
6599
  class: classnames(props.class, 'bio-properties-panel-entry', error ? 'has-error' : ''),
6385
6600
  "data-entry-id": id,
6386
- children: [jsx(FeelTextfield, {
6601
+ children: [createElement(FeelTextfield, {
6602
+ ...props,
6387
6603
  debounce: debounce,
6388
6604
  disabled: disabled,
6389
6605
  feel: feel,
6390
6606
  id: id,
6607
+ key: element,
6391
6608
  label: label,
6392
6609
  onInput: onInput,
6393
6610
  onError: onError,
@@ -6401,7 +6618,7 @@ function FeelEntry(props) {
6401
6618
  variables: variables,
6402
6619
  tooltipContainer: tooltipContainer,
6403
6620
  OptionalComponent: props.OptionalComponent
6404
- }, element), error && jsx("div", {
6621
+ }), error && jsx("div", {
6405
6622
  class: "bio-properties-panel-error",
6406
6623
  children: error
6407
6624
  }), jsx(Description$1, {
@@ -6419,218 +6636,92 @@ function FeelEntry(props) {
6419
6636
  * @param {String} props.description
6420
6637
  * @param {Boolean} props.debounce
6421
6638
  * @param {Boolean} props.disabled
6639
+ * @param {String} props.max
6640
+ * @param {String} props.min
6641
+ * @param {String} props.step
6422
6642
  * @param {Boolean} props.feel
6423
6643
  * @param {String} props.label
6424
6644
  * @param {Function} props.getValue
6425
6645
  * @param {Function} props.setValue
6426
6646
  * @param {Function} props.tooltipContainer
6427
6647
  * @param {Function} props.validate
6428
- * @param {Function} props.show
6429
- * @param {Function} props.example
6430
- * @param {Function} props.variables
6431
- * @param {Function} props.onFocus
6432
- * @param {Function} props.onBlur
6433
- */
6434
- function FeelToggleSwitchEntry(props) {
6435
- return jsx(FeelEntry, {
6436
- class: "bio-properties-panel-feel-toggle-switch",
6437
- OptionalComponent: OptionalFeelToggleSwitch,
6438
- ...props
6439
- });
6440
- }
6441
-
6442
- /**
6443
- * @param {Object} props
6444
- * @param {Object} props.element
6445
- * @param {String} props.id
6446
- * @param {String} props.description
6447
- * @param {String} props.hostLanguage
6448
- * @param {Boolean} props.singleLine
6449
- * @param {Boolean} props.debounce
6450
- * @param {Boolean} props.disabled
6451
- * @param {Boolean} props.feel
6452
- * @param {String} props.label
6453
- * @param {Function} props.getValue
6454
- * @param {Function} props.setValue
6455
- * @param {Function} props.tooltipContainer
6456
- * @param {Function} props.validate
6457
- * @param {Function} props.show
6458
- * @param {Function} props.example
6459
- * @param {Function} props.variables
6460
- * @param {Function} props.onFocus
6461
- * @param {Function} props.onBlur
6462
- */
6463
- function FeelTemplatingEntry(props) {
6464
- return jsx(FeelEntry, {
6465
- class: "bio-properties-panel-feel-templating",
6466
- OptionalComponent: CodeEditor$1,
6467
- ...props
6468
- });
6469
- }
6470
- function isEdited$6(node) {
6471
- if (!node) {
6472
- return false;
6473
- }
6474
- if (node.type === 'checkbox') {
6475
- return !!node.checked || node.classList.contains('edited');
6476
- }
6477
- return !!node.value || node.classList.contains('edited');
6478
- }
6479
-
6480
- // helpers /////////////////
6481
-
6482
- function prefixId$5(id) {
6483
- return `bio-properties-panel-${id}`;
6484
- }
6485
- function NumberField(props) {
6486
- const {
6487
- debounce,
6488
- disabled,
6489
- id,
6490
- label,
6491
- max,
6492
- min,
6493
- onInput,
6494
- step,
6495
- value = '',
6496
- onFocus,
6497
- onBlur
6498
- } = props;
6499
- const [localValue, setLocalValue] = useState(value);
6500
- const handleInputCallback = useMemo(() => {
6501
- return debounce(event => {
6502
- const {
6503
- validity,
6504
- value
6505
- } = event.target;
6506
- if (validity.valid) {
6507
- onInput(value ? parseFloat(value) : undefined);
6508
- }
6509
- });
6510
- }, [onInput, debounce]);
6511
- const handleInput = e => {
6512
- handleInputCallback(e);
6513
- setLocalValue(e.target.value);
6514
- };
6515
- useEffect(() => {
6516
- if (value === localValue) {
6517
- return;
6518
- }
6519
- setLocalValue(value);
6520
- }, [value]);
6521
- return jsxs("div", {
6522
- class: "bio-properties-panel-numberfield",
6523
- children: [jsx("label", {
6524
- for: prefixId$4(id),
6525
- class: "bio-properties-panel-label",
6526
- children: label
6527
- }), jsx("input", {
6528
- id: prefixId$4(id),
6529
- type: "number",
6530
- name: id,
6531
- spellCheck: "false",
6532
- autoComplete: "off",
6533
- disabled: disabled,
6534
- class: "bio-properties-panel-input",
6535
- max: max,
6536
- min: min,
6537
- onInput: handleInput,
6538
- onFocus: onFocus,
6539
- onBlur: onBlur,
6540
- step: step,
6541
- value: localValue
6542
- })]
6543
- });
6544
- }
6545
-
6546
- /**
6547
- * @param {Object} props
6548
- * @param {Boolean} props.debounce
6549
- * @param {String} props.description
6550
- * @param {Boolean} props.disabled
6551
- * @param {Object} props.element
6552
- * @param {Function} props.getValue
6553
- * @param {String} props.id
6554
- * @param {String} props.label
6555
- * @param {String} props.max
6556
- * @param {String} props.min
6557
- * @param {Function} props.setValue
6558
- * @param {Function} props.onFocus
6559
- * @param {Function} props.onBlur
6560
- * @param {String} props.step
6561
- * @param {Function} props.validate
6562
- */
6563
- function NumberFieldEntry(props) {
6564
- const {
6565
- debounce,
6566
- description,
6567
- disabled,
6568
- element,
6569
- getValue,
6570
- id,
6571
- label,
6572
- max,
6573
- min,
6574
- setValue,
6575
- step,
6576
- onFocus,
6577
- onBlur,
6578
- validate
6579
- } = props;
6580
- const [cachedInvalidValue, setCachedInvalidValue] = useState(null);
6581
- const globalError = useError(id);
6582
- const [localError, setLocalError] = useState(null);
6583
- let value = getValue(element);
6584
- const previousValue = usePrevious(value);
6585
- useEffect(() => {
6586
- if (isFunction(validate)) {
6587
- const newValidationError = validate(value) || null;
6588
- setLocalError(newValidationError);
6589
- }
6590
- }, [value]);
6591
- const onInput = newValue => {
6592
- let newValidationError = null;
6593
- if (isFunction(validate)) {
6594
- newValidationError = validate(newValue) || null;
6595
- }
6596
- if (newValidationError) {
6597
- setCachedInvalidValue(newValue);
6598
- } else {
6599
- setValue(newValue);
6600
- }
6601
- setLocalError(newValidationError);
6602
- };
6603
- if (previousValue === value && localError) {
6604
- value = cachedInvalidValue;
6605
- }
6606
- const error = globalError || localError;
6607
- return jsxs("div", {
6608
- class: classnames('bio-properties-panel-entry', error ? 'has-error' : ''),
6609
- "data-entry-id": id,
6610
- children: [jsx(NumberField, {
6611
- debounce: debounce,
6612
- disabled: disabled,
6613
- id: id,
6614
- label: label,
6615
- onFocus: onFocus,
6616
- onBlur: onBlur,
6617
- onInput: onInput,
6618
- max: max,
6619
- min: min,
6620
- step: step,
6621
- value: value
6622
- }, element), error && jsx("div", {
6623
- class: "bio-properties-panel-error",
6624
- children: error
6625
- }), jsx(Description$1, {
6626
- forId: id,
6627
- element: element,
6628
- value: description
6629
- })]
6648
+ * @param {Function} props.show
6649
+ * @param {Function} props.example
6650
+ * @param {Function} props.variables
6651
+ * @param {Function} props.onFocus
6652
+ * @param {Function} props.onBlur
6653
+ */
6654
+ function FeelNumberEntry(props) {
6655
+ return jsx(FeelEntry, {
6656
+ class: "bio-properties-panel-feel-number",
6657
+ OptionalComponent: OptionalFeelNumberField,
6658
+ ...props
6630
6659
  });
6631
6660
  }
6632
- function isEdited$4(node) {
6633
- return node && !!node.value;
6661
+
6662
+ /**
6663
+ * @param {Object} props
6664
+ * @param {Object} props.element
6665
+ * @param {String} props.id
6666
+ * @param {String} props.description
6667
+ * @param {Boolean} props.debounce
6668
+ * @param {Boolean} props.disabled
6669
+ * @param {Boolean} props.feel
6670
+ * @param {String} props.label
6671
+ * @param {Function} props.getValue
6672
+ * @param {Function} props.setValue
6673
+ * @param {Function} props.tooltipContainer
6674
+ * @param {Function} props.validate
6675
+ * @param {Function} props.show
6676
+ * @param {Function} props.example
6677
+ * @param {Function} props.variables
6678
+ * @param {Function} props.onFocus
6679
+ * @param {Function} props.onBlur
6680
+ */
6681
+ function FeelToggleSwitchEntry(props) {
6682
+ return jsx(FeelEntry, {
6683
+ class: "bio-properties-panel-feel-toggle-switch",
6684
+ OptionalComponent: OptionalFeelToggleSwitch,
6685
+ ...props
6686
+ });
6687
+ }
6688
+
6689
+ /**
6690
+ * @param {Object} props
6691
+ * @param {Object} props.element
6692
+ * @param {String} props.id
6693
+ * @param {String} props.description
6694
+ * @param {String} props.hostLanguage
6695
+ * @param {Boolean} props.singleLine
6696
+ * @param {Boolean} props.debounce
6697
+ * @param {Boolean} props.disabled
6698
+ * @param {Boolean} props.feel
6699
+ * @param {String} props.label
6700
+ * @param {Function} props.getValue
6701
+ * @param {Function} props.setValue
6702
+ * @param {Function} props.tooltipContainer
6703
+ * @param {Function} props.validate
6704
+ * @param {Function} props.show
6705
+ * @param {Function} props.example
6706
+ * @param {Function} props.variables
6707
+ * @param {Function} props.onFocus
6708
+ * @param {Function} props.onBlur
6709
+ */
6710
+ function FeelTemplatingEntry(props) {
6711
+ return jsx(FeelEntry, {
6712
+ class: "bio-properties-panel-feel-templating",
6713
+ OptionalComponent: CodeEditor$1,
6714
+ ...props
6715
+ });
6716
+ }
6717
+ function isEdited$5(node) {
6718
+ if (!node) {
6719
+ return false;
6720
+ }
6721
+ if (node.type === 'checkbox') {
6722
+ return !!node.checked || node.classList.contains('edited');
6723
+ }
6724
+ return !!node.value || node.classList.contains('edited');
6634
6725
  }
6635
6726
 
6636
6727
  // helpers /////////////////
@@ -7087,11 +7178,11 @@ function prefixId(id) {
7087
7178
  return `bio-properties-panel-${id}`;
7088
7179
  }
7089
7180
 
7090
- /**
7091
- * @param {string} type
7092
- * @param {boolean} [strict]
7093
- *
7094
- * @returns {any}
7181
+ /**
7182
+ * @param {string} type
7183
+ * @param {boolean} [strict]
7184
+ *
7185
+ * @returns {any}
7095
7186
  */
7096
7187
  function getService(type, strict) {}
7097
7188
  const PropertiesPanelContext = createContext({
@@ -7180,8 +7271,8 @@ const PropertiesPanelHeaderProvider = {
7180
7271
  }
7181
7272
  };
7182
7273
 
7183
- /**
7184
- * Provide placeholders for empty and multiple state.
7274
+ /**
7275
+ * Provide placeholders for empty and multiple state.
7185
7276
  */
7186
7277
  const PropertiesPanelPlaceholderProvider = {
7187
7278
  getEmpty: () => {
@@ -7253,10 +7344,10 @@ function useService (type, strict) {
7253
7344
  return getService(type, strict);
7254
7345
  }
7255
7346
 
7256
- /**
7257
- * Retrieve list of variables from the form schema.
7258
- *
7259
- * @returns { string[] } list of variables used in form schema
7347
+ /**
7348
+ * Retrieve list of variables from the form schema.
7349
+ *
7350
+ * @returns { string[] } list of variables used in form schema
7260
7351
  */
7261
7352
  function useVariables() {
7262
7353
  const form = useService('formEditor');
@@ -7279,7 +7370,7 @@ function AltTextEntry(props) {
7279
7370
  component: AltText,
7280
7371
  editField: editField,
7281
7372
  field: field,
7282
- isEdited: isEdited$6
7373
+ isEdited: isEdited$5
7283
7374
  });
7284
7375
  }
7285
7376
  return entries;
@@ -7301,7 +7392,7 @@ function AltText(props) {
7301
7392
  const setValue = value => {
7302
7393
  return editField(field, path, value);
7303
7394
  };
7304
- return FeelEntry({
7395
+ return FeelTemplatingEntry({
7305
7396
  debounce,
7306
7397
  element: field,
7307
7398
  feel: 'optional',
@@ -7309,6 +7400,7 @@ function AltText(props) {
7309
7400
  id,
7310
7401
  label: 'Alternative text',
7311
7402
  setValue,
7403
+ singleLine: true,
7312
7404
  variables
7313
7405
  });
7314
7406
  }
@@ -7397,7 +7489,7 @@ function DescriptionEntry(props) {
7397
7489
  component: Description,
7398
7490
  editField: editField,
7399
7491
  field: field,
7400
- isEdited: isEdited$6
7492
+ isEdited: isEdited$5
7401
7493
  });
7402
7494
  }
7403
7495
  return entries;
@@ -7863,7 +7955,7 @@ function LabelEntry(props) {
7863
7955
  component: DateLabel,
7864
7956
  editField,
7865
7957
  field,
7866
- isEdited: isEdited$6
7958
+ isEdited: isEdited$5
7867
7959
  });
7868
7960
  }
7869
7961
  if (subtype === DATETIME_SUBTYPES.TIME || subtype === DATETIME_SUBTYPES.DATETIME) {
@@ -7872,7 +7964,7 @@ function LabelEntry(props) {
7872
7964
  component: TimeLabel,
7873
7965
  editField,
7874
7966
  field,
7875
- isEdited: isEdited$6
7967
+ isEdited: isEdited$5
7876
7968
  });
7877
7969
  }
7878
7970
  } else if (INPUTS.includes(type) || type === 'button') {
@@ -7881,7 +7973,7 @@ function LabelEntry(props) {
7881
7973
  component: Label$1,
7882
7974
  editField,
7883
7975
  field,
7884
- isEdited: isEdited$6
7976
+ isEdited: isEdited$5
7885
7977
  });
7886
7978
  }
7887
7979
  return entries;
@@ -7986,7 +8078,7 @@ function SourceEntry(props) {
7986
8078
  component: Source,
7987
8079
  editField: editField,
7988
8080
  field: field,
7989
- isEdited: isEdited$6
8081
+ isEdited: isEdited$5
7990
8082
  });
7991
8083
  }
7992
8084
  return entries;
@@ -8008,7 +8100,7 @@ function Source(props) {
8008
8100
  const setValue = value => {
8009
8101
  return editField(field, path, value);
8010
8102
  };
8011
- return FeelEntry({
8103
+ return FeelTemplatingEntry({
8012
8104
  debounce,
8013
8105
  description: 'Expression or static value (link/data URI)',
8014
8106
  element: field,
@@ -8017,6 +8109,7 @@ function Source(props) {
8017
8109
  id,
8018
8110
  label: 'Image source',
8019
8111
  setValue,
8112
+ singleLine: true,
8020
8113
  variables
8021
8114
  });
8022
8115
  }
@@ -8041,7 +8134,7 @@ function TextEntry(props) {
8041
8134
  component: Text,
8042
8135
  editField: editField,
8043
8136
  field: field,
8044
- isEdited: isEdited$6
8137
+ isEdited: isEdited$5
8045
8138
  }];
8046
8139
 
8047
8140
  // todo: skipped to make the release without too much risk
@@ -8110,7 +8203,7 @@ function NumberEntries(props) {
8110
8203
  entries.push({
8111
8204
  id: id + '-decimalDigits',
8112
8205
  component: NumberDecimalDigits,
8113
- isEdited: isEdited$4,
8206
+ isEdited: isEdited$6,
8114
8207
  editField,
8115
8208
  field
8116
8209
  });
@@ -8706,14 +8799,14 @@ function Value(props) {
8706
8799
 
8707
8800
  // helpers //////////
8708
8801
 
8709
- /**
8710
- * Returns copy of object with updated value.
8711
- *
8712
- * @param {Object} properties
8713
- * @param {string} key
8714
- * @param {string} value
8715
- *
8716
- * @returns {Object}
8802
+ /**
8803
+ * Returns copy of object with updated value.
8804
+ *
8805
+ * @param {Object} properties
8806
+ * @param {string} key
8807
+ * @param {string} value
8808
+ *
8809
+ * @returns {Object}
8717
8810
  */
8718
8811
  function updateValue(properties, key, value) {
8719
8812
  return {
@@ -8722,14 +8815,14 @@ function updateValue(properties, key, value) {
8722
8815
  };
8723
8816
  }
8724
8817
 
8725
- /**
8726
- * Returns copy of object with updated key.
8727
- *
8728
- * @param {Object} properties
8729
- * @param {string} oldKey
8730
- * @param {string} newKey
8731
- *
8732
- * @returns {Object}
8818
+ /**
8819
+ * Returns copy of object with updated key.
8820
+ *
8821
+ * @param {Object} properties
8822
+ * @param {string} oldKey
8823
+ * @param {string} newKey
8824
+ *
8825
+ * @returns {Object}
8733
8826
  */
8734
8827
  function updateKey(properties, oldKey, newKey) {
8735
8828
  return Object.entries(properties).reduce((newProperties, entry) => {
@@ -8741,6 +8834,34 @@ function updateKey(properties, oldKey, newKey) {
8741
8834
  }, {});
8742
8835
  }
8743
8836
 
8837
+ function AutoFocusSelectEntry(props) {
8838
+ const {
8839
+ autoFocusEntry,
8840
+ element,
8841
+ getValue
8842
+ } = props;
8843
+ const value = getValue(element);
8844
+ const prevValue = usePrevious(value);
8845
+ const eventBus = useService('eventBus');
8846
+
8847
+ // auto focus specifc other entry when selected value changed
8848
+ useEffect(() => {
8849
+ if (autoFocusEntry && prevValue && value !== prevValue) {
8850
+ // @Note(pinussilvestrus): There is an issue in the properties
8851
+ // panel so we have to wait a bit before showing the entry.
8852
+ // Cf. https://github.com/camunda/linting/blob/4f5328e2722f73ae60ae584c5f576eaec3999cb2/lib/modeler/Linting.js#L37
8853
+ setTimeout(() => {
8854
+ eventBus.fire('propertiesPanel.showEntry', {
8855
+ id: autoFocusEntry
8856
+ });
8857
+ });
8858
+ }
8859
+ }, [value, autoFocusEntry, prevValue, eventBus]);
8860
+ return jsx(SelectEntry, {
8861
+ ...props
8862
+ });
8863
+ }
8864
+
8744
8865
  function ValuesSourceSelectEntry(props) {
8745
8866
  const {
8746
8867
  editField,
@@ -8779,7 +8900,8 @@ function ValuesSourceSelect(props) {
8779
8900
  value: valueSource
8780
8901
  }));
8781
8902
  };
8782
- return SelectEntry({
8903
+ return AutoFocusSelectEntry({
8904
+ autoFocusEntry: getAutoFocusEntryId(field),
8783
8905
  label: 'Type',
8784
8906
  element: field,
8785
8907
  getOptions: getValuesSourceOptions,
@@ -8789,6 +8911,20 @@ function ValuesSourceSelect(props) {
8789
8911
  });
8790
8912
  }
8791
8913
 
8914
+ // helpers //////////
8915
+
8916
+ function getAutoFocusEntryId(field) {
8917
+ const valuesSource = getValuesSource(field);
8918
+ if (valuesSource === VALUES_SOURCES.EXPRESSION) {
8919
+ return `${field.id}-valuesExpression-expression`;
8920
+ } else if (valuesSource === VALUES_SOURCES.INPUT) {
8921
+ return `${field.id}-dynamicValues-key`;
8922
+ } else if (valuesSource === VALUES_SOURCES.STATIC) {
8923
+ return `${field.id}-staticValues-0-label`;
8924
+ }
8925
+ return null;
8926
+ }
8927
+
8792
8928
  function InputKeyValuesSourceEntry(props) {
8793
8929
  const {
8794
8930
  editField,
@@ -8945,7 +9081,7 @@ function AdornerEntry(props) {
8945
9081
  entries.push({
8946
9082
  id: 'prefix-adorner',
8947
9083
  component: PrefixAdorner,
8948
- isEdited: isEdited,
9084
+ isEdited: isEdited$5,
8949
9085
  editField,
8950
9086
  field,
8951
9087
  onChange,
@@ -8954,7 +9090,7 @@ function AdornerEntry(props) {
8954
9090
  entries.push({
8955
9091
  id: 'suffix-adorner',
8956
9092
  component: SuffixAdorner,
8957
- isEdited: isEdited,
9093
+ isEdited: isEdited$5,
8958
9094
  editField,
8959
9095
  field,
8960
9096
  onChange,
@@ -8971,13 +9107,19 @@ function PrefixAdorner(props) {
8971
9107
  getValue
8972
9108
  } = props;
8973
9109
  const debounce = useService('debounce');
8974
- return TextfieldEntry({
9110
+ const variables = useVariables().map(name => ({
9111
+ name
9112
+ }));
9113
+ return FeelTemplatingEntry({
8975
9114
  debounce,
8976
9115
  element: field,
9116
+ feel: 'optional',
8977
9117
  getValue: getValue('prefixAdorner'),
8978
9118
  id,
8979
9119
  label: 'Prefix',
8980
- setValue: onChange('prefixAdorner')
9120
+ setValue: onChange('prefixAdorner'),
9121
+ singleLine: true,
9122
+ variables
8981
9123
  });
8982
9124
  }
8983
9125
  function SuffixAdorner(props) {
@@ -8988,13 +9130,18 @@ function SuffixAdorner(props) {
8988
9130
  getValue
8989
9131
  } = props;
8990
9132
  const debounce = useService('debounce');
8991
- return TextfieldEntry({
9133
+ const variables = useVariables().map(name => ({
9134
+ name
9135
+ }));
9136
+ return FeelTemplatingEntry({
8992
9137
  debounce,
8993
9138
  element: field,
8994
9139
  getValue: getValue('suffixAdorner'),
8995
9140
  id,
8996
9141
  label: 'Suffix',
8997
- setValue: onChange('suffixAdorner')
9142
+ setValue: onChange('suffixAdorner'),
9143
+ singleLine: true,
9144
+ variables
8998
9145
  });
8999
9146
  }
9000
9147
 
@@ -9013,7 +9160,7 @@ function ReadonlyEntry(props) {
9013
9160
  component: Readonly,
9014
9161
  editField: editField,
9015
9162
  field: field,
9016
- isEdited: isEdited$6
9163
+ isEdited: isEdited$5
9017
9164
  });
9018
9165
  }
9019
9166
  return entries;
@@ -9057,7 +9204,7 @@ function ConditionEntry(props) {
9057
9204
  component: Condition,
9058
9205
  editField: editField,
9059
9206
  field: field,
9060
- isEdited: isEdited$6
9207
+ isEdited: isEdited$5
9061
9208
  }];
9062
9209
  }
9063
9210
  function Condition(props) {
@@ -9095,6 +9242,55 @@ function Condition(props) {
9095
9242
  });
9096
9243
  }
9097
9244
 
9245
+ function ValuesExpressionEntry(props) {
9246
+ const {
9247
+ editField,
9248
+ field,
9249
+ id
9250
+ } = props;
9251
+ return [{
9252
+ id: id + '-expression',
9253
+ component: ValuesExpression,
9254
+ label: 'Values expression',
9255
+ isEdited: isEdited$5,
9256
+ editField,
9257
+ field
9258
+ }];
9259
+ }
9260
+ function ValuesExpression(props) {
9261
+ const {
9262
+ editField,
9263
+ field,
9264
+ id
9265
+ } = props;
9266
+ const debounce = useService('debounce');
9267
+ const variables = useVariables().map(name => ({
9268
+ name
9269
+ }));
9270
+ const path = VALUES_SOURCES_PATHS[VALUES_SOURCES.EXPRESSION];
9271
+ const schema = '[\n {\n "label": "dollar",\n "value": "$"\n }\n]';
9272
+ const description = jsxs("div", {
9273
+ children: ["Define an expression to populate the options from.", jsx("br", {}), jsx("br", {}), "The expression may result in an array of simple values or alternatively follow this schema:", jsx("pre", {
9274
+ children: jsx("code", {
9275
+ children: schema
9276
+ })
9277
+ })]
9278
+ });
9279
+ const getValue = () => get(field, path, '');
9280
+ const setValue = value => editField(field, path, value || '');
9281
+ return FeelEntry({
9282
+ debounce,
9283
+ description,
9284
+ element: field,
9285
+ feel: 'required',
9286
+ getValue,
9287
+ id,
9288
+ label: 'Options expression',
9289
+ setValue,
9290
+ variables
9291
+ });
9292
+ }
9293
+
9098
9294
  function GeneralGroup(field, editField, getService) {
9099
9295
  const entries = [...IdEntry({
9100
9296
  field,
@@ -9239,14 +9435,14 @@ function ValidationGroup(field, editField) {
9239
9435
  component: MinLength,
9240
9436
  getValue,
9241
9437
  field,
9242
- isEdited: isEdited$4,
9438
+ isEdited: isEdited$5,
9243
9439
  onChange
9244
9440
  }, {
9245
9441
  id: 'maxLength',
9246
9442
  component: MaxLength,
9247
9443
  getValue,
9248
9444
  field,
9249
- isEdited: isEdited$4,
9445
+ isEdited: isEdited$5,
9250
9446
  onChange
9251
9447
  });
9252
9448
  }
@@ -9266,14 +9462,14 @@ function ValidationGroup(field, editField) {
9266
9462
  component: Min,
9267
9463
  getValue,
9268
9464
  field,
9269
- isEdited: isEdited$4,
9465
+ isEdited: isEdited$5,
9270
9466
  onChange
9271
9467
  }, {
9272
9468
  id: 'max',
9273
9469
  component: Max,
9274
9470
  getValue,
9275
9471
  field,
9276
- isEdited: isEdited$4,
9472
+ isEdited: isEdited$5,
9277
9473
  onChange
9278
9474
  });
9279
9475
  }
@@ -9306,14 +9502,19 @@ function MinLength(props) {
9306
9502
  onChange
9307
9503
  } = props;
9308
9504
  const debounce = useService('debounce');
9309
- return NumberFieldEntry({
9505
+ const variables = useVariables().map(name => ({
9506
+ name
9507
+ }));
9508
+ return FeelNumberEntry({
9310
9509
  debounce,
9311
9510
  element: field,
9511
+ feel: 'optional',
9312
9512
  getValue: getValue('minLength'),
9313
9513
  id,
9314
9514
  label: 'Minimum length',
9315
9515
  min: 0,
9316
- setValue: onChange('minLength')
9516
+ setValue: onChange('minLength'),
9517
+ variables
9317
9518
  });
9318
9519
  }
9319
9520
  function MaxLength(props) {
@@ -9324,14 +9525,19 @@ function MaxLength(props) {
9324
9525
  onChange
9325
9526
  } = props;
9326
9527
  const debounce = useService('debounce');
9327
- return NumberFieldEntry({
9528
+ const variables = useVariables().map(name => ({
9529
+ name
9530
+ }));
9531
+ return FeelNumberEntry({
9328
9532
  debounce,
9329
9533
  element: field,
9534
+ feel: 'optional',
9330
9535
  getValue: getValue('maxLength'),
9331
9536
  id,
9332
9537
  label: 'Maximum length',
9333
9538
  min: 0,
9334
- setValue: onChange('maxLength')
9539
+ setValue: onChange('maxLength'),
9540
+ variables
9335
9541
  });
9336
9542
  }
9337
9543
  function Pattern(props) {
@@ -9359,14 +9565,19 @@ function Min(props) {
9359
9565
  onChange
9360
9566
  } = props;
9361
9567
  const debounce = useService('debounce');
9362
- return NumberFieldEntry({
9568
+ const variables = useVariables().map(name => ({
9569
+ name
9570
+ }));
9571
+ return FeelNumberEntry({
9363
9572
  debounce,
9364
9573
  element: field,
9574
+ feel: 'optional',
9365
9575
  id,
9366
9576
  label: 'Minimum',
9367
9577
  step: 'any',
9368
9578
  getValue: getValue('min'),
9369
- setValue: onChange('min')
9579
+ setValue: onChange('min'),
9580
+ variables
9370
9581
  });
9371
9582
  }
9372
9583
  function Max(props) {
@@ -9377,14 +9588,19 @@ function Max(props) {
9377
9588
  onChange
9378
9589
  } = props;
9379
9590
  const debounce = useService('debounce');
9380
- return NumberFieldEntry({
9591
+ const variables = useVariables().map(name => ({
9592
+ name
9593
+ }));
9594
+ return FeelNumberEntry({
9381
9595
  debounce,
9382
9596
  element: field,
9597
+ feel: 'optional',
9383
9598
  id,
9384
9599
  label: 'Maximum',
9385
9600
  step: 'any',
9386
9601
  getValue: getValue('max'),
9387
- setValue: onChange('max')
9602
+ setValue: onChange('max'),
9603
+ variables
9388
9604
  });
9389
9605
  }
9390
9606
  function ValidationType(props) {
@@ -9423,8 +9639,8 @@ function ValuesGroups(field, editField) {
9423
9639
  };
9424
9640
  const valuesSourceId = `${fieldId}-valuesSource`;
9425
9641
 
9426
- /**
9427
- * @type {Array<Group|ListGroup>}
9642
+ /**
9643
+ * @type {Array<Group|ListGroup>}
9428
9644
  */
9429
9645
  const groups = [{
9430
9646
  id: valuesSourceId,
@@ -9458,6 +9674,17 @@ function ValuesGroups(field, editField) {
9458
9674
  id: staticValuesId
9459
9675
  })
9460
9676
  });
9677
+ } else if (valuesSource === VALUES_SOURCES.EXPRESSION) {
9678
+ const valuesExpressionId = `${fieldId}-valuesExpression`;
9679
+ groups.push({
9680
+ id: valuesExpressionId,
9681
+ label: 'Options expression',
9682
+ component: Group,
9683
+ entries: ValuesExpressionEntry({
9684
+ ...context,
9685
+ id: valuesExpressionId
9686
+ })
9687
+ });
9461
9688
  }
9462
9689
  return groups;
9463
9690
  }
@@ -9526,13 +9753,13 @@ function CustomValuesGroup(field, editField) {
9526
9753
 
9527
9754
  // helpers //////////
9528
9755
 
9529
- /**
9530
- * Returns copy of object without key.
9531
- *
9532
- * @param {Object} properties
9533
- * @param {string} oldKey
9534
- *
9535
- * @returns {Object}
9756
+ /**
9757
+ * Returns copy of object without key.
9758
+ *
9759
+ * @param {Object} properties
9760
+ * @param {string} oldKey
9761
+ *
9762
+ * @returns {Object}
9536
9763
  */
9537
9764
  function removeKey(properties, oldKey) {
9538
9765
  return Object.entries(properties).reduce((newProperties, entry) => {
@@ -9635,9 +9862,9 @@ function FormPropertiesPanel(props) {
9635
9862
  });
9636
9863
  }, [eventBus, formEditor, selectionModule]);
9637
9864
  useLayoutEffect(() => {
9638
- /**
9639
- * TODO(pinussilvestrus): update with actual updated element,
9640
- * once we have a proper updater/change support
9865
+ /**
9866
+ * TODO(pinussilvestrus): update with actual updated element,
9867
+ * once we have a proper updater/change support
9641
9868
  */
9642
9869
  eventBus.on('changed', refresh);
9643
9870
  eventBus.on('import.done', refresh);
@@ -9689,10 +9916,10 @@ class PropertiesPanelRenderer {
9689
9916
  });
9690
9917
  }
9691
9918
 
9692
- /**
9693
- * Attach the properties panel to a parent node.
9694
- *
9695
- * @param {HTMLElement} container
9919
+ /**
9920
+ * Attach the properties panel to a parent node.
9921
+ *
9922
+ * @param {HTMLElement} container
9696
9923
  */
9697
9924
  attachTo(container) {
9698
9925
  if (!container) {
@@ -9712,8 +9939,8 @@ class PropertiesPanelRenderer {
9712
9939
  this._eventBus.fire('propertiesPanel.attach');
9713
9940
  }
9714
9941
 
9715
- /**
9716
- * Detach the properties panel from its parent node.
9942
+ /**
9943
+ * Detach the properties panel from its parent node.
9717
9944
  */
9718
9945
  detach() {
9719
9946
  const parentNode = this._container.parentNode;
@@ -9743,10 +9970,10 @@ var PropertiesPanelModule = {
9743
9970
  propertiesPanel: ['type', PropertiesPanelRenderer]
9744
9971
  };
9745
9972
 
9746
- /**
9747
- * Manages the rendering of visual plugins.
9748
- * @constructor
9749
- * @param {Object} eventBus - Event bus for the application.
9973
+ /**
9974
+ * Manages the rendering of visual plugins.
9975
+ * @constructor
9976
+ * @param {Object} eventBus - Event bus for the application.
9750
9977
  */
9751
9978
  class RenderInjector extends SectionModuleBase {
9752
9979
  constructor(eventBus) {
@@ -9755,10 +9982,10 @@ class RenderInjector extends SectionModuleBase {
9755
9982
  this.registeredRenderers = [];
9756
9983
  }
9757
9984
 
9758
- /**
9759
- * Inject a new renderer into the injector.
9760
- * @param {string} identifier - Identifier for the renderer.
9761
- * @param {Function} Renderer - The renderer function.
9985
+ /**
9986
+ * Inject a new renderer into the injector.
9987
+ * @param {string} identifier - Identifier for the renderer.
9988
+ * @param {Function} Renderer - The renderer function.
9762
9989
  */
9763
9990
  attachRenderer(identifier, Renderer) {
9764
9991
  this.registeredRenderers = [...this.registeredRenderers, {
@@ -9767,17 +9994,17 @@ class RenderInjector extends SectionModuleBase {
9767
9994
  }];
9768
9995
  }
9769
9996
 
9770
- /**
9771
- * Detach a renderer from the by key injector.
9772
- * @param {string} identifier - Identifier for the renderer.
9997
+ /**
9998
+ * Detach a renderer from the by key injector.
9999
+ * @param {string} identifier - Identifier for the renderer.
9773
10000
  */
9774
10001
  detachRenderer(identifier) {
9775
10002
  this.registeredRenderers = this.registeredRenderers.filter(r => r.identifier !== identifier);
9776
10003
  }
9777
10004
 
9778
- /**
9779
- * Returns the registered renderers.
9780
- * @returns {Array} Array of registered renderers.
10005
+ /**
10006
+ * Returns the registered renderers.
10007
+ * @returns {Array} Array of registered renderers.
9781
10008
  */
9782
10009
  fetchRenderers() {
9783
10010
  return this.registeredRenderers;
@@ -9811,48 +10038,48 @@ var ExpressionLanguageModule = {
9811
10038
 
9812
10039
  const ids = new Ids([32, 36, 1]);
9813
10040
 
9814
- /**
9815
- * @typedef { import('./types').Injector } Injector
9816
- * @typedef { import('./types').Module } Module
9817
- * @typedef { import('./types').Schema } Schema
9818
- *
9819
- * @typedef { import('./types').FormEditorOptions } FormEditorOptions
9820
- * @typedef { import('./types').FormEditorProperties } FormEditorProperties
9821
- *
9822
- * @typedef { {
9823
- * properties: FormEditorProperties,
9824
- * schema: Schema
9825
- * } } State
9826
- *
9827
- * @typedef { (type:string, priority:number, handler:Function) => void } OnEventWithPriority
9828
- * @typedef { (type:string, handler:Function) => void } OnEventWithOutPriority
9829
- * @typedef { OnEventWithPriority & OnEventWithOutPriority } OnEventType
10041
+ /**
10042
+ * @typedef { import('./types').Injector } Injector
10043
+ * @typedef { import('./types').Module } Module
10044
+ * @typedef { import('./types').Schema } Schema
10045
+ *
10046
+ * @typedef { import('./types').FormEditorOptions } FormEditorOptions
10047
+ * @typedef { import('./types').FormEditorProperties } FormEditorProperties
10048
+ *
10049
+ * @typedef { {
10050
+ * properties: FormEditorProperties,
10051
+ * schema: Schema
10052
+ * } } State
10053
+ *
10054
+ * @typedef { (type:string, priority:number, handler:Function) => void } OnEventWithPriority
10055
+ * @typedef { (type:string, handler:Function) => void } OnEventWithOutPriority
10056
+ * @typedef { OnEventWithPriority & OnEventWithOutPriority } OnEventType
9830
10057
  */
9831
10058
 
9832
- /**
9833
- * The form editor.
10059
+ /**
10060
+ * The form editor.
9834
10061
  */
9835
10062
  class FormEditor {
9836
- /**
9837
- * @constructor
9838
- * @param {FormEditorOptions} options
10063
+ /**
10064
+ * @constructor
10065
+ * @param {FormEditorOptions} options
9839
10066
  */
9840
10067
  constructor(options = {}) {
9841
- /**
9842
- * @public
9843
- * @type {OnEventType}
10068
+ /**
10069
+ * @public
10070
+ * @type {OnEventType}
9844
10071
  */
9845
10072
  this.on = this._onEvent;
9846
10073
 
9847
- /**
9848
- * @public
9849
- * @type {String}
10074
+ /**
10075
+ * @public
10076
+ * @type {String}
9850
10077
  */
9851
10078
  this._id = ids.next();
9852
10079
 
9853
- /**
9854
- * @private
9855
- * @type {Element}
10080
+ /**
10081
+ * @private
10082
+ * @type {Element}
9856
10083
  */
9857
10084
  this._container = createFormContainer();
9858
10085
  this._container.setAttribute('input-handle-modified-keys', 'z,y');
@@ -9863,15 +10090,15 @@ class FormEditor {
9863
10090
  properties = {}
9864
10091
  } = options;
9865
10092
 
9866
- /**
9867
- * @private
9868
- * @type {any}
10093
+ /**
10094
+ * @private
10095
+ * @type {any}
9869
10096
  */
9870
10097
  this.exporter = exporter;
9871
10098
 
9872
- /**
9873
- * @private
9874
- * @type {State}
10099
+ /**
10100
+ * @private
10101
+ * @type {State}
9875
10102
  */
9876
10103
  this._state = {
9877
10104
  properties,
@@ -9900,10 +10127,10 @@ class FormEditor {
9900
10127
  this._detach(false);
9901
10128
  }
9902
10129
 
9903
- /**
9904
- * @param {Schema} schema
9905
- *
9906
- * @return {Promise<{ warnings: Array<any> }>}
10130
+ /**
10131
+ * @param {Schema} schema
10132
+ *
10133
+ * @return {Promise<{ warnings: Array<any> }>}
9907
10134
  */
9908
10135
  importSchema(schema) {
9909
10136
  return new Promise((resolve, reject) => {
@@ -9932,15 +10159,15 @@ class FormEditor {
9932
10159
  });
9933
10160
  }
9934
10161
 
9935
- /**
9936
- * @returns {Schema}
10162
+ /**
10163
+ * @returns {Schema}
9937
10164
  */
9938
10165
  saveSchema() {
9939
10166
  return this.getSchema();
9940
10167
  }
9941
10168
 
9942
- /**
9943
- * @returns {Schema}
10169
+ /**
10170
+ * @returns {Schema}
9944
10171
  */
9945
10172
  getSchema() {
9946
10173
  const {
@@ -9949,8 +10176,8 @@ class FormEditor {
9949
10176
  return exportSchema(schema, this.exporter, schemaVersion);
9950
10177
  }
9951
10178
 
9952
- /**
9953
- * @param {Element|string} parentNode
10179
+ /**
10180
+ * @param {Element|string} parentNode
9954
10181
  */
9955
10182
  attachTo(parentNode) {
9956
10183
  if (!parentNode) {
@@ -9968,10 +10195,10 @@ class FormEditor {
9968
10195
  this._detach();
9969
10196
  }
9970
10197
 
9971
- /**
9972
- * @internal
9973
- *
9974
- * @param {boolean} [emit]
10198
+ /**
10199
+ * @internal
10200
+ *
10201
+ * @param {boolean} [emit]
9975
10202
  */
9976
10203
  _detach(emit = true) {
9977
10204
  const container = this._container,
@@ -9985,9 +10212,9 @@ class FormEditor {
9985
10212
  parentNode.removeChild(container);
9986
10213
  }
9987
10214
 
9988
- /**
9989
- * @param {any} property
9990
- * @param {any} value
10215
+ /**
10216
+ * @param {any} property
10217
+ * @param {any} value
9991
10218
  */
9992
10219
  setProperty(property, value) {
9993
10220
  const properties = set$1(this._getState().properties, [property], value);
@@ -9996,21 +10223,21 @@ class FormEditor {
9996
10223
  });
9997
10224
  }
9998
10225
 
9999
- /**
10000
- * @param {string} type
10001
- * @param {Function} handler
10226
+ /**
10227
+ * @param {string} type
10228
+ * @param {Function} handler
10002
10229
  */
10003
10230
  off(type, handler) {
10004
10231
  this.get('eventBus').off(type, handler);
10005
10232
  }
10006
10233
 
10007
- /**
10008
- * @internal
10009
- *
10010
- * @param {FormEditorOptions} options
10011
- * @param {Element} container
10012
- *
10013
- * @returns {Injector}
10234
+ /**
10235
+ * @internal
10236
+ *
10237
+ * @param {FormEditorOptions} options
10238
+ * @param {Element} container
10239
+ *
10240
+ * @returns {Injector}
10014
10241
  */
10015
10242
  _createInjector(options, container) {
10016
10243
  const {
@@ -10032,22 +10259,22 @@ class FormEditor {
10032
10259
  }, core, ...modules, ...additionalModules]);
10033
10260
  }
10034
10261
 
10035
- /**
10036
- * @internal
10262
+ /**
10263
+ * @internal
10037
10264
  */
10038
10265
  _emit(type, data) {
10039
10266
  this.get('eventBus').fire(type, data);
10040
10267
  }
10041
10268
 
10042
- /**
10043
- * @internal
10269
+ /**
10270
+ * @internal
10044
10271
  */
10045
10272
  _getState() {
10046
10273
  return this._state;
10047
10274
  }
10048
10275
 
10049
- /**
10050
- * @internal
10276
+ /**
10277
+ * @internal
10051
10278
  */
10052
10279
  _setState(state) {
10053
10280
  this._state = {
@@ -10057,15 +10284,15 @@ class FormEditor {
10057
10284
  this._emit('changed', this._getState());
10058
10285
  }
10059
10286
 
10060
- /**
10061
- * @internal
10287
+ /**
10288
+ * @internal
10062
10289
  */
10063
10290
  _getModules() {
10064
10291
  return [ModelingModule, EditorActionsModule, DraggingModule, KeyboardModule, SelectionModule, PaletteModule, ExpressionLanguageModule, MarkdownModule, PropertiesPanelModule, RenderInjectionModule];
10065
10292
  }
10066
10293
 
10067
- /**
10068
- * @internal
10294
+ /**
10295
+ * @internal
10069
10296
  */
10070
10297
  _onEvent(type, priority, handler) {
10071
10298
  this.get('eventBus').on(type, priority, handler);