@bpmn-io/properties-panel 3.7.0 → 3.8.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/properties-panel.css +1 -1
- package/dist/index.esm.js +95 -25
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +94 -24
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -677,20 +677,24 @@ function Group(props) {
|
|
|
677
677
|
|
|
678
678
|
// set edited state depending on all entries
|
|
679
679
|
hooks.useEffect(() => {
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
680
|
+
// TODO(@barmac): replace with CSS when `:has()` is supported in all major browsers, or rewrite as in https://github.com/camunda/camunda-modeler/issues/3815#issuecomment-1733038161
|
|
681
|
+
const scheduled = requestAnimationFrame(() => {
|
|
682
|
+
const hasOneEditedEntry = entries.find(entry => {
|
|
683
|
+
const {
|
|
684
|
+
id,
|
|
685
|
+
isEdited
|
|
686
|
+
} = entry;
|
|
687
|
+
const entryNode = minDom.query(`[data-entry-id="${id}"]`);
|
|
688
|
+
if (!minDash.isFunction(isEdited) || !entryNode) {
|
|
689
|
+
return false;
|
|
690
|
+
}
|
|
691
|
+
const inputNode = minDom.query('.bio-properties-panel-input', entryNode);
|
|
692
|
+
return isEdited(inputNode);
|
|
693
|
+
});
|
|
694
|
+
setEdited(hasOneEditedEntry);
|
|
691
695
|
});
|
|
692
|
-
|
|
693
|
-
}, [entries]);
|
|
696
|
+
return () => cancelAnimationFrame(scheduled);
|
|
697
|
+
}, [entries, setEdited]);
|
|
694
698
|
|
|
695
699
|
// set error state depending on all entries
|
|
696
700
|
const allErrors = useErrors();
|
|
@@ -1124,7 +1128,11 @@ function createDragger(fn, dragPreview) {
|
|
|
1124
1128
|
// (2) setup drag listeners
|
|
1125
1129
|
|
|
1126
1130
|
// attach drag + cleanup event
|
|
1127
|
-
|
|
1131
|
+
// we need to do this to make sure we track cursor
|
|
1132
|
+
// movements before we reach other drag event handlers,
|
|
1133
|
+
// e.g. in child containers.
|
|
1134
|
+
document.addEventListener('dragover', onDrag, true);
|
|
1135
|
+
document.addEventListener('dragenter', preventDefault, true);
|
|
1128
1136
|
document.addEventListener('dragend', onEnd);
|
|
1129
1137
|
document.addEventListener('drop', preventDefault);
|
|
1130
1138
|
}
|
|
@@ -1138,7 +1146,8 @@ function createDragger(fn, dragPreview) {
|
|
|
1138
1146
|
return fn.call(self, event, delta);
|
|
1139
1147
|
}
|
|
1140
1148
|
function onEnd() {
|
|
1141
|
-
document.removeEventListener('dragover', onDrag);
|
|
1149
|
+
document.removeEventListener('dragover', onDrag, true);
|
|
1150
|
+
document.removeEventListener('dragenter', preventDefault, true);
|
|
1142
1151
|
document.removeEventListener('dragend', onEnd);
|
|
1143
1152
|
document.removeEventListener('drop', preventDefault);
|
|
1144
1153
|
}
|
|
@@ -1170,8 +1179,9 @@ const noop$3 = () => {};
|
|
|
1170
1179
|
* @param {boolean} [props.returnFocus]
|
|
1171
1180
|
* @param {boolean} [props.closeOnEscape]
|
|
1172
1181
|
* @param {string} props.title
|
|
1182
|
+
* @param {Ref} [ref]
|
|
1173
1183
|
*/
|
|
1174
|
-
function
|
|
1184
|
+
function PopupComponent(props, globalRef) {
|
|
1175
1185
|
const {
|
|
1176
1186
|
container,
|
|
1177
1187
|
className,
|
|
@@ -1187,7 +1197,8 @@ function Popup(props) {
|
|
|
1187
1197
|
title
|
|
1188
1198
|
} = props;
|
|
1189
1199
|
const focusTrapRef = hooks.useRef(null);
|
|
1190
|
-
const
|
|
1200
|
+
const localRef = hooks.useRef(null);
|
|
1201
|
+
const popupRef = globalRef || localRef;
|
|
1191
1202
|
const handleKeydown = event => {
|
|
1192
1203
|
// do not allow keyboard events to bubble
|
|
1193
1204
|
event.stopPropagation();
|
|
@@ -1249,6 +1260,7 @@ function Popup(props) {
|
|
|
1249
1260
|
children: props.children
|
|
1250
1261
|
}), container || document.body);
|
|
1251
1262
|
}
|
|
1263
|
+
const Popup = compat.forwardRef(PopupComponent);
|
|
1252
1264
|
Popup.Title = Title;
|
|
1253
1265
|
Popup.Body = Body;
|
|
1254
1266
|
Popup.Footer = Footer;
|
|
@@ -1257,6 +1269,7 @@ function Title(props) {
|
|
|
1257
1269
|
children,
|
|
1258
1270
|
className,
|
|
1259
1271
|
draggable,
|
|
1272
|
+
emit = () => {},
|
|
1260
1273
|
title,
|
|
1261
1274
|
...rest
|
|
1262
1275
|
} = props;
|
|
@@ -1269,7 +1282,8 @@ function Title(props) {
|
|
|
1269
1282
|
});
|
|
1270
1283
|
const dragPreviewRef = hooks.useRef();
|
|
1271
1284
|
const titleRef = hooks.useRef();
|
|
1272
|
-
const onMove =
|
|
1285
|
+
const onMove = (event, delta) => {
|
|
1286
|
+
cancel(event);
|
|
1273
1287
|
const {
|
|
1274
1288
|
x: dx,
|
|
1275
1289
|
y: dy
|
|
@@ -1281,20 +1295,33 @@ function Title(props) {
|
|
|
1281
1295
|
const popupParent = getPopupParent(titleRef.current);
|
|
1282
1296
|
popupParent.style.top = newPosition.y + 'px';
|
|
1283
1297
|
popupParent.style.left = newPosition.x + 'px';
|
|
1284
|
-
|
|
1298
|
+
|
|
1299
|
+
// notify interested parties
|
|
1300
|
+
emit('dragover', {
|
|
1301
|
+
newPosition,
|
|
1302
|
+
delta
|
|
1303
|
+
});
|
|
1304
|
+
};
|
|
1285
1305
|
const onMoveStart = event => {
|
|
1286
1306
|
// initialize drag handler
|
|
1287
1307
|
const onDragStart = createDragger(onMove, dragPreviewRef.current);
|
|
1288
1308
|
onDragStart(event);
|
|
1309
|
+
event.stopPropagation();
|
|
1289
1310
|
const popupParent = getPopupParent(titleRef.current);
|
|
1290
1311
|
const bounds = popupParent.getBoundingClientRect();
|
|
1291
1312
|
context.current.startPosition = {
|
|
1292
1313
|
x: bounds.left,
|
|
1293
1314
|
y: bounds.top
|
|
1294
1315
|
};
|
|
1316
|
+
|
|
1317
|
+
// notify interested parties
|
|
1318
|
+
emit('dragstart');
|
|
1295
1319
|
};
|
|
1296
1320
|
const onMoveEnd = () => {
|
|
1297
1321
|
context.current.newPosition = null;
|
|
1322
|
+
|
|
1323
|
+
// notify interested parties
|
|
1324
|
+
emit('dragend');
|
|
1298
1325
|
};
|
|
1299
1326
|
return jsxRuntime.jsxs("div", {
|
|
1300
1327
|
class: classnames__default["default"]('bio-properties-panel-popup__header', draggable && 'draggable', className),
|
|
@@ -1347,12 +1374,20 @@ function Footer(props) {
|
|
|
1347
1374
|
function getPopupParent(node) {
|
|
1348
1375
|
return node.closest('.bio-properties-panel-popup');
|
|
1349
1376
|
}
|
|
1377
|
+
function cancel(event) {
|
|
1378
|
+
event.preventDefault();
|
|
1379
|
+
event.stopPropagation();
|
|
1380
|
+
}
|
|
1350
1381
|
|
|
1351
1382
|
const FEEL_POPUP_WIDTH = 700;
|
|
1352
1383
|
const FEEL_POPUP_HEIGHT = 250;
|
|
1353
1384
|
|
|
1354
1385
|
/**
|
|
1355
|
-
* FEEL popup component, built as a singleton.
|
|
1386
|
+
* FEEL popup component, built as a singleton. Emits lifecycle events as follows:
|
|
1387
|
+
* - `feelPopup.open` - fired before the popup is mounted
|
|
1388
|
+
* - `feelPopup.opened` - fired after the popup is mounted. Event context contains the DOM node of the popup
|
|
1389
|
+
* - `feelPopup.close` - fired before the popup is unmounted. Event context contains the DOM node of the popup
|
|
1390
|
+
* - `feelPopup.closed` - fired after the popup is unmounted
|
|
1356
1391
|
*/
|
|
1357
1392
|
function FEELPopupRoot(props) {
|
|
1358
1393
|
const {
|
|
@@ -1375,17 +1410,21 @@ function FEELPopupRoot(props) {
|
|
|
1375
1410
|
const isOpen = hooks.useCallback(() => {
|
|
1376
1411
|
return !!open;
|
|
1377
1412
|
}, [open]);
|
|
1413
|
+
useUpdateEffect(() => {
|
|
1414
|
+
if (!open) {
|
|
1415
|
+
emit('closed');
|
|
1416
|
+
}
|
|
1417
|
+
}, [open]);
|
|
1378
1418
|
const handleOpen = (entryId, config, _sourceElement) => {
|
|
1379
1419
|
setSource(entryId);
|
|
1380
1420
|
setPopupConfig(config);
|
|
1381
1421
|
setOpen(true);
|
|
1382
1422
|
setSourceElement(_sourceElement);
|
|
1383
|
-
emit('
|
|
1423
|
+
emit('open');
|
|
1384
1424
|
};
|
|
1385
1425
|
const handleClose = () => {
|
|
1386
1426
|
setOpen(false);
|
|
1387
1427
|
setSource(null);
|
|
1388
|
-
emit('closed');
|
|
1389
1428
|
};
|
|
1390
1429
|
const feelPopupContext = {
|
|
1391
1430
|
open: handleOpen,
|
|
@@ -1428,6 +1467,7 @@ function FEELPopupRoot(props) {
|
|
|
1428
1467
|
onClose: handleClose,
|
|
1429
1468
|
container: popupContainer,
|
|
1430
1469
|
sourceElement: sourceElement,
|
|
1470
|
+
emit: emit,
|
|
1431
1471
|
...popupConfig
|
|
1432
1472
|
}), props.children]
|
|
1433
1473
|
});
|
|
@@ -1446,9 +1486,11 @@ function FeelPopupComponent(props) {
|
|
|
1446
1486
|
tooltipContainer,
|
|
1447
1487
|
type,
|
|
1448
1488
|
value,
|
|
1449
|
-
variables
|
|
1489
|
+
variables,
|
|
1490
|
+
emit
|
|
1450
1491
|
} = props;
|
|
1451
1492
|
const editorRef = hooks.useRef();
|
|
1493
|
+
const popupRef = hooks.useRef();
|
|
1452
1494
|
const isAutoCompletionOpen = hooks.useRef(false);
|
|
1453
1495
|
const handleSetReturnFocus = () => {
|
|
1454
1496
|
sourceElement && sourceElement.focus();
|
|
@@ -1471,9 +1513,18 @@ function FeelPopupComponent(props) {
|
|
|
1471
1513
|
}
|
|
1472
1514
|
}
|
|
1473
1515
|
};
|
|
1516
|
+
hooks.useEffect(() => {
|
|
1517
|
+
emit('opened', {
|
|
1518
|
+
domNode: popupRef.current
|
|
1519
|
+
});
|
|
1520
|
+
return () => emit('close', {
|
|
1521
|
+
domNode: popupRef.current
|
|
1522
|
+
});
|
|
1523
|
+
}, []);
|
|
1474
1524
|
return jsxRuntime.jsxs(Popup, {
|
|
1475
1525
|
container: container,
|
|
1476
1526
|
className: "bio-properties-panel-feel-popup",
|
|
1527
|
+
emit: emit,
|
|
1477
1528
|
position: position,
|
|
1478
1529
|
title: title,
|
|
1479
1530
|
onClose: onClose
|
|
@@ -1486,8 +1537,10 @@ function FeelPopupComponent(props) {
|
|
|
1486
1537
|
onPostDeactivate: handleSetReturnFocus,
|
|
1487
1538
|
height: FEEL_POPUP_HEIGHT,
|
|
1488
1539
|
width: FEEL_POPUP_WIDTH,
|
|
1540
|
+
ref: popupRef,
|
|
1489
1541
|
children: [jsxRuntime.jsx(Popup.Title, {
|
|
1490
1542
|
title: title,
|
|
1543
|
+
emit: emit,
|
|
1491
1544
|
draggable: true
|
|
1492
1545
|
}), jsxRuntime.jsx(Popup.Body, {
|
|
1493
1546
|
children: jsxRuntime.jsxs("div", {
|
|
@@ -1538,6 +1591,23 @@ function autoCompletionOpen(element) {
|
|
|
1538
1591
|
return element.closest('.cm-editor').querySelector('.cm-tooltip-autocomplete');
|
|
1539
1592
|
}
|
|
1540
1593
|
|
|
1594
|
+
/**
|
|
1595
|
+
* This hook behaves like useEffect, but does not trigger on the first render.
|
|
1596
|
+
*
|
|
1597
|
+
* @param {Function} effect
|
|
1598
|
+
* @param {Array} deps
|
|
1599
|
+
*/
|
|
1600
|
+
function useUpdateEffect(effect, deps) {
|
|
1601
|
+
const isMounted = hooks.useRef(false);
|
|
1602
|
+
hooks.useEffect(() => {
|
|
1603
|
+
if (isMounted.current) {
|
|
1604
|
+
return effect();
|
|
1605
|
+
} else {
|
|
1606
|
+
isMounted.current = true;
|
|
1607
|
+
}
|
|
1608
|
+
}, deps);
|
|
1609
|
+
}
|
|
1610
|
+
|
|
1541
1611
|
function ToggleSwitch(props) {
|
|
1542
1612
|
const {
|
|
1543
1613
|
id,
|
|
@@ -2489,7 +2559,7 @@ function calculatePopupPosition(element) {
|
|
|
2489
2559
|
|
|
2490
2560
|
// todo(pinussilvestrus): make this configurable in the future
|
|
2491
2561
|
function getPopupTitle(element, label) {
|
|
2492
|
-
let popupTitle;
|
|
2562
|
+
let popupTitle = '';
|
|
2493
2563
|
if (element && element.type) {
|
|
2494
2564
|
popupTitle = `${element.type} / `;
|
|
2495
2565
|
}
|