@bpmn-io/properties-panel 0.24.0 → 0.25.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
@@ -8,52 +8,50 @@ import { createContext, createElement } from '../preact';
8
8
  import FeelEditor from '@bpmn-io/feel-editor';
9
9
 
10
10
  var ArrowIcon = function ArrowIcon(props) {
11
- return jsx("svg", { ...props,
11
+ return jsx("svg", {
12
+ ...props,
12
13
  children: jsx("path", {
13
14
  fillRule: "evenodd",
14
15
  d: "m11.657 8-4.95 4.95a1 1 0 0 1-1.414-1.414L8.828 8 5.293 4.464A1 1 0 1 1 6.707 3.05L11.657 8Z"
15
16
  })
16
17
  });
17
18
  };
18
-
19
19
  ArrowIcon.defaultProps = {
20
20
  xmlns: "http://www.w3.org/2000/svg",
21
21
  width: "16",
22
22
  height: "16"
23
23
  };
24
-
25
24
  var CreateIcon = function CreateIcon(props) {
26
- return jsx("svg", { ...props,
25
+ return jsx("svg", {
26
+ ...props,
27
27
  children: jsx("path", {
28
28
  fillRule: "evenodd",
29
29
  d: "M9 13V9h4a1 1 0 0 0 0-2H9V3a1 1 0 1 0-2 0v4H3a1 1 0 1 0 0 2h4v4a1 1 0 0 0 2 0Z"
30
30
  })
31
31
  });
32
32
  };
33
-
34
33
  CreateIcon.defaultProps = {
35
34
  xmlns: "http://www.w3.org/2000/svg",
36
35
  width: "16",
37
36
  height: "16"
38
37
  };
39
-
40
38
  var DeleteIcon = function DeleteIcon(props) {
41
- return jsx("svg", { ...props,
39
+ return jsx("svg", {
40
+ ...props,
42
41
  children: jsx("path", {
43
42
  fillRule: "evenodd",
44
43
  d: "M12 6v7c0 1.1-.4 1.55-1.5 1.55h-5C4.4 14.55 4 14.1 4 13V6h8Zm-1.5 1.5h-5v4.3c0 .66.5 1.2 1.111 1.2H9.39c.611 0 1.111-.54 1.111-1.2V7.5ZM13 3h-2l-1-1H6L5 3H3v1.5h10V3Z"
45
44
  })
46
45
  });
47
46
  };
48
-
49
47
  DeleteIcon.defaultProps = {
50
48
  xmlns: "http://www.w3.org/2000/svg",
51
49
  width: "16",
52
50
  height: "16"
53
51
  };
54
-
55
52
  var ExternalLinkIcon = function ExternalLinkIcon(props) {
56
- return jsx("svg", { ...props,
53
+ return jsx("svg", {
54
+ ...props,
57
55
  children: jsx("path", {
58
56
  fillRule: "evenodd",
59
57
  clipRule: "evenodd",
@@ -62,16 +60,15 @@ var ExternalLinkIcon = function ExternalLinkIcon(props) {
62
60
  })
63
61
  });
64
62
  };
65
-
66
63
  ExternalLinkIcon.defaultProps = {
67
64
  width: "16",
68
65
  height: "16",
69
66
  fill: "none",
70
67
  xmlns: "http://www.w3.org/2000/svg"
71
68
  };
72
-
73
69
  var FeelRequiredIcon = function FeelRequiredIcon(props) {
74
- return jsxs("svg", { ...props,
70
+ return jsxs("svg", {
71
+ ...props,
75
72
  children: [jsx("path", {
76
73
  d: "M5.8 7.06V5.95h4.307v1.11H5.8Zm0 3.071v-1.11h4.307v1.11H5.8Z",
77
74
  fill: "currentColor"
@@ -86,15 +83,14 @@ var FeelRequiredIcon = function FeelRequiredIcon(props) {
86
83
  })]
87
84
  });
88
85
  };
89
-
90
86
  FeelRequiredIcon.defaultProps = {
91
87
  viewBox: "0 0 16 16",
92
88
  fill: "none",
93
89
  xmlns: "http://www.w3.org/2000/svg"
94
90
  };
95
-
96
91
  var FeelOptionalIcon = function FeelOptionalIcon(props) {
97
- return jsxs("svg", { ...props,
92
+ return jsxs("svg", {
93
+ ...props,
98
94
  children: [jsx("path", {
99
95
  d: "M5.845 7.04V5.93h4.307v1.11H5.845Zm0 3.07V9h4.307v1.11H5.845Z",
100
96
  fill: "currentColor"
@@ -106,7 +102,6 @@ var FeelOptionalIcon = function FeelOptionalIcon(props) {
106
102
  })]
107
103
  });
108
104
  };
109
-
110
105
  FeelOptionalIcon.defaultProps = {
111
106
  viewBox: "0 0 16 16",
112
107
  fill: "none",
@@ -211,7 +206,6 @@ const LayoutContext = createContext({
211
206
  *
212
207
  * @returns {string}
213
208
  */
214
-
215
209
  function useDescriptionContext(id, element) {
216
210
  const {
217
211
  getDescriptionForId
@@ -232,28 +226,25 @@ function useError(id) {
232
226
  * @param {string} event
233
227
  * @param {Function} callback
234
228
  */
235
-
236
229
  function useEvent(event, callback, eventBus) {
237
230
  const eventContext = useContext(EventContext);
238
-
239
231
  if (!eventBus) {
240
232
  ({
241
233
  eventBus
242
234
  } = eventContext);
243
235
  }
236
+ const didMount = useRef(false);
244
237
 
245
- const didMount = useRef(false); // (1) subscribe immediately
246
-
238
+ // (1) subscribe immediately
247
239
  if (eventBus && !didMount.current) {
248
240
  eventBus.on(event, callback);
249
- } // (2) update subscription after inputs changed
250
-
241
+ }
251
242
 
243
+ // (2) update subscription after inputs changed
252
244
  useEffect(() => {
253
245
  if (eventBus && didMount.current) {
254
246
  eventBus.on(event, callback);
255
247
  }
256
-
257
248
  didMount.current = true;
258
249
  return () => {
259
250
  if (eventBus) {
@@ -264,6 +255,7 @@ function useEvent(event, callback, eventBus) {
264
255
  }
265
256
 
266
257
  const KEY_LENGTH = 6;
258
+
267
259
  /**
268
260
  * Create a persistent key factory for plain objects without id.
269
261
  *
@@ -283,21 +275,16 @@ const KEY_LENGTH = 6;
283
275
  * @param {any[]} dependencies
284
276
  * @returns {(element: object) => string}
285
277
  */
286
-
287
278
  function useKeyFactory(dependencies = []) {
288
279
  const map = useMemo(() => new Map(), dependencies);
289
-
290
280
  const getKey = el => {
291
281
  let key = map.get(el);
292
-
293
282
  if (!key) {
294
283
  key = Math.random().toString().slice(-KEY_LENGTH);
295
284
  map.set(el, key);
296
285
  }
297
-
298
286
  return key;
299
287
  };
300
-
301
288
  return getKey;
302
289
  }
303
290
 
@@ -316,7 +303,6 @@ function useKeyFactory(dependencies = []) {
316
303
  *
317
304
  * @returns {[ any, Function ]}
318
305
  */
319
-
320
306
  function useLayoutState(path, defaultValue) {
321
307
  const {
322
308
  getLayoutForKey,
@@ -324,14 +310,13 @@ function useLayoutState(path, defaultValue) {
324
310
  } = useContext(LayoutContext);
325
311
  const layoutForKey = getLayoutForKey(path, defaultValue);
326
312
  const [value, set] = useState(layoutForKey);
327
-
328
313
  const setState = newValue => {
329
314
  // (1) set component state
330
- set(newValue); // (2) set context
315
+ set(newValue);
331
316
 
317
+ // (2) set context
332
318
  setLayoutForKey(path, newValue);
333
319
  };
334
-
335
320
  return [value, setState];
336
321
  }
337
322
 
@@ -357,7 +342,6 @@ function usePrevious(value) {
357
342
  *
358
343
  * @returns {import('preact').Ref}
359
344
  */
360
-
361
345
  function useShowEntryEvent(id) {
362
346
  const {
363
347
  onShow
@@ -367,7 +351,6 @@ function useShowEntryEvent(id) {
367
351
  const onShowEntry = useCallback(event => {
368
352
  if (event.id === id) {
369
353
  onShow();
370
-
371
354
  if (!focus.current) {
372
355
  focus.current = true;
373
356
  }
@@ -378,11 +361,9 @@ function useShowEntryEvent(id) {
378
361
  if (isFunction(ref.current.focus)) {
379
362
  ref.current.focus();
380
363
  }
381
-
382
364
  if (isFunction(ref.current.select)) {
383
365
  ref.current.select();
384
366
  }
385
-
386
367
  focus.current = false;
387
368
  }
388
369
  });
@@ -405,17 +386,15 @@ function useShowEntryEvent(id) {
405
386
  * @param {string} scrollContainerSelector
406
387
  * @param {setSticky} setSticky
407
388
  */
408
-
409
389
  function useStickyIntersectionObserver(ref, scrollContainerSelector, setSticky) {
410
390
  useEffect(() => {
411
- const Observer = IntersectionObserver; // return early if IntersectionObserver is not available
391
+ const Observer = IntersectionObserver;
412
392
 
393
+ // return early if IntersectionObserver is not available
413
394
  if (!Observer) {
414
395
  return;
415
396
  }
416
-
417
397
  let observer;
418
-
419
398
  if (ref.current) {
420
399
  const scrollContainer = query(scrollContainerSelector);
421
400
  observer = new Observer(entries => {
@@ -433,9 +412,9 @@ function useStickyIntersectionObserver(ref, scrollContainerSelector, setSticky)
433
412
  threshold: [1]
434
413
  });
435
414
  observer.observe(ref.current);
436
- } // Unobserve if unmounted
437
-
415
+ }
438
416
 
417
+ // Unobserve if unmounted
439
418
  return () => {
440
419
  if (ref.current && observer) {
441
420
  observer.unobserve(ref.current);
@@ -458,7 +437,6 @@ function useStickyIntersectionObserver(ref, scrollContainerSelector, setSticky)
458
437
  * @param {Function} callback function with changing reference
459
438
  * @returns {Function} static function reference
460
439
  */
461
-
462
440
  function useStaticCallback(callback) {
463
441
  const callbackRef = useRef(callback);
464
442
  callbackRef.current = callback;
@@ -476,12 +454,11 @@ function Group(props) {
476
454
  const groupRef = useRef(null);
477
455
  const [open, setOpen] = useLayoutState(['groups', id, 'open'], shouldOpen);
478
456
  const onShow = useCallback(() => setOpen(true), [setOpen]);
479
-
480
457
  const toggleOpen = () => setOpen(!open);
481
-
482
458
  const [edited, setEdited] = useState(false);
483
- const [sticky, setSticky] = useState(false); // set edited state depending on all entries
459
+ const [sticky, setSticky] = useState(false);
484
460
 
461
+ // set edited state depending on all entries
485
462
  useEffect(() => {
486
463
  const hasOneEditedEntry = entries.find(entry => {
487
464
  const {
@@ -489,19 +466,19 @@ function Group(props) {
489
466
  isEdited
490
467
  } = entry;
491
468
  const entryNode = query(`[data-entry-id="${id}"]`);
492
-
493
469
  if (!isFunction(isEdited) || !entryNode) {
494
470
  return false;
495
471
  }
496
-
497
472
  const inputNode = query('.bio-properties-panel-input', entryNode);
498
473
  return isEdited(inputNode);
499
474
  });
500
475
  setEdited(hasOneEditedEntry);
501
- }, [entries]); // set css class when group is sticky to top
476
+ }, [entries]);
502
477
 
478
+ // set css class when group is sticky to top
503
479
  useStickyIntersectionObserver(groupRef, 'div.bio-properties-panel-scroll-container', setSticky);
504
- const propertiesPanelContext = { ...useContext(LayoutContext),
480
+ const propertiesPanelContext = {
481
+ ...useContext(LayoutContext),
505
482
  onShow
506
483
  };
507
484
  return jsxs("div", {
@@ -534,7 +511,8 @@ function Group(props) {
534
511
  component: Component,
535
512
  id
536
513
  } = entry;
537
- return createElement(Component, { ...entry,
514
+ return createElement(Component, {
515
+ ...entry,
538
516
  element: element,
539
517
  key: id
540
518
  });
@@ -543,7 +521,6 @@ function Group(props) {
543
521
  })]
544
522
  });
545
523
  }
546
-
547
524
  function DataMarker() {
548
525
  return jsx("div", {
549
526
  title: "Section contains data",
@@ -582,6 +559,7 @@ const DEFAULT_LAYOUT = {
582
559
  open: true
583
560
  };
584
561
  const DEFAULT_DESCRIPTION = {};
562
+
585
563
  /**
586
564
  * @typedef { {
587
565
  * component: import('preact').Component,
@@ -649,7 +627,6 @@ const DEFAULT_DESCRIPTION = {};
649
627
  * @param {Function} [props.descriptionLoaded]
650
628
  * @param {Object} [props.eventBus]
651
629
  */
652
-
653
630
  function PropertiesPanel(props) {
654
631
  const {
655
632
  element,
@@ -661,52 +638,46 @@ function PropertiesPanel(props) {
661
638
  descriptionConfig = {},
662
639
  descriptionLoaded,
663
640
  eventBus
664
- } = props; // set-up layout context
641
+ } = props;
665
642
 
643
+ // set-up layout context
666
644
  const [layout, setLayout] = useState(createLayout(layoutConfig));
667
645
  useEffect(() => {
668
646
  if (typeof layoutChanged === 'function') {
669
647
  layoutChanged(layout);
670
648
  }
671
649
  }, [layout, layoutChanged]);
672
-
673
650
  const getLayoutForKey = (key, defaultValue) => {
674
651
  return get(layout, key, defaultValue);
675
652
  };
676
-
677
653
  const setLayoutForKey = (key, config) => {
678
654
  const newLayout = assign({}, layout);
679
655
  set(newLayout, key, config);
680
656
  setLayout(newLayout);
681
657
  };
682
-
683
658
  const layoutContext = {
684
659
  layout,
685
660
  setLayout,
686
661
  getLayoutForKey,
687
662
  setLayoutForKey
688
- }; // set-up description context
663
+ };
689
664
 
665
+ // set-up description context
690
666
  const description = createDescriptionContext(descriptionConfig);
691
-
692
667
  if (typeof descriptionLoaded === 'function') {
693
668
  descriptionLoaded(description);
694
669
  }
695
-
696
670
  const getDescriptionForId = (id, element) => {
697
671
  return description[id] && description[id](element);
698
672
  };
699
-
700
673
  const descriptionContext = {
701
674
  description,
702
675
  getDescriptionForId
703
676
  };
704
677
  const [errors, setErrors] = useState({});
705
-
706
678
  const onSetErrors = ({
707
679
  errors
708
680
  }) => setErrors(errors);
709
-
710
681
  useEvent('propertiesPanel.setErrors', onSetErrors, eventBus);
711
682
  const errorsContext = {
712
683
  errors
@@ -716,19 +687,21 @@ function PropertiesPanel(props) {
716
687
  };
717
688
  const propertiesPanelContext = {
718
689
  element
719
- }; // empty state
690
+ };
720
691
 
692
+ // empty state
721
693
  if (placeholderProvider && !element) {
722
- return jsx(Placeholder, { ...placeholderProvider.getEmpty()
694
+ return jsx(Placeholder, {
695
+ ...placeholderProvider.getEmpty()
723
696
  });
724
- } // multiple state
725
-
697
+ }
726
698
 
699
+ // multiple state
727
700
  if (placeholderProvider && isArray(element)) {
728
- return jsx(Placeholder, { ...placeholderProvider.getMultiple()
701
+ return jsx(Placeholder, {
702
+ ...placeholderProvider.getMultiple()
729
703
  });
730
704
  }
731
-
732
705
  return jsx(LayoutContext.Provider, {
733
706
  value: propertiesPanelContext,
734
707
  children: jsx(ErrorsContext.Provider, {
@@ -751,7 +724,8 @@ function PropertiesPanel(props) {
751
724
  component: Component = Group,
752
725
  id
753
726
  } = group;
754
- return createElement(Component, { ...group,
727
+ return createElement(Component, {
728
+ ...group,
755
729
  key: id,
756
730
  element: element
757
731
  });
@@ -763,16 +737,19 @@ function PropertiesPanel(props) {
763
737
  })
764
738
  })
765
739
  });
766
- } // helpers //////////////////
740
+ }
741
+
742
+ // helpers //////////////////
767
743
 
768
744
  function createLayout(overrides) {
769
- return { ...DEFAULT_LAYOUT,
745
+ return {
746
+ ...DEFAULT_LAYOUT,
770
747
  ...overrides
771
748
  };
772
749
  }
773
-
774
750
  function createDescriptionContext(overrides) {
775
- return { ...DEFAULT_DESCRIPTION,
751
+ return {
752
+ ...DEFAULT_DESCRIPTION,
776
753
  ...overrides
777
754
  };
778
755
  }
@@ -786,24 +763,19 @@ function DropdownButton(props) {
786
763
  const dropdownRef = useRef(null);
787
764
  const menuRef = useRef(null);
788
765
  const [open, setOpen] = useState(false);
789
-
790
766
  const close = () => setOpen(false);
791
-
792
767
  function onDropdownToggle(event) {
793
768
  if (menuRef.current && menuRef.current.contains(event.target)) {
794
769
  return;
795
770
  }
796
-
797
771
  event.stopPropagation();
798
772
  setOpen(open => !open);
799
773
  }
800
-
801
774
  function onActionClick(event, action) {
802
775
  event.stopPropagation();
803
776
  close();
804
777
  action();
805
778
  }
806
-
807
779
  useGlobalClick([dropdownRef.current], () => close());
808
780
  return jsxs("div", {
809
781
  class: classnames('bio-properties-panel-dropdown-button', {
@@ -821,7 +793,6 @@ function DropdownButton(props) {
821
793
  })]
822
794
  });
823
795
  }
824
-
825
796
  function MenuItem({
826
797
  item,
827
798
  onClick
@@ -831,7 +802,6 @@ function MenuItem({
831
802
  class: "bio-properties-panel-dropdown-button__menu-item bio-properties-panel-dropdown-button__menu-item--separator"
832
803
  });
833
804
  }
834
-
835
805
  if (item.action) {
836
806
  return jsx("button", {
837
807
  class: "bio-properties-panel-dropdown-button__menu-item bio-properties-panel-dropdown-button__menu-item--actionable",
@@ -839,19 +809,17 @@ function MenuItem({
839
809
  children: item.entry
840
810
  });
841
811
  }
842
-
843
812
  return jsx("div", {
844
813
  class: "bio-properties-panel-dropdown-button__menu-item",
845
814
  children: item.entry
846
815
  });
847
816
  }
817
+
848
818
  /**
849
819
  *
850
820
  * @param {Array<null | Element>} ignoredElements
851
821
  * @param {Function} callback
852
822
  */
853
-
854
-
855
823
  function useGlobalClick(ignoredElements, callback) {
856
824
  useEffect(() => {
857
825
  /**
@@ -861,10 +829,8 @@ function useGlobalClick(ignoredElements, callback) {
861
829
  if (ignoredElements.some(element => element && element.contains(event.target))) {
862
830
  return;
863
831
  }
864
-
865
832
  callback();
866
833
  }
867
-
868
834
  document.addEventListener('click', listener, {
869
835
  capture: true
870
836
  });
@@ -881,7 +847,8 @@ function HeaderButton(props) {
881
847
  onClick = () => {},
882
848
  ...otherProps
883
849
  } = props;
884
- return jsx("button", { ...otherProps,
850
+ return jsx("button", {
851
+ ...otherProps,
885
852
  onClick: onClick,
886
853
  class: classnames('bio-properties-panel-group-header-button', classname),
887
854
  children: children
@@ -898,22 +865,21 @@ function CollapsibleEntry(props) {
898
865
  remove
899
866
  } = props;
900
867
  const [open, setOpen] = useState(shouldOpen);
901
-
902
868
  const toggleOpen = () => setOpen(!open);
903
-
904
869
  const {
905
870
  onShow
906
871
  } = useContext(LayoutContext);
907
- const propertiesPanelContext = { ...useContext(LayoutContext),
872
+ const propertiesPanelContext = {
873
+ ...useContext(LayoutContext),
908
874
  onShow: useCallback(() => {
909
875
  setOpen(true);
910
-
911
876
  if (isFunction(onShow)) {
912
877
  onShow();
913
878
  }
914
879
  }, [onShow, setOpen])
915
- }; // todo(pinussilvestrus): translate once we have a translate mechanism for the core
880
+ };
916
881
 
882
+ // todo(pinussilvestrus): translate once we have a translate mechanism for the core
917
883
  const placeholderLabel = '<empty>';
918
884
  return jsxs("div", {
919
885
  "data-entry-id": id,
@@ -946,7 +912,8 @@ function CollapsibleEntry(props) {
946
912
  component: Component,
947
913
  id
948
914
  } = entry;
949
- return createElement(Component, { ...entry,
915
+ return createElement(Component, {
916
+ ...entry,
950
917
  element: element,
951
918
  key: id
952
919
  });
@@ -960,13 +927,13 @@ function ListItem(props) {
960
927
  const {
961
928
  autoFocusEntry,
962
929
  autoOpen
963
- } = props; // focus specified entry on auto open
930
+ } = props;
964
931
 
932
+ // focus specified entry on auto open
965
933
  useEffect(() => {
966
934
  if (autoOpen && autoFocusEntry) {
967
935
  const entry = query(`[data-entry-id="${autoFocusEntry}"]`);
968
936
  const focusableInput = query('.bio-properties-panel-input', entry);
969
-
970
937
  if (focusableInput) {
971
938
  if (isFunction(focusableInput.select)) {
972
939
  focusableInput.select();
@@ -978,18 +945,18 @@ function ListItem(props) {
978
945
  }, [autoOpen, autoFocusEntry]);
979
946
  return jsx("div", {
980
947
  class: "bio-properties-panel-list-item",
981
- children: jsx(CollapsibleEntry, { ...props,
948
+ children: jsx(CollapsibleEntry, {
949
+ ...props,
982
950
  open: autoOpen
983
951
  })
984
952
  });
985
953
  }
986
954
 
987
955
  const noop$2 = () => {};
956
+
988
957
  /**
989
958
  * @param {import('../PropertiesPanel').ListGroupDefinition} props
990
959
  */
991
-
992
-
993
960
  function ListGroup(props) {
994
961
  const {
995
962
  add,
@@ -1009,20 +976,23 @@ function ListGroup(props) {
1009
976
  const prevItems = usePrevious(items);
1010
977
  const prevElement = usePrevious(element);
1011
978
  const elementChanged = element !== prevElement;
1012
- const shouldHandleEffects = !elementChanged && (shouldSort || shouldOpen); // reset initial ordering when element changes (before first render)
979
+ const shouldHandleEffects = !elementChanged && (shouldSort || shouldOpen);
1013
980
 
981
+ // reset initial ordering when element changes (before first render)
1014
982
  if (elementChanged) {
1015
983
  setOrdering(createOrdering(shouldSort ? sortItems(items) : items));
1016
- } // keep ordering in sync to items - and open changes
1017
- // (0) set initial ordering from given items
984
+ }
1018
985
 
986
+ // keep ordering in sync to items - and open changes
1019
987
 
988
+ // (0) set initial ordering from given items
1020
989
  useEffect(() => {
1021
990
  if (!prevItems || !shouldSort) {
1022
991
  setOrdering(createOrdering(items));
1023
992
  }
1024
- }, [items, element]); // (1) items were added
993
+ }, [items, element]);
1025
994
 
995
+ // (1) items were added
1026
996
  useEffect(() => {
1027
997
  if (shouldHandleEffects && prevItems && items.length > prevItems.length) {
1028
998
  let add = [];
@@ -1031,38 +1001,40 @@ function ListGroup(props) {
1031
1001
  add.push(item.id);
1032
1002
  }
1033
1003
  });
1034
- let newOrdering = ordering; // open if not open and configured
1004
+ let newOrdering = ordering;
1035
1005
 
1006
+ // open if not open and configured
1036
1007
  if (!open && shouldOpen) {
1037
- toggleOpen(); // if I opened and I should sort, then sort items
1008
+ toggleOpen();
1038
1009
 
1010
+ // if I opened and I should sort, then sort items
1039
1011
  if (shouldSort) {
1040
1012
  newOrdering = createOrdering(sortItems(items));
1041
1013
  }
1042
- } // add new items on top or bottom depending on sorting behavior
1043
-
1014
+ }
1044
1015
 
1016
+ // add new items on top or bottom depending on sorting behavior
1045
1017
  newOrdering = newOrdering.filter(item => !add.includes(item));
1046
-
1047
1018
  if (shouldSort) {
1048
1019
  newOrdering.unshift(...add);
1049
1020
  } else {
1050
1021
  newOrdering.push(...add);
1051
1022
  }
1052
-
1053
1023
  setOrdering(newOrdering);
1054
1024
  setNewItemAdded(true);
1055
1025
  } else {
1056
1026
  setNewItemAdded(false);
1057
1027
  }
1058
- }, [items, open, shouldHandleEffects]); // (2) sort items on open if shouldSort is set
1028
+ }, [items, open, shouldHandleEffects]);
1059
1029
 
1030
+ // (2) sort items on open if shouldSort is set
1060
1031
  useEffect(() => {
1061
1032
  if (shouldSort && open && !newItemAdded) {
1062
1033
  setOrdering(createOrdering(sortItems(items)));
1063
1034
  }
1064
- }, [open, shouldSort]); // (3) items were deleted
1035
+ }, [open, shouldSort]);
1065
1036
 
1037
+ // (3) items were deleted
1066
1038
  useEffect(() => {
1067
1039
  if (shouldHandleEffects && prevItems && items.length < prevItems.length) {
1068
1040
  let keep = [];
@@ -1073,14 +1045,14 @@ function ListGroup(props) {
1073
1045
  });
1074
1046
  setOrdering(keep);
1075
1047
  }
1076
- }, [items, shouldHandleEffects]); // set css class when group is sticky to top
1048
+ }, [items, shouldHandleEffects]);
1077
1049
 
1050
+ // set css class when group is sticky to top
1078
1051
  useStickyIntersectionObserver(groupRef, 'div.bio-properties-panel-scroll-container', setSticky);
1079
-
1080
1052
  const toggleOpen = () => setOpen(!open);
1081
-
1082
1053
  const hasItems = !!items.length;
1083
- const propertiesPanelContext = { ...useContext(LayoutContext),
1054
+ const propertiesPanelContext = {
1055
+ ...useContext(LayoutContext),
1084
1056
  onShow
1085
1057
  };
1086
1058
  return jsxs("div", {
@@ -1122,17 +1094,17 @@ function ListGroup(props) {
1122
1094
  value: propertiesPanelContext,
1123
1095
  children: ordering.map((o, index) => {
1124
1096
  const item = getItem(items, o);
1125
-
1126
1097
  if (!item) {
1127
1098
  return;
1128
1099
  }
1129
-
1130
1100
  const {
1131
1101
  id
1132
- } = item; // if item was added, open first or last item based on ordering
1102
+ } = item;
1133
1103
 
1104
+ // if item was added, open first or last item based on ordering
1134
1105
  const autoOpen = newItemAdded && (shouldSort ? index === 0 : index === ordering.length - 1);
1135
- return createElement(ListItem, { ...item,
1106
+ return createElement(ListItem, {
1107
+ ...item,
1136
1108
  autoOpen: autoOpen,
1137
1109
  element: element,
1138
1110
  index: index,
@@ -1142,20 +1114,19 @@ function ListGroup(props) {
1142
1114
  })
1143
1115
  })]
1144
1116
  });
1145
- } // helpers ////////////////////
1117
+ }
1118
+
1119
+ // helpers ////////////////////
1146
1120
 
1147
1121
  /**
1148
1122
  * Sorts given items alphanumeric by label
1149
1123
  */
1150
-
1151
1124
  function sortItems(items) {
1152
1125
  return sortBy(items, i => i.label.toLowerCase());
1153
1126
  }
1154
-
1155
1127
  function getItem(items, id) {
1156
1128
  return find(items, i => i.id === id);
1157
1129
  }
1158
-
1159
1130
  function createOrdering(items) {
1160
1131
  return items.map(i => i.id);
1161
1132
  }
@@ -1168,7 +1139,6 @@ function Description(props) {
1168
1139
  } = props;
1169
1140
  const contextDescription = useDescriptionContext(forId, element);
1170
1141
  const description = value || contextDescription;
1171
-
1172
1142
  if (description) {
1173
1143
  return jsx("div", {
1174
1144
  class: "bio-properties-panel-description",
@@ -1188,23 +1158,19 @@ function Checkbox(props) {
1188
1158
  onBlur
1189
1159
  } = props;
1190
1160
  const [localValue, setLocalValue] = useState(value);
1191
-
1192
1161
  const handleChangeCallback = ({
1193
1162
  target
1194
1163
  }) => {
1195
1164
  onChange(target.checked);
1196
1165
  };
1197
-
1198
1166
  const handleChange = e => {
1199
1167
  handleChangeCallback(e);
1200
1168
  setLocalValue(e.target.value);
1201
1169
  };
1202
-
1203
1170
  useEffect(() => {
1204
1171
  if (value === localValue) {
1205
1172
  return;
1206
1173
  }
1207
-
1208
1174
  setLocalValue(value);
1209
1175
  }, [value]);
1210
1176
  const ref = useShowEntryEvent(id);
@@ -1228,6 +1194,7 @@ function Checkbox(props) {
1228
1194
  })]
1229
1195
  });
1230
1196
  }
1197
+
1231
1198
  /**
1232
1199
  * @param {Object} props
1233
1200
  * @param {Object} props.element
@@ -1240,8 +1207,6 @@ function Checkbox(props) {
1240
1207
  * @param {Function} props.onBlur
1241
1208
  * @param {boolean} [props.disabled]
1242
1209
  */
1243
-
1244
-
1245
1210
  function CheckboxEntry(props) {
1246
1211
  const {
1247
1212
  element,
@@ -1279,7 +1244,9 @@ function CheckboxEntry(props) {
1279
1244
  }
1280
1245
  function isEdited$7(node) {
1281
1246
  return node && !!node.checked;
1282
- } // helpers /////////////////
1247
+ }
1248
+
1249
+ // helpers /////////////////
1283
1250
 
1284
1251
  function prefixId$7(id) {
1285
1252
  return `bio-properties-panel-${id}`;
@@ -1288,11 +1255,14 @@ function prefixId$7(id) {
1288
1255
  const useBufferedFocus = function (editor, ref) {
1289
1256
  const [buffer, setBuffer] = useState(undefined);
1290
1257
  ref.current = useMemo(() => ({
1291
- focus: argument => {
1258
+ focus: offset => {
1292
1259
  if (editor) {
1293
- editor.focus(argument);
1260
+ editor.focus(offset);
1294
1261
  } else {
1295
- setBuffer(argument);
1262
+ if (typeof offset === 'undefined') {
1263
+ offset = Infinity;
1264
+ }
1265
+ setBuffer(offset);
1296
1266
  }
1297
1267
  }
1298
1268
  }), [editor]);
@@ -1303,7 +1273,6 @@ const useBufferedFocus = function (editor, ref) {
1303
1273
  }
1304
1274
  }, [editor, buffer]);
1305
1275
  };
1306
-
1307
1276
  const CodeEditor = forwardRef((props, ref) => {
1308
1277
  const {
1309
1278
  value,
@@ -1311,6 +1280,7 @@ const CodeEditor = forwardRef((props, ref) => {
1311
1280
  onFeelToggle,
1312
1281
  onLint = () => {},
1313
1282
  disabled,
1283
+ tooltipContainer,
1314
1284
  variables
1315
1285
  } = props;
1316
1286
  const inputRef = useRef();
@@ -1323,30 +1293,28 @@ const CodeEditor = forwardRef((props, ref) => {
1323
1293
  });
1324
1294
  useEffect(() => {
1325
1295
  let editor;
1296
+
1326
1297
  /* Trigger FEEL toggle when
1327
1298
  *
1328
1299
  * - `backspace` is pressed
1329
1300
  * - AND the cursor is at the beginning of the input
1330
1301
  */
1331
-
1332
1302
  const onKeyDown = e => {
1333
1303
  if (e.key !== 'Backspace' || !editor) {
1334
1304
  return;
1335
1305
  }
1336
-
1337
1306
  const selection = editor.getSelection();
1338
1307
  const range = selection.ranges[selection.mainIndex];
1339
-
1340
1308
  if (range.from === 0 && range.to === 0) {
1341
1309
  onFeelToggle();
1342
1310
  }
1343
1311
  };
1344
-
1345
1312
  editor = new FeelEditor({
1346
1313
  container: inputRef.current,
1347
1314
  onChange: handleInput,
1348
1315
  onKeyDown: onKeyDown,
1349
1316
  onLint: onLint,
1317
+ tooltipContainer: tooltipContainer,
1350
1318
  value: localValue,
1351
1319
  variables: variables
1352
1320
  });
@@ -1356,24 +1324,26 @@ const CodeEditor = forwardRef((props, ref) => {
1356
1324
  inputRef.current.innerHTML = '';
1357
1325
  setEditor(null);
1358
1326
  };
1359
- }, [variables]);
1327
+ }, []);
1360
1328
  useEffect(() => {
1361
1329
  if (!editor) {
1362
1330
  return;
1363
1331
  }
1364
-
1365
1332
  if (value === localValue) {
1366
1333
  return;
1367
1334
  }
1368
-
1369
1335
  editor.setValue(value);
1370
1336
  setLocalValue(value);
1371
1337
  }, [value]);
1372
-
1338
+ useEffect(() => {
1339
+ if (!editor) {
1340
+ return;
1341
+ }
1342
+ editor.setVariables(variables);
1343
+ }, [variables]);
1373
1344
  const handleClick = () => {
1374
1345
  ref.current.focus();
1375
1346
  };
1376
-
1377
1347
  return jsx("div", {
1378
1348
  class: classnames('bio-properties-panel-feel-editor-container', disabled ? 'disabled' : null),
1379
1349
  children: jsx("div", {
@@ -1389,11 +1359,9 @@ function FeelIndicator(props) {
1389
1359
  const {
1390
1360
  active
1391
1361
  } = props;
1392
-
1393
1362
  if (!active) {
1394
1363
  return null;
1395
1364
  }
1396
-
1397
1365
  return jsx("span", {
1398
1366
  class: "bio-properties-panel-feel-indicator",
1399
1367
  children: "="
@@ -1401,13 +1369,12 @@ function FeelIndicator(props) {
1401
1369
  }
1402
1370
 
1403
1371
  const noop$1 = () => {};
1372
+
1404
1373
  /**
1405
1374
  * @param {Object} props
1406
1375
  * @param {Object} props.label
1407
1376
  * @param {String} props.feel
1408
1377
  */
1409
-
1410
-
1411
1378
  function FeelIcon(props) {
1412
1379
  const {
1413
1380
  label,
@@ -1418,15 +1385,14 @@ function FeelIcon(props) {
1418
1385
  } = props;
1419
1386
  const feelRequiredLabel = ' must be a FEEL expression';
1420
1387
  const feelOptionalLabel = ' can optionally be a FEEL expression';
1421
-
1422
1388
  const handleClick = e => {
1423
- onClick(e); // when pointer event was created from keyboard, keep focus on button
1389
+ onClick(e);
1424
1390
 
1391
+ // when pointer event was created from keyboard, keep focus on button
1425
1392
  if (!e.pointerType) {
1426
1393
  e.stopPropagation();
1427
1394
  }
1428
1395
  };
1429
-
1430
1396
  return jsx("button", {
1431
1397
  class: classnames('bio-properties-panel-feel-icon', active ? 'active' : null, feel === 'required' ? 'required' : 'optional'),
1432
1398
  onClick: handleClick,
@@ -1437,7 +1403,6 @@ function FeelIcon(props) {
1437
1403
  }
1438
1404
 
1439
1405
  const noop = () => {};
1440
-
1441
1406
  function FeelTextfield(props) {
1442
1407
  const {
1443
1408
  debounce,
@@ -1449,6 +1414,7 @@ function FeelTextfield(props) {
1449
1414
  value = '',
1450
1415
  disabled = false,
1451
1416
  variables,
1417
+ tooltipContainer,
1452
1418
  OptionalComponent = OptionalFeelInput
1453
1419
  } = props;
1454
1420
  const [localValue, _setLocalValue] = useState(value);
@@ -1457,66 +1423,54 @@ function FeelTextfield(props) {
1457
1423
  const feelActive = localValue.startsWith('=') || feel === 'required';
1458
1424
  const feelOnlyValue = localValue.startsWith('=') ? localValue.substring(1) : localValue;
1459
1425
  const [focus, _setFocus] = useState(undefined);
1460
-
1461
1426
  const setFocus = (offset = 0) => {
1462
- const hasFocus = containerRef.current.contains(document.activeElement); // Keep caret position if it is already focused, otherwise focus at the end
1427
+ const hasFocus = containerRef.current.contains(document.activeElement);
1463
1428
 
1429
+ // Keep caret position if it is already focused, otherwise focus at the end
1464
1430
  const position = hasFocus ? document.activeElement.selectionStart : Infinity;
1465
-
1466
1431
  _setFocus(position + offset);
1467
1432
  };
1468
-
1469
1433
  const handleInputCallback = useMemo(() => {
1470
1434
  return debounce(newValue => {
1471
1435
  onInput(newValue);
1472
1436
  });
1473
1437
  }, [onInput, debounce]);
1474
-
1475
1438
  const setLocalValue = newValue => {
1476
1439
  _setLocalValue(newValue);
1477
-
1478
1440
  if (!newValue || newValue === '=') {
1479
1441
  handleInputCallback(undefined);
1480
1442
  } else {
1481
1443
  handleInputCallback(newValue);
1482
1444
  }
1483
1445
  };
1484
-
1485
1446
  const handleFeelToggle = useStaticCallback(() => {
1486
1447
  if (feel === 'required') {
1487
1448
  return;
1488
1449
  }
1489
-
1490
1450
  if (!feelActive) {
1491
1451
  setLocalValue('=' + localValue);
1492
1452
  } else {
1493
1453
  setLocalValue(feelOnlyValue);
1494
1454
  }
1495
1455
  });
1496
-
1497
1456
  const handleLocalInput = newValue => {
1498
1457
  if (feelActive) {
1499
1458
  newValue = '=' + newValue;
1500
1459
  }
1501
-
1502
1460
  if (newValue === localValue) {
1503
1461
  return;
1504
1462
  }
1505
-
1506
1463
  setLocalValue(newValue);
1507
-
1508
1464
  if (!feelActive && newValue.startsWith('=')) {
1509
1465
  // focus is behind `=` sign that will be removed
1510
1466
  setFocus(-1);
1511
1467
  }
1512
1468
  };
1513
-
1514
1469
  const handleLint = useStaticCallback(lint => {
1515
1470
  if (!(lint && lint.length)) {
1516
1471
  onError(undefined);
1517
1472
  return;
1518
1473
  }
1519
-
1520
1474
  const error = lint[0];
1521
1475
  const message = `${error.source}: ${error.message}`;
1522
1476
  onError(message);
@@ -1524,40 +1478,35 @@ function FeelTextfield(props) {
1524
1478
  useEffect(() => {
1525
1479
  if (typeof focus !== 'undefined') {
1526
1480
  editorRef.current.focus(focus);
1527
-
1528
1481
  _setFocus(undefined);
1529
1482
  }
1530
1483
  }, [focus]);
1531
1484
  useEffect(() => {
1532
1485
  if (value === localValue) {
1533
1486
  return;
1534
- } // External value change removed content => keep FEEL configuration
1535
-
1487
+ }
1536
1488
 
1489
+ // External value change removed content => keep FEEL configuration
1537
1490
  if (!value) {
1538
1491
  setLocalValue(feelActive ? '=' : '');
1539
1492
  return;
1540
1493
  }
1541
-
1542
1494
  setLocalValue(value);
1543
- }, [value]); // copy-paste integration
1495
+ }, [value]);
1544
1496
 
1497
+ // copy-paste integration
1545
1498
  useEffect(() => {
1546
1499
  const copyHandler = event => {
1547
1500
  if (!feelActive) {
1548
1501
  return;
1549
1502
  }
1550
-
1551
1503
  event.clipboardData.setData('application/FEEL', event.clipboardData.getData('text'));
1552
1504
  };
1553
-
1554
1505
  const pasteHandler = event => {
1555
1506
  if (feelActive) {
1556
1507
  return;
1557
1508
  }
1558
-
1559
1509
  const data = event.clipboardData.getData('application/FEEL');
1560
-
1561
1510
  if (data) {
1562
1511
  setTimeout(() => {
1563
1512
  handleFeelToggle();
@@ -1565,7 +1514,6 @@ function FeelTextfield(props) {
1565
1514
  });
1566
1515
  }
1567
1516
  };
1568
-
1569
1517
  containerRef.current.addEventListener('copy', copyHandler);
1570
1518
  containerRef.current.addEventListener('cut', copyHandler);
1571
1519
  containerRef.current.addEventListener('paste', pasteHandler);
@@ -1606,8 +1554,10 @@ function FeelTextfield(props) {
1606
1554
  onLint: handleLint,
1607
1555
  value: feelOnlyValue,
1608
1556
  variables: variables,
1609
- ref: editorRef
1610
- }) : jsx(OptionalComponent, { ...props,
1557
+ ref: editorRef,
1558
+ tooltipContainer: tooltipContainer
1559
+ }) : jsx(OptionalComponent, {
1560
+ ...props,
1611
1561
  onInput: handleLocalInput,
1612
1562
  value: localValue,
1613
1563
  ref: editorRef
@@ -1615,7 +1565,6 @@ function FeelTextfield(props) {
1615
1565
  })]
1616
1566
  });
1617
1567
  }
1618
-
1619
1568
  const OptionalFeelInput = forwardRef((props, ref) => {
1620
1569
  const {
1621
1570
  id,
@@ -1625,24 +1574,21 @@ const OptionalFeelInput = forwardRef((props, ref) => {
1625
1574
  onFocus,
1626
1575
  onBlur
1627
1576
  } = props;
1628
- const inputRef = useRef(); // To be consistent with the FEEL editor, set focus at start of input
1629
- // this ensures clean editing experience when switching with the keyboard
1577
+ const inputRef = useRef();
1630
1578
 
1579
+ // To be consistent with the FEEL editor, set focus at start of input
1580
+ // this ensures clean editing experience when switching with the keyboard
1631
1581
  ref.current = {
1632
1582
  focus: position => {
1633
1583
  const input = inputRef.current;
1634
-
1635
1584
  if (!input) {
1636
1585
  return;
1637
1586
  }
1638
-
1639
1587
  input.focus();
1640
-
1641
1588
  if (typeof position === 'number') {
1642
1589
  if (position > value.length) {
1643
1590
  position = value.length;
1644
1591
  }
1645
-
1646
1592
  input.setSelectionRange(position, position);
1647
1593
  }
1648
1594
  }
@@ -1671,17 +1617,16 @@ const OptionalFeelTextArea = forwardRef((props, ref) => {
1671
1617
  onFocus,
1672
1618
  onBlur
1673
1619
  } = props;
1674
- const inputRef = useRef(); // To be consistent with the FEEL editor, set focus at start of input
1675
- // this ensures clean editing experience when switching with the keyboard
1620
+ const inputRef = useRef();
1676
1621
 
1622
+ // To be consistent with the FEEL editor, set focus at start of input
1623
+ // this ensures clean editing experience when switching with the keyboard
1677
1624
  ref.current = {
1678
1625
  focus: () => {
1679
1626
  const input = inputRef.current;
1680
-
1681
1627
  if (!input) {
1682
1628
  return;
1683
1629
  }
1684
-
1685
1630
  input.focus();
1686
1631
  input.setSelectionRange(0, 0);
1687
1632
  }
@@ -1701,6 +1646,7 @@ const OptionalFeelTextArea = forwardRef((props, ref) => {
1701
1646
  value: value || ''
1702
1647
  });
1703
1648
  });
1649
+
1704
1650
  /**
1705
1651
  * @param {Object} props
1706
1652
  * @param {Object} props.element
@@ -1713,7 +1659,6 @@ const OptionalFeelTextArea = forwardRef((props, ref) => {
1713
1659
  * @param {Function} props.setValue
1714
1660
  * @param {Function} props.validate
1715
1661
  */
1716
-
1717
1662
  function FeelEntry(props) {
1718
1663
  const {
1719
1664
  element,
@@ -1725,6 +1670,7 @@ function FeelEntry(props) {
1725
1670
  label,
1726
1671
  getValue,
1727
1672
  setValue,
1673
+ tooltipContainer,
1728
1674
  validate,
1729
1675
  show = noop,
1730
1676
  example,
@@ -1745,11 +1691,9 @@ function FeelEntry(props) {
1745
1691
  }, [value]);
1746
1692
  const onInput = useStaticCallback(newValue => {
1747
1693
  let newValidationError = null;
1748
-
1749
1694
  if (isFunction(validate)) {
1750
1695
  newValidationError = validate(newValue) || null;
1751
1696
  }
1752
-
1753
1697
  if (newValidationError) {
1754
1698
  setCachedInvalidValue(newValue);
1755
1699
  } else {
@@ -1758,17 +1702,14 @@ function FeelEntry(props) {
1758
1702
  setValue(newValue);
1759
1703
  }
1760
1704
  }
1761
-
1762
1705
  setValidationError(newValidationError);
1763
1706
  });
1764
1707
  const onError = useCallback(err => {
1765
1708
  setLocalError(err);
1766
1709
  }, []);
1767
-
1768
1710
  if (previousValue === value && validationError) {
1769
1711
  value = cachedInvalidValue;
1770
1712
  }
1771
-
1772
1713
  const temporaryError = useError(id);
1773
1714
  const error = localError || temporaryError || validationError;
1774
1715
  return jsxs("div", {
@@ -1788,6 +1729,7 @@ function FeelEntry(props) {
1788
1729
  show: show,
1789
1730
  value: value,
1790
1731
  variables: variables,
1732
+ tooltipContainer: tooltipContainer,
1791
1733
  OptionalComponent: props.OptionalComponent
1792
1734
  }, element), error && jsx("div", {
1793
1735
  class: "bio-properties-panel-error",
@@ -1799,6 +1741,7 @@ function FeelEntry(props) {
1799
1741
  })]
1800
1742
  });
1801
1743
  }
1744
+
1802
1745
  /**
1803
1746
  * @param {Object} props
1804
1747
  * @param {Object} props.element
@@ -1813,7 +1756,6 @@ function FeelEntry(props) {
1813
1756
  * @param {Function} props.onBlur
1814
1757
  * @param {Function} props.validate
1815
1758
  */
1816
-
1817
1759
  function FeelTextArea(props) {
1818
1760
  return jsx(FeelEntry, {
1819
1761
  class: "bio-properties-panel-feel-textarea",
@@ -1823,7 +1765,9 @@ function FeelTextArea(props) {
1823
1765
  }
1824
1766
  function isEdited$6(node) {
1825
1767
  return node && (!!node.value || node.classList.contains('edited'));
1826
- } // helpers /////////////////
1768
+ }
1769
+
1770
+ // helpers /////////////////
1827
1771
 
1828
1772
  function prefixId$6(id) {
1829
1773
  return `bio-properties-panel-${id}`;
@@ -1845,9 +1789,7 @@ function List(props) {
1845
1789
  } = props;
1846
1790
  const [open, setOpen] = useState(!!shouldOpen);
1847
1791
  const hasItems = !!items.length;
1848
-
1849
1792
  const toggleOpen = () => hasItems && setOpen(!open);
1850
-
1851
1793
  const opening = !usePrevious(open) && open;
1852
1794
  const elementChanged = usePrevious(element) !== element;
1853
1795
  const shouldReset = opening || elementChanged;
@@ -1858,19 +1800,17 @@ function List(props) {
1858
1800
  setOpen(false);
1859
1801
  }
1860
1802
  }, [open, hasItems]);
1803
+
1861
1804
  /**
1862
1805
  * @param {MouseEvent} event
1863
1806
  */
1864
-
1865
1807
  function addItem(event) {
1866
1808
  event.stopPropagation();
1867
1809
  onAdd();
1868
-
1869
1810
  if (!open) {
1870
1811
  setOpen(true);
1871
1812
  }
1872
1813
  }
1873
-
1874
1814
  return jsxs("div", {
1875
1815
  "data-entry-id": id,
1876
1816
  class: classnames('bio-properties-panel-entry', 'bio-properties-panel-list-entry', hasItems ? '' : 'empty', open ? 'open' : ''),
@@ -1903,7 +1843,8 @@ function List(props) {
1903
1843
  })
1904
1844
  })]
1905
1845
  })]
1906
- }), hasItems && jsx(ItemsList, { ...restProps,
1846
+ }), hasItems && jsx(ItemsList, {
1847
+ ...restProps,
1907
1848
  autoFocusEntry: autoFocusEntry,
1908
1849
  component: component,
1909
1850
  element: element,
@@ -1915,7 +1856,6 @@ function List(props) {
1915
1856
  })]
1916
1857
  });
1917
1858
  }
1918
-
1919
1859
  function ItemsList(props) {
1920
1860
  const {
1921
1861
  autoFocusEntry,
@@ -1933,11 +1873,13 @@ function ItemsList(props) {
1933
1873
  useEffect(() => {
1934
1874
  if (newItem && autoFocusEntry) {
1935
1875
  // (0) select the parent entry (containing all list items)
1936
- const entry = query(`[data-entry-id="${id}"]`); // (1) select the first input or a custom element to be focussed
1876
+ const entry = query(`[data-entry-id="${id}"]`);
1937
1877
 
1878
+ // (1) select the first input or a custom element to be focussed
1938
1879
  const selector = typeof autoFocusEntry === 'boolean' ? '.bio-properties-panel-input' : autoFocusEntry;
1939
- const focusableInput = query(selector, entry); // (2) set focus
1880
+ const focusableInput = query(selector, entry);
1940
1881
 
1882
+ // (2) set focus
1941
1883
  if (focusableInput) {
1942
1884
  if (isFunction(focusableInput.select)) {
1943
1885
  focusableInput.select();
@@ -1953,7 +1895,8 @@ function ItemsList(props) {
1953
1895
  const key = getKey(item);
1954
1896
  return jsxs("li", {
1955
1897
  class: "bio-properties-panel-list-entry-item",
1956
- children: [jsx(Component, { ...restProps,
1898
+ children: [jsx(Component, {
1899
+ ...restProps,
1957
1900
  element: element,
1958
1901
  id: id,
1959
1902
  index: index,
@@ -1970,6 +1913,7 @@ function ItemsList(props) {
1970
1913
  })
1971
1914
  });
1972
1915
  }
1916
+
1973
1917
  /**
1974
1918
  * Place new items in the beginning of the list and sort the rest with provided function.
1975
1919
  *
@@ -1979,41 +1923,36 @@ function ItemsList(props) {
1979
1923
  * @param {boolean} [shouldReset=false] set to `true` to reset state of the hook
1980
1924
  * @returns {Item[]}
1981
1925
  */
1982
-
1983
-
1984
1926
  function useSortedItems(currentItems, compareFn, shouldReset = false) {
1985
- const itemsRef = useRef(currentItems.slice()); // (1) Reset and optionally sort.
1927
+ const itemsRef = useRef(currentItems.slice());
1986
1928
 
1929
+ // (1) Reset and optionally sort.
1987
1930
  if (shouldReset) {
1988
1931
  itemsRef.current = currentItems.slice();
1989
-
1990
1932
  if (compareFn) {
1991
1933
  itemsRef.current.sort(compareFn);
1992
1934
  }
1993
1935
  } else {
1994
- const items = itemsRef.current; // (2) Add new item to the list.
1936
+ const items = itemsRef.current;
1995
1937
 
1938
+ // (2) Add new item to the list.
1996
1939
  for (const item of currentItems) {
1997
1940
  if (!items.includes(item)) {
1998
1941
  // Unshift or push depending on whether we have a compareFn
1999
1942
  compareFn ? items.unshift(item) : items.push(item);
2000
1943
  }
2001
- } // (3) Filter out removed items.
2002
-
1944
+ }
2003
1945
 
1946
+ // (3) Filter out removed items.
2004
1947
  itemsRef.current = items.filter(item => currentItems.includes(item));
2005
1948
  }
2006
-
2007
1949
  return itemsRef.current;
2008
1950
  }
2009
-
2010
1951
  function useNewItems(items = [], shouldReset) {
2011
1952
  const previousItems = usePrevious(items.slice()) || [];
2012
-
2013
1953
  if (shouldReset) {
2014
1954
  return [];
2015
1955
  }
2016
-
2017
1956
  return previousItems ? items.filter(item => !previousItems.includes(item)) : [];
2018
1957
  }
2019
1958
 
@@ -2038,23 +1977,19 @@ function NumberField(props) {
2038
1977
  validity,
2039
1978
  value
2040
1979
  } = event.target;
2041
-
2042
1980
  if (validity.valid) {
2043
1981
  onInput(value ? parseFloat(value) : undefined);
2044
1982
  }
2045
1983
  });
2046
1984
  }, [onInput, debounce]);
2047
-
2048
1985
  const handleInput = e => {
2049
1986
  handleInputCallback(e);
2050
1987
  setLocalValue(e.target.value);
2051
1988
  };
2052
-
2053
1989
  useEffect(() => {
2054
1990
  if (value === localValue) {
2055
1991
  return;
2056
1992
  }
2057
-
2058
1993
  setLocalValue(value);
2059
1994
  }, [value]);
2060
1995
  return jsxs("div", {
@@ -2081,6 +2016,7 @@ function NumberField(props) {
2081
2016
  })]
2082
2017
  });
2083
2018
  }
2019
+
2084
2020
  /**
2085
2021
  * @param {Object} props
2086
2022
  * @param {Boolean} props.debounce
@@ -2097,8 +2033,6 @@ function NumberField(props) {
2097
2033
  * @param {Function} props.onBlur
2098
2034
  * @param {String} props.step
2099
2035
  */
2100
-
2101
-
2102
2036
  function NumberFieldEntry(props) {
2103
2037
  const {
2104
2038
  debounce,
@@ -2140,7 +2074,9 @@ function NumberFieldEntry(props) {
2140
2074
  }
2141
2075
  function isEdited$5(node) {
2142
2076
  return node && !!node.value;
2143
- } // helpers /////////////////
2077
+ }
2078
+
2079
+ // helpers /////////////////
2144
2080
 
2145
2081
  function prefixId$5(id) {
2146
2082
  return `bio-properties-panel-${id}`;
@@ -2159,23 +2095,19 @@ function Select(props) {
2159
2095
  } = props;
2160
2096
  const ref = useShowEntryEvent(id);
2161
2097
  const [localValue, setLocalValue] = useState(value);
2162
-
2163
2098
  const handleChangeCallback = ({
2164
2099
  target
2165
2100
  }) => {
2166
2101
  onChange(target.value);
2167
2102
  };
2168
-
2169
2103
  const handleChange = e => {
2170
2104
  handleChangeCallback(e);
2171
2105
  setLocalValue(e.target.value);
2172
2106
  };
2173
-
2174
2107
  useEffect(() => {
2175
2108
  if (value === localValue) {
2176
2109
  return;
2177
2110
  }
2178
-
2179
2111
  setLocalValue(value);
2180
2112
  }, [value]);
2181
2113
  return jsxs("div", {
@@ -2204,6 +2136,7 @@ function Select(props) {
2204
2136
  })]
2205
2137
  });
2206
2138
  }
2139
+
2207
2140
  /**
2208
2141
  * @param {object} props
2209
2142
  * @param {object} props.element
@@ -2217,8 +2150,6 @@ function Select(props) {
2217
2150
  * @param {Function} props.getOptions
2218
2151
  * @param {boolean} [props.disabled]
2219
2152
  */
2220
-
2221
-
2222
2153
  function SelectEntry(props) {
2223
2154
  const {
2224
2155
  element,
@@ -2259,7 +2190,9 @@ function SelectEntry(props) {
2259
2190
  }
2260
2191
  function isEdited$4(node) {
2261
2192
  return node && !!node.value;
2262
- } // helpers /////////////////
2193
+ }
2194
+
2195
+ // helpers /////////////////
2263
2196
 
2264
2197
  function prefixId$4(id) {
2265
2198
  return `bio-properties-panel-${id}`;
@@ -2283,17 +2216,14 @@ function Simple(props) {
2283
2216
  target
2284
2217
  }) => setValue(target.value.length ? target.value : undefined));
2285
2218
  }, [setValue, debounce]);
2286
-
2287
2219
  const handleInput = e => {
2288
2220
  handleInputCallback(e);
2289
2221
  setLocalValue(e.target.value);
2290
2222
  };
2291
-
2292
2223
  useEffect(() => {
2293
2224
  if (value === localValue) {
2294
2225
  return;
2295
2226
  }
2296
-
2297
2227
  setLocalValue(value);
2298
2228
  }, [value]);
2299
2229
  return jsx("div", {
@@ -2316,7 +2246,9 @@ function Simple(props) {
2316
2246
  }
2317
2247
  function isEdited$3(node) {
2318
2248
  return node && !!node.value;
2319
- } // helpers /////////////////
2249
+ }
2250
+
2251
+ // helpers /////////////////
2320
2252
 
2321
2253
  function prefixId$3(id) {
2322
2254
  return `bio-properties-panel-${id}`;
@@ -2342,17 +2274,14 @@ function TextArea(props) {
2342
2274
  target
2343
2275
  }) => onInput(target.value.length ? target.value : undefined));
2344
2276
  }, [onInput, debounce]);
2345
-
2346
2277
  const handleInput = e => {
2347
2278
  handleInputCallback(e);
2348
2279
  setLocalValue(e.target.value);
2349
2280
  };
2350
-
2351
2281
  useEffect(() => {
2352
2282
  if (value === localValue) {
2353
2283
  return;
2354
2284
  }
2355
-
2356
2285
  setLocalValue(value);
2357
2286
  }, [value]);
2358
2287
  return jsxs("div", {
@@ -2376,6 +2305,7 @@ function TextArea(props) {
2376
2305
  })]
2377
2306
  });
2378
2307
  }
2308
+
2379
2309
  /**
2380
2310
  * @param {object} props
2381
2311
  * @param {object} props.element
@@ -2391,8 +2321,6 @@ function TextArea(props) {
2391
2321
  * @param {boolean} props.monospace
2392
2322
  * @param {boolean} [props.disabled]
2393
2323
  */
2394
-
2395
-
2396
2324
  function TextAreaEntry(props) {
2397
2325
  const {
2398
2326
  element,
@@ -2436,7 +2364,9 @@ function TextAreaEntry(props) {
2436
2364
  }
2437
2365
  function isEdited$2(node) {
2438
2366
  return node && !!node.value;
2439
- } // helpers /////////////////
2367
+ }
2368
+
2369
+ // helpers /////////////////
2440
2370
 
2441
2371
  function prefixId$2(id) {
2442
2372
  return `bio-properties-panel-${id}`;
@@ -2460,17 +2390,14 @@ function Textfield(props) {
2460
2390
  target
2461
2391
  }) => onInput(target.value.length ? target.value : undefined));
2462
2392
  }, [onInput, debounce]);
2463
-
2464
2393
  const handleInput = e => {
2465
2394
  handleInputCallback(e);
2466
2395
  setLocalValue(e.target.value);
2467
2396
  };
2468
-
2469
2397
  useEffect(() => {
2470
2398
  if (value === localValue) {
2471
2399
  return;
2472
2400
  }
2473
-
2474
2401
  setLocalValue(value);
2475
2402
  }, [value]);
2476
2403
  return jsxs("div", {
@@ -2495,6 +2422,7 @@ function Textfield(props) {
2495
2422
  })]
2496
2423
  });
2497
2424
  }
2425
+
2498
2426
  /**
2499
2427
  * @param {Object} props
2500
2428
  * @param {Object} props.element
@@ -2509,8 +2437,6 @@ function Textfield(props) {
2509
2437
  * @param {Function} props.onBlur
2510
2438
  * @param {Function} props.validate
2511
2439
  */
2512
-
2513
-
2514
2440
  function TextfieldEntry(props) {
2515
2441
  const {
2516
2442
  element,
@@ -2536,27 +2462,21 @@ function TextfieldEntry(props) {
2536
2462
  setLocalError(newValidationError);
2537
2463
  }
2538
2464
  }, [value]);
2539
-
2540
2465
  const onInput = newValue => {
2541
2466
  let newValidationError = null;
2542
-
2543
2467
  if (isFunction(validate)) {
2544
2468
  newValidationError = validate(newValue) || null;
2545
2469
  }
2546
-
2547
2470
  if (newValidationError) {
2548
2471
  setCachedInvalidValue(newValue);
2549
2472
  } else {
2550
2473
  setValue(newValue);
2551
2474
  }
2552
-
2553
2475
  setLocalError(newValidationError);
2554
2476
  };
2555
-
2556
2477
  if (previousValue === value && localError) {
2557
2478
  value = cachedInvalidValue;
2558
2479
  }
2559
-
2560
2480
  const error = globalError || localError;
2561
2481
  return jsxs("div", {
2562
2482
  class: classnames('bio-properties-panel-entry', error ? 'has-error' : ''),
@@ -2582,7 +2502,9 @@ function TextfieldEntry(props) {
2582
2502
  }
2583
2503
  function isEdited$1(node) {
2584
2504
  return node && !!node.value;
2585
- } // helpers /////////////////
2505
+ }
2506
+
2507
+ // helpers /////////////////
2586
2508
 
2587
2509
  function prefixId$1(id) {
2588
2510
  return `bio-properties-panel-${id}`;
@@ -2599,21 +2521,17 @@ function ToggleSwitch(props) {
2599
2521
  onBlur
2600
2522
  } = props;
2601
2523
  const [localValue, setLocalValue] = useState(value);
2602
-
2603
2524
  const handleInputCallback = async () => {
2604
2525
  onInput(!value);
2605
2526
  };
2606
-
2607
2527
  const handleInput = e => {
2608
2528
  handleInputCallback();
2609
2529
  setLocalValue(e.target.value);
2610
2530
  };
2611
-
2612
2531
  useEffect(() => {
2613
2532
  if (value === localValue) {
2614
2533
  return;
2615
2534
  }
2616
-
2617
2535
  setLocalValue(value);
2618
2536
  }, [value]);
2619
2537
  return jsxs("div", {
@@ -2645,6 +2563,7 @@ function ToggleSwitch(props) {
2645
2563
  })]
2646
2564
  });
2647
2565
  }
2566
+
2648
2567
  /**
2649
2568
  * @param {Object} props
2650
2569
  * @param {Object} props.element
@@ -2657,8 +2576,6 @@ function ToggleSwitch(props) {
2657
2576
  * @param {Function} props.onFocus
2658
2577
  * @param {Function} props.onBlur
2659
2578
  */
2660
-
2661
-
2662
2579
  function ToggleSwitchEntry(props) {
2663
2580
  const {
2664
2581
  element,
@@ -2692,7 +2609,9 @@ function ToggleSwitchEntry(props) {
2692
2609
  }
2693
2610
  function isEdited(node) {
2694
2611
  return node && !!node.checked;
2695
- } // helpers /////////////////
2612
+ }
2613
+
2614
+ // helpers /////////////////
2696
2615
 
2697
2616
  function prefixId(id) {
2698
2617
  return `bio-properties-panel-${id}`;