@bpmn-io/properties-panel 3.4.0 → 3.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1160,6 +1160,7 @@ const noop$3 = () => {};
1160
1160
  * @param {Object} props
1161
1161
  * @param {HTMLElement} [props.container]
1162
1162
  * @param {string} [props.className]
1163
+ * @param {boolean} [props.delayInitialFocus]
1163
1164
  * @param {{x: number, y: number}} [props.position]
1164
1165
  * @param {number} [props.width]
1165
1166
  * @param {number} [props.height]
@@ -1167,12 +1168,14 @@ const noop$3 = () => {};
1167
1168
  * @param {Function} [props.onPostActivate]
1168
1169
  * @param {Function} [props.onPostDeactivate]
1169
1170
  * @param {boolean} [props.returnFocus]
1171
+ * @param {boolean} [props.closeOnEscape]
1170
1172
  * @param {string} props.title
1171
1173
  */
1172
1174
  function Popup(props) {
1173
1175
  const {
1174
1176
  container,
1175
1177
  className,
1178
+ delayInitialFocus,
1176
1179
  position,
1177
1180
  width,
1178
1181
  height,
@@ -1180,12 +1183,15 @@ function Popup(props) {
1180
1183
  onPostActivate = noop$3,
1181
1184
  onPostDeactivate = noop$3,
1182
1185
  returnFocus = true,
1186
+ closeOnEscape = true,
1183
1187
  title
1184
1188
  } = props;
1185
1189
  const focusTrapRef = hooks.useRef(null);
1186
1190
  const popupRef = hooks.useRef(null);
1187
- const handleKeyPress = event => {
1188
- if (event.key === 'Escape') {
1191
+ const handleKeydown = event => {
1192
+ // do not allow keyboard events to bubble
1193
+ event.stopPropagation();
1194
+ if (closeOnEscape && event.key === 'Escape') {
1189
1195
  onClose();
1190
1196
  }
1191
1197
  };
@@ -1210,14 +1216,6 @@ function Popup(props) {
1210
1216
  if (height) {
1211
1217
  style.height = height + 'px';
1212
1218
  }
1213
- hooks.useEffect(() => {
1214
- if (popupRef.current) {
1215
- popupRef.current.addEventListener('keydown', handleKeyPress);
1216
- }
1217
- return () => {
1218
- popupRef.current.removeEventListener('keydown', handleKeyPress);
1219
- };
1220
- }, [popupRef]);
1221
1219
  hooks.useEffect(() => {
1222
1220
  if (popupRef.current) {
1223
1221
  popupRef.current.addEventListener('focusin', handleFocus);
@@ -1230,6 +1228,7 @@ function Popup(props) {
1230
1228
  if (popupRef.current) {
1231
1229
  focusTrapRef.current = focusTrap__namespace.createFocusTrap(popupRef.current, {
1232
1230
  clickOutsideDeactivates: true,
1231
+ delayInitialFocus,
1233
1232
  fallbackFocus: popupRef.current,
1234
1233
  onPostActivate,
1235
1234
  onPostDeactivate,
@@ -1243,6 +1242,7 @@ function Popup(props) {
1243
1242
  "aria-label": title,
1244
1243
  tabIndex: -1,
1245
1244
  ref: popupRef,
1245
+ onKeyDown: handleKeydown,
1246
1246
  role: "dialog",
1247
1247
  class: classnames__default["default"]('bio-properties-panel-popup', className),
1248
1248
  style: style,
@@ -1356,7 +1356,8 @@ const FEEL_POPUP_HEIGHT = 250;
1356
1356
  */
1357
1357
  function FEELPopupRoot(props) {
1358
1358
  const {
1359
- element
1359
+ element,
1360
+ popupContainer
1360
1361
  } = props;
1361
1362
  const prevElement = usePrevious(element);
1362
1363
  const [popupConfig, setPopupConfig] = hooks.useState({});
@@ -1389,6 +1390,7 @@ function FEELPopupRoot(props) {
1389
1390
  value: feelPopupContext,
1390
1391
  children: [open && jsxRuntime.jsx(FeelPopupComponent, {
1391
1392
  onClose: handleClose,
1393
+ container: popupContainer,
1392
1394
  sourceElement: sourceElement,
1393
1395
  ...popupConfig
1394
1396
  }), props.children]
@@ -1396,6 +1398,7 @@ function FEELPopupRoot(props) {
1396
1398
  }
1397
1399
  function FeelPopupComponent(props) {
1398
1400
  const {
1401
+ container,
1399
1402
  id,
1400
1403
  hostLanguage,
1401
1404
  onInput,
@@ -1410,16 +1413,30 @@ function FeelPopupComponent(props) {
1410
1413
  variables
1411
1414
  } = props;
1412
1415
  const editorRef = hooks.useRef();
1416
+ const isAutoCompletionOpen = hooks.useRef(false);
1413
1417
  const handleSetReturnFocus = () => {
1414
1418
  sourceElement && sourceElement.focus();
1415
1419
  };
1416
- hooks.useEffect(() => {
1417
- const editor = editorRef.current;
1418
- if (editor) {
1419
- editor.focus();
1420
+ const onKeyDownCapture = event => {
1421
+ // we use capture here to make sure we handle the event before the editor does
1422
+ if (event.key === 'Escape') {
1423
+ isAutoCompletionOpen.current = autoCompletionOpen(event.target);
1424
+ }
1425
+ };
1426
+ const onKeyDown = event => {
1427
+ if (event.key === 'Escape') {
1428
+ // close popup only if auto completion is not open
1429
+ // we need to do check this because the editor is not
1430
+ // stop propagating the keydown event
1431
+ // cf. https://discuss.codemirror.net/t/how-can-i-replace-the-default-autocompletion-keymap-v6/3322/5
1432
+ if (!isAutoCompletionOpen.current) {
1433
+ onClose();
1434
+ isAutoCompletionOpen.current = false;
1435
+ }
1420
1436
  }
1421
- }, [editorRef, id]);
1437
+ };
1422
1438
  return jsxRuntime.jsxs(Popup, {
1439
+ container: container,
1423
1440
  className: "bio-properties-panel-feel-popup",
1424
1441
  position: position,
1425
1442
  title: title,
@@ -1428,6 +1445,8 @@ function FeelPopupComponent(props) {
1428
1445
  // handle focus manually on deactivate
1429
1446
  ,
1430
1447
  returnFocus: false,
1448
+ closeOnEscape: false,
1449
+ delayInitialFocus: false,
1431
1450
  onPostDeactivate: handleSetReturnFocus,
1432
1451
  height: FEEL_POPUP_HEIGHT,
1433
1452
  width: FEEL_POPUP_WIDTH,
@@ -1436,6 +1455,8 @@ function FeelPopupComponent(props) {
1436
1455
  draggable: true
1437
1456
  }), jsxRuntime.jsx(Popup.Body, {
1438
1457
  children: jsxRuntime.jsxs("div", {
1458
+ onKeyDownCapture: onKeyDownCapture,
1459
+ onKeyDown: onKeyDown,
1439
1460
  class: "bio-properties-panel-feel-popup__body",
1440
1461
  children: [type === 'feel' && jsxRuntime.jsx(CodeEditor, {
1441
1462
  enableGutters: true,
@@ -1477,6 +1498,9 @@ function FeelPopupComponent(props) {
1477
1498
  function prefixId$8(id) {
1478
1499
  return `bio-properties-panel-${id}`;
1479
1500
  }
1501
+ function autoCompletionOpen(element) {
1502
+ return element.closest('.cm-editor').querySelector('.cm-tooltip-autocomplete');
1503
+ }
1480
1504
 
1481
1505
  function ToggleSwitch(props) {
1482
1506
  const {
@@ -2226,7 +2250,7 @@ function FeelEntry(props) {
2226
2250
  setLocalError(err);
2227
2251
  }, []);
2228
2252
  const temporaryError = useError(id);
2229
- const error = localError || temporaryError || validationError;
2253
+ const error = temporaryError || localError || validationError;
2230
2254
  return jsxRuntime.jsxs("div", {
2231
2255
  class: classnames__default["default"](props.class, 'bio-properties-panel-entry', error ? 'has-error' : ''),
2232
2256
  "data-entry-id": id,
@@ -2517,6 +2541,7 @@ const DEFAULT_TOOLTIP = {};
2517
2541
  * @param {Function} [props.descriptionLoaded]
2518
2542
  * @param {TooltipConfig} [props.tooltipConfig]
2519
2543
  * @param {Function} [props.tooltipLoaded]
2544
+ * @param {HTMLElement} [props.feelPopupContainer]
2520
2545
  * @param {Object} [props.eventBus]
2521
2546
  */
2522
2547
  function PropertiesPanel(props) {
@@ -2531,6 +2556,7 @@ function PropertiesPanel(props) {
2531
2556
  descriptionLoaded,
2532
2557
  tooltipConfig,
2533
2558
  tooltipLoaded,
2559
+ feelPopupContainer,
2534
2560
  eventBus
2535
2561
  } = props;
2536
2562
 
@@ -2633,6 +2659,7 @@ function PropertiesPanel(props) {
2633
2659
  value: eventContext,
2634
2660
  children: jsxRuntime.jsx(FEELPopupRoot, {
2635
2661
  element: element,
2662
+ popupContainer: feelPopupContainer,
2636
2663
  children: jsxRuntime.jsxs("div", {
2637
2664
  class: "bio-properties-panel",
2638
2665
  children: [jsxRuntime.jsx(Header, {