@bpmn-io/properties-panel 0.24.0 → 0.24.1

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,
@@ -1323,25 +1292,22 @@ const CodeEditor = forwardRef((props, ref) => {
1323
1292
  });
1324
1293
  useEffect(() => {
1325
1294
  let editor;
1295
+
1326
1296
  /* Trigger FEEL toggle when
1327
1297
  *
1328
1298
  * - `backspace` is pressed
1329
1299
  * - AND the cursor is at the beginning of the input
1330
1300
  */
1331
-
1332
1301
  const onKeyDown = e => {
1333
1302
  if (e.key !== 'Backspace' || !editor) {
1334
1303
  return;
1335
1304
  }
1336
-
1337
1305
  const selection = editor.getSelection();
1338
1306
  const range = selection.ranges[selection.mainIndex];
1339
-
1340
1307
  if (range.from === 0 && range.to === 0) {
1341
1308
  onFeelToggle();
1342
1309
  }
1343
1310
  };
1344
-
1345
1311
  editor = new FeelEditor({
1346
1312
  container: inputRef.current,
1347
1313
  onChange: handleInput,
@@ -1356,24 +1322,26 @@ const CodeEditor = forwardRef((props, ref) => {
1356
1322
  inputRef.current.innerHTML = '';
1357
1323
  setEditor(null);
1358
1324
  };
1359
- }, [variables]);
1325
+ }, []);
1360
1326
  useEffect(() => {
1361
1327
  if (!editor) {
1362
1328
  return;
1363
1329
  }
1364
-
1365
1330
  if (value === localValue) {
1366
1331
  return;
1367
1332
  }
1368
-
1369
1333
  editor.setValue(value);
1370
1334
  setLocalValue(value);
1371
1335
  }, [value]);
1372
-
1336
+ useEffect(() => {
1337
+ if (!editor) {
1338
+ return;
1339
+ }
1340
+ editor.setVariables(variables);
1341
+ }, [variables]);
1373
1342
  const handleClick = () => {
1374
1343
  ref.current.focus();
1375
1344
  };
1376
-
1377
1345
  return jsx("div", {
1378
1346
  class: classnames('bio-properties-panel-feel-editor-container', disabled ? 'disabled' : null),
1379
1347
  children: jsx("div", {
@@ -1389,11 +1357,9 @@ function FeelIndicator(props) {
1389
1357
  const {
1390
1358
  active
1391
1359
  } = props;
1392
-
1393
1360
  if (!active) {
1394
1361
  return null;
1395
1362
  }
1396
-
1397
1363
  return jsx("span", {
1398
1364
  class: "bio-properties-panel-feel-indicator",
1399
1365
  children: "="
@@ -1401,13 +1367,12 @@ function FeelIndicator(props) {
1401
1367
  }
1402
1368
 
1403
1369
  const noop$1 = () => {};
1370
+
1404
1371
  /**
1405
1372
  * @param {Object} props
1406
1373
  * @param {Object} props.label
1407
1374
  * @param {String} props.feel
1408
1375
  */
1409
-
1410
-
1411
1376
  function FeelIcon(props) {
1412
1377
  const {
1413
1378
  label,
@@ -1418,15 +1383,14 @@ function FeelIcon(props) {
1418
1383
  } = props;
1419
1384
  const feelRequiredLabel = ' must be a FEEL expression';
1420
1385
  const feelOptionalLabel = ' can optionally be a FEEL expression';
1421
-
1422
1386
  const handleClick = e => {
1423
- onClick(e); // when pointer event was created from keyboard, keep focus on button
1387
+ onClick(e);
1424
1388
 
1389
+ // when pointer event was created from keyboard, keep focus on button
1425
1390
  if (!e.pointerType) {
1426
1391
  e.stopPropagation();
1427
1392
  }
1428
1393
  };
1429
-
1430
1394
  return jsx("button", {
1431
1395
  class: classnames('bio-properties-panel-feel-icon', active ? 'active' : null, feel === 'required' ? 'required' : 'optional'),
1432
1396
  onClick: handleClick,
@@ -1437,7 +1401,6 @@ function FeelIcon(props) {
1437
1401
  }
1438
1402
 
1439
1403
  const noop = () => {};
1440
-
1441
1404
  function FeelTextfield(props) {
1442
1405
  const {
1443
1406
  debounce,
@@ -1457,66 +1420,54 @@ function FeelTextfield(props) {
1457
1420
  const feelActive = localValue.startsWith('=') || feel === 'required';
1458
1421
  const feelOnlyValue = localValue.startsWith('=') ? localValue.substring(1) : localValue;
1459
1422
  const [focus, _setFocus] = useState(undefined);
1460
-
1461
1423
  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
1424
+ const hasFocus = containerRef.current.contains(document.activeElement);
1463
1425
 
1426
+ // Keep caret position if it is already focused, otherwise focus at the end
1464
1427
  const position = hasFocus ? document.activeElement.selectionStart : Infinity;
1465
-
1466
1428
  _setFocus(position + offset);
1467
1429
  };
1468
-
1469
1430
  const handleInputCallback = useMemo(() => {
1470
1431
  return debounce(newValue => {
1471
1432
  onInput(newValue);
1472
1433
  });
1473
1434
  }, [onInput, debounce]);
1474
-
1475
1435
  const setLocalValue = newValue => {
1476
1436
  _setLocalValue(newValue);
1477
-
1478
1437
  if (!newValue || newValue === '=') {
1479
1438
  handleInputCallback(undefined);
1480
1439
  } else {
1481
1440
  handleInputCallback(newValue);
1482
1441
  }
1483
1442
  };
1484
-
1485
1443
  const handleFeelToggle = useStaticCallback(() => {
1486
1444
  if (feel === 'required') {
1487
1445
  return;
1488
1446
  }
1489
-
1490
1447
  if (!feelActive) {
1491
1448
  setLocalValue('=' + localValue);
1492
1449
  } else {
1493
1450
  setLocalValue(feelOnlyValue);
1494
1451
  }
1495
1452
  });
1496
-
1497
1453
  const handleLocalInput = newValue => {
1498
1454
  if (feelActive) {
1499
1455
  newValue = '=' + newValue;
1500
1456
  }
1501
-
1502
1457
  if (newValue === localValue) {
1503
1458
  return;
1504
1459
  }
1505
-
1506
1460
  setLocalValue(newValue);
1507
-
1508
1461
  if (!feelActive && newValue.startsWith('=')) {
1509
1462
  // focus is behind `=` sign that will be removed
1510
1463
  setFocus(-1);
1511
1464
  }
1512
1465
  };
1513
-
1514
1466
  const handleLint = useStaticCallback(lint => {
1515
1467
  if (!(lint && lint.length)) {
1516
1468
  onError(undefined);
1517
1469
  return;
1518
1470
  }
1519
-
1520
1471
  const error = lint[0];
1521
1472
  const message = `${error.source}: ${error.message}`;
1522
1473
  onError(message);
@@ -1524,40 +1475,35 @@ function FeelTextfield(props) {
1524
1475
  useEffect(() => {
1525
1476
  if (typeof focus !== 'undefined') {
1526
1477
  editorRef.current.focus(focus);
1527
-
1528
1478
  _setFocus(undefined);
1529
1479
  }
1530
1480
  }, [focus]);
1531
1481
  useEffect(() => {
1532
1482
  if (value === localValue) {
1533
1483
  return;
1534
- } // External value change removed content => keep FEEL configuration
1535
-
1484
+ }
1536
1485
 
1486
+ // External value change removed content => keep FEEL configuration
1537
1487
  if (!value) {
1538
1488
  setLocalValue(feelActive ? '=' : '');
1539
1489
  return;
1540
1490
  }
1541
-
1542
1491
  setLocalValue(value);
1543
- }, [value]); // copy-paste integration
1492
+ }, [value]);
1544
1493
 
1494
+ // copy-paste integration
1545
1495
  useEffect(() => {
1546
1496
  const copyHandler = event => {
1547
1497
  if (!feelActive) {
1548
1498
  return;
1549
1499
  }
1550
-
1551
1500
  event.clipboardData.setData('application/FEEL', event.clipboardData.getData('text'));
1552
1501
  };
1553
-
1554
1502
  const pasteHandler = event => {
1555
1503
  if (feelActive) {
1556
1504
  return;
1557
1505
  }
1558
-
1559
1506
  const data = event.clipboardData.getData('application/FEEL');
1560
-
1561
1507
  if (data) {
1562
1508
  setTimeout(() => {
1563
1509
  handleFeelToggle();
@@ -1565,7 +1511,6 @@ function FeelTextfield(props) {
1565
1511
  });
1566
1512
  }
1567
1513
  };
1568
-
1569
1514
  containerRef.current.addEventListener('copy', copyHandler);
1570
1515
  containerRef.current.addEventListener('cut', copyHandler);
1571
1516
  containerRef.current.addEventListener('paste', pasteHandler);
@@ -1607,7 +1552,8 @@ function FeelTextfield(props) {
1607
1552
  value: feelOnlyValue,
1608
1553
  variables: variables,
1609
1554
  ref: editorRef
1610
- }) : jsx(OptionalComponent, { ...props,
1555
+ }) : jsx(OptionalComponent, {
1556
+ ...props,
1611
1557
  onInput: handleLocalInput,
1612
1558
  value: localValue,
1613
1559
  ref: editorRef
@@ -1615,7 +1561,6 @@ function FeelTextfield(props) {
1615
1561
  })]
1616
1562
  });
1617
1563
  }
1618
-
1619
1564
  const OptionalFeelInput = forwardRef((props, ref) => {
1620
1565
  const {
1621
1566
  id,
@@ -1625,24 +1570,21 @@ const OptionalFeelInput = forwardRef((props, ref) => {
1625
1570
  onFocus,
1626
1571
  onBlur
1627
1572
  } = 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
1573
+ const inputRef = useRef();
1630
1574
 
1575
+ // To be consistent with the FEEL editor, set focus at start of input
1576
+ // this ensures clean editing experience when switching with the keyboard
1631
1577
  ref.current = {
1632
1578
  focus: position => {
1633
1579
  const input = inputRef.current;
1634
-
1635
1580
  if (!input) {
1636
1581
  return;
1637
1582
  }
1638
-
1639
1583
  input.focus();
1640
-
1641
1584
  if (typeof position === 'number') {
1642
1585
  if (position > value.length) {
1643
1586
  position = value.length;
1644
1587
  }
1645
-
1646
1588
  input.setSelectionRange(position, position);
1647
1589
  }
1648
1590
  }
@@ -1671,17 +1613,16 @@ const OptionalFeelTextArea = forwardRef((props, ref) => {
1671
1613
  onFocus,
1672
1614
  onBlur
1673
1615
  } = 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
1616
+ const inputRef = useRef();
1676
1617
 
1618
+ // To be consistent with the FEEL editor, set focus at start of input
1619
+ // this ensures clean editing experience when switching with the keyboard
1677
1620
  ref.current = {
1678
1621
  focus: () => {
1679
1622
  const input = inputRef.current;
1680
-
1681
1623
  if (!input) {
1682
1624
  return;
1683
1625
  }
1684
-
1685
1626
  input.focus();
1686
1627
  input.setSelectionRange(0, 0);
1687
1628
  }
@@ -1701,6 +1642,7 @@ const OptionalFeelTextArea = forwardRef((props, ref) => {
1701
1642
  value: value || ''
1702
1643
  });
1703
1644
  });
1645
+
1704
1646
  /**
1705
1647
  * @param {Object} props
1706
1648
  * @param {Object} props.element
@@ -1713,7 +1655,6 @@ const OptionalFeelTextArea = forwardRef((props, ref) => {
1713
1655
  * @param {Function} props.setValue
1714
1656
  * @param {Function} props.validate
1715
1657
  */
1716
-
1717
1658
  function FeelEntry(props) {
1718
1659
  const {
1719
1660
  element,
@@ -1745,11 +1686,9 @@ function FeelEntry(props) {
1745
1686
  }, [value]);
1746
1687
  const onInput = useStaticCallback(newValue => {
1747
1688
  let newValidationError = null;
1748
-
1749
1689
  if (isFunction(validate)) {
1750
1690
  newValidationError = validate(newValue) || null;
1751
1691
  }
1752
-
1753
1692
  if (newValidationError) {
1754
1693
  setCachedInvalidValue(newValue);
1755
1694
  } else {
@@ -1758,17 +1697,14 @@ function FeelEntry(props) {
1758
1697
  setValue(newValue);
1759
1698
  }
1760
1699
  }
1761
-
1762
1700
  setValidationError(newValidationError);
1763
1701
  });
1764
1702
  const onError = useCallback(err => {
1765
1703
  setLocalError(err);
1766
1704
  }, []);
1767
-
1768
1705
  if (previousValue === value && validationError) {
1769
1706
  value = cachedInvalidValue;
1770
1707
  }
1771
-
1772
1708
  const temporaryError = useError(id);
1773
1709
  const error = localError || temporaryError || validationError;
1774
1710
  return jsxs("div", {
@@ -1799,6 +1735,7 @@ function FeelEntry(props) {
1799
1735
  })]
1800
1736
  });
1801
1737
  }
1738
+
1802
1739
  /**
1803
1740
  * @param {Object} props
1804
1741
  * @param {Object} props.element
@@ -1813,7 +1750,6 @@ function FeelEntry(props) {
1813
1750
  * @param {Function} props.onBlur
1814
1751
  * @param {Function} props.validate
1815
1752
  */
1816
-
1817
1753
  function FeelTextArea(props) {
1818
1754
  return jsx(FeelEntry, {
1819
1755
  class: "bio-properties-panel-feel-textarea",
@@ -1823,7 +1759,9 @@ function FeelTextArea(props) {
1823
1759
  }
1824
1760
  function isEdited$6(node) {
1825
1761
  return node && (!!node.value || node.classList.contains('edited'));
1826
- } // helpers /////////////////
1762
+ }
1763
+
1764
+ // helpers /////////////////
1827
1765
 
1828
1766
  function prefixId$6(id) {
1829
1767
  return `bio-properties-panel-${id}`;
@@ -1845,9 +1783,7 @@ function List(props) {
1845
1783
  } = props;
1846
1784
  const [open, setOpen] = useState(!!shouldOpen);
1847
1785
  const hasItems = !!items.length;
1848
-
1849
1786
  const toggleOpen = () => hasItems && setOpen(!open);
1850
-
1851
1787
  const opening = !usePrevious(open) && open;
1852
1788
  const elementChanged = usePrevious(element) !== element;
1853
1789
  const shouldReset = opening || elementChanged;
@@ -1858,19 +1794,17 @@ function List(props) {
1858
1794
  setOpen(false);
1859
1795
  }
1860
1796
  }, [open, hasItems]);
1797
+
1861
1798
  /**
1862
1799
  * @param {MouseEvent} event
1863
1800
  */
1864
-
1865
1801
  function addItem(event) {
1866
1802
  event.stopPropagation();
1867
1803
  onAdd();
1868
-
1869
1804
  if (!open) {
1870
1805
  setOpen(true);
1871
1806
  }
1872
1807
  }
1873
-
1874
1808
  return jsxs("div", {
1875
1809
  "data-entry-id": id,
1876
1810
  class: classnames('bio-properties-panel-entry', 'bio-properties-panel-list-entry', hasItems ? '' : 'empty', open ? 'open' : ''),
@@ -1903,7 +1837,8 @@ function List(props) {
1903
1837
  })
1904
1838
  })]
1905
1839
  })]
1906
- }), hasItems && jsx(ItemsList, { ...restProps,
1840
+ }), hasItems && jsx(ItemsList, {
1841
+ ...restProps,
1907
1842
  autoFocusEntry: autoFocusEntry,
1908
1843
  component: component,
1909
1844
  element: element,
@@ -1915,7 +1850,6 @@ function List(props) {
1915
1850
  })]
1916
1851
  });
1917
1852
  }
1918
-
1919
1853
  function ItemsList(props) {
1920
1854
  const {
1921
1855
  autoFocusEntry,
@@ -1933,11 +1867,13 @@ function ItemsList(props) {
1933
1867
  useEffect(() => {
1934
1868
  if (newItem && autoFocusEntry) {
1935
1869
  // (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
1870
+ const entry = query(`[data-entry-id="${id}"]`);
1937
1871
 
1872
+ // (1) select the first input or a custom element to be focussed
1938
1873
  const selector = typeof autoFocusEntry === 'boolean' ? '.bio-properties-panel-input' : autoFocusEntry;
1939
- const focusableInput = query(selector, entry); // (2) set focus
1874
+ const focusableInput = query(selector, entry);
1940
1875
 
1876
+ // (2) set focus
1941
1877
  if (focusableInput) {
1942
1878
  if (isFunction(focusableInput.select)) {
1943
1879
  focusableInput.select();
@@ -1953,7 +1889,8 @@ function ItemsList(props) {
1953
1889
  const key = getKey(item);
1954
1890
  return jsxs("li", {
1955
1891
  class: "bio-properties-panel-list-entry-item",
1956
- children: [jsx(Component, { ...restProps,
1892
+ children: [jsx(Component, {
1893
+ ...restProps,
1957
1894
  element: element,
1958
1895
  id: id,
1959
1896
  index: index,
@@ -1970,6 +1907,7 @@ function ItemsList(props) {
1970
1907
  })
1971
1908
  });
1972
1909
  }
1910
+
1973
1911
  /**
1974
1912
  * Place new items in the beginning of the list and sort the rest with provided function.
1975
1913
  *
@@ -1979,41 +1917,36 @@ function ItemsList(props) {
1979
1917
  * @param {boolean} [shouldReset=false] set to `true` to reset state of the hook
1980
1918
  * @returns {Item[]}
1981
1919
  */
1982
-
1983
-
1984
1920
  function useSortedItems(currentItems, compareFn, shouldReset = false) {
1985
- const itemsRef = useRef(currentItems.slice()); // (1) Reset and optionally sort.
1921
+ const itemsRef = useRef(currentItems.slice());
1986
1922
 
1923
+ // (1) Reset and optionally sort.
1987
1924
  if (shouldReset) {
1988
1925
  itemsRef.current = currentItems.slice();
1989
-
1990
1926
  if (compareFn) {
1991
1927
  itemsRef.current.sort(compareFn);
1992
1928
  }
1993
1929
  } else {
1994
- const items = itemsRef.current; // (2) Add new item to the list.
1930
+ const items = itemsRef.current;
1995
1931
 
1932
+ // (2) Add new item to the list.
1996
1933
  for (const item of currentItems) {
1997
1934
  if (!items.includes(item)) {
1998
1935
  // Unshift or push depending on whether we have a compareFn
1999
1936
  compareFn ? items.unshift(item) : items.push(item);
2000
1937
  }
2001
- } // (3) Filter out removed items.
2002
-
1938
+ }
2003
1939
 
1940
+ // (3) Filter out removed items.
2004
1941
  itemsRef.current = items.filter(item => currentItems.includes(item));
2005
1942
  }
2006
-
2007
1943
  return itemsRef.current;
2008
1944
  }
2009
-
2010
1945
  function useNewItems(items = [], shouldReset) {
2011
1946
  const previousItems = usePrevious(items.slice()) || [];
2012
-
2013
1947
  if (shouldReset) {
2014
1948
  return [];
2015
1949
  }
2016
-
2017
1950
  return previousItems ? items.filter(item => !previousItems.includes(item)) : [];
2018
1951
  }
2019
1952
 
@@ -2038,23 +1971,19 @@ function NumberField(props) {
2038
1971
  validity,
2039
1972
  value
2040
1973
  } = event.target;
2041
-
2042
1974
  if (validity.valid) {
2043
1975
  onInput(value ? parseFloat(value) : undefined);
2044
1976
  }
2045
1977
  });
2046
1978
  }, [onInput, debounce]);
2047
-
2048
1979
  const handleInput = e => {
2049
1980
  handleInputCallback(e);
2050
1981
  setLocalValue(e.target.value);
2051
1982
  };
2052
-
2053
1983
  useEffect(() => {
2054
1984
  if (value === localValue) {
2055
1985
  return;
2056
1986
  }
2057
-
2058
1987
  setLocalValue(value);
2059
1988
  }, [value]);
2060
1989
  return jsxs("div", {
@@ -2081,6 +2010,7 @@ function NumberField(props) {
2081
2010
  })]
2082
2011
  });
2083
2012
  }
2013
+
2084
2014
  /**
2085
2015
  * @param {Object} props
2086
2016
  * @param {Boolean} props.debounce
@@ -2097,8 +2027,6 @@ function NumberField(props) {
2097
2027
  * @param {Function} props.onBlur
2098
2028
  * @param {String} props.step
2099
2029
  */
2100
-
2101
-
2102
2030
  function NumberFieldEntry(props) {
2103
2031
  const {
2104
2032
  debounce,
@@ -2140,7 +2068,9 @@ function NumberFieldEntry(props) {
2140
2068
  }
2141
2069
  function isEdited$5(node) {
2142
2070
  return node && !!node.value;
2143
- } // helpers /////////////////
2071
+ }
2072
+
2073
+ // helpers /////////////////
2144
2074
 
2145
2075
  function prefixId$5(id) {
2146
2076
  return `bio-properties-panel-${id}`;
@@ -2159,23 +2089,19 @@ function Select(props) {
2159
2089
  } = props;
2160
2090
  const ref = useShowEntryEvent(id);
2161
2091
  const [localValue, setLocalValue] = useState(value);
2162
-
2163
2092
  const handleChangeCallback = ({
2164
2093
  target
2165
2094
  }) => {
2166
2095
  onChange(target.value);
2167
2096
  };
2168
-
2169
2097
  const handleChange = e => {
2170
2098
  handleChangeCallback(e);
2171
2099
  setLocalValue(e.target.value);
2172
2100
  };
2173
-
2174
2101
  useEffect(() => {
2175
2102
  if (value === localValue) {
2176
2103
  return;
2177
2104
  }
2178
-
2179
2105
  setLocalValue(value);
2180
2106
  }, [value]);
2181
2107
  return jsxs("div", {
@@ -2204,6 +2130,7 @@ function Select(props) {
2204
2130
  })]
2205
2131
  });
2206
2132
  }
2133
+
2207
2134
  /**
2208
2135
  * @param {object} props
2209
2136
  * @param {object} props.element
@@ -2217,8 +2144,6 @@ function Select(props) {
2217
2144
  * @param {Function} props.getOptions
2218
2145
  * @param {boolean} [props.disabled]
2219
2146
  */
2220
-
2221
-
2222
2147
  function SelectEntry(props) {
2223
2148
  const {
2224
2149
  element,
@@ -2259,7 +2184,9 @@ function SelectEntry(props) {
2259
2184
  }
2260
2185
  function isEdited$4(node) {
2261
2186
  return node && !!node.value;
2262
- } // helpers /////////////////
2187
+ }
2188
+
2189
+ // helpers /////////////////
2263
2190
 
2264
2191
  function prefixId$4(id) {
2265
2192
  return `bio-properties-panel-${id}`;
@@ -2283,17 +2210,14 @@ function Simple(props) {
2283
2210
  target
2284
2211
  }) => setValue(target.value.length ? target.value : undefined));
2285
2212
  }, [setValue, debounce]);
2286
-
2287
2213
  const handleInput = e => {
2288
2214
  handleInputCallback(e);
2289
2215
  setLocalValue(e.target.value);
2290
2216
  };
2291
-
2292
2217
  useEffect(() => {
2293
2218
  if (value === localValue) {
2294
2219
  return;
2295
2220
  }
2296
-
2297
2221
  setLocalValue(value);
2298
2222
  }, [value]);
2299
2223
  return jsx("div", {
@@ -2316,7 +2240,9 @@ function Simple(props) {
2316
2240
  }
2317
2241
  function isEdited$3(node) {
2318
2242
  return node && !!node.value;
2319
- } // helpers /////////////////
2243
+ }
2244
+
2245
+ // helpers /////////////////
2320
2246
 
2321
2247
  function prefixId$3(id) {
2322
2248
  return `bio-properties-panel-${id}`;
@@ -2342,17 +2268,14 @@ function TextArea(props) {
2342
2268
  target
2343
2269
  }) => onInput(target.value.length ? target.value : undefined));
2344
2270
  }, [onInput, debounce]);
2345
-
2346
2271
  const handleInput = e => {
2347
2272
  handleInputCallback(e);
2348
2273
  setLocalValue(e.target.value);
2349
2274
  };
2350
-
2351
2275
  useEffect(() => {
2352
2276
  if (value === localValue) {
2353
2277
  return;
2354
2278
  }
2355
-
2356
2279
  setLocalValue(value);
2357
2280
  }, [value]);
2358
2281
  return jsxs("div", {
@@ -2376,6 +2299,7 @@ function TextArea(props) {
2376
2299
  })]
2377
2300
  });
2378
2301
  }
2302
+
2379
2303
  /**
2380
2304
  * @param {object} props
2381
2305
  * @param {object} props.element
@@ -2391,8 +2315,6 @@ function TextArea(props) {
2391
2315
  * @param {boolean} props.monospace
2392
2316
  * @param {boolean} [props.disabled]
2393
2317
  */
2394
-
2395
-
2396
2318
  function TextAreaEntry(props) {
2397
2319
  const {
2398
2320
  element,
@@ -2436,7 +2358,9 @@ function TextAreaEntry(props) {
2436
2358
  }
2437
2359
  function isEdited$2(node) {
2438
2360
  return node && !!node.value;
2439
- } // helpers /////////////////
2361
+ }
2362
+
2363
+ // helpers /////////////////
2440
2364
 
2441
2365
  function prefixId$2(id) {
2442
2366
  return `bio-properties-panel-${id}`;
@@ -2460,17 +2384,14 @@ function Textfield(props) {
2460
2384
  target
2461
2385
  }) => onInput(target.value.length ? target.value : undefined));
2462
2386
  }, [onInput, debounce]);
2463
-
2464
2387
  const handleInput = e => {
2465
2388
  handleInputCallback(e);
2466
2389
  setLocalValue(e.target.value);
2467
2390
  };
2468
-
2469
2391
  useEffect(() => {
2470
2392
  if (value === localValue) {
2471
2393
  return;
2472
2394
  }
2473
-
2474
2395
  setLocalValue(value);
2475
2396
  }, [value]);
2476
2397
  return jsxs("div", {
@@ -2495,6 +2416,7 @@ function Textfield(props) {
2495
2416
  })]
2496
2417
  });
