@bpmn-io/properties-panel 3.7.1 → 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 +94 -24
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +93 -23
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -1237,7 +1237,7 @@ textarea.bio-properties-panel-input {
|
|
|
1237
1237
|
--feel-popup-close-background-color: hsla(219, 99%, 53%, 1);
|
|
1238
1238
|
--feel-popup-gutters-background-color: hsla(0, 0%, 90%, 1);
|
|
1239
1239
|
|
|
1240
|
-
position:
|
|
1240
|
+
position: fixed;
|
|
1241
1241
|
display: flex;
|
|
1242
1242
|
flex: auto;
|
|
1243
1243
|
flex-direction: column;
|
package/dist/index.esm.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useContext, useState, useRef, useEffect, useMemo, useCallback, useLayoutEffect } from '../preact/hooks';
|
|
2
|
-
import { isFunction,
|
|
2
|
+
import { isFunction, isString, isArray, get, assign, set, sortBy, find, isNumber, debounce } from 'min-dash';
|
|
3
3
|
import { createPortal, forwardRef } from '../preact/compat';
|
|
4
4
|
import { jsx, jsxs, Fragment } from '../preact/jsx-runtime';
|
|
5
5
|
import { createContext, createElement } from '../preact';
|
|
@@ -649,20 +649,24 @@ function Group(props) {
|
|
|
649
649
|
|
|
650
650
|
// set edited state depending on all entries
|
|
651
651
|
useEffect(() => {
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
652
|
+
// 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
|
|
653
|
+
const scheduled = requestAnimationFrame(() => {
|
|
654
|
+
const hasOneEditedEntry = entries.find(entry => {
|
|
655
|
+
const {
|
|
656
|
+
id,
|
|
657
|
+
isEdited
|
|
658
|
+
} = entry;
|
|
659
|
+
const entryNode = query(`[data-entry-id="${id}"]`);
|
|
660
|
+
if (!isFunction(isEdited) || !entryNode) {
|
|
661
|
+
return false;
|
|
662
|
+
}
|
|
663
|
+
const inputNode = query('.bio-properties-panel-input', entryNode);
|
|
664
|
+
return isEdited(inputNode);
|
|
665
|
+
});
|
|
666
|
+
setEdited(hasOneEditedEntry);
|
|
663
667
|
});
|
|
664
|
-
|
|
665
|
-
}, [entries]);
|
|
668
|
+
return () => cancelAnimationFrame(scheduled);
|
|
669
|
+
}, [entries, setEdited]);
|
|
666
670
|
|
|
667
671
|
// set error state depending on all entries
|
|
668
672
|
const allErrors = useErrors();
|
|
@@ -1096,7 +1100,11 @@ function createDragger(fn, dragPreview) {
|
|
|
1096
1100
|
// (2) setup drag listeners
|
|
1097
1101
|
|
|
1098
1102
|
// attach drag + cleanup event
|
|
1099
|
-
|
|
1103
|
+
// we need to do this to make sure we track cursor
|
|
1104
|
+
// movements before we reach other drag event handlers,
|
|
1105
|
+
// e.g. in child containers.
|
|
1106
|
+
document.addEventListener('dragover', onDrag, true);
|
|
1107
|
+
document.addEventListener('dragenter', preventDefault, true);
|
|
1100
1108
|
document.addEventListener('dragend', onEnd);
|
|
1101
1109
|
document.addEventListener('drop', preventDefault);
|
|
1102
1110
|
}
|
|
@@ -1110,7 +1118,8 @@ function createDragger(fn, dragPreview) {
|
|
|
1110
1118
|
return fn.call(self, event, delta);
|
|
1111
1119
|
}
|
|
1112
1120
|
function onEnd() {
|
|
1113
|
-
document.removeEventListener('dragover', onDrag);
|
|
1121
|
+
document.removeEventListener('dragover', onDrag, true);
|
|
1122
|
+
document.removeEventListener('dragenter', preventDefault, true);
|
|
1114
1123
|
document.removeEventListener('dragend', onEnd);
|
|
1115
1124
|
document.removeEventListener('drop', preventDefault);
|
|
1116
1125
|
}
|
|
@@ -1142,8 +1151,9 @@ const noop$3 = () => {};
|
|
|
1142
1151
|
* @param {boolean} [props.returnFocus]
|
|
1143
1152
|
* @param {boolean} [props.closeOnEscape]
|
|
1144
1153
|
* @param {string} props.title
|
|
1154
|
+
* @param {Ref} [ref]
|
|
1145
1155
|
*/
|
|
1146
|
-
function
|
|
1156
|
+
function PopupComponent(props, globalRef) {
|
|
1147
1157
|
const {
|
|
1148
1158
|
container,
|
|
1149
1159
|
className,
|
|
@@ -1159,7 +1169,8 @@ function Popup(props) {
|
|
|
1159
1169
|
title
|
|
1160
1170
|
} = props;
|
|
1161
1171
|
const focusTrapRef = useRef(null);
|
|
1162
|
-
const
|
|
1172
|
+
const localRef = useRef(null);
|
|
1173
|
+
const popupRef = globalRef || localRef;
|
|
1163
1174
|
const handleKeydown = event => {
|
|
1164
1175
|
// do not allow keyboard events to bubble
|
|
1165
1176
|
event.stopPropagation();
|
|
@@ -1221,6 +1232,7 @@ function Popup(props) {
|
|
|
1221
1232
|
children: props.children
|
|
1222
1233
|
}), container || document.body);
|
|
1223
1234
|
}
|
|
1235
|
+
const Popup = forwardRef(PopupComponent);
|
|
1224
1236
|
Popup.Title = Title;
|
|
1225
1237
|
Popup.Body = Body;
|
|
1226
1238
|
Popup.Footer = Footer;
|
|
@@ -1229,6 +1241,7 @@ function Title(props) {
|
|
|
1229
1241
|
children,
|
|
1230
1242
|
className,
|
|
1231
1243
|
draggable,
|
|
1244
|
+
emit = () => {},
|
|
1232
1245
|
title,
|
|
1233
1246
|
...rest
|
|
1234
1247
|
} = props;
|
|
@@ -1241,7 +1254,8 @@ function Title(props) {
|
|
|
1241
1254
|
});
|
|
1242
1255
|
const dragPreviewRef = useRef();
|
|
1243
1256
|
const titleRef = useRef();
|
|
1244
|
-
const onMove =
|
|
1257
|
+
const onMove = (event, delta) => {
|
|
1258
|
+
cancel(event);
|
|
1245
1259
|
const {
|
|
1246
1260
|
x: dx,
|
|
1247
1261
|
y: dy
|
|
@@ -1253,20 +1267,33 @@ function Title(props) {
|
|
|
1253
1267
|
const popupParent = getPopupParent(titleRef.current);
|
|
1254
1268
|
popupParent.style.top = newPosition.y + 'px';
|
|
1255
1269
|
popupParent.style.left = newPosition.x + 'px';
|
|
1256
|
-
|
|
1270
|
+
|
|
1271
|
+
// notify interested parties
|
|
1272
|
+
emit('dragover', {
|
|
1273
|
+
newPosition,
|
|
1274
|
+
delta
|
|
1275
|
+
});
|
|
1276
|
+
};
|
|
1257
1277
|
const onMoveStart = event => {
|
|
1258
1278
|
// initialize drag handler
|
|
1259
1279
|
const onDragStart = createDragger(onMove, dragPreviewRef.current);
|
|
1260
1280
|
onDragStart(event);
|
|
1281
|
+
event.stopPropagation();
|
|
1261
1282
|
const popupParent = getPopupParent(titleRef.current);
|
|
1262
1283
|
const bounds = popupParent.getBoundingClientRect();
|
|
1263
1284
|
context.current.startPosition = {
|
|
1264
1285
|
x: bounds.left,
|
|
1265
1286
|
y: bounds.top
|
|
1266
1287
|
};
|
|
1288
|
+
|
|
1289
|
+
// notify interested parties
|
|
1290
|
+
emit('dragstart');
|
|
1267
1291
|
};
|
|
1268
1292
|
const onMoveEnd = () => {
|
|
1269
1293
|
context.current.newPosition = null;
|
|
1294
|
+
|
|
1295
|
+
// notify interested parties
|
|
1296
|
+
emit('dragend');
|
|
1270
1297
|
};
|
|
1271
1298
|
return jsxs("div", {
|
|
1272
1299
|
class: classnames('bio-properties-panel-popup__header', draggable && 'draggable', className),
|
|
@@ -1319,12 +1346,20 @@ function Footer(props) {
|
|
|
1319
1346
|
function getPopupParent(node) {
|
|
1320
1347
|
return node.closest('.bio-properties-panel-popup');
|
|
1321
1348
|
}
|
|
1349
|
+
function cancel(event) {
|
|
1350
|
+
event.preventDefault();
|
|
1351
|
+
event.stopPropagation();
|
|
1352
|
+
}
|
|
1322
1353
|
|
|
1323
1354
|
const FEEL_POPUP_WIDTH = 700;
|
|
1324
1355
|
const FEEL_POPUP_HEIGHT = 250;
|
|
1325
1356
|
|
|
1326
1357
|
/**
|
|
1327
|
-
* FEEL popup component, built as a singleton.
|
|
1358
|
+
* FEEL popup component, built as a singleton. Emits lifecycle events as follows:
|
|
1359
|
+
* - `feelPopup.open` - fired before the popup is mounted
|
|
1360
|
+
* - `feelPopup.opened` - fired after the popup is mounted. Event context contains the DOM node of the popup
|
|
1361
|
+
* - `feelPopup.close` - fired before the popup is unmounted. Event context contains the DOM node of the popup
|
|
1362
|
+
* - `feelPopup.closed` - fired after the popup is unmounted
|
|
1328
1363
|
*/
|
|
1329
1364
|
function FEELPopupRoot(props) {
|
|
1330
1365
|
const {
|
|
@@ -1347,17 +1382,21 @@ function FEELPopupRoot(props) {
|
|
|
1347
1382
|
const isOpen = useCallback(() => {
|
|
1348
1383
|
return !!open;
|
|
1349
1384
|
}, [open]);
|
|
1385
|
+
useUpdateEffect(() => {
|
|
1386
|
+
if (!open) {
|
|
1387
|
+
emit('closed');
|
|
1388
|
+
}
|
|
1389
|
+
}, [open]);
|
|
1350
1390
|
const handleOpen = (entryId, config, _sourceElement) => {
|
|
1351
1391
|
setSource(entryId);
|
|
1352
1392
|
setPopupConfig(config);
|
|
1353
1393
|
setOpen(true);
|
|
1354
1394
|
setSourceElement(_sourceElement);
|
|
1355
|
-
emit('
|
|
1395
|
+
emit('open');
|
|
1356
1396
|
};
|
|
1357
1397
|
const handleClose = () => {
|
|
1358
1398
|
setOpen(false);
|
|
1359
1399
|
setSource(null);
|
|
1360
|
-
emit('closed');
|
|
1361
1400
|
};
|
|
1362
1401
|
const feelPopupContext = {
|
|
1363
1402
|
open: handleOpen,
|
|
@@ -1400,6 +1439,7 @@ function FEELPopupRoot(props) {
|
|
|
1400
1439
|
onClose: handleClose,
|
|
1401
1440
|
container: popupContainer,
|
|
1402
1441
|
sourceElement: sourceElement,
|
|
1442
|
+
emit: emit,
|
|
1403
1443
|
...popupConfig
|
|
1404
1444
|
}), props.children]
|
|
1405
1445
|
});
|
|
@@ -1418,9 +1458,11 @@ function FeelPopupComponent(props) {
|
|
|
1418
1458
|
tooltipContainer,
|
|
1419
1459
|
type,
|
|
1420
1460
|
value,
|
|
1421
|
-
variables
|
|
1461
|
+
variables,
|
|
1462
|
+
emit
|
|
1422
1463
|
} = props;
|
|
1423
1464
|
const editorRef = useRef();
|
|
1465
|
+
const popupRef = useRef();
|
|
1424
1466
|
const isAutoCompletionOpen = useRef(false);
|
|
1425
1467
|
const handleSetReturnFocus = () => {
|
|
1426
1468
|
sourceElement && sourceElement.focus();
|
|
@@ -1443,9 +1485,18 @@ function FeelPopupComponent(props) {
|
|
|
1443
1485
|
}
|
|
1444
1486
|
}
|
|
1445
1487
|
};
|
|
1488
|
+
useEffect(() => {
|
|
1489
|
+
emit('opened', {
|
|
1490
|
+
domNode: popupRef.current
|
|
1491
|
+
});
|
|
1492
|
+
return () => emit('close', {
|
|
1493
|
+
domNode: popupRef.current
|
|
1494
|
+
});
|
|
1495
|
+
}, []);
|
|
1446
1496
|
return jsxs(Popup, {
|
|
1447
1497
|
container: container,
|
|
1448
1498
|
className: "bio-properties-panel-feel-popup",
|
|
1499
|
+
emit: emit,
|
|
1449
1500
|
position: position,
|
|
1450
1501
|
title: title,
|
|
1451
1502
|
onClose: onClose
|
|
@@ -1458,8 +1509,10 @@ function FeelPopupComponent(props) {
|
|
|
1458
1509
|
onPostDeactivate: handleSetReturnFocus,
|
|
1459
1510
|
height: FEEL_POPUP_HEIGHT,
|
|
1460
1511
|
width: FEEL_POPUP_WIDTH,
|
|
1512
|
+
ref: popupRef,
|
|
1461
1513
|
children: [jsx(Popup.Title, {
|
|
1462
1514
|
title: title,
|
|
1515
|
+
emit: emit,
|
|
1463
1516
|
draggable: true
|
|
1464
1517
|
}), jsx(Popup.Body, {
|
|
1465
1518
|
children: jsxs("div", {
|
|
@@ -1510,6 +1563,23 @@ function autoCompletionOpen(element) {
|
|
|
1510
1563
|
return element.closest('.cm-editor').querySelector('.cm-tooltip-autocomplete');
|
|
1511
1564
|
}
|
|
1512
1565
|
|
|
1566
|
+
/**
|
|
1567
|
+
* This hook behaves like useEffect, but does not trigger on the first render.
|
|
1568
|
+
*
|
|
1569
|
+
* @param {Function} effect
|
|
1570
|
+
* @param {Array} deps
|
|
1571
|
+
*/
|
|
1572
|
+
function useUpdateEffect(effect, deps) {
|
|
1573
|
+
const isMounted = useRef(false);
|
|
1574
|
+
useEffect(() => {
|
|
1575
|
+
if (isMounted.current) {
|
|
1576
|
+
return effect();
|
|
1577
|
+
} else {
|
|
1578
|
+
isMounted.current = true;
|
|
1579
|
+
}
|
|
1580
|
+
}, deps);
|
|
1581
|
+
}
|
|
1582
|
+
|
|
1513
1583
|
function ToggleSwitch(props) {
|
|
1514
1584
|
const {
|
|
1515
1585
|
id,
|