@bpmn-io/form-js-editor 0.7.1 → 0.8.0-alpha.1

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.
Files changed (53) hide show
  1. package/README.md +1 -0
  2. package/dist/assets/form-js-editor.css +26 -214
  3. package/dist/assets/properties-panel.css +930 -0
  4. package/dist/index.cjs +3099 -1072
  5. package/dist/index.cjs.map +1 -1
  6. package/dist/index.es.js +3036 -1010
  7. package/dist/index.es.js.map +1 -1
  8. package/dist/types/FormEditor.d.ts +6 -4
  9. package/dist/types/features/palette/PaletteRenderer.d.ts +33 -0
  10. package/dist/types/{render/components/palette → features/palette/components}/Palette.d.ts +0 -0
  11. package/dist/types/features/palette/index.d.ts +5 -0
  12. package/dist/types/render/Renderer.d.ts +1 -1
  13. package/dist/types/render/components/{palette/icons → icons}/index.d.ts +2 -0
  14. package/dist/types/render/components/properties-panel/PropertiesPanel.d.ts +1 -1
  15. package/dist/types/render/components/properties-panel/PropertiesPanelHeaderProvider.d.ts +5 -0
  16. package/dist/types/render/components/properties-panel/PropertiesPanelPlaceholderProvider.d.ts +8 -0
  17. package/dist/types/render/components/properties-panel/Util.d.ts +1 -0
  18. package/dist/types/render/components/properties-panel/entries/ActionEntry.d.ts +9 -1
  19. package/dist/types/render/components/properties-panel/entries/ColumnsEntry.d.ts +9 -1
  20. package/dist/types/render/components/properties-panel/entries/CustomValueEntry.d.ts +11 -1
  21. package/dist/types/render/components/properties-panel/entries/DefaultValueEntry.d.ts +1 -1
  22. package/dist/types/render/components/properties-panel/entries/DescriptionEntry.d.ts +9 -1
  23. package/dist/types/render/components/properties-panel/entries/DisabledEntry.d.ts +9 -1
  24. package/dist/types/render/components/properties-panel/entries/IdEntry.d.ts +9 -1
  25. package/dist/types/render/components/properties-panel/entries/InputKeyValuesSourceEntry.d.ts +11 -0
  26. package/dist/types/render/components/properties-panel/entries/KeyEntry.d.ts +9 -1
  27. package/dist/types/render/components/properties-panel/entries/LabelEntry.d.ts +9 -1
  28. package/dist/types/render/components/properties-panel/entries/StaticValuesSourceEntry.d.ts +4 -0
  29. package/dist/types/render/components/properties-panel/entries/TextEntry.d.ts +9 -1
  30. package/dist/types/render/components/properties-panel/entries/ValueEntry.d.ts +11 -1
  31. package/dist/types/render/components/properties-panel/entries/ValuesSourceSelectEntry.d.ts +9 -0
  32. package/dist/types/render/components/properties-panel/entries/ValuesSourceUtil.d.ts +15 -0
  33. package/dist/types/render/components/properties-panel/entries/index.d.ts +3 -0
  34. package/dist/types/render/components/properties-panel/groups/CustomValuesGroup.d.ts +22 -1
  35. package/dist/types/render/components/properties-panel/groups/GeneralGroup.d.ts +5 -1
  36. package/dist/types/render/components/properties-panel/groups/ValidationGroup.d.ts +14 -1
  37. package/dist/types/render/components/properties-panel/groups/ValuesGroups.d.ts +1 -0
  38. package/dist/types/render/components/properties-panel/groups/index.d.ts +1 -1
  39. package/package.json +5 -4
  40. package/dist/types/render/components/properties-panel/components/CheckboxInput.d.ts +0 -1
  41. package/dist/types/render/components/properties-panel/components/CheckboxInputEntry.d.ts +0 -1
  42. package/dist/types/render/components/properties-panel/components/CollapsibleEntry.d.ts +0 -1
  43. package/dist/types/render/components/properties-panel/components/Group.d.ts +0 -1
  44. package/dist/types/render/components/properties-panel/components/NumberInput.d.ts +0 -1
  45. package/dist/types/render/components/properties-panel/components/NumberInputEntry.d.ts +0 -1
  46. package/dist/types/render/components/properties-panel/components/Select.d.ts +0 -1
  47. package/dist/types/render/components/properties-panel/components/SelectEntry.d.ts +0 -1
  48. package/dist/types/render/components/properties-panel/components/TextInput.d.ts +0 -1
  49. package/dist/types/render/components/properties-panel/components/TextInputEntry.d.ts +0 -1
  50. package/dist/types/render/components/properties-panel/components/Textarea.d.ts +0 -1
  51. package/dist/types/render/components/properties-panel/components/TextareaEntry.d.ts +0 -1
  52. package/dist/types/render/components/properties-panel/components/index.d.ts +0 -12
  53. package/dist/types/render/components/properties-panel/groups/ValuesGroup.d.ts +0 -1
package/dist/index.cjs CHANGED
@@ -7,20 +7,22 @@ var Ids = require('ids');
7
7
  var minDash = require('min-dash');
8
8
  var preact = require('preact');
9
9
  var hooks$1 = require('preact/hooks');
10
+ var classnames = require('classnames');
10
11
  var React = require('preact/compat');
11
12
  var jsxRuntime = require('preact/jsx-runtime');
12
- var dragula = require('dragula');
13
13
  var minDom = require('min-dom');
14
+ var dragula = require('dragula');
14
15
  var arrayMove = require('array-move');
15
16
 
16
17
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
17
18
 
18
19
  var Ids__default = /*#__PURE__*/_interopDefaultLegacy(Ids);
20
+ var classnames__default = /*#__PURE__*/_interopDefaultLegacy(classnames);
19
21
  var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
20
22
  var dragula__default = /*#__PURE__*/_interopDefaultLegacy(dragula);
21
23
 
22
24
  var FN_REF = '__fn';
23
- var DEFAULT_PRIORITY$2 = 1000;
25
+ var DEFAULT_PRIORITY$3 = 1000;
24
26
  var slice = Array.prototype.slice;
25
27
  /**
26
28
  * A general purpose event bus.
@@ -136,7 +138,7 @@ EventBus.prototype.on = function (events, priority, callback, that) {
136
138
  if (minDash.isFunction(priority)) {
137
139
  that = callback;
138
140
  callback = priority;
139
- priority = DEFAULT_PRIORITY$2;
141
+ priority = DEFAULT_PRIORITY$3;
140
142
  }
141
143
 
142
144
  if (!minDash.isNumber(priority)) {
@@ -178,7 +180,7 @@ EventBus.prototype.once = function (event, priority, callback, that) {
178
180
  if (minDash.isFunction(priority)) {
179
181
  that = callback;
180
182
  callback = priority;
181
- priority = DEFAULT_PRIORITY$2;
183
+ priority = DEFAULT_PRIORITY$3;
182
184
  }
183
185
 
184
186
  if (!minDash.isNumber(priority)) {
@@ -774,887 +776,2244 @@ function useService (type, strict) {
774
776
  return getService(type, strict);
775
777
  }
776
778
 
777
- function _extends$c() { _extends$c = Object.assign || 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$c.apply(this, arguments); }
778
- var ButtonIcon = (({
779
- styles = {},
780
- ...props
781
- }) => /*#__PURE__*/React__default['default'].createElement("svg", _extends$c({
782
- xmlns: "http://www.w3.org/2000/svg",
783
- width: "54",
784
- height: "54"
785
- }, props), /*#__PURE__*/React__default['default'].createElement("path", {
786
- fillRule: "evenodd",
787
- d: "M45 17a3 3 0 013 3v14a3 3 0 01-3 3H9a3 3 0 01-3-3V20a3 3 0 013-3h36zm-9 8.889H18v2.222h18V25.89z"
788
- })));
779
+ var ArrowIcon = function ArrowIcon(props) {
780
+ return jsxRuntime.jsx("svg", { ...props,
781
+ children: jsxRuntime.jsx("path", {
782
+ fillRule: "evenodd",
783
+ d: "m11.657 8-4.95 4.95a1 1 0 0 1-1.414-1.414L8.828 8 5.293 4.464A1 1 0 1 1 6.707 3.05L11.657 8z"
784
+ })
785
+ });
786
+ };
789
787
 
790
- function _extends$b() { _extends$b = Object.assign || 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$b.apply(this, arguments); }
791
- var CheckboxIcon = (({
792
- styles = {},
793
- ...props
794
- }) => /*#__PURE__*/React__default['default'].createElement("svg", _extends$b({
788
+ ArrowIcon.defaultProps = {
795
789
  xmlns: "http://www.w3.org/2000/svg",
796
- width: "54",
797
- height: "54"
798
- }, props), /*#__PURE__*/React__default['default'].createElement("path", {
799
- d: "M34 18H20a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2V20a2 2 0 00-2-2zm-9 14l-5-5 1.41-1.41L25 29.17l7.59-7.59L34 23l-9 9z"
800
- })));
790
+ width: "16",
791
+ height: "16"
792
+ };
801
793
 
802
- function _extends$a() { _extends$a = Object.assign || 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$a.apply(this, arguments); }
803
- var FormIcon = (({
804
- styles = {},
805
- ...props
806
- }) => /*#__PURE__*/React__default['default'].createElement("svg", _extends$a({
807
- xmlns: "http://www.w3.org/2000/svg",
808
- width: "54",
809
- height: "54"
810
- }, props), /*#__PURE__*/React__default['default'].createElement("rect", {
811
- x: "15",
812
- y: "17",
813
- width: "24",
814
- height: "4",
815
- rx: "1"
816
- }), /*#__PURE__*/React__default['default'].createElement("rect", {
817
- x: "15",
818
- y: "25",
819
- width: "24",
820
- height: "4",
821
- rx: "1"
822
- }), /*#__PURE__*/React__default['default'].createElement("rect", {
823
- x: "15",
824
- y: "33",
825
- width: "13",
826
- height: "4",
827
- rx: "1"
828
- })));
794
+ var CreateIcon = function CreateIcon(props) {
795
+ return jsxRuntime.jsx("svg", { ...props,
796
+ children: jsxRuntime.jsx("path", {
797
+ fillRule: "evenodd",
798
+ d: "M9 13V9h4a1 1 0 0 0 0-2H9V3a1 1 0 1 0-2 0v4H3a1 1 0 1 0 0 2h4v4a1 1 0 0 0 2 0z"
799
+ })
800
+ });
801
+ };
829
802
 
830
- function _extends$9() { _extends$9 = Object.assign || 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$9.apply(this, arguments); }
831
- var ColumnsIcon = (({
832
- styles = {},
833
- ...props
834
- }) => /*#__PURE__*/React__default['default'].createElement("svg", _extends$9({
803
+ CreateIcon.defaultProps = {
835
804
  xmlns: "http://www.w3.org/2000/svg",
836
- width: "54",
837
- height: "54"
838
- }, props), /*#__PURE__*/React__default['default'].createElement("path", {
839
- fillRule: "evenodd",
840
- d: "M8 33v5a1 1 0 001 1h4v2H9a3 3 0 01-3-3v-5h2zm18 6v2H15v-2h11zm13 0v2H28v-2h11zm9-6v5a3 3 0 01-3 3h-4v-2h4a1 1 0 00.993-.883L46 38v-5h2zM8 22v9H6v-9h2zm40 0v9h-2v-9h2zm-35-9v2H9a1 1 0 00-.993.883L8 16v4H6v-4a3 3 0 013-3h4zm32 0a3 3 0 013 3v4h-2v-4a1 1 0 00-.883-.993L45 15h-4v-2h4zm-6 0v2H28v-2h11zm-13 0v2H15v-2h11z"
841
- })));
805
+ width: "16",
806
+ height: "16"
807
+ };
842
808
 
843
- function _extends$8() { _extends$8 = Object.assign || 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$8.apply(this, arguments); }
844
- var NumberIcon = (({
845
- styles = {},
846
- ...props
847
- }) => /*#__PURE__*/React__default['default'].createElement("svg", _extends$8({
848
- xmlns: "http://www.w3.org/2000/svg",
849
- width: "54",
850
- height: "54"
851
- }, props), /*#__PURE__*/React__default['default'].createElement("path", {
852
- fillRule: "evenodd",
853
- d: "M45 16a3 3 0 013 3v16a3 3 0 01-3 3H9a3 3 0 01-3-3V19a3 3 0 013-3h36zm0 2H9a1 1 0 00-1 1v16a1 1 0 001 1h36a1 1 0 001-1V19a1 1 0 00-1-1zM35 28.444h7l-3.5 4-3.5-4zM35 26h7l-3.5-4-3.5 4z"
854
- })));
809
+ var DeleteIcon = function DeleteIcon(props) {
810
+ return jsxRuntime.jsx("svg", { ...props,
811
+ children: jsxRuntime.jsx("path", {
812
+ fillRule: "evenodd",
813
+ d: "M12 6v7c0 1.1-.4 1.55-1.5 1.55h-5C4.4 14.55 4 14.1 4 13V6h8zm-1.5 1.5h-5v4.3c0 .66.5 1.2 1.111 1.2H9.39c.611 0 1.111-.54 1.111-1.2V7.5zM13 3h-2l-1-1H6L5 3H3v1.5h10V3z"
814
+ })
815
+ });
816
+ };
855
817
 
856
- function _extends$7() { _extends$7 = Object.assign || 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$7.apply(this, arguments); }
857
- var RadioIcon = (({
858
- styles = {},
859
- ...props
860
- }) => /*#__PURE__*/React__default['default'].createElement("svg", _extends$7({
818
+ DeleteIcon.defaultProps = {
861
819
  xmlns: "http://www.w3.org/2000/svg",
862
- width: "54",
863
- height: "54"
864
- }, props), /*#__PURE__*/React__default['default'].createElement("path", {
865
- d: "M27 22c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5zm0-5c-5.52 0-10 4.48-10 10s4.48 10 10 10 10-4.48 10-10-4.48-10-10-10zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"
866
- })));
820
+ width: "16",
821
+ height: "16"
822
+ };
867
823
 
868
- function _extends$6() { _extends$6 = Object.assign || 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$6.apply(this, arguments); }
869
- var SelectIcon = (({
870
- styles = {},
871
- ...props
872
- }) => /*#__PURE__*/React__default['default'].createElement("svg", _extends$6({
873
- xmlns: "http://www.w3.org/2000/svg",
874
- width: "54",
875
- height: "54"
876
- }, props), /*#__PURE__*/React__default['default'].createElement("path", {
877
- fillRule: "evenodd",
878
- d: "M45 16a3 3 0 013 3v16a3 3 0 01-3 3H9a3 3 0 01-3-3V19a3 3 0 013-3h36zm0 2H9a1 1 0 00-1 1v16a1 1 0 001 1h36a1 1 0 001-1V19a1 1 0 00-1-1zm-12 7h9l-4.5 6-4.5-6z"
879
- })));
824
+ var ExternalLinkIcon = function ExternalLinkIcon(props) {
825
+ return jsxRuntime.jsx("svg", { ...props,
826
+ children: jsxRuntime.jsx("path", {
827
+ fillRule: "evenodd",
828
+ clipRule: "evenodd",
829
+ d: "M12.637 12.637v-4.72h1.362v4.721c0 .36-.137.676-.411.95-.275.275-.591.412-.95.412H3.362c-.38 0-.703-.132-.967-.396A1.315 1.315 0 0 1 2 12.638V3.362c0-.38.132-.703.396-.967S2.982 2 3.363 2h4.553v1.363H3.363v9.274h9.274zM14 2H9.28l-.001 1.362h2.408L5.065 9.984l.95.95 6.622-6.622v2.409H14V2z",
830
+ fill: "#818798"
831
+ })
832
+ });
833
+ };
880
834
 
881
- function _extends$5() { _extends$5 = Object.assign || 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$5.apply(this, arguments); }
882
- var TextIcon = (({
883
- styles = {},
884
- ...props
885
- }) => /*#__PURE__*/React__default['default'].createElement("svg", _extends$5({
886
- xmlns: "http://www.w3.org/2000/svg",
887
- width: "54",
888
- height: "54"
889
- }, props), /*#__PURE__*/React__default['default'].createElement("path", {
890
- d: "M20.58 33.77h-3l-1.18-3.08H11l-1.1 3.08H7l5.27-13.54h2.89zm-5-5.36l-1.86-5-1.83 5zM22 20.23h5.41a15.47 15.47 0 012.4.14 3.42 3.42 0 011.41.55 3.47 3.47 0 011 1.14 3 3 0 01.42 1.58 3.26 3.26 0 01-1.91 2.94 3.63 3.63 0 011.91 1.22 3.28 3.28 0 01.66 2 4 4 0 01-.43 1.8 3.63 3.63 0 01-1.09 1.4 3.89 3.89 0 01-1.83.65q-.69.07-3.3.09H22zm2.73 2.25v3.13h3.8a1.79 1.79 0 001.1-.49 1.41 1.41 0 00.41-1 1.49 1.49 0 00-.35-1 1.54 1.54 0 00-1-.48c-.27 0-1.05-.05-2.34-.05zm0 5.39v3.62h2.57a11.52 11.52 0 001.88-.09 1.65 1.65 0 001-.54 1.6 1.6 0 00.38-1.14 1.75 1.75 0 00-.29-1 1.69 1.69 0 00-.86-.62 9.28 9.28 0 00-2.41-.23zM44.35 28.79l2.65.84a5.94 5.94 0 01-2 3.29A5.74 5.74 0 0141.38 34a5.87 5.87 0 01-4.44-1.84 7.09 7.09 0 01-1.73-5A7.43 7.43 0 0137 21.87 6 6 0 0141.54 20a5.64 5.64 0 014 1.47A5.33 5.33 0 0147 24l-2.7.65a2.8 2.8 0 00-2.86-2.27A3.09 3.09 0 0039 23.42a5.31 5.31 0 00-.93 3.5 5.62 5.62 0 00.93 3.65 3 3 0 002.4 1.09 2.72 2.72 0 001.82-.66 4 4 0 001.13-2.21z"
891
- })));
835
+ ExternalLinkIcon.defaultProps = {
836
+ width: "16",
837
+ height: "16",
838
+ fill: "none",
839
+ xmlns: "http://www.w3.org/2000/svg"
840
+ };
892
841
 
893
- function _extends$4() { _extends$4 = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$4.apply(this, arguments); }
894
- var TextfieldIcon = (({
895
- styles = {},
896
- ...props
897
- }) => /*#__PURE__*/React__default['default'].createElement("svg", _extends$4({
898
- xmlns: "http://www.w3.org/2000/svg",
899
- width: "54",
900
- height: "54"
901
- }, props), /*#__PURE__*/React__default['default'].createElement("path", {
902
- fillRule: "evenodd",
903
- d: "M45 16a3 3 0 013 3v16a3 3 0 01-3 3H9a3 3 0 01-3-3V19a3 3 0 013-3h36zm0 2H9a1 1 0 00-1 1v16a1 1 0 001 1h36a1 1 0 001-1V19a1 1 0 00-1-1zm-32 4v10h-2V22h2z"
904
- })));
842
+ var FeelRequiredIcon = function FeelRequiredIcon(props) {
843
+ return jsxRuntime.jsxs("svg", { ...props,
844
+ children: [jsxRuntime.jsx("path", {
845
+ d: "M5.8 7.06V5.95h4.307v1.11H5.8zm0 3.071v-1.11h4.307v1.11H5.8z",
846
+ fill: "#505562"
847
+ }), jsxRuntime.jsx("path", {
848
+ fillRule: "evenodd",
849
+ clipRule: "evenodd",
850
+ d: "M8 3.268A4.732 4.732 0 1 0 12.732 8H14a6 6 0 1 1-6-6v1.268z",
851
+ fill: "#505562"
852
+ }), jsxRuntime.jsx("path", {
853
+ d: "m11.28 6.072-.832-.56 1.016-1.224L10 3.848l.312-.912 1.392.584L11.632 2h1.032l-.072 1.52 1.392-.584.312.912-1.464.44 1.008 1.224-.832.552-.864-1.296-.864 1.304z",
854
+ fill: "#505562"
855
+ })]
856
+ });
857
+ };
905
858
 
