@bpmn-io/properties-panel 3.2.1 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/properties-panel.css +242 -1
- package/dist/index.esm.js +1832 -1321
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +1839 -1307
- package/dist/index.js.map +1 -1
- package/package.json +5 -3
package/dist/index.js
CHANGED
|
@@ -11,11 +11,32 @@ var classnames = require('classnames');
|
|
|
11
11
|
var minDom = require('min-dom');
|
|
12
12
|
var feelers = require('feelers');
|
|
13
13
|
var FeelEditor = require('@bpmn-io/feel-editor');
|
|
14
|
+
var view = require('@codemirror/view');
|
|
15
|
+
var focusTrap = require('focus-trap');
|
|
14
16
|
|
|
15
17
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
16
18
|
|
|
19
|
+
function _interopNamespace(e) {
|
|
20
|
+
if (e && e.__esModule) return e;
|
|
21
|
+
var n = Object.create(null);
|
|
22
|
+
if (e) {
|
|
23
|
+
Object.keys(e).forEach(function (k) {
|
|
24
|
+
if (k !== 'default') {
|
|
25
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
26
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
27
|
+
enumerable: true,
|
|
28
|
+
get: function () { return e[k]; }
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
n["default"] = e;
|
|
34
|
+
return Object.freeze(n);
|
|
35
|
+
}
|
|
36
|
+
|
|
17
37
|
var classnames__default = /*#__PURE__*/_interopDefaultLegacy(classnames);
|
|
18
38
|
var FeelEditor__default = /*#__PURE__*/_interopDefaultLegacy(FeelEditor);
|
|
39
|
+
var focusTrap__namespace = /*#__PURE__*/_interopNamespace(focusTrap);
|
|
19
40
|
|
|
20
41
|
var ArrowIcon = function ArrowIcon(props) {
|
|
21
42
|
return jsxRuntime.jsx("svg", {
|
|
@@ -59,6 +80,33 @@ DeleteIcon.defaultProps = {
|
|
|
59
80
|
width: "16",
|
|
60
81
|
height: "16"
|
|
61
82
|
};
|
|
83
|
+
var DragIcon = function DragIcon(props) {
|
|
84
|
+
return jsxRuntime.jsxs("svg", {
|
|
85
|
+
...props,
|
|
86
|
+
children: [jsxRuntime.jsx("path", {
|
|
87
|
+
fill: "#fff",
|
|
88
|
+
style: {
|
|
89
|
+
mixBlendMode: "multiply"
|
|
90
|
+
},
|
|
91
|
+
d: "M0 0h16v16H0z"
|
|
92
|
+
}), jsxRuntime.jsx("path", {
|
|
93
|
+
fill: "#fff",
|
|
94
|
+
style: {
|
|
95
|
+
mixBlendMode: "multiply"
|
|
96
|
+
},
|
|
97
|
+
d: "M0 0h16v16H0z"
|
|
98
|
+
}), jsxRuntime.jsx("path", {
|
|
99
|
+
d: "M7 3H5v2h2V3zm4 0H9v2h2V3zM7 7H5v2h2V7zm4 0H9v2h2V7zm-4 4H5v2h2v-2zm4 0H9v2h2v-2z",
|
|
100
|
+
fill: "#161616"
|
|
101
|
+
})]
|
|
102
|
+
});
|
|
103
|
+
};
|
|
104
|
+
DragIcon.defaultProps = {
|
|
105
|
+
width: "16",
|
|
106
|
+
height: "16",
|
|
107
|
+
fill: "none",
|
|
108
|
+
xmlns: "http://www.w3.org/2000/svg"
|
|
109
|
+
};
|
|
62
110
|
var ExternalLinkIcon = function ExternalLinkIcon(props) {
|
|
63
111
|
return jsxRuntime.jsx("svg", {
|
|
64
112
|
...props,
|
|
@@ -66,7 +114,7 @@ var ExternalLinkIcon = function ExternalLinkIcon(props) {
|
|
|
66
114
|
fillRule: "evenodd",
|
|
67
115
|
clipRule: "evenodd",
|
|
68
116
|
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",
|
|
69
|
-
fill: "
|
|
117
|
+
fill: "currentcolor"
|
|
70
118
|
})
|
|
71
119
|
});
|
|
72
120
|
};
|
|
@@ -215,7 +263,7 @@ function TooltipWrapper(props) {
|
|
|
215
263
|
return jsxRuntime.jsx(Tooltip, {
|
|
216
264
|
...props,
|
|
217
265
|
value: value,
|
|
218
|
-
forId: prefixId$
|
|
266
|
+
forId: prefixId$9(forId)
|
|
219
267
|
});
|
|
220
268
|
}
|
|
221
269
|
function Tooltip(props) {
|
|
@@ -333,7 +381,7 @@ function getTooltipPosition(refElement) {
|
|
|
333
381
|
function isHovered(element) {
|
|
334
382
|
return element.matches(':hover');
|
|
335
383
|
}
|
|
336
|
-
function prefixId$
|
|
384
|
+
function prefixId$9(id) {
|
|
337
385
|
return `bio-properties-panel-${id}`;
|
|
338
386
|
}
|
|
339
387
|
|
|
@@ -743,713 +791,704 @@ function Placeholder(props) {
|
|
|
743
791
|
});
|
|
744
792
|
}
|
|
745
793
|
|
|
746
|
-
|
|
747
|
-
const
|
|
748
|
-
|
|
794
|
+
function Description(props) {
|
|
795
|
+
const {
|
|
796
|
+
element,
|
|
797
|
+
forId,
|
|
798
|
+
value
|
|
799
|
+
} = props;
|
|
800
|
+
const contextDescription = useDescriptionContext(forId, element);
|
|
801
|
+
const description = value || contextDescription;
|
|
802
|
+
if (description) {
|
|
803
|
+
return jsxRuntime.jsx("div", {
|
|
804
|
+
class: "bio-properties-panel-description",
|
|
805
|
+
children: description
|
|
806
|
+
});
|
|
807
|
+
}
|
|
808
|
+
}
|
|
749
809
|
|
|
750
|
-
|
|
751
|
-
* @typedef { {
|
|
752
|
-
* component: import('preact').Component,
|
|
753
|
-
* id: String,
|
|
754
|
-
* isEdited?: Function
|
|
755
|
-
* } } EntryDefinition
|
|
756
|
-
*
|
|
757
|
-
* @typedef { {
|
|
758
|
-
* autoFocusEntry: String,
|
|
759
|
-
* autoOpen?: Boolean,
|
|
760
|
-
* entries: Array<EntryDefinition>,
|
|
761
|
-
* id: String,
|
|
762
|
-
* label: String,
|
|
763
|
-
* remove: (event: MouseEvent) => void
|
|
764
|
-
* } } ListItemDefinition
|
|
765
|
-
*
|
|
766
|
-
* @typedef { {
|
|
767
|
-
* add: (event: MouseEvent) => void,
|
|
768
|
-
* component: import('preact').Component,
|
|
769
|
-
* element: Object,
|
|
770
|
-
* id: String,
|
|
771
|
-
* items: Array<ListItemDefinition>,
|
|
772
|
-
* label: String,
|
|
773
|
-
* shouldSort?: Boolean,
|
|
774
|
-
* shouldOpen?: Boolean
|
|
775
|
-
* } } ListGroupDefinition
|
|
776
|
-
*
|
|
777
|
-
* @typedef { {
|
|
778
|
-
* component?: import('preact').Component,
|
|
779
|
-
* entries: Array<EntryDefinition>,
|
|
780
|
-
* id: String,
|
|
781
|
-
* label: String,
|
|
782
|
-
* shouldOpen?: Boolean
|
|
783
|
-
* } } GroupDefinition
|
|
784
|
-
*
|
|
785
|
-
* @typedef { {
|
|
786
|
-
* [id: String]: GetDescriptionFunction
|
|
787
|
-
* } } DescriptionConfig
|
|
788
|
-
*
|
|
789
|
-
* @typedef { {
|
|
790
|
-
* [id: String]: GetTooltipFunction
|
|
791
|
-
* } } TooltipConfig
|
|
792
|
-
*
|
|
793
|
-
* @callback { {
|
|
794
|
-
* @param {string} id
|
|
795
|
-
* @param {Object} element
|
|
796
|
-
* @returns {string}
|
|
797
|
-
* } } GetDescriptionFunction
|
|
798
|
-
*
|
|
799
|
-
* @callback { {
|
|
800
|
-
* @param {string} id
|
|
801
|
-
* @param {Object} element
|
|
802
|
-
* @returns {string}
|
|
803
|
-
* } } GetTooltipFunction
|
|
804
|
-
*
|
|
805
|
-
* @typedef { {
|
|
806
|
-
* getEmpty: (element: object) => import('./components/Placeholder').PlaceholderDefinition,
|
|
807
|
-
* getMultiple: (element: Object) => import('./components/Placeholder').PlaceholderDefinition
|
|
808
|
-
* } } PlaceholderProvider
|
|
809
|
-
*
|
|
810
|
-
*/
|
|
810
|
+
const noop$6 = () => {};
|
|
811
811
|
|
|
812
812
|
/**
|
|
813
|
-
*
|
|
814
|
-
*
|
|
815
|
-
*
|
|
816
|
-
* @param {Object} props
|
|
817
|
-
* @param {Object|Array} props.element
|
|
818
|
-
* @param {import('./components/Header').HeaderProvider} props.headerProvider
|
|
819
|
-
* @param {PlaceholderProvider} [props.placeholderProvider]
|
|
820
|
-
* @param {Array<GroupDefinition|ListGroupDefinition>} props.groups
|
|
821
|
-
* @param {Object} [props.layoutConfig]
|
|
822
|
-
* @param {Function} [props.layoutChanged]
|
|
823
|
-
* @param {DescriptionConfig} [props.descriptionConfig]
|
|
824
|
-
* @param {Function} [props.descriptionLoaded]
|
|
825
|
-
* @param {TooltipConfig} [props.tooltipConfig]
|
|
826
|
-
* @param {Function} [props.tooltipLoaded]
|
|
827
|
-
* @param {Object} [props.eventBus]
|
|
813
|
+
* Buffer `.focus()` calls while the editor is not initialized.
|
|
814
|
+
* Set Focus inside when the editor is ready.
|
|
828
815
|
*/
|
|
829
|
-
function
|
|
816
|
+
const useBufferedFocus$1 = function (editor, ref) {
|
|
817
|
+
const [buffer, setBuffer] = hooks.useState(undefined);
|
|
818
|
+
ref.current = hooks.useMemo(() => ({
|
|
819
|
+
focus: offset => {
|
|
820
|
+
if (editor) {
|
|
821
|
+
editor.focus(offset);
|
|
822
|
+
} else {
|
|
823
|
+
if (typeof offset === 'undefined') {
|
|
824
|
+
offset = Infinity;
|
|
825
|
+
}
|
|
826
|
+
setBuffer(offset);
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
}), [editor]);
|
|
830
|
+
hooks.useEffect(() => {
|
|
831
|
+
if (typeof buffer !== 'undefined' && editor) {
|
|
832
|
+
editor.focus(buffer);
|
|
833
|
+
setBuffer(false);
|
|
834
|
+
}
|
|
835
|
+
}, [editor, buffer]);
|
|
836
|
+
};
|
|
837
|
+
const CodeEditor$1 = compat.forwardRef((props, ref) => {
|
|
830
838
|
const {
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
839
|
+
onInput,
|
|
840
|
+
disabled,
|
|
841
|
+
tooltipContainer,
|
|
842
|
+
enableGutters,
|
|
843
|
+
value,
|
|
844
|
+
onLint = noop$6,
|
|
845
|
+
onPopupOpen = noop$6,
|
|
846
|
+
popupOpen,
|
|
847
|
+
contentAttributes = {},
|
|
848
|
+
hostLanguage = null,
|
|
849
|
+
singleLine = false
|
|
842
850
|
} = props;
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
const [
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
}, [layoutConfig]);
|
|
851
|
+
const inputRef = hooks.useRef();
|
|
852
|
+
const [editor, setEditor] = hooks.useState();
|
|
853
|
+
const [localValue, setLocalValue] = hooks.useState(value || '');
|
|
854
|
+
useBufferedFocus$1(editor, ref);
|
|
855
|
+
const handleInput = useStaticCallback(newValue => {
|
|
856
|
+
onInput(newValue);
|
|
857
|
+
setLocalValue(newValue);
|
|
858
|
+
});
|
|
852
859
|
hooks.useEffect(() => {
|
|
853
|
-
|
|
854
|
-
|
|
860
|
+
let editor;
|
|
861
|
+
editor = new feelers.FeelersEditor({
|
|
862
|
+
container: inputRef.current,
|
|
863
|
+
onChange: handleInput,
|
|
864
|
+
value: localValue,
|
|
865
|
+
onLint,
|
|
866
|
+
contentAttributes,
|
|
867
|
+
tooltipContainer,
|
|
868
|
+
enableGutters,
|
|
869
|
+
hostLanguage,
|
|
870
|
+
singleLine
|
|
871
|
+
});
|
|
872
|
+
setEditor(editor);
|
|
873
|
+
return () => {
|
|
874
|
+
onLint([]);
|
|
875
|
+
inputRef.current.innerHTML = '';
|
|
876
|
+
setEditor(null);
|
|
877
|
+
};
|
|
878
|
+
}, []);
|
|
879
|
+
hooks.useEffect(() => {
|
|
880
|
+
if (!editor) {
|
|
881
|
+
return;
|
|
855
882
|
}
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
};
|
|
865
|
-
const layoutContext = {
|
|
866
|
-
layout,
|
|
867
|
-
setLayout,
|
|
868
|
-
getLayoutForKey,
|
|
869
|
-
setLayoutForKey
|
|
883
|
+
if (value === localValue) {
|
|
884
|
+
return;
|
|
885
|
+
}
|
|
886
|
+
editor.setValue(value);
|
|
887
|
+
setLocalValue(value);
|
|
888
|
+
}, [value]);
|
|
889
|
+
const handleClick = () => {
|
|
890
|
+
ref.current.focus();
|
|
870
891
|
};
|
|
892
|
+
return jsxRuntime.jsxs("div", {
|
|
893
|
+
class: classnames__default["default"]('bio-properties-panel-feelers-editor-container', popupOpen ? 'popupOpen' : null),
|
|
894
|
+
children: [jsxRuntime.jsx("div", {
|
|
895
|
+
class: "bio-properties-panel-feelers-editor__open-popup-placeholder",
|
|
896
|
+
children: "Opened in editor"
|
|
897
|
+
}), jsxRuntime.jsx("div", {
|
|
898
|
+
name: props.name,
|
|
899
|
+
class: classnames__default["default"]('bio-properties-panel-feelers-editor bio-properties-panel-input', localValue ? 'edited' : null, disabled ? 'disabled' : null),
|
|
900
|
+
ref: inputRef,
|
|
901
|
+
onClick: handleClick
|
|
902
|
+
}), jsxRuntime.jsx("button", {
|
|
903
|
+
title: "Open pop-up editor",
|
|
904
|
+
class: "bio-properties-panel-open-feel-popup",
|
|
905
|
+
onClick: () => onPopupOpen('feelers'),
|
|
906
|
+
children: jsxRuntime.jsx(ExternalLinkIcon, {})
|
|
907
|
+
})]
|
|
908
|
+
});
|
|
909
|
+
});
|
|
871
910
|
|
|
872
|
-
|
|
873
|
-
|
|
911
|
+
const noop$5 = () => {};
|
|
912
|
+
|
|
913
|
+
/**
|
|
914
|
+
* Buffer `.focus()` calls while the editor is not initialized.
|
|
915
|
+
* Set Focus inside when the editor is ready.
|
|
916
|
+
*/
|
|
917
|
+
const useBufferedFocus = function (editor, ref) {
|
|
918
|
+
const [buffer, setBuffer] = hooks.useState(undefined);
|
|
919
|
+
ref.current = hooks.useMemo(() => ({
|
|
920
|
+
focus: offset => {
|
|
921
|
+
if (editor) {
|
|
922
|
+
editor.focus(offset);
|
|
923
|
+
} else {
|
|
924
|
+
if (typeof offset === 'undefined') {
|
|
925
|
+
offset = Infinity;
|
|
926
|
+
}
|
|
927
|
+
setBuffer(offset);
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
}), [editor]);
|
|
874
931
|
hooks.useEffect(() => {
|
|
875
|
-
if (typeof
|
|
876
|
-
|
|
932
|
+
if (typeof buffer !== 'undefined' && editor) {
|
|
933
|
+
editor.focus(buffer);
|
|
934
|
+
setBuffer(false);
|
|
877
935
|
}
|
|
878
|
-
}, [
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
936
|
+
}, [editor, buffer]);
|
|
937
|
+
};
|
|
938
|
+
const CodeEditor = compat.forwardRef((props, ref) => {
|
|
939
|
+
const {
|
|
940
|
+
enableGutters,
|
|
941
|
+
value,
|
|
942
|
+
onInput,
|
|
943
|
+
onFeelToggle = noop$5,
|
|
944
|
+
onLint = noop$5,
|
|
945
|
+
onPopupOpen = noop$5,
|
|
946
|
+
popupOpen,
|
|
947
|
+
disabled,
|
|
948
|
+
tooltipContainer,
|
|
949
|
+
variables
|
|
950
|
+
} = props;
|
|
951
|
+
const inputRef = hooks.useRef();
|
|
952
|
+
const [editor, setEditor] = hooks.useState();
|
|
953
|
+
const [localValue, setLocalValue] = hooks.useState(value || '');
|
|
954
|
+
useBufferedFocus(editor, ref);
|
|
955
|
+
const handleInput = useStaticCallback(newValue => {
|
|
956
|
+
onInput(newValue);
|
|
957
|
+
setLocalValue(newValue);
|
|
958
|
+
});
|
|
959
|
+
hooks.useEffect(() => {
|
|
960
|
+
let editor;
|
|
886
961
|
|
|
887
|
-
|
|
888
|
-
|
|
962
|
+
/* Trigger FEEL toggle when
|
|
963
|
+
*
|
|
964
|
+
* - `backspace` is pressed
|
|
965
|
+
* - AND the cursor is at the beginning of the input
|
|
966
|
+
*/
|
|
967
|
+
const onKeyDown = e => {
|
|
968
|
+
if (e.key !== 'Backspace' || !editor) {
|
|
969
|
+
return;
|
|
970
|
+
}
|
|
971
|
+
const selection = editor.getSelection();
|
|
972
|
+
const range = selection.ranges[selection.mainIndex];
|
|
973
|
+
if (range.from === 0 && range.to === 0) {
|
|
974
|
+
onFeelToggle();
|
|
975
|
+
}
|
|
976
|
+
};
|
|
977
|
+
editor = new FeelEditor__default["default"]({
|
|
978
|
+
container: inputRef.current,
|
|
979
|
+
onChange: handleInput,
|
|
980
|
+
onKeyDown: onKeyDown,
|
|
981
|
+
onLint: onLint,
|
|
982
|
+
tooltipContainer: tooltipContainer,
|
|
983
|
+
value: localValue,
|
|
984
|
+
variables: variables,
|
|
985
|
+
extensions: [...(enableGutters ? [view.lineNumbers()] : [])]
|
|
986
|
+
});
|
|
987
|
+
setEditor(editor);
|
|
988
|
+
return () => {
|
|
989
|
+
onLint([]);
|
|
990
|
+
inputRef.current.innerHTML = '';
|
|
991
|
+
setEditor(null);
|
|
992
|
+
};
|
|
993
|
+
}, []);
|
|
889
994
|
hooks.useEffect(() => {
|
|
890
|
-
if (
|
|
891
|
-
|
|
995
|
+
if (!editor) {
|
|
996
|
+
return;
|
|
892
997
|
}
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
}
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
errors
|
|
908
|
-
};
|
|
909
|
-
const eventContext = {
|
|
910
|
-
eventBus
|
|
911
|
-
};
|
|
912
|
-
const propertiesPanelContext = {
|
|
913
|
-
element
|
|
998
|
+
if (value === localValue) {
|
|
999
|
+
return;
|
|
1000
|
+
}
|
|
1001
|
+
editor.setValue(value);
|
|
1002
|
+
setLocalValue(value);
|
|
1003
|
+
}, [value]);
|
|
1004
|
+
hooks.useEffect(() => {
|
|
1005
|
+
if (!editor) {
|
|
1006
|
+
return;
|
|
1007
|
+
}
|
|
1008
|
+
editor.setVariables(variables);
|
|
1009
|
+
}, [variables]);
|
|
1010
|
+
const handleClick = () => {
|
|
1011
|
+
ref.current.focus();
|
|
914
1012
|
};
|
|
1013
|
+
return jsxRuntime.jsxs("div", {
|
|
1014
|
+
class: classnames__default["default"]('bio-properties-panel-feel-editor-container', disabled ? 'disabled' : null, popupOpen ? 'popupOpen' : null),
|
|
1015
|
+
children: [jsxRuntime.jsx("div", {
|
|
1016
|
+
class: "bio-properties-panel-feel-editor__open-popup-placeholder",
|
|
1017
|
+
children: "Opened in editor"
|
|
1018
|
+
}), jsxRuntime.jsx("div", {
|
|
1019
|
+
name: props.name,
|
|
1020
|
+
class: classnames__default["default"]('bio-properties-panel-input', localValue ? 'edited' : null),
|
|
1021
|
+
ref: inputRef,
|
|
1022
|
+
onClick: handleClick
|
|
1023
|
+
}), jsxRuntime.jsx("button", {
|
|
1024
|
+
title: "Open pop-up editor",
|
|
1025
|
+
class: "bio-properties-panel-open-feel-popup",
|
|
1026
|
+
onClick: () => onPopupOpen(),
|
|
1027
|
+
children: jsxRuntime.jsx(ExternalLinkIcon, {})
|
|
1028
|
+
})]
|
|
1029
|
+
});
|
|
1030
|
+
});
|
|
915
1031
|
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
// multiple state
|
|
924
|
-
if (placeholderProvider && minDash.isArray(element)) {
|
|
925
|
-
return jsxRuntime.jsx(Placeholder, {
|
|
926
|
-
...placeholderProvider.getMultiple()
|
|
927
|
-
});
|
|
1032
|
+
function FeelIndicator(props) {
|
|
1033
|
+
const {
|
|
1034
|
+
active
|
|
1035
|
+
} = props;
|
|
1036
|
+
if (!active) {
|
|
1037
|
+
return null;
|
|
928
1038
|
}
|
|
929
|
-
return jsxRuntime.jsx(
|
|
930
|
-
|
|
931
|
-
children:
|
|
932
|
-
value: errorsContext,
|
|
933
|
-
children: jsxRuntime.jsx(DescriptionContext.Provider, {
|
|
934
|
-
value: descriptionContext,
|
|
935
|
-
children: jsxRuntime.jsx(TooltipContext.Provider, {
|
|
936
|
-
value: tooltipContext,
|
|
937
|
-
children: jsxRuntime.jsx(LayoutContext.Provider, {
|
|
938
|
-
value: layoutContext,
|
|
939
|
-
children: jsxRuntime.jsx(EventContext.Provider, {
|
|
940
|
-
value: eventContext,
|
|
941
|
-
children: jsxRuntime.jsxs("div", {
|
|
942
|
-
class: "bio-properties-panel",
|
|
943
|
-
children: [jsxRuntime.jsx(Header, {
|
|
944
|
-
element: element,
|
|
945
|
-
headerProvider: headerProvider
|
|
946
|
-
}), jsxRuntime.jsx("div", {
|
|
947
|
-
class: "bio-properties-panel-scroll-container",
|
|
948
|
-
children: groups.map(group => {
|
|
949
|
-
const {
|
|
950
|
-
component: Component = Group,
|
|
951
|
-
id
|
|
952
|
-
} = group;
|
|
953
|
-
return preact.createElement(Component, {
|
|
954
|
-
...group,
|
|
955
|
-
key: id,
|
|
956
|
-
element: element
|
|
957
|
-
});
|
|
958
|
-
})
|
|
959
|
-
})]
|
|
960
|
-
})
|
|
961
|
-
})
|
|
962
|
-
})
|
|
963
|
-
})
|
|
964
|
-
})
|
|
965
|
-
})
|
|
1039
|
+
return jsxRuntime.jsx("span", {
|
|
1040
|
+
class: "bio-properties-panel-feel-indicator",
|
|
1041
|
+
children: "="
|
|
966
1042
|
});
|
|
967
1043
|
}
|
|
968
1044
|
|
|
969
|
-
|
|
1045
|
+
const noop$4 = () => {};
|
|
970
1046
|
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
}
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
1047
|
+
/**
|
|
1048
|
+
* @param {Object} props
|
|
1049
|
+
* @param {Object} props.label
|
|
1050
|
+
* @param {String} props.feel
|
|
1051
|
+
*/
|
|
1052
|
+
function FeelIcon(props) {
|
|
1053
|
+
const {
|
|
1054
|
+
feel = false,
|
|
1055
|
+
active,
|
|
1056
|
+
disabled = false,
|
|
1057
|
+
onClick = noop$4
|
|
1058
|
+
} = props;
|
|
1059
|
+
const feelRequiredLabel = 'FEEL expression is mandatory';
|
|
1060
|
+
const feelOptionalLabel = `Click to ${active ? 'remove' : 'set a'} dynamic value with FEEL expression`;
|
|
1061
|
+
const handleClick = e => {
|
|
1062
|
+
onClick(e);
|
|
1063
|
+
|
|
1064
|
+
// when pointer event was created from keyboard, keep focus on button
|
|
1065
|
+
if (!e.pointerType) {
|
|
1066
|
+
e.stopPropagation();
|
|
1067
|
+
}
|
|
987
1068
|
};
|
|
1069
|
+
return jsxRuntime.jsx("button", {
|
|
1070
|
+
class: classnames__default["default"]('bio-properties-panel-feel-icon', active ? 'active' : null, feel === 'required' ? 'required' : 'optional'),
|
|
1071
|
+
onClick: handleClick,
|
|
1072
|
+
disabled: feel === 'required' || disabled,
|
|
1073
|
+
title: feel === 'required' ? feelRequiredLabel : feelOptionalLabel,
|
|
1074
|
+
children: jsxRuntime.jsx(FeelIcon$1, {})
|
|
1075
|
+
});
|
|
988
1076
|
}
|
|
989
1077
|
|
|
990
|
-
|
|
1078
|
+
const FeelPopupContext = preact.createContext({
|
|
1079
|
+
open: () => {},
|
|
1080
|
+
close: () => {},
|
|
1081
|
+
source: null
|
|
1082
|
+
});
|
|
991
1083
|
|
|
992
1084
|
/**
|
|
993
|
-
*
|
|
1085
|
+
* Add a dragger that calls back the passed function with
|
|
1086
|
+
* { event, delta } on drag.
|
|
994
1087
|
*
|
|
995
|
-
* @
|
|
996
|
-
*
|
|
1088
|
+
* @example
|
|
1089
|
+
*
|
|
1090
|
+
* function dragMove(event, delta) {
|
|
1091
|
+
* // we are dragging (!!)
|
|
1092
|
+
* }
|
|
1093
|
+
*
|
|
1094
|
+
* domElement.addEventListener('dragstart', dragger(dragMove));
|
|
1095
|
+
*
|
|
1096
|
+
* @param {Function} fn
|
|
1097
|
+
* @param {Element} [dragPreview]
|
|
1098
|
+
*
|
|
1099
|
+
* @return {Function} drag start callback function
|
|
997
1100
|
*/
|
|
998
|
-
function
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1101
|
+
function createDragger(fn, dragPreview) {
|
|
1102
|
+
let self;
|
|
1103
|
+
let startX, startY;
|
|
1104
|
+
|
|
1105
|
+
/** drag start */
|
|
1106
|
+
function onDragStart(event) {
|
|
1107
|
+
self = this;
|
|
1108
|
+
startX = event.clientX;
|
|
1109
|
+
startY = event.clientY;
|
|
1110
|
+
|
|
1111
|
+
// (1) prevent preview image
|
|
1112
|
+
if (event.dataTransfer) {
|
|
1113
|
+
event.dataTransfer.setDragImage(dragPreview || emptyCanvas(), 0, 0);
|
|
1005
1114
|
}
|
|
1006
|
-
|
|
1115
|
+
|
|
1116
|
+
// (2) setup drag listeners
|
|
1117
|
+
|
|
1118
|
+
// attach drag + cleanup event
|
|
1119
|
+
document.addEventListener('dragover', onDrag);
|
|
1120
|
+
document.addEventListener('dragend', onEnd);
|
|
1121
|
+
document.addEventListener('drop', preventDefault);
|
|
1122
|
+
}
|
|
1123
|
+
function onDrag(event) {
|
|
1124
|
+
const delta = {
|
|
1125
|
+
x: event.clientX - startX,
|
|
1126
|
+
y: event.clientY - startY
|
|
1127
|
+
};
|
|
1128
|
+
|
|
1129
|
+
// call provided fn with event, delta
|
|
1130
|
+
return fn.call(self, event, delta);
|
|
1131
|
+
}
|
|
1132
|
+
function onEnd() {
|
|
1133
|
+
document.removeEventListener('dragover', onDrag);
|
|
1134
|
+
document.removeEventListener('dragend', onEnd);
|
|
1135
|
+
document.removeEventListener('drop', preventDefault);
|
|
1136
|
+
}
|
|
1137
|
+
return onDragStart;
|
|
1138
|
+
}
|
|
1139
|
+
function preventDefault(event) {
|
|
1140
|
+
event.preventDefault();
|
|
1141
|
+
event.stopPropagation();
|
|
1142
|
+
}
|
|
1143
|
+
function emptyCanvas() {
|
|
1144
|
+
return minDom.domify('<canvas width="0" height="0" />');
|
|
1007
1145
|
}
|
|
1008
1146
|
|
|
1009
|
-
|
|
1147
|
+
const noop$3 = () => {};
|
|
1148
|
+
|
|
1149
|
+
/**
|
|
1150
|
+
* A generic popup component.
|
|
1151
|
+
*
|
|
1152
|
+
* @param {Object} props
|
|
1153
|
+
* @param {HTMLElement} [props.container]
|
|
1154
|
+
* @param {string} [props.className]
|
|
1155
|
+
* @param {{x: number, y: number}} [props.position]
|
|
1156
|
+
* @param {number} [props.width]
|
|
1157
|
+
* @param {number} [props.height]
|
|
1158
|
+
* @param {Function} props.onClose
|
|
1159
|
+
* @param {Function} [props.onPostActivate]
|
|
1160
|
+
* @param {Function} [props.onPostDeactivate]
|
|
1161
|
+
* @param {boolean} [props.returnFocus]
|
|
1162
|
+
* @param {string} props.title
|
|
1163
|
+
*/
|
|
1164
|
+
function Popup(props) {
|
|
1010
1165
|
const {
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1166
|
+
container,
|
|
1167
|
+
className,
|
|
1168
|
+
position,
|
|
1169
|
+
width,
|
|
1170
|
+
height,
|
|
1171
|
+
onClose,
|
|
1172
|
+
onPostActivate = noop$3,
|
|
1173
|
+
onPostDeactivate = noop$3,
|
|
1174
|
+
returnFocus = true,
|
|
1175
|
+
title
|
|
1014
1176
|
} = props;
|
|
1015
|
-
const
|
|
1016
|
-
const
|
|
1017
|
-
const
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
if (menuRef.current && menuRef.current.contains(event.target)) {
|
|
1021
|
-
return;
|
|
1177
|
+
const focusTrapRef = hooks.useRef(null);
|
|
1178
|
+
const popupRef = hooks.useRef(null);
|
|
1179
|
+
const handleKeyPress = event => {
|
|
1180
|
+
if (event.key === 'Escape') {
|
|
1181
|
+
onClose();
|
|
1022
1182
|
}
|
|
1023
|
-
|
|
1024
|
-
|
|
1183
|
+
};
|
|
1184
|
+
|
|
1185
|
+
// re-activate focus trap on focus
|
|
1186
|
+
const handleFocus = () => {
|
|
1187
|
+
if (focusTrapRef.current) {
|
|
1188
|
+
focusTrapRef.current.activate();
|
|
1189
|
+
}
|
|
1190
|
+
};
|
|
1191
|
+
let style = {};
|
|
1192
|
+
if (position) {
|
|
1193
|
+
style = {
|
|
1194
|
+
...style,
|
|
1195
|
+
top: position.top + 'px',
|
|
1196
|
+
left: position.left + 'px'
|
|
1197
|
+
};
|
|
1025
1198
|
}
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
close();
|
|
1029
|
-
action();
|
|
1199
|
+
if (width) {
|
|
1200
|
+
style.width = width + 'px';
|
|
1030
1201
|
}
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
class: classnames__default["default"]('bio-properties-panel-dropdown-button', {
|
|
1034
|
-
open
|
|
1035
|
-
}, className),
|
|
1036
|
-
onClick: onDropdownToggle,
|
|
1037
|
-
ref: dropdownRef,
|
|
1038
|
-
children: [children, jsxRuntime.jsx("div", {
|
|
1039
|
-
class: "bio-properties-panel-dropdown-button__menu",
|
|
1040
|
-
ref: menuRef,
|
|
1041
|
-
children: menuItems.map((item, index) => jsxRuntime.jsx(MenuItem, {
|
|
1042
|
-
onClick: onActionClick,
|
|
1043
|
-
item: item
|
|
1044
|
-
}, index))
|
|
1045
|
-
})]
|
|
1046
|
-
});
|
|
1047
|
-
}
|
|
1048
|
-
function MenuItem({
|
|
1049
|
-
item,
|
|
1050
|
-
onClick
|
|
1051
|
-
}) {
|
|
1052
|
-
if (item.separator) {
|
|
1053
|
-
return jsxRuntime.jsx("div", {
|
|
1054
|
-
class: "bio-properties-panel-dropdown-button__menu-item bio-properties-panel-dropdown-button__menu-item--separator"
|
|
1055
|
-
});
|
|
1056
|
-
}
|
|
1057
|
-
if (item.action) {
|
|
1058
|
-
return jsxRuntime.jsx("button", {
|
|
1059
|
-
class: "bio-properties-panel-dropdown-button__menu-item bio-properties-panel-dropdown-button__menu-item--actionable",
|
|
1060
|
-
onClick: event => onClick(event, item.action),
|
|
1061
|
-
children: item.entry
|
|
1062
|
-
});
|
|
1202
|
+
if (height) {
|
|
1203
|
+
style.height = height + 'px';
|
|
1063
1204
|
}
|
|
1064
|
-
return jsxRuntime.jsx("div", {
|
|
1065
|
-
class: "bio-properties-panel-dropdown-button__menu-item",
|
|
1066
|
-
children: item.entry
|
|
1067
|
-
});
|
|
1068
|
-
}
|
|
1069
|
-
|
|
1070
|
-
/**
|
|
1071
|
-
*
|
|
1072
|
-
* @param {Array<null | Element>} ignoredElements
|
|
1073
|
-
* @param {Function} callback
|
|
1074
|
-
*/
|
|
1075
|
-
function useGlobalClick(ignoredElements, callback) {
|
|
1076
1205
|
hooks.useEffect(() => {
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
*/
|
|
1080
|
-
function listener(event) {
|
|
1081
|
-
if (ignoredElements.some(element => element && element.contains(event.target))) {
|
|
1082
|
-
return;
|
|
1083
|
-
}
|
|
1084
|
-
callback();
|
|
1206
|
+
if (popupRef.current) {
|
|
1207
|
+
popupRef.current.addEventListener('keydown', handleKeyPress);
|
|
1085
1208
|
}
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
}
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1209
|
+
return () => {
|
|
1210
|
+
popupRef.current.removeEventListener('keydown', handleKeyPress);
|
|
1211
|
+
};
|
|
1212
|
+
}, [popupRef]);
|
|
1213
|
+
hooks.useEffect(() => {
|
|
1214
|
+
if (popupRef.current) {
|
|
1215
|
+
popupRef.current.addEventListener('focusin', handleFocus);
|
|
1216
|
+
}
|
|
1217
|
+
return () => {
|
|
1218
|
+
popupRef.current.removeEventListener('focusin', handleFocus);
|
|
1219
|
+
};
|
|
1220
|
+
}, [popupRef]);
|
|
1221
|
+
hooks.useEffect(() => {
|
|
1222
|
+
if (popupRef.current) {
|
|
1223
|
+
focusTrapRef.current = focusTrap__namespace.createFocusTrap(popupRef.current, {
|
|
1224
|
+
clickOutsideDeactivates: true,
|
|
1225
|
+
fallbackFocus: popupRef.current,
|
|
1226
|
+
onPostActivate,
|
|
1227
|
+
onPostDeactivate,
|
|
1228
|
+
returnFocusOnDeactivate: returnFocus
|
|
1229
|
+
});
|
|
1230
|
+
focusTrapRef.current.activate();
|
|
1231
|
+
}
|
|
1232
|
+
return () => focusTrapRef.current && focusTrapRef.current.deactivate();
|
|
1233
|
+
}, [popupRef]);
|
|
1234
|
+
return compat.createPortal(jsxRuntime.jsx("div", {
|
|
1235
|
+
"aria-label": title,
|
|
1236
|
+
tabIndex: -1,
|
|
1237
|
+
ref: popupRef,
|
|
1238
|
+
role: "dialog",
|
|
1239
|
+
class: classnames__default["default"]('bio-properties-panel-popup', className),
|
|
1240
|
+
style: style,
|
|
1241
|
+
children: props.children
|
|
1242
|
+
}), container || document.body);
|
|
1093
1243
|
}
|
|
1094
|
-
|
|
1095
|
-
|
|
1244
|
+
Popup.Title = Title;
|
|
1245
|
+
Popup.Body = Body;
|
|
1246
|
+
Popup.Footer = Footer;
|
|
1247
|
+
function Title(props) {
|
|
1096
1248
|
const {
|
|
1097
|
-
children
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1249
|
+
children,
|
|
1250
|
+
className,
|
|
1251
|
+
draggable,
|
|
1252
|
+
title,
|
|
1253
|
+
...rest
|
|
1101
1254
|
} = props;
|
|
1102
|
-
return jsxRuntime.jsx("button", {
|
|
1103
|
-
...otherProps,
|
|
1104
|
-
onClick: onClick,
|
|
1105
|
-
class: classnames__default["default"]('bio-properties-panel-group-header-button', classname),
|
|
1106
|
-
children: children
|
|
1107
|
-
});
|
|
1108
|
-
}
|
|
1109
1255
|
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1256
|
+
// we can't use state as we need to
|
|
1257
|
+
// manipulate this inside dragging events
|
|
1258
|
+
const context = hooks.useRef({
|
|
1259
|
+
startPosition: null,
|
|
1260
|
+
newPosition: null
|
|
1261
|
+
});
|
|
1262
|
+
const dragPreviewRef = hooks.useRef();
|
|
1263
|
+
const titleRef = hooks.useRef();
|
|
1264
|
+
const onMove = minDash.throttle((_, delta) => {
|
|
1265
|
+
const {
|
|
1266
|
+
x: dx,
|
|
1267
|
+
y: dy
|
|
1268
|
+
} = delta;
|
|
1269
|
+
const newPosition = {
|
|
1270
|
+
x: context.current.startPosition.x + dx,
|
|
1271
|
+
y: context.current.startPosition.y + dy
|
|
1272
|
+
};
|
|
1273
|
+
const popupParent = getPopupParent(titleRef.current);
|
|
1274
|
+
popupParent.style.top = newPosition.y + 'px';
|
|
1275
|
+
popupParent.style.left = newPosition.x + 'px';
|
|
1276
|
+
});
|
|
1277
|
+
const onMoveStart = event => {
|
|
1278
|
+
// initialize drag handler
|
|
1279
|
+
const onDragStart = createDragger(onMove, dragPreviewRef.current);
|
|
1280
|
+
onDragStart(event);
|
|
1281
|
+
const popupParent = getPopupParent(titleRef.current);
|
|
1282
|
+
const bounds = popupParent.getBoundingClientRect();
|
|
1283
|
+
context.current.startPosition = {
|
|
1284
|
+
x: bounds.left,
|
|
1285
|
+
y: bounds.top
|
|
1286
|
+
};
|
|
1287
|
+
};
|
|
1288
|
+
const onMoveEnd = () => {
|
|
1289
|
+
context.current.newPosition = null;
|
|
1132
1290
|
};
|
|
1133
|
-
|
|
1134
|
-
// todo(pinussilvestrus): translate once we have a translate mechanism for the core
|
|
1135
|
-
const placeholderLabel = '<empty>';
|
|
1136
1291
|
return jsxRuntime.jsxs("div", {
|
|
1137
|
-
"
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1292
|
+
class: classnames__default["default"]('bio-properties-panel-popup__header', draggable && 'draggable', className),
|
|
1293
|
+
ref: titleRef,
|
|
1294
|
+
draggable: draggable,
|
|
1295
|
+
onDragStart: onMoveStart,
|
|
1296
|
+
onDragEnd: onMoveEnd,
|
|
1297
|
+
...rest,
|
|
1298
|
+
children: [draggable && jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
1142
1299
|
children: [jsxRuntime.jsx("div", {
|
|
1143
|
-
|
|
1144
|
-
class:
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
children: jsxRuntime.jsx(ArrowIcon, {
|
|
1150
|
-
class: open ? 'bio-properties-panel-arrow-down' : 'bio-properties-panel-arrow-right'
|
|
1151
|
-
})
|
|
1152
|
-
}), remove ? jsxRuntime.jsx("button", {
|
|
1153
|
-
title: "Delete item",
|
|
1154
|
-
class: "bio-properties-panel-remove-entry",
|
|
1155
|
-
onClick: remove,
|
|
1156
|
-
children: jsxRuntime.jsx(DeleteIcon, {})
|
|
1157
|
-
}) : null]
|
|
1300
|
+
ref: dragPreviewRef,
|
|
1301
|
+
class: "bio-properties-panel-popup__drag-preview"
|
|
1302
|
+
}), jsxRuntime.jsx("div", {
|
|
1303
|
+
class: "bio-properties-panel-popup__drag-handle",
|
|
1304
|
+
children: jsxRuntime.jsx(DragIcon, {})
|
|
1305
|
+
})]
|
|
1158
1306
|
}), jsxRuntime.jsx("div", {
|
|
1159
|
-
class:
|
|
1160
|
-
children:
|
|
1161
|
-
|
|
1162
|
-
children: entries.map(entry => {
|
|
1163
|
-
const {
|
|
1164
|
-
component: Component,
|
|
1165
|
-
id
|
|
1166
|
-
} = entry;
|
|
1167
|
-
return preact.createElement(Component, {
|
|
1168
|
-
...entry,
|
|
1169
|
-
element: element,
|
|
1170
|
-
key: id
|
|
1171
|
-
});
|
|
1172
|
-
})
|
|
1173
|
-
})
|
|
1174
|
-
})]
|
|
1307
|
+
class: "bio-properties-panel-popup__title",
|
|
1308
|
+
children: title
|
|
1309
|
+
}), children]
|
|
1175
1310
|
});
|
|
1176
1311
|
}
|
|
1177
|
-
|
|
1178
|
-
function ListItem(props) {
|
|
1312
|
+
function Body(props) {
|
|
1179
1313
|
const {
|
|
1180
|
-
|
|
1181
|
-
|
|
1314
|
+
children,
|
|
1315
|
+
className,
|
|
1316
|
+
...rest
|
|
1182
1317
|
} = props;
|
|
1183
|
-
|
|
1184
|
-
// focus specified entry on auto open
|
|
1185
|
-
hooks.useEffect(() => {
|
|
1186
|
-
if (autoOpen && autoFocusEntry) {
|
|
1187
|
-
const entry = minDom.query(`[data-entry-id="${autoFocusEntry}"]`);
|
|
1188
|
-
const focusableInput = minDom.query('.bio-properties-panel-input', entry);
|
|
1189
|
-
if (focusableInput) {
|
|
1190
|
-
if (minDash.isFunction(focusableInput.select)) {
|
|
1191
|
-
focusableInput.select();
|
|
1192
|
-
} else if (minDash.isFunction(focusableInput.focus)) {
|
|
1193
|
-
focusableInput.focus();
|
|
1194
|
-
}
|
|
1195
|
-
}
|
|
1196
|
-
}
|
|
1197
|
-
}, [autoOpen, autoFocusEntry]);
|
|
1198
1318
|
return jsxRuntime.jsx("div", {
|
|
1199
|
-
class: "bio-properties-panel-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1319
|
+
class: classnames__default["default"]('bio-properties-panel-popup__body', className),
|
|
1320
|
+
...rest,
|
|
1321
|
+
children: children
|
|
1322
|
+
});
|
|
1323
|
+
}
|
|
1324
|
+
function Footer(props) {
|
|
1325
|
+
const {
|
|
1326
|
+
children,
|
|
1327
|
+
className,
|
|
1328
|
+
...rest
|
|
1329
|
+
} = props;
|
|
1330
|
+
return jsxRuntime.jsx("div", {
|
|
1331
|
+
class: classnames__default["default"]('bio-properties-panel-popup__footer', className),
|
|
1332
|
+
...rest,
|
|
1333
|
+
children: props.children
|
|
1204
1334
|
});
|
|
1205
1335
|
}
|
|
1206
1336
|
|
|
1207
|
-
|
|
1337
|
+
// helpers //////////////////////
|
|
1338
|
+
|
|
1339
|
+
function getPopupParent(node) {
|
|
1340
|
+
return node.closest('.bio-properties-panel-popup');
|
|
1341
|
+
}
|
|
1342
|
+
|
|
1343
|
+
const FEEL_POPUP_WIDTH = 700;
|
|
1344
|
+
const FEEL_POPUP_HEIGHT = 250;
|
|
1208
1345
|
|
|
1209
1346
|
/**
|
|
1210
|
-
*
|
|
1347
|
+
* FEEL popup component, built as a singleton.
|
|
1211
1348
|
*/
|
|
1212
|
-
function
|
|
1349
|
+
function FEELPopupRoot(props) {
|
|
1213
1350
|
const {
|
|
1214
|
-
|
|
1215
|
-
element,
|
|
1216
|
-
id,
|
|
1217
|
-
items,
|
|
1218
|
-
label,
|
|
1219
|
-
shouldOpen = true,
|
|
1220
|
-
shouldSort = true
|
|
1351
|
+
element
|
|
1221
1352
|
} = props;
|
|
1222
|
-
const groupRef = hooks.useRef(null);
|
|
1223
|
-
const [open, setOpen] = useLayoutState(['groups', id, 'open'], false);
|
|
1224
|
-
const [sticky, setSticky] = hooks.useState(false);
|
|
1225
|
-
const onShow = hooks.useCallback(() => setOpen(true), [setOpen]);
|
|
1226
|
-
const [ordering, setOrdering] = hooks.useState([]);
|
|
1227
|
-
const [newItemAdded, setNewItemAdded] = hooks.useState(false);
|
|
1228
|
-
|
|
1229
|
-
// Flag to mark that add button was clicked in the last render cycle
|
|
1230
|
-
const [addTriggered, setAddTriggered] = hooks.useState(false);
|
|
1231
|
-
const prevItems = usePrevious(items);
|
|
1232
1353
|
const prevElement = usePrevious(element);
|
|
1233
|
-
const
|
|
1234
|
-
const
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1354
|
+
const [popupConfig, setPopupConfig] = hooks.useState({});
|
|
1355
|
+
const [open, setOpen] = hooks.useState(false);
|
|
1356
|
+
const [source, setSource] = hooks.useState(null);
|
|
1357
|
+
const [sourceElement, setSourceElement] = hooks.useState(null);
|
|
1358
|
+
const handleOpen = (key, config, _sourceElement) => {
|
|
1359
|
+
setSource(key);
|
|
1360
|
+
setPopupConfig(config);
|
|
1361
|
+
setOpen(true);
|
|
1362
|
+
setSourceElement(_sourceElement);
|
|
1363
|
+
};
|
|
1364
|
+
const handleClose = () => {
|
|
1365
|
+
setOpen(false);
|
|
1366
|
+
setSource(null);
|
|
1367
|
+
};
|
|
1368
|
+
const feelPopupContext = {
|
|
1369
|
+
open: handleOpen,
|
|
1370
|
+
close: handleClose,
|
|
1371
|
+
source
|
|
1372
|
+
};
|
|
1242
1373
|
|
|
1243
|
-
//
|
|
1374
|
+
// close popup on element change, cf. https://github.com/bpmn-io/properties-panel/issues/270
|
|
1244
1375
|
hooks.useEffect(() => {
|
|
1245
|
-
if (
|
|
1246
|
-
|
|
1376
|
+
if (element && element !== prevElement) {
|
|
1377
|
+
handleClose();
|
|
1247
1378
|
}
|
|
1248
|
-
}, [
|
|
1249
|
-
|
|
1250
|
-
|
|
1379
|
+
}, [element]);
|
|
1380
|
+
return jsxRuntime.jsxs(FeelPopupContext.Provider, {
|
|
1381
|
+
value: feelPopupContext,
|
|
1382
|
+
children: [open && jsxRuntime.jsx(FeelPopupComponent, {
|
|
1383
|
+
onClose: handleClose,
|
|
1384
|
+
sourceElement: sourceElement,
|
|
1385
|
+
...popupConfig
|
|
1386
|
+
}), props.children]
|
|
1387
|
+
});
|
|
1388
|
+
}
|
|
1389
|
+
function FeelPopupComponent(props) {
|
|
1390
|
+
const {
|
|
1391
|
+
id,
|
|
1392
|
+
hostLanguage,
|
|
1393
|
+
onInput,
|
|
1394
|
+
onClose,
|
|
1395
|
+
position,
|
|
1396
|
+
singleLine,
|
|
1397
|
+
sourceElement,
|
|
1398
|
+
title,
|
|
1399
|
+
tooltipContainer,
|
|
1400
|
+
type,
|
|
1401
|
+
value,
|
|
1402
|
+
variables
|
|
1403
|
+
} = props;
|
|
1404
|
+
const editorRef = hooks.useRef();
|
|
1405
|
+
const handleSetReturnFocus = () => {
|
|
1406
|
+
sourceElement && sourceElement.focus();
|
|
1407
|
+
};
|
|
1251
1408
|
hooks.useEffect(() => {
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1409
|
+
const editor = editorRef.current;
|
|
1410
|
+
if (editor) {
|
|
1411
|
+
editor.focus();
|
|
1412
|
+
}
|
|
1413
|
+
}, [editorRef, id]);
|
|
1414
|
+
return jsxRuntime.jsxs(Popup, {
|
|
1415
|
+
className: "bio-properties-panel-feel-popup",
|
|
1416
|
+
position: position,
|
|
1417
|
+
title: title,
|
|
1418
|
+
onClose: onClose
|
|
1419
|
+
|
|
1420
|
+
// handle focus manually on deactivate
|
|
1421
|
+
,
|
|
1422
|
+
returnFocus: false,
|
|
1423
|
+
onPostDeactivate: handleSetReturnFocus,
|
|
1424
|
+
height: FEEL_POPUP_HEIGHT,
|
|
1425
|
+
width: FEEL_POPUP_WIDTH,
|
|
1426
|
+
children: [jsxRuntime.jsx(Popup.Title, {
|
|
1427
|
+
title: title,
|
|
1428
|
+
draggable: true
|
|
1429
|
+
}), jsxRuntime.jsx(Popup.Body, {
|
|
1430
|
+
children: jsxRuntime.jsxs("div", {
|
|
1431
|
+
class: "bio-properties-panel-feel-popup__body",
|
|
1432
|
+
children: [type === 'feel' && jsxRuntime.jsx(CodeEditor, {
|
|
1433
|
+
enableGutters: true,
|
|
1434
|
+
id: prefixId$8(id),
|
|
1435
|
+
name: id,
|
|
1436
|
+
onInput: onInput,
|
|
1437
|
+
value: value,
|
|
1438
|
+
variables: variables,
|
|
1439
|
+
ref: editorRef,
|
|
1440
|
+
tooltipContainer: tooltipContainer
|
|
1441
|
+
}), type === 'feelers' && jsxRuntime.jsx(CodeEditor$1, {
|
|
1442
|
+
id: prefixId$8(id),
|
|
1443
|
+
contentAttributes: {
|
|
1444
|
+
'aria-label': title
|
|
1445
|
+
},
|
|
1446
|
+
enableGutters: true,
|
|
1447
|
+
hostLanguage: hostLanguage,
|
|
1448
|
+
name: id,
|
|
1449
|
+
onInput: onInput,
|
|
1450
|
+
value: value,
|
|
1451
|
+
ref: editorRef,
|
|
1452
|
+
singleLine: singleLine,
|
|
1453
|
+
tooltipContainer: tooltipContainer
|
|
1454
|
+
})]
|
|
1455
|
+
})
|
|
1456
|
+
}), jsxRuntime.jsx(Popup.Footer, {
|
|
1457
|
+
children: jsxRuntime.jsx("button", {
|
|
1458
|
+
onClick: onClose,
|
|
1459
|
+
title: "Close pop-up editor",
|
|
1460
|
+
class: "bio-properties-panel-feel-popup__close-btn",
|
|
1461
|
+
children: "Close"
|
|
1462
|
+
})
|
|
1463
|
+
})]
|
|
1464
|
+
});
|
|
1465
|
+
}
|
|
1262
1466
|
|
|
1263
|
-
|
|
1264
|
-
//
|
|
1265
|
-
// TODO(marstamm): remove once we refactor layout handling for listGroups.
|
|
1266
|
-
// Ideally, opening should be handled as part of the `add` callback and
|
|
1267
|
-
// not be a concern for the ListGroup component.
|
|
1268
|
-
if (addTriggered && !open && shouldOpen) {
|
|
1269
|
-
toggleOpen();
|
|
1270
|
-
}
|
|
1467
|
+
// helpers /////////////////
|
|
1271
1468
|
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
newOrdering = createOrdering(sortItems(items));
|
|
1275
|
-
}
|
|
1276
|
-
|
|
1277
|
-
// add new items on top or bottom depending on sorting behavior
|
|
1278
|
-
newOrdering = newOrdering.filter(item => !add.includes(item));
|
|
1279
|
-
if (shouldSort) {
|
|
1280
|
-
newOrdering.unshift(...add);
|
|
1281
|
-
} else {
|
|
1282
|
-
newOrdering.push(...add);
|
|
1283
|
-
}
|
|
1284
|
-
setOrdering(newOrdering);
|
|
1285
|
-
setNewItemAdded(addTriggered);
|
|
1286
|
-
} else {
|
|
1287
|
-
setNewItemAdded(false);
|
|
1288
|
-
}
|
|
1289
|
-
}, [items, open, shouldHandleEffects, addTriggered]);
|
|
1290
|
-
|
|
1291
|
-
// (2) sort items on open if shouldSort is set
|
|
1292
|
-
hooks.useEffect(() => {
|
|
1293
|
-
if (shouldSort && open && !newItemAdded) {
|
|
1294
|
-
setOrdering(createOrdering(sortItems(items)));
|
|
1295
|
-
}
|
|
1296
|
-
}, [open, shouldSort]);
|
|
1297
|
-
|
|
1298
|
-
// (3) items were deleted
|
|
1299
|
-
hooks.useEffect(() => {
|
|
1300
|
-
if (shouldHandleEffects && prevItems && items.length < prevItems.length) {
|
|
1301
|
-
let keep = [];
|
|
1302
|
-
ordering.forEach(o => {
|
|
1303
|
-
if (getItem(items, o)) {
|
|
1304
|
-
keep.push(o);
|
|
1305
|
-
}
|
|
1306
|
-
});
|
|
1307
|
-
setOrdering(keep);
|
|
1308
|
-
}
|
|
1309
|
-
}, [items, shouldHandleEffects]);
|
|
1310
|
-
|
|
1311
|
-
// set css class when group is sticky to top
|
|
1312
|
-
useStickyIntersectionObserver(groupRef, 'div.bio-properties-panel-scroll-container', setSticky);
|
|
1313
|
-
const toggleOpen = () => setOpen(!open);
|
|
1314
|
-
const hasItems = !!items.length;
|
|
1315
|
-
const propertiesPanelContext = {
|
|
1316
|
-
...hooks.useContext(LayoutContext),
|
|
1317
|
-
onShow
|
|
1318
|
-
};
|
|
1319
|
-
const handleAddClick = e => {
|
|
1320
|
-
setAddTriggered(true);
|
|
1321
|
-
add(e);
|
|
1322
|
-
};
|
|
1323
|
-
const allErrors = useErrors();
|
|
1324
|
-
const hasError = items.some(item => {
|
|
1325
|
-
if (allErrors[item.id]) {
|
|
1326
|
-
return true;
|
|
1327
|
-
}
|
|
1328
|
-
if (!item.entries) {
|
|
1329
|
-
return;
|
|
1330
|
-
}
|
|
1331
|
-
|
|
1332
|
-
// also check if the error is nested, e.g. for name-value entries
|
|
1333
|
-
return item.entries.some(entry => allErrors[entry.id]);
|
|
1334
|
-
});
|
|
1335
|
-
return jsxRuntime.jsxs("div", {
|
|
1336
|
-
class: "bio-properties-panel-group",
|
|
1337
|
-
"data-group-id": 'group-' + id,
|
|
1338
|
-
ref: groupRef,
|
|
1339
|
-
children: [jsxRuntime.jsxs("div", {
|
|
1340
|
-
class: classnames__default["default"]('bio-properties-panel-group-header', hasItems ? '' : 'empty', hasItems && open ? 'open' : '', sticky && open ? 'sticky' : ''),
|
|
1341
|
-
onClick: hasItems ? toggleOpen : noop$3,
|
|
1342
|
-
children: [jsxRuntime.jsx("div", {
|
|
1343
|
-
title: label,
|
|
1344
|
-
class: "bio-properties-panel-group-header-title",
|
|
1345
|
-
children: jsxRuntime.jsx(TooltipWrapper, {
|
|
1346
|
-
value: props.tooltip,
|
|
1347
|
-
forId: 'group-' + id,
|
|
1348
|
-
element: element,
|
|
1349
|
-
parent: groupRef,
|
|
1350
|
-
children: label
|
|
1351
|
-
})
|
|
1352
|
-
}), jsxRuntime.jsxs("div", {
|
|
1353
|
-
class: "bio-properties-panel-group-header-buttons",
|
|
1354
|
-
children: [add ? jsxRuntime.jsxs("button", {
|
|
1355
|
-
title: "Create new list item",
|
|
1356
|
-
class: "bio-properties-panel-group-header-button bio-properties-panel-add-entry",
|
|
1357
|
-
onClick: handleAddClick,
|
|
1358
|
-
children: [jsxRuntime.jsx(CreateIcon, {}), !hasItems ? jsxRuntime.jsx("span", {
|
|
1359
|
-
class: "bio-properties-panel-add-entry-label",
|
|
1360
|
-
children: "Create"
|
|
1361
|
-
}) : null]
|
|
1362
|
-
}) : null, hasItems ? jsxRuntime.jsx("div", {
|
|
1363
|
-
title: `List contains ${items.length} item${items.length != 1 ? 's' : ''}`,
|
|
1364
|
-
class: classnames__default["default"]('bio-properties-panel-list-badge', hasError ? 'bio-properties-panel-list-badge--error' : ''),
|
|
1365
|
-
children: items.length
|
|
1366
|
-
}) : null, hasItems ? jsxRuntime.jsx("button", {
|
|
1367
|
-
title: "Toggle section",
|
|
1368
|
-
class: "bio-properties-panel-group-header-button bio-properties-panel-arrow",
|
|
1369
|
-
children: jsxRuntime.jsx(ArrowIcon, {
|
|
1370
|
-
class: open ? 'bio-properties-panel-arrow-down' : 'bio-properties-panel-arrow-right'
|
|
1371
|
-
})
|
|
1372
|
-
}) : null]
|
|
1373
|
-
})]
|
|
1374
|
-
}), jsxRuntime.jsx("div", {
|
|
1375
|
-
class: classnames__default["default"]('bio-properties-panel-list', open && hasItems ? 'open' : ''),
|
|
1376
|
-
children: jsxRuntime.jsx(LayoutContext.Provider, {
|
|
1377
|
-
value: propertiesPanelContext,
|
|
1378
|
-
children: ordering.map((o, index) => {
|
|
1379
|
-
const item = getItem(items, o);
|
|
1380
|
-
if (!item) {
|
|
1381
|
-
return;
|
|
1382
|
-
}
|
|
1383
|
-
const {
|
|
1384
|
-
id
|
|
1385
|
-
} = item;
|
|
1386
|
-
|
|
1387
|
-
// if item was added, open it
|
|
1388
|
-
// Existing items will not be affected as autoOpen is only applied on first render
|
|
1389
|
-
const autoOpen = newItemAdded;
|
|
1390
|
-
return preact.createElement(ListItem, {
|
|
1391
|
-
...item,
|
|
1392
|
-
autoOpen: autoOpen,
|
|
1393
|
-
element: element,
|
|
1394
|
-
index: index,
|
|
1395
|
-
key: id
|
|
1396
|
-
});
|
|
1397
|
-
})
|
|
1398
|
-
})
|
|
1399
|
-
})]
|
|
1400
|
-
});
|
|
1401
|
-
}
|
|
1402
|
-
|
|
1403
|
-
// helpers ////////////////////
|
|
1404
|
-
|
|
1405
|
-
/**
|
|
1406
|
-
* Sorts given items alphanumeric by label
|
|
1407
|
-
*/
|
|
1408
|
-
function sortItems(items) {
|
|
1409
|
-
return minDash.sortBy(items, i => i.label.toLowerCase());
|
|
1410
|
-
}
|
|
1411
|
-
function getItem(items, id) {
|
|
1412
|
-
return minDash.find(items, i => i.id === id);
|
|
1413
|
-
}
|
|
1414
|
-
function createOrdering(items) {
|
|
1415
|
-
return items.map(i => i.id);
|
|
1416
|
-
}
|
|
1417
|
-
|
|
1418
|
-
function Description(props) {
|
|
1419
|
-
const {
|
|
1420
|
-
element,
|
|
1421
|
-
forId,
|
|
1422
|
-
value
|
|
1423
|
-
} = props;
|
|
1424
|
-
const contextDescription = useDescriptionContext(forId, element);
|
|
1425
|
-
const description = value || contextDescription;
|
|
1426
|
-
if (description) {
|
|
1427
|
-
return jsxRuntime.jsx("div", {
|
|
1428
|
-
class: "bio-properties-panel-description",
|
|
1429
|
-
children: description
|
|
1430
|
-
});
|
|
1431
|
-
}
|
|
1469
|
+
function prefixId$8(id) {
|
|
1470
|
+
return `bio-properties-panel-${id}`;
|
|
1432
1471
|
}
|
|
1433
1472
|
|
|
1434
|
-
function
|
|
1473
|
+
function ToggleSwitch(props) {
|
|
1435
1474
|
const {
|
|
1436
1475
|
id,
|
|
1437
1476
|
label,
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1477
|
+
onInput,
|
|
1478
|
+
value,
|
|
1479
|
+
switcherLabel,
|
|
1480
|
+
inline,
|
|
1441
1481
|
onFocus,
|
|
1442
1482
|
onBlur,
|
|
1483
|
+
inputRef,
|
|
1443
1484
|
tooltip
|
|
1444
1485
|
} = props;
|
|
1445
1486
|
const [localValue, setLocalValue] = hooks.useState(value);
|
|
1446
|
-
const
|
|
1447
|
-
|
|
1448
|
-
}) => {
|
|
1449
|
-
onChange(target.checked);
|
|
1487
|
+
const handleInputCallback = async () => {
|
|
1488
|
+
onInput(!value);
|
|
1450
1489
|
};
|
|
1451
|
-
const
|
|
1452
|
-
|
|
1490
|
+
const handleInput = e => {
|
|
1491
|
+
handleInputCallback();
|
|
1453
1492
|
setLocalValue(e.target.value);
|
|
1454
1493
|
};
|
|
1455
1494
|
hooks.useEffect(() => {
|
|
@@ -1458,29 +1497,40 @@ function Checkbox(props) {
|
|
|
1458
1497
|
}
|
|
1459
1498
|
setLocalValue(value);
|
|
1460
1499
|
}, [value]);
|
|
1461
|
-
const ref = useShowEntryEvent(id);
|
|
1462
1500
|
return jsxRuntime.jsxs("div", {
|
|
1463
|
-
class: "bio-properties-panel-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
name: id,
|
|
1468
|
-
onFocus: onFocus,
|
|
1469
|
-
onBlur: onBlur,
|
|
1470
|
-
type: "checkbox",
|
|
1471
|
-
class: "bio-properties-panel-input",
|
|
1472
|
-
onChange: handleChange,
|
|
1473
|
-
checked: localValue,
|
|
1474
|
-
disabled: disabled
|
|
1475
|
-
}), jsxRuntime.jsx("label", {
|
|
1476
|
-
for: prefixId$7(id),
|
|
1501
|
+
class: classnames__default["default"]('bio-properties-panel-toggle-switch', {
|
|
1502
|
+
inline
|
|
1503
|
+
}),
|
|
1504
|
+
children: [jsxRuntime.jsx("label", {
|
|
1477
1505
|
class: "bio-properties-panel-label",
|
|
1506
|
+
for: prefixId$7(id),
|
|
1478
1507
|
children: jsxRuntime.jsx(TooltipWrapper, {
|
|
1479
1508
|
value: tooltip,
|
|
1480
1509
|
forId: id,
|
|
1481
1510
|
element: props.element,
|
|
1482
1511
|
children: label
|
|
1483
1512
|
})
|
|
1513
|
+
}), jsxRuntime.jsxs("div", {
|
|
1514
|
+
class: "bio-properties-panel-field-wrapper",
|
|
1515
|
+
children: [jsxRuntime.jsxs("label", {
|
|
1516
|
+
class: "bio-properties-panel-toggle-switch__switcher",
|
|
1517
|
+
children: [jsxRuntime.jsx("input", {
|
|
1518
|
+
ref: inputRef,
|
|
1519
|
+
id: prefixId$7(id),
|
|
1520
|
+
class: "bio-properties-panel-input",
|
|
1521
|
+
type: "checkbox",
|
|
1522
|
+
onFocus: onFocus,
|
|
1523
|
+
onBlur: onBlur,
|
|
1524
|
+
name: id,
|
|
1525
|
+
onInput: handleInput,
|
|
1526
|
+
checked: !!localValue
|
|
1527
|
+
}), jsxRuntime.jsx("span", {
|
|
1528
|
+
class: "bio-properties-panel-toggle-switch__slider"
|
|
1529
|
+
})]
|
|
1530
|
+
}), switcherLabel && jsxRuntime.jsx("p", {
|
|
1531
|
+
class: "bio-properties-panel-toggle-switch__label",
|
|
1532
|
+
children: switcherLabel
|
|
1533
|
+
})]
|
|
1484
1534
|
})]
|
|
1485
1535
|
});
|
|
1486
1536
|
}
|
|
@@ -1491,44 +1541,43 @@ function Checkbox(props) {
|
|
|
1491
1541
|
* @param {String} props.id
|
|
1492
1542
|
* @param {String} props.description
|
|
1493
1543
|
* @param {String} props.label
|
|
1544
|
+
* @param {String} props.switcherLabel
|
|
1545
|
+
* @param {Boolean} props.inline
|
|
1494
1546
|
* @param {Function} props.getValue
|
|
1495
1547
|
* @param {Function} props.setValue
|
|
1496
1548
|
* @param {Function} props.onFocus
|
|
1497
1549
|
* @param {Function} props.onBlur
|
|
1498
1550
|
* @param {string|import('preact').Component} props.tooltip
|
|
1499
|
-
* @param {boolean} [props.disabled]
|
|
1500
1551
|
*/
|
|
1501
|
-
function
|
|
1552
|
+
function ToggleSwitchEntry(props) {
|
|
1502
1553
|
const {
|
|
1503
1554
|
element,
|
|
1504
1555
|
id,
|
|
1505
1556
|
description,
|
|
1506
1557
|
label,
|
|
1558
|
+
switcherLabel,
|
|
1559
|
+
inline,
|
|
1507
1560
|
getValue,
|
|
1508
1561
|
setValue,
|
|
1509
|
-
disabled,
|
|
1510
1562
|
onFocus,
|
|
1511
1563
|
onBlur,
|
|
1512
1564
|
tooltip
|
|
1513
1565
|
} = props;
|
|
1514
1566
|
const value = getValue(element);
|
|
1515
|
-
const error = useError(id);
|
|
1516
1567
|
return jsxRuntime.jsxs("div", {
|
|
1517
|
-
class: "bio-properties-panel-entry bio-properties-panel-
|
|
1568
|
+
class: "bio-properties-panel-entry bio-properties-panel-toggle-switch-entry",
|
|
1518
1569
|
"data-entry-id": id,
|
|
1519
|
-
children: [jsxRuntime.jsx(
|
|
1520
|
-
disabled: disabled,
|
|
1570
|
+
children: [jsxRuntime.jsx(ToggleSwitch, {
|
|
1521
1571
|
id: id,
|
|
1522
1572
|
label: label,
|
|
1523
|
-
|
|
1573
|
+
value: value,
|
|
1574
|
+
onInput: setValue,
|
|
1524
1575
|
onFocus: onFocus,
|
|
1525
1576
|
onBlur: onBlur,
|
|
1526
|
-
|
|
1577
|
+
switcherLabel: switcherLabel,
|
|
1578
|
+
inline: inline,
|
|
1527
1579
|
tooltip: tooltip,
|
|
1528
1580
|
element: element
|
|
1529
|
-
}, element), error && jsxRuntime.jsx("div", {
|
|
1530
|
-
class: "bio-properties-panel-error",
|
|
1531
|
-
children: error
|
|
1532
1581
|
}), jsxRuntime.jsx(Description, {
|
|
1533
1582
|
forId: id,
|
|
1534
1583
|
element: element,
|
|
@@ -1546,450 +1595,94 @@ function prefixId$7(id) {
|
|
|
1546
1595
|
return `bio-properties-panel-${id}`;
|
|
1547
1596
|
}
|
|
1548
1597
|
|
|
1549
|
-
|
|
1550
|
-
const [buffer, setBuffer] = hooks.useState(undefined);
|
|
1551
|
-
ref.current = hooks.useMemo(() => ({
|
|
1552
|
-
focus: offset => {
|
|
1553
|
-
if (editor) {
|
|
1554
|
-
editor.focus(offset);
|
|
1555
|
-
} else {
|
|
1556
|
-
if (typeof offset === 'undefined') {
|
|
1557
|
-
offset = Infinity;
|
|
1558
|
-
}
|
|
1559
|
-
setBuffer(offset);
|
|
1560
|
-
}
|
|
1561
|
-
}
|
|
1562
|
-
}), [editor]);
|
|
1563
|
-
hooks.useEffect(() => {
|
|
1564
|
-
if (typeof buffer !== 'undefined' && editor) {
|
|
1565
|
-
editor.focus(buffer);
|
|
1566
|
-
setBuffer(false);
|
|
1567
|
-
}
|
|
1568
|
-
}, [editor, buffer]);
|
|
1569
|
-
};
|
|
1570
|
-
const CodeEditor$1 = compat.forwardRef((props, ref) => {
|
|
1598
|
+
function NumberField(props) {
|
|
1571
1599
|
const {
|
|
1572
|
-
|
|
1600
|
+
debounce,
|
|
1573
1601
|
disabled,
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
singleLine = false
|
|
1581
|
-
} = props;
|
|
1582
|
-
const inputRef = hooks.useRef();
|
|
1583
|
-
const [editor, setEditor] = hooks.useState();
|
|
1584
|
-
const [localValue, setLocalValue] = hooks.useState(value || '');
|
|
1585
|
-
useBufferedFocus$1(editor, ref);
|
|
1586
|
-
const handleInput = useStaticCallback(newValue => {
|
|
1587
|
-
onInput(newValue);
|
|
1588
|
-
setLocalValue(newValue);
|
|
1589
|
-
});
|
|
1590
|
-
hooks.useEffect(() => {
|
|
1591
|
-
let editor;
|
|
1592
|
-
editor = new feelers.FeelersEditor({
|
|
1593
|
-
container: inputRef.current,
|
|
1594
|
-
onChange: handleInput,
|
|
1595
|
-
value: localValue,
|
|
1596
|
-
onLint,
|
|
1597
|
-
contentAttributes,
|
|
1598
|
-
tooltipContainer,
|
|
1599
|
-
enableGutters,
|
|
1600
|
-
hostLanguage,
|
|
1601
|
-
singleLine
|
|
1602
|
-
});
|
|
1603
|
-
setEditor(editor);
|
|
1604
|
-
return () => {
|
|
1605
|
-
onLint([]);
|
|
1606
|
-
inputRef.current.innerHTML = '';
|
|
1607
|
-
setEditor(null);
|
|
1608
|
-
};
|
|
1609
|
-
}, []);
|
|
1610
|
-
hooks.useEffect(() => {
|
|
1611
|
-
if (!editor) {
|
|
1612
|
-
return;
|
|
1613
|
-
}
|
|
1614
|
-
if (value === localValue) {
|
|
1615
|
-
return;
|
|
1616
|
-
}
|
|
1617
|
-
editor.setValue(value);
|
|
1618
|
-
setLocalValue(value);
|
|
1619
|
-
}, [value]);
|
|
1620
|
-
const handleClick = () => {
|
|
1621
|
-
ref.current.focus();
|
|
1622
|
-
};
|
|
1623
|
-
return jsxRuntime.jsx("div", {
|
|
1624
|
-
name: props.name,
|
|
1625
|
-
class: classnames__default["default"]('bio-properties-panel-feelers-editor bio-properties-panel-input', localValue ? 'edited' : null, disabled ? 'disabled' : null),
|
|
1626
|
-
ref: inputRef,
|
|
1627
|
-
onClick: handleClick
|
|
1628
|
-
});
|
|
1629
|
-
});
|
|
1630
|
-
|
|
1631
|
-
const useBufferedFocus = function (editor, ref) {
|
|
1632
|
-
const [buffer, setBuffer] = hooks.useState(undefined);
|
|
1633
|
-
ref.current = hooks.useMemo(() => ({
|
|
1634
|
-
focus: offset => {
|
|
1635
|
-
if (editor) {
|
|
1636
|
-
editor.focus(offset);
|
|
1637
|
-
} else {
|
|
1638
|
-
if (typeof offset === 'undefined') {
|
|
1639
|
-
offset = Infinity;
|
|
1640
|
-
}
|
|
1641
|
-
setBuffer(offset);
|
|
1642
|
-
}
|
|
1643
|
-
}
|
|
1644
|
-
}), [editor]);
|
|
1645
|
-
hooks.useEffect(() => {
|
|
1646
|
-
if (typeof buffer !== 'undefined' && editor) {
|
|
1647
|
-
editor.focus(buffer);
|
|
1648
|
-
setBuffer(false);
|
|
1649
|
-
}
|
|
1650
|
-
}, [editor, buffer]);
|
|
1651
|
-
};
|
|
1652
|
-
const CodeEditor = compat.forwardRef((props, ref) => {
|
|
1653
|
-
const {
|
|
1654
|
-
value,
|
|
1602
|
+
displayLabel = true,
|
|
1603
|
+
id,
|
|
1604
|
+
inputRef,
|
|
1605
|
+
label,
|
|
1606
|
+
max,
|
|
1607
|
+
min,
|
|
1655
1608
|
onInput,
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
variables
|
|
1609
|
+
step,
|
|
1610
|
+
value = '',
|
|
1611
|
+
onFocus,
|
|
1612
|
+
onBlur
|
|
1661
1613
|
} = props;
|
|
1662
|
-
const
|
|
1663
|
-
const
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
let editor;
|
|
1672
|
-
|
|
1673
|
-
/* Trigger FEEL toggle when
|
|
1674
|
-
*
|
|
1675
|
-
* - `backspace` is pressed
|
|
1676
|
-
* - AND the cursor is at the beginning of the input
|
|
1677
|
-
*/
|
|
1678
|
-
const onKeyDown = e => {
|
|
1679
|
-
if (e.key !== 'Backspace' || !editor) {
|
|
1680
|
-
return;
|
|
1681
|
-
}
|
|
1682
|
-
const selection = editor.getSelection();
|
|
1683
|
-
const range = selection.ranges[selection.mainIndex];
|
|
1684
|
-
if (range.from === 0 && range.to === 0) {
|
|
1685
|
-
onFeelToggle();
|
|
1614
|
+
const [localValue, setLocalValue] = hooks.useState(value);
|
|
1615
|
+
const handleInputCallback = hooks.useMemo(() => {
|
|
1616
|
+
return debounce(event => {
|
|
1617
|
+
const {
|
|
1618
|
+
validity,
|
|
1619
|
+
value
|
|
1620
|
+
} = event.target;
|
|
1621
|
+
if (validity.valid) {
|
|
1622
|
+
onInput(value ? parseFloat(value) : undefined);
|
|
1686
1623
|
}
|
|
1687
|
-
};
|
|
1688
|
-
editor = new FeelEditor__default["default"]({
|
|
1689
|
-
container: inputRef.current,
|
|
1690
|
-
onChange: handleInput,
|
|
1691
|
-
onKeyDown: onKeyDown,
|
|
1692
|
-
onLint: onLint,
|
|
1693
|
-
tooltipContainer: tooltipContainer,
|
|
1694
|
-
value: localValue,
|
|
1695
|
-
variables: variables
|
|
1696
1624
|
});
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
};
|
|
1703
|
-
}, []);
|
|
1625
|
+
}, [onInput, debounce]);
|
|
1626
|
+
const handleInput = e => {
|
|
1627
|
+
handleInputCallback(e);
|
|
1628
|
+
setLocalValue(e.target.value);
|
|
1629
|
+
};
|
|
1704
1630
|
hooks.useEffect(() => {
|
|
1705
|
-
if (!editor) {
|
|
1706
|
-
return;
|
|
1707
|
-
}
|
|
1708
1631
|
if (value === localValue) {
|
|
1709
1632
|
return;
|
|
1710
1633
|
}
|
|
1711
|
-
editor.setValue(value);
|
|
1712
1634
|
setLocalValue(value);
|
|
1713
1635
|
}, [value]);
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
};
|
|
1723
|
-
return jsxRuntime.jsx("div", {
|
|
1724
|
-
class: classnames__default["default"]('bio-properties-panel-feel-editor-container', disabled ? 'disabled' : null),
|
|
1725
|
-
children: jsxRuntime.jsx("div", {
|
|
1726
|
-
name: props.name,
|
|
1727
|
-
class: classnames__default["default"]('bio-properties-panel-input', localValue ? 'edited' : null),
|
|
1636
|
+
return jsxRuntime.jsxs("div", {
|
|
1637
|
+
class: "bio-properties-panel-numberfield",
|
|
1638
|
+
children: [displayLabel && jsxRuntime.jsx("label", {
|
|
1639
|
+
for: prefixId$6(id),
|
|
1640
|
+
class: "bio-properties-panel-label",
|
|
1641
|
+
children: label
|
|
1642
|
+
}), jsxRuntime.jsx("input", {
|
|
1643
|
+
id: prefixId$6(id),
|
|
1728
1644
|
ref: inputRef,
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
children: "="
|
|
1645
|
+
type: "number",
|
|
1646
|
+
name: id,
|
|
1647
|
+
spellCheck: "false",
|
|
1648
|
+
autoComplete: "off",
|
|
1649
|
+
disabled: disabled,
|
|
1650
|
+
class: "bio-properties-panel-input",
|
|
1651
|
+
max: max,
|
|
1652
|
+
min: min,
|
|
1653
|
+
onInput: handleInput,
|
|
1654
|
+
onFocus: onFocus,
|
|
1655
|
+
onBlur: onBlur,
|
|
1656
|
+
step: step,
|
|
1657
|
+
value: localValue
|
|
1658
|
+
})]
|
|
1744
1659
|
});
|
|
1745
1660
|
}
|
|
1746
1661
|
|
|
1747
|
-
const noop$2 = () => {};
|
|
1748
|
-
|
|
1749
1662
|
/**
|
|
1750
1663
|
* @param {Object} props
|
|
1751
|
-
* @param {
|
|
1752
|
-
* @param {String} props.
|
|
1664
|
+
* @param {Boolean} props.debounce
|
|
1665
|
+
* @param {String} props.description
|
|
1666
|
+
* @param {Boolean} props.disabled
|
|
1667
|
+
* @param {Object} props.element
|
|
1668
|
+
* @param {Function} props.getValue
|
|
1669
|
+
* @param {String} props.id
|
|
1670
|
+
* @param {String} props.label
|
|
1671
|
+
* @param {String} props.max
|
|
1672
|
+
* @param {String} props.min
|
|
1673
|
+
* @param {Function} props.setValue
|
|
1674
|
+
* @param {Function} props.onFocus
|
|
1675
|
+
* @param {Function} props.onBlur
|
|
1676
|
+
* @param {String} props.step
|
|
1677
|
+
* @param {Function} props.validate
|
|
1753
1678
|
*/
|
|
1754
|
-
function
|
|
1755
|
-
const {
|
|
1756
|
-
feel = false,
|
|
1757
|
-
active,
|
|
1758
|
-
disabled = false,
|
|
1759
|
-
onClick = noop$2
|
|
1760
|
-
} = props;
|
|
1761
|
-
const feelRequiredLabel = 'FEEL expression is mandatory';
|
|
1762
|
-
const feelOptionalLabel = `Click to ${active ? 'remove' : 'set a'} dynamic value with FEEL expression`;
|
|
1763
|
-
const handleClick = e => {
|
|
1764
|
-
onClick(e);
|
|
1765
|
-
|
|
1766
|
-
// when pointer event was created from keyboard, keep focus on button
|
|
1767
|
-
if (!e.pointerType) {
|
|
1768
|
-
e.stopPropagation();
|
|
1769
|
-
}
|
|
1770
|
-
};
|
|
1771
|
-
return jsxRuntime.jsx("button", {
|
|
1772
|
-
class: classnames__default["default"]('bio-properties-panel-feel-icon', active ? 'active' : null, feel === 'required' ? 'required' : 'optional'),
|
|
1773
|
-
onClick: handleClick,
|
|
1774
|
-
disabled: feel === 'required' || disabled,
|
|
1775
|
-
title: feel === 'required' ? feelRequiredLabel : feelOptionalLabel,
|
|
1776
|
-
children: jsxRuntime.jsx(FeelIcon$1, {})
|
|
1777
|
-
});
|
|
1778
|
-
}
|
|
1779
|
-
|
|
1780
|
-
function ToggleSwitch(props) {
|
|
1679
|
+
function NumberFieldEntry(props) {
|
|
1781
1680
|
const {
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
inline,
|
|
1788
|
-
onFocus,
|
|
1789
|
-
onBlur,
|
|
1790
|
-
inputRef,
|
|
1791
|
-
tooltip
|
|
1792
|
-
} = props;
|
|
1793
|
-
const [localValue, setLocalValue] = hooks.useState(value);
|
|
1794
|
-
const handleInputCallback = async () => {
|
|
1795
|
-
onInput(!value);
|
|
1796
|
-
};
|
|
1797
|
-
const handleInput = e => {
|
|
1798
|
-
handleInputCallback();
|
|
1799
|
-
setLocalValue(e.target.value);
|
|
1800
|
-
};
|
|
1801
|
-
hooks.useEffect(() => {
|
|
1802
|
-
if (value === localValue) {
|
|
1803
|
-
return;
|
|
1804
|
-
}
|
|
1805
|
-
setLocalValue(value);
|
|
1806
|
-
}, [value]);
|
|
1807
|
-
return jsxRuntime.jsxs("div", {
|
|
1808
|
-
class: classnames__default["default"]('bio-properties-panel-toggle-switch', {
|
|
1809
|
-
inline
|
|
1810
|
-
}),
|
|
1811
|
-
children: [jsxRuntime.jsx("label", {
|
|
1812
|
-
class: "bio-properties-panel-label",
|
|
1813
|
-
for: prefixId$6(id),
|
|
1814
|
-
children: jsxRuntime.jsx(TooltipWrapper, {
|
|
1815
|
-
value: tooltip,
|
|
1816
|
-
forId: id,
|
|
1817
|
-
element: props.element,
|
|
1818
|
-
children: label
|
|
1819
|
-
})
|
|
1820
|
-
}), jsxRuntime.jsxs("div", {
|
|
1821
|
-
class: "bio-properties-panel-field-wrapper",
|
|
1822
|
-
children: [jsxRuntime.jsxs("label", {
|
|
1823
|
-
class: "bio-properties-panel-toggle-switch__switcher",
|
|
1824
|
-
children: [jsxRuntime.jsx("input", {
|
|
1825
|
-
ref: inputRef,
|
|
1826
|
-
id: prefixId$6(id),
|
|
1827
|
-
class: "bio-properties-panel-input",
|
|
1828
|
-
type: "checkbox",
|
|
1829
|
-
onFocus: onFocus,
|
|
1830
|
-
onBlur: onBlur,
|
|
1831
|
-
name: id,
|
|
1832
|
-
onInput: handleInput,
|
|
1833
|
-
checked: !!localValue
|
|
1834
|
-
}), jsxRuntime.jsx("span", {
|
|
1835
|
-
class: "bio-properties-panel-toggle-switch__slider"
|
|
1836
|
-
})]
|
|
1837
|
-
}), switcherLabel && jsxRuntime.jsx("p", {
|
|
1838
|
-
class: "bio-properties-panel-toggle-switch__label",
|
|
1839
|
-
children: switcherLabel
|
|
1840
|
-
})]
|
|
1841
|
-
})]
|
|
1842
|
-
});
|
|
1843
|
-
}
|
|
1844
|
-
|
|
1845
|
-
/**
|
|
1846
|
-
* @param {Object} props
|
|
1847
|
-
* @param {Object} props.element
|
|
1848
|
-
* @param {String} props.id
|
|
1849
|
-
* @param {String} props.description
|
|
1850
|
-
* @param {String} props.label
|
|
1851
|
-
* @param {String} props.switcherLabel
|
|
1852
|
-
* @param {Boolean} props.inline
|
|
1853
|
-
* @param {Function} props.getValue
|
|
1854
|
-
* @param {Function} props.setValue
|
|
1855
|
-
* @param {Function} props.onFocus
|
|
1856
|
-
* @param {Function} props.onBlur
|
|
1857
|
-
* @param {string|import('preact').Component} props.tooltip
|
|
1858
|
-
*/
|
|
1859
|
-
function ToggleSwitchEntry(props) {
|
|
1860
|
-
const {
|
|
1861
|
-
element,
|
|
1862
|
-
id,
|
|
1863
|
-
description,
|
|
1864
|
-
label,
|
|
1865
|
-
switcherLabel,
|
|
1866
|
-
inline,
|
|
1867
|
-
getValue,
|
|
1868
|
-
setValue,
|
|
1869
|
-
onFocus,
|
|
1870
|
-
onBlur,
|
|
1871
|
-
tooltip
|
|
1872
|
-
} = props;
|
|
1873
|
-
const value = getValue(element);
|
|
1874
|
-
return jsxRuntime.jsxs("div", {
|
|
1875
|
-
class: "bio-properties-panel-entry bio-properties-panel-toggle-switch-entry",
|
|
1876
|
-
"data-entry-id": id,
|
|
1877
|
-
children: [jsxRuntime.jsx(ToggleSwitch, {
|
|
1878
|
-
id: id,
|
|
1879
|
-
label: label,
|
|
1880
|
-
value: value,
|
|
1881
|
-
onInput: setValue,
|
|
1882
|
-
onFocus: onFocus,
|
|
1883
|
-
onBlur: onBlur,
|
|
1884
|
-
switcherLabel: switcherLabel,
|
|
1885
|
-
inline: inline,
|
|
1886
|
-
tooltip: tooltip,
|
|
1887
|
-
element: element
|
|
1888
|
-
}), jsxRuntime.jsx(Description, {
|
|
1889
|
-
forId: id,
|
|
1890
|
-
element: element,
|
|
1891
|
-
value: description
|
|
1892
|
-
})]
|
|
1893
|
-
});
|
|
1894
|
-
}
|
|
1895
|
-
function isEdited$7(node) {
|
|
1896
|
-
return node && !!node.checked;
|
|
1897
|
-
}
|
|
1898
|
-
|
|
1899
|
-
// helpers /////////////////
|
|
1900
|
-
|
|
1901
|
-
function prefixId$6(id) {
|
|
1902
|
-
return `bio-properties-panel-${id}`;
|
|
1903
|
-
}
|
|
1904
|
-
|
|
1905
|
-
function NumberField(props) {
|
|
1906
|
-
const {
|
|
1907
|
-
debounce,
|
|
1908
|
-
disabled,
|
|
1909
|
-
displayLabel = true,
|
|
1910
|
-
id,
|
|
1911
|
-
inputRef,
|
|
1912
|
-
label,
|
|
1913
|
-
max,
|
|
1914
|
-
min,
|
|
1915
|
-
onInput,
|
|
1916
|
-
step,
|
|
1917
|
-
value = '',
|
|
1918
|
-
onFocus,
|
|
1919
|
-
onBlur
|
|
1920
|
-
} = props;
|
|
1921
|
-
const [localValue, setLocalValue] = hooks.useState(value);
|
|
1922
|
-
const handleInputCallback = hooks.useMemo(() => {
|
|
1923
|
-
return debounce(event => {
|
|
1924
|
-
const {
|
|
1925
|
-
validity,
|
|
1926
|
-
value
|
|
1927
|
-
} = event.target;
|
|
1928
|
-
if (validity.valid) {
|
|
1929
|
-
onInput(value ? parseFloat(value) : undefined);
|
|
1930
|
-
}
|
|
1931
|
-
});
|
|
1932
|
-
}, [onInput, debounce]);
|
|
1933
|
-
const handleInput = e => {
|
|
1934
|
-
handleInputCallback(e);
|
|
1935
|
-
setLocalValue(e.target.value);
|
|
1936
|
-
};
|
|
1937
|
-
hooks.useEffect(() => {
|
|
1938
|
-
if (value === localValue) {
|
|
1939
|
-
return;
|
|
1940
|
-
}
|
|
1941
|
-
setLocalValue(value);
|
|
1942
|
-
}, [value]);
|
|
1943
|
-
return jsxRuntime.jsxs("div", {
|
|
1944
|
-
class: "bio-properties-panel-numberfield",
|
|
1945
|
-
children: [displayLabel && jsxRuntime.jsx("label", {
|
|
1946
|
-
for: prefixId$5(id),
|
|
1947
|
-
class: "bio-properties-panel-label",
|
|
1948
|
-
children: label
|
|
1949
|
-
}), jsxRuntime.jsx("input", {
|
|
1950
|
-
id: prefixId$5(id),
|
|
1951
|
-
ref: inputRef,
|
|
1952
|
-
type: "number",
|
|
1953
|
-
name: id,
|
|
1954
|
-
spellCheck: "false",
|
|
1955
|
-
autoComplete: "off",
|
|
1956
|
-
disabled: disabled,
|
|
1957
|
-
class: "bio-properties-panel-input",
|
|
1958
|
-
max: max,
|
|
1959
|
-
min: min,
|
|
1960
|
-
onInput: handleInput,
|
|
1961
|
-
onFocus: onFocus,
|
|
1962
|
-
onBlur: onBlur,
|
|
1963
|
-
step: step,
|
|
1964
|
-
value: localValue
|
|
1965
|
-
})]
|
|
1966
|
-
});
|
|
1967
|
-
}
|
|
1968
|
-
|
|
1969
|
-
/**
|
|
1970
|
-
* @param {Object} props
|
|
1971
|
-
* @param {Boolean} props.debounce
|
|
1972
|
-
* @param {String} props.description
|
|
1973
|
-
* @param {Boolean} props.disabled
|
|
1974
|
-
* @param {Object} props.element
|
|
1975
|
-
* @param {Function} props.getValue
|
|
1976
|
-
* @param {String} props.id
|
|
1977
|
-
* @param {String} props.label
|
|
1978
|
-
* @param {String} props.max
|
|
1979
|
-
* @param {String} props.min
|
|
1980
|
-
* @param {Function} props.setValue
|
|
1981
|
-
* @param {Function} props.onFocus
|
|
1982
|
-
* @param {Function} props.onBlur
|
|
1983
|
-
* @param {String} props.step
|
|
1984
|
-
* @param {Function} props.validate
|
|
1985
|
-
*/
|
|
1986
|
-
function NumberFieldEntry(props) {
|
|
1987
|
-
const {
|
|
1988
|
-
debounce,
|
|
1989
|
-
description,
|
|
1990
|
-
disabled,
|
|
1991
|
-
element,
|
|
1992
|
-
getValue,
|
|
1681
|
+
debounce,
|
|
1682
|
+
description,
|
|
1683
|
+
disabled,
|
|
1684
|
+
element,
|
|
1685
|
+
getValue,
|
|
1993
1686
|
id,
|
|
1994
1687
|
label,
|
|
1995
1688
|
max,
|
|
@@ -2043,28 +1736,31 @@ function NumberFieldEntry(props) {
|
|
|
2043
1736
|
})]
|
|
2044
1737
|
});
|
|
2045
1738
|
}
|
|
2046
|
-
function isEdited$
|
|
1739
|
+
function isEdited$7(node) {
|
|
2047
1740
|
return node && !!node.value;
|
|
2048
1741
|
}
|
|
2049
1742
|
|
|
2050
1743
|
// helpers /////////////////
|
|
2051
1744
|
|
|
2052
|
-
function prefixId$
|
|
1745
|
+
function prefixId$6(id) {
|
|
2053
1746
|
return `bio-properties-panel-${id}`;
|
|
2054
1747
|
}
|
|
2055
1748
|
|
|
2056
|
-
const noop$
|
|
1749
|
+
const noop$2 = () => {};
|
|
2057
1750
|
function FeelTextfield(props) {
|
|
2058
1751
|
const {
|
|
2059
1752
|
debounce,
|
|
2060
1753
|
id,
|
|
1754
|
+
element,
|
|
2061
1755
|
label,
|
|
1756
|
+
hostLanguage,
|
|
2062
1757
|
onInput,
|
|
2063
1758
|
onError,
|
|
2064
1759
|
feel,
|
|
2065
1760
|
value = '',
|
|
2066
1761
|
disabled = false,
|
|
2067
1762
|
variables,
|
|
1763
|
+
singleLine,
|
|
2068
1764
|
tooltipContainer,
|
|
2069
1765
|
OptionalComponent = OptionalFeelInput,
|
|
2070
1766
|
tooltip
|
|
@@ -2075,6 +1771,11 @@ function FeelTextfield(props) {
|
|
|
2075
1771
|
const feelActive = minDash.isString(localValue) && localValue.startsWith('=') || feel === 'required';
|
|
2076
1772
|
const feelOnlyValue = minDash.isString(localValue) && localValue.startsWith('=') ? localValue.substring(1) : localValue;
|
|
2077
1773
|
const [focus, _setFocus] = hooks.useState(undefined);
|
|
1774
|
+
const {
|
|
1775
|
+
open: openPopup,
|
|
1776
|
+
source: popupSource
|
|
1777
|
+
} = hooks.useContext(FeelPopupContext);
|
|
1778
|
+
const popuOpen = popupSource === id;
|
|
2078
1779
|
const setFocus = (offset = 0) => {
|
|
2079
1780
|
const hasFocus = containerRef.current.contains(document.activeElement);
|
|
2080
1781
|
|
|
@@ -2127,6 +1828,21 @@ function FeelTextfield(props) {
|
|
|
2127
1828
|
const message = `${error.source}: ${error.message}`;
|
|
2128
1829
|
onError(message);
|
|
2129
1830
|
});
|
|
1831
|
+
const handlePopupOpen = (type = 'feel') => {
|
|
1832
|
+
const popupOptions = {
|
|
1833
|
+
id,
|
|
1834
|
+
hostLanguage,
|
|
1835
|
+
onInput: handleLocalInput,
|
|
1836
|
+
position: calculatePopupPosition(containerRef.current),
|
|
1837
|
+
singleLine,
|
|
1838
|
+
title: getPopupTitle(element, label),
|
|
1839
|
+
tooltipContainer,
|
|
1840
|
+
type,
|
|
1841
|
+
value: feelOnlyValue,
|
|
1842
|
+
variables
|
|
1843
|
+
};
|
|
1844
|
+
openPopup(id, popupOptions, editorRef.current);
|
|
1845
|
+
};
|
|
2130
1846
|
hooks.useEffect(() => {
|
|
2131
1847
|
if (typeof focus !== 'undefined') {
|
|
2132
1848
|
editorRef.current.focus(focus);
|
|
@@ -2155,7 +1871,7 @@ function FeelTextfield(props) {
|
|
|
2155
1871
|
event.clipboardData.setData('application/FEEL', event.clipboardData.getData('text'));
|
|
2156
1872
|
};
|
|
2157
1873
|
const pasteHandler = event => {
|
|
2158
|
-
if (feelActive) {
|
|
1874
|
+
if (feelActive || popuOpen) {
|
|
2159
1875
|
return;
|
|
2160
1876
|
}
|
|
2161
1877
|
const data = event.clipboardData.getData('application/FEEL');
|
|
@@ -2180,7 +1896,7 @@ function FeelTextfield(props) {
|
|
|
2180
1896
|
'feel-active': feelActive
|
|
2181
1897
|
}),
|
|
2182
1898
|
children: [jsxRuntime.jsxs("label", {
|
|
2183
|
-
for: prefixId$
|
|
1899
|
+
for: prefixId$5(id),
|
|
2184
1900
|
class: "bio-properties-panel-label",
|
|
2185
1901
|
onClick: () => setFocus(),
|
|
2186
1902
|
children: [jsxRuntime.jsx(TooltipWrapper, {
|
|
@@ -2202,28 +1918,33 @@ function FeelTextfield(props) {
|
|
|
2202
1918
|
disabled: feel !== 'optional' || disabled,
|
|
2203
1919
|
onClick: handleFeelToggle
|
|
2204
1920
|
}), feelActive ? jsxRuntime.jsx(CodeEditor, {
|
|
2205
|
-
id: prefixId$
|
|
1921
|
+
id: prefixId$5(id),
|
|
2206
1922
|
name: id,
|
|
2207
1923
|
onInput: handleLocalInput,
|
|
2208
1924
|
disabled: disabled,
|
|
1925
|
+
popupOpen: popuOpen,
|
|
2209
1926
|
onFeelToggle: () => {
|
|
2210
1927
|
handleFeelToggle();
|
|
2211
1928
|
setFocus(true);
|
|
2212
1929
|
},
|
|
2213
1930
|
onLint: handleLint,
|
|
1931
|
+
onPopupOpen: handlePopupOpen,
|
|
2214
1932
|
value: feelOnlyValue,
|
|
2215
1933
|
variables: variables,
|
|
2216
1934
|
ref: editorRef,
|
|
2217
1935
|
tooltipContainer: tooltipContainer
|
|
2218
1936
|
}) : jsxRuntime.jsx(OptionalComponent, {
|
|
2219
1937
|
...props,
|
|
1938
|
+
popupOpen: popuOpen,
|
|
2220
1939
|
onInput: handleLocalInput,
|
|
2221
1940
|
contentAttributes: {
|
|
2222
|
-
'id': prefixId$
|
|
1941
|
+
'id': prefixId$5(id),
|
|
2223
1942
|
'aria-label': label
|
|
2224
1943
|
},
|
|
2225
1944
|
value: localValue,
|
|
2226
|
-
ref: editorRef
|
|
1945
|
+
ref: editorRef,
|
|
1946
|
+
onPopupOpen: handlePopupOpen,
|
|
1947
|
+
containerRef: containerRef
|
|
2227
1948
|
})]
|
|
2228
1949
|
})]
|
|
2229
1950
|
});
|
|
@@ -2257,7 +1978,7 @@ const OptionalFeelInput = compat.forwardRef((props, ref) => {
|
|
|
2257
1978
|
}
|
|
2258
1979
|
};
|
|
2259
1980
|
return jsxRuntime.jsx("input", {
|
|
2260
|
-
id: prefixId$
|
|
1981
|
+
id: prefixId$5(id),
|
|
2261
1982
|
type: "text",
|
|
2262
1983
|
ref: inputRef,
|
|
2263
1984
|
name: id,
|
|
@@ -2342,7 +2063,7 @@ const OptionalFeelTextArea = compat.forwardRef((props, ref) => {
|
|
|
2342
2063
|
}
|
|
2343
2064
|
};
|
|
2344
2065
|
return jsxRuntime.jsx("textarea", {
|
|
2345
|
-
id: prefixId$
|
|
2066
|
+
id: prefixId$5(id),
|
|
2346
2067
|
type: "text",
|
|
2347
2068
|
ref: inputRef,
|
|
2348
2069
|
name: id,
|
|
@@ -2418,7 +2139,7 @@ const OptionalFeelCheckbox = compat.forwardRef((props, ref) => {
|
|
|
2418
2139
|
};
|
|
2419
2140
|
return jsxRuntime.jsx("input", {
|
|
2420
2141
|
ref: inputRef,
|
|
2421
|
-
id: prefixId$
|
|
2142
|
+
id: prefixId$5(id),
|
|
2422
2143
|
name: id,
|
|
2423
2144
|
onFocus: onFocus,
|
|
2424
2145
|
onBlur: onBlur,
|
|
@@ -2428,101 +2149,1056 @@ const OptionalFeelCheckbox = compat.forwardRef((props, ref) => {
|
|
|
2428
2149
|
checked: value,
|
|
2429
2150
|
disabled: disabled
|
|
2430
2151
|
});
|
|
2431
|
-
});
|
|
2152
|
+
});
|
|
2153
|
+
|
|
2154
|
+
/**
|
|
2155
|
+
* @param {Object} props
|
|
2156
|
+
* @param {Object} props.element
|
|
2157
|
+
* @param {String} props.id
|
|
2158
|
+
* @param {String} props.description
|
|
2159
|
+
* @param {Boolean} props.debounce
|
|
2160
|
+
* @param {Boolean} props.disabled
|
|
2161
|
+
* @param {Boolean} props.feel
|
|
2162
|
+
* @param {String} props.label
|
|
2163
|
+
* @param {Function} props.getValue
|
|
2164
|
+
* @param {Function} props.setValue
|
|
2165
|
+
* @param {Function} props.tooltipContainer
|
|
2166
|
+
* @param {Function} props.validate
|
|
2167
|
+
* @param {Function} props.show
|
|
2168
|
+
* @param {Function} props.example
|
|
2169
|
+
* @param {Function} props.variables
|
|
2170
|
+
* @param {Function} props.onFocus
|
|
2171
|
+
* @param {Function} props.onBlur
|
|
2172
|
+
* @param {string|import('preact').Component} props.tooltip
|
|
2173
|
+
*/
|
|
2174
|
+
function FeelEntry(props) {
|
|
2175
|
+
const {
|
|
2176
|
+
element,
|
|
2177
|
+
id,
|
|
2178
|
+
description,
|
|
2179
|
+
debounce,
|
|
2180
|
+
disabled,
|
|
2181
|
+
feel,
|
|
2182
|
+
label,
|
|
2183
|
+
getValue,
|
|
2184
|
+
setValue,
|
|
2185
|
+
tooltipContainer,
|
|
2186
|
+
hostLanguage,
|
|
2187
|
+
singleLine,
|
|
2188
|
+
validate,
|
|
2189
|
+
show = noop$2,
|
|
2190
|
+
example,
|
|
2191
|
+
variables,
|
|
2192
|
+
onFocus,
|
|
2193
|
+
onBlur,
|
|
2194
|
+
tooltip
|
|
2195
|
+
} = props;
|
|
2196
|
+
const [validationError, setValidationError] = hooks.useState(null);
|
|
2197
|
+
const [localError, setLocalError] = hooks.useState(null);
|
|
2198
|
+
let value = getValue(element);
|
|
2199
|
+
hooks.useEffect(() => {
|
|
2200
|
+
if (minDash.isFunction(validate)) {
|
|
2201
|
+
const newValidationError = validate(value) || null;
|
|
2202
|
+
setValidationError(newValidationError);
|
|
2203
|
+
}
|
|
2204
|
+
}, [value]);
|
|
2205
|
+
const onInput = useStaticCallback(newValue => {
|
|
2206
|
+
let newValidationError = null;
|
|
2207
|
+
if (minDash.isFunction(validate)) {
|
|
2208
|
+
newValidationError = validate(newValue) || null;
|
|
2209
|
+
}
|
|
2210
|
+
|
|
2211
|
+
// don't create multiple commandStack entries for the same value
|
|
2212
|
+
if (newValue !== value) {
|
|
2213
|
+
setValue(newValue, newValidationError);
|
|
2214
|
+
}
|
|
2215
|
+
setValidationError(newValidationError);
|
|
2216
|
+
});
|
|
2217
|
+
const onError = hooks.useCallback(err => {
|
|
2218
|
+
setLocalError(err);
|
|
2219
|
+
}, []);
|
|
2220
|
+
const temporaryError = useError(id);
|
|
2221
|
+
const error = localError || temporaryError || validationError;
|
|
2222
|
+
return jsxRuntime.jsxs("div", {
|
|
2223
|
+
class: classnames__default["default"](props.class, 'bio-properties-panel-entry', error ? 'has-error' : ''),
|
|
2224
|
+
"data-entry-id": id,
|
|
2225
|
+
children: [preact.createElement(FeelTextfield, {
|
|
2226
|
+
...props,
|
|
2227
|
+
debounce: debounce,
|
|
2228
|
+
disabled: disabled,
|
|
2229
|
+
feel: feel,
|
|
2230
|
+
id: id,
|
|
2231
|
+
key: element,
|
|
2232
|
+
label: label,
|
|
2233
|
+
onInput: onInput,
|
|
2234
|
+
onError: onError,
|
|
2235
|
+
onFocus: onFocus,
|
|
2236
|
+
onBlur: onBlur,
|
|
2237
|
+
example: example,
|
|
2238
|
+
hostLanguage: hostLanguage,
|
|
2239
|
+
singleLine: singleLine,
|
|
2240
|
+
show: show,
|
|
2241
|
+
value: value,
|
|
2242
|
+
variables: variables,
|
|
2243
|
+
tooltipContainer: tooltipContainer,
|
|
2244
|
+
OptionalComponent: props.OptionalComponent,
|
|
2245
|
+
tooltip: tooltip
|
|
2246
|
+
}), error && jsxRuntime.jsx("div", {
|
|
2247
|
+
class: "bio-properties-panel-error",
|
|
2248
|
+
children: error
|
|
2249
|
+
}), jsxRuntime.jsx(Description, {
|
|
2250
|
+
forId: id,
|
|
2251
|
+
element: element,
|
|
2252
|
+
value: description
|
|
2253
|
+
})]
|
|
2254
|
+
});
|
|
2255
|
+
}
|
|
2256
|
+
|
|
2257
|
+
/**
|
|
2258
|
+
* @param {Object} props
|
|
2259
|
+
* @param {Object} props.element
|
|
2260
|
+
* @param {String} props.id
|
|
2261
|
+
* @param {String} props.description
|
|
2262
|
+
* @param {Boolean} props.debounce
|
|
2263
|
+
* @param {Boolean} props.disabled
|
|
2264
|
+
* @param {String} props.max
|
|
2265
|
+
* @param {String} props.min
|
|
2266
|
+
* @param {String} props.step
|
|
2267
|
+
* @param {Boolean} props.feel
|
|
2268
|
+
* @param {String} props.label
|
|
2269
|
+
* @param {Function} props.getValue
|
|
2270
|
+
* @param {Function} props.setValue
|
|
2271
|
+
* @param {Function} props.tooltipContainer
|
|
2272
|
+
* @param {Function} props.validate
|
|
2273
|
+
* @param {Function} props.show
|
|
2274
|
+
* @param {Function} props.example
|
|
2275
|
+
* @param {Function} props.variables
|
|
2276
|
+
* @param {Function} props.onFocus
|
|
2277
|
+
* @param {Function} props.onBlur
|
|
2278
|
+
*/
|
|
2279
|
+
function FeelNumberEntry(props) {
|
|
2280
|
+
return jsxRuntime.jsx(FeelEntry, {
|
|
2281
|
+
class: "bio-properties-panel-feel-number",
|
|
2282
|
+
OptionalComponent: OptionalFeelNumberField,
|
|
2283
|
+
...props
|
|
2284
|
+
});
|
|
2285
|
+
}
|
|
2286
|
+
|
|
2287
|
+
/**
|
|
2288
|
+
* @param {Object} props
|
|
2289
|
+
* @param {Object} props.element
|
|
2290
|
+
* @param {String} props.id
|
|
2291
|
+
* @param {String} props.description
|
|
2292
|
+
* @param {Boolean} props.debounce
|
|
2293
|
+
* @param {Boolean} props.disabled
|
|
2294
|
+
* @param {Boolean} props.feel
|
|
2295
|
+
* @param {String} props.label
|
|
2296
|
+
* @param {Function} props.getValue
|
|
2297
|
+
* @param {Function} props.setValue
|
|
2298
|
+
* @param {Function} props.tooltipContainer
|
|
2299
|
+
* @param {Function} props.validate
|
|
2300
|
+
* @param {Function} props.show
|
|
2301
|
+
* @param {Function} props.example
|
|
2302
|
+
* @param {Function} props.variables
|
|
2303
|
+
* @param {Function} props.onFocus
|
|
2304
|
+
* @param {Function} props.onBlur
|
|
2305
|
+
*/
|
|
2306
|
+
function FeelTextAreaEntry(props) {
|
|
2307
|
+
return jsxRuntime.jsx(FeelEntry, {
|
|
2308
|
+
class: "bio-properties-panel-feel-textarea",
|
|
2309
|
+
OptionalComponent: OptionalFeelTextArea,
|
|
2310
|
+
...props
|
|
2311
|
+
});
|
|
2312
|
+
}
|
|
2313
|
+
|
|
2314
|
+
/**
|
|
2315
|
+
* @param {Object} props
|
|
2316
|
+
* @param {Object} props.element
|
|
2317
|
+
* @param {String} props.id
|
|
2318
|
+
* @param {String} props.description
|
|
2319
|
+
* @param {Boolean} props.debounce
|
|
2320
|
+
* @param {Boolean} props.disabled
|
|
2321
|
+
* @param {Boolean} props.feel
|
|
2322
|
+
* @param {String} props.label
|
|
2323
|
+
* @param {Function} props.getValue
|
|
2324
|
+
* @param {Function} props.setValue
|
|
2325
|
+
* @param {Function} props.tooltipContainer
|
|
2326
|
+
* @param {Function} props.validate
|
|
2327
|
+
* @param {Function} props.show
|
|
2328
|
+
* @param {Function} props.example
|
|
2329
|
+
* @param {Function} props.variables
|
|
2330
|
+
* @param {Function} props.onFocus
|
|
2331
|
+
* @param {Function} props.onBlur
|
|
2332
|
+
*/
|
|
2333
|
+
function FeelToggleSwitchEntry(props) {
|
|
2334
|
+
return jsxRuntime.jsx(FeelEntry, {
|
|
2335
|
+
class: "bio-properties-panel-feel-toggle-switch",
|
|
2336
|
+
OptionalComponent: OptionalFeelToggleSwitch,
|
|
2337
|
+
...props
|
|
2338
|
+
});
|
|
2339
|
+
}
|
|
2340
|
+
|
|
2341
|
+
/**
|
|
2342
|
+
* @param {Object} props
|
|
2343
|
+
* @param {Object} props.element
|
|
2344
|
+
* @param {String} props.id
|
|
2345
|
+
* @param {String} props.description
|
|
2346
|
+
* @param {Boolean} props.debounce
|
|
2347
|
+
* @param {Boolean} props.disabled
|
|
2348
|
+
* @param {Boolean} props.feel
|
|
2349
|
+
* @param {String} props.label
|
|
2350
|
+
* @param {Function} props.getValue
|
|
2351
|
+
* @param {Function} props.setValue
|
|
2352
|
+
* @param {Function} props.tooltipContainer
|
|
2353
|
+
* @param {Function} props.validate
|
|
2354
|
+
* @param {Function} props.show
|
|
2355
|
+
* @param {Function} props.example
|
|
2356
|
+
* @param {Function} props.variables
|
|
2357
|
+
* @param {Function} props.onFocus
|
|
2358
|
+
* @param {Function} props.onBlur
|
|
2359
|
+
*/
|
|
2360
|
+
function FeelCheckboxEntry(props) {
|
|
2361
|
+
return jsxRuntime.jsx(FeelEntry, {
|
|
2362
|
+
class: "bio-properties-panel-feel-checkbox",
|
|
2363
|
+
OptionalComponent: OptionalFeelCheckbox,
|
|
2364
|
+
...props
|
|
2365
|
+
});
|
|
2366
|
+
}
|
|
2367
|
+
|
|
2368
|
+
/**
|
|
2369
|
+
* @param {Object} props
|
|
2370
|
+
* @param {Object} props.element
|
|
2371
|
+
* @param {String} props.id
|
|
2372
|
+
* @param {String} props.description
|
|
2373
|
+
* @param {String} props.hostLanguage
|
|
2374
|
+
* @param {Boolean} props.singleLine
|
|
2375
|
+
* @param {Boolean} props.debounce
|
|
2376
|
+
* @param {Boolean} props.disabled
|
|
2377
|
+
* @param {Boolean} props.feel
|
|
2378
|
+
* @param {String} props.label
|
|
2379
|
+
* @param {Function} props.getValue
|
|
2380
|
+
* @param {Function} props.setValue
|
|
2381
|
+
* @param {Function} props.tooltipContainer
|
|
2382
|
+
* @param {Function} props.validate
|
|
2383
|
+
* @param {Function} props.show
|
|
2384
|
+
* @param {Function} props.example
|
|
2385
|
+
* @param {Function} props.variables
|
|
2386
|
+
* @param {Function} props.onFocus
|
|
2387
|
+
* @param {Function} props.onBlur
|
|
2388
|
+
*/
|
|
2389
|
+
function FeelTemplatingEntry(props) {
|
|
2390
|
+
return jsxRuntime.jsx(FeelEntry, {
|
|
2391
|
+
class: "bio-properties-panel-feel-templating",
|
|
2392
|
+
OptionalComponent: CodeEditor$1,
|
|
2393
|
+
...props
|
|
2394
|
+
});
|
|
2395
|
+
}
|
|
2396
|
+
function isEdited$6(node) {
|
|
2397
|
+
if (!node) {
|
|
2398
|
+
return false;
|
|
2399
|
+
}
|
|
2400
|
+
if (node.type === 'checkbox') {
|
|
2401
|
+
return !!node.checked || node.classList.contains('edited');
|
|
2402
|
+
}
|
|
2403
|
+
return !!node.value || node.classList.contains('edited');
|
|
2404
|
+
}
|
|
2405
|
+
|
|
2406
|
+
// helpers /////////////////
|
|
2407
|
+
|
|
2408
|
+
function prefixId$5(id) {
|
|
2409
|
+
return `bio-properties-panel-${id}`;
|
|
2410
|
+
}
|
|
2411
|
+
function calculatePopupPosition(element) {
|
|
2412
|
+
const {
|
|
2413
|
+
top,
|
|
2414
|
+
left
|
|
2415
|
+
} = element.getBoundingClientRect();
|
|
2416
|
+
return {
|
|
2417
|
+
left: left - FEEL_POPUP_WIDTH - 20,
|
|
2418
|
+
top: top
|
|
2419
|
+
};
|
|
2420
|
+
}
|
|
2421
|
+
|
|
2422
|
+
// todo(pinussilvestrus): make this configurable in the future
|
|
2423
|
+
function getPopupTitle(element, label) {
|
|
2424
|
+
let popupTitle;
|
|
2425
|
+
if (element && element.type) {
|
|
2426
|
+
popupTitle = `${element.type} / `;
|
|
2427
|
+
}
|
|
2428
|
+
return `${popupTitle}${label}`;
|
|
2429
|
+
}
|
|
2430
|
+
|
|
2431
|
+
const DEFAULT_LAYOUT = {};
|
|
2432
|
+
const DEFAULT_DESCRIPTION = {};
|
|
2433
|
+
const DEFAULT_TOOLTIP = {};
|
|
2434
|
+
|
|
2435
|
+
/**
|
|
2436
|
+
* @typedef { {
|
|
2437
|
+
* component: import('preact').Component,
|
|
2438
|
+
* id: String,
|
|
2439
|
+
* isEdited?: Function
|
|
2440
|
+
* } } EntryDefinition
|
|
2441
|
+
*
|
|
2442
|
+
* @typedef { {
|
|
2443
|
+
* autoFocusEntry: String,
|
|
2444
|
+
* autoOpen?: Boolean,
|
|
2445
|
+
* entries: Array<EntryDefinition>,
|
|
2446
|
+
* id: String,
|
|
2447
|
+
* label: String,
|
|
2448
|
+
* remove: (event: MouseEvent) => void
|
|
2449
|
+
* } } ListItemDefinition
|
|
2450
|
+
*
|
|
2451
|
+
* @typedef { {
|
|
2452
|
+
* add: (event: MouseEvent) => void,
|
|
2453
|
+
* component: import('preact').Component,
|
|
2454
|
+
* element: Object,
|
|
2455
|
+
* id: String,
|
|
2456
|
+
* items: Array<ListItemDefinition>,
|
|
2457
|
+
* label: String,
|
|
2458
|
+
* shouldSort?: Boolean,
|
|
2459
|
+
* shouldOpen?: Boolean
|
|
2460
|
+
* } } ListGroupDefinition
|
|
2461
|
+
*
|
|
2462
|
+
* @typedef { {
|
|
2463
|
+
* component?: import('preact').Component,
|
|
2464
|
+
* entries: Array<EntryDefinition>,
|
|
2465
|
+
* id: String,
|
|
2466
|
+
* label: String,
|
|
2467
|
+
* shouldOpen?: Boolean
|
|
2468
|
+
* } } GroupDefinition
|
|
2469
|
+
*
|
|
2470
|
+
* @typedef { {
|
|
2471
|
+
* [id: String]: GetDescriptionFunction
|
|
2472
|
+
* } } DescriptionConfig
|
|
2473
|
+
*
|
|
2474
|
+
* @typedef { {
|
|
2475
|
+
* [id: String]: GetTooltipFunction
|
|
2476
|
+
* } } TooltipConfig
|
|
2477
|
+
*
|
|
2478
|
+
* @callback { {
|
|
2479
|
+
* @param {string} id
|
|
2480
|
+
* @param {Object} element
|
|
2481
|
+
* @returns {string}
|
|
2482
|
+
* } } GetDescriptionFunction
|
|
2483
|
+
*
|
|
2484
|
+
* @callback { {
|
|
2485
|
+
* @param {string} id
|
|
2486
|
+
* @param {Object} element
|
|
2487
|
+
* @returns {string}
|
|
2488
|
+
* } } GetTooltipFunction
|
|
2489
|
+
*
|
|
2490
|
+
* @typedef { {
|
|
2491
|
+
* getEmpty: (element: object) => import('./components/Placeholder').PlaceholderDefinition,
|
|
2492
|
+
* getMultiple: (element: Object) => import('./components/Placeholder').PlaceholderDefinition
|
|
2493
|
+
* } } PlaceholderProvider
|
|
2494
|
+
*
|
|
2495
|
+
*/
|
|
2496
|
+
|
|
2497
|
+
/**
|
|
2498
|
+
* A basic properties panel component. Describes *how* content will be rendered, accepts
|
|
2499
|
+
* data from implementor to describe *what* will be rendered.
|
|
2500
|
+
*
|
|
2501
|
+
* @param {Object} props
|
|
2502
|
+
* @param {Object|Array} props.element
|
|
2503
|
+
* @param {import('./components/Header').HeaderProvider} props.headerProvider
|
|
2504
|
+
* @param {PlaceholderProvider} [props.placeholderProvider]
|
|
2505
|
+
* @param {Array<GroupDefinition|ListGroupDefinition>} props.groups
|
|
2506
|
+
* @param {Object} [props.layoutConfig]
|
|
2507
|
+
* @param {Function} [props.layoutChanged]
|
|
2508
|
+
* @param {DescriptionConfig} [props.descriptionConfig]
|
|
2509
|
+
* @param {Function} [props.descriptionLoaded]
|
|
2510
|
+
* @param {TooltipConfig} [props.tooltipConfig]
|
|
2511
|
+
* @param {Function} [props.tooltipLoaded]
|
|
2512
|
+
* @param {Object} [props.eventBus]
|
|
2513
|
+
*/
|
|
2514
|
+
function PropertiesPanel(props) {
|
|
2515
|
+
const {
|
|
2516
|
+
element,
|
|
2517
|
+
headerProvider,
|
|
2518
|
+
placeholderProvider,
|
|
2519
|
+
groups,
|
|
2520
|
+
layoutConfig,
|
|
2521
|
+
layoutChanged,
|
|
2522
|
+
descriptionConfig,
|
|
2523
|
+
descriptionLoaded,
|
|
2524
|
+
tooltipConfig,
|
|
2525
|
+
tooltipLoaded,
|
|
2526
|
+
eventBus
|
|
2527
|
+
} = props;
|
|
2528
|
+
|
|
2529
|
+
// set-up layout context
|
|
2530
|
+
const [layout, setLayout] = hooks.useState(createLayout(layoutConfig));
|
|
2531
|
+
|
|
2532
|
+
// react to external changes in the layout config
|
|
2533
|
+
useUpdateLayoutEffect(() => {
|
|
2534
|
+
const newLayout = createLayout(layoutConfig);
|
|
2535
|
+
setLayout(newLayout);
|
|
2536
|
+
}, [layoutConfig]);
|
|
2537
|
+
hooks.useEffect(() => {
|
|
2538
|
+
if (typeof layoutChanged === 'function') {
|
|
2539
|
+
layoutChanged(layout);
|
|
2540
|
+
}
|
|
2541
|
+
}, [layout, layoutChanged]);
|
|
2542
|
+
const getLayoutForKey = (key, defaultValue) => {
|
|
2543
|
+
return minDash.get(layout, key, defaultValue);
|
|
2544
|
+
};
|
|
2545
|
+
const setLayoutForKey = (key, config) => {
|
|
2546
|
+
const newLayout = minDash.assign({}, layout);
|
|
2547
|
+
minDash.set(newLayout, key, config);
|
|
2548
|
+
setLayout(newLayout);
|
|
2549
|
+
};
|
|
2550
|
+
const layoutContext = {
|
|
2551
|
+
layout,
|
|
2552
|
+
setLayout,
|
|
2553
|
+
getLayoutForKey,
|
|
2554
|
+
setLayoutForKey
|
|
2555
|
+
};
|
|
2556
|
+
|
|
2557
|
+
// set-up description context
|
|
2558
|
+
const description = hooks.useMemo(() => createDescriptionContext(descriptionConfig), [descriptionConfig]);
|
|
2559
|
+
hooks.useEffect(() => {
|
|
2560
|
+
if (typeof descriptionLoaded === 'function') {
|
|
2561
|
+
descriptionLoaded(description);
|
|
2562
|
+
}
|
|
2563
|
+
}, [description, descriptionLoaded]);
|
|
2564
|
+
const getDescriptionForId = (id, element) => {
|
|
2565
|
+
return description[id] && description[id](element);
|
|
2566
|
+
};
|
|
2567
|
+
const descriptionContext = {
|
|
2568
|
+
description,
|
|
2569
|
+
getDescriptionForId
|
|
2570
|
+
};
|
|
2571
|
+
|
|
2572
|
+
// set-up tooltip context
|
|
2573
|
+
const tooltip = hooks.useMemo(() => createTooltipContext(tooltipConfig), [tooltipConfig]);
|
|
2574
|
+
hooks.useEffect(() => {
|
|
2575
|
+
if (typeof tooltipLoaded === 'function') {
|
|
2576
|
+
tooltipLoaded(tooltip);
|
|
2577
|
+
}
|
|
2578
|
+
}, [tooltip, tooltipLoaded]);
|
|
2579
|
+
const getTooltipForId = (id, element) => {
|
|
2580
|
+
return tooltip[id] && tooltip[id](element);
|
|
2581
|
+
};
|
|
2582
|
+
const tooltipContext = {
|
|
2583
|
+
tooltip,
|
|
2584
|
+
getTooltipForId
|
|
2585
|
+
};
|
|
2586
|
+
const [errors, setErrors] = hooks.useState({});
|
|
2587
|
+
const onSetErrors = ({
|
|
2588
|
+
errors
|
|
2589
|
+
}) => setErrors(errors);
|
|
2590
|
+
useEvent('propertiesPanel.setErrors', onSetErrors, eventBus);
|
|
2591
|
+
const errorsContext = {
|
|
2592
|
+
errors
|
|
2593
|
+
};
|
|
2594
|
+
const eventContext = {
|
|
2595
|
+
eventBus
|
|
2596
|
+
};
|
|
2597
|
+
const propertiesPanelContext = {
|
|
2598
|
+
element
|
|
2599
|
+
};
|
|
2600
|
+
|
|
2601
|
+
// empty state
|
|
2602
|
+
if (placeholderProvider && !element) {
|
|
2603
|
+
return jsxRuntime.jsx(Placeholder, {
|
|
2604
|
+
...placeholderProvider.getEmpty()
|
|
2605
|
+
});
|
|
2606
|
+
}
|
|
2607
|
+
|
|
2608
|
+
// multiple state
|
|
2609
|
+
if (placeholderProvider && minDash.isArray(element)) {
|
|
2610
|
+
return jsxRuntime.jsx(Placeholder, {
|
|
2611
|
+
...placeholderProvider.getMultiple()
|
|
2612
|
+
});
|
|
2613
|
+
}
|
|
2614
|
+
return jsxRuntime.jsx(LayoutContext.Provider, {
|
|
2615
|
+
value: propertiesPanelContext,
|
|
2616
|
+
children: jsxRuntime.jsx(ErrorsContext.Provider, {
|
|
2617
|
+
value: errorsContext,
|
|
2618
|
+
children: jsxRuntime.jsx(DescriptionContext.Provider, {
|
|
2619
|
+
value: descriptionContext,
|
|
2620
|
+
children: jsxRuntime.jsx(TooltipContext.Provider, {
|
|
2621
|
+
value: tooltipContext,
|
|
2622
|
+
children: jsxRuntime.jsx(LayoutContext.Provider, {
|
|
2623
|
+
value: layoutContext,
|
|
2624
|
+
children: jsxRuntime.jsx(EventContext.Provider, {
|
|
2625
|
+
value: eventContext,
|
|
2626
|
+
children: jsxRuntime.jsx(FEELPopupRoot, {
|
|
2627
|
+
element: element,
|
|
2628
|
+
children: jsxRuntime.jsxs("div", {
|
|
2629
|
+
class: "bio-properties-panel",
|
|
2630
|
+
children: [jsxRuntime.jsx(Header, {
|
|
2631
|
+
element: element,
|
|
2632
|
+
headerProvider: headerProvider
|
|
2633
|
+
}), jsxRuntime.jsx("div", {
|
|
2634
|
+
class: "bio-properties-panel-scroll-container",
|
|
2635
|
+
children: groups.map(group => {
|
|
2636
|
+
const {
|
|
2637
|
+
component: Component = Group,
|
|
2638
|
+
id
|
|
2639
|
+
} = group;
|
|
2640
|
+
return preact.createElement(Component, {
|
|
2641
|
+
...group,
|
|
2642
|
+
key: id,
|
|
2643
|
+
element: element
|
|
2644
|
+
});
|
|
2645
|
+
})
|
|
2646
|
+
})]
|
|
2647
|
+
})
|
|
2648
|
+
})
|
|
2649
|
+
})
|
|
2650
|
+
})
|
|
2651
|
+
})
|
|
2652
|
+
})
|
|
2653
|
+
})
|
|
2654
|
+
});
|
|
2655
|
+
}
|
|
2656
|
+
|
|
2657
|
+
// helpers //////////////////
|
|
2658
|
+
|
|
2659
|
+
function createLayout(overrides = {}, defaults = DEFAULT_LAYOUT) {
|
|
2660
|
+
return {
|
|
2661
|
+
...defaults,
|
|
2662
|
+
...overrides
|
|
2663
|
+
};
|
|
2664
|
+
}
|
|
2665
|
+
function createDescriptionContext(overrides = {}) {
|
|
2666
|
+
return {
|
|
2667
|
+
...DEFAULT_DESCRIPTION,
|
|
2668
|
+
...overrides
|
|
2669
|
+
};
|
|
2670
|
+
}
|
|
2671
|
+
function createTooltipContext(overrides = {}) {
|
|
2672
|
+
return {
|
|
2673
|
+
...DEFAULT_TOOLTIP,
|
|
2674
|
+
...overrides
|
|
2675
|
+
};
|
|
2676
|
+
}
|
|
2677
|
+
|
|
2678
|
+
// hooks //////////////////
|
|
2679
|
+
|
|
2680
|
+
/**
|
|
2681
|
+
* This hook behaves like useLayoutEffect, but does not trigger on the first render.
|
|
2682
|
+
*
|
|
2683
|
+
* @param {Function} effect
|
|
2684
|
+
* @param {Array} deps
|
|
2685
|
+
*/
|
|
2686
|
+
function useUpdateLayoutEffect(effect, deps) {
|
|
2687
|
+
const isMounted = hooks.useRef(false);
|
|
2688
|
+
hooks.useLayoutEffect(() => {
|
|
2689
|
+
if (isMounted.current) {
|
|
2690
|
+
return effect();
|
|
2691
|
+
} else {
|
|
2692
|
+
isMounted.current = true;
|
|
2693
|
+
}
|
|
2694
|
+
}, deps);
|
|
2695
|
+
}
|
|
2696
|
+
|
|
2697
|
+
function DropdownButton(props) {
|
|
2698
|
+
const {
|
|
2699
|
+
class: className,
|
|
2700
|
+
children,
|
|
2701
|
+
menuItems = []
|
|
2702
|
+
} = props;
|
|
2703
|
+
const dropdownRef = hooks.useRef(null);
|
|
2704
|
+
const menuRef = hooks.useRef(null);
|
|
2705
|
+
const [open, setOpen] = hooks.useState(false);
|
|
2706
|
+
const close = () => setOpen(false);
|
|
2707
|
+
function onDropdownToggle(event) {
|
|
2708
|
+
if (menuRef.current && menuRef.current.contains(event.target)) {
|
|
2709
|
+
return;
|
|
2710
|
+
}
|
|
2711
|
+
event.stopPropagation();
|
|
2712
|
+
setOpen(open => !open);
|
|
2713
|
+
}
|
|
2714
|
+
function onActionClick(event, action) {
|
|
2715
|
+
event.stopPropagation();
|
|
2716
|
+
close();
|
|
2717
|
+
action();
|
|
2718
|
+
}
|
|
2719
|
+
useGlobalClick([dropdownRef.current], () => close());
|
|
2720
|
+
return jsxRuntime.jsxs("div", {
|
|
2721
|
+
class: classnames__default["default"]('bio-properties-panel-dropdown-button', {
|
|
2722
|
+
open
|
|
2723
|
+
}, className),
|
|
2724
|
+
onClick: onDropdownToggle,
|
|
2725
|
+
ref: dropdownRef,
|
|
2726
|
+
children: [children, jsxRuntime.jsx("div", {
|
|
2727
|
+
class: "bio-properties-panel-dropdown-button__menu",
|
|
2728
|
+
ref: menuRef,
|
|
2729
|
+
children: menuItems.map((item, index) => jsxRuntime.jsx(MenuItem, {
|
|
2730
|
+
onClick: onActionClick,
|
|
2731
|
+
item: item
|
|
2732
|
+
}, index))
|
|
2733
|
+
})]
|
|
2734
|
+
});
|
|
2735
|
+
}
|
|
2736
|
+
function MenuItem({
|
|
2737
|
+
item,
|
|
2738
|
+
onClick
|
|
2739
|
+
}) {
|
|
2740
|
+
if (item.separator) {
|
|
2741
|
+
return jsxRuntime.jsx("div", {
|
|
2742
|
+
class: "bio-properties-panel-dropdown-button__menu-item bio-properties-panel-dropdown-button__menu-item--separator"
|
|
2743
|
+
});
|
|
2744
|
+
}
|
|
2745
|
+
if (item.action) {
|
|
2746
|
+
return jsxRuntime.jsx("button", {
|
|
2747
|
+
class: "bio-properties-panel-dropdown-button__menu-item bio-properties-panel-dropdown-button__menu-item--actionable",
|
|
2748
|
+
onClick: event => onClick(event, item.action),
|
|
2749
|
+
children: item.entry
|
|
2750
|
+
});
|
|
2751
|
+
}
|
|
2752
|
+
return jsxRuntime.jsx("div", {
|
|
2753
|
+
class: "bio-properties-panel-dropdown-button__menu-item",
|
|
2754
|
+
children: item.entry
|
|
2755
|
+
});
|
|
2756
|
+
}
|
|
2757
|
+
|
|
2758
|
+
/**
|
|
2759
|
+
*
|
|
2760
|
+
* @param {Array<null | Element>} ignoredElements
|
|
2761
|
+
* @param {Function} callback
|
|
2762
|
+
*/
|
|
2763
|
+
function useGlobalClick(ignoredElements, callback) {
|
|
2764
|
+
hooks.useEffect(() => {
|
|
2765
|
+
/**
|
|
2766
|
+
* @param {MouseEvent} event
|
|
2767
|
+
*/
|
|
2768
|
+
function listener(event) {
|
|
2769
|
+
if (ignoredElements.some(element => element && element.contains(event.target))) {
|
|
2770
|
+
return;
|
|
2771
|
+
}
|
|
2772
|
+
callback();
|
|
2773
|
+
}
|
|
2774
|
+
document.addEventListener('click', listener, {
|
|
2775
|
+
capture: true
|
|
2776
|
+
});
|
|
2777
|
+
return () => document.removeEventListener('click', listener, {
|
|
2778
|
+
capture: true
|
|
2779
|
+
});
|
|
2780
|
+
}, [...ignoredElements, callback]);
|
|
2781
|
+
}
|
|
2782
|
+
|
|
2783
|
+
function HeaderButton(props) {
|
|
2784
|
+
const {
|
|
2785
|
+
children = null,
|
|
2786
|
+
class: classname,
|
|
2787
|
+
onClick = () => {},
|
|
2788
|
+
...otherProps
|
|
2789
|
+
} = props;
|
|
2790
|
+
return jsxRuntime.jsx("button", {
|
|
2791
|
+
...otherProps,
|
|
2792
|
+
onClick: onClick,
|
|
2793
|
+
class: classnames__default["default"]('bio-properties-panel-group-header-button', classname),
|
|
2794
|
+
children: children
|
|
2795
|
+
});
|
|
2796
|
+
}
|
|
2797
|
+
|
|
2798
|
+
function CollapsibleEntry(props) {
|
|
2799
|
+
const {
|
|
2800
|
+
element,
|
|
2801
|
+
entries = [],
|
|
2802
|
+
id,
|
|
2803
|
+
label,
|
|
2804
|
+
open: shouldOpen,
|
|
2805
|
+
remove
|
|
2806
|
+
} = props;
|
|
2807
|
+
const [open, setOpen] = hooks.useState(shouldOpen);
|
|
2808
|
+
const toggleOpen = () => setOpen(!open);
|
|
2809
|
+
const {
|
|
2810
|
+
onShow
|
|
2811
|
+
} = hooks.useContext(LayoutContext);
|
|
2812
|
+
const propertiesPanelContext = {
|
|
2813
|
+
...hooks.useContext(LayoutContext),
|
|
2814
|
+
onShow: hooks.useCallback(() => {
|
|
2815
|
+
setOpen(true);
|
|
2816
|
+
if (minDash.isFunction(onShow)) {
|
|
2817
|
+
onShow();
|
|
2818
|
+
}
|
|
2819
|
+
}, [onShow, setOpen])
|
|
2820
|
+
};
|
|
2821
|
+
|
|
2822
|
+
// todo(pinussilvestrus): translate once we have a translate mechanism for the core
|
|
2823
|
+
const placeholderLabel = '<empty>';
|
|
2824
|
+
return jsxRuntime.jsxs("div", {
|
|
2825
|
+
"data-entry-id": id,
|
|
2826
|
+
class: classnames__default["default"]('bio-properties-panel-collapsible-entry', open ? 'open' : ''),
|
|
2827
|
+
children: [jsxRuntime.jsxs("div", {
|
|
2828
|
+
class: "bio-properties-panel-collapsible-entry-header",
|
|
2829
|
+
onClick: toggleOpen,
|
|
2830
|
+
children: [jsxRuntime.jsx("div", {
|
|
2831
|
+
title: label || placeholderLabel,
|
|
2832
|
+
class: classnames__default["default"]('bio-properties-panel-collapsible-entry-header-title', !label && 'empty'),
|
|
2833
|
+
children: label || placeholderLabel
|
|
2834
|
+
}), jsxRuntime.jsx("button", {
|
|
2835
|
+
title: "Toggle list item",
|
|
2836
|
+
class: "bio-properties-panel-arrow bio-properties-panel-collapsible-entry-arrow",
|
|
2837
|
+
children: jsxRuntime.jsx(ArrowIcon, {
|
|
2838
|
+
class: open ? 'bio-properties-panel-arrow-down' : 'bio-properties-panel-arrow-right'
|
|
2839
|
+
})
|
|
2840
|
+
}), remove ? jsxRuntime.jsx("button", {
|
|
2841
|
+
title: "Delete item",
|
|
2842
|
+
class: "bio-properties-panel-remove-entry",
|
|
2843
|
+
onClick: remove,
|
|
2844
|
+
children: jsxRuntime.jsx(DeleteIcon, {})
|
|
2845
|
+
}) : null]
|
|
2846
|
+
}), jsxRuntime.jsx("div", {
|
|
2847
|
+
class: classnames__default["default"]('bio-properties-panel-collapsible-entry-entries', open ? 'open' : ''),
|
|
2848
|
+
children: jsxRuntime.jsx(LayoutContext.Provider, {
|
|
2849
|
+
value: propertiesPanelContext,
|
|
2850
|
+
children: entries.map(entry => {
|
|
2851
|
+
const {
|
|
2852
|
+
component: Component,
|
|
2853
|
+
id
|
|
2854
|
+
} = entry;
|
|
2855
|
+
return preact.createElement(Component, {
|
|
2856
|
+
...entry,
|
|
2857
|
+
element: element,
|
|
2858
|
+
key: id
|
|
2859
|
+
});
|
|
2860
|
+
})
|
|
2861
|
+
})
|
|
2862
|
+
})]
|
|
2863
|
+
});
|
|
2864
|
+
}
|
|
2865
|
+
|
|
2866
|
+
function ListItem(props) {
|
|
2867
|
+
const {
|
|
2868
|
+
autoFocusEntry,
|
|
2869
|
+
autoOpen
|
|
2870
|
+
} = props;
|
|
2871
|
+
|
|
2872
|
+
// focus specified entry on auto open
|
|
2873
|
+
hooks.useEffect(() => {
|
|
2874
|
+
if (autoOpen && autoFocusEntry) {
|
|
2875
|
+
const entry = minDom.query(`[data-entry-id="${autoFocusEntry}"]`);
|
|
2876
|
+
const focusableInput = minDom.query('.bio-properties-panel-input', entry);
|
|
2877
|
+
if (focusableInput) {
|
|
2878
|
+
if (minDash.isFunction(focusableInput.select)) {
|
|
2879
|
+
focusableInput.select();
|
|
2880
|
+
} else if (minDash.isFunction(focusableInput.focus)) {
|
|
2881
|
+
focusableInput.focus();
|
|
2882
|
+
}
|
|
2883
|
+
}
|
|
2884
|
+
}
|
|
2885
|
+
}, [autoOpen, autoFocusEntry]);
|
|
2886
|
+
return jsxRuntime.jsx("div", {
|
|
2887
|
+
class: "bio-properties-panel-list-item",
|
|
2888
|
+
children: jsxRuntime.jsx(CollapsibleEntry, {
|
|
2889
|
+
...props,
|
|
2890
|
+
open: autoOpen
|
|
2891
|
+
})
|
|
2892
|
+
});
|
|
2893
|
+
}
|
|
2894
|
+
|
|
2895
|
+
const noop$1 = () => {};
|
|
2896
|
+
|
|
2897
|
+
/**
|
|
2898
|
+
* @param {import('../PropertiesPanel').ListGroupDefinition} props
|
|
2899
|
+
*/
|
|
2900
|
+
function ListGroup(props) {
|
|
2901
|
+
const {
|
|
2902
|
+
add,
|
|
2903
|
+
element,
|
|
2904
|
+
id,
|
|
2905
|
+
items,
|
|
2906
|
+
label,
|
|
2907
|
+
shouldOpen = true,
|
|
2908
|
+
shouldSort = true
|
|
2909
|
+
} = props;
|
|
2910
|
+
const groupRef = hooks.useRef(null);
|
|
2911
|
+
const [open, setOpen] = useLayoutState(['groups', id, 'open'], false);
|
|
2912
|
+
const [sticky, setSticky] = hooks.useState(false);
|
|
2913
|
+
const onShow = hooks.useCallback(() => setOpen(true), [setOpen]);
|
|
2914
|
+
const [ordering, setOrdering] = hooks.useState([]);
|
|
2915
|
+
const [newItemAdded, setNewItemAdded] = hooks.useState(false);
|
|
2916
|
+
|
|
2917
|
+
// Flag to mark that add button was clicked in the last render cycle
|
|
2918
|
+
const [addTriggered, setAddTriggered] = hooks.useState(false);
|
|
2919
|
+
const prevItems = usePrevious(items);
|
|
2920
|
+
const prevElement = usePrevious(element);
|
|
2921
|
+
const elementChanged = element !== prevElement;
|
|
2922
|
+
const shouldHandleEffects = !elementChanged && (shouldSort || shouldOpen);
|
|
2923
|
+
|
|
2924
|
+
// reset initial ordering when element changes (before first render)
|
|
2925
|
+
if (elementChanged) {
|
|
2926
|
+
setOrdering(createOrdering(shouldSort ? sortItems(items) : items));
|
|
2927
|
+
}
|
|
2928
|
+
|
|
2929
|
+
// keep ordering in sync to items - and open changes
|
|
2930
|
+
|
|
2931
|
+
// (0) set initial ordering from given items
|
|
2932
|
+
hooks.useEffect(() => {
|
|
2933
|
+
if (!prevItems || !shouldSort) {
|
|
2934
|
+
setOrdering(createOrdering(items));
|
|
2935
|
+
}
|
|
2936
|
+
}, [items, element]);
|
|
2937
|
+
|
|
2938
|
+
// (1) items were added
|
|
2939
|
+
hooks.useEffect(() => {
|
|
2940
|
+
// reset addTriggered flag
|
|
2941
|
+
setAddTriggered(false);
|
|
2942
|
+
if (shouldHandleEffects && prevItems && items.length > prevItems.length) {
|
|
2943
|
+
let add = [];
|
|
2944
|
+
items.forEach(item => {
|
|
2945
|
+
if (!ordering.includes(item.id)) {
|
|
2946
|
+
add.push(item.id);
|
|
2947
|
+
}
|
|
2948
|
+
});
|
|
2949
|
+
let newOrdering = ordering;
|
|
2950
|
+
|
|
2951
|
+
// open if not open, configured and triggered by add button
|
|
2952
|
+
//
|
|
2953
|
+
// TODO(marstamm): remove once we refactor layout handling for listGroups.
|
|
2954
|
+
// Ideally, opening should be handled as part of the `add` callback and
|
|
2955
|
+
// not be a concern for the ListGroup component.
|
|
2956
|
+
if (addTriggered && !open && shouldOpen) {
|
|
2957
|
+
toggleOpen();
|
|
2958
|
+
}
|
|
2959
|
+
|
|
2960
|
+
// filter when not open and configured
|
|
2961
|
+
if (!open && shouldSort) {
|
|
2962
|
+
newOrdering = createOrdering(sortItems(items));
|
|
2963
|
+
}
|
|
2964
|
+
|
|
2965
|
+
// add new items on top or bottom depending on sorting behavior
|
|
2966
|
+
newOrdering = newOrdering.filter(item => !add.includes(item));
|
|
2967
|
+
if (shouldSort) {
|
|
2968
|
+
newOrdering.unshift(...add);
|
|
2969
|
+
} else {
|
|
2970
|
+
newOrdering.push(...add);
|
|
2971
|
+
}
|
|
2972
|
+
setOrdering(newOrdering);
|
|
2973
|
+
setNewItemAdded(addTriggered);
|
|
2974
|
+
} else {
|
|
2975
|
+
setNewItemAdded(false);
|
|
2976
|
+
}
|
|
2977
|
+
}, [items, open, shouldHandleEffects, addTriggered]);
|
|
2978
|
+
|
|
2979
|
+
// (2) sort items on open if shouldSort is set
|
|
2980
|
+
hooks.useEffect(() => {
|
|
2981
|
+
if (shouldSort && open && !newItemAdded) {
|
|
2982
|
+
setOrdering(createOrdering(sortItems(items)));
|
|
2983
|
+
}
|
|
2984
|
+
}, [open, shouldSort]);
|
|
2985
|
+
|
|
2986
|
+
// (3) items were deleted
|
|
2987
|
+
hooks.useEffect(() => {
|
|
2988
|
+
if (shouldHandleEffects && prevItems && items.length < prevItems.length) {
|
|
2989
|
+
let keep = [];
|
|
2990
|
+
ordering.forEach(o => {
|
|
2991
|
+
if (getItem(items, o)) {
|
|
2992
|
+
keep.push(o);
|
|
2993
|
+
}
|
|
2994
|
+
});
|
|
2995
|
+
setOrdering(keep);
|
|
2996
|
+
}
|
|
2997
|
+
}, [items, shouldHandleEffects]);
|
|
2998
|
+
|
|
2999
|
+
// set css class when group is sticky to top
|
|
3000
|
+
useStickyIntersectionObserver(groupRef, 'div.bio-properties-panel-scroll-container', setSticky);
|
|
3001
|
+
const toggleOpen = () => setOpen(!open);
|
|
3002
|
+
const hasItems = !!items.length;
|
|
3003
|
+
const propertiesPanelContext = {
|
|
3004
|
+
...hooks.useContext(LayoutContext),
|
|
3005
|
+
onShow
|
|
3006
|
+
};
|
|
3007
|
+
const handleAddClick = e => {
|
|
3008
|
+
setAddTriggered(true);
|
|
3009
|
+
add(e);
|
|
3010
|
+
};
|
|
3011
|
+
const allErrors = useErrors();
|
|
3012
|
+
const hasError = items.some(item => {
|
|
3013
|
+
if (allErrors[item.id]) {
|
|
3014
|
+
return true;
|
|
3015
|
+
}
|
|
3016
|
+
if (!item.entries) {
|
|
3017
|
+
return;
|
|
3018
|
+
}
|
|
3019
|
+
|
|
3020
|
+
// also check if the error is nested, e.g. for name-value entries
|
|
3021
|
+
return item.entries.some(entry => allErrors[entry.id]);
|
|
3022
|
+
});
|
|
3023
|
+
return jsxRuntime.jsxs("div", {
|
|
3024
|
+
class: "bio-properties-panel-group",
|
|
3025
|
+
"data-group-id": 'group-' + id,
|
|
3026
|
+
ref: groupRef,
|
|
3027
|
+
children: [jsxRuntime.jsxs("div", {
|
|
3028
|
+
class: classnames__default["default"]('bio-properties-panel-group-header', hasItems ? '' : 'empty', hasItems && open ? 'open' : '', sticky && open ? 'sticky' : ''),
|
|
3029
|
+
onClick: hasItems ? toggleOpen : noop$1,
|
|
3030
|
+
children: [jsxRuntime.jsx("div", {
|
|
3031
|
+
title: label,
|
|
3032
|
+
class: "bio-properties-panel-group-header-title",
|
|
3033
|
+
children: jsxRuntime.jsx(TooltipWrapper, {
|
|
3034
|
+
value: props.tooltip,
|
|
3035
|
+
forId: 'group-' + id,
|
|
3036
|
+
element: element,
|
|
3037
|
+
parent: groupRef,
|
|
3038
|
+
children: label
|
|
3039
|
+
})
|
|
3040
|
+
}), jsxRuntime.jsxs("div", {
|
|
3041
|
+
class: "bio-properties-panel-group-header-buttons",
|
|
3042
|
+
children: [add ? jsxRuntime.jsxs("button", {
|
|
3043
|
+
title: "Create new list item",
|
|
3044
|
+
class: "bio-properties-panel-group-header-button bio-properties-panel-add-entry",
|
|
3045
|
+
onClick: handleAddClick,
|
|
3046
|
+
children: [jsxRuntime.jsx(CreateIcon, {}), !hasItems ? jsxRuntime.jsx("span", {
|
|
3047
|
+
class: "bio-properties-panel-add-entry-label",
|
|
3048
|
+
children: "Create"
|
|
3049
|
+
}) : null]
|
|
3050
|
+
}) : null, hasItems ? jsxRuntime.jsx("div", {
|
|
3051
|
+
title: `List contains ${items.length} item${items.length != 1 ? 's' : ''}`,
|
|
3052
|
+
class: classnames__default["default"]('bio-properties-panel-list-badge', hasError ? 'bio-properties-panel-list-badge--error' : ''),
|
|
3053
|
+
children: items.length
|
|
3054
|
+
}) : null, hasItems ? jsxRuntime.jsx("button", {
|
|
3055
|
+
title: "Toggle section",
|
|
3056
|
+
class: "bio-properties-panel-group-header-button bio-properties-panel-arrow",
|
|
3057
|
+
children: jsxRuntime.jsx(ArrowIcon, {
|
|
3058
|
+
class: open ? 'bio-properties-panel-arrow-down' : 'bio-properties-panel-arrow-right'
|
|
3059
|
+
})
|
|
3060
|
+
}) : null]
|
|
3061
|
+
})]
|
|
3062
|
+
}), jsxRuntime.jsx("div", {
|
|
3063
|
+
class: classnames__default["default"]('bio-properties-panel-list', open && hasItems ? 'open' : ''),
|
|
3064
|
+
children: jsxRuntime.jsx(LayoutContext.Provider, {
|
|
3065
|
+
value: propertiesPanelContext,
|
|
3066
|
+
children: ordering.map((o, index) => {
|
|
3067
|
+
const item = getItem(items, o);
|
|
3068
|
+
if (!item) {
|
|
3069
|
+
return;
|
|
3070
|
+
}
|
|
3071
|
+
const {
|
|
3072
|
+
id
|
|
3073
|
+
} = item;
|
|
3074
|
+
|
|
3075
|
+
// if item was added, open it
|
|
3076
|
+
// Existing items will not be affected as autoOpen is only applied on first render
|
|
3077
|
+
const autoOpen = newItemAdded;
|
|
3078
|
+
return preact.createElement(ListItem, {
|
|
3079
|
+
...item,
|
|
3080
|
+
autoOpen: autoOpen,
|
|
3081
|
+
element: element,
|
|
3082
|
+
index: index,
|
|
3083
|
+
key: id
|
|
3084
|
+
});
|
|
3085
|
+
})
|
|
3086
|
+
})
|
|
3087
|
+
})]
|
|
3088
|
+
});
|
|
3089
|
+
}
|
|
3090
|
+
|
|
3091
|
+
// helpers ////////////////////
|
|
3092
|
+
|
|
3093
|
+
/**
|
|
3094
|
+
* Sorts given items alphanumeric by label
|
|
3095
|
+
*/
|
|
3096
|
+
function sortItems(items) {
|
|
3097
|
+
return minDash.sortBy(items, i => i.label.toLowerCase());
|
|
3098
|
+
}
|
|
3099
|
+
function getItem(items, id) {
|
|
3100
|
+
return minDash.find(items, i => i.id === id);
|
|
3101
|
+
}
|
|
3102
|
+
function createOrdering(items) {
|
|
3103
|
+
return items.map(i => i.id);
|
|
3104
|
+
}
|
|
3105
|
+
|
|
3106
|
+
function Checkbox(props) {
|
|
3107
|
+
const {
|
|
3108
|
+
id,
|
|
3109
|
+
label,
|
|
3110
|
+
onChange,
|
|
3111
|
+
disabled,
|
|
3112
|
+
value = false,
|
|
3113
|
+
onFocus,
|
|
3114
|
+
onBlur,
|
|
3115
|
+
tooltip
|
|
3116
|
+
} = props;
|
|
3117
|
+
const [localValue, setLocalValue] = hooks.useState(value);
|
|
3118
|
+
const handleChangeCallback = ({
|
|
3119
|
+
target
|
|
3120
|
+
}) => {
|
|
3121
|
+
onChange(target.checked);
|
|
3122
|
+
};
|
|
3123
|
+
const handleChange = e => {
|
|
3124
|
+
handleChangeCallback(e);
|
|
3125
|
+
setLocalValue(e.target.value);
|
|
3126
|
+
};
|
|
3127
|
+
hooks.useEffect(() => {
|
|
3128
|
+
if (value === localValue) {
|
|
3129
|
+
return;
|
|
3130
|
+
}
|
|
3131
|
+
setLocalValue(value);
|
|
3132
|
+
}, [value]);
|
|
3133
|
+
const ref = useShowEntryEvent(id);
|
|
3134
|
+
return jsxRuntime.jsxs("div", {
|
|
3135
|
+
class: "bio-properties-panel-checkbox",
|
|
3136
|
+
children: [jsxRuntime.jsx("input", {
|
|
3137
|
+
ref: ref,
|
|
3138
|
+
id: prefixId$4(id),
|
|
3139
|
+
name: id,
|
|
3140
|
+
onFocus: onFocus,
|
|
3141
|
+
onBlur: onBlur,
|
|
3142
|
+
type: "checkbox",
|
|
3143
|
+
class: "bio-properties-panel-input",
|
|
3144
|
+
onChange: handleChange,
|
|
3145
|
+
checked: localValue,
|
|
3146
|
+
disabled: disabled
|
|
3147
|
+
}), jsxRuntime.jsx("label", {
|
|
3148
|
+
for: prefixId$4(id),
|
|
3149
|
+
class: "bio-properties-panel-label",
|
|
3150
|
+
children: jsxRuntime.jsx(TooltipWrapper, {
|
|
3151
|
+
value: tooltip,
|
|
3152
|
+
forId: id,
|
|
3153
|
+
element: props.element,
|
|
3154
|
+
children: label
|
|
3155
|
+
})
|
|
3156
|
+
})]
|
|
3157
|
+
});
|
|
3158
|
+
}
|
|
2432
3159
|
|
|
2433
3160
|
/**
|
|
2434
3161
|
* @param {Object} props
|
|
2435
3162
|
* @param {Object} props.element
|
|
2436
3163
|
* @param {String} props.id
|
|
2437
3164
|
* @param {String} props.description
|
|
2438
|
-
* @param {Boolean} props.debounce
|
|
2439
|
-
* @param {Boolean} props.disabled
|
|
2440
|
-
* @param {Boolean} props.feel
|
|
2441
3165
|
* @param {String} props.label
|
|
2442
3166
|
* @param {Function} props.getValue
|
|
2443
3167
|
* @param {Function} props.setValue
|
|
2444
|
-
* @param {Function} props.tooltipContainer
|
|
2445
|
-
* @param {Function} props.validate
|
|
2446
|
-
* @param {Function} props.show
|
|
2447
|
-
* @param {Function} props.example
|
|
2448
|
-
* @param {Function} props.variables
|
|
2449
3168
|
* @param {Function} props.onFocus
|
|
2450
3169
|
* @param {Function} props.onBlur
|
|
2451
3170
|
* @param {string|import('preact').Component} props.tooltip
|
|
3171
|
+
* @param {boolean} [props.disabled]
|
|
2452
3172
|
*/
|
|
2453
|
-
function
|
|
3173
|
+
function CheckboxEntry(props) {
|
|
2454
3174
|
const {
|
|
2455
3175
|
element,
|
|
2456
3176
|
id,
|
|
2457
3177
|
description,
|
|
2458
|
-
debounce,
|
|
2459
|
-
disabled,
|
|
2460
|
-
feel,
|
|
2461
3178
|
label,
|
|
2462
3179
|
getValue,
|
|
2463
3180
|
setValue,
|
|
2464
|
-
|
|
2465
|
-
hostLanguage,
|
|
2466
|
-
singleLine,
|
|
2467
|
-
validate,
|
|
2468
|
-
show = noop$1,
|
|
2469
|
-
example,
|
|
2470
|
-
variables,
|
|
3181
|
+
disabled,
|
|
2471
3182
|
onFocus,
|
|
2472
3183
|
onBlur,
|
|
2473
3184
|
tooltip
|
|
2474
3185
|
} = props;
|
|
2475
|
-
const
|
|
2476
|
-
const
|
|
2477
|
-
let value = getValue(element);
|
|
2478
|
-
hooks.useEffect(() => {
|
|
2479
|
-
if (minDash.isFunction(validate)) {
|
|
2480
|
-
const newValidationError = validate(value) || null;
|
|
2481
|
-
setValidationError(newValidationError);
|
|
2482
|
-
}
|
|
2483
|
-
}, [value]);
|
|
2484
|
-
const onInput = useStaticCallback(newValue => {
|
|
2485
|
-
let newValidationError = null;
|
|
2486
|
-
if (minDash.isFunction(validate)) {
|
|
2487
|
-
newValidationError = validate(newValue) || null;
|
|
2488
|
-
}
|
|
2489
|
-
|
|
2490
|
-
// don't create multiple commandStack entries for the same value
|
|
2491
|
-
if (newValue !== value) {
|
|
2492
|
-
setValue(newValue, newValidationError);
|
|
2493
|
-
}
|
|
2494
|
-
setValidationError(newValidationError);
|
|
2495
|
-
});
|
|
2496
|
-
const onError = hooks.useCallback(err => {
|
|
2497
|
-
setLocalError(err);
|
|
2498
|
-
}, []);
|
|
2499
|
-
const temporaryError = useError(id);
|
|
2500
|
-
const error = localError || temporaryError || validationError;
|
|
3186
|
+
const value = getValue(element);
|
|
3187
|
+
const error = useError(id);
|
|
2501
3188
|
return jsxRuntime.jsxs("div", {
|
|
2502
|
-
class:
|
|
3189
|
+
class: "bio-properties-panel-entry bio-properties-panel-checkbox-entry",
|
|
2503
3190
|
"data-entry-id": id,
|
|
2504
|
-
children: [
|
|
2505
|
-
...props,
|
|
2506
|
-
debounce: debounce,
|
|
3191
|
+
children: [jsxRuntime.jsx(Checkbox, {
|
|
2507
3192
|
disabled: disabled,
|
|
2508
|
-
feel: feel,
|
|
2509
3193
|
id: id,
|
|
2510
|
-
key: element,
|
|
2511
3194
|
label: label,
|
|
2512
|
-
|
|
2513
|
-
onError: onError,
|
|
3195
|
+
onChange: setValue,
|
|
2514
3196
|
onFocus: onFocus,
|
|
2515
3197
|
onBlur: onBlur,
|
|
2516
|
-
example: example,
|
|
2517
|
-
hostLanguage: hostLanguage,
|
|
2518
|
-
singleLine: singleLine,
|
|
2519
|
-
show: show,
|
|
2520
3198
|
value: value,
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
tooltip: tooltip
|
|
2525
|
-
}), error && jsxRuntime.jsx("div", {
|
|
3199
|
+
tooltip: tooltip,
|
|
3200
|
+
element: element
|
|
3201
|
+
}, element), error && jsxRuntime.jsx("div", {
|
|
2526
3202
|
class: "bio-properties-panel-error",
|
|
2527
3203
|
children: error
|
|
2528
3204
|
}), jsxRuntime.jsx(Description, {
|
|
@@ -2532,154 +3208,8 @@ function FeelEntry(props) {
|
|
|
2532
3208
|
})]
|
|
2533
3209
|
});
|
|
2534
3210
|
}
|
|
2535
|
-
|
|
2536
|
-
/**
|
|
2537
|
-
* @param {Object} props
|
|
2538
|
-
* @param {Object} props.element
|
|
2539
|
-
* @param {String} props.id
|
|
2540
|
-
* @param {String} props.description
|
|
2541
|
-
* @param {Boolean} props.debounce
|
|
2542
|
-
* @param {Boolean} props.disabled
|
|
2543
|
-
* @param {String} props.max
|
|
2544
|
-
* @param {String} props.min
|
|
2545
|
-
* @param {String} props.step
|
|
2546
|
-
* @param {Boolean} props.feel
|
|
2547
|
-
* @param {String} props.label
|
|
2548
|
-
* @param {Function} props.getValue
|
|
2549
|
-
* @param {Function} props.setValue
|
|
2550
|
-
* @param {Function} props.tooltipContainer
|
|
2551
|
-
* @param {Function} props.validate
|
|
2552
|
-
* @param {Function} props.show
|
|
2553
|
-
* @param {Function} props.example
|
|
2554
|
-
* @param {Function} props.variables
|
|
2555
|
-
* @param {Function} props.onFocus
|
|
2556
|
-
* @param {Function} props.onBlur
|
|
2557
|
-
*/
|
|
2558
|
-
function FeelNumberEntry(props) {
|
|
2559
|
-
return jsxRuntime.jsx(FeelEntry, {
|
|
2560
|
-
class: "bio-properties-panel-feel-number",
|
|
2561
|
-
OptionalComponent: OptionalFeelNumberField,
|
|
2562
|
-
...props
|
|
2563
|
-
});
|
|
2564
|
-
}
|
|
2565
|
-
|
|
2566
|
-
/**
|
|
2567
|
-
* @param {Object} props
|
|
2568
|
-
* @param {Object} props.element
|
|
2569
|
-
* @param {String} props.id
|
|
2570
|
-
* @param {String} props.description
|
|
2571
|
-
* @param {Boolean} props.debounce
|
|
2572
|
-
* @param {Boolean} props.disabled
|
|
2573
|
-
* @param {Boolean} props.feel
|
|
2574
|
-
* @param {String} props.label
|
|
2575
|
-
* @param {Function} props.getValue
|
|
2576
|
-
* @param {Function} props.setValue
|
|
2577
|
-
* @param {Function} props.tooltipContainer
|
|
2578
|
-
* @param {Function} props.validate
|
|
2579
|
-
* @param {Function} props.show
|
|
2580
|
-
* @param {Function} props.example
|
|
2581
|
-
* @param {Function} props.variables
|
|
2582
|
-
* @param {Function} props.onFocus
|
|
2583
|
-
* @param {Function} props.onBlur
|
|
2584
|
-
*/
|
|
2585
|
-
function FeelTextAreaEntry(props) {
|
|
2586
|
-
return jsxRuntime.jsx(FeelEntry, {
|
|
2587
|
-
class: "bio-properties-panel-feel-textarea",
|
|
2588
|
-
OptionalComponent: OptionalFeelTextArea,
|
|
2589
|
-
...props
|
|
2590
|
-
});
|
|
2591
|
-
}
|
|
2592
|
-
|
|
2593
|
-
/**
|
|
2594
|
-
* @param {Object} props
|
|
2595
|
-
* @param {Object} props.element
|
|
2596
|
-
* @param {String} props.id
|
|
2597
|
-
* @param {String} props.description
|
|
2598
|
-
* @param {Boolean} props.debounce
|
|
2599
|
-
* @param {Boolean} props.disabled
|
|
2600
|
-
* @param {Boolean} props.feel
|
|
2601
|
-
* @param {String} props.label
|
|
2602
|
-
* @param {Function} props.getValue
|
|
2603
|
-
* @param {Function} props.setValue
|
|
2604
|
-
* @param {Function} props.tooltipContainer
|
|
2605
|
-
* @param {Function} props.validate
|
|
2606
|
-
* @param {Function} props.show
|
|
2607
|
-
* @param {Function} props.example
|
|
2608
|
-
* @param {Function} props.variables
|
|
2609
|
-
* @param {Function} props.onFocus
|
|
2610
|
-
* @param {Function} props.onBlur
|
|
2611
|
-
*/
|
|
2612
|
-
function FeelToggleSwitchEntry(props) {
|
|
2613
|
-
return jsxRuntime.jsx(FeelEntry, {
|
|
2614
|
-
class: "bio-properties-panel-feel-toggle-switch",
|
|
2615
|
-
OptionalComponent: OptionalFeelToggleSwitch,
|
|
2616
|
-
...props
|
|
2617
|
-
});
|
|
2618
|
-
}
|
|
2619
|
-
|
|
2620
|
-
/**
|
|
2621
|
-
* @param {Object} props
|
|
2622
|
-
* @param {Object} props.element
|
|
2623
|
-
* @param {String} props.id
|
|
2624
|
-
* @param {String} props.description
|
|
2625
|
-
* @param {Boolean} props.debounce
|
|
2626
|
-
* @param {Boolean} props.disabled
|
|
2627
|
-
* @param {Boolean} props.feel
|
|
2628
|
-
* @param {String} props.label
|
|
2629
|
-
* @param {Function} props.getValue
|
|
2630
|
-
* @param {Function} props.setValue
|
|
2631
|
-
* @param {Function} props.tooltipContainer
|
|
2632
|
-
* @param {Function} props.validate
|
|
2633
|
-
* @param {Function} props.show
|
|
2634
|
-
* @param {Function} props.example
|
|
2635
|
-
* @param {Function} props.variables
|
|
2636
|
-
* @param {Function} props.onFocus
|
|
2637
|
-
* @param {Function} props.onBlur
|
|
2638
|
-
*/
|
|
2639
|
-
function FeelCheckboxEntry(props) {
|
|
2640
|
-
return jsxRuntime.jsx(FeelEntry, {
|
|
2641
|
-
class: "bio-properties-panel-feel-checkbox",
|
|
2642
|
-
OptionalComponent: OptionalFeelCheckbox,
|
|
2643
|
-
...props
|
|
2644
|
-
});
|
|
2645
|
-
}
|
|
2646
|
-
|
|
2647
|
-
/**
|
|
2648
|
-
* @param {Object} props
|
|
2649
|
-
* @param {Object} props.element
|
|
2650
|
-
* @param {String} props.id
|
|
2651
|
-
* @param {String} props.description
|
|
2652
|
-
* @param {String} props.hostLanguage
|
|
2653
|
-
* @param {Boolean} props.singleLine
|
|
2654
|
-
* @param {Boolean} props.debounce
|
|
2655
|
-
* @param {Boolean} props.disabled
|
|
2656
|
-
* @param {Boolean} props.feel
|
|
2657
|
-
* @param {String} props.label
|
|
2658
|
-
* @param {Function} props.getValue
|
|
2659
|
-
* @param {Function} props.setValue
|
|
2660
|
-
* @param {Function} props.tooltipContainer
|
|
2661
|
-
* @param {Function} props.validate
|
|
2662
|
-
* @param {Function} props.show
|
|
2663
|
-
* @param {Function} props.example
|
|
2664
|
-
* @param {Function} props.variables
|
|
2665
|
-
* @param {Function} props.onFocus
|
|
2666
|
-
* @param {Function} props.onBlur
|
|
2667
|
-
*/
|
|
2668
|
-
function FeelTemplatingEntry(props) {
|
|
2669
|
-
return jsxRuntime.jsx(FeelEntry, {
|
|
2670
|
-
class: "bio-properties-panel-feel-templating",
|
|
2671
|
-
OptionalComponent: CodeEditor$1,
|
|
2672
|
-
...props
|
|
2673
|
-
});
|
|
2674
|
-
}
|
|
2675
3211
|
function isEdited$5(node) {
|
|
2676
|
-
|
|
2677
|
-
return false;
|
|
2678
|
-
}
|
|
2679
|
-
if (node.type === 'checkbox') {
|
|
2680
|
-
return !!node.checked || node.classList.contains('edited');
|
|
2681
|
-
}
|
|
2682
|
-
return !!node.value || node.classList.contains('edited');
|
|
3212
|
+
return node && !!node.checked;
|
|
2683
3213
|
}
|
|
2684
3214
|
|
|
2685
3215
|
// helpers /////////////////
|
|
@@ -3570,6 +4100,7 @@ exports.DebounceInputModule = index;
|
|
|
3570
4100
|
exports.DeleteIcon = DeleteIcon;
|
|
3571
4101
|
exports.DescriptionContext = DescriptionContext;
|
|
3572
4102
|
exports.DescriptionEntry = Description;
|
|
4103
|
+
exports.DragIcon = DragIcon;
|
|
3573
4104
|
exports.DropdownButton = DropdownButton;
|
|
3574
4105
|
exports.ErrorsContext = ErrorsContext;
|
|
3575
4106
|
exports.EventContext = EventContext;
|
|
@@ -3590,6 +4121,7 @@ exports.ListGroup = ListGroup;
|
|
|
3590
4121
|
exports.ListItem = ListItem;
|
|
3591
4122
|
exports.NumberFieldEntry = NumberFieldEntry;
|
|
3592
4123
|
exports.Placeholder = Placeholder;
|
|
4124
|
+
exports.Popup = Popup;
|
|
3593
4125
|
exports.PropertiesPanel = PropertiesPanel;
|
|
3594
4126
|
exports.PropertiesPanelContext = LayoutContext;
|
|
3595
4127
|
exports.SelectEntry = SelectEntry;
|
|
@@ -3599,15 +4131,15 @@ exports.TextAreaEntry = TextAreaEntry;
|
|
|
3599
4131
|
exports.TextFieldEntry = TextfieldEntry;
|
|
3600
4132
|
exports.ToggleSwitchEntry = ToggleSwitchEntry;
|
|
3601
4133
|
exports.TooltipContext = TooltipContext;
|
|
3602
|
-
exports.isCheckboxEntryEdited = isEdited$
|
|
3603
|
-
exports.isFeelEntryEdited = isEdited$
|
|
3604
|
-
exports.isNumberFieldEntryEdited = isEdited$
|
|
4134
|
+
exports.isCheckboxEntryEdited = isEdited$5;
|
|
4135
|
+
exports.isFeelEntryEdited = isEdited$6;
|
|
4136
|
+
exports.isNumberFieldEntryEdited = isEdited$7;
|
|
3605
4137
|
exports.isSelectEntryEdited = isEdited$3;
|
|
3606
4138
|
exports.isSimpleEntryEdited = isEdited$2;
|
|
3607
4139
|
exports.isTemplatingEntryEdited = isEdited$4;
|
|
3608
4140
|
exports.isTextAreaEntryEdited = isEdited$1;
|
|
3609
4141
|
exports.isTextFieldEntryEdited = isEdited;
|
|
3610
|
-
exports.isToggleSwitchEntryEdited = isEdited$
|
|
4142
|
+
exports.isToggleSwitchEntryEdited = isEdited$8;
|
|
3611
4143
|
exports.useDescriptionContext = useDescriptionContext;
|
|
3612
4144
|
exports.useError = useError;
|
|
3613
4145
|
exports.useErrors = useErrors;
|