@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.esm.js CHANGED
@@ -1132,6 +1132,7 @@ const noop$3 = () => {};
1132
1132
  * @param {Object} props
1133
1133
  * @param {HTMLElement} [props.container]
1134
1134
  * @param {string} [props.className]
1135
+ * @param {boolean} [props.delayInitialFocus]
1135
1136
  * @param {{x: number, y: number}} [props.position]
1136
1137
  * @param {number} [props.width]
1137
1138
  * @param {number} [props.height]
@@ -1139,12 +1140,14 @@ const noop$3 = () => {};
1139
1140
  * @param {Function} [props.onPostActivate]
1140
1141
  * @param {Function} [props.onPostDeactivate]
1141
1142
  * @param {boolean} [props.returnFocus]
1143
+ * @param {boolean} [props.closeOnEscape]
1142
1144
  * @param {string} props.title
1143
1145
  */
1144
1146
  function Popup(props) {
1145
1147
  const {
1146
1148
  container,
1147
1149
  className,
1150
+ delayInitialFocus,
1148
1151
  position,
1149
1152
  width,
1150
1153
  height,
@@ -1152,12 +1155,15 @@ function Popup(props) {
1152
1155
  onPostActivate = noop$3,
1153
1156
  onPostDeactivate = noop$3,
1154
1157
  returnFocus = true,
1158
+ closeOnEscape = true,
1155
1159
  title
1156
1160
  } = props;
1157
1161
  const focusTrapRef = useRef(null);
1158
1162
  const popupRef = useRef(null);
1159
- const handleKeyPress = event => {
1160
- if (event.key === 'Escape') {
1163
+ const handleKeydown = event => {
1164
+ // do not allow keyboard events to bubble
1165
+ event.stopPropagation();
1166
+ if (closeOnEscape && event.key === 'Escape') {
1161
1167
  onClose();
1162
1168
  }
1163
1169
  };
@@ -1182,14 +1188,6 @@ function Popup(props) {
1182
1188
  if (height) {
1183
1189
  style.height = height + 'px';
1184
1190
  }
1185
- useEffect(() => {
1186
- if (popupRef.current) {
1187
- popupRef.current.addEventListener('keydown', handleKeyPress);
1188
- }
1189
- return () => {
1190
- popupRef.current.removeEventListener('keydown', handleKeyPress);
1191
- };
1192
- }, [popupRef]);
1193
1191
  useEffect(() => {
1194
1192
  if (popupRef.current) {
1195
1193
  popupRef.current.addEventListener('focusin', handleFocus);
@@ -1202,6 +1200,7 @@ function Popup(props) {
1202
1200
  if (popupRef.current) {
1203
1201
  focusTrapRef.current = focusTrap.createFocusTrap(popupRef.current, {
1204
1202
  clickOutsideDeactivates: true,
1203
+ delayInitialFocus,
1205
1204
  fallbackFocus: popupRef.current,
1206
1205
  onPostActivate,
1207
1206
  onPostDeactivate,
@@ -1215,6 +1214,7 @@ function Popup(props) {
1215
1214
  "aria-label": title,
1216
1215
  tabIndex: -1,
1217
1216
  ref: popupRef,
1217
+ onKeyDown: handleKeydown,
1218
1218
  role: "dialog",
1219
1219
  class: classnames('bio-properties-panel-popup', className),
1220
1220
  style: style,
@@ -1328,7 +1328,8 @@ const FEEL_POPUP_HEIGHT = 250;
1328
1328
  */
1329
1329
  function FEELPopupRoot(props) {
1330
1330
  const {
1331
- element
1331
+ element,
1332
+ popupContainer
1332
1333
  } = props;
1333
1334
  const prevElement = usePrevious(element);
1334
1335
  const [popupConfig, setPopupConfig] = useState({});
@@ -1361,6 +1362,7 @@ function FEELPopupRoot(props) {
1361
1362
  value: feelPopupContext,
1362
1363
  children: [open && jsx(FeelPopupComponent, {
1363
1364
  onClose: handleClose,
1365
+ container: popupContainer,
1364
1366
  sourceElement: sourceElement,
1365
1367
  ...popupConfig
1366
1368
  }), props.children]
@@ -1368,6 +1370,7 @@ function FEELPopupRoot(props) {
1368
1370
  }
1369
1371
  function FeelPopupComponent(props) {
1370
1372
  const {
1373
+ container,
1371
1374
  id,
1372
1375
  hostLanguage,
1373
1376
  onInput,
@@ -1382,16 +1385,30 @@ function FeelPopupComponent(props) {
1382
1385
  variables
1383
1386
  } = props;
1384
1387
  const editorRef = useRef();
1388
+ const isAutoCompletionOpen = useRef(false);
1385
1389
  const handleSetReturnFocus = () => {
1386
1390
  sourceElement && sourceElement.focus();
1387
1391
  };
1388
- useEffect(() => {
1389
- const editor = editorRef.current;
1390
- if (editor) {
1391
- editor.focus();
1392
+ const onKeyDownCapture = event => {
1393
+ // we use capture here to make sure we handle the event before the editor does
1394
+ if (event.key === 'Escape') {
1395
+ isAutoCompletionOpen.current = autoCompletionOpen(event.target);
1396
+ }
1397
+ };
1398
+ const onKeyDown = event => {
1399
+ if (event.key === 'Escape') {
1400
+ // close popup only if auto completion is not open
1401
+ // we need to do check this because the editor is not
1402
+ // stop propagating the keydown event
1403
+ // cf. https://discuss.codemirror.net/t/how-can-i-replace-the-default-autocompletion-keymap-v6/3322/5
1404
+ if (!isAutoCompletionOpen.current) {
1405
+ onClose();
1406
+ isAutoCompletionOpen.current = false;
1407
+ }
1392
1408
  }
1393
- }, [editorRef, id]);
1409
+ };
1394
1410
  return jsxs(Popup, {
1411
+ container: container,
1395
1412
  className: "bio-properties-panel-feel-popup",
1396
1413
  position: position,
1397
1414
  title: title,
@@ -1400,6 +1417,8 @@ function FeelPopupComponent(props) {
1400
1417
  // handle focus manually on deactivate
1401
1418
  ,
1402
1419
  returnFocus: false,
1420
+ closeOnEscape: false,
1421
+ delayInitialFocus: false,
1403
1422
  onPostDeactivate: handleSetReturnFocus,
1404
1423
  height: FEEL_POPUP_HEIGHT,
1405
1424
  width: FEEL_POPUP_WIDTH,
@@ -1408,6 +1427,8 @@ function FeelPopupComponent(props) {
1408
1427
  draggable: true
1409
1428
  }), jsx(Popup.Body, {
1410
1429
  children: jsxs("div", {
1430
+ onKeyDownCapture: onKeyDownCapture,
1431
+ onKeyDown: onKeyDown,
1411
1432
  class: "bio-properties-panel-feel-popup__body",
1412
1433
  children: [type === 'feel' && jsx(CodeEditor, {
1413
1434
  enableGutters: true,
@@ -1449,6 +1470,9 @@ function FeelPopupComponent(props) {
1449
1470
  function prefixId$8(id) {
1450
1471
  return `bio-properties-panel-${id}`;
1451
1472
  }
1473
+ function autoCompletionOpen(element) {
1474
+ return element.closest('.cm-editor').querySelector('.cm-tooltip-autocomplete');
1475
+ }
1452
1476
 
1453
1477
  function ToggleSwitch(props) {
1454
1478
  const {
@@ -2198,7 +2222,7 @@ function FeelEntry(props) {
2198
2222
  setLocalError(err);
2199
2223
  }, []);
2200
2224
  const temporaryError = useError(id);
2201
- const error = localError || temporaryError || validationError;
2225
+ const error = temporaryError || localError || validationError;
2202
2226
  return jsxs("div", {
2203
2227
  class: classnames(props.class, 'bio-properties-panel-entry', error ? 'has-error' : ''),
2204
2228
  "data-entry-id": id,
@@ -2489,6 +2513,7 @@ const DEFAULT_TOOLTIP = {};
2489
2513
  * @param {Function} [props.descriptionLoaded]
2490
2514
  * @param {TooltipConfig} [props.tooltipConfig]
2491
2515
  * @param {Function} [props.tooltipLoaded]
2516
+ * @param {HTMLElement} [props.feelPopupContainer]
2492
2517
  * @param {Object} [props.eventBus]
2493
2518
  */
2494
2519
  function PropertiesPanel(props) {
@@ -2503,6 +2528,7 @@ function PropertiesPanel(props) {
2503
2528
  descriptionLoaded,
2504
2529
  tooltipConfig,
2505
2530
  tooltipLoaded,
2531
+ feelPopupContainer,
2506
2532
  eventBus
2507
2533
  } = props;
2508
2534
 
@@ -2605,6 +2631,7 @@ function PropertiesPanel(props) {
2605
2631
  value: eventContext,
2606
2632
  children: jsx(FEELPopupRoot, {
2607
2633
  element: element,
2634
+ popupContainer: feelPopupContainer,
2608
2635
  children: jsxs("div", {
2609
2636
  class: "bio-properties-panel",
2610
2637
  children: [jsx(Header, {