@bpmn-io/properties-panel 3.7.1 → 3.9.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 +102 -25
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +101 -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,9 @@ 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;
|
|
1202
|
+
const containerNode = hooks.useMemo(() => getContainerNode(container), [container]);
|
|
1191
1203
|
const handleKeydown = event => {
|
|
1192
1204
|
// do not allow keyboard events to bubble
|
|
1193
1205
|
event.stopPropagation();
|
|
@@ -1247,8 +1259,9 @@ function Popup(props) {
|
|
|
1247
1259
|
class: classnames__default["default"]('bio-properties-panel-popup', className),
|
|
1248
1260
|
style: style,
|
|
1249
1261
|
children: props.children
|
|
1250
|
-
}),
|
|
1262
|
+
}), containerNode || document.body);
|
|
1251
1263
|
}
|
|
1264
|
+
const Popup = compat.forwardRef(PopupComponent);
|
|
1252
1265
|
Popup.Title = Title;
|
|
1253
1266
|
Popup.Body = Body;
|
|
1254
1267
|
Popup.Footer = Footer;
|
|
@@ -1257,6 +1270,7 @@ function Title(props) {
|
|
|
1257
1270
|
children,
|
|
1258
1271
|
className,
|
|
1259
1272
|
draggable,
|
|
1273
|
+
emit = () => {},
|
|
1260
1274
|
title,
|
|
1261
1275
|
...rest
|
|
1262
1276
|
} = props;
|
|
@@ -1269,7 +1283,8 @@ function Title(props) {
|
|
|
1269
1283
|
});
|
|
1270
1284
|
const dragPreviewRef = hooks.useRef();
|
|
1271
1285
|
const titleRef = hooks.useRef();
|
|
1272
|
-
const onMove =
|
|
1286
|
+
const onMove = (event, delta) => {
|
|
1287
|
+
cancel(event);
|
|
1273
1288
|
const {
|
|
1274
1289
|
x: dx,
|
|
1275
1290
|
y: dy
|
|
@@ -1281,20 +1296,33 @@ function Title(props) {
|
|
|
1281
1296
|
const popupParent = getPopupParent(titleRef.current);
|
|
1282
1297
|
popupParent.style.top = newPosition.y + 'px';
|
|
1283
1298
|
popupParent.style.left = newPosition.x + 'px';
|
|
1284
|
-
|
|
1299
|
+
|
|
1300
|
+
// notify interested parties
|
|
1301
|
+
emit('dragover', {
|
|
1302
|
+
newPosition,
|
|
1303
|
+
delta
|
|
1304
|
+
});
|
|
1305
|
+
};
|
|
1285
1306
|
const onMoveStart = event => {
|
|
1286
1307
|
// initialize drag handler
|
|
1287
1308
|
const onDragStart = createDragger(onMove, dragPreviewRef.current);
|
|
1288
1309
|
onDragStart(event);
|
|
1310
|
+
event.stopPropagation();
|
|
1289
1311
|
const popupParent = getPopupParent(titleRef.current);
|
|
1290
1312
|
const bounds = popupParent.getBoundingClientRect();
|
|
1291
1313
|
context.current.startPosition = {
|
|
1292
1314
|
x: bounds.left,
|
|
1293
1315
|
y: bounds.top
|
|
1294
1316
|
};
|
|
1317
|
+
|
|
1318
|
+
// notify interested parties
|
|
1319
|
+
emit('dragstart');
|
|
1295
1320
|
};
|
|
1296
1321
|
const onMoveEnd = () => {
|
|
1297
1322
|
context.current.newPosition = null;
|
|
1323
|
+
|
|
1324
|
+
// notify interested parties
|
|
1325
|
+
emit('dragend');
|
|
1298
1326
|
};
|
|
1299
1327
|
return jsxRuntime.jsxs("div", {
|
|
1300
1328
|
class: classnames__default["default"]('bio-properties-panel-popup__header', draggable && 'draggable', className),
|
|
@@ -1347,12 +1375,26 @@ function Footer(props) {
|
|
|
1347
1375
|
function getPopupParent(node) {
|
|
1348
1376
|
return node.closest('.bio-properties-panel-popup');
|
|
1349
1377
|
}
|
|
1378
|
+
function cancel(event) {
|
|
1379
|
+
event.preventDefault();
|
|
1380
|
+
event.stopPropagation();
|
|
1381
|
+
}
|
|
1382
|
+
function getContainerNode(node) {
|
|
1383
|
+
if (typeof node === 'string') {
|
|
1384
|
+
return minDom.query(node);
|
|
1385
|
+
}
|
|
1386
|
+
return node;
|
|
1387
|
+
}
|
|
1350
1388
|
|
|
1351
1389
|
const FEEL_POPUP_WIDTH = 700;
|
|
1352
1390
|
const FEEL_POPUP_HEIGHT = 250;
|
|
1353
1391
|
|
|
1354
1392
|
/**
|
|
1355
|
-
* FEEL popup component, built as a singleton.
|
|
1393
|
+
* FEEL popup component, built as a singleton. Emits lifecycle events as follows:
|
|
1394
|
+
* - `feelPopup.open` - fired before the popup is mounted
|
|
1395
|
+
* - `feelPopup.opened` - fired after the popup is mounted. Event context contains the DOM node of the popup
|
|
1396
|
+
* - `feelPopup.close` - fired before the popup is unmounted. Event context contains the DOM node of the popup
|
|
1397
|
+
* - `feelPopup.closed` - fired after the popup is unmounted
|
|
1356
1398
|
*/
|
|
1357
1399
|
function FEELPopupRoot(props) {
|
|
1358
1400
|
const {
|
|
@@ -1375,17 +1417,21 @@ function FEELPopupRoot(props) {
|
|
|
1375
1417
|
const isOpen = hooks.useCallback(() => {
|
|
1376
1418
|
return !!open;
|
|
1377
1419
|
}, [open]);
|
|
1420
|
+
useUpdateEffect(() => {
|
|
1421
|
+
if (!open) {
|
|
1422
|
+
emit('closed');
|
|
1423
|
+
}
|
|
1424
|
+
}, [open]);
|
|
1378
1425
|
const handleOpen = (entryId, config, _sourceElement) => {
|
|
1379
1426
|
setSource(entryId);
|
|
1380
1427
|
setPopupConfig(config);
|
|
1381
1428
|
setOpen(true);
|
|
1382
1429
|
setSourceElement(_sourceElement);
|
|
1383
|
-
emit('
|
|
1430
|
+
emit('open');
|
|
1384
1431
|
};
|
|
1385
1432
|
const handleClose = () => {
|
|
1386
1433
|
setOpen(false);
|
|
1387
1434
|
setSource(null);
|
|
1388
|
-
emit('closed');
|
|
1389
1435
|
};
|
|
1390
1436
|
const feelPopupContext = {
|
|
1391
1437
|
open: handleOpen,
|
|
@@ -1428,6 +1474,7 @@ function FEELPopupRoot(props) {
|
|
|
1428
1474
|
onClose: handleClose,
|
|
1429
1475
|
container: popupContainer,
|
|
1430
1476
|
sourceElement: sourceElement,
|
|
1477
|
+
emit: emit,
|
|
1431
1478
|
...popupConfig
|
|
1432
1479
|
}), props.children]
|
|
1433
1480
|
});
|
|
@@ -1446,9 +1493,11 @@ function FeelPopupComponent(props) {
|
|
|
1446
1493
|
tooltipContainer,
|
|
1447
1494
|
type,
|
|
1448
1495
|
value,
|
|
1449
|
-
variables
|
|
1496
|
+
variables,
|
|
1497
|
+
emit
|
|
1450
1498
|
} = props;
|
|
1451
1499
|
const editorRef = hooks.useRef();
|
|
1500
|
+
const popupRef = hooks.useRef();
|
|
1452
1501
|
const isAutoCompletionOpen = hooks.useRef(false);
|
|
1453
1502
|
const handleSetReturnFocus = () => {
|
|
1454
1503
|
sourceElement && sourceElement.focus();
|
|
@@ -1471,9 +1520,18 @@ function FeelPopupComponent(props) {
|
|
|
1471
1520
|
}
|
|
1472
1521
|
}
|
|
1473
1522
|
};
|
|
1523
|
+
hooks.useEffect(() => {
|
|
1524
|
+
emit('opened', {
|
|
1525
|
+
domNode: popupRef.current
|
|
1526
|
+
});
|
|
1527
|
+
return () => emit('close', {
|
|
1528
|
+
domNode: popupRef.current
|
|
1529
|
+
});
|
|
1530
|
+
}, []);
|
|
1474
1531
|
return jsxRuntime.jsxs(Popup, {
|
|
1475
1532
|
container: container,
|
|
1476
1533
|
className: "bio-properties-panel-feel-popup",
|
|
1534
|
+
emit: emit,
|
|
1477
1535
|
position: position,
|
|
1478
1536
|
title: title,
|
|
1479
1537
|
onClose: onClose
|
|
@@ -1486,8 +1544,10 @@ function FeelPopupComponent(props) {
|
|
|
1486
1544
|
onPostDeactivate: handleSetReturnFocus,
|
|
1487
1545
|
height: FEEL_POPUP_HEIGHT,
|
|
1488
1546
|
width: FEEL_POPUP_WIDTH,
|
|
1547
|
+
ref: popupRef,
|
|
1489
1548
|
children: [jsxRuntime.jsx(Popup.Title, {
|
|
1490
1549
|
title: title,
|
|
1550
|
+
emit: emit,
|
|
1491
1551
|
draggable: true
|
|
1492
1552
|
}), jsxRuntime.jsx(Popup.Body, {
|
|
1493
1553
|
children: jsxRuntime.jsxs("div", {
|
|
@@ -1538,6 +1598,23 @@ function autoCompletionOpen(element) {
|
|
|
1538
1598
|
return element.closest('.cm-editor').querySelector('.cm-tooltip-autocomplete');
|
|
1539
1599
|
}
|
|
1540
1600
|
|
|
1601
|
+
/**
|
|
1602
|
+
* This hook behaves like useEffect, but does not trigger on the first render.
|
|
1603
|
+
*
|
|
1604
|
+
* @param {Function} effect
|
|
1605
|
+
* @param {Array} deps
|
|
1606
|
+
*/
|
|
1607
|
+
function useUpdateEffect(effect, deps) {
|
|
1608
|
+
const isMounted = hooks.useRef(false);
|
|
1609
|
+
hooks.useEffect(() => {
|
|
1610
|
+
if (isMounted.current) {
|
|
1611
|
+
return effect();
|
|
1612
|
+
} else {
|
|
1613
|
+
isMounted.current = true;
|
|
1614
|
+
}
|
|
1615
|
+
}, deps);
|
|
1616
|
+
}
|
|
1617
|
+
|
|
1541
1618
|
function ToggleSwitch(props) {
|
|
1542
1619
|
const {
|
|
1543
1620
|
id,
|