2497
2418
  }
2419
+
2498
2420
  /**
2499
2421
  * @param {Object} props
2500
2422
  * @param {Object} props.element
@@ -2509,8 +2431,6 @@ function Textfield(props) {
2509
2431
  * @param {Function} props.onBlur
2510
2432
  * @param {Function} props.validate
2511
2433
  */
2512
-
2513
-
2514
2434
  function TextfieldEntry(props) {
2515
2435
  const {
2516
2436
  element,
@@ -2536,27 +2456,21 @@ function TextfieldEntry(props) {
2536
2456
  setLocalError(newValidationError);
2537
2457
  }
2538
2458
  }, [value]);
2539
-
2540
2459
  const onInput = newValue => {
2541
2460
  let newValidationError = null;
2542
-
2543
2461
  if (isFunction(validate)) {
2544
2462
  newValidationError = validate(newValue) || null;
2545
2463
  }
2546
-
2547
2464
  if (newValidationError) {
2548
2465
  setCachedInvalidValue(newValue);
2549
2466
  } else {
2550
2467
  setValue(newValue);
2551
2468
  }
2552
-
2553
2469
  setLocalError(newValidationError);
2554
2470
  };
2555
-
2556
2471
  if (previousValue === value && localError) {
2557
2472
  value = cachedInvalidValue;
2558
2473
  }