906
- const iconsByType = {
907
- button: ButtonIcon,
908
- checkbox: CheckboxIcon,
909
- columns: ColumnsIcon,
910
- number: NumberIcon,
911
- radio: RadioIcon,
912
- select: SelectIcon,
913
- text: TextIcon,
914
- textfield: TextfieldIcon,
915
- default: FormIcon
859
+ FeelRequiredIcon.defaultProps = {
860
+ viewBox: "0 0 16 16",
861
+ fill: "none",
862
+ xmlns: "http://www.w3.org/2000/svg"
916
863
  };
917
864
 
918
- const types = [{
919
- label: 'Text Field',
920
- type: 'textfield'
921
- }, {
922
- label: 'Number',
923
- type: 'number'
924
- }, {
925
- label: 'Checkbox',
926
- type: 'checkbox'
927
- }, {
928
- label: 'Radio',
929
- type: 'radio'
930
- }, {
931
- label: 'Select',
932
- type: 'select'
933
- }, {
934
- label: 'Text',
935
- type: 'text'
936
- }, {
937
- label: 'Button',
938
- type: 'button'
939
- }];
940
- function Palette(props) {
941
- return jsxRuntime.jsxs("div", {
942
- class: "fjs-palette",
943
- children: [jsxRuntime.jsxs("div", {
944
- class: "fjs-palette-header",
945
- title: "Form elements library",
946
- children: [jsxRuntime.jsx("span", {
947
- class: "fjs-hide-compact",
948
- children: "FORM ELEMENTS "
949
- }), "LIBRARY"]
950
- }), jsxRuntime.jsx("div", {
951
- class: "fjs-palette-fields fjs-drag-container fjs-no-drop",
952
- children: types.map(({
953
- label,
954
- type
955
- }) => {
956
- const Icon = iconsByType[type];
957
- return jsxRuntime.jsxs("div", {
958
- class: "fjs-palette-field fjs-drag-copy fjs-no-drop",
959
- "data-field-type": type,
960
- title: `Create a ${label} element`,
961
- children: [Icon ? jsxRuntime.jsx(Icon, {
962
- class: "fjs-palette-field-icon",
963
- width: "36",
964
- height: "36",
965
- viewBox: "0 0 54 54"
966
- }) : null, jsxRuntime.jsx("span", {
967
- class: "fjs-palette-field-text fjs-hide-compact",
968
- children: label
969
- })]
970
- });
971
- })
865
+ var FeelOptionalIcon = function FeelOptionalIcon(props) {
866
+ return jsxRuntime.jsxs("svg", { ...props,
867
+ children: [jsxRuntime.jsx("path", {
868
+ d: "M5.845 7.04V5.93h4.307v1.11H5.845zm0 3.07V9h4.307v1.11H5.845z",
869
+ fill: "#505562"
870
+ }), jsxRuntime.jsx("path", {
871
+ fillRule: "evenodd",
872
+ clipRule: "evenodd",
873
+ d: "M3.286 8a4.714 4.714 0 1 0 9.428 0 4.714 4.714 0 0 0-9.428 0zM8 2a6 6 0 1 0 0 12A6 6 0 0 0 8 2z",
874
+ fill: "#505562"
972
875
  })]
973
876
  });
974
- }
975
-
976
- function arrayAdd$1(array, index, item) {
977
- const copy = [...array];
978
- copy.splice(index, 0, item);
979
- return copy;
980
- }
981
- function arrayRemove$1(array, index) {
982
- const copy = [...array];
983
- copy.splice(index, 1);
984
- return copy;
985
- }
986
- function prefixId(id) {
987
- return `fjs-properties-panel-${id}`;
988
- }
989
- function stopPropagation(listener) {
990
- return event => {
991
- event.stopPropagation();
992
- listener(event);
993
- };
994
- }
995
- function textToLabel(text = '...') {
996
- if (text.length > 10) {
997
- return `${text.substring(0, 30)}...`;
998
- }
877
+ };
999
878
 
1000
- return text;
1001
- }
1002
- const INPUTS = ['checkbox', 'number', 'radio', 'select', 'textfield'];
879
+ FeelOptionalIcon.defaultProps = {
880
+ viewBox: "0 0 16 16",
881
+ fill: "none",
882
+ xmlns: "http://www.w3.org/2000/svg"
883
+ };
1003
884
 
1004
- function CheckboxInput(props) {
885
+ function Header(props) {
1005
886
  const {
1006
- id,
1007
- label,
1008
- onChange,
1009
- value = false
887
+ element,
888
+ headerProvider
1010
889
  } = props;
1011
-
1012
- const handleChange = ({
1013
- target
1014
- }) => {
1015
- onChange(target.checked);
1016
- };
1017
-
890
+ const {
891
+ getElementIcon,
892
+ getDocumentationRef,
893
+ getElementLabel,
894
+ getTypeLabel
895
+ } = headerProvider;
896
+ const label = getElementLabel(element);
897
+ const type = getTypeLabel(element);
898
+ const documentationRef = getDocumentationRef && getDocumentationRef(element);
899
+ const ElementIcon = getElementIcon(element);
1018
900
  return jsxRuntime.jsxs("div", {
1019
- class: "fjs-properties-panel-checkbox",
1020
- children: [jsxRuntime.jsx("label", {
1021
- for: prefixId(id),
1022
- class: "fjs-properties-panel-label",
1023
- children: label
1024
- }), jsxRuntime.jsx("input", {
1025
- id: prefixId(id),
1026
- type: "checkbox",
1027
- class: "fjs-properties-panel-input",
1028
- onChange: handleChange,
1029
- checked: value
901
+ class: "bio-properties-panel-header",
902
+ children: [jsxRuntime.jsx("div", {
903
+ class: "bio-properties-panel-header-icon",
904
+ children: ElementIcon && jsxRuntime.jsx(ElementIcon, {
905
+ width: "32",
906
+ height: "32",
907
+ viewBox: "0 0 32 32"
908
+ })
909
+ }), jsxRuntime.jsxs("div", {
910
+ class: "bio-properties-panel-header-labels",
911
+ children: [jsxRuntime.jsx("div", {
912
+ title: type,
913
+ class: "bio-properties-panel-header-type",
914
+ children: type
915
+ }), label ? jsxRuntime.jsx("div", {
916
+ title: label,
917
+ class: "bio-properties-panel-header-label",
918
+ children: label
919
+ }) : null]
920
+ }), jsxRuntime.jsx("div", {
921
+ class: "bio-properties-panel-header-actions",
922
+ children: documentationRef ? jsxRuntime.jsx("a", {
923
+ rel: "noopener",
924
+ class: "bio-properties-panel-header-link",
925
+ href: documentationRef,
926
+ title: "Open documentation",
927
+ target: "_blank",
928
+ children: jsxRuntime.jsx(ExternalLinkIcon, {})
929
+ }) : null
1030
930
  })]
1031
931
  });
1032
932
  }
1033
933
 
1034
- function usePrevious(value) {
1035
- const ref = hooks$1.useRef();
1036
- hooks$1.useEffect(() => ref.current = value);
1037
- return ref.current;
1038
- }
934
+ const DescriptionContext = preact.createContext({
935
+ description: {},
936
+ getDescriptionForId: () => {}
937
+ });
938
+ /**
939
+ * @typedef {Function} <propertiesPanel.showEntry> callback
940
+ *
941
+ * @example
942
+ *
943
+ * useEvent('propertiesPanel.showEntry', ({ focus = false, ...rest }) => {
944
+ * // ...
945
+ * });
946
+ *
947
+ * @param {Object} context
948
+ * @param {boolean} [context.focus]
949
+ *
950
+ * @returns void
951
+ */
952
+
953
+ const EventContext = preact.createContext({
954
+ eventBus: null
955
+ });
956
+ const LayoutContext = preact.createContext({
957
+ layout: {},
958
+ setLayout: () => {},
959
+ getLayoutForKey: () => {},
960
+ setLayoutForKey: () => {}
961
+ });
962
+ /**
963
+ * Accesses the global DescriptionContext and returns a description for a given id and element.
964
+ *
965
+ * @example
966
+ * ```jsx
967
+ * function TextField(props) {
968
+ * const description = useDescriptionContext('input1', element);
969
+ * }
970
+ * ```
971
+ *
972
+ * @param {string} id
973
+ * @param {object} element
974
+ *
975
+ * @returns {string}
976
+ */
977
+
978
+ function useDescriptionContext(id, element) {
979
+ const {
980
+ getDescriptionForId
981
+ } = hooks$1.useContext(DescriptionContext);
982
+ return getDescriptionForId(id, element);
983
+ }
984
+
985
+ const DEFAULT_PRIORITY$2 = 1000;
986
+ /**
987
+ * Subscribe to an event.
988
+ *
989
+ * @param {string} event
990
+ * @param {Function} callback
991
+ * @param {number} [priority]
992
+ *
993
+ * @returns {import('preact').Ref}
994
+ */
995
+
996
+ function useEvent(event, callback, priority = DEFAULT_PRIORITY$2) {
997
+ const {
998
+ eventBus
999
+ } = hooks$1.useContext(EventContext);
1000
+ hooks$1.useEffect(() => {
1001
+ if (!eventBus) {
1002
+ return;
1003
+ }
1004
+
1005
+ eventBus.on(event, priority, callback);
1006
+ return () => eventBus.off(event, callback);
1007
+ }, [callback, event, eventBus, priority]);
1008
+ }
1009
+
1010
+ const HIGH_PRIORITY = 10000;
1011
+ /**
1012
+ * Buffer events and re-fire during passive effect phase.
1013
+ *
1014
+ * @param {string[]} bufferedEvents
1015
+ * @param {Object} [eventBus]
1016
+ */
1017
+
1018
+ function useEventBuffer(bufferedEvents, eventBus) {
1019
+ const buffer = hooks$1.useRef([]),
1020
+ buffering = hooks$1.useRef(true);
1021
+
1022
+ const createCallback = event => data => {
1023
+ if (buffering.current === true) {
1024
+ buffer.current.unshift([event, data]);
1025
+ }
1026
+ }; // (1) buffer events
1039
1027
 
1040
- function useDebounce(fn, dependencies = []) {
1041
- const debounce = useService('debounce');
1042
- const callback = hooks$1.useMemo(() => {
1043
- return debounce(fn);
1044
- }, dependencies); // cleanup async side-effect if callback #flush is provided.
1045
1028
 
1046
1029
  hooks$1.useEffect(() => {
1030
+ if (!eventBus) {
1031
+ return;
1032
+ }
1033
+
1034
+ const listeners = bufferedEvents.map(event => {
1035
+ return [event, createCallback(event)];
1036
+ });
1037
+ listeners.forEach(([event, callback]) => {
1038
+ eventBus.on(event, HIGH_PRIORITY, callback);
1039
+ });
1047
1040
  return () => {
1048
- typeof callback.flush === 'function' && callback.flush();
1041
+ listeners.forEach(([event, callback]) => {
1042
+ eventBus.off(event, callback);
1043
+ });
1049
1044
  };
1050
- }, [callback]);
1051
- return callback;
1052
- }
1045
+ }, [bufferedEvents, eventBus]); // (2) re-fire events
1053
1046
 
1054
- function NumberInput(props) {
1055
- const {
1056
- id,
1057
- label,
1058
- max,
1059
- min,
1060
- value = '',
1061
- onInput: _onInput
1062
- } = props;
1063
- const onInput = useDebounce(event => {
1064
- const {
1065
- validity,
1066
- value
1067
- } = event.target;
1047
+ hooks$1.useEffect(() => {
1048
+ if (!eventBus) {
1049
+ return;
1050
+ }
1051
+
1052
+ buffering.current = false;
1068
1053
 
1069
- if (validity.valid) {
1070
- _onInput(value ? parseInt(value, 10) : undefined);
1054
+ while (buffer.current.length) {
1055
+ const [event, data] = buffer.current.pop();
1056
+ eventBus.fire(event, data);
1071
1057
  }
1072
- }, [_onInput]);
1073
- return jsxRuntime.jsxs("div", {
1074
- class: "fjs-properties-panel-number",
1075
- children: [jsxRuntime.jsx("label", {
1076
- for: prefixId(id),
1077
- class: "fjs-properties-panel-label",
1078
- children: label
1079
- }), jsxRuntime.jsx("input", {
1080
- id: prefixId(id),
1081
- type: "number",
1082
- class: "fjs-properties-panel-input",
1083
- max: max,
1084
- min: min,
1085
- onInput: onInput,
1086
- value: value
1087
- })]
1058
+
1059
+ buffering.current = true;
1088
1060
  });
1089
1061
  }
1062
+ /**
1063
+ * Creates a state that persists in the global LayoutContext.
1064
+ *
1065
+ * @example
1066
+ * ```jsx
1067
+ * function Group(props) {
1068
+ * const [ open, setOpen ] = useLayoutState([ 'groups', 'foo', 'open' ], false);
1069
+ * }
1070
+ * ```
1071
+ *
1072
+ * @param {(string|number)[]} path
1073
+ * @param {any} [defaultValue]
1074
+ *
1075
+ * @returns {[ any, Function ]}
1076
+ */
1090
1077
 
1091
- function Select(props) {
1078
+
1079
+ function useLayoutState(path, defaultValue) {
1092
1080
  const {
1093
- id,
1094
- label,
1095
- onChange,
1096
- options,
1097
- value
1098
- } = props;
1081
+ getLayoutForKey,
1082
+ setLayoutForKey
1083
+ } = hooks$1.useContext(LayoutContext);
1084
+ const layoutForKey = getLayoutForKey(path, defaultValue);
1085
+ const [value, set] = hooks$1.useState(layoutForKey);
1099
1086
 
1100
- const handleChange = ({
1101
- target
1102
- }) => {
1103
- onChange(target.value);
1087
+ const setState = newValue => {
1088
+ // (1) set component state
1089
+ set(newValue); // (2) set context
1090
+
1091
+ setLayoutForKey(path, newValue);
1104
1092
  };
1105
1093
 
1106
- return jsxRuntime.jsxs("div", {
1107
- class: "fjs-properties-panel-select",
1108
- children: [jsxRuntime.jsx("label", {
1109
- for: prefixId(id),
1110
- class: "fjs-properties-panel-label",
1111
- children: label
1112
- }), jsxRuntime.jsx("select", {
1113
- id: prefixId(id),
1114
- class: "fjs-properties-panel-input",
1115
- onInput: handleChange,
1116
- children: options.map(option => {
1117
- return jsxRuntime.jsx("option", {
1118
- value: option.value,
1119
- selected: option.value === value,
1120
- children: option.label
1121
- });
1122
- })
1123
- })]
1094
+ return [value, setState];
1095
+ }
1096
+ /**
1097
+ * @pinussilvestrus: we need to introduce our own hook to persist the previous
1098
+ * state on updates.
1099
+ *
1100
+ * cf. https://reactjs.org/docs/hooks-faq.html#how-to-get-the-previous-props-or-state
1101
+ */
1102
+
1103
+
1104
+ function usePrevious(value) {
1105
+ const ref = hooks$1.useRef();
1106
+ hooks$1.useEffect(() => {
1107
+ ref.current = value;
1124
1108
  });
1109
+ return ref.current;
1110
+ }
1111
+ /**
1112
+ * Subscribe to `propertiesPanel.showEntry`.
1113
+ *
1114
+ * @param {Function} show
1115
+ *
1116
+ * @returns {import('preact').Ref}
1117
+ */
1118
+
1119
+
1120
+ function useShowEntryEvent(show) {
1121
+ const {
1122
+ onShow
1123
+ } = hooks$1.useContext(LayoutContext);
1124
+ const ref = hooks$1.useRef();
1125
+ const [focus, setFocus] = hooks$1.useState(false);
1126
+ const onShowEntry = hooks$1.useCallback(event => {
1127
+ if (show(event)) {
1128
+ if (minDash.isFunction(onShow)) {
1129
+ onShow();
1130
+ }
1131
+
1132
+ if (event.focus && !focus) {
1133
+ setFocus(true);
1134
+ }
1135
+ }
1136
+ }, [show]);
1137
+ hooks$1.useEffect(() => {
1138
+ if (focus && ref.current) {
1139
+ if (minDash.isFunction(ref.current.focus)) {
1140
+ ref.current.focus();
1141
+ }
1142
+
1143
+ if (minDash.isFunction(ref.current.select)) {
1144
+ ref.current.select();
1145
+ }
1146
+
1147
+ setFocus(false);
1148
+ }
1149
+ }, [focus]);
1150
+ useEvent('propertiesPanel.showEntry', onShowEntry);
1151
+ return ref;
1152
+ }
1153
+ /**
1154
+ * Subscribe to `propertiesPanel.showError`. On `propertiesPanel.showError` set
1155
+ * temporary error. Fire `propertiesPanel.showEntry` for temporary error to be
1156
+ * visible. Unset error on `propertiesPanel.updated`.
1157
+ *
1158
+ * @param {Function} show
1159
+ *
1160
+ * @returns {import('preact').Ref}
1161
+ */
1162
+
1163
+
1164
+ function useShowErrorEvent(show) {
1165
+ const {
1166
+ eventBus
1167
+ } = hooks$1.useContext(EventContext);
1168
+ const [temporaryError, setTemporaryError] = hooks$1.useState(null);
1169
+ const onPropertiesPanelUpdated = hooks$1.useCallback(() => setTemporaryError(null), []);
1170
+ useEvent('propertiesPanel.updated', onPropertiesPanelUpdated);
1171
+ const onShowError = hooks$1.useCallback(event => {
1172
+ setTemporaryError(null);
1173
+
1174
+ if (show(event)) {
1175
+ if (eventBus) {
1176
+ eventBus.fire('propertiesPanel.showEntry', event);
1177
+ }
1178
+
1179
+ setTemporaryError(event.message);
1180
+ }
1181
+ }, [show]);
1182
+ useEvent('propertiesPanel.showError', onShowError);
1183
+ return temporaryError;
1184
+ }
1185
+ /**
1186
+ * @callback setSticky
1187
+ * @param {boolean} value
1188
+ */
1189
+
1190
+ /**
1191
+ * Use IntersectionObserver to identify when DOM element is in sticky mode.
1192
+ * If sticky is observered setSticky(true) will be called.
1193
+ * If sticky mode is left, setSticky(false) will be called.
1194
+ *
1195
+ *
1196
+ * @param {Object} ref
1197
+ * @param {string} scrollContainerSelector
1198
+ * @param {setSticky} setSticky
1199
+ */
1200
+
1201
+
1202
+ function useStickyIntersectionObserver(ref, scrollContainerSelector, setSticky) {
1203
+ hooks$1.useEffect(() => {
1204
+ // return early if IntersectionObserver is not available
1205
+ if (!IntersectionObserver) {
1206
+ return;
1207
+ }
1208
+
1209
+ let observer;
1210
+
1211
+ if (ref.current) {
1212
+ const scrollContainer = minDom.query(scrollContainerSelector);
1213
+ observer = new IntersectionObserver(entries => {
1214
+ if (entries[0].intersectionRatio < 1) {
1215
+ setSticky(true);
1216
+ } else if (entries[0].intersectionRatio === 1) {
1217
+ setSticky(false);
1218
+ }
1219
+ }, {
1220
+ root: scrollContainer,
1221
+ rootMargin: '0px 0px 999999% 0px',
1222
+ // Use bottom margin to avoid stickyness when scrolling out to bottom
1223
+ threshold: [1]
1224
+ });
1225
+ observer.observe(ref.current);
1226
+ } // Unobserve if unmounted
1227
+
1228
+
1229
+ return () => {
1230
+ if (ref.current && observer) {
1231
+ observer.unobserve(ref.current);
1232
+ }
1233
+ };
1234
+ }, [ref]);
1125
1235
  }
1126
1236
 
1127
- function Textarea(props) {
1237
+ function Group(props) {
1128
1238
  const {
1239
+ element,
1240
+ entries = [],
1129
1241
  id,
1130
1242
  label,
1131
- rows = 10,
1132
- value = '',
1133
- onInput: _onInput
1243
+ shouldOpen = false
1134
1244
  } = props;
1135
- const onInput = useDebounce(event => {
1136
- const value = event.target.value;
1245
+ const groupRef = hooks$1.useRef(null);
1246
+ const [open, setOpen] = useLayoutState(['groups', id, 'open'], shouldOpen);
1247
+ const onShow = hooks$1.useCallback(() => setOpen(true), [setOpen]);
1248
+
1249
+ const toggleOpen = () => setOpen(!open);
1250
+
1251
+ const [edited, setEdited] = hooks$1.useState(false);
1252
+ const [sticky, setSticky] = hooks$1.useState(false); // set edited state depending on all entries
1253
+
1254
+ hooks$1.useEffect(() => {
1255
+ const hasOneEditedEntry = entries.find(entry => {
1256
+ const {
1257
+ id,
1258
+ isEdited
1259
+ } = entry;
1260
+ const entryNode = minDom.query(`[data-entry-id="${id}"]`);
1137
1261
 
1138
- _onInput(value.length ? value : undefined);
1139
- }, [_onInput]);
1262
+ if (!minDash.isFunction(isEdited) || !entryNode) {
1263
+ return false;
1264
+ }
1265
+
1266
+ const inputNode = minDom.query('.bio-properties-panel-input', entryNode);
1267
+ return isEdited(inputNode);
1268
+ });
1269
+ setEdited(hasOneEditedEntry);
1270
+ }, [entries]); // set css class when group is sticky to top
1271
+
1272
+ useStickyIntersectionObserver(groupRef, 'div.bio-properties-panel-scroll-container', setSticky);
1273
+ const propertiesPanelContext = { ...hooks$1.useContext(LayoutContext),
1274
+ onShow
1275
+ };
1140
1276
  return jsxRuntime.jsxs("div", {
1141
- class: "fjs-properties-panel-textarea",
1142
- children: [jsxRuntime.jsx("label", {
1143
- for: prefixId(id),
1144
- class: "fjs-properties-panel-label",
1145
- children: label
1146
- }), jsxRuntime.jsx("textarea", {
1147
- id: prefixId(id),
1148
- spellcheck: false,
1149
- class: "fjs-properties-panel-input",
1150
- onInput: onInput,
1151
- rows: rows,
1152
- value: value
1277
+ class: "bio-properties-panel-group",
1278
+ "data-group-id": 'group-' + id,
1279
+ ref: groupRef,
1280
+ children: [jsxRuntime.jsxs("div", {
1281
+ class: classnames__default['default']('bio-properties-panel-group-header', edited ? '' : 'empty', open ? 'open' : '', sticky && open ? 'sticky' : ''),
1282
+ onClick: toggleOpen,
1283
+ children: [jsxRuntime.jsx("div", {
1284
+ title: label,
1285
+ class: "bio-properties-panel-group-header-title",
1286
+ children: label
1287
+ }), jsxRuntime.jsxs("div", {
1288
+ class: "bio-properties-panel-group-header-buttons",
1289
+ children: [edited && jsxRuntime.jsx(DataMarker, {}), jsxRuntime.jsx("button", {
1290
+ title: "Toggle section",
1291
+ class: "bio-properties-panel-group-header-button bio-properties-panel-arrow",
1292
+ children: jsxRuntime.jsx(ArrowIcon, {
1293
+ class: open ? 'bio-properties-panel-arrow-down' : 'bio-properties-panel-arrow-right'
1294
+ })
1295
+ })]
1296
+ })]
1297
+ }), jsxRuntime.jsx("div", {
1298
+ class: classnames__default['default']('bio-properties-panel-group-entries', open ? 'open' : ''),
1299
+ children: jsxRuntime.jsx(LayoutContext.Provider, {
1300
+ value: propertiesPanelContext,
1301
+ children: entries.map(entry => {
1302
+ const {
1303
+ component: Component,
1304
+ id
1305
+ } = entry;
1306
+ return preact.createElement(Component, { ...entry,
1307
+ element: element,
1308
+ key: id
1309
+ });
1310
+ })
1311
+ })
1153
1312
  })]
1154
1313
  });
1155
1314
  }
1156
1315
 
1157
- function TextInput(props) {
1158
- let {
1159
- id,
1160
- label,
1161
- validate = () => null,
1162
- onInput: _onInput,
1163
- value = ''
1316
+ function DataMarker() {
1317
+ return jsxRuntime.jsx("div", {
1318
+ title: "Section contains data",
1319
+ class: "bio-properties-panel-dot"
1320
+ });
1321
+ }
1322
+ /**
1323
+ * @typedef { {
1324
+ * text: (element: object) => string,
1325
+ * icon?: (element: Object) => import('preact').Component
1326
+ * } } PlaceholderDefinition
1327
+ *
1328
+ * @param { PlaceholderDefinition } props
1329
+ */
1330
+
1331
+
1332
+ function Placeholder(props) {
1333
+ const {
1334
+ text,
1335
+ icon: Icon
1164
1336
  } = props;
1165
- const prevValue = usePrevious(value);
1166
- const [cachedValue, setCachedValue] = hooks$1.useState(null);
1167
- const [error, setError] = hooks$1.useState(null);
1168
- hooks$1.useEffect(() => setError(validate(value)), [validate, value]);
1169
- const onInput = useDebounce(event => {
1170
- const value = event.target.value;
1171
- const error = validate(value);
1172
-
1173
- if (error) {
1174
- setCachedValue(value);
1175
- } else {
1176
- _onInput(value.length ? value : undefined);
1337
+ return jsxRuntime.jsx("div", {
1338
+ class: "bio-properties-panel open",
1339
+ children: jsxRuntime.jsxs("section", {
1340
+ class: "bio-properties-panel-placeholder",
1341
+ children: [Icon && jsxRuntime.jsx(Icon, {
1342
+ class: "bio-properties-panel-placeholder-icon"
1343
+ }), jsxRuntime.jsx("p", {
1344
+ class: "bio-properties-panel-placeholder-text",
1345
+ children: text
1346
+ })]
1347
+ })
1348
+ });
1349
+ }
1350
+
1351
+ const DEFAULT_LAYOUT = {
1352
+ open: true
1353
+ };
1354
+ const DEFAULT_DESCRIPTION = {};
1355
+ const bufferedEvents = ['propertiesPanel.showEntry', 'propertiesPanel.showError'];
1356
+ /**
1357
+ * @typedef { {
1358
+ * component: import('preact').Component,
1359
+ * id: String,
1360
+ * isEdited?: Function
1361
+ * } } EntryDefinition
1362
+ *
1363
+ * @typedef { {
1364
+ * autoFocusEntry: String,
1365
+ * autoOpen?: Boolean,
1366
+ * entries: Array<EntryDefinition>,
1367
+ * id: String,
1368
+ * label: String,
1369
+ * remove: (event: MouseEvent) => void
1370
+ * } } ListItemDefinition
1371
+ *
1372
+ * @typedef { {
1373
+ * add: (event: MouseEvent) => void,
1374
+ * component: import('preact').Component,
1375
+ * element: Object,
1376
+ * id: String,
1377
+ * items: Array<ListItemDefinition>,
1378
+ * label: String,
1379
+ * shouldSort?: Boolean,
1380
+ * shouldOpen?: Boolean
1381
+ * } } ListGroupDefinition
1382
+ *
1383
+ * @typedef { {
1384
+ * component?: import('preact').Component,
1385
+ * entries: Array<EntryDefinition>,
1386
+ * id: String,
1387
+ * label: String,
1388
+ * shouldOpen?: Boolean
1389
+ * } } GroupDefinition
1390
+ *
1391
+ * @typedef { {
1392
+ * [id: String]: GetDescriptionFunction
1393
+ * } } DescriptionConfig
1394
+ *
1395
+ * @callback { {
1396
+ * @param {string} id
1397
+ * @param {Object} element
1398
+ * @returns {string}
1399
+ * } } GetDescriptionFunction
1400
+ *
1401
+ * @typedef { {
1402
+ * getEmpty: (element: object) => import('./components/Placeholder').PlaceholderDefinition,
1403
+ * getMultiple: (element: Object) => import('./components/Placeholder').PlaceholderDefinition
1404
+ * } } PlaceholderProvider
1405
+ *
1406
+ */
1407
+
1408
+ /**
1409
+ * A basic properties panel component. Describes *how* content will be rendered, accepts
1410
+ * data from implementor to describe *what* will be rendered.
1411
+ *
1412
+ * @param {Object} props
1413
+ * @param {Object|Array} props.element
1414
+ * @param {import('./components/Header').HeaderProvider} props.headerProvider
1415
+ * @param {PlaceholderProvider} [props.placeholderProvider]
1416
+ * @param {Array<GroupDefinition|ListGroupDefinition>} props.groups
1417
+ * @param {Object} [props.layoutConfig]
1418
+ * @param {Function} [props.layoutChanged]
1419
+ * @param {DescriptionConfig} [props.descriptionConfig]
1420
+ * @param {Function} [props.descriptionLoaded]
1421
+ * @param {Object} [props.eventBus]
1422
+ */
1423
+
1424
+ function PropertiesPanel(props) {
1425
+ const {
1426
+ element,
1427
+ headerProvider,
1428
+ placeholderProvider,
1429
+ groups,
1430
+ layoutConfig = {},
1431
+ layoutChanged,
1432
+ descriptionConfig = {},
1433
+ descriptionLoaded,
1434
+ eventBus
1435
+ } = props; // set-up layout context
1436
+
1437
+ const [layout, setLayout] = hooks$1.useState(createLayout(layoutConfig));
1438
+ hooks$1.useEffect(() => {
1439
+ if (typeof layoutChanged === 'function') {
1440
+ layoutChanged(layout);
1177
1441
  }
1442
+ }, [layout, layoutChanged]);
1443
+
1444
+ const getLayoutForKey = (key, defaultValue) => {
1445
+ return minDash.get(layout, key, defaultValue);
1446
+ };
1447
+
1448
+ const setLayoutForKey = (key, config) => {
1449
+ const newLayout = minDash.assign({}, layout);
1450
+ minDash.set(newLayout, key, config);
1451
+ setLayout(newLayout);
1452
+ };
1453
+
1454
+ const layoutContext = {
1455
+ layout,
1456
+ setLayout,
1457
+ getLayoutForKey,
1458
+ setLayoutForKey
1459
+ }; // set-up description context
1460
+
1461
+ const description = createDescriptionContext(descriptionConfig);
1462
+
1463
+ if (typeof descriptionLoaded === 'function') {
1464
+ descriptionLoaded(description);
1465
+ }
1466
+
1467
+ const getDescriptionForId = (id, element) => {
1468
+ return description[id] && description[id](element);
1469
+ };
1470
+
1471
+ const descriptionContext = {
1472
+ description,
1473
+ getDescriptionForId
1474
+ };
1475
+ useEventBuffer(bufferedEvents, eventBus);
1476
+ const eventContext = {
1477
+ eventBus
1478
+ };
1479
+ const propertiesPanelContext = {
1480
+ element
1481
+ }; // empty state
1482
+
1483
+ if (placeholderProvider && !element) {
1484
+ return jsxRuntime.jsx(Placeholder, { ...placeholderProvider.getEmpty()
1485
+ });
1486
+ } // multiple state
1178
1487
 
1179
- setError(error);
1180
- }, [validate, setCachedValue, _onInput]);
1181
1488
 
1182
- if (prevValue === value && error) {
1183
- value = cachedValue;
1489
+ if (placeholderProvider && minDash.isArray(element)) {
1490
+ return jsxRuntime.jsx(Placeholder, { ...placeholderProvider.getMultiple()
1491
+ });
1184
1492
  }
1185
1493
 
1186
- const classes = ['fjs-properties-panel-input'];
1494
+ return jsxRuntime.jsx(LayoutContext.Provider, {
1495
+ value: propertiesPanelContext,
1496
+ children: jsxRuntime.jsx(DescriptionContext.Provider, {
1497
+ value: descriptionContext,
1498
+ children: jsxRuntime.jsx(LayoutContext.Provider, {
1499
+ value: layoutContext,
1500
+ children: jsxRuntime.jsx(EventContext.Provider, {
1501
+ value: eventContext,
1502
+ children: jsxRuntime.jsxs("div", {
1503
+ class: classnames__default['default']('bio-properties-panel', layout.open ? 'open' : ''),
1504
+ children: [jsxRuntime.jsx(Header, {
1505
+ element: element,
1506
+ headerProvider: headerProvider
1507
+ }), jsxRuntime.jsx("div", {
1508
+ class: "bio-properties-panel-scroll-container",
1509
+ children: groups.map(group => {
1510
+ const {
1511
+ component: Component = Group,
1512
+ id
1513
+ } = group;
1514
+ return preact.createElement(Component, { ...group,
1515
+ key: id,
1516
+ element: element
1517
+ });
1518
+ })
1519
+ })]
1520
+ })
1521
+ })
1522
+ })
1523
+ })
1524
+ });
1525
+ } // helpers //////////////////
1526
+
1527
+
1528
+ function createLayout(overrides) {
1529
+ return { ...DEFAULT_LAYOUT,
1530
+ ...overrides
1531
+ };
1532
+ }
1533
+
1534
+ function createDescriptionContext(overrides) {
1535
+ return { ...DEFAULT_DESCRIPTION,
1536
+ ...overrides
1537
+ };
1538
+ }
1539
+
1540
+ function CollapsibleEntry(props) {
1541
+ const {
1542
+ element,
1543
+ entries = [],
1544
+ id,
1545
+ label,
1546
+ open: shouldOpen,
1547
+ remove
1548
+ } = props;
1549
+ const [open, setOpen] = hooks$1.useState(shouldOpen);
1550
+
1551
+ const toggleOpen = () => setOpen(!open);
1552
+
1553
+ const {
1554
+ onShow
1555
+ } = hooks$1.useContext(LayoutContext);
1556
+ const propertiesPanelContext = { ...hooks$1.useContext(LayoutContext),
1557
+ onShow: hooks$1.useCallback(() => {
1558
+ setOpen(true);
1559
+
1560
+ if (minDash.isFunction(onShow)) {
1561
+ onShow();
1562
+ }
1563
+ }, [onShow, setOpen])
1564
+ }; // todo(pinussilvestrus): translate once we have a translate mechanism for the core
1565
+
1566
+ const placeholderLabel = '<empty>';
1567
+ return jsxRuntime.jsxs("div", {
1568
+ "data-entry-id": id,
1569
+ class: classnames__default['default']('bio-properties-panel-collapsible-entry', open ? 'open' : ''),
1570
+ children: [jsxRuntime.jsxs("div", {
1571
+ class: "bio-properties-panel-collapsible-entry-header",
1572
+ onClick: toggleOpen,
1573
+ children: [jsxRuntime.jsx("div", {
1574
+ title: label || placeholderLabel,
1575
+ class: classnames__default['default']('bio-properties-panel-collapsible-entry-header-title', !label && 'empty'),
1576
+ children: label || placeholderLabel
1577
+ }), jsxRuntime.jsx("button", {
1578
+ title: "Toggle list item",
1579
+ class: "bio-properties-panel-arrow bio-properties-panel-collapsible-entry-arrow",
1580
+ children: jsxRuntime.jsx(ArrowIcon, {
1581
+ class: open ? 'bio-properties-panel-arrow-down' : 'bio-properties-panel-arrow-right'
1582
+ })
1583
+ }), remove ? jsxRuntime.jsx("button", {
1584
+ title: "Delete item",
1585
+ class: "bio-properties-panel-remove-entry",
1586
+ onClick: remove,
1587
+ children: jsxRuntime.jsx(DeleteIcon, {})
1588
+ }) : null]
1589
+ }), jsxRuntime.jsx("div", {
1590
+ class: classnames__default['default']('bio-properties-panel-collapsible-entry-entries', open ? 'open' : ''),
1591
+ children: jsxRuntime.jsx(LayoutContext.Provider, {
1592
+ value: propertiesPanelContext,
1593
+ children: entries.map(entry => {
1594
+ const {
1595
+ component: Component,
1596
+ id
1597
+ } = entry;
1598
+ return preact.createElement(Component, { ...entry,
1599
+ element: element,
1600
+ key: id
1601
+ });
1602
+ })
1603
+ })
1604
+ })]
1605
+ });
1606
+ }
1607
+
1608
+ function ListItem(props) {
1609
+ const {
1610
+ autoFocusEntry,
1611
+ autoOpen
1612
+ } = props; // focus specified entry on auto open
1613
+
1614
+ hooks$1.useEffect(() => {
1615
+ if (autoOpen && autoFocusEntry) {
1616
+ const entry = minDom.query(`[data-entry-id="${autoFocusEntry}"]`);
1617
+ const focusableInput = minDom.query('.bio-properties-panel-input', entry);
1618
+
1619
+ if (focusableInput) {
1620
+ if (minDash.isFunction(focusableInput.select)) {
1621
+ focusableInput.select();
1622
+ } else if (minDash.isFunction(focusableInput.focus)) {
1623
+ focusableInput.focus();
1624
+ }
1625
+ }
1626
+ }
1627
+ }, [autoOpen, autoFocusEntry]);
1628
+ return jsxRuntime.jsx("div", {
1629
+ class: "bio-properties-panel-list-item",
1630
+ children: jsxRuntime.jsx(CollapsibleEntry, { ...props,
1631
+ open: autoOpen
1632
+ })
1633
+ });
1634
+ }
1635
+
1636
+ const noop$3 = () => {};
1637
+ /**
1638
+ * @param {import('../PropertiesPanel').ListGroupDefinition} props
1639
+ */
1640
+
1641
+
1642
+ function ListGroup(props) {
1643
+ const {
1644
+ add,
1645
+ element,
1646
+ id,
1647
+ items,
1648
+ label,
1649
+ shouldOpen = true,
1650
+ shouldSort = true
1651
+ } = props;
1652
+ const groupRef = hooks$1.useRef(null);
1653
+ const [open, setOpen] = useLayoutState(['groups', id, 'open'], false);
1654
+ const [sticky, setSticky] = hooks$1.useState(false);
1655
+ const onShow = hooks$1.useCallback(() => setOpen(true), [setOpen]);
1656
+ const [ordering, setOrdering] = hooks$1.useState([]);
1657
+ const [newItemAdded, setNewItemAdded] = hooks$1.useState(false);
1658
+ const prevItems = usePrevious(items);
1659
+ const prevElement = usePrevious(element);
1660
+ const elementChanged = element !== prevElement;
1661
+ const shouldHandleEffects = !elementChanged && (shouldSort || shouldOpen); // reset initial ordering when element changes (before first render)
1662
+
1663
+ if (elementChanged) {
1664
+ setOrdering(createOrdering(shouldSort ? sortItems(items) : items));
1665
+ } // keep ordering in sync to items - and open changes
1666
+ // (0) set initial ordering from given items
1667
+
1668
+
1669
+ hooks$1.useEffect(() => {
1670
+ if (!prevItems || !shouldSort) {
1671
+ setOrdering(createOrdering(items));
1672
+ }
1673
+ }, [items, element]); // (1) items were added
1674
+
1675
+ hooks$1.useEffect(() => {
1676
+ if (shouldHandleEffects && prevItems && items.length > prevItems.length) {
1677
+ let add = [];
1678
+ items.forEach(item => {
1679
+ if (!ordering.includes(item.id)) {
1680
+ add.push(item.id);
1681
+ }
1682
+ });
1683
+ let newOrdering = ordering; // open if not open and configured
1684
+
1685
+ if (!open && shouldOpen) {
1686
+ toggleOpen(); // if I opened and I should sort, then sort items
1687
+
1688
+ if (shouldSort) {
1689
+ newOrdering = createOrdering(sortItems(items));
1690
+ }
1691
+ } // add new items on top or bottom depending on sorting behavior
1692
+
1693
+
1694
+ newOrdering = newOrdering.filter(item => !add.includes(item));
1695
+
1696
+ if (shouldSort) {
1697
+ newOrdering.unshift(...add);
1698
+ } else {
1699
+ newOrdering.push(...add);
1700
+ }
1701
+
1702
+ setOrdering(newOrdering);
1703
+ setNewItemAdded(true);
1704
+ } else {
1705
+ setNewItemAdded(false);
1706
+ }
1707
+ }, [items, open, shouldHandleEffects]); // (2) sort items on open if shouldSort is set
1708
+
1709
+ hooks$1.useEffect(() => {
1710
+ if (shouldSort && open && !newItemAdded) {
1711
+ setOrdering(createOrdering(sortItems(items)));
1712
+ }
1713
+ }, [open, shouldSort]); // (3) items were deleted
1714
+
1715
+ hooks$1.useEffect(() => {
1716
+ if (shouldHandleEffects && prevItems && items.length < prevItems.length) {
1717
+ let keep = [];
1718
+ ordering.forEach(o => {
1719
+ if (getItem(items, o)) {
1720
+ keep.push(o);
1721
+ }
1722
+ });
1723
+ setOrdering(keep);
1724
+ }
1725
+ }, [items, shouldHandleEffects]); // set css class when group is sticky to top
1726
+
1727
+ useStickyIntersectionObserver(groupRef, 'div.bio-properties-panel-scroll-container', setSticky);
1728
+
1729
+ const toggleOpen = () => setOpen(!open);
1730
+
1731
+ const hasItems = !!items.length;
1732
+ const propertiesPanelContext = { ...hooks$1.useContext(LayoutContext),
1733
+ onShow
1734
+ };
1735
+ return jsxRuntime.jsxs("div", {
1736
+ class: "bio-properties-panel-group",
1737
+ "data-group-id": 'group-' + id,
1738
+ ref: groupRef,
1739
+ children: [jsxRuntime.jsxs("div", {
1740
+ class: classnames__default['default']('bio-properties-panel-group-header', hasItems ? '' : 'empty', hasItems && open ? 'open' : '', sticky && open ? 'sticky' : ''),
1741
+ onClick: hasItems ? toggleOpen : noop$3,
1742
+ children: [jsxRuntime.jsx("div", {
1743
+ title: label,
1744
+ class: "bio-properties-panel-group-header-title",
1745
+ children: label
1746
+ }), jsxRuntime.jsxs("div", {
1747
+ class: "bio-properties-panel-group-header-buttons",
1748
+ children: [add ? jsxRuntime.jsxs("button", {
1749
+ title: "Create new list item",
1750
+ class: "bio-properties-panel-group-header-button bio-properties-panel-add-entry",
1751
+ onClick: add,
1752
+ children: [jsxRuntime.jsx(CreateIcon, {}), !hasItems ? jsxRuntime.jsx("span", {
1753
+ class: "bio-properties-panel-add-entry-label",
1754
+ children: "Create"
1755
+ }) : null]
1756
+ }) : null, hasItems ? jsxRuntime.jsx("div", {
1757
+ title: `List contains ${items.length} item${items.length != 1 ? 's' : ''}`,
1758
+ class: "bio-properties-panel-list-badge",
1759
+ children: items.length
1760
+ }) : null, hasItems ? jsxRuntime.jsx("button", {
1761
+ title: "Toggle section",
1762
+ class: "bio-properties-panel-group-header-button bio-properties-panel-arrow",
1763
+ children: jsxRuntime.jsx(ArrowIcon, {
1764
+ class: open ? 'bio-properties-panel-arrow-down' : 'bio-properties-panel-arrow-right'
1765
+ })
1766
+ }) : null]
1767
+ })]
1768
+ }), jsxRuntime.jsx("div", {
1769
+ class: classnames__default['default']('bio-properties-panel-list', open && hasItems ? 'open' : ''),
1770
+ children: jsxRuntime.jsx(LayoutContext.Provider, {
1771
+ value: propertiesPanelContext,
1772
+ children: ordering.map((o, index) => {
1773
+ const item = getItem(items, o);
1774
+
1775
+ if (!item) {
1776
+ return;
1777
+ }
1778
+
1779
+ const {
1780
+ id
1781
+ } = item; // if item was added, open first or last item based on ordering
1782
+
1783
+ const autoOpen = newItemAdded && (shouldSort ? index === 0 : index === ordering.length - 1);
1784
+ return preact.createElement(ListItem, { ...item,
1785
+ autoOpen: autoOpen,
1786
+ element: element,
1787
+ index: index,
1788
+ key: id
1789
+ });
1790
+ })
1791
+ })
1792
+ })]
1793
+ });
1794
+ } // helpers ////////////////////
1795
+
1796
+ /**
1797
+ * Sorts given items alphanumeric by label
1798
+ */
1799
+
1800
+
1801
+ function sortItems(items) {
1802
+ return minDash.sortBy(items, i => i.label.toLowerCase());
1803
+ }
1804
+
1805
+ function getItem(items, id) {
1806
+ return minDash.find(items, i => i.id === id);
1807
+ }
1808
+
1809
+ function createOrdering(items) {
1810
+ return items.map(i => i.id);
1811
+ }
1812
+
1813
+ function Description$1(props) {
1814
+ const {
1815
+ element,
1816
+ forId,
1817
+ value
1818
+ } = props;
1819
+ const contextDescription = useDescriptionContext(forId, element);
1820
+ const description = value || contextDescription;
1821
+
1822
+ if (description) {
1823
+ return jsxRuntime.jsx("div", {
1824
+ class: "bio-properties-panel-description",
1825
+ children: description
1826
+ });
1827
+ }
1828
+ }
1829
+
1830
+ const noop$2 = () => {};
1831
+
1832
+ function Checkbox(props) {
1833
+ const {
1834
+ id,
1835
+ label,
1836
+ onChange,
1837
+ disabled,
1838
+ value = false,
1839
+ show = noop$2
1840
+ } = props;
1841
+
1842
+ const handleChange = ({
1843
+ target
1844
+ }) => {
1845
+ onChange(target.checked);
1846
+ };
1847
+
1848
+ const ref = useShowEntryEvent(show);
1849
+ return jsxRuntime.jsxs("div", {
1850
+ class: "bio-properties-panel-checkbox",
1851
+ children: [jsxRuntime.jsx("input", {
1852
+ ref: ref,
1853
+ id: prefixId$6(id),
1854
+ name: id,
1855
+ type: "checkbox",
1856
+ class: "bio-properties-panel-input",
1857
+ onChange: handleChange,
1858
+ checked: value,
1859
+ disabled: disabled
1860
+ }), jsxRuntime.jsx("label", {
1861
+ for: prefixId$6(id),
1862
+ class: "bio-properties-panel-label",
1863
+ children: label
1864
+ })]
1865
+ });
1866
+ }
1867
+ /**
1868
+ * @param {Object} props
1869
+ * @param {Object} props.element
1870
+ * @param {String} props.id
1871
+ * @param {String} props.description
1872
+ * @param {String} props.label
1873
+ * @param {Function} props.getValue
1874
+ * @param {Function} props.setValue
1875
+ * @param {boolean} [props.disabled]
1876
+ */
1877
+
1878
+
1879
+ function CheckboxEntry(props) {
1880
+ const {
1881
+ element,
1882
+ id,
1883
+ description,
1884
+ label,
1885
+ getValue,
1886
+ setValue,
1887
+ disabled,
1888
+ show = noop$2
1889
+ } = props;
1890
+ const value = getValue(element);
1891
+ const error = useShowErrorEvent(show);
1892
+ return jsxRuntime.jsxs("div", {
1893
+ class: "bio-properties-panel-entry bio-properties-panel-checkbox-entry",
1894
+ "data-entry-id": id,
1895
+ children: [jsxRuntime.jsx(Checkbox, {
1896
+ disabled: disabled,
1897
+ id: id,
1898
+ label: label,
1899
+ onChange: setValue,
1900
+ show: show,
1901
+ value: value
1902
+ }), error && jsxRuntime.jsx("div", {
1903
+ class: "bio-properties-panel-error",
1904
+ children: error
1905
+ }), jsxRuntime.jsx(Description$1, {
1906
+ forId: id,
1907
+ element: element,
1908
+ value: description
1909
+ })]
1910
+ });
1911
+ }
1912
+
1913
+ function isEdited$6(node) {
1914
+ return node && !!node.checked;
1915
+ } // helpers /////////////////
1916
+
1917
+
1918
+ function prefixId$6(id) {
1919
+ return `bio-properties-panel-${id}`;
1920
+ }
1921
+
1922
+ function NumberField(props) {
1923
+ const {
1924
+ debounce,
1925
+ disabled,
1926
+ id,
1927
+ label,
1928
+ max,
1929
+ min,
1930
+ onInput,
1931
+ step,
1932
+ value = ''
1933
+ } = props;
1934
+ const handleInput = hooks$1.useMemo(() => {
1935
+ return debounce(event => {
1936
+ const {
1937
+ validity,
1938
+ value
1939
+ } = event.target;
1940
+
1941
+ if (validity.valid) {
1942
+ onInput(value ? parseFloat(value) : undefined);
1943
+ }
1944
+ });
1945
+ }, [onInput, debounce]);
1946
+ return jsxRuntime.jsxs("div", {
1947
+ class: "bio-properties-panel-numberfield",
1948
+ children: [jsxRuntime.jsx("label", {
1949
+ for: prefixId$5(id),
1950
+ class: "bio-properties-panel-label",
1951
+ children: label
1952
+ }), jsxRuntime.jsx("input", {
1953
+ id: prefixId$5(id),
1954
+ type: "number",
1955
+ name: id,
1956
+ spellCheck: "false",
1957
+ autoComplete: "off",
1958
+ disabled: disabled,
1959
+ class: "bio-properties-panel-input",
1960
+ max: max,
1961
+ min: min,
1962
+ onInput: handleInput,
1963
+ step: step,
1964
+ value: value
1965
+ })]
1966
+ });
1967
+ }
1968
+ /**
1969
+ * @param {Object} props
1970
+ * @param {Boolean} props.debounce
1971
+ * @param {String} props.description
1972
+ * @param {Boolean} props.disabled
1973
+ * @param {Object} props.element
1974
+ * @param {Function} props.getValue
1975
+ * @param {String} props.id
1976
+ * @param {String} props.label
1977
+ * @param {String} props.max
1978
+ * @param {String} props.min
1979
+ * @param {Function} props.setValue
1980
+ * @param {String} props.step
1981
+ */
1982
+
1983
+
1984
+ function NumberFieldEntry(props) {
1985
+ const {
1986
+ debounce,
1987
+ description,
1988
+ disabled,
1989
+ element,
1990
+ getValue,
1991
+ id,
1992
+ label,
1993
+ max,
1994
+ min,
1995
+ setValue,
1996
+ step
1997
+ } = props;
1998
+ const value = getValue(element);
1999
+ return jsxRuntime.jsxs("div", {
2000
+ class: "bio-properties-panel-entry",
2001
+ "data-entry-id": id,
2002
+ children: [jsxRuntime.jsx(NumberField, {
2003
+ debounce: debounce,
2004
+ disabled: disabled,
2005
+ id: id,
2006
+ label: label,
2007
+ onInput: setValue,
2008
+ max: max,
2009
+ min: min,
2010
+ step: step,
2011
+ value: value
2012
+ }), jsxRuntime.jsx(Description$1, {
2013
+ forId: id,
2014
+ element: element,
2015
+ value: description
2016
+ })]
2017
+ });
2018
+ }
2019
+
2020
+ function isEdited$5(node) {
2021
+ return node && !!node.value;
2022
+ } // helpers /////////////////
2023
+
2024
+
2025
+ function prefixId$5(id) {
2026
+ return `bio-properties-panel-${id}`;
2027
+ }
2028
+
2029
+ const noop$1 = () => {};
2030
+ /**
2031
+ * @typedef { { value: string, label: string, disabled: boolean } } Option
2032
+ */
2033
+
2034
+ /**
2035
+ * Provides basic select input.
2036
+ *
2037
+ * @param {object} props
2038
+ * @param {string} props.id
2039
+ * @param {string[]} props.path
2040
+ * @param {string} props.label
2041
+ * @param {Function} props.onChange
2042
+ * @param {Array<Option>} [props.options]
2043
+ * @param {string} props.value
2044
+ * @param {boolean} [props.disabled]
2045
+ */
2046
+
2047
+
2048
+ function Select(props) {
2049
+ const {
2050
+ id,
2051
+ label,
2052
+ onChange,
2053
+ options = [],
2054
+ value,
2055
+ disabled,
2056
+ show = noop$1
2057
+ } = props;
2058
+ const ref = useShowEntryEvent(show);
2059
+
2060
+ const handleChange = ({
2061
+ target
2062
+ }) => {
2063
+ onChange(target.value);
2064
+ };
2065
+
2066
+ return jsxRuntime.jsxs("div", {
2067
+ class: "bio-properties-panel-select",
2068
+ children: [jsxRuntime.jsx("label", {
2069
+ for: prefixId$4(id),
2070
+ class: "bio-properties-panel-label",
2071
+ children: label
2072
+ }), jsxRuntime.jsx("select", {
2073
+ ref: ref,
2074
+ id: prefixId$4(id),
2075
+ name: id,
2076
+ class: "bio-properties-panel-input",
2077
+ onInput: handleChange,
2078
+ value: value,
2079
+ disabled: disabled,
2080
+ children: options.map((option, idx) => {
2081
+ return jsxRuntime.jsx("option", {
2082
+ value: option.value,
2083
+ disabled: option.disabled,
2084
+ children: option.label
2085
+ }, idx);
2086
+ })
2087
+ })]
2088
+ });
2089
+ }
2090
+ /**
2091
+ * @param {object} props
2092
+ * @param {object} props.element
2093
+ * @param {string} props.id
2094
+ * @param {string} [props.description]
2095
+ * @param {string} props.label
2096
+ * @param {Function} props.getValue
2097
+ * @param {Function} props.setValue
2098
+ * @param {Function} props.getOptions
2099
+ * @param {boolean} [props.disabled]
2100
+ */
2101
+
2102
+
2103
+ function SelectEntry(props) {
2104
+ const {
2105
+ element,
2106
+ id,
2107
+ description,
2108
+ label,
2109
+ getValue,
2110
+ setValue,
2111
+ getOptions,
2112
+ disabled,
2113
+ show = noop$1
2114
+ } = props;
2115
+ const value = getValue(element);
2116
+ const options = getOptions(element);
2117
+ const error = useShowErrorEvent(show);
2118
+ return jsxRuntime.jsxs("div", {
2119
+ class: classnames__default['default']('bio-properties-panel-entry', error ? 'has-error' : ''),
2120
+ "data-entry-id": id,
2121
+ children: [jsxRuntime.jsx(Select, {
2122
+ id: id,
2123
+ label: label,
2124
+ value: value,
2125
+ onChange: setValue,
2126
+ options: options,
2127
+ disabled: disabled,
2128
+ show: show
2129
+ }), error && jsxRuntime.jsx("div", {
2130
+ class: "bio-properties-panel-error",
2131
+ children: error
2132
+ }), jsxRuntime.jsx(Description$1, {
2133
+ forId: id,
2134
+ element: element,
2135
+ value: description
2136
+ })]
2137
+ });
2138
+ }
2139
+
2140
+ function isEdited$4(node) {
2141
+ return node && !!node.value;
2142
+ } // helpers /////////////////
2143
+
2144
+
2145
+ function prefixId$4(id) {
2146
+ return `bio-properties-panel-${id}`;
2147
+ }
2148
+
2149
+ function FeelIcon(props) {
2150
+ const {
2151
+ label,
2152
+ feel = false
2153
+ } = props;
2154
+ const feelRequiredLabel = ' must be a FEEL expression';
2155
+ const feelOptionalLabel = ' can optionally be a FEEL expression';
2156
+ return jsxRuntime.jsx("i", {
2157
+ class: "bio-properties-panel-feel-icon",
2158
+ title: label + (feel === 'required' ? feelRequiredLabel : feelOptionalLabel),
2159
+ children: feel === 'required' ? jsxRuntime.jsx(FeelRequiredIcon, {}) : jsxRuntime.jsx(FeelOptionalIcon, {})
2160
+ });
2161
+ }
2162
+
2163
+ function TextArea(props) {
2164
+ const {
2165
+ id,
2166
+ label,
2167
+ rows = 2,
2168
+ debounce,
2169
+ feel,
2170
+ onInput,
2171
+ value = '',
2172
+ disabled,
2173
+ monospace
2174
+ } = props;
2175
+ const handleInput = hooks$1.useMemo(() => {
2176
+ return debounce(({
2177
+ target
2178
+ }) => onInput(target.value.length ? target.value : undefined));
2179
+ }, [onInput, debounce]);
2180
+ return jsxRuntime.jsxs("div", {
2181
+ class: "bio-properties-panel-textarea",
2182
+ children: [jsxRuntime.jsxs("label", {
2183
+ for: prefixId$2(id),
2184
+ class: "bio-properties-panel-label",
2185
+ children: [label, feel && jsxRuntime.jsx(FeelIcon, {
2186
+ feel: feel,
2187
+ label: label
2188
+ })]
2189
+ }), jsxRuntime.jsx("textarea", {
2190
+ id: prefixId$2(id),
2191
+ name: id,
2192
+ spellCheck: "false",
2193
+ class: classnames__default['default']('bio-properties-panel-input', monospace ? 'bio-properties-panel-input-monospace' : ''),
2194
+ onInput: handleInput,
2195
+ onFocus: props.onFocus,
2196
+ onBlur: props.onBlur,
2197
+ rows: rows,
2198
+ value: value,
2199
+ disabled: disabled
2200
+ })]
2201
+ });
2202
+ }
2203
+ /**
2204
+ * @param {object} props
2205
+ * @param {object} props.element
2206
+ * @param {string} props.id
2207
+ * @param {string} props.description
2208
+ * @param {boolean} props.debounce
2209
+ * @param {string} props.label
2210
+ * @param {Function} props.getValue
2211
+ * @param {Function} props.setValue
2212
+ * @param {number} props.rows
2213
+ * @param {boolean} props.monospace
2214
+ * @param {boolean} [props.disabled]
2215
+ */
2216
+
2217
+
2218
+ function TextAreaEntry(props) {
2219
+ const {
2220
+ element,
2221
+ id,
2222
+ description,
2223
+ debounce,
2224
+ feel,
2225
+ label,
2226
+ getValue,
2227
+ setValue,
2228
+ rows,
2229
+ monospace,
2230
+ disabled
2231
+ } = props;
2232
+ const value = getValue(element);
2233
+ return jsxRuntime.jsxs("div", {
2234
+ class: "bio-properties-panel-entry",
2235
+ "data-entry-id": id,
2236
+ children: [jsxRuntime.jsx(TextArea, {
2237
+ id: id,
2238
+ label: label,
2239
+ value: value,
2240
+ onInput: setValue,
2241
+ rows: rows,
2242
+ debounce: debounce,
2243
+ monospace: monospace,
2244
+ feel: feel,
2245
+ disabled: disabled
2246
+ }), jsxRuntime.jsx(Description$1, {
2247
+ forId: id,
2248
+ element: element,
2249
+ value: description
2250
+ })]
2251
+ });
2252
+ }
2253
+
2254
+ function isEdited$2(node) {
2255
+ return node && !!node.value;
2256
+ } // helpers /////////////////
2257
+
2258
+
2259
+ function prefixId$2(id) {
2260
+ return `bio-properties-panel-${id}`;
2261
+ }
2262
+
2263
+ const noop = () => {};
2264
+
2265
+ function Textfield(props) {
2266
+ const {
2267
+ debounce,
2268
+ disabled = false,
2269
+ id,
2270
+ label,
2271
+ onInput,
2272
+ feel = false,
2273
+ value = '',
2274
+ show = noop
2275
+ } = props;
2276
+ const ref = useShowEntryEvent(show);
2277
+ const handleInput = hooks$1.useMemo(() => {
2278
+ return debounce(({
2279
+ target
2280
+ }) => onInput(target.value.length ? target.value : undefined));
2281
+ }, [onInput, debounce]);
2282
+ return jsxRuntime.jsxs("div", {
2283
+ class: "bio-properties-panel-textfield",
2284
+ children: [jsxRuntime.jsxs("label", {
2285
+ for: prefixId$1(id),
2286
+ class: "bio-properties-panel-label",
2287
+ children: [label, feel && jsxRuntime.jsx(FeelIcon, {
2288
+ feel: feel,
2289
+ label: label
2290
+ })]
2291
+ }), jsxRuntime.jsx("input", {
2292
+ ref: ref,
2293
+ id: prefixId$1(id),
2294
+ type: "text",
2295
+ name: id,
2296
+ spellCheck: "false",
2297
+ autoComplete: "off",
2298
+ disabled: disabled,
2299
+ class: "bio-properties-panel-input",
2300
+ onInput: handleInput,
2301
+ onFocus: props.onFocus,
2302
+ onBlur: props.onBlur,
2303
+ value: value || ''
2304
+ })]
2305
+ });
2306
+ }
2307
+ /**
2308
+ * @param {Object} props
2309
+ * @param {Object} props.element
2310
+ * @param {String} props.id
2311
+ * @param {String} props.description
2312
+ * @param {Boolean} props.debounce
2313
+ * @param {Boolean} props.disabled
2314
+ * @param {String} props.label
2315
+ * @param {Function} props.getValue
2316
+ * @param {Function} props.setValue
2317
+ * @param {Function} props.validate
2318
+ */
2319
+
2320
+
2321
+ function TextfieldEntry(props) {
2322
+ const {
2323
+ element,
2324
+ id,
2325
+ description,
2326
+ debounce,
2327
+ disabled,
2328
+ feel,
2329
+ label,
2330
+ getValue,
2331
+ setValue,
2332
+ validate,
2333
+ show = noop
2334
+ } = props;
2335
+ const [cachedInvalidValue, setCachedInvalidValue] = hooks$1.useState(null);
2336
+ const [validationError, setValidationError] = hooks$1.useState(null);
2337
+ let value = getValue(element);
2338
+ const previousValue = usePrevious(value);
2339
+ hooks$1.useEffect(() => {
2340
+ if (minDash.isFunction(validate)) {
2341
+ const newValidationError = validate(value) || null;
2342
+ setValidationError(newValidationError);
2343
+ }
2344
+ }, [value]);
2345
+
2346
+ const onInput = newValue => {
2347
+ let newValidationError = null;
2348
+
2349
+ if (minDash.isFunction(validate)) {
2350
+ newValidationError = validate(newValue) || null;
2351
+ }
2352
+
2353
+ if (newValidationError) {
2354
+ setCachedInvalidValue(newValue);
2355
+ } else {
2356
+ setValue(newValue);
2357
+ }
2358
+
2359
+ setValidationError(newValidationError);
2360
+ };
2361
+
2362
+ if (previousValue === value && validationError) {
2363
+ value = cachedInvalidValue;
2364
+ }
2365
+
2366
+ const temporaryError = useShowErrorEvent(show);
2367
+ const error = temporaryError || validationError;
2368
+ return jsxRuntime.jsxs("div", {
2369
+ class: classnames__default['default']('bio-properties-panel-entry', error ? 'has-error' : ''),
2370
+ "data-entry-id": id,
2371
+ children: [jsxRuntime.jsx(Textfield, {
2372
+ debounce: debounce,
2373
+ disabled: disabled,
2374
+ feel: feel,
2375
+ id: id,
2376
+ label: label,
2377
+ onInput: onInput,
2378
+ show: show,
2379
+ value: value
2380
+ }), error && jsxRuntime.jsx("div", {
2381
+ class: "bio-properties-panel-error",
2382
+ children: error
2383
+ }), jsxRuntime.jsx(Description$1, {
2384
+ forId: id,
2385
+ element: element,
2386
+ value: description
2387
+ })]
2388
+ });
2389
+ }
2390
+
2391
+ function isEdited$1(node) {
2392
+ return node && !!node.value;
2393
+ } // helpers /////////////////
2394
+
2395
+
2396
+ function prefixId$1(id) {
2397
+ return `bio-properties-panel-${id}`;
2398
+ }
2399
+
2400
+ function arrayAdd$1(array, index, item) {
2401
+ const copy = [...array];
2402
+ copy.splice(index, 0, item);
2403
+ return copy;
2404
+ }
2405
+ function textToLabel(text = '...') {
2406
+ if (text.length > 10) {
2407
+ return `${text.substring(0, 30)}...`;
2408
+ }
2409
+
2410
+ return text;
2411
+ }
2412
+ const INPUTS = ['checkbox', 'checklist', 'number', 'radio', 'select', 'taglist', 'textfield'];
2413
+ const VALUES_INPUTS = ['checklist', 'radio', 'select', 'taglist'];
2414
+
2415
+ function _extends$b() { _extends$b = Object.assign || 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$b.apply(this, arguments); }
2416
+ var ButtonIcon = (({
2417
+ styles = {},
2418
+ ...props
2419
+ }) => /*#__PURE__*/React__default['default'].createElement("svg", _extends$b({
2420
+ xmlns: "http://www.w3.org/2000/svg",
2421
+ width: "54",
2422
+ height: "54"
2423
+ }, props), /*#__PURE__*/React__default['default'].createElement("path", {
2424
+ fillRule: "evenodd",
2425
+ d: "M45 17a3 3 0 013 3v14a3 3 0 01-3 3H9a3 3 0 01-3-3V20a3 3 0 013-3h36zm-9 8.889H18v2.222h18V25.89z"
2426
+ })));
2427
+
2428
+ function _extends$a() { _extends$a = Object.assign || 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$a.apply(this, arguments); }
2429
+ var CheckboxIcon = (({
2430
+ styles = {},
2431
+ ...props
2432
+ }) => /*#__PURE__*/React__default['default'].createElement("svg", _extends$a({
2433
+ xmlns: "http://www.w3.org/2000/svg",
2434
+ width: "54",
2435
+ height: "54"
2436
+ }, props), /*#__PURE__*/React__default['default'].createElement("path", {
2437
+ d: "M34 18H20a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2V20a2 2 0 00-2-2zm-9 14l-5-5 1.41-1.41L25 29.17l7.59-7.59L34 23l-9 9z"
2438
+ })));
2439
+
2440
+ function _extends$9() { _extends$9 = Object.assign || 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$9.apply(this, arguments); }
2441
+ var ChecklistIcon = (({
2442
+ styles = {},
2443
+ ...props
2444
+ }) => /*#__PURE__*/React__default['default'].createElement("svg", _extends$9({
2445
+ width: "54",
2446
+ height: "54",
2447
+ fill: "none",
2448
+ xmlns: "http://www.w3.org/2000/svg"
2449
+ }, props), /*#__PURE__*/React__default['default'].createElement("path", {
2450
+ fillRule: "evenodd",
2451
+ clipRule: "evenodd",
2452
+ d: "M19 24h-6v6h6v-6zm-6-2a2 2 0 00-2 2v6a2 2 0 002 2h6a2 2 0 002-2v-6a2 2 0 00-2-2h-6zm6 18h-6v6h6v-6zm-6-2a2 2 0 00-2 2v6a2 2 0 002 2h6a2 2 0 002-2v-6a2 2 0 00-2-2h-6zm6-30h-6v6h6V8zm-6-2a2 2 0 00-2 2v6a2 2 0 002 2h6a2 2 0 002-2V8a2 2 0 00-2-2h-6z",
2453
+ fill: "#22242A"
2454
+ }), /*#__PURE__*/React__default['default'].createElement("path", {
2455
+ d: "M26 26a1 1 0 011-1h15a1 1 0 011 1v2a1 1 0 01-1 1H27a1 1 0 01-1-1v-2zm0 16a1 1 0 011-1h15a1 1 0 011 1v2a1 1 0 01-1 1H27a1 1 0 01-1-1v-2zm0-32a1 1 0 011-1h15a1 1 0 011 1v2a1 1 0 01-1 1H27a1 1 0 01-1-1v-2z",
2456
+ fill: "#22242A"
2457
+ })));
2458
+
2459
+ function _extends$8() { _extends$8 = Object.assign || 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$8.apply(this, arguments); }
2460
+ var TaglistIcon = (({
2461
+ styles = {},
2462
+ ...props
2463
+ }) => /*#__PURE__*/React__default['default'].createElement("svg", _extends$8({
2464
+ width: "54",
2465
+ height: "54",
2466
+ fill: "none",
2467
+ xmlns: "http://www.w3.org/2000/svg"
2468
+ }, props), /*#__PURE__*/React__default['default'].createElement("path", {
2469
+ fillRule: "evenodd",
2470
+ clipRule: "evenodd",
2471
+ d: "M45 16a3 3 0 013 3v16a3 3 0 01-3 3H9a3 3 0 01-3-3V19a3 3 0 013-3h36zm0 2H9a1 1 0 00-1 1v16a1 1 0 001 1h36a1 1 0 001-1V19a1 1 0 00-1-1z",
2472
+ fill: "#000"
2473
+ }), /*#__PURE__*/React__default['default'].createElement("path", {
2474
+ d: "M11 22a1 1 0 011-1h19a1 1 0 011 1v10a1 1 0 01-1 1H12a1 1 0 01-1-1V22z",
2475
+ fill: "#505562"
2476
+ })));
2477
+
2478
+ function _extends$7() { _extends$7 = Object.assign || 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$7.apply(this, arguments); }
2479
+ var FormIcon = (({
2480
+ styles = {},
2481
+ ...props
2482
+ }) => /*#__PURE__*/React__default['default'].createElement("svg", _extends$7({
2483
+ xmlns: "http://www.w3.org/2000/svg",
2484
+ width: "54",
2485
+ height: "54"
2486
+ }, props), /*#__PURE__*/React__default['default'].createElement("rect", {
2487
+ x: "15",
2488
+ y: "17",
2489
+ width: "24",
2490
+ height: "4",
2491
+ rx: "1"
2492
+ }), /*#__PURE__*/React__default['default'].createElement("rect", {
2493
+ x: "15",
2494
+ y: "25",
2495
+ width: "24",
2496
+ height: "4",
2497
+ rx: "1"
2498
+ }), /*#__PURE__*/React__default['default'].createElement("rect", {
2499
+ x: "15",
2500
+ y: "33",
2501
+ width: "13",
2502
+ height: "4",
2503
+ rx: "1"
2504
+ })));
2505
+
2506
+ function _extends$6() { _extends$6 = Object.assign || 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$6.apply(this, arguments); }
2507
+ var ColumnsIcon = (({
2508
+ styles = {},
2509
+ ...props
2510
+ }) => /*#__PURE__*/React__default['default'].createElement("svg", _extends$6({
2511
+ xmlns: "http://www.w3.org/2000/svg",
2512
+ width: "54",
2513
+ height: "54"
2514
+ }, props), /*#__PURE__*/React__default['default'].createElement("path", {
2515
+ fillRule: "evenodd",
2516
+ d: "M8 33v5a1 1 0 001 1h4v2H9a3 3 0 01-3-3v-5h2zm18 6v2H15v-2h11zm13 0v2H28v-2h11zm9-6v5a3 3 0 01-3 3h-4v-2h4a1 1 0 00.993-.883L46 38v-5h2zM8 22v9H6v-9h2zm40 0v9h-2v-9h2zm-35-9v2H9a1 1 0 00-.993.883L8 16v4H6v-4a3 3 0 013-3h4zm32 0a3 3 0 013 3v4h-2v-4a1 1 0 00-.883-.993L45 15h-4v-2h4zm-6 0v2H28v-2h11zm-13 0v2H15v-2h11z"
2517
+ })));
2518
+
2519
+ function _extends$5() { _extends$5 = Object.assign || 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$5.apply(this, arguments); }
2520
+ var NumberIcon = (({
2521
+ styles = {},
2522
+ ...props
2523
+ }) => /*#__PURE__*/React__default['default'].createElement("svg", _extends$5({
2524
+ xmlns: "http://www.w3.org/2000/svg",
2525
+ width: "54",
2526
+ height: "54"
2527
+ }, props), /*#__PURE__*/React__default['default'].createElement("path", {
2528
+ fillRule: "evenodd",
2529
+ d: "M45 16a3 3 0 013 3v16a3 3 0 01-3 3H9a3 3 0 01-3-3V19a3 3 0 013-3h36zm0 2H9a1 1 0 00-1 1v16a1 1 0 001 1h36a1 1 0 001-1V19a1 1 0 00-1-1zM35 28.444h7l-3.5 4-3.5-4zM35 26h7l-3.5-4-3.5 4z"
2530
+ })));
2531
+
2532
+ function _extends$4() { _extends$4 = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$4.apply(this, arguments); }
2533
+ var RadioIcon = (({
2534
+ styles = {},
2535
+ ...props
2536
+ }) => /*#__PURE__*/React__default['default'].createElement("svg", _extends$4({
2537
+ xmlns: "http://www.w3.org/2000/svg",
2538
+ width: "54",
2539
+ height: "54"
2540
+ }, props), /*#__PURE__*/React__default['default'].createElement("path", {
2541
+ d: "M27 22c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5zm0-5c-5.52 0-10 4.48-10 10s4.48 10 10 10 10-4.48 10-10-4.48-10-10-10zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"
2542
+ })));
2543
+
2544
+ function _extends$3() { _extends$3 = Object.assign || 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); }
2545
+ var SelectIcon = (({
2546
+ styles = {},
2547
+ ...props
2548
+ }) => /*#__PURE__*/React__default['default'].createElement("svg", _extends$3({
2549
+ xmlns: "http://www.w3.org/2000/svg",
2550
+ width: "54",
2551
+ height: "54"
2552
+ }, props), /*#__PURE__*/React__default['default'].createElement("path", {
2553
+ fillRule: "evenodd",
2554
+ d: "M45 16a3 3 0 013 3v16a3 3 0 01-3 3H9a3 3 0 01-3-3V19a3 3 0 013-3h36zm0 2H9a1 1 0 00-1 1v16a1 1 0 001 1h36a1 1 0 001-1V19a1 1 0 00-1-1zm-12 7h9l-4.5 6-4.5-6z"
2555
+ })));
2556
+
2557
+ function _extends$2() { _extends$2 = Object.assign || 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); }
2558
+ var TextIcon = (({
2559
+ styles = {},
2560
+ ...props
2561
+ }) => /*#__PURE__*/React__default['default'].createElement("svg", _extends$2({
2562
+ xmlns: "http://www.w3.org/2000/svg",
2563
+ width: "54",
2564
+ height: "54"
2565
+ }, props), /*#__PURE__*/React__default['default'].createElement("path", {
2566
+ d: "M20.58 33.77h-3l-1.18-3.08H11l-1.1 3.08H7l5.27-13.54h2.89zm-5-5.36l-1.86-5-1.83 5zM22 20.23h5.41a15.47 15.47 0 012.4.14 3.42 3.42 0 011.41.55 3.47 3.47 0 011 1.14 3 3 0 01.42 1.58 3.26 3.26 0 01-1.91 2.94 3.63 3.63 0 011.91 1.22 3.28 3.28 0 01.66 2 4 4 0 01-.43 1.8 3.63 3.63 0 01-1.09 1.4 3.89 3.89 0 01-1.83.65q-.69.07-3.3.09H22zm2.73 2.25v3.13h3.8a1.79 1.79 0 001.1-.49 1.41 1.41 0 00.41-1 1.49 1.49 0 00-.35-1 1.54 1.54 0 00-1-.48c-.27 0-1.05-.05-2.34-.05zm0 5.39v3.62h2.57a11.52 11.52 0 001.88-.09 1.65 1.65 0 001-.54 1.6 1.6 0 00.38-1.14 1.75 1.75 0 00-.29-1 1.69 1.69 0 00-.86-.62 9.28 9.28 0 00-2.41-.23zM44.35 28.79l2.65.84a5.94 5.94 0 01-2 3.29A5.74 5.74 0 0141.38 34a5.87 5.87 0 01-4.44-1.84 7.09 7.09 0 01-1.73-5A7.43 7.43 0 0137 21.87 6 6 0 0141.54 20a5.64 5.64 0 014 1.47A5.33 5.33 0 0147 24l-2.7.65a2.8 2.8 0 00-2.86-2.27A3.09 3.09 0 0039 23.42a5.31 5.31 0 00-.93 3.5 5.62 5.62 0 00.93 3.65 3 3 0 002.4 1.09 2.72 2.72 0 001.82-.66 4 4 0 001.13-2.21z"
2567
+ })));
2568
+
2569
+ function _extends$1() { _extends$1 = Object.assign || 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); }
2570
+ var TextfieldIcon = (({
2571
+ styles = {},
2572
+ ...props
2573
+ }) => /*#__PURE__*/React__default['default'].createElement("svg", _extends$1({
2574
+ xmlns: "http://www.w3.org/2000/svg",
2575
+ width: "54",
2576
+ height: "54"
2577
+ }, props), /*#__PURE__*/React__default['default'].createElement("path", {
2578
+ fillRule: "evenodd",
2579
+ d: "M45 16a3 3 0 013 3v16a3 3 0 01-3 3H9a3 3 0 01-3-3V19a3 3 0 013-3h36zm0 2H9a1 1 0 00-1 1v16a1 1 0 001 1h36a1 1 0 001-1V19a1 1 0 00-1-1zm-32 4v10h-2V22h2z"
2580
+ })));
2581
+
2582
+ const iconsByType = {
2583
+ button: ButtonIcon,
2584
+ checkbox: CheckboxIcon,
2585
+ checklist: ChecklistIcon,
2586
+ columns: ColumnsIcon,
2587
+ number: NumberIcon,
2588
+ radio: RadioIcon,
2589
+ select: SelectIcon,
2590
+ taglist: TaglistIcon,
2591
+ text: TextIcon,
2592
+ textfield: TextfieldIcon,
2593
+ default: FormIcon
2594
+ };
2595
+
2596
+ const labelsByType = {
2597
+ button: 'BUTTON',
2598
+ checkbox: 'CHECKBOX',
2599
+ checklist: 'CHECKLIST',
2600
+ columns: 'COLUMNS',
2601
+ default: 'FORM',
2602
+ number: 'NUMBER',
2603
+ radio: 'RADIO',
2604
+ select: 'SELECT',
2605
+ taglist: 'TAGLIST',
2606
+ text: 'TEXT',
2607
+ textfield: 'TEXT FIELD'
2608
+ };
2609
+ const PropertiesPanelHeaderProvider = {
2610
+ getElementLabel: field => {
2611
+ const {
2612
+ type
2613
+ } = field;
2614
+
2615
+ if (type === 'text') {
2616
+ return textToLabel(field.text);
2617
+ }
2618
+
2619
+ if (type === 'default') {
2620
+ return field.id;
2621
+ }
2622
+
2623
+ return field.label;
2624
+ },
2625
+ getElementIcon: field => {
2626
+ const {
2627
+ type
2628
+ } = field;
2629
+ const Icon = iconsByType[type];
2630
+
2631
+ if (Icon) {
2632
+ return () => jsxRuntime.jsx(Icon, {
2633
+ width: "36",
2634
+ height: "36",
2635
+ viewBox: "0 0 54 54"
2636
+ });
2637
+ }
2638
+ },
2639
+ getTypeLabel: field => {
2640
+ const {
2641
+ type
2642
+ } = field;
2643
+ return labelsByType[type];
2644
+ }
2645
+ };
2646
+
2647
+ /**
2648
+ * Provide placeholders for empty and multiple state.
2649
+ */
2650
+ const PropertiesPanelPlaceholderProvider = {
2651
+ getEmpty: () => {
2652
+ return {
2653
+ text: 'Select a form field to edit its properties.'
2654
+ };
2655
+ },
2656
+ getMultiple: () => {
2657
+ return {
2658
+ text: 'Multiple form fields are selected. Select a single form field to edit its properties.'
2659
+ };
2660
+ }
2661
+ };
2662
+
2663
+ function ActionEntry(props) {
2664
+ const {
2665
+ editField,
2666
+ field
2667
+ } = props;
2668
+ const {
2669
+ type
2670
+ } = field;
2671
+ const entries = [];
1187
2672
 
1188
- if (error) {
1189
- classes.push('fjs-has-error');
2673
+ if (type === 'button') {
2674
+ entries.push({
2675
+ id: 'action',
2676
+ component: Action,
2677
+ editField: editField,
2678
+ field: field,
2679
+ isEdited: isEdited$4
2680
+ });
1190
2681
  }
1191
2682
 
1192
- return jsxRuntime.jsxs("div", {
1193
- class: "fjs-properties-panel-text",
1194
- children: [jsxRuntime.jsx("label", {
1195
- for: prefixId(id),
1196
- class: "fjs-properties-panel-label",
1197
- children: label
1198
- }), jsxRuntime.jsx("input", {
1199
- id: prefixId(id),
1200
- type: "text",
1201
- spellcheck: false,
1202
- class: classes.join(' '),
1203
- onInput: onInput,
1204
- value: value
1205
- }), error && jsxRuntime.jsx("div", {
1206
- class: "fjs-properties-panel-error",
1207
- children: error
1208
- })]
1209
- });
2683
+ return entries;
1210
2684
  }
1211
2685
 
1212
- function CheckboxInputEntry(props) {
2686
+ function Action(props) {
1213
2687
  const {
1214
2688
  editField,
1215
2689
  field,
1216
- id,
1217
- label,
1218
- path
2690
+ id
1219
2691
  } = props;
2692
+ const path = ['action'];
1220
2693
 
1221
- const onChange = value => {
1222
- if (editField && path) {
1223
- editField(field, path, value);
1224
- } else {
1225
- props.onChange(value);
1226
- }
2694
+ const getValue = () => {
2695
+ return minDash.get(field, path, '');
1227
2696
  };
1228
2697
 
1229
- const value = path ? minDash.get(field, path, false) : props.value;
1230
- return jsxRuntime.jsx("div", {
1231
- class: "fjs-properties-panel-entry",
1232
- children: jsxRuntime.jsx(CheckboxInput, {
1233
- id: id,
1234
- label: label,
1235
- onChange: onChange,
1236
- value: value
1237
- })
2698
+ const setValue = value => {
2699
+ return editField(field, path, value);
2700
+ };
2701
+
2702
+ const getOptions = () => [{
2703
+ label: 'Submit',
2704
+ value: 'submit'
2705
+ }, {
2706
+ label: 'Reset',
2707
+ value: 'reset'
2708
+ }];
2709
+
2710
+ return SelectEntry({
2711
+ element: field,
2712
+ getOptions,
2713
+ getValue,
2714
+ id,
2715
+ label: 'Action',
2716
+ setValue
1238
2717
  });
1239
2718
  }
1240
2719
 
1241
- function NumberInputEntry(props) {
2720
+ function ColumnsEntry(props) {
1242
2721
  const {
1243
2722
  editField,
1244
- field,
1245
- id,
1246
- label,
1247
- max,
1248
- min,
1249
- onChange,
1250
- path
2723
+ field
1251
2724
  } = props;
2725
+ const {
2726
+ type
2727
+ } = field;
2728
+ const entries = [];
1252
2729
 
1253
- const onInput = value => {
1254
- if (editField && path) {
1255
- editField(field, path, value);
1256
- } else {
1257
- onChange(value);
1258
- }
1259
- };
2730
+ if (type === 'columns') {
2731
+ entries.push({
2732
+ id: 'columns',
2733
+ component: Columns,
2734
+ editField: editField,
2735
+ field: field,
2736
+ isEdited: isEdited$5
2737
+ });
2738
+ }
1260
2739
 
1261
- const value = path ? minDash.get(field, path, '') : props.value;
1262
- return jsxRuntime.jsx("div", {
1263
- class: "fjs-properties-panel-entry",
1264
- children: jsxRuntime.jsx(NumberInput, {
1265
- id: id,
1266
- label: label,
1267
- max: max,
1268
- min: min,
1269
- onInput: onInput,
1270
- value: value
1271
- })
1272
- });
2740
+ return entries;
1273
2741
  }
1274
2742
 
1275
- function SelectEntry(props) {
2743
+ function Columns(props) {
1276
2744
  const {
1277
2745
  editField,
1278
2746
  field,
1279
- id,
1280
- description,
1281
- label,
1282
- options,
1283
- path
2747
+ id
1284
2748
  } = props;
2749
+ const debounce = useService('debounce');
2750
+
2751
+ const getValue = () => {
2752
+ return field.components.length;
2753
+ };
2754
+
2755
+ const setValue = value => {
2756
+ let components = field.components.slice();
1285
2757
 
1286
- const onChange = value => {
1287
- if (editField && path) {
1288
- editField(field, path, value);
2758
+ if (value > components.length) {
2759
+ while (value > components.length) {
2760
+ components.push(formJsViewer.Default.create({
2761
+ _parent: field.id
2762
+ }));
2763
+ }
1289
2764
  } else {
1290
- props.onChange(value);
2765
+ components = components.slice(0, value);
1291
2766
  }
2767
+
2768
+ editField(field, 'components', components);
1292
2769
  };
1293
2770
 
1294
- const value = path ? minDash.get(field, path, '') : props.value;
1295
- return jsxRuntime.jsxs("div", {
1296
- class: "fjs-properties-panel-entry",
1297
- children: [jsxRuntime.jsx(Select, {
1298
- id: id,
1299
- label: label,
1300
- onChange: onChange,
1301
- options: options,
1302
- value: value
1303
- }), description && jsxRuntime.jsx("div", {
1304
- class: "fjs-properties-panel-description",
1305
- children: description
1306
- })]
2771
+ return NumberFieldEntry({
2772
+ debounce,
2773
+ element: field,
2774
+ getValue,
2775
+ id,
2776
+ label: 'Columns',
2777
+ setValue
1307
2778
  });
1308
2779
  }
1309
2780
 
1310
- function TextareaEntry(props) {
2781
+ function DescriptionEntry(props) {
1311
2782
  const {
1312
2783
  editField,
1313
- field,
1314
- id,
1315
- description,
1316
- label,
1317
- onChange,
1318
- path
2784
+ field
1319
2785
  } = props;
2786
+ const {
2787
+ type
2788
+ } = field;
2789
+ const entries = [];
1320
2790
 
1321
- const onInput = value => {
1322
- if (editField && path) {
1323
- editField(field, path, value);
1324
- } else {
1325
- onChange(value);
1326
- }
1327
- };
2791
+ if (INPUTS.includes(type)) {
2792
+ entries.push({
2793
+ id: 'description',
2794
+ component: Description,
2795
+ editField: editField,
2796
+ field: field,
2797
+ isEdited: isEdited$1
2798
+ });
2799
+ }
1328
2800
 
1329
- const value = path ? minDash.get(field, path, '') : props.value;
1330
- return jsxRuntime.jsxs("div", {
1331
- class: "fjs-properties-panel-entry",
1332
- children: [jsxRuntime.jsx(Textarea, {
1333
- id: id,
1334
- label: label,
1335
- onInput: onInput,
1336
- value: value
1337
- }), description && jsxRuntime.jsx("div", {
1338
- class: "fjs-properties-panel-description",
1339
- children: description
1340
- })]
1341
- });
2801
+ return entries;
1342
2802
  }
1343
2803
 
1344
- function TextInputEntry(props) {
2804
+ function Description(props) {
1345
2805
  const {
1346
2806
  editField,
1347
2807
  field,
1348
- id,
1349
- description,
1350
- label,
1351
- onChange,
1352
- path,
1353
- validate
2808
+ id
1354
2809
  } = props;
2810
+ const debounce = useService('debounce');
2811
+ const path = ['description'];
1355
2812
 
1356
- const onInput = value => {
1357
- if (editField && path) {
1358
- editField(field, path, value);
1359
- } else {
1360
- onChange(value);
1361
- }
2813
+ const getValue = () => {
2814
+ return minDash.get(field, path, '');
1362
2815
  };
1363
2816
 
1364
- const value = path ? minDash.get(field, path, '') : props.value;
1365
- return jsxRuntime.jsxs("div", {
1366
- class: "fjs-properties-panel-entry",
1367
- children: [jsxRuntime.jsx(TextInput, {
1368
- id: id,
1369
- label: label,
1370
- onInput: onInput,
1371
- validate: validate,
1372
- value: value
1373
- }), description && jsxRuntime.jsx("div", {
1374
- class: "fjs-properties-panel-description",
1375
- children: description
1376
- })]
2817
+ const setValue = value => {
2818
+ return editField(field, path, value);
2819
+ };
2820
+
2821
+ return TextfieldEntry({
2822
+ debounce,
2823
+ element: field,
2824
+ getValue,
2825
+ id,
2826
+ label: 'Field description',
2827
+ setValue
1377
2828
  });
1378
2829
  }
1379
2830
 
1380
- function _extends$3() { _extends$3 = Object.assign || 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); }
1381
- var CreateIcon = (({
1382
- styles = {},
1383
- ...props
1384
- }) => /*#__PURE__*/React__default['default'].createElement("svg", _extends$3({
1385
- xmlns: "http://www.w3.org/2000/svg",
1386
- width: "12",
1387
- height: "12"
1388
- }, props), /*#__PURE__*/React__default['default'].createElement("path", {
1389
- fillRule: "evenodd",
1390
- d: "M7 0v5h5v2H7v5H5V7H0V5h5V0h2z"
1391
- })));
1392
-
1393
- function _extends$2() { _extends$2 = Object.assign || 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); }
1394
- var ListArrowIcon = (({
1395
- styles = {},
1396
- ...props
1397
- }) => /*#__PURE__*/React__default['default'].createElement("svg", _extends$2({
1398
- xmlns: "http://www.w3.org/2000/svg",
1399
- width: "7",
1400
- height: "9"
1401
- }, props), /*#__PURE__*/React__default['default'].createElement("path", {
1402
- fillRule: "evenodd",
1403
- d: "M6.25 4.421L4.836 5.835h-.001L2.007 8.663.593 7.249 3.421 4.42.593 1.593 2.007.178 6.25 4.421z"
1404
- })));
1405
-
1406
- function _extends$1() { _extends$1 = Object.assign || 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); }
1407
- var ListDeleteIcon = (({
1408
- styles = {},
1409
- ...props
1410
- }) => /*#__PURE__*/React__default['default'].createElement("svg", _extends$1({
1411
- xmlns: "http://www.w3.org/2000/svg",
1412
- width: "11",
1413
- height: "14"
1414
- }, props), /*#__PURE__*/React__default['default'].createElement("path", {
1415
- d: "M10 4v8c0 1.1-.9 2-2 2H3c-1.1 0-2-.9-2-2V4h9zM8 6H3v4.8c0 .66.5 1.2 1.111 1.2H6.89C7.5 12 8 11.46 8 10.8V6zm3-5H8.5l-1-1h-4l-1 1H0v1.5h11V1z"
1416
- })));
1417
-
1418
- function _extends() { _extends = Object.assign || 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); }
1419
- var SectionArrowIcon = (({
1420
- styles = {},
1421
- ...props
1422
- }) => /*#__PURE__*/React__default['default'].createElement("svg", _extends({
1423
- xmlns: "http://www.w3.org/2000/svg",
1424
- width: "8",
1425
- height: "12"
1426
- }, props), /*#__PURE__*/React__default['default'].createElement("path", {
1427
- fillRule: "evenodd",
1428
- d: "M2.007 11.66L.593 10.248l4.242-4.243L.593 1.761 2.007.347l5.657 5.657-5.657 5.657z"
1429
- })));
1430
-
1431
- function CollapsibleEntry(props) {
2831
+ function DefaultOptionEntry(props) {
1432
2832
  const {
1433
- children,
1434
- label,
1435
- removeEntry = () => {}
2833
+ editField,
2834
+ field
1436
2835
  } = props;
1437
- const [collapsed, setCollapsed] = hooks$1.useState(false);
2836
+ const {
2837
+ type
2838
+ } = field;
2839
+ const entries = []; // Only make default values available when they are statically defined
1438
2840
 
1439
- const toggleCollapsed = () => setCollapsed(!collapsed);
2841
+ if (!INPUTS.includes(type) || VALUES_INPUTS.includes(type) && !field.values) {
2842
+ return entries;
2843
+ }
1440
2844
 
1441
- const classes = ['fjs-properties-panel-collapsible-entry'];
2845
+ const defaultOptions = {
2846
+ editField,
2847
+ field,
2848
+ id: 'defaultValue',
2849
+ label: 'Default value'
2850
+ };
1442
2851
 
1443
- if (collapsed) {
1444
- classes.push('fjs-properties-panel-collapsible-entry-collapsed');
2852
+ if (type === 'checkbox') {
2853
+ entries.push({ ...defaultOptions,
2854
+ component: DefaultValueCheckbox,
2855
+ isEdited: isEdited$4
2856
+ });
1445
2857
  }
1446
2858
 
1447
- return jsxRuntime.jsxs("div", {
1448
- class: classes.join(' '),
1449
- children: [jsxRuntime.jsxs("div", {
1450
- class: "fjs-properties-panel-collapsible-entry-header",
1451
- onClick: toggleCollapsed,
1452
- children: [jsxRuntime.jsxs("div", {
1453
- children: [jsxRuntime.jsx(ListArrowIcon, {
1454
- class: collapsed ? 'fjs-arrow-right' : 'fjs-arrow-down'
1455
- }), jsxRuntime.jsx("span", {
1456
- class: "fjs-properties-panel-collapsible-entry-header-label",
1457
- children: label
1458
- })]
1459
- }), jsxRuntime.jsx("button", {
1460
- class: "fjs-properties-panel-collapsible-entry-header-remove-entry",
1461
- onClick: stopPropagation(removeEntry),
1462
- children: jsxRuntime.jsx(ListDeleteIcon, {})
1463
- })]
1464
- }), collapsed ? null : jsxRuntime.jsx("div", {
1465
- class: "fjs-properties-panel-collapsible-entry-entries",
1466
- children: children
1467
- })]
1468
- });
1469
- }
2859
+ if (type === 'number') {
2860
+ entries.push({ ...defaultOptions,
2861
+ component: DefaultValueNumber,
2862
+ isEdited: isEdited$5
2863
+ });
2864
+ }
1470
2865
 
1471
- function Group(props) {
1472
- const {
1473
- children,
1474
- hasEntries = true,
1475
- label
1476
- } = props;
1477
- const [open, setOpen] = hooks$1.useState(hasEntries);
2866
+ if (type === 'radio' || type === 'select') {
2867
+ entries.push({ ...defaultOptions,
2868
+ component: DefaultValueSingleSelect,
2869
+ isEdited: isEdited$4
2870
+ });
2871
+ } // todo(Skaiir): implement a multiselect equivalent (cf. https://github.com/bpmn-io/form-js/issues/265)
1478
2872
 
1479
- const toggleOpen = () => setOpen(!open);
1480
2873
 
1481
- const addEntry = event => {
1482
- event.stopPropagation();
1483
- setOpen(true);
1484
- props.addEntry();
1485
- };
2874
+ if (type === 'textfield') {
2875
+ entries.push({ ...defaultOptions,
2876
+ component: DefaultValueTextfield,
2877
+ isEdited: isEdited$1
2878
+ });
2879
+ }
1486
2880
 
1487
- return jsxRuntime.jsxs("div", {
1488
- class: "fjs-properties-panel-group",
1489
- children: [jsxRuntime.jsxs("div", {
1490
- class: "fjs-properties-panel-group-header",
1491
- onClick: hasEntries ? toggleOpen : () => {},
1492
- children: [jsxRuntime.jsx("span", {
1493
- class: "fjs-properties-panel-group-header-label",
1494
- children: label
1495
- }), jsxRuntime.jsxs("div", {
1496
- class: "fjs-properties-panel-group-header-buttons",
1497
- children: [props.addEntry ? jsxRuntime.jsx("button", {
1498
- class: "fjs-properties-panel-group-header-button fjs-properties-panel-group-header-button-add-entry",
1499
- onClick: addEntry,
1500
- children: jsxRuntime.jsx(CreateIcon, {})
1501
- }) : null, jsxRuntime.jsx("button", {
1502
- class: "fjs-properties-panel-group-header-button fjs-properties-panel-group-header-button-toggle-open",
1503
- children: jsxRuntime.jsx(SectionArrowIcon, {
1504
- class: hasEntries && open ? 'fjs-arrow-down' : 'fjs-arrow-right'
1505
- })
1506
- })]
1507
- })]
1508
- }), hasEntries && open ? jsxRuntime.jsx("div", {
1509
- class: "fjs-properties-panel-group-entries",
1510
- children: children
1511
- }) : null]
1512
- });
2881
+ return entries;
1513
2882
  }
1514
2883
 
1515
- function ActionEntry(props) {
2884
+ function DefaultValueCheckbox(props) {
1516
2885
  const {
1517
2886
  editField,
1518
- field
2887
+ field,
2888
+ id,
2889
+ label
1519
2890
  } = props;
1520
- const options = [{
1521
- label: 'Submit',
1522
- value: 'submit'
1523
- }, {
1524
- label: 'Reset',
1525
- value: 'reset'
1526
- }];
1527
- return jsxRuntime.jsx(SelectEntry, {
1528
- editField: editField,
1529
- field: field,
1530
- id: "action",
1531
- label: "Action",
1532
- options: options,
1533
- path: ['action']
1534
- });
1535
- }
1536
-
1537
- function ColumnsEntry(props) {
1538
2891
  const {
1539
- editField,
1540
- field
1541
- } = props;
2892
+ defaultValue
2893
+ } = field;
2894
+ const path = ['defaultValue'];
1542
2895
 
1543
- const onInput = value => {
1544
- let components = field.components.slice();
2896
+ const getOptions = () => {
2897
+ return [{
2898
+ label: 'Checked',
2899
+ value: 'true'
2900
+ }, {
2901
+ label: 'Not checked',
2902
+ value: 'false'
2903
+ }];
2904
+ };
1545
2905
 
1546
- if (value > components.length) {
1547
- while (value > components.length) {
1548
- components.push(formJsViewer.Default.create({
1549
- _parent: field.id
1550
- }));
1551
- }
1552
- } else {
1553
- components = components.slice(0, value);
1554
- }
2906
+ const setValue = value => {
2907
+ return editField(field, path, parseStringToBoolean(value));
2908
+ };
1555
2909
 
1556
- editField(field, 'components', components);
2910
+ const getValue = () => {
2911
+ return parseBooleanToString(defaultValue);
1557
2912
  };
1558
2913
 
1559
- const value = field.components.length;
1560
- return jsxRuntime.jsx("div", {
1561
- class: "fjs-properties-panel-entry",
1562
- children: jsxRuntime.jsx(NumberInputEntry, {
1563
- id: "columns",
1564
- label: "Columns",
1565
- onInput: onInput,
1566
- value: value,
1567
- min: "1",
1568
- max: "3"
1569
- })
2914
+ return SelectEntry({
2915
+ element: field,
2916
+ getOptions,
2917
+ getValue,
2918
+ id,
2919
+ label,
2920
+ setValue
1570
2921
  });
1571
2922
  }
1572
2923
 
1573
- function DescriptionEntry(props) {
2924
+ function DefaultValueNumber(props) {
1574
2925
  const {
1575
2926
  editField,
1576
- field
2927
+ field,
2928
+ id,
2929
+ label
1577
2930
  } = props;
1578
- return jsxRuntime.jsx(TextInputEntry, {
1579
- editField: editField,
1580
- field: field,
1581
- id: "description",
1582
- label: "Field Description",
1583
- path: ['description']
2931
+ const debounce = useService('debounce');
2932
+ const path = ['defaultValue'];
2933
+
2934
+ const getValue = () => {
2935
+ return minDash.get(field, path, '');
2936
+ };
2937
+
2938
+ const setValue = value => {
2939
+ return editField(field, path, value);
2940
+ };
2941
+
2942
+ return NumberFieldEntry({
2943
+ debounce,
2944
+ element: field,
2945
+ getValue,
2946
+ id,
2947
+ label,
2948
+ setValue
1584
2949
  });
1585
2950
  }
1586
2951
 
1587
- function DefaultValueEntry(props) {
2952
+ function DefaultValueSingleSelect(props) {
1588
2953
  const {
1589
2954
  editField,
1590
- field
2955
+ field,
2956
+ id,
2957
+ label
1591
2958
  } = props;
1592
2959
  const {
1593
2960
  defaultValue,
1594
- type,
1595
2961
  values = []
1596
2962
  } = field;
2963
+ const path = ['defaultValue'];
1597
2964
 
1598
- if (type === 'checkbox') {
1599
- const options = [{
1600
- label: 'Checked',
1601
- value: 'true'
1602
- }, {
1603
- label: 'Not checked',
1604
- value: 'false'
1605
- }];
2965
+ const getOptions = () => {
2966
+ return [{
2967
+ label: '<none>'
2968
+ }, ...values];
2969
+ };
1606
2970
 
1607
- const onChange = value => {
1608
- editField(field, ['defaultValue'], parseStringToBoolean(value));
1609
- };
2971
+ const setValue = value => {
2972
+ return editField(field, path, value.length ? value : undefined);
2973
+ };
1610
2974
 
1611
- return jsxRuntime.jsx(SelectEntry, {
1612
- id: "defaultValue",
1613
- label: "Default Value",
1614
- onChange: onChange,
1615
- options: options,
1616
- value: parseBooleanToString(defaultValue)
1617
- });
1618
- }
2975
+ const getValue = () => {
2976
+ return defaultValue;
2977
+ };
1619
2978
 
1620
- if (type === 'number') {
1621
- return jsxRuntime.jsx(NumberInputEntry, {
1622
- editField: editField,
1623
- field: field,
1624
- id: "defaultValue",
1625
- label: "Default Value",
1626
- path: ['defaultValue']
1627
- });
1628
- }
2979
+ return SelectEntry({
2980
+ element: field,
2981
+ getOptions,
2982
+ getValue,
2983
+ id,
2984
+ label,
2985
+ setValue
2986
+ });
2987
+ }
1629
2988
 
1630
- if (type === 'radio' || type === 'select') {
1631
- const options = [{
1632
- label: '<none>'
1633
- }, ...values];
2989
+ function DefaultValueTextfield(props) {
2990
+ const {
2991
+ editField,
2992
+ field,
2993
+ id,
2994
+ label
2995
+ } = props;
2996
+ const debounce = useService('debounce');
2997
+ const path = ['defaultValue'];
1634
2998
 
1635
- const onChange = value => {
1636
- editField(field, ['defaultValue'], value.length ? value : undefined);
1637
- };
2999
+ const getValue = () => {
3000
+ return minDash.get(field, path, '');
3001
+ };
1638
3002
 
1639
- return jsxRuntime.jsx(SelectEntry, {
1640
- id: "defaultValue",
1641
- label: "Default Value",
1642
- onChange: onChange,
1643
- options: options,
1644
- value: defaultValue
1645
- });
1646
- }
3003
+ const setValue = value => {
3004
+ return editField(field, path, value);
3005
+ };
3006
+
3007
+ return TextfieldEntry({
3008
+ debounce,
3009
+ element: field,
3010
+ getValue,
3011
+ id,
3012
+ label,
3013
+ setValue
3014
+ });
3015
+ } // helpers /////////////////
1647
3016
 
1648
- if (type === 'textfield') {
1649
- return jsxRuntime.jsx(TextInputEntry, {
1650
- editField: editField,
1651
- field: field,
1652
- id: "defaultValue",
1653
- label: "Default Value",
1654
- path: ['defaultValue']
1655
- });
1656
- }
1657
- }
1658
3017
 
1659
3018
  function parseStringToBoolean(value) {
1660
3019
  if (value === 'true') {
@@ -1677,17 +3036,46 @@ function DisabledEntry(props) {
1677
3036
  editField,
1678
3037
  field
1679
3038
  } = props;
3039
+ const {
3040
+ type
3041
+ } = field;
3042
+ const entries = [];
3043
+
3044
+ if (INPUTS.includes(type)) {
3045
+ entries.push({
3046
+ id: 'disabled',
3047
+ component: Disabled,
3048
+ editField: editField,
3049
+ field: field,
3050
+ isEdited: isEdited$6
3051
+ });
3052
+ }
3053
+
3054
+ return entries;
3055
+ }
3056
+
3057
+ function Disabled(props) {
3058
+ const {
3059
+ editField,
3060
+ field,
3061
+ id
3062
+ } = props;
3063
+ const path = ['disabled'];
3064
+
3065
+ const getValue = () => {
3066
+ return minDash.get(field, path, '');
3067
+ };
1680
3068
 
1681
- const onChange = value => {
1682
- editField(field, 'disabled', value);
3069
+ const setValue = value => {
3070
+ return editField(field, path, value);
1683
3071
  };
1684
3072
 
1685
- return jsxRuntime.jsx(CheckboxInputEntry, {
1686
- id: "disabled",
1687
- field: field,
1688
- label: "Disabled",
1689
- path: ['disabled'],
1690
- onChange: onChange
3073
+ return CheckboxEntry({
3074
+ element: field,
3075
+ getValue,
3076
+ id,
3077
+ label: 'Disabled',
3078
+ setValue
1691
3079
  });
1692
3080
  }
1693
3081
 
@@ -1696,7 +3084,38 @@ function IdEntry(props) {
1696
3084
  editField,
1697
3085
  field
1698
3086
  } = props;
3087
+ const entries = [];
3088
+
3089
+ if (field.type === 'default') {
3090
+ entries.push({
3091
+ id: 'id',
3092
+ component: Id,
3093
+ editField: editField,
3094
+ field: field,
3095
+ isEdited: isEdited$1
3096
+ });
3097
+ }
3098
+
3099
+ return entries;
3100
+ }
3101
+
3102
+ function Id(props) {
3103
+ const {
3104
+ editField,
3105
+ field,
3106
+ id
3107
+ } = props;
1699
3108
  const formFieldRegistry = useService('formFieldRegistry');
3109
+ const debounce = useService('debounce');
3110
+ const path = ['id'];
3111
+
3112
+ const getValue = () => {
3113
+ return minDash.get(field, path, '');
3114
+ };
3115
+
3116
+ const setValue = value => {
3117
+ return editField(field, path, value);
3118
+ };
1700
3119
 
1701
3120
  const validate = value => {
1702
3121
  if (minDash.isUndefined(value) || !value.length) {
@@ -1712,16 +3131,18 @@ function IdEntry(props) {
1712
3131
  return validateId(value) || null;
1713
3132
  };
1714
3133
 
1715
- return jsxRuntime.jsx(TextInputEntry, {
1716
- editField: editField,
1717
- field: field,
1718
- id: "id",
1719
- label: "Id",
1720
- path: ['id'],
1721
- validate: validate
3134
+ return TextfieldEntry({
3135
+ debounce,
3136
+ element: field,
3137
+ getValue,
3138
+ id,
3139
+ label: 'ID',
3140
+ setValue,
3141
+ validate
1722
3142
  });
1723
3143
  } // id structural validation /////////////
1724
3144
 
3145
+
1725
3146
  const SPACE_REGEX = /\s/; // for QName validation as per http://www.w3.org/TR/REC-xml/#NT-NameChar
1726
3147
 
1727
3148
  const QNAME_REGEX = /^([a-z][\w-.]*:)?[a-z_][\w-.]*$/i; // for ID validation as per BPMN Schema (QName - Namespace)
@@ -1751,7 +3172,41 @@ function KeyEntry(props) {
1751
3172
  editField,
1752
3173
  field
1753
3174
  } = props;
3175
+ const {
3176
+ type
3177
+ } = field;
3178
+ const entries = [];
3179
+
3180
+ if (INPUTS.includes(type)) {
3181
+ entries.push({
3182
+ id: 'key',
3183
+ component: Key$1,
3184
+ editField: editField,
3185
+ field: field,
3186
+ isEdited: isEdited$1
3187
+ });
3188
+ }
3189
+
3190
+ return entries;
3191
+ }
3192
+
3193
+ function Key$1(props) {
3194
+ const {
3195
+ editField,
3196
+ field,
3197
+ id
3198
+ } = props;
1754
3199
  const formFieldRegistry = useService('formFieldRegistry');
3200
+ const debounce = useService('debounce');
3201
+ const path = ['key'];
3202
+
3203
+ const getValue = () => {
3204
+ return minDash.get(field, path, '');
3205
+ };
3206
+
3207
+ const setValue = value => {
3208
+ return editField(field, path, value);
3209
+ };
1755
3210
 
1756
3211
  const validate = value => {
1757
3212
  if (minDash.isUndefined(value) || !value.length) {
@@ -1762,134 +3217,306 @@ function KeyEntry(props) {
1762
3217
  return 'Must not contain spaces.';
1763
3218
  }
1764
3219
 
1765
- const assigned = formFieldRegistry._keys.assigned(value);
3220
+ const assigned = formFieldRegistry._keys.assigned(value);
3221
+
3222
+ if (assigned && assigned !== field) {
3223
+ return 'Must be unique.';
3224
+ }
3225
+
3226
+ return null;
3227
+ };
3228
+
3229
+ return TextfieldEntry({
3230
+ debounce,
3231
+ description: 'Binds to a form variable',
3232
+ element: field,
3233
+ getValue,
3234
+ id,
3235
+ label: 'Key',
3236
+ setValue,
3237
+ validate
3238
+ });
3239
+ }
3240
+
3241
+ function LabelEntry(props) {
3242
+ const {
3243
+ editField,
3244
+ field
3245
+ } = props;
3246
+ const {
3247
+ type
3248
+ } = field;
3249
+ const entries = [];
3250
+
3251
+ if (INPUTS.includes(type) || type === 'button') {
3252
+ entries.push({
3253
+ id: 'label',
3254
+ component: Label$1,
3255
+ editField: editField,
3256
+ field: field,
3257
+ isEdited: isEdited$1
3258
+ });
3259
+ }
3260
+
3261
+ return entries;
3262
+ }
3263
+
3264
+ function Label$1(props) {
3265
+ const {
3266
+ editField,
3267
+ field,
3268
+ id
3269
+ } = props;
3270
+ const debounce = useService('debounce');
3271
+ const path = ['label'];
3272
+
3273
+ const getValue = () => {
3274
+ return minDash.get(field, path, '');
3275
+ };
3276
+
3277
+ const setValue = value => {
3278
+ return editField(field, path, value);
3279
+ };
3280
+
3281
+ return TextfieldEntry({
3282
+ debounce,
3283
+ element: field,
3284
+ getValue,
3285
+ id,
3286
+ label: 'Field label',
3287
+ setValue
3288
+ });
3289
+ }
3290
+
3291
+ function TextEntry(props) {
3292
+ const {
3293
+ editField,
3294
+ field
3295
+ } = props;
3296
+ const {
3297
+ type
3298
+ } = field;
3299
+ const entries = [];
3300
+
3301
+ if (type === 'text') {
3302
+ entries.push({
3303
+ id: 'text',
3304
+ component: Text,
3305
+ editField: editField,
3306
+ field: field,
3307
+ isEdited: isEdited$2
3308
+ });
3309
+ }
3310
+
3311
+ return entries;
3312
+ }
3313
+
3314
+ function Text(props) {
3315
+ const {
3316
+ editField,
3317
+ field,
3318
+ id
3319
+ } = props;
3320
+ const debounce = useService('debounce');
3321
+ const path = ['text'];
3322
+
3323
+ const getValue = () => {
3324
+ return minDash.get(field, path, '');
3325
+ };
3326
+
3327
+ const setValue = value => {
3328
+ return editField(field, path, value);
3329
+ };
3330
+
3331
+ return TextAreaEntry({
3332
+ debounce,
3333
+ description: 'Use Markdown or basic HTML to format.',
3334
+ element: field,
3335
+ getValue,
3336
+ id,
3337
+ label: 'Text',
3338
+ rows: 10,
3339
+ setValue
3340
+ });
3341
+ }
3342
+
3343
+ function ValueEntry(props) {
3344
+ const {
3345
+ editField,
3346
+ field,
3347
+ idPrefix,
3348
+ index,
3349
+ validateFactory
3350
+ } = props;
3351
+ const entries = [{
3352
+ component: Label,
3353
+ editField,
3354
+ field,
3355
+ id: idPrefix + '-label',
3356
+ idPrefix,
3357
+ index,
3358
+ validateFactory
3359
+ }, {
3360
+ component: Value$1,
3361
+ editField,
3362
+ field,
3363
+ id: idPrefix + '-value',
3364
+ idPrefix,
3365
+ index,
3366
+ validateFactory
3367
+ }];
3368
+ return entries;
3369
+ }
3370
+
3371
+ function Label(props) {
3372
+ const {
3373
+ editField,
3374
+ field,
3375
+ id,
3376
+ index,
3377
+ validateFactory
3378
+ } = props;
3379
+ const debounce = useService('debounce');
1766
3380
 
1767
- if (assigned && assigned !== field) {
1768
- return 'Must be unique.';
1769
- }
3381
+ const setValue = value => {
3382
+ const values = minDash.get(field, ['values']);
3383
+ return editField(field, 'values', minDash.set(values, [index, 'label'], value));
3384
+ };
1770
3385
 
1771
- return null;
3386
+ const getValue = () => {
3387
+ return minDash.get(field, ['values', index, 'label']);
1772
3388
  };
1773
3389
 
1774
- return jsxRuntime.jsx(TextInputEntry, {
1775
- editField: editField,
1776
- field: field,
1777
- id: "key",
1778
- label: "Key",
1779
- description: "Maps to a process variable.",
1780
- path: ['key'],
1781
- validate: validate
3390
+ return TextfieldEntry({
3391
+ debounce,
3392
+ element: field,
3393
+ getValue,
3394
+ id,
3395
+ label: 'Label',
3396
+ setValue,
3397
+ validate: validateFactory(getValue())
1782
3398
  });
1783
3399
  }
1784
3400
 
1785
- function LabelEntry(props) {
3401
+ function Value$1(props) {
1786
3402
  const {
1787
3403
  editField,
1788
- field
3404
+ field,
3405
+ id,
3406
+ index,
3407
+ validateFactory
1789
3408
  } = props;
1790
- return jsxRuntime.jsx(TextInputEntry, {
1791
- editField: editField,
1792
- field: field,
1793
- id: "label",
1794
- label: "Field Label",
1795
- path: ['label']
3409
+ const debounce = useService('debounce');
3410
+
3411
+ const setValue = value => {
3412
+ const values = minDash.get(field, ['values']);
3413
+ return editField(field, 'values', minDash.set(values, [index, 'value'], value));
3414
+ };
3415
+
3416
+ const getValue = () => {
3417
+ return minDash.get(field, ['values', index, 'value']);
3418
+ };
3419
+
3420
+ return TextfieldEntry({
3421
+ debounce,
3422
+ element: field,
3423
+ getValue,
3424
+ id,
3425
+ label: 'Value',
3426
+ setValue,
3427
+ validate: validateFactory(getValue())
1796
3428
  });
1797
3429
  }
1798
3430
 
1799
- function TextEntry(props) {
3431
+ function CustomValueEntry(props) {
1800
3432
  const {
1801
3433
  editField,
1802
- field
3434
+ field,
3435
+ idPrefix,
3436
+ index,
3437
+ validateFactory
1803
3438
  } = props;
1804
- return jsxRuntime.jsx(TextareaEntry, {
1805
- editField: editField,
1806
- field: field,
1807
- id: "text",
1808
- label: "Text",
1809
- path: ['text'],
1810
- description: "Use Markdown or basic HTML to format."
1811
- });
3439
+ const entries = [{
3440
+ component: Key,
3441
+ editField,
3442
+ field,
3443
+ id: idPrefix + '-key',
3444
+ idPrefix,
3445
+ index,
3446
+ validateFactory
3447
+ }, {
3448
+ component: Value,
3449
+ editField,
3450
+ field,
3451
+ id: idPrefix + '-value',
3452
+ idPrefix,
3453
+ index,
3454
+ validateFactory
3455
+ }];
3456
+ return entries;
1812
3457
  }
1813
3458
 
1814
- function ValueEntry(props) {
3459
+ function Key(props) {
1815
3460
  const {
1816
3461
  editField,
1817
3462
  field,
3463
+ id,
1818
3464
  index,
1819
- validate
3465
+ validateFactory
1820
3466
  } = props;
3467
+ const debounce = useService('debounce');
1821
3468
 
1822
- const getLabel = () => {
1823
- return minDash.get(field, ['values', index, 'label']);
3469
+ const setValue = value => {
3470
+ const properties = minDash.get(field, ['properties']);
3471
+ const key = Object.keys(properties)[index];
3472
+ return editField(field, 'properties', updateKey(properties, key, value));
1824
3473
  };
1825
3474
 
1826
3475
  const getValue = () => {
1827
- return minDash.get(field, ['values', index, 'value']);
1828
- };
1829
-
1830
- const onChange = key => {
1831
- const values = minDash.get(field, ['values']);
1832
- return value => {
1833
- editField(field, 'values', minDash.set(values, [index, key], value));
1834
- };
3476
+ return Object.keys(minDash.get(field, ['properties']))[index];
1835
3477
  };
1836
3478
 
1837
- return jsxRuntime.jsxs(jsxRuntime.Fragment, {
1838
- children: [jsxRuntime.jsx(TextInputEntry, {
1839
- id: `value-label-${index}`,
1840
- label: "Label",
1841
- onChange: onChange('label'),
1842
- value: getLabel()
1843
- }), jsxRuntime.jsx(TextInputEntry, {
1844
- id: `value-value-${index}`,
1845
- label: "Value",
1846
- onChange: onChange('value'),
1847
- value: getValue(),
1848
- validate: validate(getValue())
1849
- })]
3479
+ return TextfieldEntry({
3480
+ debounce,
3481
+ element: field,
3482
+ getValue,
3483
+ id,
3484
+ label: 'Key',
3485
+ setValue,
3486
+ validate: validateFactory(getValue())
1850
3487
  });
1851
3488
  }
1852
3489
 
1853
- function CustomValueEntry(props) {
3490
+ function Value(props) {
1854
3491
  const {
1855
3492
  editField,
1856
3493
  field,
3494
+ id,
1857
3495
  index,
1858
- validate
3496
+ validateFactory
1859
3497
  } = props;
3498
+ const debounce = useService('debounce');
1860
3499
 
1861
- const getKey = () => {
1862
- return Object.keys(minDash.get(field, ['properties']))[index];
3500
+ const setValue = value => {
3501
+ const properties = minDash.get(field, ['properties']);
3502
+ const key = Object.keys(properties)[index];
3503
+ editField(field, 'properties', updateValue(properties, key, value));
1863
3504
  };
1864
3505
 
1865
3506
  const getValue = () => {
1866
- return minDash.get(field, ['properties', getKey()]);
1867
- };
1868
-
1869
- const onChange = key => {
1870
3507
  const properties = minDash.get(field, ['properties']);
1871
- return value => {
1872
- if (key === 'value') {
1873
- editField(field, 'properties', updateValue(properties, getKey(), value));
1874
- } else if (key === 'key') {
1875
- editField(field, 'properties', updateKey(properties, getKey(), value));
1876
- }
1877
- };
3508
+ const key = Object.keys(properties)[index];
3509
+ return minDash.get(field, ['properties', key]);
1878
3510
  };
1879
3511
 
1880
- return jsxRuntime.jsxs(jsxRuntime.Fragment, {
1881
- children: [jsxRuntime.jsx(TextInputEntry, {
1882
- id: `value-key-${index}`,
1883
- label: "Key",
1884
- onChange: onChange('key'),
1885
- value: getKey(),
1886
- validate: validate(getKey())
1887
- }), jsxRuntime.jsx(TextInputEntry, {
1888
- id: `value-value-${index}`,
1889
- label: "Value",
1890
- onChange: onChange('value'),
1891
- value: getValue()
1892
- })]
3512
+ return TextfieldEntry({
3513
+ debounce,
3514
+ element: field,
3515
+ getValue,
3516
+ id,
3517
+ label: 'Value',
3518
+ setValue,
3519
+ validate: validateFactory(getValue())
1893
3520
  });
1894
3521
  } // helpers //////////
1895
3522
 
@@ -1903,6 +3530,7 @@ function CustomValueEntry(props) {
1903
3530
  * @returns {Object}
1904
3531
  */
1905
3532
 
3533
+
1906
3534
  function updateValue(properties, key, value) {
1907
3535
  return { ...properties,
1908
3536
  [key]: value
@@ -1928,79 +3556,225 @@ function updateKey(properties, oldKey, newKey) {
1928
3556
  }, {});
1929
3557
  }
1930
3558
 
1931
- function GeneralGroup(field, editField) {
3559
+ const VALUES_SOURCES = {
3560
+ STATIC: 'static',
3561
+ INPUT: 'input'
3562
+ };
3563
+ const VALUES_SOURCE_DEFAULT = VALUES_SOURCES.STATIC;
3564
+ const VALUES_SOURCES_LABELS = {
3565
+ [VALUES_SOURCES.STATIC]: 'Static',
3566
+ [VALUES_SOURCES.INPUT]: 'Input data'
3567
+ };
3568
+ const VALUES_SOURCES_PATHS = {
3569
+ [VALUES_SOURCES.STATIC]: ['values'],
3570
+ [VALUES_SOURCES.INPUT]: ['valuesKey']
3571
+ };
3572
+ const VALUES_SOURCES_DEFAULTS = {
3573
+ [VALUES_SOURCES.STATIC]: [],
3574
+ [VALUES_SOURCES.INPUT]: ''
3575
+ }; // helpers ///////////////////
3576
+
3577
+ function getValuesSource(field) {
3578
+ for (const source of Object.values(VALUES_SOURCES)) {
3579
+ if (minDash.get(field, VALUES_SOURCES_PATHS[source]) !== undefined) {
3580
+ return source;
3581
+ }
3582
+ }
3583
+
3584
+ return VALUES_SOURCE_DEFAULT;
3585
+ }
3586
+
3587
+ function ValuesSourceSelectEntry(props) {
1932
3588
  const {
1933
- type
1934
- } = field;
1935
- const entries = [];
3589
+ editField,
3590
+ field,
3591
+ id
3592
+ } = props;
3593
+ return [{
3594
+ id: id + '-select',
3595
+ component: ValuesSourceSelect,
3596
+ isEdited: isEdited$4,
3597
+ editField,
3598
+ field
3599
+ }];
3600
+ }
1936
3601
 
1937
- if (type === 'default') {
1938
- entries.push(jsxRuntime.jsx(IdEntry, {
1939
- editField: editField,
1940
- field: field
1941
- }));
1942
- }
3602
+ function ValuesSourceSelect(props) {
3603
+ const {
3604
+ editField,
3605
+ field,
3606
+ id
3607
+ } = props;
3608
+ const getValue = getValuesSource;
3609
+
3610
+ const setValue = value => {
3611
+ let newField = field;
3612
+ Object.values(VALUES_SOURCES).forEach(source => {
3613
+ // Clear all values source definitions and default the newly selected one
3614
+ const newValue = value === source ? VALUES_SOURCES_DEFAULTS[source] : undefined;
3615
+ newField = editField(field, VALUES_SOURCES_PATHS[source], newValue);
3616
+ });
3617
+ return newField;
3618
+ };
1943
3619
 
1944
- if (INPUTS.includes(type) || type === 'button') {
1945
- entries.push(jsxRuntime.jsx(LabelEntry, {
1946
- editField: editField,
1947
- field: field
3620
+ const getValuesSourceOptions = () => {
3621
+ return Object.values(VALUES_SOURCES).map(valueSource => ({
3622
+ label: VALUES_SOURCES_LABELS[valueSource],
3623
+ value: valueSource
1948
3624
  }));
1949
- }
3625
+ };
1950
3626
 
1951
- if (INPUTS.includes(type)) {
1952
- entries.push(jsxRuntime.jsx(DescriptionEntry, {
1953
- editField: editField,
1954
- field: field
1955
- }));
1956
- }
3627
+ return SelectEntry({
3628
+ label: 'Type',
3629
+ element: field,
3630
+ getOptions: getValuesSourceOptions,
3631
+ getValue,
3632
+ id,
3633
+ setValue
3634
+ });
3635
+ }
1957
3636
 
1958
- if (INPUTS.includes(type)) {
1959
- entries.push(jsxRuntime.jsx(KeyEntry, {
1960
- editField: editField,
1961
- field: field
1962
- }));
1963
- }
3637
+ function InputKeyValuesSourceEntry(props) {
3638
+ const {
3639
+ editField,
3640
+ field,
3641
+ id
3642
+ } = props;
3643
+ return [{
3644
+ id: id + '-key',
3645
+ component: InputValuesKey,
3646
+ label: 'Input values key',
3647
+ description: 'Define which input property to populate the values from',
3648
+ isEdited: isEdited$1,
3649
+ editField,
3650
+ field
3651
+ }];
3652
+ }
1964
3653
 
1965
- if (INPUTS.includes(type)) {
1966
- entries.push(jsxRuntime.jsx(DefaultValueEntry, {
1967
- editField: editField,
1968
- field: field
1969
- }));
1970
- }
3654
+ function InputValuesKey(props) {
3655
+ const {
3656
+ editField,
3657
+ field,
3658
+ id,
3659
+ label,
3660
+ description
3661
+ } = props;
3662
+ const debounce = useService('debounce');
3663
+ const path = VALUES_SOURCES_PATHS[VALUES_SOURCES.INPUT];
1971
3664
 
1972
- if (type === 'button') {
1973
- entries.push(jsxRuntime.jsx(ActionEntry, {
1974
- editField: editField,
1975
- field: field
1976
- }));
1977
- }
3665
+ const getValue = () => minDash.get(field, path, '');
1978
3666
 
1979
- if (type === 'columns') {
1980
- entries.push(jsxRuntime.jsx(ColumnsEntry, {
1981
- editField: editField,
1982
- field: field
1983
- }));
1984
- }
3667
+ const setValue = value => editField(field, path, value || '');
1985
3668
 
1986
- if (type === 'text') {
1987
- entries.push(jsxRuntime.jsx(TextEntry, {
1988
- editField: editField,
1989
- field: field
1990
- }));
1991
- }
3669
+ return TextfieldEntry({
3670
+ debounce,
3671
+ description,
3672
+ element: field,
3673
+ getValue,
3674
+ id,
3675
+ label,
3676
+ setValue
3677
+ });
3678
+ }
1992
3679
 
1993
- if (INPUTS.includes(type)) {
1994
- entries.push(jsxRuntime.jsx(DisabledEntry, {
1995
- editField: editField,
1996
- field: field
1997
- }));
1998
- }
3680
+ function StaticValuesSourceEntry(props) {
3681
+ const {
3682
+ editField,
3683
+ field,
3684
+ id: idPrefix
3685
+ } = props;
3686
+ const {
3687
+ values
3688
+ } = field;
3689
+
3690
+ const addEntry = e => {
3691
+ e.stopPropagation();
3692
+ const index = values.length + 1;
3693
+ const entry = {
3694
+ label: `Value ${index}`,
3695
+ value: `value${index}`
3696
+ };
3697
+ editField(field, VALUES_SOURCES_PATHS[VALUES_SOURCES.STATIC], arrayAdd$1(values, values.length, entry));
3698
+ };
3699
+
3700
+ const removeEntry = entry => {
3701
+ editField(field, VALUES_SOURCES_PATHS[VALUES_SOURCES.STATIC], minDash.without(values, entry));
3702
+ };
3703
+
3704
+ const validateFactory = key => {
3705
+ return value => {
3706
+ if (value === key) {
3707
+ return;
3708
+ }
1999
3709
 
2000
- return jsxRuntime.jsx(Group, {
2001
- label: "General",
2002
- children: entries.length ? entries : null
3710
+ if (minDash.isUndefined(value) || !value.length) {
3711
+ return 'Must not be empty.';
3712
+ }
3713
+
3714
+ const isValueAssigned = values.find(entry => entry.value === value);
3715
+
3716
+ if (isValueAssigned) {
3717
+ return 'Must be unique.';
3718
+ }
3719
+ };
3720
+ };
3721
+
3722
+ const items = values.map((entry, index) => {
3723
+ const id = idPrefix + '-' + index;
3724
+ return {
3725
+ id,
3726
+ label: entry.label,
3727
+ entries: ValueEntry({
3728
+ editField,
3729
+ field,
3730
+ idPrefix: id,
3731
+ index,
3732
+ validateFactory
3733
+ }),
3734
+ autoFocusEntry: id + '-label',
3735
+ remove: () => removeEntry(entry)
3736
+ };
2003
3737
  });
3738
+ return {
3739
+ items,
3740
+ add: addEntry
3741
+ };
3742
+ }
3743
+
3744
+ function GeneralGroup(field, editField) {
3745
+ const entries = [...IdEntry({
3746
+ field,
3747
+ editField
3748
+ }), ...LabelEntry({
3749
+ field,
3750
+ editField
3751
+ }), ...DescriptionEntry({
3752
+ field,
3753
+ editField
3754
+ }), ...KeyEntry({
3755
+ field,
3756
+ editField
3757
+ }), ...DefaultOptionEntry({
3758
+ field,
3759
+ editField
3760
+ }), ...ActionEntry({
3761
+ field,
3762
+ editField
3763
+ }), ...ColumnsEntry({
3764
+ field,
3765
+ editField
3766
+ }), ...TextEntry({
3767
+ field,
3768
+ editField
3769
+ }), ...DisabledEntry({
3770
+ field,
3771
+ editField
3772
+ })];
3773
+ return {
3774
+ id: 'general',
3775
+ label: 'General',
3776
+ entries
3777
+ };
2004
3778
  }
2005
3779
 
2006
3780
  function ValidationGroup(field, editField) {
@@ -2008,6 +3782,10 @@ function ValidationGroup(field, editField) {
2008
3782
  type
2009
3783
  } = field;
2010
3784
 
3785
+ if (!(INPUTS.includes(type) && type !== 'checkbox' && type !== 'checklist' && type !== 'taglist')) {
3786
+ return null;
3787
+ }
3788
+
2011
3789
  const onChange = key => {
2012
3790
  return value => {
2013
3791
  const validate = minDash.get(field, ['validate'], {});
@@ -2015,122 +3793,247 @@ function ValidationGroup(field, editField) {
2015
3793
  };
2016
3794
  };
2017
3795
 
2018
- const entries = [jsxRuntime.jsx(CheckboxInputEntry, {
2019
- id: "required",
2020
- label: "Required",
2021
- onChange: onChange('required'),
2022
- value: minDash.get(field, ['validate', 'required'])
2023
- })];
3796
+ const getValue = key => {
3797
+ return () => {
3798
+ return minDash.get(field, ['validate', key]);
3799
+ };
3800
+ };
3801
+
3802
+ let entries = [{
3803
+ id: 'required',
3804
+ component: Required,
3805
+ getValue,
3806
+ field,
3807
+ isEdited: isEdited$6,
3808
+ onChange
3809
+ }];
2024
3810
 
2025
3811
  if (type === 'textfield') {
2026
- entries.push(jsxRuntime.jsx(NumberInputEntry, {
2027
- id: "minLength",
2028
- label: "Minimum Length",
2029
- min: "0",
2030
- onChange: onChange('minLength'),
2031
- value: minDash.get(field, ['validate', 'minLength'])
2032
- }), jsxRuntime.jsx(NumberInputEntry, {
2033
- id: "maxLength",
2034
- label: "Maximum Length",
2035
- min: "0",
2036
- onChange: onChange('maxLength'),
2037
- value: minDash.get(field, ['validate', 'maxLength'])
2038
- }), jsxRuntime.jsx(TextInputEntry, {
2039
- id: "regularExpressionPattern",
2040
- label: "Regular Expression Pattern",
2041
- onChange: onChange('regularExpressionPattern'),
2042
- value: minDash.get(field, ['validate', 'regularExpressionPattern'])
2043
- }));
3812
+ entries.push({
3813
+ id: 'minLength',
3814
+ component: MinLength,
3815
+ getValue,
3816
+ field,
3817
+ isEdited: isEdited$5,
3818
+ onChange
3819
+ }, {
3820
+ id: 'maxLength',
3821
+ component: MaxLength,
3822
+ getValue,
3823
+ field,
3824
+ isEdited: isEdited$5,
3825
+ onChange
3826
+ }, {
3827
+ id: 'pattern',
3828
+ component: Pattern,
3829
+ getValue,
3830
+ field,
3831
+ isEdited: isEdited$1,
3832
+ onChange
3833
+ });
2044
3834
  }
2045
3835
 
2046
3836
  if (type === 'number') {
2047
- entries.push(jsxRuntime.jsx(NumberInputEntry, {
2048
- id: "min",
2049
- label: "Minimum",
2050
- onChange: onChange('min'),
2051
- value: minDash.get(field, ['validate', 'min'])
2052
- }), jsxRuntime.jsx(NumberInputEntry, {
2053
- id: "max",
2054
- label: "Maximum",
2055
- onChange: onChange('max'),
2056
- value: minDash.get(field, ['validate', 'max'])
2057
- }));
3837
+ entries.push({
3838
+ id: 'min',
3839
+ component: Min,
3840
+ getValue,
3841
+ field,
3842
+ isEdited: isEdited$5,
3843
+ onChange
3844
+ }, {
3845
+ id: 'max',
3846
+ component: Max,
3847
+ getValue,
3848
+ field,
3849
+ isEdited: isEdited$5,
3850
+ onChange
3851
+ });
2058
3852
  }
2059
3853
 
2060
- return jsxRuntime.jsx(Group, {
2061
- label: "Validation",
2062
- children: entries.length ? entries : null
3854
+ return {
3855
+ id: 'validation',
3856
+ label: 'Validation',
3857
+ entries
3858
+ };
3859
+ }
3860
+
3861
+ function Required(props) {
3862
+ const {
3863
+ field,
3864
+ getValue,
3865
+ id,
3866
+ onChange
3867
+ } = props;
3868
+ return CheckboxEntry({
3869
+ element: field,
3870
+ getValue: getValue('required'),
3871
+ id,
3872
+ label: 'Required',
3873
+ setValue: onChange('required')
3874
+ });
3875
+ }
3876
+
3877
+ function MinLength(props) {
3878
+ const {
3879
+ field,
3880
+ getValue,
3881
+ id,
3882
+ onChange
3883
+ } = props;
3884
+ const debounce = useService('debounce');
3885
+ return NumberFieldEntry({
3886
+ debounce,
3887
+ element: field,
3888
+ getValue: getValue('minLength'),
3889
+ id,
3890
+ label: 'Minimum length',
3891
+ min: 0,
3892
+ setValue: onChange('minLength')
3893
+ });
3894
+ }
3895
+
3896
+ function MaxLength(props) {
3897
+ const {
3898
+ field,
3899
+ getValue,
3900
+ id,
3901
+ onChange
3902
+ } = props;
3903
+ const debounce = useService('debounce');
3904
+ return NumberFieldEntry({
3905
+ debounce,
3906
+ element: field,
3907
+ getValue: getValue('maxLength'),
3908
+ id,
3909
+ label: 'Maximum length',
3910
+ min: 0,
3911
+ setValue: onChange('maxLength')
2063
3912
  });
2064
3913
  }
2065
3914
 
2066
- function ValuesGroup(field, editField) {
3915
+ function Pattern(props) {
2067
3916
  const {
3917
+ field,
3918
+ getValue,
2068
3919
  id,
2069
- values = []
2070
- } = field;
3920
+ onChange
3921
+ } = props;
3922
+ const debounce = useService('debounce');
3923
+ return TextfieldEntry({
3924
+ debounce,
3925
+ element: field,
3926
+ getValue: getValue('pattern'),
3927
+ id,
3928
+ label: 'Regular expression pattern',
3929
+ setValue: onChange('pattern')
3930
+ });
3931
+ }
2071
3932
 
2072
- const addEntry = () => {
2073
- const index = values.length + 1;
2074
- const entry = {
2075
- label: `Value ${index}`,
2076
- value: `value${index}`
2077
- };
2078
- editField(field, ['values'], arrayAdd$1(values, values.length, entry));
2079
- };
3933
+ function Min(props) {
3934
+ const {
3935
+ field,
3936
+ getValue,
3937
+ id,
3938
+ onChange
3939
+ } = props;
3940
+ const debounce = useService('debounce');
3941
+ return NumberFieldEntry({
3942
+ debounce,
3943
+ element: field,
3944
+ getValue: getValue('min'),
3945
+ id,
3946
+ label: 'Minimum',
3947
+ min: 0,
3948
+ setValue: onChange('min')
3949
+ });
3950
+ }
2080
3951
 
2081
- const validateFactory = key => {
2082
- return value => {
2083
- if (value === key) {
2084
- return;
2085
- }
3952
+ function Max(props) {
3953
+ const {
3954
+ field,
3955
+ getValue,
3956
+ id,
3957
+ onChange
3958
+ } = props;
3959
+ const debounce = useService('debounce');
3960
+ return NumberFieldEntry({
3961
+ debounce,
3962
+ element: field,
3963
+ getValue: getValue('max'),
3964
+ id,
3965
+ label: 'Maximum',
3966
+ min: 0,
3967
+ setValue: onChange('max')
3968
+ });
3969
+ }
2086
3970
 
2087
- if (minDash.isUndefined(value) || !value.length) {
2088
- return 'Must not be empty.';
2089
- }
3971
+ function ValuesGroups(field, editField) {
3972
+ const {
3973
+ type,
3974
+ id: fieldId
3975
+ } = field;
2090
3976
 
2091
- const isValueAssigned = values.find(entry => entry.value === value);
3977
+ if (!VALUES_INPUTS.includes(type)) {
3978
+ return [];
3979
+ }
2092
3980
 
2093
- if (isValueAssigned) {
2094
- return 'Must be unique.';
2095
- }
2096
- };
3981
+ const context = {
3982
+ editField,
3983
+ field
2097
3984
  };
3985
+ const valuesSourceId = `${fieldId}-valuesSource`;
3986
+ /**
3987
+ * @type {Array<Group|ListGroup>}
3988
+ */
2098
3989
 
2099
- const hasEntries = values.length > 0;
2100
- return jsxRuntime.jsx(Group, {
2101
- label: "Values",
2102
- addEntry: addEntry,
2103
- hasEntries: hasEntries,
2104
- children: values.map((value, index) => {
2105
- const {
2106
- label
2107
- } = value;
2108
-
2109
- const removeEntry = () => {
2110
- editField(field, ['values'], arrayRemove$1(values, index));
2111
- };
2112
-
2113
- return jsxRuntime.jsx(CollapsibleEntry, {
2114
- label: label,
2115
- removeEntry: removeEntry,
2116
- children: jsxRuntime.jsx(ValueEntry, {
2117
- editField: editField,
2118
- field: field,
2119
- index: index,
2120
- validate: validateFactory
2121
- })
2122
- }, `${id}-${index}`);
3990
+ const groups = [{
3991
+ id: valuesSourceId,
3992
+ label: 'Options source',
3993
+ component: Group,
3994
+ entries: ValuesSourceSelectEntry({ ...context,
3995
+ id: valuesSourceId
2123
3996
  })
2124
- });
3997
+ }];
3998
+ const valuesSource = getValuesSource(field);
3999
+
4000
+ if (valuesSource === VALUES_SOURCES.INPUT) {
4001
+ const dynamicValuesId = `${fieldId}-dynamicValues`;
4002
+ groups.push({
4003
+ id: dynamicValuesId,
4004
+ label: 'Dynamic options',
4005
+ component: Group,
4006
+ entries: InputKeyValuesSourceEntry({ ...context,
4007
+ id: dynamicValuesId
4008
+ })
4009
+ });
4010
+ } else if (valuesSource === VALUES_SOURCES.STATIC) {
4011
+ const staticValuesId = `${fieldId}-staticValues`;
4012
+ groups.push({
4013
+ id: staticValuesId,
4014
+ label: 'Static options',
4015
+ component: ListGroup,
4016
+ ...StaticValuesSourceEntry({ ...context,
4017
+ id: staticValuesId
4018
+ })
4019
+ });
4020
+ }
4021
+
4022
+ return groups;
2125
4023
  }
2126
4024
 
2127
4025
  function CustomValuesGroup(field, editField) {
2128
4026
  const {
2129
- id,
2130
- properties = {}
4027
+ properties = {},
4028
+ type
2131
4029
  } = field;
2132
4030
 
2133
- const addEntry = () => {
4031
+ if (type === 'default') {
4032
+ return null;
4033
+ }
4034
+
4035
+ const addEntry = event => {
4036
+ event.stopPropagation();
2134
4037
  const index = Object.keys(properties).length + 1;
2135
4038
  const key = `key${index}`,
2136
4039
  value = 'value';
@@ -2155,28 +4058,35 @@ function CustomValuesGroup(field, editField) {
2155
4058
  };
2156
4059
  };
2157
4060
 
2158
- const hasEntries = Object.keys(properties).length > 0;
2159
- return jsxRuntime.jsx(Group, {
2160
- label: "Custom Properties",
2161
- addEntry: addEntry,
2162
- hasEntries: hasEntries,
2163
- children: Object.keys(properties).map((key, index) => {
2164
- const removeEntry = () => {
2165
- editField(field, ['properties'], removeKey(properties, key));
2166
- };
4061
+ const items = Object.keys(properties).map((key, index) => {
4062
+ const removeEntry = event => {
4063
+ event.stopPropagation();
4064
+ return editField(field, ['properties'], removeKey(properties, key));
4065
+ };
2167
4066
 
2168
- return jsxRuntime.jsx(CollapsibleEntry, {
2169
- label: key,
2170
- removeEntry: removeEntry,
2171
- children: jsxRuntime.jsx(CustomValueEntry, {
2172
- editField: editField,
2173
- field: field,
2174
- index: index,
2175
- validate: validateFactory
2176
- })
2177
- }, `${id}-${index}`);
2178
- })
4067
+ const id = `${field.id}-property-${index}`;
4068
+ return {
4069
+ autoFocusEntry: id + '-key',
4070
+ entries: CustomValueEntry({
4071
+ editField,
4072
+ field,
4073
+ idPrefix: id,
4074
+ index,
4075
+ validateFactory
4076
+ }),
4077
+ id,
4078
+ label: key || '',
4079
+ remove: removeEntry
4080
+ };
2179
4081
  });
4082
+ return {
4083
+ add: addEntry,
4084
+ component: ListGroup,
4085
+ id: 'custom-values',
4086
+ items,
4087
+ label: 'Custom properties',
4088
+ shouldSort: false
4089
+ };
2180
4090
  } // helpers //////////
2181
4091
 
2182
4092
  /**
@@ -2202,95 +4112,54 @@ function removeKey(properties, oldKey) {
2202
4112
  }, {});
2203
4113
  }
2204
4114
 
2205
- const labelsByType = {
2206
- button: 'BUTTON',
2207
- checkbox: 'CHECKBOX',
2208
- columns: 'COLUMNS',
2209
- default: 'FORM',
2210
- number: 'NUMBER',
2211
- radio: 'RADIO',
2212
- select: 'SELECT',
2213
- text: 'TEXT',
2214
- textfield: 'TEXT FIELD'
2215
- };
2216
-
2217
4115
  function getGroups(field, editField) {
2218
- const {
2219
- type
2220
- } = field;
2221
- const groups = [GeneralGroup(field, editField)];
2222
-
2223
- if (type === 'radio' || type === 'select') {
2224
- groups.push(ValuesGroup(field, editField));
2225
- }
2226
-
2227
- if (INPUTS.includes(type) && type !== 'checkbox') {
2228
- groups.push(ValidationGroup(field, editField));
4116
+ if (!field) {
4117
+ return [];
2229
4118
  }
2230
4119
 
2231
- if (type !== 'default') {
2232
- groups.push(CustomValuesGroup(field, editField));
2233
- }
4120
+ const groups = [GeneralGroup(field, editField), ...ValuesGroups(field, editField), ValidationGroup(field, editField), CustomValuesGroup(field, editField)]; // contract: if a group returns null, it should not be displayed at all
2234
4121
 
2235
- return groups;
4122
+ return groups.filter(group => group !== null);
2236
4123
  }
2237
4124
 
2238
- function PropertiesPanel(props) {
4125
+ function FormPropertiesPanel(props) {
2239
4126
  const {
2240
4127
  editField,
2241
4128
  field
2242
4129
  } = props;
2243
4130
  const eventBus = useService('eventBus');
2244
4131
 
2245
- if (!field) {
2246
- return jsxRuntime.jsx("div", {
2247
- class: "fjs-properties-panel-placeholder",
2248
- children: "Select a form field to edit its properties."
2249
- });
2250
- }
2251
-
2252
4132
  const onFocus = () => eventBus.fire('propertiesPanel.focusin');
2253
4133
 
2254
4134
  const onBlur = () => eventBus.fire('propertiesPanel.focusout');
2255
4135
 
2256
- const {
2257
- type
2258
- } = field;
2259
- const Icon = iconsByType[type];
2260
- const label = labelsByType[type];
2261
- return jsxRuntime.jsxs("div", {
4136
+ return jsxRuntime.jsx("div", {
2262
4137
  class: "fjs-properties-panel",
2263
- "data-field": field.id,
4138
+ "data-field": field && field.id,
2264
4139
  onFocusCapture: onFocus,
2265
4140
  onBlurCapture: onBlur,
2266
- children: [jsxRuntime.jsxs("div", {
2267
- class: "fjs-properties-panel-header",
2268
- children: [jsxRuntime.jsx("div", {
2269
- class: "fjs-properties-panel-header-icon",
2270
- children: jsxRuntime.jsx(Icon, {
2271
- width: "36",
2272
- height: "36",
2273
- viewBox: "0 0 54 54"
2274
- })
2275
- }), jsxRuntime.jsxs("div", {
2276
- children: [jsxRuntime.jsx("span", {
2277
- class: "fjs-properties-panel-header-type",
2278
- children: label
2279
- }), type === 'text' ? jsxRuntime.jsx("div", {
2280
- class: "fjs-properties-panel-header-label",
2281
- children: textToLabel(field.text)
2282
- }) : type === 'default' ? jsxRuntime.jsx("div", {
2283
- class: "fjs-properties-panel-header-label",
2284
- children: field.id
2285
- }) : jsxRuntime.jsx("div", {
2286
- class: "fjs-properties-panel-header-label",
2287
- children: field.label
2288
- })]
2289
- })]
2290
- }), getGroups(field, editField)]
4141
+ children: jsxRuntime.jsx(PropertiesPanel, {
4142
+ element: field,
4143
+ eventBus: eventBus,
4144
+ groups: getGroups(field, editField),
4145
+ headerProvider: PropertiesPanelHeaderProvider,
4146
+ placeholderProvider: PropertiesPanelPlaceholderProvider
4147
+ })
2291
4148
  });
2292
4149
  }
2293
4150
 
4151
+ function _extends() { _extends = Object.assign || 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); }
4152
+ var ListDeleteIcon = (({
4153
+ styles = {},
4154
+ ...props
4155
+ }) => /*#__PURE__*/React__default['default'].createElement("svg", _extends({
4156
+ xmlns: "http://www.w3.org/2000/svg",
4157
+ width: "11",
4158
+ height: "14"
4159
+ }, props), /*#__PURE__*/React__default['default'].createElement("path", {
4160
+ d: "M10 4v8c0 1.1-.9 2-2 2H3c-1.1 0-2-.9-2-2V4h9zM8 6H3v4.8c0 .66.5 1.2 1.111 1.2H6.89C7.5 12 8 11.46 8 10.8V6zm3-5H8.5l-1-1h-4l-1 1H0v1.5h11V1z"
4161
+ })));
4162
+
2294
4163
  function ContextPad(props) {
2295
4164
  if (!props.children) {
2296
4165
  return null;
@@ -2405,12 +4274,15 @@ function FormEditor$1(props) {
2405
4274
  formFieldRegistry = useService('formFieldRegistry'),
2406
4275
  injector = useService('injector'),
2407
4276
  modeling = useService('modeling'),
2408
- selection = useService('selection');
4277
+ selection = useService('selection'),
4278
+ palette = useService('palette'),
4279
+ paletteConfig = useService('config.palette');
2409
4280
 
2410
4281
  const {
2411
4282
  schema
2412
4283
  } = formEditor._getState();
2413
4284
 
4285
+ const paletteRef = hooks$1.useRef(null);
2414
4286
  const [selectedFormField, setSelection] = hooks$1.useState(schema);
2415
4287
  hooks$1.useEffect(() => {
2416
4288
  function handleSelectionChanged(event) {
@@ -2494,6 +4366,10 @@ function FormEditor$1(props) {
2494
4366
  eventBus.off('attach', onAttach);
2495
4367
  eventBus.off('detach', onDetach);
2496
4368
  };
4369
+ }, []); // fire event after first render to notify interested parties
4370
+
4371
+ hooks$1.useEffect(() => {
4372
+ eventBus.fire('formEditor.rendered');
2497
4373
  }, []);
2498
4374
  const formRenderContext = {
2499
4375
  Children,
@@ -2528,14 +4404,21 @@ function FormEditor$1(props) {
2528
4404
  };
2529
4405
  const onSubmit = hooks$1.useCallback(() => {}, []);
2530
4406
  const onReset = hooks$1.useCallback(() => {}, []);
2531
- const editField = hooks$1.useCallback((formField, key, value) => modeling.editFormField(formField, key, value), [modeling]);
4407
+ const editField = hooks$1.useCallback((formField, key, value) => modeling.editFormField(formField, key, value), [modeling]); // attach default palette
4408
+
4409
+ const hasDefaultPalette = defaultPalette(paletteConfig);
4410
+ hooks$1.useEffect(() => {
4411
+ if (hasDefaultPalette) {
4412
+ palette.attachTo(paletteRef.current);
4413
+ }
4414
+ }, [palette, paletteRef, hasDefaultPalette]);
2532
4415
  return jsxRuntime.jsxs("div", {
2533
4416
  class: "fjs-form-editor",
2534
4417
  children: [jsxRuntime.jsxs(DragAndDropContext.Provider, {
2535
4418
  value: dragAndDropContext,
2536
- children: [jsxRuntime.jsx("div", {
2537
- class: "fjs-palette-container",
2538
- children: jsxRuntime.jsx(Palette, {})
4419
+ children: [hasDefaultPalette && jsxRuntime.jsx("div", {
4420
+ class: "fjs-editor-palette-container",
4421
+ ref: paletteRef
2539
4422
  }), jsxRuntime.jsx("div", {
2540
4423
  class: "fjs-form-container",
2541
4424
  children: jsxRuntime.jsx(formJsViewer.FormContext.Provider, {
@@ -2551,7 +4434,7 @@ function FormEditor$1(props) {
2551
4434
  }), jsxRuntime.jsx(CreatePreview, {})]
2552
4435
  }), jsxRuntime.jsx("div", {
2553
4436
  class: "fjs-properties-container",
2554
- children: jsxRuntime.jsx(PropertiesPanel, {
4437
+ children: jsxRuntime.jsx(FormPropertiesPanel, {
2555
4438
  field: selectedFormField,
2556
4439
  editField: editField
2557
4440
  })
@@ -2596,6 +4479,11 @@ function CreatePreview(props) {
2596
4479
  return () => drake.off('cloned', handleCloned);
2597
4480
  }, [drake]);
2598
4481
  return null;
4482
+ } // helper //////
4483
+
4484
+
4485
+ function defaultPalette(paletteConfig) {
4486
+ return !(paletteConfig && paletteConfig.parent);
2599
4487
  }
2600
4488
 
2601
4489
  class Renderer {
@@ -4652,6 +6540,145 @@ var SelectionModule = {
4652
6540
  selectionBehavior: ['type', SelectionBehavior]
4653
6541
  };
4654
6542
 
6543
+ const types = [{
6544
+ label: 'Text Field',
6545
+ type: 'textfield'
6546
+ }, {
6547
+ label: 'Number',
6548
+ type: 'number'
6549
+ }, {
6550
+ label: 'Checkbox',
6551
+ type: 'checkbox'
6552
+ }, {
6553
+ label: 'Checklist',
6554
+ type: 'checklist'
6555
+ }, {
6556
+ label: 'Taglist',
6557
+ type: 'taglist'
6558
+ }, {
6559
+ label: 'Radio',
6560
+ type: 'radio'
6561
+ }, {
6562
+ label: 'Select',
6563
+ type: 'select'
6564
+ }, {
6565
+ label: 'Text',
6566
+ type: 'text'
6567
+ }, {
6568
+ label: 'Button',
6569
+ type: 'button'
6570
+ }];
6571
+ function Palette(props) {
6572
+ return jsxRuntime.jsxs("div", {
6573
+ class: "fjs-palette",
6574
+ children: [jsxRuntime.jsxs("div", {
6575
+ class: "fjs-palette-header",
6576
+ title: "Form elements library",
6577
+ children: [jsxRuntime.jsx("span", {
6578
+ class: "fjs-hide-compact",
6579
+ children: "FORM ELEMENTS "
6580
+ }), "LIBRARY"]
6581
+ }), jsxRuntime.jsx("div", {
6582
+ class: "fjs-palette-fields fjs-drag-container fjs-no-drop",
6583
+ children: types.map(({
6584
+ label,
6585
+ type
6586
+ }) => {
6587
+ const Icon = iconsByType[type];
6588
+ return jsxRuntime.jsxs("div", {
6589
+ class: "fjs-palette-field fjs-drag-copy fjs-no-drop",
6590
+ "data-field-type": type,
6591
+ title: `Create a ${label} element`,
6592
+ children: [Icon ? jsxRuntime.jsx(Icon, {
6593
+ class: "fjs-palette-field-icon",
6594
+ width: "36",
6595
+ height: "36",
6596
+ viewBox: "0 0 54 54"
6597
+ }) : null, jsxRuntime.jsx("span", {
6598
+ class: "fjs-palette-field-text fjs-hide-compact",
6599
+ children: label
6600
+ })]
6601
+ });
6602
+ })
6603
+ })]
6604
+ });
6605
+ }
6606
+
6607
+ class PaletteRenderer {
6608
+ constructor(paletteConfig, eventBus) {
6609
+ const {
6610
+ parent
6611
+ } = paletteConfig || {};
6612
+ this._eventBus = eventBus;
6613
+ this._container = minDom.domify('<div class="fjs-palette-container"></div>');
6614
+
6615
+ if (parent) {
6616
+ this.attachTo(parent);
6617
+ }
6618
+
6619
+ this._eventBus.once('formEditor.rendered', 500, () => {
6620
+ this._render();
6621
+ });
6622
+ }
6623
+ /**
6624
+ * Attach the palette to a parent node.
6625
+ *
6626
+ * @param {HTMLElement} container
6627
+ */
6628
+
6629
+
6630
+ attachTo(container) {
6631
+ if (!container) {
6632
+ throw new Error('container required');
6633
+ }
6634
+
6635
+ if (typeof container === 'string') {
6636
+ container = minDom.query(container);
6637
+ } // (1) detach from old parent
6638
+
6639
+
6640
+ this.detach(); // (2) append to parent container
6641
+
6642
+ container.appendChild(this._container); // (3) notify interested parties
6643
+
6644
+ this._eventBus.fire('palette.attach');
6645
+ }
6646
+ /**
6647
+ * Detach the palette from its parent node.
6648
+ */
6649
+
6650
+
6651
+ detach() {
6652
+ const parentNode = this._container.parentNode;
6653
+
6654
+ if (parentNode) {
6655
+ parentNode.removeChild(this._container);
6656
+
6657
+ this._eventBus.fire('palette.detach');
6658
+ }
6659
+ }
6660
+
6661
+ _render() {
6662
+ preact.render(jsxRuntime.jsx(Palette, {}), this._container);
6663
+
6664
+ this._eventBus.fire('palette.rendered');
6665
+ }
6666
+
6667
+ _destroy() {
6668
+ if (this._container) {
6669
+ preact.render(null, this._container);
6670
+
6671
+ this._eventBus.fire('palette.destroyed');
6672
+ }
6673
+ }
6674
+
6675
+ }
6676
+ PaletteRenderer.$inject = ['config.palette', 'eventBus'];
6677
+
6678
+ var PaletteModule = {
6679
+ palette: ['type', PaletteRenderer]
6680
+ };
6681
+
4655
6682
  const ids = new Ids__default['default']([32, 36, 1]);
4656
6683
  /**
4657
6684
  * @typedef { import('./types').Injector } Injector
@@ -4933,7 +6960,7 @@ class FormEditor {
4933
6960
 
4934
6961
 
4935
6962
  _getModules() {
4936
- return [ModelingModule, EditorActionsModule, KeyboardModule, SelectionModule];
6963
+ return [ModelingModule, EditorActionsModule, KeyboardModule, SelectionModule, PaletteModule];
4937
6964
  }
4938
6965
  /**
4939
6966
  * @internal