@bpmn-io/properties-panel 3.18.2 → 3.19.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 +41 -132
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +40 -131
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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, isString, isArray, get, assign, set,
|
|
2
|
+
import { isFunction, isString, isArray, get, assign, set, 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';
|
|
@@ -2666,7 +2666,6 @@ const DEFAULT_TOOLTIP = {};
|
|
|
2666
2666
|
* id: String,
|
|
2667
2667
|
* items: Array<ListItemDefinition>,
|
|
2668
2668
|
* label: String,
|
|
2669
|
-
* shouldSort?: Boolean,
|
|
2670
2669
|
* shouldOpen?: Boolean
|
|
2671
2670
|
* } } ListGroupDefinition
|
|
2672
2671
|
*
|
|
@@ -3099,6 +3098,7 @@ function ListItem(props) {
|
|
|
3099
3098
|
} else if (isFunction(focusableInput.focus)) {
|
|
3100
3099
|
focusableInput.focus();
|
|
3101
3100
|
}
|
|
3101
|
+
focusableInput.scrollIntoView();
|
|
3102
3102
|
}
|
|
3103
3103
|
}
|
|
3104
3104
|
}, [autoOpen, autoFocusEntry]);
|
|
@@ -3123,97 +3123,61 @@ function ListGroup(props) {
|
|
|
3123
3123
|
id,
|
|
3124
3124
|
items,
|
|
3125
3125
|
label,
|
|
3126
|
-
shouldOpen = true
|
|
3127
|
-
shouldSort = true
|
|
3126
|
+
shouldOpen = true
|
|
3128
3127
|
} = props;
|
|
3128
|
+
useEffect(() => {
|
|
3129
|
+
if (props.shouldSort != undefined) {
|
|
3130
|
+
console.warn('the property \'shouldSort\' is no longer supported');
|
|
3131
|
+
}
|
|
3132
|
+
}, [props.shouldSort]);
|
|
3129
3133
|
const groupRef = useRef(null);
|
|
3130
3134
|
const [open, setOpen] = useLayoutState(['groups', id, 'open'], false);
|
|
3131
3135
|
const [sticky, setSticky] = useState(false);
|
|
3132
3136
|
const onShow = useCallback(() => setOpen(true), [setOpen]);
|
|
3133
|
-
const [
|
|
3134
|
-
const [
|
|
3137
|
+
const [localItems, setLocalItems] = useState([]);
|
|
3138
|
+
const [newlyAddedItemIds, setNewlyAddedItemIds] = useState([]);
|
|
3135
3139
|
|
|
3136
3140
|
// Flag to mark that add button was clicked in the last render cycle
|
|
3137
3141
|
const [addTriggered, setAddTriggered] = useState(false);
|
|
3138
|
-
const prevItems = usePrevious(items);
|
|
3139
3142
|
const prevElement = usePrevious(element);
|
|
3140
3143
|
const elementChanged = element !== prevElement;
|
|
3141
|
-
const shouldHandleEffects = !elementChanged &&
|
|
3142
|
-
|
|
3143
|
-
//
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
//
|
|
3149
|
-
|
|
3150
|
-
// (0) set initial ordering from given items
|
|
3144
|
+
const shouldHandleEffects = !elementChanged && shouldOpen;
|
|
3145
|
+
|
|
3146
|
+
// (0) delay setting items
|
|
3147
|
+
//
|
|
3148
|
+
// We need to this to align the render cycles of items
|
|
3149
|
+
// with the detection of newly added items.
|
|
3150
|
+
// This is important, because the autoOpen property can
|
|
3151
|
+
// only set per list item on its very first render.
|
|
3151
3152
|
useEffect(() => {
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
}
|
|
3155
|
-
}, [items, element]);
|
|
3153
|
+
setLocalItems(items);
|
|
3154
|
+
}, [items]);
|
|
3156
3155
|
|
|
3157
|
-
// (1) items were added
|
|
3156
|
+
// (1) handle auto opening when items were added
|
|
3158
3157
|
useEffect(() => {
|
|
3159
3158
|
// reset addTriggered flag
|
|
3160
3159
|
setAddTriggered(false);
|
|
3161
|
-
if (shouldHandleEffects &&
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3160
|
+
if (shouldHandleEffects && localItems) {
|
|
3161
|
+
if (addTriggered) {
|
|
3162
|
+
const previousItemIds = localItems.map(item => item.id);
|
|
3163
|
+
const currentItemsIds = items.map(item => item.id);
|
|
3164
|
+
const newItemIds = currentItemsIds.filter(itemId => !previousItemIds.includes(itemId));
|
|
3165
|
+
|
|
3166
|
+
// open if not open, configured and triggered by add button
|
|
3167
|
+
//
|
|
3168
|
+
// TODO(marstamm): remove once we refactor layout handling for listGroups.
|
|
3169
|
+
// Ideally, opening should be handled as part of the `add` callback and
|
|
3170
|
+
// not be a concern for the ListGroup component.
|
|
3171
|
+
if (!open && shouldOpen && newItemIds.length > 0) {
|
|
3172
|
+
toggleOpen();
|
|
3166
3173
|
}
|
|
3167
|
-
|
|
3168
|
-
let newOrdering = ordering;
|
|
3169
|
-
|
|
3170
|
-
// open if not open, configured and triggered by add button
|
|
3171
|
-
//
|
|
3172
|
-
// TODO(marstamm): remove once we refactor layout handling for listGroups.
|
|
3173
|
-
// Ideally, opening should be handled as part of the `add` callback and
|
|
3174
|
-
// not be a concern for the ListGroup component.
|
|
3175
|
-
if (addTriggered && !open && shouldOpen) {
|
|
3176
|
-
toggleOpen();
|
|
3177
|
-
}
|
|
3178
|
-
|
|
3179
|
-
// filter when not open and configured
|
|
3180
|
-
if (!open && shouldSort) {
|
|
3181
|
-
newOrdering = createOrdering(sortItems(items));
|
|
3182
|
-
}
|
|
3183
|
-
|
|
3184
|
-
// add new items on top or bottom depending on sorting behavior
|
|
3185
|
-
newOrdering = newOrdering.filter(item => !add.includes(item));
|
|
3186
|
-
if (shouldSort) {
|
|
3187
|
-
newOrdering.unshift(...add);
|
|
3174
|
+
setNewlyAddedItemIds(newItemIds);
|
|
3188
3175
|
} else {
|
|
3189
|
-
|
|
3176
|
+
// ignore newly added items that do not result from a triggered add
|
|
3177
|
+
setNewlyAddedItemIds([]);
|
|
3190
3178
|
}
|
|
3191
|
-
setOrdering(newOrdering);
|
|
3192
|
-
setNewItemAdded(addTriggered);
|
|
3193
|
-
} else {
|
|
3194
|
-
setNewItemAdded(false);
|
|
3195
|
-
}
|
|
3196
|
-
}, [items, open, shouldHandleEffects, addTriggered]);
|
|
3197
|
-
|
|
3198
|
-
// (2) sort items on open if shouldSort is set
|
|
3199
|
-
useEffect(() => {
|
|
3200
|
-
if (shouldSort && open && !newItemAdded) {
|
|
3201
|
-
setOrdering(createOrdering(sortItems(items)));
|
|
3202
|
-
}
|
|
3203
|
-
}, [open, shouldSort]);
|
|
3204
|
-
|
|
3205
|
-
// (3) items were deleted
|
|
3206
|
-
useEffect(() => {
|
|
3207
|
-
if (shouldHandleEffects && prevItems && items.length < prevItems.length) {
|
|
3208
|
-
let keep = [];
|
|
3209
|
-
ordering.forEach(o => {
|
|
3210
|
-
if (getItem(items, o)) {
|
|
3211
|
-
keep.push(o);
|
|
3212
|
-
}
|
|
3213
|
-
});
|
|
3214
|
-
setOrdering(keep);
|
|
3215
3179
|
}
|
|
3216
|
-
}, [items, shouldHandleEffects]);
|
|
3180
|
+
}, [items, open, shouldHandleEffects, addTriggered, localItems]);
|
|
3217
3181
|
|
|
3218
3182
|
// set css class when group is sticky to top
|
|
3219
3183
|
useStickyIntersectionObserver(groupRef, 'div.bio-properties-panel-scroll-container', setSticky);
|
|
@@ -3285,8 +3249,7 @@ function ListGroup(props) {
|
|
|
3285
3249
|
class: classnames('bio-properties-panel-list', open && hasItems ? 'open' : ''),
|
|
3286
3250
|
children: jsx(LayoutContext.Provider, {
|
|
3287
3251
|
value: propertiesPanelContext,
|
|
3288
|
-
children:
|
|
3289
|
-
const item = getItem(items, o);
|
|
3252
|
+
children: localItems.map((item, index) => {
|
|
3290
3253
|
if (!item) {
|
|
3291
3254
|
return;
|
|
3292
3255
|
}
|
|
@@ -3296,7 +3259,7 @@ function ListGroup(props) {
|
|
|
3296
3259
|
|
|
3297
3260
|
// if item was added, open it
|
|
3298
3261
|
// Existing items will not be affected as autoOpen is only applied on first render
|
|
3299
|
-
const autoOpen =
|
|
3262
|
+
const autoOpen = newlyAddedItemIds.includes(item.id);
|
|
3300
3263
|
return createElement(ListItem, {
|
|
3301
3264
|
...item,
|
|
3302
3265
|
autoOpen: autoOpen,
|
|
@@ -3310,21 +3273,6 @@ function ListGroup(props) {
|
|
|
3310
3273
|
});
|
|
3311
3274
|
}
|
|
3312
3275
|
|
|
3313
|
-
// helpers ////////////////////
|
|
3314
|
-
|
|
3315
|
-
/**
|
|
3316
|
-
* Sorts given items alphanumeric by label
|
|
3317
|
-
*/
|
|
3318
|
-
function sortItems(items) {
|
|
3319
|
-
return sortBy(items, i => i.label.toLowerCase());
|
|
3320
|
-
}
|
|
3321
|
-
function getItem(items, id) {
|
|
3322
|
-
return find(items, i => i.id === id);
|
|
3323
|
-
}
|
|
3324
|
-
function createOrdering(items) {
|
|
3325
|
-
return items.map(i => i.id);
|
|
3326
|
-
}
|
|
3327
|
-
|
|
3328
3276
|
function Checkbox(props) {
|
|
3329
3277
|
const {
|
|
3330
3278
|
id,
|
|
@@ -3616,16 +3564,12 @@ function List(props) {
|
|
|
3616
3564
|
onAdd,
|
|
3617
3565
|
onRemove,
|
|
3618
3566
|
autoFocusEntry,
|
|
3619
|
-
compareFn,
|
|
3620
3567
|
...restProps
|
|
3621
3568
|
} = props;
|
|
3622
3569
|
const [open, setOpen] = useState(!!shouldOpen);
|
|
3623
3570
|
const hasItems = !!items.length;
|
|
3624
3571
|
const toggleOpen = () => hasItems && setOpen(!open);
|
|
3625
|
-
const opening = !usePrevious(open) && open;
|
|
3626
3572
|
const elementChanged = usePrevious(element) !== element;
|
|
3627
|
-
const shouldReset = opening || elementChanged;
|
|
3628
|
-
const sortedItems = useSortedItems(items, compareFn, shouldReset);
|
|
3629
3573
|
const newItems = useNewItems(items, elementChanged);
|
|
3630
3574
|
useEffect(() => {
|
|
3631
3575
|
if (open && !hasItems) {
|
|
@@ -3683,7 +3627,7 @@ function List(props) {
|
|
|
3683
3627
|
component: component,
|
|
3684
3628
|
element: element,
|
|
3685
3629
|
id: id,
|
|
3686
|
-
items:
|
|
3630
|
+
items: items,
|
|
3687
3631
|
newItems: newItems,
|
|
3688
3632
|
onRemove: onRemove,
|
|
3689
3633
|
open: open
|
|
@@ -3747,41 +3691,6 @@ function ItemsList(props) {
|
|
|
3747
3691
|
})
|
|
3748
3692
|
});
|
|
3749
3693
|
}
|
|
3750
|
-
|
|
3751
|
-
/**
|
|
3752
|
-
* Place new items in the beginning of the list and sort the rest with provided function.
|
|
3753
|
-
*
|
|
3754
|
-
* @template Item
|
|
3755
|
-
* @param {Item[]} currentItems
|
|
3756
|
-
* @param {(a: Item, b: Item) => 0 | 1 | -1} [compareFn] function used to sort items
|
|
3757
|
-
* @param {boolean} [shouldReset=false] set to `true` to reset state of the hook
|
|
3758
|
-
* @returns {Item[]}
|
|
3759
|
-
*/
|
|
3760
|
-
function useSortedItems(currentItems, compareFn, shouldReset = false) {
|
|
3761
|
-
const itemsRef = useRef(currentItems.slice());
|
|
3762
|
-
|
|
3763
|
-
// (1) Reset and optionally sort.
|
|
3764
|
-
if (shouldReset) {
|
|
3765
|
-
itemsRef.current = currentItems.slice();
|
|
3766
|
-
if (compareFn) {
|
|
3767
|
-
itemsRef.current.sort(compareFn);
|
|
3768
|
-
}
|
|
3769
|
-
} else {
|
|
3770
|
-
const items = itemsRef.current;
|
|
3771
|
-
|
|
3772
|
-
// (2) Add new item to the list.
|
|
3773
|
-
for (const item of currentItems) {
|
|
3774
|
-
if (!items.includes(item)) {
|
|
3775
|
-
// Unshift or push depending on whether we have a compareFn
|
|
3776
|
-
compareFn ? items.unshift(item) : items.push(item);
|
|
3777
|
-
}
|
|
3778
|
-
}
|
|
3779
|
-
|
|
3780
|
-
// (3) Filter out removed items.
|
|
3781
|
-
itemsRef.current = items.filter(item => currentItems.includes(item));
|
|
3782
|
-
}
|
|
3783
|
-
return itemsRef.current;
|
|
3784
|
-
}
|
|
3785
3694
|
function useNewItems(items = [], shouldReset) {
|
|
3786
3695
|
const previousItems = usePrevious(items.slice()) || [];
|
|
3787
3696
|
if (shouldReset) {
|