@bpmn-io/form-js-editor 1.26.0 → 2.0.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/form-js-editor-base.css +69 -132
- package/dist/assets/form-js-editor.css +482 -271
- package/dist/assets/properties-panel.css +449 -179
- package/dist/index.cjs +329 -139
- package/dist/index.cjs.map +1 -1
- package/dist/index.es.js +333 -143
- package/dist/index.es.js.map +1 -1
- package/package.json +7 -5
package/dist/index.es.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { Ids } from 'ids';
|
|
2
|
-
import { FormFieldRegistry as FormFieldRegistry$1, iconsByType, Label as Label$3, IFrame, Text as Text$1, Html, Table, ExpressionField, DocumentPreview, FormFields, sanitizeImageSource, getSchemaVariables, getAncestryList, FormContext, FormRenderContext, FormComponent, getScrollContainer, FieldFactory, FormLayouter, PathRegistry, Importer, FeelExpressionLanguage, OPTIONS_SOURCES, OPTIONS_SOURCES_PATHS, clone, runRecursively, DATETIME_SUBTYPES, DATE_LABEL_PATH, TIME_LABEL_PATH, TEXT_VIEW_DEFAULT_TEXT, TIME_USE24H_PATH, DATETIME_SUBTYPE_PATH, DATETIME_SUBTYPES_LABELS, TIME_INTERVAL_PATH, TIME_SERIALISING_FORMAT_PATH, DATE_DISALLOW_PAST_PATH, TIME_SERIALISING_FORMATS, TIME_SERIALISINGFORMAT_LABELS, getOptionsSource, OPTIONS_SOURCES_DEFAULTS, OPTIONS_SOURCES_LABELS, SECURITY_ATTRIBUTES_DEFINITIONS, createFormContainer, createInjector, MarkdownRendererModule, schemaVersion } from '@bpmn-io/form-js-viewer';
|
|
2
|
+
import { FormFieldRegistry as FormFieldRegistry$1, iconsByType, Label as Label$3, IFrame, Text as Text$1, Html, Table, ExpressionField, DocumentPreview, FormFields, sanitizeImageSource, getSchemaVariables, getAncestryList, FormContext, FormRenderContext, FormComponent, getScrollContainer as getScrollContainer$1, FieldFactory, FormLayouter, PathRegistry, Importer, FeelExpressionLanguage, OPTIONS_SOURCES, OPTIONS_SOURCES_PATHS, clone, runRecursively, DATETIME_SUBTYPES, DATE_LABEL_PATH, TIME_LABEL_PATH, TEXT_VIEW_DEFAULT_TEXT, TIME_USE24H_PATH, DATETIME_SUBTYPE_PATH, DATETIME_SUBTYPES_LABELS, TIME_INTERVAL_PATH, TIME_SERIALISING_FORMAT_PATH, DATE_DISALLOW_PAST_PATH, TIME_SERIALISING_FORMATS, TIME_SERIALISINGFORMAT_LABELS, getOptionsSource, OPTIONS_SOURCES_DEFAULTS, OPTIONS_SOURCES_LABELS, SECURITY_ATTRIBUTES_DEFINITIONS, createFormContainer, createInjector, MarkdownRendererModule, schemaVersion } from '@bpmn-io/form-js-viewer';
|
|
3
3
|
export { schemaVersion } from '@bpmn-io/form-js-viewer';
|
|
4
|
-
import { isArray, isFunction, isNumber, bind, assign, debounce, isString, set as set$1, get, reduce, forEach, uniqueBy, isObject,
|
|
4
|
+
import { isArray, isFunction, isNumber, bind, assign, debounce, isString, isDefined, set as set$1, get, reduce, forEach, uniqueBy, isObject, isNil, without, has } from 'min-dash';
|
|
5
5
|
import classnames from 'classnames';
|
|
6
6
|
import { jsxs, jsx, Fragment as Fragment$1 } from 'preact/jsx-runtime';
|
|
7
7
|
import { useContext, useRef, useEffect, useMemo, useState, useCallback, useLayoutEffect } from 'preact/hooks';
|
|
8
8
|
import { createContext, Fragment, render, createElement as createElement$1 } from 'preact';
|
|
9
9
|
import * as React from 'preact/compat';
|
|
10
10
|
import { createPortal, useRef as useRef$1, useContext as useContext$1, useEffect as useEffect$1, forwardRef } from 'preact/compat';
|
|
11
|
-
import { query, domify, classes, event } from 'min-dom';
|
|
11
|
+
import { query, closest, domify, classes, event } from 'min-dom';
|
|
12
12
|
import { EditorView, lineNumbers } from '@codemirror/view';
|
|
13
13
|
import { Annotation } from '@codemirror/state';
|
|
14
14
|
import '@codemirror/language';
|
|
@@ -64,7 +64,7 @@ var TranslateModule = {
|
|
|
64
64
|
};
|
|
65
65
|
|
|
66
66
|
var FN_REF = '__fn';
|
|
67
|
-
var DEFAULT_PRIORITY$
|
|
67
|
+
var DEFAULT_PRIORITY$5 = 1000;
|
|
68
68
|
var slice = Array.prototype.slice;
|
|
69
69
|
|
|
70
70
|
/**
|
|
@@ -232,7 +232,7 @@ EventBus.prototype.on = function (events, priority, callback, that) {
|
|
|
232
232
|
if (isFunction(priority)) {
|
|
233
233
|
that = callback;
|
|
234
234
|
callback = priority;
|
|
235
|
-
priority = DEFAULT_PRIORITY$
|
|
235
|
+
priority = DEFAULT_PRIORITY$5;
|
|
236
236
|
}
|
|
237
237
|
if (!isNumber(priority)) {
|
|
238
238
|
throw new Error('priority must be a number');
|
|
@@ -283,7 +283,7 @@ EventBus.prototype.once = function (events, priority, callback, that) {
|
|
|
283
283
|
if (isFunction(priority)) {
|
|
284
284
|
that = callback;
|
|
285
285
|
callback = priority;
|
|
286
|
-
priority = DEFAULT_PRIORITY$
|
|
286
|
+
priority = DEFAULT_PRIORITY$5;
|
|
287
287
|
}
|
|
288
288
|
if (!isNumber(priority)) {
|
|
289
289
|
throw new Error('priority must be a number');
|
|
@@ -1365,7 +1365,7 @@ const ModularSection = props => {
|
|
|
1365
1365
|
}) => RootElement ? jsx(RootElement, {
|
|
1366
1366
|
children: children
|
|
1367
1367
|
}) : jsx("div", {
|
|
1368
|
-
className: rootClass,
|
|
1368
|
+
className: classnames(rootClass, 'bio-theme-parent'),
|
|
1369
1369
|
children: children
|
|
1370
1370
|
}), [rootClass, RootElement]);
|
|
1371
1371
|
return shouldRender ? parent ? createPortal(jsx(Root, {
|
|
@@ -2076,7 +2076,8 @@ const EventContext = createContext({
|
|
|
2076
2076
|
* @typedef { {
|
|
2077
2077
|
* parserDialect?: import('@bpmn-io/feel-editor').ParserDialect,
|
|
2078
2078
|
* builtins?: import('@bpmn-io/feel-editor').Variable[],
|
|
2079
|
-
* dialect?: import('@bpmn-io/feel-editor').Dialect
|
|
2079
|
+
* dialect?: import('@bpmn-io/feel-editor').Dialect,
|
|
2080
|
+
* engines?: Record<string, string>
|
|
2080
2081
|
* } } FeelLanguageContextType
|
|
2081
2082
|
*/
|
|
2082
2083
|
|
|
@@ -2278,7 +2279,7 @@ function Tooltip(props) {
|
|
|
2278
2279
|
const tooltipStyle = position || (tooltipPosition ? `right: ${tooltipPosition.right}; top: ${tooltipPosition.top}px;` : undefined);
|
|
2279
2280
|
const arrowStyle = arrowOffset != null ? `margin-top: ${arrowOffset}px;` : undefined;
|
|
2280
2281
|
return jsxs("div", {
|
|
2281
|
-
class: `bio-properties-panel-tooltip ${direction}`,
|
|
2282
|
+
class: `bio-properties-panel-tooltip bio-theme-parent ${direction}`,
|
|
2282
2283
|
role: "tooltip",
|
|
2283
2284
|
id: "bio-properties-panel-tooltip",
|
|
2284
2285
|
"aria-labelledby": forId,
|
|
@@ -2516,24 +2517,32 @@ function useShowEntryEvent(id) {
|
|
|
2516
2517
|
* @param {boolean} value
|
|
2517
2518
|
*/
|
|
2518
2519
|
|
|
2520
|
+
/**
|
|
2521
|
+
* Resolve scroll container closest to the referenced element.
|
|
2522
|
+
*/
|
|
2523
|
+
function getScrollContainer(ref, scrollContainerSelector) {
|
|
2524
|
+
return ref.current ? closest(ref.current, scrollContainerSelector, true) : null;
|
|
2525
|
+
}
|
|
2526
|
+
|
|
2519
2527
|
/**
|
|
2520
2528
|
* Use IntersectionObserver to identify when DOM element is in sticky mode.
|
|
2529
|
+
*
|
|
2521
2530
|
* If sticky is observered setSticky(true) will be called.
|
|
2522
2531
|
* If sticky mode is left, setSticky(false) will be called.
|
|
2523
2532
|
*
|
|
2524
|
-
*
|
|
2525
2533
|
* @param {Object} ref
|
|
2526
2534
|
* @param {string} scrollContainerSelector
|
|
2527
2535
|
* @param {setSticky} setSticky
|
|
2528
2536
|
*/
|
|
2529
2537
|
function useStickyIntersectionObserver(ref, scrollContainerSelector, setSticky) {
|
|
2530
|
-
|
|
2538
|
+
// resolved from the observed element after mount (see effect below)
|
|
2539
|
+
const [scrollContainer, setScrollContainer] = useState(null);
|
|
2531
2540
|
const updateScrollContainer = useCallback(() => {
|
|
2532
|
-
const newScrollContainer =
|
|
2541
|
+
const newScrollContainer = getScrollContainer(ref, scrollContainerSelector);
|
|
2533
2542
|
if (newScrollContainer !== scrollContainer) {
|
|
2534
2543
|
setScrollContainer(newScrollContainer);
|
|
2535
2544
|
}
|
|
2536
|
-
}, [scrollContainerSelector, scrollContainer]);
|
|
2545
|
+
}, [ref, scrollContainerSelector, scrollContainer]);
|
|
2537
2546
|
useEffect(() => {
|
|
2538
2547
|
updateScrollContainer();
|
|
2539
2548
|
}, [updateScrollContainer]);
|
|
@@ -2546,9 +2555,8 @@ function useStickyIntersectionObserver(ref, scrollContainerSelector, setSticky)
|
|
|
2546
2555
|
if (!Observer) {
|
|
2547
2556
|
return;
|
|
2548
2557
|
}
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
if (!ref.current || !scrollContainer) {
|
|
2558
|
+
const element = ref.current;
|
|
2559
|
+
if (!element || !scrollContainer) {
|
|
2552
2560
|
return;
|
|
2553
2561
|
}
|
|
2554
2562
|
const observer = new Observer(entries => {
|
|
@@ -2569,13 +2577,13 @@ function useStickyIntersectionObserver(ref, scrollContainerSelector, setSticky)
|
|
|
2569
2577
|
// Use bottom margin to avoid stickyness when scrolling out to bottom
|
|
2570
2578
|
threshold: [1]
|
|
2571
2579
|
});
|
|
2572
|
-
observer.observe(
|
|
2580
|
+
observer.observe(element);
|
|
2573
2581
|
|
|
2574
2582
|
// Unobserve if unmounted
|
|
2575
2583
|
return () => {
|
|
2576
|
-
observer.unobserve(
|
|
2584
|
+
observer.unobserve(element);
|
|
2577
2585
|
};
|
|
2578
|
-
}, [ref
|
|
2586
|
+
}, [ref, scrollContainer, setSticky]);
|
|
2579
2587
|
}
|
|
2580
2588
|
|
|
2581
2589
|
/**
|
|
@@ -2602,23 +2610,6 @@ function useStaticCallback(callback) {
|
|
|
2602
2610
|
});
|
|
2603
2611
|
return useCallback((...args) => callbackRef.current(...args), []);
|
|
2604
2612
|
}
|
|
2605
|
-
function useElementVisible(element) {
|
|
2606
|
-
const [visible, setVisible] = useState(!!element && !!element.clientHeight);
|
|
2607
|
-
useLayoutEffect(() => {
|
|
2608
|
-
if (!element) return;
|
|
2609
|
-
const resizeObserver = new ResizeObserver(([entry]) => {
|
|
2610
|
-
requestAnimationFrame(() => {
|
|
2611
|
-
const newVisible = !!entry.contentRect.height;
|
|
2612
|
-
if (newVisible !== visible) {
|
|
2613
|
-
setVisible(newVisible);
|
|
2614
|
-
}
|
|
2615
|
-
});
|
|
2616
|
-
});
|
|
2617
|
-
resizeObserver.observe(element);
|
|
2618
|
-
return () => resizeObserver.disconnect();
|
|
2619
|
-
}, [element, visible]);
|
|
2620
|
-
return visible;
|
|
2621
|
-
}
|
|
2622
2613
|
|
|
2623
2614
|
/**
|
|
2624
2615
|
* @param {import('../PropertiesPanel').GroupDefinition} props
|
|
@@ -2970,7 +2961,7 @@ function PropertiesPanel$1(props) {
|
|
|
2970
2961
|
children: jsx(EventContext.Provider, {
|
|
2971
2962
|
value: eventContext,
|
|
2972
2963
|
children: jsxs("div", {
|
|
2973
|
-
class: "bio-properties-panel",
|
|
2964
|
+
class: "bio-properties-panel bio-theme-parent",
|
|
2974
2965
|
children: [headerProvider ? jsx(Header, {
|
|
2975
2966
|
element: element,
|
|
2976
2967
|
headerProvider: headerProvider
|
|
@@ -3061,16 +3052,17 @@ function CollapsibleEntry(props) {
|
|
|
3061
3052
|
}, [onShow, setOpen])
|
|
3062
3053
|
};
|
|
3063
3054
|
const placeholderLabel = translate('<empty>');
|
|
3055
|
+
const hasEntries = entries.length > 0;
|
|
3064
3056
|
return jsxs("div", {
|
|
3065
3057
|
"data-entry-id": id,
|
|
3066
3058
|
class: classnames('bio-properties-panel-collapsible-entry', open ? 'open' : ''),
|
|
3067
3059
|
children: [jsxs("div", {
|
|
3068
3060
|
class: "bio-properties-panel-collapsible-entry-header",
|
|
3069
|
-
onClick: toggleOpen,
|
|
3061
|
+
onClick: hasEntries ? toggleOpen : null,
|
|
3070
3062
|
children: [jsx("div", {
|
|
3071
3063
|
class: classnames('bio-properties-panel-collapsible-entry-header-title', !label && 'empty'),
|
|
3072
3064
|
children: label || placeholderLabel
|
|
3073
|
-
}), jsx("button", {
|
|
3065
|
+
}), hasEntries && jsx("button", {
|
|
3074
3066
|
type: "button",
|
|
3075
3067
|
title: translate('Toggle list item'),
|
|
3076
3068
|
class: "bio-properties-panel-arrow bio-properties-panel-collapsible-entry-arrow",
|
|
@@ -3586,7 +3578,8 @@ const FeelEditor = forwardRef((props, ref) => {
|
|
|
3586
3578
|
const {
|
|
3587
3579
|
builtins,
|
|
3588
3580
|
dialect,
|
|
3589
|
-
parserDialect
|
|
3581
|
+
parserDialect,
|
|
3582
|
+
engines
|
|
3590
3583
|
} = feelLanguageContext || {};
|
|
3591
3584
|
useBufferedFocus(editor, ref);
|
|
3592
3585
|
const handleInput = useStaticCallback(newValue => {
|
|
@@ -3629,6 +3622,7 @@ const FeelEditor = forwardRef((props, ref) => {
|
|
|
3629
3622
|
builtins,
|
|
3630
3623
|
dialect,
|
|
3631
3624
|
parserDialect,
|
|
3625
|
+
engines,
|
|
3632
3626
|
extensions: [...(enableGutters ? [lineNumbers()] : []), EditorView.lineWrapping, EditorView.domEventHandlers({
|
|
3633
3627
|
blur: handleBlur
|
|
3634
3628
|
})],
|
|
@@ -3663,6 +3657,12 @@ const FeelEditor = forwardRef((props, ref) => {
|
|
|
3663
3657
|
}
|
|
3664
3658
|
editor.setPlaceholder(placeholder);
|
|
3665
3659
|
}, [placeholder]);
|
|
3660
|
+
useEffect(() => {
|
|
3661
|
+
if (!editor) {
|
|
3662
|
+
return;
|
|
3663
|
+
}
|
|
3664
|
+
editor.setEngines(engines);
|
|
3665
|
+
}, [engines]);
|
|
3666
3666
|
const handleClick = () => {
|
|
3667
3667
|
ref.current.focus();
|
|
3668
3668
|
};
|
|
@@ -4984,16 +4984,10 @@ function isEdited$3(node) {
|
|
|
4984
4984
|
function prefixId$4(id) {
|
|
4985
4985
|
return `bio-properties-panel-${id}`;
|
|
4986
4986
|
}
|
|
4987
|
-
function resizeToContents(element) {
|
|
4988
|
-
element.style.height = 'auto';
|
|
4989
|
-
|
|
4990
|
-
// a 2px pixel offset is required to prevent scrollbar from
|
|
4991
|
-
// appearing on OS with a full length scroll bar (Windows/Linux)
|
|
4992
|
-
element.style.height = `${element.scrollHeight + 2}px`;
|
|
4993
|
-
}
|
|
4994
4987
|
function TextArea(props) {
|
|
4995
4988
|
const {
|
|
4996
4989
|
id,
|
|
4990
|
+
element,
|
|
4997
4991
|
label,
|
|
4998
4992
|
debounce,
|
|
4999
4993
|
onInput: commitValue,
|
|
@@ -5006,22 +5000,31 @@ function TextArea(props) {
|
|
|
5006
5000
|
autoResize = true,
|
|
5007
5001
|
placeholder,
|
|
5008
5002
|
rows = autoResize ? 1 : 2,
|
|
5009
|
-
tooltip
|
|
5003
|
+
tooltip,
|
|
5004
|
+
translate = translateFallback
|
|
5010
5005
|
} = props;
|
|
5011
5006
|
const [localValue, setLocalValue] = useState(value);
|
|
5012
5007
|
const ref = useShowEntryEvent(id);
|
|
5008
|
+
const containerRef = useRef();
|
|
5009
|
+
|
|
5010
|
+
// keep a live reference to the current value so callbacks captured by the
|
|
5011
|
+
// popup (frozen at open time) can compare against the latest value
|
|
5012
|
+
const localValueRef = useRef(localValue);
|
|
5013
|
+
localValueRef.current = localValue;
|
|
5014
|
+
const {
|
|
5015
|
+
eventBus
|
|
5016
|
+
} = useContext(EventContext);
|
|
5017
|
+
const [isPopupOpen, setIsPopupOpen] = useState(false);
|
|
5013
5018
|
const onInput = useCallback(newValue => {
|
|
5014
5019
|
const newModelValue = newValue === '' ? undefined : newValue;
|
|
5015
5020
|
commitValue(newModelValue);
|
|
5016
5021
|
}, [commitValue]);
|
|
5017
|
-
const visible = useElementVisible(ref.current);
|
|
5018
5022
|
|
|
5019
5023
|
/**
|
|
5020
5024
|
* @type { import('min-dash').DebouncedFunction }
|
|
5021
5025
|
*/
|
|
5022
5026
|
const handleInput = useDebounce(onInput, debounce);
|
|
5023
5027
|
const handleLocalInput = e => {
|
|
5024
|
-
autoResize && resizeToContents(e.target);
|
|
5025
5028
|
if (e.target.value === localValue) {
|
|
5026
5029
|
return;
|
|
5027
5030
|
}
|
|
@@ -5066,12 +5069,35 @@ function TextArea(props) {
|
|
|
5066
5069
|
handleInput.flush?.();
|
|
5067
5070
|
}
|
|
5068
5071
|
};
|
|
5069
|
-
|
|
5070
|
-
|
|
5072
|
+
const handlePopupInput = newValue => {
|
|
5073
|
+
if (newValue === localValueRef.current) {
|
|
5074
|
+
return;
|
|
5075
|
+
}
|
|
5076
|
+
setLocalValue(newValue);
|
|
5077
|
+
handleInput(newValue);
|
|
5078
|
+
};
|
|
5079
|
+
const handleOpenPopup = () => {
|
|
5080
|
+
const isOpen = eventBus.fire('propertiesPanel.openPopup', {
|
|
5081
|
+
element,
|
|
5082
|
+
entryId: id,
|
|
5083
|
+
label,
|
|
5084
|
+
onInput: handlePopupInput,
|
|
5085
|
+
sourceElement: ref.current,
|
|
5086
|
+
value: localValue
|
|
5087
|
+
});
|
|
5088
|
+
if (isOpen) {
|
|
5089
|
+
eventBus.once('propertiesPanelPopup.close', () => {
|
|
5090
|
+
handleInput.flush?.();
|
|
5091
|
+
setIsPopupOpen(false);
|
|
5092
|
+
});
|
|
5093
|
+
}
|
|
5094
|
+
setIsPopupOpen(isOpen === true);
|
|
5095
|
+
};
|
|
5096
|
+
useEffect(() => {
|
|
5097
|
+
return () => {
|
|
5098
|
+
eventBus && eventBus.fire('propertiesPanel.closePopup');
|
|
5099
|
+
};
|
|
5071
5100
|
}, []);
|
|
5072
|
-
useLayoutEffect(() => {
|
|
5073
|
-
visible && autoResize && resizeToContents(ref.current);
|
|
5074
|
-
}, [visible]);
|
|
5075
5101
|
useEffect(() => {
|
|
5076
5102
|
if (value === localValue) {
|
|
5077
5103
|
return;
|
|
@@ -5086,25 +5112,35 @@ function TextArea(props) {
|
|
|
5086
5112
|
children: jsx(TooltipWrapper, {
|
|
5087
5113
|
value: tooltip,
|
|
5088
5114
|
forId: id,
|
|
5089
|
-
element:
|
|
5115
|
+
element: element,
|
|
5090
5116
|
children: label
|
|
5091
5117
|
})
|
|
5092
|
-
}),
|
|
5093
|
-
|
|
5094
|
-
|
|
5095
|
-
|
|
5096
|
-
|
|
5097
|
-
|
|
5098
|
-
|
|
5099
|
-
|
|
5100
|
-
|
|
5101
|
-
|
|
5102
|
-
|
|
5103
|
-
|
|
5104
|
-
|
|
5105
|
-
|
|
5106
|
-
|
|
5107
|
-
|
|
5118
|
+
}), jsxs("div", {
|
|
5119
|
+
class: classnames('bio-properties-panel-textarea-container', isPopupOpen ? 'popupOpen' : null),
|
|
5120
|
+
ref: containerRef,
|
|
5121
|
+
children: [isPopupOpen && jsx("div", {
|
|
5122
|
+
class: "bio-properties-panel-textarea__open-popup-placeholder",
|
|
5123
|
+
children: translate('Opened in editor')
|
|
5124
|
+
}), jsx("textarea", {
|
|
5125
|
+
ref: ref,
|
|
5126
|
+
id: prefixId$2(id),
|
|
5127
|
+
name: id,
|
|
5128
|
+
spellCheck: "false",
|
|
5129
|
+
class: classnames('bio-properties-panel-input', monospace ? 'bio-properties-panel-input-monospace' : '', autoResize ? 'auto-resize' : ''),
|
|
5130
|
+
onInput: handleLocalInput,
|
|
5131
|
+
onFocus: onFocus,
|
|
5132
|
+
onKeyDown: handleOnKeyDown,
|
|
5133
|
+
onBlur: handleOnBlur,
|
|
5134
|
+
onPaste: handleOnPaste,
|
|
5135
|
+
placeholder: placeholder,
|
|
5136
|
+
rows: rows,
|
|
5137
|
+
value: localValue,
|
|
5138
|
+
disabled: disabled,
|
|
5139
|
+
"data-gramm": "false"
|
|
5140
|
+
}), eventBus && !disabled && jsx(OpenPopupButton, {
|
|
5141
|
+
onClick: handleOpenPopup,
|
|
5142
|
+
translate: translate
|
|
5143
|
+
})]
|
|
5108
5144
|
})]
|
|
5109
5145
|
});
|
|
5110
5146
|
}
|
|
@@ -5125,6 +5161,7 @@ function TextArea(props) {
|
|
|
5125
5161
|
* @param {boolean} props.monospace
|
|
5126
5162
|
* @param {Function} [props.validate]
|
|
5127
5163
|
* @param {boolean} [props.disabled]
|
|
5164
|
+
* @param {Function} [props.translate]
|
|
5128
5165
|
*/
|
|
5129
5166
|
function TextAreaEntry(props) {
|
|
5130
5167
|
const {
|
|
@@ -5144,7 +5181,8 @@ function TextAreaEntry(props) {
|
|
|
5144
5181
|
onPaste,
|
|
5145
5182
|
placeholder,
|
|
5146
5183
|
autoResize,
|
|
5147
|
-
tooltip
|
|
5184
|
+
tooltip,
|
|
5185
|
+
translate
|
|
5148
5186
|
} = props;
|
|
5149
5187
|
const globalError = useError(id);
|
|
5150
5188
|
const [localError, setLocalError] = useState(null);
|
|
@@ -5185,6 +5223,7 @@ function TextAreaEntry(props) {
|
|
|
5185
5223
|
placeholder: placeholder,
|
|
5186
5224
|
autoResize: autoResize,
|
|
5187
5225
|
tooltip: tooltip,
|
|
5226
|
+
translate: translate,
|
|
5188
5227
|
element: element
|
|
5189
5228
|
}, element), error && jsx("div", {
|
|
5190
5229
|
class: "bio-properties-panel-error",
|
|
@@ -5400,6 +5439,16 @@ function isEdited(node) {
|
|
|
5400
5439
|
function prefixId$1(id) {
|
|
5401
5440
|
return `bio-properties-panel-${id}`;
|
|
5402
5441
|
}
|
|
5442
|
+
function getPopupTitle({
|
|
5443
|
+
element,
|
|
5444
|
+
label
|
|
5445
|
+
}) {
|
|
5446
|
+
let popupTitle = '';
|
|
5447
|
+
if (element && element.type) {
|
|
5448
|
+
popupTitle = `${element.type} / `;
|
|
5449
|
+
}
|
|
5450
|
+
return `${popupTitle}${label}`;
|
|
5451
|
+
}
|
|
5403
5452
|
|
|
5404
5453
|
/**
|
|
5405
5454
|
* Add a dragger that calls back the passed function with
|
|
@@ -5484,6 +5533,9 @@ const noop = () => {};
|
|
|
5484
5533
|
* @param {Function} [props.onPostDeactivate]
|
|
5485
5534
|
* @param {boolean} [props.returnFocus]
|
|
5486
5535
|
* @param {boolean} [props.closeOnEscape]
|
|
5536
|
+
* @param {(event: KeyboardEvent) => boolean} [props.allowFocusMove] -
|
|
5537
|
+
* Whether a Tab keypress may move focus. Return false to leave the keypress
|
|
5538
|
+
* to the focused element, e.g. an editor navigating snippet placeholders.
|
|
5487
5539
|
* @param {string} props.title
|
|
5488
5540
|
* @param {Ref} [ref]
|
|
5489
5541
|
*/
|
|
@@ -5499,6 +5551,7 @@ function PopupComponent(props, globalRef) {
|
|
|
5499
5551
|
onPostDeactivate = noop,
|
|
5500
5552
|
returnFocus = true,
|
|
5501
5553
|
closeOnEscape = true,
|
|
5554
|
+
allowFocusMove = () => true,
|
|
5502
5555
|
title
|
|
5503
5556
|
} = props;
|
|
5504
5557
|
const focusTrapRef = useRef(null);
|
|
@@ -5518,13 +5571,14 @@ function PopupComponent(props, globalRef) {
|
|
|
5518
5571
|
focusTrapRef.current.activate();
|
|
5519
5572
|
}
|
|
5520
5573
|
};
|
|
5521
|
-
|
|
5522
|
-
|
|
5523
|
-
|
|
5524
|
-
|
|
5525
|
-
|
|
5526
|
-
|
|
5527
|
-
|
|
5574
|
+
const {
|
|
5575
|
+
top,
|
|
5576
|
+
left
|
|
5577
|
+
} = position || getCenterPosition(width, height);
|
|
5578
|
+
const style = {};
|
|
5579
|
+
if (isDefined(top) && isDefined(left)) {
|
|
5580
|
+
style.top = top + 'px';
|
|
5581
|
+
style.left = left + 'px';
|
|
5528
5582
|
}
|
|
5529
5583
|
if (width) {
|
|
5530
5584
|
style.width = width + 'px';
|
|
@@ -5548,6 +5602,8 @@ function PopupComponent(props, globalRef) {
|
|
|
5548
5602
|
clickOutsideDeactivates: true,
|
|
5549
5603
|
delayInitialFocus,
|
|
5550
5604
|
fallbackFocus: popupRef.current,
|
|
5605
|
+
isKeyForward: event => isTab(event) && !event.shiftKey && allowFocusMove(event),
|
|
5606
|
+
isKeyBackward: event => isTab(event) && event.shiftKey && allowFocusMove(event),
|
|
5551
5607
|
onPostActivate,
|
|
5552
5608
|
onPostDeactivate,
|
|
5553
5609
|
returnFocusOnDeactivate: returnFocus
|
|
@@ -5562,21 +5618,23 @@ function PopupComponent(props, globalRef) {
|
|
|
5562
5618
|
ref: popupRef,
|
|
5563
5619
|
onKeyDown: handleKeydown,
|
|
5564
5620
|
role: "dialog",
|
|
5565
|
-
class: classnames('bio-properties-panel-popup', className),
|
|
5621
|
+
class: classnames('bio-properties-panel-popup', 'bio-theme-parent', className),
|
|
5566
5622
|
style: style,
|
|
5567
5623
|
children: props.children
|
|
5568
5624
|
});
|
|
5569
5625
|
}
|
|
5570
|
-
const Popup = forwardRef(PopupComponent);
|
|
5571
|
-
Popup.Title = Title;
|
|
5572
|
-
Popup.Body = Body;
|
|
5573
|
-
Popup.Footer = Footer;
|
|
5626
|
+
const Popup$1 = forwardRef(PopupComponent);
|
|
5627
|
+
Popup$1.Title = Title;
|
|
5628
|
+
Popup$1.Body = Body;
|
|
5629
|
+
Popup$1.Footer = Footer;
|
|
5574
5630
|
function Title(props) {
|
|
5631
|
+
const {
|
|
5632
|
+
eventBus
|
|
5633
|
+
} = useContext(EventContext);
|
|
5575
5634
|
const {
|
|
5576
5635
|
children,
|
|
5577
5636
|
className,
|
|
5578
5637
|
draggable,
|
|
5579
|
-
eventBus,
|
|
5580
5638
|
title,
|
|
5581
5639
|
showCloseButton = false,
|
|
5582
5640
|
closeButtonTooltip = 'Close popup',
|
|
@@ -5681,6 +5739,26 @@ function Footer(props) {
|
|
|
5681
5739
|
|
|
5682
5740
|
// helpers //////////////////////
|
|
5683
5741
|
|
|
5742
|
+
/**
|
|
5743
|
+
* Center the popup in the viewport, based on its own dimensions.
|
|
5744
|
+
*
|
|
5745
|
+
* @param {number} [width]
|
|
5746
|
+
* @param {number} [height]
|
|
5747
|
+
*/
|
|
5748
|
+
function getCenterPosition(width, height) {
|
|
5749
|
+
if (!width || !height) {
|
|
5750
|
+
return {};
|
|
5751
|
+
}
|
|
5752
|
+
const viewportWidth = window.innerWidth || document.documentElement.clientWidth;
|
|
5753
|
+
const viewportHeight = window.innerHeight || document.documentElement.clientHeight;
|
|
5754
|
+
return {
|
|
5755
|
+
left: Math.max(0, (viewportWidth - width) / 2),
|
|
5756
|
+
top: Math.max(0, (viewportHeight - height) / 2)
|
|
5757
|
+
};
|
|
5758
|
+
}
|
|
5759
|
+
function isTab(event) {
|
|
5760
|
+
return event.key === 'Tab';
|
|
5761
|
+
}
|
|
5684
5762
|
function getPopupParent(node) {
|
|
5685
5763
|
return node.closest('.bio-properties-panel-popup');
|
|
5686
5764
|
}
|
|
@@ -5699,22 +5777,20 @@ function cancel(event) {
|
|
|
5699
5777
|
* @property {string} value
|
|
5700
5778
|
* @property {Array} [links]
|
|
5701
5779
|
* @property {Array|Object} [variables]
|
|
5702
|
-
* @property {Object} [position]
|
|
5703
5780
|
* @property {string} [hostLanguage]
|
|
5704
5781
|
* @property {boolean} [singleLine]
|
|
5705
5782
|
* @property {HTMLElement} [sourceElement]
|
|
5706
5783
|
* @property {HTMLElement|string} [tooltipContainer]
|
|
5707
|
-
* @property {Object} [eventBus]
|
|
5708
5784
|
*/
|
|
5709
5785
|
|
|
5710
5786
|
const FEEL_POPUP_WIDTH = 700;
|
|
5711
|
-
const FEEL_POPUP_HEIGHT =
|
|
5787
|
+
const FEEL_POPUP_HEIGHT = 400;
|
|
5712
5788
|
|
|
5713
5789
|
/**
|
|
5714
5790
|
* FEEL expression editor popup component
|
|
5715
5791
|
* @param {FeelPopupProps} props
|
|
5716
5792
|
*/
|
|
5717
|
-
function FeelPopup
|
|
5793
|
+
function FeelPopup(props) {
|
|
5718
5794
|
const {
|
|
5719
5795
|
entryId,
|
|
5720
5796
|
onInput,
|
|
@@ -5724,12 +5800,10 @@ function FeelPopup$1(props) {
|
|
|
5724
5800
|
value,
|
|
5725
5801
|
links,
|
|
5726
5802
|
variables,
|
|
5727
|
-
position,
|
|
5728
5803
|
hostLanguage,
|
|
5729
5804
|
singleLine,
|
|
5730
5805
|
sourceElement,
|
|
5731
5806
|
tooltipContainer,
|
|
5732
|
-
eventBus,
|
|
5733
5807
|
feelLanguageContext
|
|
5734
5808
|
} = props;
|
|
5735
5809
|
const editorRef = useRef();
|
|
@@ -5759,20 +5833,19 @@ function FeelPopup$1(props) {
|
|
|
5759
5833
|
editorRef.current.focus();
|
|
5760
5834
|
}
|
|
5761
5835
|
}, [editorRef]);
|
|
5762
|
-
return jsxs(Popup, {
|
|
5836
|
+
return jsxs(Popup$1, {
|
|
5763
5837
|
className: "bio-properties-panel-feel-popup",
|
|
5764
|
-
position: position,
|
|
5765
5838
|
title: title,
|
|
5766
5839
|
returnFocus: false,
|
|
5767
5840
|
closeOnEscape: false,
|
|
5768
5841
|
delayInitialFocus: false,
|
|
5842
|
+
allowFocusMove: event => !isSnippetNavigation(event),
|
|
5769
5843
|
onPostDeactivate: handleSetReturnFocus,
|
|
5770
5844
|
height: FEEL_POPUP_HEIGHT,
|
|
5771
5845
|
width: FEEL_POPUP_WIDTH,
|
|
5772
5846
|
ref: popupRef,
|
|
5773
|
-
children: [jsx(Popup.Title, {
|
|
5847
|
+
children: [jsx(Popup$1.Title, {
|
|
5774
5848
|
title: title,
|
|
5775
|
-
eventBus: eventBus,
|
|
5776
5849
|
showCloseButton: true,
|
|
5777
5850
|
closeButtonTooltip: "Save and close",
|
|
5778
5851
|
onClose: onClose,
|
|
@@ -5788,14 +5861,13 @@ function FeelPopup$1(props) {
|
|
|
5788
5861
|
}, index);
|
|
5789
5862
|
})
|
|
5790
5863
|
})
|
|
5791
|
-
}), jsx(Popup.Body, {
|
|
5864
|
+
}), jsx(Popup$1.Body, {
|
|
5792
5865
|
children: jsxs("div", {
|
|
5793
5866
|
onKeyDownCapture: onKeyDownCapture,
|
|
5794
5867
|
onKeyDown: onKeyDown,
|
|
5795
5868
|
class: "bio-properties-panel-feel-popup__body",
|
|
5796
5869
|
children: [type === 'feel' && jsx(FeelEditor, {
|
|
5797
5870
|
enableGutters: true,
|
|
5798
|
-
id: prefixId(entryId),
|
|
5799
5871
|
name: entryId,
|
|
5800
5872
|
onInput: onInput,
|
|
5801
5873
|
value: value,
|
|
@@ -5804,7 +5876,6 @@ function FeelPopup$1(props) {
|
|
|
5804
5876
|
ref: editorRef,
|
|
5805
5877
|
tooltipContainer: tooltipContainer
|
|
5806
5878
|
}), type === 'feelers' && jsx(TemplatingEditor, {
|
|
5807
|
-
id: prefixId(entryId),
|
|
5808
5879
|
contentAttributes: {
|
|
5809
5880
|
'aria-label': title
|
|
5810
5881
|
},
|
|
@@ -5821,34 +5892,107 @@ function FeelPopup$1(props) {
|
|
|
5821
5892
|
})]
|
|
5822
5893
|
});
|
|
5823
5894
|
}
|
|
5824
|
-
function prefixId(id) {
|
|
5825
|
-
return `bio-properties-panel-${id}`;
|
|
5826
|
-
}
|
|
5827
5895
|
function autoCompletionOpen(element) {
|
|
5828
5896
|
const editor = element.closest('.cm-editor');
|
|
5829
5897
|
return editor ? editor.querySelector('.cm-tooltip-autocomplete') : null;
|
|
5830
5898
|
}
|
|
5831
|
-
|
|
5832
|
-
|
|
5833
|
-
|
|
5834
|
-
|
|
5835
|
-
|
|
5836
|
-
if (element && element.type) {
|
|
5837
|
-
popupTitle = `${element.type} / `;
|
|
5838
|
-
}
|
|
5839
|
-
return `${popupTitle}${label}`;
|
|
5899
|
+
|
|
5900
|
+
// while a snippet is active, Tab navigates its placeholders inside the editor
|
|
5901
|
+
function isSnippetNavigation(event) {
|
|
5902
|
+
const editor = event.target.closest('.cm-editor');
|
|
5903
|
+
return !!(editor && editor.querySelector('.cm-snippetField'));
|
|
5840
5904
|
}
|
|
5841
|
-
|
|
5842
|
-
|
|
5843
|
-
|
|
5844
|
-
|
|
5845
|
-
|
|
5846
|
-
|
|
5905
|
+
|
|
5906
|
+
/**
|
|
5907
|
+
* @typedef {Object} TextPopupProps
|
|
5908
|
+
* @property {string} entryId
|
|
5909
|
+
* @property {Function} onInput
|
|
5910
|
+
* @property {Function} onClose
|
|
5911
|
+
* @property {string} title
|
|
5912
|
+
* @property {string} value
|
|
5913
|
+
* @property {HTMLElement} [sourceElement]
|
|
5914
|
+
*/
|
|
5915
|
+
|
|
5916
|
+
const TEXT_POPUP_WIDTH = 700;
|
|
5917
|
+
const TEXT_POPUP_HEIGHT = 400;
|
|
5918
|
+
|
|
5919
|
+
/**
|
|
5920
|
+
* Plain text editor popup component.
|
|
5921
|
+
*
|
|
5922
|
+
* Intentionally kept separate from the FEEL popup: the two are expected to
|
|
5923
|
+
* diverge as we add FEEL-specific capabilities that do not apply to plain text.
|
|
5924
|
+
*
|
|
5925
|
+
* @param {TextPopupProps} props
|
|
5926
|
+
*/
|
|
5927
|
+
function TextPopup(props) {
|
|
5928
|
+
const {
|
|
5929
|
+
entryId,
|
|
5930
|
+
onInput,
|
|
5931
|
+
onClose,
|
|
5932
|
+
title,
|
|
5933
|
+
value,
|
|
5934
|
+
sourceElement
|
|
5935
|
+
} = props;
|
|
5936
|
+
const editorRef = useRef();
|
|
5937
|
+
const popupRef = useRef();
|
|
5938
|
+
const handleSetReturnFocus = () => {
|
|
5939
|
+
sourceElement && sourceElement.focus();
|
|
5847
5940
|
};
|
|
5941
|
+
useEffect(() => {
|
|
5942
|
+
// set focus on editor when popup is opened
|
|
5943
|
+
if (editorRef.current) {
|
|
5944
|
+
editorRef.current.focus();
|
|
5945
|
+
}
|
|
5946
|
+
}, [editorRef]);
|
|
5947
|
+
return jsxs(Popup$1, {
|
|
5948
|
+
className: "bio-properties-panel-text-popup",
|
|
5949
|
+
title: title,
|
|
5950
|
+
returnFocus: false,
|
|
5951
|
+
closeOnEscape: true,
|
|
5952
|
+
delayInitialFocus: false,
|
|
5953
|
+
onClose: onClose,
|
|
5954
|
+
onPostDeactivate: handleSetReturnFocus,
|
|
5955
|
+
height: TEXT_POPUP_HEIGHT,
|
|
5956
|
+
width: TEXT_POPUP_WIDTH,
|
|
5957
|
+
ref: popupRef,
|
|
5958
|
+
children: [jsx(Popup$1.Title, {
|
|
5959
|
+
title: title,
|
|
5960
|
+
showCloseButton: true,
|
|
5961
|
+
closeButtonTooltip: "Save and close",
|
|
5962
|
+
onClose: onClose,
|
|
5963
|
+
draggable: true
|
|
5964
|
+
}), jsx(Popup$1.Body, {
|
|
5965
|
+
children: jsx("textarea", {
|
|
5966
|
+
id: prefixId(entryId),
|
|
5967
|
+
name: entryId,
|
|
5968
|
+
class: "bio-properties-panel-input",
|
|
5969
|
+
ref: editorRef,
|
|
5970
|
+
onInput: e => onInput(e.target.value),
|
|
5971
|
+
value: value || '',
|
|
5972
|
+
spellCheck: "false",
|
|
5973
|
+
autoComplete: "off",
|
|
5974
|
+
"aria-label": title,
|
|
5975
|
+
"data-gramm": "false"
|
|
5976
|
+
})
|
|
5977
|
+
})]
|
|
5978
|
+
});
|
|
5979
|
+
}
|
|
5980
|
+
|
|
5981
|
+
// The in-panel field stays mounted (hidden) while the popup is open, so we
|
|
5982
|
+
// scope the popup editor id to keep it unique in the DOM.
|
|
5983
|
+
function prefixId(id) {
|
|
5984
|
+
return `bio-properties-panel-popup-${id}`;
|
|
5848
5985
|
}
|
|
5986
|
+
const DEFAULT_POPUP_TYPE = 'text';
|
|
5987
|
+
|
|
5988
|
+
// consumers registering via #registerProvider default to DEFAULT_PRIORITY,
|
|
5989
|
+
// so their providers take precedence over the LOW_PRIORITY built-ins.
|
|
5990
|
+
const DEFAULT_PRIORITY$4 = 1000;
|
|
5991
|
+
const LOW_PRIORITY$2 = 500;
|
|
5849
5992
|
|
|
5850
5993
|
/**
|
|
5851
|
-
*
|
|
5994
|
+
* Popup manager, built as a singleton. Renders the registered provider for a
|
|
5995
|
+
* given popup type; consumers may plug in their own via #registerProvider.
|
|
5852
5996
|
*
|
|
5853
5997
|
* In order to implement a custom replacement, handle the following events:
|
|
5854
5998
|
* - `propertiesPanel.openPopup`
|
|
@@ -5861,16 +6005,19 @@ function getPopupPosition() {
|
|
|
5861
6005
|
* - `feelPopup.close` - fired before the popup is unmounted. Event context contains the DOM node of the popup as `domNode`
|
|
5862
6006
|
* - `feelPopup.closed` - fired after the popup is unmounted
|
|
5863
6007
|
*/
|
|
5864
|
-
class
|
|
6008
|
+
class Popup {
|
|
5865
6009
|
constructor(eventBus, config = {}) {
|
|
5866
6010
|
this._eventBus = eventBus;
|
|
5867
6011
|
this._config = config;
|
|
5868
6012
|
this._isOpen = false;
|
|
5869
|
-
eventBus.on('propertiesPanel.openPopup', (_, context) => {
|
|
5870
|
-
this.open(context.entryId, context, context.sourceElement);
|
|
5871
6013
|
|
|
5872
|
-
|
|
5873
|
-
|
|
6014
|
+
// built-in providers, registered at LOW_PRIORITY so consumers can
|
|
6015
|
+
// override them via #registerProvider using the default priority
|
|
6016
|
+
this.registerProvider('feel', LOW_PRIORITY$2, FeelPopup);
|
|
6017
|
+
this.registerProvider('feelers', LOW_PRIORITY$2, FeelPopup);
|
|
6018
|
+
this.registerProvider('text', LOW_PRIORITY$2, TextPopup);
|
|
6019
|
+
eventBus.on('propertiesPanel.openPopup', (_, context) => {
|
|
6020
|
+
return this.open(context.entryId, context, context.sourceElement);
|
|
5874
6021
|
});
|
|
5875
6022
|
eventBus.on(['propertiesPanel.closePopup', 'propertiesPanel.detach'], () => {
|
|
5876
6023
|
this.close();
|
|
@@ -5878,7 +6025,43 @@ class FeelPopup {
|
|
|
5878
6025
|
}
|
|
5879
6026
|
|
|
5880
6027
|
/**
|
|
5881
|
-
*
|
|
6028
|
+
* Register a popup provider (component) for a given type.
|
|
6029
|
+
*
|
|
6030
|
+
* A higher `priority` wins when multiple providers are registered for the
|
|
6031
|
+
* same type; the built-in providers use a low priority so consumers override
|
|
6032
|
+
* them by default.
|
|
6033
|
+
*
|
|
6034
|
+
* @param {string} type
|
|
6035
|
+
* @param {number} [priority=DEFAULT_PRIORITY]
|
|
6036
|
+
* @param {Function|import('preact').Component} provider
|
|
6037
|
+
*/
|
|
6038
|
+
registerProvider(type, priority, provider) {
|
|
6039
|
+
if (!provider) {
|
|
6040
|
+
provider = priority;
|
|
6041
|
+
priority = DEFAULT_PRIORITY$4;
|
|
6042
|
+
}
|
|
6043
|
+
this._eventBus.on('propertiesPanelPopup.getProviders.' + type, priority, function (event) {
|
|
6044
|
+
event.providers.push(provider);
|
|
6045
|
+
});
|
|
6046
|
+
}
|
|
6047
|
+
|
|
6048
|
+
/**
|
|
6049
|
+
* Get the popup providers registered for a type.
|
|
6050
|
+
*
|
|
6051
|
+
* @param {string} type
|
|
6052
|
+
* @return {Array<Function|import('preact').Component>}
|
|
6053
|
+
*/
|
|
6054
|
+
_getProviders(type) {
|
|
6055
|
+
const event = this._eventBus.createEvent({
|
|
6056
|
+
type: 'propertiesPanelPopup.getProviders.' + type,
|
|
6057
|
+
providers: []
|
|
6058
|
+
});
|
|
6059
|
+
this._eventBus.fire(event);
|
|
6060
|
+
return event.providers;
|
|
6061
|
+
}
|
|
6062
|
+
|
|
6063
|
+
/**
|
|
6064
|
+
* Check if the popup is open.
|
|
5882
6065
|
* @return {Boolean}
|
|
5883
6066
|
*/
|
|
5884
6067
|
isOpen() {
|
|
@@ -5886,7 +6069,7 @@ class FeelPopup {
|
|
|
5886
6069
|
}
|
|
5887
6070
|
|
|
5888
6071
|
/**
|
|
5889
|
-
* Open the
|
|
6072
|
+
* Open the popup.
|
|
5890
6073
|
*
|
|
5891
6074
|
* @param {String} entryId
|
|
5892
6075
|
* @param {Object} popupConfig
|
|
@@ -5895,7 +6078,7 @@ class FeelPopup {
|
|
|
5895
6078
|
open(entryId, popupConfig, sourceElement) {
|
|
5896
6079
|
// close before opening a new one
|
|
5897
6080
|
this.close();
|
|
5898
|
-
this._openPopup({
|
|
6081
|
+
return this._openPopup({
|
|
5899
6082
|
...popupConfig,
|
|
5900
6083
|
entryId,
|
|
5901
6084
|
sourceElement
|
|
@@ -5903,7 +6086,7 @@ class FeelPopup {
|
|
|
5903
6086
|
}
|
|
5904
6087
|
|
|
5905
6088
|
/**
|
|
5906
|
-
* Close the
|
|
6089
|
+
* Close the popup.
|
|
5907
6090
|
*/
|
|
5908
6091
|
close() {
|
|
5909
6092
|
this._closePopup();
|
|
@@ -5913,13 +6096,18 @@ class FeelPopup {
|
|
|
5913
6096
|
element,
|
|
5914
6097
|
label,
|
|
5915
6098
|
sourceElement,
|
|
5916
|
-
type
|
|
6099
|
+
type = DEFAULT_POPUP_TYPE
|
|
5917
6100
|
} = context;
|
|
6101
|
+
const component = this._getProviders(type)[0];
|
|
6102
|
+
if (!component) {
|
|
6103
|
+
return false;
|
|
6104
|
+
}
|
|
5918
6105
|
this._isOpen = true;
|
|
5919
6106
|
this._eventBus.fire('propertiesPanelPopup.open', {
|
|
5920
6107
|
container: this._config.feelPopupContainer,
|
|
5921
6108
|
config: {
|
|
5922
6109
|
...context,
|
|
6110
|
+
component,
|
|
5923
6111
|
links: this._config.getFeelPopupLinks?.(type) || [],
|
|
5924
6112
|
onClose: () => {
|
|
5925
6113
|
this._closePopup();
|
|
@@ -5929,13 +6117,13 @@ class FeelPopup {
|
|
|
5929
6117
|
sourceElement && sourceElement.focus();
|
|
5930
6118
|
}, 0);
|
|
5931
6119
|
},
|
|
5932
|
-
position: getPopupPosition(),
|
|
5933
6120
|
title: getPopupTitle({
|
|
5934
6121
|
element,
|
|
5935
6122
|
label
|
|
5936
6123
|
})
|
|
5937
6124
|
}
|
|
5938
6125
|
});
|
|
6126
|
+
return true;
|
|
5939
6127
|
}
|
|
5940
6128
|
_closePopup() {
|
|
5941
6129
|
if (this._isOpen) {
|
|
@@ -5944,8 +6132,8 @@ class FeelPopup {
|
|
|
5944
6132
|
}
|
|
5945
6133
|
}
|
|
5946
6134
|
}
|
|
5947
|
-
|
|
5948
|
-
class
|
|
6135
|
+
Popup.$inject = ['eventBus', 'config.propertiesPanel'];
|
|
6136
|
+
class PopupRenderer {
|
|
5949
6137
|
constructor(eventBus) {
|
|
5950
6138
|
this._eventBus = eventBus;
|
|
5951
6139
|
this._container = null;
|
|
@@ -5965,15 +6153,16 @@ class FeelPopupRenderer {
|
|
|
5965
6153
|
container = this._container = getContainer(container) || document.body;
|
|
5966
6154
|
const element = this._element = createElement();
|
|
5967
6155
|
container.appendChild(element);
|
|
5968
|
-
|
|
5969
|
-
// TODO(philippfromme): there is no useService in this context, so we need
|
|
5970
|
-
// to pass the event bus as a prop or create a context provider, however,
|
|
5971
|
-
// a custom renderer would have to use that context provider as well to have
|
|
5972
|
-
// access to the event bus and other services
|
|
5973
6156
|
this._emit('feelPopup.open');
|
|
5974
|
-
|
|
5975
|
-
|
|
5976
|
-
|
|
6157
|
+
const Component = config.component;
|
|
6158
|
+
render(jsx(EventContext.Provider, {
|
|
6159
|
+
value: {
|
|
6160
|
+
eventBus: this._eventBus
|
|
6161
|
+
},
|
|
6162
|
+
children: jsx(Component, {
|
|
6163
|
+
...config,
|
|
6164
|
+
eventBus: this._eventBus
|
|
6165
|
+
})
|
|
5977
6166
|
}), element);
|
|
5978
6167
|
this._emit('feelPopup.opened', {
|
|
5979
6168
|
domNode: element
|
|
@@ -5989,13 +6178,14 @@ class FeelPopupRenderer {
|
|
|
5989
6178
|
render(null, this._element);
|
|
5990
6179
|
this._container.removeChild(this._element);
|
|
5991
6180
|
this._container = null;
|
|
6181
|
+
this._element = null;
|
|
5992
6182
|
this._emit('feelPopup.closed');
|
|
5993
6183
|
}
|
|
5994
6184
|
_emit(event, context) {
|
|
5995
6185
|
this._eventBus.fire(event, context);
|
|
5996
6186
|
}
|
|
5997
6187
|
}
|
|
5998
|
-
|
|
6188
|
+
PopupRenderer.$inject = ['eventBus'];
|
|
5999
6189
|
|
|
6000
6190
|
// helpers /////////////////
|
|
6001
6191
|
|
|
@@ -6012,8 +6202,8 @@ function getContainer(container) {
|
|
|
6012
6202
|
}
|
|
6013
6203
|
var index = {
|
|
6014
6204
|
__init__: ['feelPopup', 'feelPopupRenderer'],
|
|
6015
|
-
feelPopup: ['type',
|
|
6016
|
-
feelPopupRenderer: ['type',
|
|
6205
|
+
feelPopup: ['type', Popup],
|
|
6206
|
+
feelPopupRenderer: ['type', PopupRenderer]
|
|
6017
6207
|
};
|
|
6018
6208
|
|
|
6019
6209
|
function getPropertiesPanelHeaderProvider(options = {}) {
|
|
@@ -6775,7 +6965,7 @@ function Element$1(props) {
|
|
|
6775
6965
|
function scrollIntoView({
|
|
6776
6966
|
selection
|
|
6777
6967
|
}) {
|
|
6778
|
-
const scrollContainer = getScrollContainer(ref.current);
|
|
6968
|
+
const scrollContainer = getScrollContainer$1(ref.current);
|
|
6779
6969
|
if (!selection || selection.type === 'default' || selection.id !== id || !scrollContainer || !ref.current) {
|
|
6780
6970
|
return;
|
|
6781
6971
|
}
|