2559
-
2560
2474
  const error = globalError || localError;
2561
2475
  return jsxs("div", {
2562
2476
  class: classnames('bio-properties-panel-entry', error ? 'has-error' : ''),
@@ -2582,7 +2496,9 @@ function TextfieldEntry(props) {
2582
2496
  }
2583
2497
  function isEdited$1(node) {
2584
2498
  return node && !!node.value;
2585
- } // helpers /////////////////
2499
+ }
2500
+
2501
+ // helpers /////////////////
2586
2502
 
2587
2503
  function prefixId$1(id) {
2588
2504
  return `bio-properties-panel-${id}`;
@@ -2599,21 +2515,17 @@ function ToggleSwitch(props) {
2599
2515
  onBlur
2600
2516
  } = props;
2601
2517
  const [localValue, setLocalValue] = useState(value);
2602
-
2603
2518
  const handleInputCallback = async () => {
2604
2519
  onInput(!value);
2605
2520
  };
2606
-
2607
2521
  const handleInput = e => {
2608
2522
  handleInputCallback();
2609
2523
  setLocalValue(e.target.value);
2610
2524
  };
2611
-
2612
2525
  useEffect(() => {
2613
2526
  if (value === localValue) {
2614
2527
  return;
2615
2528
  }
2616
-
2617
2529
  setLocalValue(value);
2618
2530
  }, [value]);
2619
2531
  return jsxs("div", {
@@ -2645,6 +2557,7 @@ function ToggleSwitch(props) {
2645
2557
  })]
2646
2558
  });
2647
2559
  }
2560
+
2648
2561
  /**
2649
2562
  * @param {Object} props
2650
2563
  * @param {Object} props.element
@@ -2657,8 +2570,6 @@ function ToggleSwitch(props) {
2657
2570
  * @param {Function} props.onFocus
2658
2571
  * @param {Function} props.onBlur
2659
2572
  */
2660
-
2661
-
2662
2573
  function ToggleSwitchEntry(props) {
2663
2574
  const {
2664
2575
  element,
@@ -2692,7 +2603,9 @@ function ToggleSwitchEntry(props) {
2692
2603
  }
2693
2604
  function isEdited(node) {
2694
2605
  return node && !!node.checked;
2695
- } // helpers /////////////////
2606
+ }
2607
+
2608
+ // helpers /////////////////
2696
2609
 
2697
2610
  function prefixId(id) {
2698
2611
  return `bio-properties-panel-${id}`;