@bpmn-io/form-js-editor 1.18.0 → 1.20.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.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var Ids = require('ids');
3
+ var ids$1 = require('ids');
4
4
  var formJsViewer = require('@bpmn-io/form-js-viewer');
5
5
  var minDash = require('min-dash');
6
6
  var classnames = require('classnames');
@@ -2890,11 +2890,35 @@ EditorActions.prototype._registerDefaultActions = function (injector) {
2890
2890
  }
2891
2891
  });
2892
2892
  }
2893
+ if (copyPaste && selection) {
2894
+ this.register('duplicate', function () {
2895
+ var selectedElements = selection.get();
2896
+ if (selectedElements.length) {
2897
+ return copyPaste.duplicate(selectedElements);
2898
+ }
2899
+ });
2900
+ }
2893
2901
  if (copyPaste) {
2894
2902
  this.register('paste', function () {
2895
2903
  copyPaste.paste();
2896
2904
  });
2897
2905
  }
2906
+ if (copyPaste && selection && rules) {
2907
+ this.register('cut', function () {
2908
+ var selectedElements = selection.get();
2909
+ if (!selectedElements.length) {
2910
+ return;
2911
+ }
2912
+ var allowed = rules.allowed('elements.delete', {
2913
+ elements: selectedElements
2914
+ });
2915
+ if (allowed === false) {
2916
+ return;
2917
+ }
2918
+ var cuttableElements = minDash.isArray(allowed) ? allowed : selectedElements;
2919
+ return copyPaste.cut(cuttableElements.slice());
2920
+ });
2921
+ }
2898
2922
  if (zoomScroll) {
2899
2923
  this.register('stepZoom', function (opts) {
2900
2924
  zoomScroll.stepZoom(opts.value);
@@ -3113,6 +3137,8 @@ const EditorExpressionLanguageModule = {
3113
3137
 
3114
3138
  var KEYS_COPY = ['c', 'C'];
3115
3139
  var KEYS_PASTE = ['v', 'V'];
3140
+ var KEYS_DUPLICATE = ['d', 'D'];
3141
+ var KEYS_CUT = ['x', 'X'];
3116
3142
  var KEYS_REDO = ['y', 'Y'];
3117
3143
  var KEYS_UNDO = ['z', 'Z'];
3118
3144
 
@@ -3128,7 +3154,7 @@ function hasModifier(event) {
3128
3154
  * @param {KeyboardEvent} event
3129
3155
  * @return {boolean}
3130
3156
  */
3131
- function isCmd(event) {
3157
+ function isCmd$1(event) {
3132
3158
  // ensure we don't react to AltGr
3133
3159
  // (mapped to CTRL + ALT)
3134
3160
  if (event.altKey) {
@@ -3160,28 +3186,42 @@ function isShift(event) {
3160
3186
  * @param {KeyboardEvent} event
3161
3187
  */
3162
3188
  function isCopy(event) {
3163
- return isCmd(event) && isKey(KEYS_COPY, event);
3189
+ return isCmd$1(event) && isKey(KEYS_COPY, event);
3164
3190
  }
3165
3191
 
3166
3192
  /**
3167
3193
  * @param {KeyboardEvent} event
3168
3194
  */
3169
3195
  function isPaste(event) {
3170
- return isCmd(event) && isKey(KEYS_PASTE, event);
3196
+ return isCmd$1(event) && isKey(KEYS_PASTE, event);
3197
+ }
3198
+
3199
+ /**
3200
+ * @param {KeyboardEvent} event
3201
+ */
3202
+ function isDuplicate(event) {
3203
+ return isCmd$1(event) && isKey(KEYS_DUPLICATE, event);
3204
+ }
3205
+
3206
+ /**
3207
+ * @param {KeyboardEvent} event
3208
+ */
3209
+ function isCut(event) {
3210
+ return isCmd$1(event) && isKey(KEYS_CUT, event);
3171
3211
  }
3172
3212
 
3173
3213
  /**
3174
3214
  * @param {KeyboardEvent} event
3175
3215
  */
3176
3216
  function isUndo(event) {
3177
- return isCmd(event) && !isShift(event) && isKey(KEYS_UNDO, event);
3217
+ return isCmd$1(event) && !isShift(event) && isKey(KEYS_UNDO, event);
3178
3218
  }
3179
3219
 
3180
3220
  /**
3181
3221
  * @param {KeyboardEvent} event
3182
3222
  */
3183
3223
  function isRedo(event) {
3184
- return isCmd(event) && (isKey(KEYS_REDO, event) || isKey(KEYS_UNDO, event) && isShift(event));
3224
+ return isCmd$1(event) && (isKey(KEYS_REDO, event) || isKey(KEYS_UNDO, event) && isShift(event));
3185
3225
  }
3186
3226
 
3187
3227
  /**
@@ -3350,7 +3390,7 @@ Keyboard.prototype.removeListener = function (listener, type) {
3350
3390
  this._eventBus.off(type || KEYDOWN_EVENT, listener);
3351
3391
  };
3352
3392
  Keyboard.prototype.hasModifier = hasModifier;
3353
- Keyboard.prototype.isCmd = isCmd;
3393
+ Keyboard.prototype.isCmd = isCmd$1;
3354
3394
  Keyboard.prototype.isShift = isShift;
3355
3395
  Keyboard.prototype.isKey = isKey;
3356
3396
 
@@ -3435,6 +3475,26 @@ KeyboardBindings.prototype.registerBindings = function (keyboard, editorActions)
3435
3475
  }
3436
3476
  });
3437
3477
 
3478
+ // duplicate
3479
+ // CTRL/CMD + D
3480
+ addListener('duplicate', function (context) {
3481
+ var event = context.keyEvent;
3482
+ if (isDuplicate(event)) {
3483
+ editorActions.trigger('duplicate');
3484
+ return true;
3485
+ }
3486
+ });
3487
+
3488
+ // cut
3489
+ // CTRL/CMD + X
3490
+ addListener('cut', function (context) {
3491
+ var event = context.keyEvent;
3492
+ if (isCut(event)) {
3493
+ editorActions.trigger('cut');
3494
+ return true;
3495
+ }
3496
+ });
3497
+
3438
3498
  // zoom in one step
3439
3499
  // CTRL/CMD + +
3440
3500
  addListener('stepZoom', function (context) {
@@ -3442,7 +3502,7 @@ KeyboardBindings.prototype.registerBindings = function (keyboard, editorActions)
3442
3502
 
3443
3503
  // quirk: it has to be triggered by `=` as well to work on international keyboard layout
3444
3504
  // cf: https://github.com/bpmn-io/bpmn-js/issues/1362#issuecomment-722989754
3445
- if (isKey(['+', 'Add', '='], event) && isCmd(event)) {
3505
+ if (isKey(['+', 'Add', '='], event) && isCmd$1(event)) {
3446
3506
  editorActions.trigger('stepZoom', {
3447
3507
  value: 1
3448
3508
  });
@@ -3454,7 +3514,7 @@ KeyboardBindings.prototype.registerBindings = function (keyboard, editorActions)
3454
3514
  // CTRL + -
3455
3515
  addListener('stepZoom', function (context) {
3456
3516
  var event = context.keyEvent;
3457
- if (isKey(['-', 'Subtract'], event) && isCmd(event)) {
3517
+ if (isKey(['-', 'Subtract'], event) && isCmd$1(event)) {
3458
3518
  editorActions.trigger('stepZoom', {
3459
3519
  value: -1
3460
3520
  });
@@ -3466,7 +3526,7 @@ KeyboardBindings.prototype.registerBindings = function (keyboard, editorActions)
3466
3526
  // CTRL + 0
3467
3527
  addListener('zoom', function (context) {
3468
3528
  var event = context.keyEvent;
3469
- if (isKey('0', event) && isCmd(event)) {
3529
+ if (isKey('0', event) && isCmd$1(event)) {
3470
3530
  editorActions.trigger('zoom', {
3471
3531
  value: 1
3472
3532
  });
@@ -5473,6 +5533,21 @@ OpenPopupIcon.defaultProps = {
5473
5533
  xmlns: "http://www.w3.org/2000/svg",
5474
5534
  viewBox: "0 0 16 16"
5475
5535
  };
5536
+
5537
+ /**
5538
+ * @typedef { {
5539
+ * getElementLabel: (element: object) => string,
5540
+ * getTypeLabel: (element: object) => string,
5541
+ * getElementIcon: (element: object) => import('preact').Component,
5542
+ * getDocumentationRef: (element: object) => string
5543
+ * } } HeaderProvider
5544
+ */
5545
+
5546
+ /**
5547
+ * @param {Object} props
5548
+ * @param {Object} props.element,
5549
+ * @param {HeaderProvider} props.headerProvider
5550
+ */
5476
5551
  function Header(props) {
5477
5552
  const {
5478
5553
  element,
@@ -5500,11 +5575,9 @@ function Header(props) {
5500
5575
  }), jsxRuntime.jsxs("div", {
5501
5576
  class: "bio-properties-panel-header-labels",
5502
5577
  children: [jsxRuntime.jsx("div", {
5503
- title: type,
5504
5578
  class: "bio-properties-panel-header-type",
5505
5579
  children: type
5506
5580
  }), label ? jsxRuntime.jsx("div", {
5507
- title: label,
5508
5581
  class: "bio-properties-panel-header-label",
5509
5582
  children: label
5510
5583
  }) : null]
@@ -5592,6 +5665,27 @@ function useTooltipContext(id, element) {
5592
5665
  } = hooks.useContext(TooltipContext);
5593
5666
  return getTooltipForId(id, element);
5594
5667
  }
5668
+
5669
+ /**
5670
+ * @typedef {Object} TooltipProps
5671
+ * @property {Object} [parent] - Parent element ref for portal rendering
5672
+ * @property {String} [direction='right'] - Tooltip direction ( 'right', 'top')
5673
+ * @property {String} [position] - Custom CSS position override
5674
+ * @property {Number} [showDelay=250] - Delay in ms before showing tooltip on hover
5675
+ * @property {Number} [hideDelay=250] - Delay in ms before hiding tooltip when mouse leaves, to avoid multiple tooltips from being opened, this should be the same as showDelay
5676
+ * @property {*} [children] - Child elements to render inside the tooltip wrapper
5677
+ */
5678
+
5679
+ /**
5680
+ * Tooltip wrapper that provides context-based tooltip content lookup.
5681
+ * All props are forwarded to the underlying Tooltip component.
5682
+ *
5683
+ * @param {TooltipProps & {
5684
+ * forId: String,
5685
+ * value?: String|Object,
5686
+ * element?: Object
5687
+ * }} props - Shared tooltip props plus wrapper-specific ones
5688
+ */
5595
5689
  function TooltipWrapper(props) {
5596
5690
  const {
5597
5691
  forId,
@@ -5608,35 +5702,93 @@ function TooltipWrapper(props) {
5608
5702
  forId: `bio-properties-panel-${forId}`
5609
5703
  });
5610
5704
  }
5705
+
5706
+ /**
5707
+ * @param {TooltipProps & {
5708
+ * forId: String,
5709
+ * value: String|Object
5710
+ * }} props
5711
+ */
5611
5712
  function Tooltip(props) {
5612
5713
  const {
5613
5714
  forId,
5614
5715
  value,
5615
5716
  parent,
5616
5717
  direction = 'right',
5617
- position
5718
+ position,
5719
+ showDelay = 250,
5720
+ hideDelay = 250
5618
5721
  } = props;
5619
5722
  const [visible, setVisible] = hooks.useState(false);
5620
-
5621
- // Tooltip will be shown after SHOW_DELAY ms from hovering over the source element.
5622
- const SHOW_DELAY = 200;
5623
- let timeout = null;
5723
+ const [tooltipPosition, setTooltipPosition] = hooks.useState(null);
5724
+ const [arrowOffset, setArrowOffset] = hooks.useState(null);
5725
+ const showTimeoutRef = hooks.useRef(null);
5726
+ const hideTimeoutRef = hooks.useRef(null);
5624
5727
  const wrapperRef = hooks.useRef(null);
5625
5728
  const tooltipRef = hooks.useRef(null);
5626
5729
  const show = (_, delay) => {
5730
+ clearTimeout(showTimeoutRef.current);
5731
+ clearTimeout(hideTimeoutRef.current);
5627
5732
  if (visible) return;
5628
5733
  if (delay) {
5629
- timeout = setTimeout(() => {
5734
+ showTimeoutRef.current = setTimeout(() => {
5630
5735
  setVisible(true);
5631
- }, SHOW_DELAY);
5736
+ }, showDelay);
5632
5737
  } else {
5633
5738
  setVisible(true);
5634
5739
  }
5635
5740
  };
5636
- const hide = () => {
5637
- clearTimeout(timeout);
5638
- setVisible(false);
5741
+ const handleWrapperMouseEnter = e => {
5742
+ show(e, true);
5743
+ };
5744
+ const hide = (delay = false) => {
5745
+ clearTimeout(showTimeoutRef.current);
5746
+ clearTimeout(hideTimeoutRef.current);
5747
+ if (delay) {
5748
+ hideTimeoutRef.current = setTimeout(() => {
5749
+ setVisible(false);
5750
+ }, hideDelay);
5751
+ } else {
5752
+ setVisible(false);
5753
+ }
5639
5754
  };
5755
+
5756
+ // Cleanup timeouts on unmount
5757
+ hooks.useEffect(() => {
5758
+ return () => {
5759
+ clearTimeout(showTimeoutRef.current);
5760
+ clearTimeout(hideTimeoutRef.current);
5761
+ };
5762
+ }, []);
5763
+
5764
+ // Handle click outside to close tooltip for non-focusable elements
5765
+ hooks.useEffect(() => {
5766
+ if (!visible) return;
5767
+ const handleClickOutside = e => {
5768
+ // If clicking outside both the wrapper and tooltip, hide it
5769
+ if (wrapperRef.current && !wrapperRef.current.contains(e.target) && tooltipRef.current && !tooltipRef.current.contains(e.target)) {
5770
+ hide(false);
5771
+ }
5772
+ };
5773
+ document.addEventListener('mousedown', handleClickOutside);
5774
+ return () => {
5775
+ document.removeEventListener('mousedown', handleClickOutside);
5776
+ };
5777
+ }, [visible, hide]);
5778
+ hooks.useLayoutEffect(() => {
5779
+ if (!visible || position) {
5780
+ setTooltipPosition(null);
5781
+ setArrowOffset(null);
5782
+ return;
5783
+ }
5784
+ if (!wrapperRef.current || !tooltipRef.current) return;
5785
+ const {
5786
+ tooltipPosition: newPosition,
5787
+ arrowOffset: newArrowOffset
5788
+ } = getTooltipPosition(wrapperRef.current, tooltipRef.current, direction);
5789
+ setTooltipPosition(newPosition);
5790
+ setArrowOffset(newArrowOffset);
5791
+ }, [visible, position]);
5640
5792
  const handleMouseLeave = ({
5641
5793
  relatedTarget
5642
5794
  }) => {
@@ -5644,39 +5796,52 @@ function Tooltip(props) {
5644
5796
  if (relatedTarget === wrapperRef.current || relatedTarget === tooltipRef.current || relatedTarget?.parentElement === tooltipRef.current) {
5645
5797
  return;
5646
5798
  }
5647
- hide();
5799
+ const selection = window.getSelection();
5800
+ if (selection && selection.toString().length > 0) {
5801
+ // Check if selection is within tooltip content
5802
+ const selectionRange = selection.getRangeAt(0);
5803
+ if (tooltipRef.current?.contains(selectionRange.commonAncestorContainer) || tooltipRef.current?.contains(selection.anchorNode) || tooltipRef.current?.contains(selection.focusNode)) {
5804
+ return; // Keep tooltip open during text selection
5805
+ }
5806
+ }
5807
+ hide(true);
5808
+ };
5809
+ const handleTooltipMouseEnter = () => {
5810
+ clearTimeout(hideTimeoutRef.current);
5648
5811
  };
5649
5812
  const handleFocusOut = e => {
5650
5813
  const {
5651
- target
5814
+ relatedTarget
5652
5815
  } = e;
5653
5816
 
5654
- // Don't hide the tooltip if the wrapper or the tooltip itself is clicked.
5655
- const isHovered = target.matches(':hover') || tooltipRef.current?.matches(':hover');
5656
- if (target === wrapperRef.current && isHovered) {
5657
- e.stopPropagation();
5817
+ // Don't hide if focus moved to the tooltip or another element within the wrapper
5818
+ if (tooltipRef.current?.contains(relatedTarget) || wrapperRef.current?.contains(relatedTarget)) {
5658
5819
  return;
5659
5820
  }
5660
- hide();
5821
+ hide(false);
5661
5822
  };
5662
5823
  const hideTooltipViaEscape = e => {
5663
- e.code === 'Escape' && hide();
5824
+ e.code === 'Escape' && hide(false);
5664
5825
  };
5665
5826
  const renderTooltip = () => {
5827
+ const tooltipStyle = position || (tooltipPosition ? `right: ${tooltipPosition.right}; top: ${tooltipPosition.top}px;` : undefined);
5828
+ const arrowStyle = arrowOffset != null ? `margin-top: ${arrowOffset}px;` : undefined;
5666
5829
  return jsxRuntime.jsxs("div", {
5667
5830
  class: `bio-properties-panel-tooltip ${direction}`,
5668
5831
  role: "tooltip",
5669
5832
  id: "bio-properties-panel-tooltip",
5670
5833
  "aria-labelledby": forId,
5671
- style: position || getTooltipPosition(wrapperRef.current),
5834
+ style: tooltipStyle,
5672
5835
  ref: tooltipRef,
5673
5836
  onClick: e => e.stopPropagation(),
5837
+ onMouseEnter: handleTooltipMouseEnter,
5674
5838
  onMouseLeave: handleMouseLeave,
5675
5839
  children: [jsxRuntime.jsx("div", {
5676
5840
  class: "bio-properties-panel-tooltip-content",
5677
5841
  children: value
5678
5842
  }), jsxRuntime.jsx("div", {
5679
- class: "bio-properties-panel-tooltip-arrow"
5843
+ class: "bio-properties-panel-tooltip-arrow",
5844
+ style: arrowStyle
5680
5845
  })]
5681
5846
  });
5682
5847
  };
@@ -5684,7 +5849,7 @@ function Tooltip(props) {
5684
5849
  class: "bio-properties-panel-tooltip-wrapper",
5685
5850
  tabIndex: "0",
5686
5851
  ref: wrapperRef,
5687
- onMouseEnter: e => show(e, true),
5852
+ onMouseEnter: handleWrapperMouseEnter,
5688
5853
  onMouseLeave: handleMouseLeave,
5689
5854
  onFocus: show,
5690
5855
  onBlur: handleFocusOut,
@@ -5695,11 +5860,47 @@ function Tooltip(props) {
5695
5860
 
5696
5861
  // helper
5697
5862
 
5698
- function getTooltipPosition(refElement) {
5863
+ function getTooltipPosition(refElement, tooltipElement, direction) {
5864
+ if (!refElement) {
5865
+ return {
5866
+ tooltipPosition: null,
5867
+ arrowOffset: null
5868
+ };
5869
+ }
5699
5870
  const refPosition = refElement.getBoundingClientRect();
5700
5871
  const right = `calc(100% - ${refPosition.x}px)`;
5701
- const top = `${refPosition.top - 10}px`;
5702
- return `right: ${right}; top: ${top};`;
5872
+ let top = refPosition.top - 10;
5873
+ let arrowOffset = null;
5874
+
5875
+ // Ensure that the tooltip is within the viewport, adjust the top position if needed.
5876
+ // This is only relevant for the 'right' direction for now
5877
+ if (tooltipElement && direction === 'right') {
5878
+ const tooltipRect = tooltipElement.getBoundingClientRect();
5879
+ const viewportHeight = window.innerHeight;
5880
+ const minTop = 0;
5881
+ const maxTop = viewportHeight - tooltipRect.height;
5882
+ const originalTop = top;
5883
+ if (top > maxTop) {
5884
+ top = maxTop;
5885
+ }
5886
+ if (top < minTop) {
5887
+ top = minTop;
5888
+ }
5889
+
5890
+ // Adjust the arrow position if the tooltip had to be moved to stay within viewport
5891
+ if (top !== originalTop) {
5892
+ const defaultMarginTop = 16;
5893
+ const topDiff = top - originalTop;
5894
+ arrowOffset = defaultMarginTop - topDiff;
5895
+ }
5896
+ }
5897
+ return {
5898
+ tooltipPosition: {
5899
+ right,
5900
+ top
5901
+ },
5902
+ arrowOffset
5903
+ };
5703
5904
  }
5704
5905
 
5705
5906
  /**
@@ -5937,12 +6138,17 @@ function useStickyIntersectionObserver(ref, scrollContainerSelector, setSticky)
5937
6138
  * The `callback` reference is static and can be safely used in external
5938
6139
  * libraries or as a prop that does not cause rerendering of children.
5939
6140
  *
6141
+ * The ref update is deferred to useLayoutEffect to prevent stale-closure
6142
+ * bugs when Chrome fires blur on elements removed during re-render.
6143
+ *
5940
6144
  * @param {Function} callback function with changing reference
5941
6145
  * @returns {Function} static function reference
5942
6146
  */
5943
6147
  function useStaticCallback(callback) {
5944
6148
  const callbackRef = hooks.useRef(callback);
5945
- callbackRef.current = callback;
6149
+ hooks.useLayoutEffect(() => {
6150
+ callbackRef.current = callback;
6151
+ });
5946
6152
  return hooks.useCallback((...args) => callbackRef.current(...args), []);
5947
6153
  }
5948
6154
  function useElementVisible(element) {
@@ -5962,6 +6168,10 @@ function useElementVisible(element) {
5962
6168
  }, [element, visible]);
5963
6169
  return visible;
5964
6170
  }
6171
+
6172
+ /**
6173
+ * @param {import('../PropertiesPanel').GroupDefinition} props
6174
+ */
5965
6175
  function Group(props) {
5966
6176
  const {
5967
6177
  element,
@@ -6016,8 +6226,6 @@ function Group(props) {
6016
6226
  class: classnames('bio-properties-panel-group-header', edited ? '' : 'empty', open ? 'open' : '', sticky && open ? 'sticky' : ''),
6017
6227
  onClick: toggleOpen,
6018
6228
  children: [jsxRuntime.jsx("div", {
6019
- title: props.tooltip ? null : label,
6020
- "data-title": label,
6021
6229
  class: "bio-properties-panel-group-header-title",
6022
6230
  children: jsxRuntime.jsx(TooltipWrapper, {
6023
6231
  value: props.tooltip,
@@ -6221,9 +6429,11 @@ function PropertiesPanel$1(props) {
6221
6429
  return minDash.get(layout, key, defaultValue);
6222
6430
  };
6223
6431
  const setLayoutForKey = (key, config) => {
6224
- const newLayout = minDash.assign({}, layout);
6225
- minDash.set(newLayout, key, config);
6226
- setLayout(newLayout);
6432
+ setLayout(prevLayout => {
6433
+ const newLayout = minDash.assign({}, prevLayout);
6434
+ minDash.set(newLayout, key, config);
6435
+ return newLayout;
6436
+ });
6227
6437
  };
6228
6438
  const layoutContext = {
6229
6439
  layout,
@@ -6422,7 +6632,6 @@ function CollapsibleEntry(props) {
6422
6632
  class: "bio-properties-panel-collapsible-entry-header",
6423
6633
  onClick: toggleOpen,
6424
6634
  children: [jsxRuntime.jsx("div", {
6425
- title: label || placeholderLabel,
6426
6635
  class: classnames('bio-properties-panel-collapsible-entry-header-title', !label && 'empty'),
6427
6636
  children: label || placeholderLabel
6428
6637
  }), jsxRuntime.jsx("button", {
@@ -6458,6 +6667,10 @@ function CollapsibleEntry(props) {
6458
6667
  })]
6459
6668
  });
6460
6669
  }
6670
+
6671
+ /**
6672
+ * @param {import('../PropertiesPanel').ListItemDefinition} props
6673
+ */
6461
6674
  function ListItem(props) {
6462
6675
  const {
6463
6676
  autoFocusEntry,
@@ -6559,8 +6772,6 @@ function ListGroup(props) {
6559
6772
  class: classnames('bio-properties-panel-group-header', hasItems ? '' : 'empty', hasItems && open ? 'open' : '', sticky && open ? 'sticky' : ''),
6560
6773
  onClick: hasItems ? toggleOpen : noop$6,
6561
6774
  children: [jsxRuntime.jsx("div", {
6562
- title: props.tooltip ? null : label,
6563
- "data-title": label,
6564
6775
  class: "bio-properties-panel-group-header-title",
6565
6776
  children: jsxRuntime.jsx(TooltipWrapper, {
6566
6777
  value: props.tooltip,
@@ -6629,6 +6840,13 @@ function getNewItemIds(newItems, oldItems) {
6629
6840
  const oldIds = oldItems.map(item => item.id);
6630
6841
  return newIds.filter(itemId => !oldIds.includes(itemId));
6631
6842
  }
6843
+
6844
+ /**
6845
+ * @param {Object} props
6846
+ * @param {Object} props.element
6847
+ * @param {String} props.forId - id of the entry the description is used for
6848
+ * @param {String} props.value
6849
+ */
6632
6850
  function Description$1(props) {
6633
6851
  const {
6634
6852
  element,
@@ -6758,6 +6976,16 @@ function isEdited$8(node) {
6758
6976
  function prefixId$8(id) {
6759
6977
  return `bio-properties-panel-${id}`;
6760
6978
  }
6979
+
6980
+ /**
6981
+ * Button to open popups.
6982
+ *
6983
+ * @param {Object} props
6984
+ * @param {Function} props.onClick - Callback to trigger when the button is clicked.
6985
+ * @param {string} [props.title] - Tooltip text for the button.
6986
+ * @param {boolean} [props.disabled] - Whether the button is disabled.
6987
+ * @param {string} [props.className] - Additional class names for the button.
6988
+ */
6761
6989
  function OpenPopupButton({
6762
6990
  onClick,
6763
6991
  title = 'Open pop-up editor'
@@ -6901,6 +7129,7 @@ const FeelEditor = React.forwardRef((props, ref) => {
6901
7129
  enableGutters,
6902
7130
  value,
6903
7131
  onInput,
7132
+ onKeyDown: onKeyDownProp = noop$4,
6904
7133
  onFeelToggle = noop$4,
6905
7134
  onLint = noop$4,
6906
7135
  onOpenPopup = noop$4,
@@ -6933,6 +7162,8 @@ const FeelEditor = React.forwardRef((props, ref) => {
6933
7162
  * - AND the cursor is at the beginning of the input
6934
7163
  */
6935
7164
  const onKeyDown = e => {
7165
+ // Call parent onKeyDown handler first
7166
+ onKeyDownProp(e);
6936
7167
  if (e.key !== 'Backspace' || !editor) {
6937
7168
  return;
6938
7169
  }
@@ -7049,6 +7280,22 @@ function FeelIcon(props) {
7049
7280
  children: jsxRuntime.jsx(FeelIcon$1, {})
7050
7281
  });
7051
7282
  }
7283
+
7284
+ /**
7285
+ * @param {KeyboardEvent} event
7286
+ * @return {boolean}
7287
+ */
7288
+ function isCmd(event) {
7289
+ // ensure we don't react to AltGr
7290
+ // (mapped to CTRL + ALT)
7291
+ if (event.altKey) {
7292
+ return false;
7293
+ }
7294
+ return event.ctrlKey || event.metaKey;
7295
+ }
7296
+ function isCmdWithChar(event) {
7297
+ return isCmd(event) && event.key.length === 1 && /^[a-zA-Z]$/.test(event.key);
7298
+ }
7052
7299
  function ToggleSwitch(props) {
7053
7300
  const {
7054
7301
  id,
@@ -7157,7 +7404,7 @@ function ToggleSwitchEntry(props) {
7157
7404
  inline: inline,
7158
7405
  tooltip: tooltip,
7159
7406
  element: element
7160
- }), jsxRuntime.jsx(Description$1, {
7407
+ }, element), jsxRuntime.jsx(Description$1, {
7161
7408
  forId: id,
7162
7409
  element: element,
7163
7410
  value: description
@@ -7330,7 +7577,7 @@ function prefixId$6(id) {
7330
7577
  const noop$2 = () => {};
7331
7578
 
7332
7579
  /**
7333
- * @typedef {'required'|'optional'|'static'} FeelType
7580
+ * @typedef {'required'|'optional'|'optional-default-enabled'|'static'} FeelType
7334
7581
  */
7335
7582
 
7336
7583
  /**
@@ -7360,7 +7607,7 @@ function FeelTextfield(props) {
7360
7607
  element,
7361
7608
  label,
7362
7609
  hostLanguage,
7363
- onInput,
7610
+ onInput: commitValue,
7364
7611
  onBlur,
7365
7612
  onError,
7366
7613
  placeholder,
@@ -7373,11 +7620,17 @@ function FeelTextfield(props) {
7373
7620
  OptionalComponent = OptionalFeelInput,
7374
7621
  tooltip
7375
7622
  } = props;
7376
- const [localValue, setLocalValue] = hooks.useState(value);
7623
+ const [localValue, setLocalValue] = hooks.useState(getInitialFeelLocalValue(feel, value));
7377
7624
  const editorRef = useShowEntryEvent(id);
7378
7625
  const containerRef = hooks.useRef();
7379
- const feelActive = minDash.isString(localValue) && localValue.startsWith('=') || feel === 'required';
7380
- const feelOnlyValue = minDash.isString(localValue) && localValue.startsWith('=') ? localValue.substring(1) : localValue;
7626
+ const onInput = hooks.useCallback(newValue => {
7627
+ // we don't commit empty FEEL expressions,
7628
+ // but instead serialize them as <undefined>
7629
+ const newModelValue = newValue === '' || newValue === '=' ? undefined : newValue;
7630
+ commitValue(newModelValue);
7631
+ }, [commitValue]);
7632
+ const feelActive = isFeelActive(feel, localValue);
7633
+ const feelOnlyValue = getFeelValue(localValue);
7381
7634
  const feelLanguageContext = hooks.useContext(FeelLanguageContext);
7382
7635
  const [focus, _setFocus] = hooks.useState(undefined);
7383
7636
  const {
@@ -7395,13 +7648,7 @@ function FeelTextfield(props) {
7395
7648
  /**
7396
7649
  * @type { import('min-dash').DebouncedFunction }
7397
7650
  */
7398
- const handleInputCallback = useDebounce(onInput, debounce);
7399
- const handleInput = newValue => {
7400
- // we don't commit empty FEEL expressions,
7401
- // but instead serialize them as <undefined>
7402
- const newModelValue = newValue === '' || newValue === '=' ? undefined : newValue;
7403
- handleInputCallback(newModelValue);
7404
- };
7651
+ const handleInput = useDebounce(onInput, debounce);
7405
7652
  const handleFeelToggle = useStaticCallback(() => {
7406
7653
  if (feel === 'required') {
7407
7654
  return;
@@ -7414,7 +7661,7 @@ function FeelTextfield(props) {
7414
7661
  handleInput(feelOnlyValue);
7415
7662
  }
7416
7663
  });
7417
- const handleLocalInput = newValue => {
7664
+ const handleLocalInput = (newValue, useDebounce = true) => {
7418
7665
  if (feelActive) {
7419
7666
  newValue = '=' + newValue;
7420
7667
  }
@@ -7422,23 +7669,33 @@ function FeelTextfield(props) {
7422
7669
  return;
7423
7670
  }
7424
7671
  setLocalValue(newValue);
7425
- handleInput(newValue);
7672
+ if (useDebounce) {
7673
+ handleInput(newValue);
7674
+ } else {
7675
+ onInput(newValue);
7676
+ }
7426
7677
  if (!feelActive && minDash.isString(newValue) && newValue.startsWith('=')) {
7427
7678
  // focus is behind `=` sign that will be removed
7428
7679
  setFocus(-1);
7429
7680
  }
7430
7681
  };
7431
7682
  const handleOnBlur = e => {
7683
+ handleInput.cancel?.();
7432
7684
  if (e.target.type === 'checkbox') {
7433
7685
  onInput(e.target.checked);
7434
7686
  } else {
7435
7687
  const trimmedValue = e.target.value.trim();
7436
- onInput(trimmedValue);
7688
+ handleLocalInput(trimmedValue, false);
7437
7689
  }
7438
7690
  if (onBlur) {
7439
7691
  onBlur(e);
7440
7692
  }
7441
7693
  };
7694
+ const handleOnKeyDown = e => {
7695
+ if (isCmdWithChar(e)) {
7696
+ handleInput.flush?.();
7697
+ }
7698
+ };
7442
7699
  const handleLint = useStaticCallback((lint = []) => {
7443
7700
  const syntaxError = lint.some(report => report.type === 'Syntax Error');
7444
7701
  if (syntaxError) {
@@ -7505,12 +7762,26 @@ function FeelTextfield(props) {
7505
7762
  if (feelActive || isPopupOpen) {
7506
7763
  return;
7507
7764
  }
7508
- const data = event.clipboardData.getData('application/FEEL');
7509
- if (data) {
7765
+ const feelData = event.clipboardData.getData('application/FEEL');
7766
+ if (feelData) {
7510
7767
  setTimeout(() => {
7511
7768
  handleFeelToggle();
7512
7769
  setFocus();
7513
7770
  });
7771
+ return;
7772
+ }
7773
+ const input = event.target;
7774
+ const isFieldEmpty = !input.value;
7775
+ const isAllSelected = input.selectionStart === 0 && input.selectionEnd === input.value.length;
7776
+ if (isFieldEmpty || isAllSelected) {
7777
+ const textData = event.clipboardData.getData('text');
7778
+ const trimmedValue = textData.trim();
7779
+ setLocalValue(trimmedValue);
7780
+ handleInput(trimmedValue);
7781
+ if (!feelActive && minDash.isString(trimmedValue) && trimmedValue.startsWith('=')) {
7782
+ setFocus(trimmedValue.length - 1);
7783
+ }
7784
+ event.preventDefault();
7514
7785
  }
7515
7786
  };
7516
7787
  containerRef.current.addEventListener('copy', copyHandler);
@@ -7546,11 +7817,12 @@ function FeelTextfield(props) {
7546
7817
  ref: containerRef,
7547
7818
  children: [jsxRuntime.jsx(FeelIndicator, {
7548
7819
  active: feelActive,
7549
- disabled: feel !== 'optional' || disabled,
7820
+ disabled: !isFeelOptional(feel) || disabled,
7550
7821
  onClick: handleFeelToggle
7551
7822
  }), feelActive ? jsxRuntime.jsx(FeelEditor, {
7552
7823
  name: id,
7553
7824
  onInput: handleLocalInput,
7825
+ onKeyDown: handleOnKeyDown,
7554
7826
  contentAttributes: {
7555
7827
  'id': prefixId$5(id),
7556
7828
  'aria-label': label
@@ -7573,6 +7845,7 @@ function FeelTextfield(props) {
7573
7845
  ...props,
7574
7846
  popupOpen: isPopupOpen,
7575
7847
  onInput: handleLocalInput,
7848
+ onKeyDown: handleOnKeyDown,
7576
7849
  onBlur: handleOnBlur,
7577
7850
  contentAttributes: {
7578
7851
  'id': prefixId$5(id),
@@ -7591,6 +7864,7 @@ const OptionalFeelInput = React.forwardRef((props, ref) => {
7591
7864
  id,
7592
7865
  disabled,
7593
7866
  onInput,
7867
+ onKeyDown,
7594
7868
  value,
7595
7869
  onFocus,
7596
7870
  onBlur,
@@ -7626,6 +7900,7 @@ const OptionalFeelInput = React.forwardRef((props, ref) => {
7626
7900
  class: "bio-properties-panel-input",
7627
7901
  onInput: e => onInput(e.target.value),
7628
7902
  onFocus: onFocus,
7903
+ onKeyDown: onKeyDown,
7629
7904
  onBlur: onBlur,
7630
7905
  placeholder: placeholder,
7631
7906
  value: value || ''
@@ -7999,6 +8274,87 @@ function isEdited$5(node) {
7999
8274
  function prefixId$5(id) {
8000
8275
  return `bio-properties-panel-${id}`;
8001
8276
  }
8277
+
8278
+ /**
8279
+ * Determine if FEEL is optional for the configured {@link FeelType}.
8280
+ *
8281
+ * @param {FeelType} feelType
8282
+ *
8283
+ * @return {boolean}
8284
+ */
8285
+ function isFeelOptional(feelType) {
8286
+ return feelType === 'optional' || feelType === 'optional-default-enabled';
8287
+ }
8288
+
8289
+ /**
8290
+ * Determine if FEEL editing is currently active.
8291
+ *
8292
+ * @param {FeelType} feelType
8293
+ * @param {string} localValue
8294
+ *
8295
+ * @return {boolean}
8296
+ */
8297
+ function isFeelActive(feelType, localValue) {
8298
+ if (feelType === 'required') {
8299
+ return true;
8300
+ }
8301
+ if (minDash.isString(localValue)) {
8302
+ if (localValue.startsWith('=')) {
8303
+ return true;
8304
+ }
8305
+ }
8306
+ return false;
8307
+ }
8308
+
8309
+ /**
8310
+ * @template T
8311
+ * @param {T} value
8312
+ *
8313
+ * @return {string|T}
8314
+ */
8315
+ function getFeelValue(value) {
8316
+ if (minDash.isString(value) && value.startsWith('=')) {
8317
+ return value.substring(1);
8318
+ }
8319
+ return value;
8320
+ }
8321
+
8322
+ /**
8323
+ * Initialize local FEEL value.
8324
+ *
8325
+ * `optional-default-enabled` starts in FEEL mode if no value or empty string is provided.
8326
+ *
8327
+ * @template T
8328
+ * @param {FeelType} feelType
8329
+ * @param {T} value
8330
+ *
8331
+ * @return {string|T}
8332
+ */
8333
+ function getInitialFeelLocalValue(feelType, value) {
8334
+ if (feelType === 'optional-default-enabled' && (value === undefined || value === '')) {
8335
+ return '=';
8336
+ }
8337
+ return value;
8338
+ }
8339
+
8340
+ /**
8341
+ * @typedef { { value: string, label: string, disabled: boolean, children: { value: string, label: string, disabled: boolean } } } Option
8342
+ */
8343
+
8344
+ /**
8345
+ * Provides basic select input.
8346
+ *
8347
+ * @param {object} props
8348
+ * @param {string} props.id
8349
+ * @param {string[]} props.path
8350
+ * @param {string} props.label
8351
+ * @param {Function} props.onChange
8352
+ * @param {Function} props.onFocus
8353
+ * @param {Function} props.onBlur
8354
+ * @param {Array<Option>} [props.options]
8355
+ * @param {string} props.value
8356
+ * @param {boolean} [props.disabled]
8357
+ */
8002
8358
  function Select(props) {
8003
8359
  const {
8004
8360
  id,
@@ -8164,12 +8520,13 @@ function TextArea(props) {
8164
8520
  id,
8165
8521
  label,
8166
8522
  debounce,
8167
- onInput,
8523
+ onInput: commitValue,
8168
8524
  value = '',
8169
8525
  disabled,
8170
8526
  monospace,
8171
8527
  onFocus,
8172
8528
  onBlur,
8529
+ onPaste,
8173
8530
  autoResize = true,
8174
8531
  placeholder,
8175
8532
  rows = autoResize ? 1 : 2,
@@ -8177,16 +8534,16 @@ function TextArea(props) {
8177
8534
  } = props;
8178
8535
  const [localValue, setLocalValue] = hooks.useState(value);
8179
8536
  const ref = useShowEntryEvent(id);
8537
+ const onInput = hooks.useCallback(newValue => {
8538
+ const newModelValue = newValue === '' ? undefined : newValue;
8539
+ commitValue(newModelValue);
8540
+ }, [commitValue]);
8180
8541
  const visible = useElementVisible(ref.current);
8181
8542
 
8182
8543
  /**
8183
8544
  * @type { import('min-dash').DebouncedFunction }
8184
8545
  */
8185
- const handleInputCallback = useDebounce(onInput, debounce);
8186
- const handleInput = newValue => {
8187
- const newModelValue = newValue === '' ? undefined : newValue;
8188
- handleInputCallback(newModelValue);
8189
- };
8546
+ const handleInput = useDebounce(onInput, debounce);
8190
8547
  const handleLocalInput = e => {
8191
8548
  autoResize && resizeToContents(e.target);
8192
8549
  if (e.target.value === localValue) {
@@ -8199,11 +8556,40 @@ function TextArea(props) {
8199
8556
  const trimmedValue = e.target.value.trim();
8200
8557
 
8201
8558
  // trim and commit on blur
8559
+ handleInput.cancel?.();
8202
8560
  onInput(trimmedValue);
8561
+ setLocalValue(trimmedValue);
8203
8562
  if (onBlur) {
8204
8563
  onBlur(e);
8205
8564
  }
8206
8565
  };
8566
+ const handleOnPaste = e => {
8567
+ const input = e.target;
8568
+ const isFieldEmpty = !input.value;
8569
+ const isAllSelected = input.selectionStart === 0 && input.selectionEnd === input.value.length;
8570
+
8571
+ // Trim and handle paste if field is empty or all content is selected
8572
+ if (isFieldEmpty || isAllSelected) {
8573
+ const trimmedValue = e.clipboardData.getData('text').trim();
8574
+ setLocalValue(trimmedValue);
8575
+ handleInput(trimmedValue);
8576
+ if (onPaste) {
8577
+ onPaste(e);
8578
+ }
8579
+ e.preventDefault();
8580
+ return;
8581
+ }
8582
+
8583
+ // Allow default paste behavior for normal text editing
8584
+ if (onPaste) {
8585
+ onPaste(e);
8586
+ }
8587
+ };
8588
+ const handleOnKeyDown = e => {
8589
+ if (isCmdWithChar(e)) {
8590
+ handleInput.flush?.();
8591
+ }
8592
+ };
8207
8593
  hooks.useLayoutEffect(() => {
8208
8594
  autoResize && resizeToContents(ref.current);
8209
8595
  }, []);
@@ -8235,7 +8621,9 @@ function TextArea(props) {
8235
8621
  class: classnames('bio-properties-panel-input', monospace ? 'bio-properties-panel-input-monospace' : '', autoResize ? 'auto-resize' : ''),
8236
8622
  onInput: handleLocalInput,
8237
8623
  onFocus: onFocus,
8624
+ onKeyDown: handleOnKeyDown,
8238
8625
  onBlur: handleOnBlur,
8626
+ onPaste: handleOnPaste,
8239
8627
  placeholder: placeholder,
8240
8628
  rows: rows,
8241
8629
  value: localValue,
@@ -8256,6 +8644,7 @@ function TextArea(props) {
8256
8644
  * @param {Function} props.setValue
8257
8645
  * @param {Function} props.onFocus
8258
8646
  * @param {Function} props.onBlur
8647
+ * @param {Function} props.onPaste
8259
8648
  * @param {number} props.rows
8260
8649
  * @param {boolean} props.monospace
8261
8650
  * @param {Function} [props.validate]
@@ -8276,6 +8665,7 @@ function TextAreaEntry(props) {
8276
8665
  validate,
8277
8666
  onFocus,
8278
8667
  onBlur,
8668
+ onPaste,
8279
8669
  placeholder,
8280
8670
  autoResize,
8281
8671
  tooltip
@@ -8311,6 +8701,7 @@ function TextAreaEntry(props) {
8311
8701
  onInput: onInput,
8312
8702
  onFocus: onFocus,
8313
8703
  onBlur: onBlur,
8704
+ onPaste: onPaste,
8314
8705
  rows: rows,
8315
8706
  debounce: debounce,
8316
8707
  monospace: monospace,
@@ -8344,32 +8735,57 @@ function Textfield(props) {
8344
8735
  disabled = false,
8345
8736
  id,
8346
8737
  label,
8347
- onInput,
8738
+ onInput: commitValue,
8348
8739
  onFocus,
8349
8740
  onBlur,
8741
+ onPaste,
8350
8742
  placeholder,
8351
8743
  value = '',
8352
8744
  tooltip
8353
8745
  } = props;
8354
8746
  const [localValue, setLocalValue] = hooks.useState(value || '');
8355
8747
  const ref = useShowEntryEvent(id);
8748
+ const onInput = hooks.useCallback(newValue => {
8749
+ const newModelValue = newValue === '' ? undefined : newValue;
8750
+ commitValue(newModelValue);
8751
+ }, [commitValue]);
8356
8752
 
8357
8753
  /**
8358
8754
  * @type { import('min-dash').DebouncedFunction }
8359
8755
  */
8360
- const handleInputCallback = useDebounce(onInput, debounce);
8756
+ const handleInput = useDebounce(onInput, debounce);
8361
8757
  const handleOnBlur = e => {
8362
8758
  const trimmedValue = e.target.value.trim();
8363
8759
 
8364
8760
  // trim and commit on blur
8761
+ handleInput.cancel?.();
8365
8762
  onInput(trimmedValue);
8763
+ setLocalValue(trimmedValue);
8366
8764
  if (onBlur) {
8367
8765
  onBlur(e);
8368
8766
  }
8369
8767
  };
8370
- const handleInput = newValue => {
8371
- const newModelValue = newValue === '' ? undefined : newValue;
8372
- handleInputCallback(newModelValue);
8768
+ const handleOnPaste = e => {
8769
+ const input = e.target;
8770
+ const isFieldEmpty = !input.value;
8771
+ const isAllSelected = input.selectionStart === 0 && input.selectionEnd === input.value.length;
8772
+
8773
+ // Trim and handle paste if field is empty or all content is selected (overwrite)
8774
+ if (isFieldEmpty || isAllSelected) {
8775
+ const trimmedValue = e.clipboardData.getData('text').trim();
8776
+ setLocalValue(trimmedValue);
8777
+ handleInput(trimmedValue);
8778
+ if (onPaste) {
8779
+ onPaste(e);
8780
+ }
8781
+ e.preventDefault();
8782
+ return;
8783
+ }
8784
+
8785
+ // Allow default paste behavior for normal text editing
8786
+ if (onPaste) {
8787
+ onPaste(e);
8788
+ }
8373
8789
  };
8374
8790
  const handleLocalInput = e => {
8375
8791
  if (e.target.value === localValue) {
@@ -8384,6 +8800,11 @@ function Textfield(props) {
8384
8800
  }
8385
8801
  setLocalValue(value);
8386
8802
  }, [value]);
8803
+ const handleOnKeyDown = e => {
8804
+ if (isCmdWithChar(e)) {
8805
+ handleInput.flush?.();
8806
+ }
8807
+ };
8387
8808
  return jsxRuntime.jsxs("div", {
8388
8809
  class: "bio-properties-panel-textfield",
8389
8810
  children: [jsxRuntime.jsx("label", {
@@ -8406,7 +8827,9 @@ function Textfield(props) {
8406
8827
  class: "bio-properties-panel-input",
8407
8828
  onInput: handleLocalInput,
8408
8829
  onFocus: onFocus,
8830
+ onKeyDown: handleOnKeyDown,
8409
8831
  onBlur: handleOnBlur,
8832
+ onPaste: handleOnPaste,
8410
8833
  placeholder: placeholder,
8411
8834
  value: localValue
8412
8835
  })]
@@ -8441,6 +8864,7 @@ function TextfieldEntry(props) {
8441
8864
  validate,
8442
8865
  onFocus,
8443
8866
  onBlur,
8867
+ onPaste,
8444
8868
  placeholder,
8445
8869
  tooltip
8446
8870
  } = props;
@@ -8476,6 +8900,7 @@ function TextfieldEntry(props) {
8476
8900
  onInput: onInput,
8477
8901
  onFocus: onFocus,
8478
8902
  onBlur: onBlur,
8903
+ onPaste: onPaste,
8479
8904
  placeholder: placeholder,
8480
8905
  value: value,
8481
8906
  tooltip: tooltip,
@@ -8745,6 +9170,7 @@ function Title(props) {
8745
9170
  class: "bio-properties-panel-popup__title",
8746
9171
  children: title
8747
9172
  }), children, showCloseButton && jsxRuntime.jsx("button", {
9173
+ type: "button",
8748
9174
  title: closeButtonTooltip,
8749
9175
  class: "bio-properties-panel-popup__close",
8750
9176
  onClick: onClose,
@@ -8786,6 +9212,25 @@ function cancel(event) {
8786
9212
  event.preventDefault();
8787
9213
  event.stopPropagation();
8788
9214
  }
9215
+
9216
+ /**
9217
+ * @typedef {Object} FeelPopupProps
9218
+ * @property {string} entryId
9219
+ * @property {Function} onInput
9220
+ * @property {Function} onClose
9221
+ * @property {string} title
9222
+ * @property {'feel'|'feelers'} type
9223
+ * @property {string} value
9224
+ * @property {Array} [links]
9225
+ * @property {Array|Object} [variables]
9226
+ * @property {Object} [position]
9227
+ * @property {string} [hostLanguage]
9228
+ * @property {boolean} [singleLine]
9229
+ * @property {HTMLElement} [sourceElement]
9230
+ * @property {HTMLElement|string} [tooltipContainer]
9231
+ * @property {Object} [eventBus]
9232
+ */
9233
+
8789
9234
  const FEEL_POPUP_WIDTH = 700;
8790
9235
  const FEEL_POPUP_HEIGHT = 250;
8791
9236
 
@@ -13498,7 +13943,7 @@ function CustomPropertiesGroup(field, editField) {
13498
13943
  event.stopPropagation();
13499
13944
  return editField(field, ['properties'], removeKey(properties, key));
13500
13945
  };
13501
- const id = `property-${field.id}-${index}`;
13946
+ const id = `property-${index}`;
13502
13947
  return {
13503
13948
  autoFocusEntry: id + '-key',
13504
13949
  entries: CustomValueEntry({
@@ -13880,7 +14325,7 @@ const RepeatRenderModule = {
13880
14325
  repeatRenderManager: ['type', EditorRepeatRenderManager]
13881
14326
  };
13882
14327
 
13883
- const ids = new Ids([32, 36, 1]);
14328
+ const ids = new ids$1.Ids([32, 36, 1]);
13884
14329
 
13885
14330
  /**
13886
14331
  * @typedef { import('./types').Injector } Injector