@bpmn-io/form-js-editor 1.18.0 → 1.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/form-js-editor.css +6 -0
- package/dist/assets/properties-panel.css +6 -0
- package/dist/index.cjs +386 -64
- package/dist/index.cjs.map +1 -1
- package/dist/index.es.js +386 -64
- package/dist/index.es.js.map +1 -1
- package/package.json +7 -7
package/dist/index.es.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import Ids from 'ids';
|
|
1
|
+
import { Ids } from 'ids';
|
|
2
2
|
import { FormFieldRegistry as FormFieldRegistry$1, iconsByType, Label as Label$3, IFrame, Text as Text$1, Html, Table, ExpressionField, DocumentPreview, FormFields, sanitizeImageSource, getAncestryList, FormContext, FormRenderContext, FormComponent, getScrollContainer, FieldFactory, FormLayouter, PathRegistry, Importer, FeelExpressionLanguage, OPTIONS_SOURCES, OPTIONS_SOURCES_PATHS, clone, runRecursively, getSchemaVariables, DATETIME_SUBTYPES, DATE_LABEL_PATH, TIME_LABEL_PATH, TEXT_VIEW_DEFAULT_TEXT, TIME_USE24H_PATH, DATETIME_SUBTYPE_PATH, DATETIME_SUBTYPES_LABELS, TIME_INTERVAL_PATH, TIME_SERIALISING_FORMAT_PATH, DATE_DISALLOW_PAST_PATH, TIME_SERIALISING_FORMATS, TIME_SERIALISINGFORMAT_LABELS, getOptionsSource, OPTIONS_SOURCES_DEFAULTS, OPTIONS_SOURCES_LABELS, SECURITY_ATTRIBUTES_DEFINITIONS, createFormContainer, createInjector, MarkdownRendererModule, schemaVersion } from '@bpmn-io/form-js-viewer';
|
|
3
3
|
export { schemaVersion } from '@bpmn-io/form-js-viewer';
|
|
4
4
|
import { isArray, isFunction, isNumber, bind, assign, debounce, forEach, isString, uniqueBy, isObject, get, isDefined, set as set$1, reduce, isNil, without, has } from 'min-dash';
|
|
@@ -13,7 +13,7 @@ import { classes, query, event, domify } from 'min-dom';
|
|
|
13
13
|
import { arrayMoveMutable } from 'array-move';
|
|
14
14
|
import { FeelersEditor } from 'feelers';
|
|
15
15
|
import Editor from '@bpmn-io/feel-editor';
|
|
16
|
-
import {
|
|
16
|
+
import { EditorView, lineNumbers } from '@codemirror/view';
|
|
17
17
|
import * as focusTrap from 'focus-trap';
|
|
18
18
|
import Big from 'big.js';
|
|
19
19
|
|
|
@@ -2870,11 +2870,35 @@ EditorActions.prototype._registerDefaultActions = function (injector) {
|
|
|
2870
2870
|
}
|
|
2871
2871
|
});
|
|
2872
2872
|
}
|
|
2873
|
+
if (copyPaste && selection) {
|
|
2874
|
+
this.register('duplicate', function () {
|
|
2875
|
+
var selectedElements = selection.get();
|
|
2876
|
+
if (selectedElements.length) {
|
|
2877
|
+
return copyPaste.duplicate(selectedElements);
|
|
2878
|
+
}
|
|
2879
|
+
});
|
|
2880
|
+
}
|
|
2873
2881
|
if (copyPaste) {
|
|
2874
2882
|
this.register('paste', function () {
|
|
2875
2883
|
copyPaste.paste();
|
|
2876
2884
|
});
|
|
2877
2885
|
}
|
|
2886
|
+
if (copyPaste && selection && rules) {
|
|
2887
|
+
this.register('cut', function () {
|
|
2888
|
+
var selectedElements = selection.get();
|
|
2889
|
+
if (!selectedElements.length) {
|
|
2890
|
+
return;
|
|
2891
|
+
}
|
|
2892
|
+
var allowed = rules.allowed('elements.delete', {
|
|
2893
|
+
elements: selectedElements
|
|
2894
|
+
});
|
|
2895
|
+
if (allowed === false) {
|
|
2896
|
+
return;
|
|
2897
|
+
}
|
|
2898
|
+
var cuttableElements = isArray(allowed) ? allowed : selectedElements;
|
|
2899
|
+
return copyPaste.cut(cuttableElements.slice());
|
|
2900
|
+
});
|
|
2901
|
+
}
|
|
2878
2902
|
if (zoomScroll) {
|
|
2879
2903
|
this.register('stepZoom', function (opts) {
|
|
2880
2904
|
zoomScroll.stepZoom(opts.value);
|
|
@@ -3093,6 +3117,8 @@ const EditorExpressionLanguageModule = {
|
|
|
3093
3117
|
|
|
3094
3118
|
var KEYS_COPY = ['c', 'C'];
|
|
3095
3119
|
var KEYS_PASTE = ['v', 'V'];
|
|
3120
|
+
var KEYS_DUPLICATE = ['d', 'D'];
|
|
3121
|
+
var KEYS_CUT = ['x', 'X'];
|
|
3096
3122
|
var KEYS_REDO = ['y', 'Y'];
|
|
3097
3123
|
var KEYS_UNDO = ['z', 'Z'];
|
|
3098
3124
|
|
|
@@ -3108,7 +3134,7 @@ function hasModifier(event) {
|
|
|
3108
3134
|
* @param {KeyboardEvent} event
|
|
3109
3135
|
* @return {boolean}
|
|
3110
3136
|
*/
|
|
3111
|
-
function isCmd(event) {
|
|
3137
|
+
function isCmd$1(event) {
|
|
3112
3138
|
// ensure we don't react to AltGr
|
|
3113
3139
|
// (mapped to CTRL + ALT)
|
|
3114
3140
|
if (event.altKey) {
|
|
@@ -3140,28 +3166,42 @@ function isShift(event) {
|
|
|
3140
3166
|
* @param {KeyboardEvent} event
|
|
3141
3167
|
*/
|
|
3142
3168
|
function isCopy(event) {
|
|
3143
|
-
return isCmd(event) && isKey(KEYS_COPY, event);
|
|
3169
|
+
return isCmd$1(event) && isKey(KEYS_COPY, event);
|
|
3144
3170
|
}
|
|
3145
3171
|
|
|
3146
3172
|
/**
|
|
3147
3173
|
* @param {KeyboardEvent} event
|
|
3148
3174
|
*/
|
|
3149
3175
|
function isPaste(event) {
|
|
3150
|
-
return isCmd(event) && isKey(KEYS_PASTE, event);
|
|
3176
|
+
return isCmd$1(event) && isKey(KEYS_PASTE, event);
|
|
3177
|
+
}
|
|
3178
|
+
|
|
3179
|
+
/**
|
|
3180
|
+
* @param {KeyboardEvent} event
|
|
3181
|
+
*/
|
|
3182
|
+
function isDuplicate(event) {
|
|
3183
|
+
return isCmd$1(event) && isKey(KEYS_DUPLICATE, event);
|
|
3184
|
+
}
|
|
3185
|
+
|
|
3186
|
+
/**
|
|
3187
|
+
* @param {KeyboardEvent} event
|
|
3188
|
+
*/
|
|
3189
|
+
function isCut(event) {
|
|
3190
|
+
return isCmd$1(event) && isKey(KEYS_CUT, event);
|
|
3151
3191
|
}
|
|
3152
3192
|
|
|
3153
3193
|
/**
|
|
3154
3194
|
* @param {KeyboardEvent} event
|
|
3155
3195
|
*/
|
|
3156
3196
|
function isUndo(event) {
|
|
3157
|
-
return isCmd(event) && !isShift(event) && isKey(KEYS_UNDO, event);
|
|
3197
|
+
return isCmd$1(event) && !isShift(event) && isKey(KEYS_UNDO, event);
|
|
3158
3198
|
}
|
|
3159
3199
|
|
|
3160
3200
|
/**
|
|
3161
3201
|
* @param {KeyboardEvent} event
|
|
3162
3202
|
*/
|
|
3163
3203
|
function isRedo(event) {
|
|
3164
|
-
return isCmd(event) && (isKey(KEYS_REDO, event) || isKey(KEYS_UNDO, event) && isShift(event));
|
|
3204
|
+
return isCmd$1(event) && (isKey(KEYS_REDO, event) || isKey(KEYS_UNDO, event) && isShift(event));
|
|
3165
3205
|
}
|
|
3166
3206
|
|
|
3167
3207
|
/**
|
|
@@ -3330,7 +3370,7 @@ Keyboard.prototype.removeListener = function (listener, type) {
|
|
|
3330
3370
|
this._eventBus.off(type || KEYDOWN_EVENT, listener);
|
|
3331
3371
|
};
|
|
3332
3372
|
Keyboard.prototype.hasModifier = hasModifier;
|
|
3333
|
-
Keyboard.prototype.isCmd = isCmd;
|
|
3373
|
+
Keyboard.prototype.isCmd = isCmd$1;
|
|
3334
3374
|
Keyboard.prototype.isShift = isShift;
|
|
3335
3375
|
Keyboard.prototype.isKey = isKey;
|
|
3336
3376
|
|
|
@@ -3415,6 +3455,26 @@ KeyboardBindings.prototype.registerBindings = function (keyboard, editorActions)
|
|
|
3415
3455
|
}
|
|
3416
3456
|
});
|
|
3417
3457
|
|
|
3458
|
+
// duplicate
|
|
3459
|
+
// CTRL/CMD + D
|
|
3460
|
+
addListener('duplicate', function (context) {
|
|
3461
|
+
var event = context.keyEvent;
|
|
3462
|
+
if (isDuplicate(event)) {
|
|
3463
|
+
editorActions.trigger('duplicate');
|
|
3464
|
+
return true;
|
|
3465
|
+
}
|
|
3466
|
+
});
|
|
3467
|
+
|
|
3468
|
+
// cut
|
|
3469
|
+
// CTRL/CMD + X
|
|
3470
|
+
addListener('cut', function (context) {
|
|
3471
|
+
var event = context.keyEvent;
|
|
3472
|
+
if (isCut(event)) {
|
|
3473
|
+
editorActions.trigger('cut');
|
|
3474
|
+
return true;
|
|
3475
|
+
}
|
|
3476
|
+
});
|
|
3477
|
+
|
|
3418
3478
|
// zoom in one step
|
|
3419
3479
|
// CTRL/CMD + +
|
|
3420
3480
|
addListener('stepZoom', function (context) {
|
|
@@ -3422,7 +3482,7 @@ KeyboardBindings.prototype.registerBindings = function (keyboard, editorActions)
|
|
|
3422
3482
|
|
|
3423
3483
|
// quirk: it has to be triggered by `=` as well to work on international keyboard layout
|
|
3424
3484
|
// cf: https://github.com/bpmn-io/bpmn-js/issues/1362#issuecomment-722989754
|
|
3425
|
-
if (isKey(['+', 'Add', '='], event) && isCmd(event)) {
|
|
3485
|
+
if (isKey(['+', 'Add', '='], event) && isCmd$1(event)) {
|
|
3426
3486
|
editorActions.trigger('stepZoom', {
|
|
3427
3487
|
value: 1
|
|
3428
3488
|
});
|
|
@@ -3434,7 +3494,7 @@ KeyboardBindings.prototype.registerBindings = function (keyboard, editorActions)
|
|
|
3434
3494
|
// CTRL + -
|
|
3435
3495
|
addListener('stepZoom', function (context) {
|
|
3436
3496
|
var event = context.keyEvent;
|
|
3437
|
-
if (isKey(['-', 'Subtract'], event) && isCmd(event)) {
|
|
3497
|
+
if (isKey(['-', 'Subtract'], event) && isCmd$1(event)) {
|
|
3438
3498
|
editorActions.trigger('stepZoom', {
|
|
3439
3499
|
value: -1
|
|
3440
3500
|
});
|
|
@@ -3446,7 +3506,7 @@ KeyboardBindings.prototype.registerBindings = function (keyboard, editorActions)
|
|
|
3446
3506
|
// CTRL + 0
|
|
3447
3507
|
addListener('zoom', function (context) {
|
|
3448
3508
|
var event = context.keyEvent;
|
|
3449
|
-
if (isKey('0', event) && isCmd(event)) {
|
|
3509
|
+
if (isKey('0', event) && isCmd$1(event)) {
|
|
3450
3510
|
editorActions.trigger('zoom', {
|
|
3451
3511
|
value: 1
|
|
3452
3512
|
});
|
|
@@ -5453,6 +5513,21 @@ OpenPopupIcon.defaultProps = {
|
|
|
5453
5513
|
xmlns: "http://www.w3.org/2000/svg",
|
|
5454
5514
|
viewBox: "0 0 16 16"
|
|
5455
5515
|
};
|
|
5516
|
+
|
|
5517
|
+
/**
|
|
5518
|
+
* @typedef { {
|
|
5519
|
+
* getElementLabel: (element: object) => string,
|
|
5520
|
+
* getTypeLabel: (element: object) => string,
|
|
5521
|
+
* getElementIcon: (element: object) => import('preact').Component,
|
|
5522
|
+
* getDocumentationRef: (element: object) => string
|
|
5523
|
+
* } } HeaderProvider
|
|
5524
|
+
*/
|
|
5525
|
+
|
|
5526
|
+
/**
|
|
5527
|
+
* @param {Object} props
|
|
5528
|
+
* @param {Object} props.element,
|
|
5529
|
+
* @param {HeaderProvider} props.headerProvider
|
|
5530
|
+
*/
|
|
5456
5531
|
function Header(props) {
|
|
5457
5532
|
const {
|
|
5458
5533
|
element,
|
|
@@ -5480,11 +5555,9 @@ function Header(props) {
|
|
|
5480
5555
|
}), jsxs("div", {
|
|
5481
5556
|
class: "bio-properties-panel-header-labels",
|
|
5482
5557
|
children: [jsx("div", {
|
|
5483
|
-
title: type,
|
|
5484
5558
|
class: "bio-properties-panel-header-type",
|
|
5485
5559
|
children: type
|
|
5486
5560
|
}), label ? jsx("div", {
|
|
5487
|
-
title: label,
|
|
5488
5561
|
class: "bio-properties-panel-header-label",
|
|
5489
5562
|
children: label
|
|
5490
5563
|
}) : null]
|
|
@@ -5572,6 +5645,27 @@ function useTooltipContext(id, element) {
|
|
|
5572
5645
|
} = useContext(TooltipContext);
|
|
5573
5646
|
return getTooltipForId(id, element);
|
|
5574
5647
|
}
|
|
5648
|
+
|
|
5649
|
+
/**
|
|
5650
|
+
* @typedef {Object} TooltipProps
|
|
5651
|
+
* @property {Object} [parent] - Parent element ref for portal rendering
|
|
5652
|
+
* @property {String} [direction='right'] - Tooltip direction ( 'right', 'top')
|
|
5653
|
+
* @property {String} [position] - Custom CSS position override
|
|
5654
|
+
* @property {Number} [showDelay=250] - Delay in ms before showing tooltip on hover
|
|
5655
|
+
* @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
|
|
5656
|
+
* @property {*} [children] - Child elements to render inside the tooltip wrapper
|
|
5657
|
+
*/
|
|
5658
|
+
|
|
5659
|
+
/**
|
|
5660
|
+
* Tooltip wrapper that provides context-based tooltip content lookup.
|
|
5661
|
+
* All props are forwarded to the underlying Tooltip component.
|
|
5662
|
+
*
|
|
5663
|
+
* @param {TooltipProps & {
|
|
5664
|
+
* forId: String,
|
|
5665
|
+
* value?: String|Object,
|
|
5666
|
+
* element?: Object
|
|
5667
|
+
* }} props - Shared tooltip props plus wrapper-specific ones
|
|
5668
|
+
*/
|
|
5575
5669
|
function TooltipWrapper(props) {
|
|
5576
5670
|
const {
|
|
5577
5671
|
forId,
|
|
@@ -5588,35 +5682,77 @@ function TooltipWrapper(props) {
|
|
|
5588
5682
|
forId: `bio-properties-panel-${forId}`
|
|
5589
5683
|
});
|
|
5590
5684
|
}
|
|
5685
|
+
|
|
5686
|
+
/**
|
|
5687
|
+
* @param {TooltipProps & {
|
|
5688
|
+
* forId: String,
|
|
5689
|
+
* value: String|Object
|
|
5690
|
+
* }} props
|
|
5691
|
+
*/
|
|
5591
5692
|
function Tooltip(props) {
|
|
5592
5693
|
const {
|
|
5593
5694
|
forId,
|
|
5594
5695
|
value,
|
|
5595
5696
|
parent,
|
|
5596
5697
|
direction = 'right',
|
|
5597
|
-
position
|
|
5698
|
+
position,
|
|
5699
|
+
showDelay = 250,
|
|
5700
|
+
hideDelay = 250
|
|
5598
5701
|
} = props;
|
|
5599
5702
|
const [visible, setVisible] = useState(false);
|
|
5600
|
-
|
|
5601
|
-
|
|
5602
|
-
const SHOW_DELAY = 200;
|
|
5603
|
-
let timeout = null;
|
|
5703
|
+
const showTimeoutRef = useRef(null);
|
|
5704
|
+
const hideTimeoutRef = useRef(null);
|
|
5604
5705
|
const wrapperRef = useRef(null);
|
|
5605
5706
|
const tooltipRef = useRef(null);
|
|
5606
5707
|
const show = (_, delay) => {
|
|
5708
|
+
clearTimeout(showTimeoutRef.current);
|
|
5709
|
+
clearTimeout(hideTimeoutRef.current);
|
|
5607
5710
|
if (visible) return;
|
|
5608
5711
|
if (delay) {
|
|
5609
|
-
|
|
5712
|
+
showTimeoutRef.current = setTimeout(() => {
|
|
5610
5713
|
setVisible(true);
|
|
5611
|
-
},
|
|
5714
|
+
}, showDelay);
|
|
5612
5715
|
} else {
|
|
5613
5716
|
setVisible(true);
|
|
5614
5717
|
}
|
|
5615
5718
|
};
|
|
5616
|
-
const
|
|
5617
|
-
|
|
5618
|
-
|
|
5719
|
+
const handleWrapperMouseEnter = e => {
|
|
5720
|
+
show(e, true);
|
|
5721
|
+
};
|
|
5722
|
+
const hide = (delay = false) => {
|
|
5723
|
+
clearTimeout(showTimeoutRef.current);
|
|
5724
|
+
clearTimeout(hideTimeoutRef.current);
|
|
5725
|
+
if (delay) {
|
|
5726
|
+
hideTimeoutRef.current = setTimeout(() => {
|
|
5727
|
+
setVisible(false);
|
|
5728
|
+
}, hideDelay);
|
|
5729
|
+
} else {
|
|
5730
|
+
setVisible(false);
|
|
5731
|
+
}
|
|
5619
5732
|
};
|
|
5733
|
+
|
|
5734
|
+
// Cleanup timeouts on unmount
|
|
5735
|
+
useEffect(() => {
|
|
5736
|
+
return () => {
|
|
5737
|
+
clearTimeout(showTimeoutRef.current);
|
|
5738
|
+
clearTimeout(hideTimeoutRef.current);
|
|
5739
|
+
};
|
|
5740
|
+
}, []);
|
|
5741
|
+
|
|
5742
|
+
// Handle click outside to close tooltip for non-focusable elements
|
|
5743
|
+
useEffect(() => {
|
|
5744
|
+
if (!visible) return;
|
|
5745
|
+
const handleClickOutside = e => {
|
|
5746
|
+
// If clicking outside both the wrapper and tooltip, hide it
|
|
5747
|
+
if (wrapperRef.current && !wrapperRef.current.contains(e.target) && tooltipRef.current && !tooltipRef.current.contains(e.target)) {
|
|
5748
|
+
hide(false);
|
|
5749
|
+
}
|
|
5750
|
+
};
|
|
5751
|
+
document.addEventListener('mousedown', handleClickOutside);
|
|
5752
|
+
return () => {
|
|
5753
|
+
document.removeEventListener('mousedown', handleClickOutside);
|
|
5754
|
+
};
|
|
5755
|
+
}, [visible, hide]);
|
|
5620
5756
|
const handleMouseLeave = ({
|
|
5621
5757
|
relatedTarget
|
|
5622
5758
|
}) => {
|
|
@@ -5624,23 +5760,32 @@ function Tooltip(props) {
|
|
|
5624
5760
|
if (relatedTarget === wrapperRef.current || relatedTarget === tooltipRef.current || relatedTarget?.parentElement === tooltipRef.current) {
|
|
5625
5761
|
return;
|
|
5626
5762
|
}
|
|
5627
|
-
|
|
5763
|
+
const selection = window.getSelection();
|
|
5764
|
+
if (selection && selection.toString().length > 0) {
|
|
5765
|
+
// Check if selection is within tooltip content
|
|
5766
|
+
const selectionRange = selection.getRangeAt(0);
|
|
5767
|
+
if (tooltipRef.current?.contains(selectionRange.commonAncestorContainer) || tooltipRef.current?.contains(selection.anchorNode) || tooltipRef.current?.contains(selection.focusNode)) {
|
|
5768
|
+
return; // Keep tooltip open during text selection
|
|
5769
|
+
}
|
|
5770
|
+
}
|
|
5771
|
+
hide(true);
|
|
5772
|
+
};
|
|
5773
|
+
const handleTooltipMouseEnter = () => {
|
|
5774
|
+
clearTimeout(hideTimeoutRef.current);
|
|
5628
5775
|
};
|
|
5629
5776
|
const handleFocusOut = e => {
|
|
5630
5777
|
const {
|
|
5631
|
-
|
|
5778
|
+
relatedTarget
|
|
5632
5779
|
} = e;
|
|
5633
5780
|
|
|
5634
|
-
// Don't hide
|
|
5635
|
-
|
|
5636
|
-
if (target === wrapperRef.current && isHovered) {
|
|
5637
|
-
e.stopPropagation();
|
|
5781
|
+
// Don't hide if focus moved to the tooltip or another element within the wrapper
|
|
5782
|
+
if (tooltipRef.current?.contains(relatedTarget) || wrapperRef.current?.contains(relatedTarget)) {
|
|
5638
5783
|
return;
|
|
5639
5784
|
}
|
|
5640
|
-
hide();
|
|
5785
|
+
hide(false);
|
|
5641
5786
|
};
|
|
5642
5787
|
const hideTooltipViaEscape = e => {
|
|
5643
|
-
e.code === 'Escape' && hide();
|
|
5788
|
+
e.code === 'Escape' && hide(false);
|
|
5644
5789
|
};
|
|
5645
5790
|
const renderTooltip = () => {
|
|
5646
5791
|
return jsxs("div", {
|
|
@@ -5651,6 +5796,7 @@ function Tooltip(props) {
|
|
|
5651
5796
|
style: position || getTooltipPosition(wrapperRef.current),
|
|
5652
5797
|
ref: tooltipRef,
|
|
5653
5798
|
onClick: e => e.stopPropagation(),
|
|
5799
|
+
onMouseEnter: handleTooltipMouseEnter,
|
|
5654
5800
|
onMouseLeave: handleMouseLeave,
|
|
5655
5801
|
children: [jsx("div", {
|
|
5656
5802
|
class: "bio-properties-panel-tooltip-content",
|
|
@@ -5664,7 +5810,7 @@ function Tooltip(props) {
|
|
|
5664
5810
|
class: "bio-properties-panel-tooltip-wrapper",
|
|
5665
5811
|
tabIndex: "0",
|
|
5666
5812
|
ref: wrapperRef,
|
|
5667
|
-
onMouseEnter:
|
|
5813
|
+
onMouseEnter: handleWrapperMouseEnter,
|
|
5668
5814
|
onMouseLeave: handleMouseLeave,
|
|
5669
5815
|
onFocus: show,
|
|
5670
5816
|
onBlur: handleFocusOut,
|
|
@@ -5942,6 +6088,10 @@ function useElementVisible(element) {
|
|
|
5942
6088
|
}, [element, visible]);
|
|
5943
6089
|
return visible;
|
|
5944
6090
|
}
|
|
6091
|
+
|
|
6092
|
+
/**
|
|
6093
|
+
* @param {import('../PropertiesPanel').GroupDefinition} props
|
|
6094
|
+
*/
|
|
5945
6095
|
function Group(props) {
|
|
5946
6096
|
const {
|
|
5947
6097
|
element,
|
|
@@ -5996,8 +6146,6 @@ function Group(props) {
|
|
|
5996
6146
|
class: classnames('bio-properties-panel-group-header', edited ? '' : 'empty', open ? 'open' : '', sticky && open ? 'sticky' : ''),
|
|
5997
6147
|
onClick: toggleOpen,
|
|
5998
6148
|
children: [jsx("div", {
|
|
5999
|
-
title: props.tooltip ? null : label,
|
|
6000
|
-
"data-title": label,
|
|
6001
6149
|
class: "bio-properties-panel-group-header-title",
|
|
6002
6150
|
children: jsx(TooltipWrapper, {
|
|
6003
6151
|
value: props.tooltip,
|
|
@@ -6201,9 +6349,11 @@ function PropertiesPanel$1(props) {
|
|
|
6201
6349
|
return get(layout, key, defaultValue);
|
|
6202
6350
|
};
|
|
6203
6351
|
const setLayoutForKey = (key, config) => {
|
|
6204
|
-
|
|
6205
|
-
|
|
6206
|
-
|
|
6352
|
+
setLayout(prevLayout => {
|
|
6353
|
+
const newLayout = assign({}, prevLayout);
|
|
6354
|
+
set$1(newLayout, key, config);
|
|
6355
|
+
return newLayout;
|
|
6356
|
+
});
|
|
6207
6357
|
};
|
|
6208
6358
|
const layoutContext = {
|
|
6209
6359
|
layout,
|
|
@@ -6402,7 +6552,6 @@ function CollapsibleEntry(props) {
|
|
|
6402
6552
|
class: "bio-properties-panel-collapsible-entry-header",
|
|
6403
6553
|
onClick: toggleOpen,
|
|
6404
6554
|
children: [jsx("div", {
|
|
6405
|
-
title: label || placeholderLabel,
|
|
6406
6555
|
class: classnames('bio-properties-panel-collapsible-entry-header-title', !label && 'empty'),
|
|
6407
6556
|
children: label || placeholderLabel
|
|
6408
6557
|
}), jsx("button", {
|
|
@@ -6438,6 +6587,10 @@ function CollapsibleEntry(props) {
|
|
|
6438
6587
|
})]
|
|
6439
6588
|
});
|
|
6440
6589
|
}
|
|
6590
|
+
|
|
6591
|
+
/**
|
|
6592
|
+
* @param {import('../PropertiesPanel').ListItemDefinition} props
|
|
6593
|
+
*/
|
|
6441
6594
|
function ListItem(props) {
|
|
6442
6595
|
const {
|
|
6443
6596
|
autoFocusEntry,
|
|
@@ -6539,8 +6692,6 @@ function ListGroup(props) {
|
|
|
6539
6692
|
class: classnames('bio-properties-panel-group-header', hasItems ? '' : 'empty', hasItems && open ? 'open' : '', sticky && open ? 'sticky' : ''),
|
|
6540
6693
|
onClick: hasItems ? toggleOpen : noop$6,
|
|
6541
6694
|
children: [jsx("div", {
|
|
6542
|
-
title: props.tooltip ? null : label,
|
|
6543
|
-
"data-title": label,
|
|
6544
6695
|
class: "bio-properties-panel-group-header-title",
|
|
6545
6696
|
children: jsx(TooltipWrapper, {
|
|
6546
6697
|
value: props.tooltip,
|
|
@@ -6609,6 +6760,13 @@ function getNewItemIds(newItems, oldItems) {
|
|
|
6609
6760
|
const oldIds = oldItems.map(item => item.id);
|
|
6610
6761
|
return newIds.filter(itemId => !oldIds.includes(itemId));
|
|
6611
6762
|
}
|
|
6763
|
+
|
|
6764
|
+
/**
|
|
6765
|
+
* @param {Object} props
|
|
6766
|
+
* @param {Object} props.element
|
|
6767
|
+
* @param {String} props.forId - id of the entry the description is used for
|
|
6768
|
+
* @param {String} props.value
|
|
6769
|
+
*/
|
|
6612
6770
|
function Description$1(props) {
|
|
6613
6771
|
const {
|
|
6614
6772
|
element,
|
|
@@ -6738,6 +6896,16 @@ function isEdited$8(node) {
|
|
|
6738
6896
|
function prefixId$8(id) {
|
|
6739
6897
|
return `bio-properties-panel-${id}`;
|
|
6740
6898
|
}
|
|
6899
|
+
|
|
6900
|
+
/**
|
|
6901
|
+
* Button to open popups.
|
|
6902
|
+
*
|
|
6903
|
+
* @param {Object} props
|
|
6904
|
+
* @param {Function} props.onClick - Callback to trigger when the button is clicked.
|
|
6905
|
+
* @param {string} [props.title] - Tooltip text for the button.
|
|
6906
|
+
* @param {boolean} [props.disabled] - Whether the button is disabled.
|
|
6907
|
+
* @param {string} [props.className] - Additional class names for the button.
|
|
6908
|
+
*/
|
|
6741
6909
|
function OpenPopupButton({
|
|
6742
6910
|
onClick,
|
|
6743
6911
|
title = 'Open pop-up editor'
|
|
@@ -6881,6 +7049,7 @@ const FeelEditor = forwardRef((props, ref) => {
|
|
|
6881
7049
|
enableGutters,
|
|
6882
7050
|
value,
|
|
6883
7051
|
onInput,
|
|
7052
|
+
onKeyDown: onKeyDownProp = noop$4,
|
|
6884
7053
|
onFeelToggle = noop$4,
|
|
6885
7054
|
onLint = noop$4,
|
|
6886
7055
|
onOpenPopup = noop$4,
|
|
@@ -6913,6 +7082,8 @@ const FeelEditor = forwardRef((props, ref) => {
|
|
|
6913
7082
|
* - AND the cursor is at the beginning of the input
|
|
6914
7083
|
*/
|
|
6915
7084
|
const onKeyDown = e => {
|
|
7085
|
+
// Call parent onKeyDown handler first
|
|
7086
|
+
onKeyDownProp(e);
|
|
6916
7087
|
if (e.key !== 'Backspace' || !editor) {
|
|
6917
7088
|
return;
|
|
6918
7089
|
}
|
|
@@ -7029,6 +7200,22 @@ function FeelIcon(props) {
|
|
|
7029
7200
|
children: jsx(FeelIcon$1, {})
|
|
7030
7201
|
});
|
|
7031
7202
|
}
|
|
7203
|
+
|
|
7204
|
+
/**
|
|
7205
|
+
* @param {KeyboardEvent} event
|
|
7206
|
+
* @return {boolean}
|
|
7207
|
+
*/
|
|
7208
|
+
function isCmd(event) {
|
|
7209
|
+
// ensure we don't react to AltGr
|
|
7210
|
+
// (mapped to CTRL + ALT)
|
|
7211
|
+
if (event.altKey) {
|
|
7212
|
+
return false;
|
|
7213
|
+
}
|
|
7214
|
+
return event.ctrlKey || event.metaKey;
|
|
7215
|
+
}
|
|
7216
|
+
function isCmdWithChar(event) {
|
|
7217
|
+
return isCmd(event) && event.key.length === 1 && /^[a-zA-Z]$/.test(event.key);
|
|
7218
|
+
}
|
|
7032
7219
|
function ToggleSwitch(props) {
|
|
7033
7220
|
const {
|
|
7034
7221
|
id,
|
|
@@ -7340,7 +7527,7 @@ function FeelTextfield(props) {
|
|
|
7340
7527
|
element,
|
|
7341
7528
|
label,
|
|
7342
7529
|
hostLanguage,
|
|
7343
|
-
onInput,
|
|
7530
|
+
onInput: commitValue,
|
|
7344
7531
|
onBlur,
|
|
7345
7532
|
onError,
|
|
7346
7533
|
placeholder,
|
|
@@ -7356,6 +7543,12 @@ function FeelTextfield(props) {
|
|
|
7356
7543
|
const [localValue, setLocalValue] = useState(value);
|
|
7357
7544
|
const editorRef = useShowEntryEvent(id);
|
|
7358
7545
|
const containerRef = useRef();
|
|
7546
|
+
const onInput = useCallback(newValue => {
|
|
7547
|
+
// we don't commit empty FEEL expressions,
|
|
7548
|
+
// but instead serialize them as <undefined>
|
|
7549
|
+
const newModelValue = newValue === '' || newValue === '=' ? undefined : newValue;
|
|
7550
|
+
commitValue(newModelValue);
|
|
7551
|
+
}, [commitValue]);
|
|
7359
7552
|
const feelActive = isString(localValue) && localValue.startsWith('=') || feel === 'required';
|
|
7360
7553
|
const feelOnlyValue = isString(localValue) && localValue.startsWith('=') ? localValue.substring(1) : localValue;
|
|
7361
7554
|
const feelLanguageContext = useContext(FeelLanguageContext);
|
|
@@ -7375,13 +7568,7 @@ function FeelTextfield(props) {
|
|
|
7375
7568
|
/**
|
|
7376
7569
|
* @type { import('min-dash').DebouncedFunction }
|
|
7377
7570
|
*/
|
|
7378
|
-
const
|
|
7379
|
-
const handleInput = newValue => {
|
|
7380
|
-
// we don't commit empty FEEL expressions,
|
|
7381
|
-
// but instead serialize them as <undefined>
|
|
7382
|
-
const newModelValue = newValue === '' || newValue === '=' ? undefined : newValue;
|
|
7383
|
-
handleInputCallback(newModelValue);
|
|
7384
|
-
};
|
|
7571
|
+
const handleInput = useDebounce(onInput, debounce);
|
|
7385
7572
|
const handleFeelToggle = useStaticCallback(() => {
|
|
7386
7573
|
if (feel === 'required') {
|
|
7387
7574
|
return;
|
|
@@ -7394,7 +7581,7 @@ function FeelTextfield(props) {
|
|
|
7394
7581
|
handleInput(feelOnlyValue);
|
|
7395
7582
|
}
|
|
7396
7583
|
});
|
|
7397
|
-
const handleLocalInput = newValue => {
|
|
7584
|
+
const handleLocalInput = (newValue, useDebounce = true) => {
|
|
7398
7585
|
if (feelActive) {
|
|
7399
7586
|
newValue = '=' + newValue;
|
|
7400
7587
|
}
|
|
@@ -7402,23 +7589,33 @@ function FeelTextfield(props) {
|
|
|
7402
7589
|
return;
|
|
7403
7590
|
}
|
|
7404
7591
|
setLocalValue(newValue);
|
|
7405
|
-
|
|
7592
|
+
if (useDebounce) {
|
|
7593
|
+
handleInput(newValue);
|
|
7594
|
+
} else {
|
|
7595
|
+
onInput(newValue);
|
|
7596
|
+
}
|
|
7406
7597
|
if (!feelActive && isString(newValue) && newValue.startsWith('=')) {
|
|
7407
7598
|
// focus is behind `=` sign that will be removed
|
|
7408
7599
|
setFocus(-1);
|
|
7409
7600
|
}
|
|
7410
7601
|
};
|
|
7411
7602
|
const handleOnBlur = e => {
|
|
7603
|
+
handleInput.cancel?.();
|
|
7412
7604
|
if (e.target.type === 'checkbox') {
|
|
7413
7605
|
onInput(e.target.checked);
|
|
7414
7606
|
} else {
|
|
7415
7607
|
const trimmedValue = e.target.value.trim();
|
|
7416
|
-
|
|
7608
|
+
handleLocalInput(trimmedValue, false);
|
|
7417
7609
|
}
|
|
7418
7610
|
if (onBlur) {
|
|
7419
7611
|
onBlur(e);
|
|
7420
7612
|
}
|
|
7421
7613
|
};
|
|
7614
|
+
const handleOnKeyDown = e => {
|
|
7615
|
+
if (isCmdWithChar(e)) {
|
|
7616
|
+
handleInput.flush();
|
|
7617
|
+
}
|
|
7618
|
+
};
|
|
7422
7619
|
const handleLint = useStaticCallback((lint = []) => {
|
|
7423
7620
|
const syntaxError = lint.some(report => report.type === 'Syntax Error');
|
|
7424
7621
|
if (syntaxError) {
|
|
@@ -7485,12 +7682,26 @@ function FeelTextfield(props) {
|
|
|
7485
7682
|
if (feelActive || isPopupOpen) {
|
|
7486
7683
|
return;
|
|
7487
7684
|
}
|
|
7488
|
-
const
|
|
7489
|
-
if (
|
|
7685
|
+
const feelData = event.clipboardData.getData('application/FEEL');
|
|
7686
|
+
if (feelData) {
|
|
7490
7687
|
setTimeout(() => {
|
|
7491
7688
|
handleFeelToggle();
|
|
7492
7689
|
setFocus();
|
|
7493
7690
|
});
|
|
7691
|
+
return;
|
|
7692
|
+
}
|
|
7693
|
+
const input = event.target;
|
|
7694
|
+
const isFieldEmpty = !input.value;
|
|
7695
|
+
const isAllSelected = input.selectionStart === 0 && input.selectionEnd === input.value.length;
|
|
7696
|
+
if (isFieldEmpty || isAllSelected) {
|
|
7697
|
+
const textData = event.clipboardData.getData('text');
|
|
7698
|
+
const trimmedValue = textData.trim();
|
|
7699
|
+
setLocalValue(trimmedValue);
|
|
7700
|
+
handleInput(trimmedValue);
|
|
7701
|
+
if (!feelActive && isString(trimmedValue) && trimmedValue.startsWith('=')) {
|
|
7702
|
+
setFocus(trimmedValue.length - 1);
|
|
7703
|
+
}
|
|
7704
|
+
event.preventDefault();
|
|
7494
7705
|
}
|
|
7495
7706
|
};
|
|
7496
7707
|
containerRef.current.addEventListener('copy', copyHandler);
|
|
@@ -7531,6 +7742,7 @@ function FeelTextfield(props) {
|
|
|
7531
7742
|
}), feelActive ? jsx(FeelEditor, {
|
|
7532
7743
|
name: id,
|
|
7533
7744
|
onInput: handleLocalInput,
|
|
7745
|
+
onKeyDown: handleOnKeyDown,
|
|
7534
7746
|
contentAttributes: {
|
|
7535
7747
|
'id': prefixId$5(id),
|
|
7536
7748
|
'aria-label': label
|
|
@@ -7553,6 +7765,7 @@ function FeelTextfield(props) {
|
|
|
7553
7765
|
...props,
|
|
7554
7766
|
popupOpen: isPopupOpen,
|
|
7555
7767
|
onInput: handleLocalInput,
|
|
7768
|
+
onKeyDown: handleOnKeyDown,
|
|
7556
7769
|
onBlur: handleOnBlur,
|
|
7557
7770
|
contentAttributes: {
|
|
7558
7771
|
'id': prefixId$5(id),
|
|
@@ -7571,6 +7784,7 @@ const OptionalFeelInput = forwardRef((props, ref) => {
|
|
|
7571
7784
|
id,
|
|
7572
7785
|
disabled,
|
|
7573
7786
|
onInput,
|
|
7787
|
+
onKeyDown,
|
|
7574
7788
|
value,
|
|
7575
7789
|
onFocus,
|
|
7576
7790
|
onBlur,
|
|
@@ -7606,6 +7820,7 @@ const OptionalFeelInput = forwardRef((props, ref) => {
|
|
|
7606
7820
|
class: "bio-properties-panel-input",
|
|
7607
7821
|
onInput: e => onInput(e.target.value),
|
|
7608
7822
|
onFocus: onFocus,
|
|
7823
|
+
onKeyDown: onKeyDown,
|
|
7609
7824
|
onBlur: onBlur,
|
|
7610
7825
|
placeholder: placeholder,
|
|
7611
7826
|
value: value || ''
|
|
@@ -7979,6 +8194,25 @@ function isEdited$5(node) {
|
|
|
7979
8194
|
function prefixId$5(id) {
|
|
7980
8195
|
return `bio-properties-panel-${id}`;
|
|
7981
8196
|
}
|
|
8197
|
+
|
|
8198
|
+
/**
|
|
8199
|
+
* @typedef { { value: string, label: string, disabled: boolean, children: { value: string, label: string, disabled: boolean } } } Option
|
|
8200
|
+
*/
|
|
8201
|
+
|
|
8202
|
+
/**
|
|
8203
|
+
* Provides basic select input.
|
|
8204
|
+
*
|
|
8205
|
+
* @param {object} props
|
|
8206
|
+
* @param {string} props.id
|
|
8207
|
+
* @param {string[]} props.path
|
|
8208
|
+
* @param {string} props.label
|
|
8209
|
+
* @param {Function} props.onChange
|
|
8210
|
+
* @param {Function} props.onFocus
|
|
8211
|
+
* @param {Function} props.onBlur
|
|
8212
|
+
* @param {Array<Option>} [props.options]
|
|
8213
|
+
* @param {string} props.value
|
|
8214
|
+
* @param {boolean} [props.disabled]
|
|
8215
|
+
*/
|
|
7982
8216
|
function Select(props) {
|
|
7983
8217
|
const {
|
|
7984
8218
|
id,
|
|
@@ -8144,12 +8378,13 @@ function TextArea(props) {
|
|
|
8144
8378
|
id,
|
|
8145
8379
|
label,
|
|
8146
8380
|
debounce,
|
|
8147
|
-
onInput,
|
|
8381
|
+
onInput: commitValue,
|
|
8148
8382
|
value = '',
|
|
8149
8383
|
disabled,
|
|
8150
8384
|
monospace,
|
|
8151
8385
|
onFocus,
|
|
8152
8386
|
onBlur,
|
|
8387
|
+
onPaste,
|
|
8153
8388
|
autoResize = true,
|
|
8154
8389
|
placeholder,
|
|
8155
8390
|
rows = autoResize ? 1 : 2,
|
|
@@ -8157,16 +8392,16 @@ function TextArea(props) {
|
|
|
8157
8392
|
} = props;
|
|
8158
8393
|
const [localValue, setLocalValue] = useState(value);
|
|
8159
8394
|
const ref = useShowEntryEvent(id);
|
|
8395
|
+
const onInput = useCallback(newValue => {
|
|
8396
|
+
const newModelValue = newValue === '' ? undefined : newValue;
|
|
8397
|
+
commitValue(newModelValue);
|
|
8398
|
+
}, [commitValue]);
|
|
8160
8399
|
const visible = useElementVisible(ref.current);
|
|
8161
8400
|
|
|
8162
8401
|
/**
|
|
8163
8402
|
* @type { import('min-dash').DebouncedFunction }
|
|
8164
8403
|
*/
|
|
8165
|
-
const
|
|
8166
|
-
const handleInput = newValue => {
|
|
8167
|
-
const newModelValue = newValue === '' ? undefined : newValue;
|
|
8168
|
-
handleInputCallback(newModelValue);
|
|
8169
|
-
};
|
|
8404
|
+
const handleInput = useDebounce(onInput, debounce);
|
|
8170
8405
|
const handleLocalInput = e => {
|
|
8171
8406
|
autoResize && resizeToContents(e.target);
|
|
8172
8407
|
if (e.target.value === localValue) {
|
|
@@ -8179,11 +8414,40 @@ function TextArea(props) {
|
|
|
8179
8414
|
const trimmedValue = e.target.value.trim();
|
|
8180
8415
|
|
|
8181
8416
|
// trim and commit on blur
|
|
8417
|
+
handleInput.cancel?.();
|
|
8182
8418
|
onInput(trimmedValue);
|
|
8419
|
+
setLocalValue(trimmedValue);
|
|
8183
8420
|
if (onBlur) {
|
|
8184
8421
|
onBlur(e);
|
|
8185
8422
|
}
|
|
8186
8423
|
};
|
|
8424
|
+
const handleOnPaste = e => {
|
|
8425
|
+
const input = e.target;
|
|
8426
|
+
const isFieldEmpty = !input.value;
|
|
8427
|
+
const isAllSelected = input.selectionStart === 0 && input.selectionEnd === input.value.length;
|
|
8428
|
+
|
|
8429
|
+
// Trim and handle paste if field is empty or all content is selected
|
|
8430
|
+
if (isFieldEmpty || isAllSelected) {
|
|
8431
|
+
const trimmedValue = e.clipboardData.getData('text').trim();
|
|
8432
|
+
setLocalValue(trimmedValue);
|
|
8433
|
+
handleInput(trimmedValue);
|
|
8434
|
+
if (onPaste) {
|
|
8435
|
+
onPaste(e);
|
|
8436
|
+
}
|
|
8437
|
+
e.preventDefault();
|
|
8438
|
+
return;
|
|
8439
|
+
}
|
|
8440
|
+
|
|
8441
|
+
// Allow default paste behavior for normal text editing
|
|
8442
|
+
if (onPaste) {
|
|
8443
|
+
onPaste(e);
|
|
8444
|
+
}
|
|
8445
|
+
};
|
|
8446
|
+
const handleOnKeyDown = e => {
|
|
8447
|
+
if (isCmdWithChar(e)) {
|
|
8448
|
+
handleInput.flush();
|
|
8449
|
+
}
|
|
8450
|
+
};
|
|
8187
8451
|
useLayoutEffect(() => {
|
|
8188
8452
|
autoResize && resizeToContents(ref.current);
|
|
8189
8453
|
}, []);
|
|
@@ -8215,7 +8479,9 @@ function TextArea(props) {
|
|
|
8215
8479
|
class: classnames('bio-properties-panel-input', monospace ? 'bio-properties-panel-input-monospace' : '', autoResize ? 'auto-resize' : ''),
|
|
8216
8480
|
onInput: handleLocalInput,
|
|
8217
8481
|
onFocus: onFocus,
|
|
8482
|
+
onKeyDown: handleOnKeyDown,
|
|
8218
8483
|
onBlur: handleOnBlur,
|
|
8484
|
+
onPaste: handleOnPaste,
|
|
8219
8485
|
placeholder: placeholder,
|
|
8220
8486
|
rows: rows,
|
|
8221
8487
|
value: localValue,
|
|
@@ -8236,6 +8502,7 @@ function TextArea(props) {
|
|
|
8236
8502
|
* @param {Function} props.setValue
|
|
8237
8503
|
* @param {Function} props.onFocus
|
|
8238
8504
|
* @param {Function} props.onBlur
|
|
8505
|
+
* @param {Function} props.onPaste
|
|
8239
8506
|
* @param {number} props.rows
|
|
8240
8507
|
* @param {boolean} props.monospace
|
|
8241
8508
|
* @param {Function} [props.validate]
|
|
@@ -8256,6 +8523,7 @@ function TextAreaEntry(props) {
|
|
|
8256
8523
|
validate,
|
|
8257
8524
|
onFocus,
|
|
8258
8525
|
onBlur,
|
|
8526
|
+
onPaste,
|
|
8259
8527
|
placeholder,
|
|
8260
8528
|
autoResize,
|
|
8261
8529
|
tooltip
|
|
@@ -8291,6 +8559,7 @@ function TextAreaEntry(props) {
|
|
|
8291
8559
|
onInput: onInput,
|
|
8292
8560
|
onFocus: onFocus,
|
|
8293
8561
|
onBlur: onBlur,
|
|
8562
|
+
onPaste: onPaste,
|
|
8294
8563
|
rows: rows,
|
|
8295
8564
|
debounce: debounce,
|
|
8296
8565
|
monospace: monospace,
|
|
@@ -8324,32 +8593,57 @@ function Textfield(props) {
|
|
|
8324
8593
|
disabled = false,
|
|
8325
8594
|
id,
|
|
8326
8595
|
label,
|
|
8327
|
-
onInput,
|
|
8596
|
+
onInput: commitValue,
|
|
8328
8597
|
onFocus,
|
|
8329
8598
|
onBlur,
|
|
8599
|
+
onPaste,
|
|
8330
8600
|
placeholder,
|
|
8331
8601
|
value = '',
|
|
8332
8602
|
tooltip
|
|
8333
8603
|
} = props;
|
|
8334
8604
|
const [localValue, setLocalValue] = useState(value || '');
|
|
8335
8605
|
const ref = useShowEntryEvent(id);
|
|
8606
|
+
const onInput = useCallback(newValue => {
|
|
8607
|
+
const newModelValue = newValue === '' ? undefined : newValue;
|
|
8608
|
+
commitValue(newModelValue);
|
|
8609
|
+
}, [commitValue]);
|
|
8336
8610
|
|
|
8337
8611
|
/**
|
|
8338
8612
|
* @type { import('min-dash').DebouncedFunction }
|
|
8339
8613
|
*/
|
|
8340
|
-
const
|
|
8614
|
+
const handleInput = useDebounce(onInput, debounce);
|
|
8341
8615
|
const handleOnBlur = e => {
|
|
8342
8616
|
const trimmedValue = e.target.value.trim();
|
|
8343
8617
|
|
|
8344
8618
|
// trim and commit on blur
|
|
8619
|
+
handleInput.cancel?.();
|
|
8345
8620
|
onInput(trimmedValue);
|
|
8621
|
+
setLocalValue(trimmedValue);
|
|
8346
8622
|
if (onBlur) {
|
|
8347
8623
|
onBlur(e);
|
|
8348
8624
|
}
|
|
8349
8625
|
};
|
|
8350
|
-
const
|
|
8351
|
-
const
|
|
8352
|
-
|
|
8626
|
+
const handleOnPaste = e => {
|
|
8627
|
+
const input = e.target;
|
|
8628
|
+
const isFieldEmpty = !input.value;
|
|
8629
|
+
const isAllSelected = input.selectionStart === 0 && input.selectionEnd === input.value.length;
|
|
8630
|
+
|
|
8631
|
+
// Trim and handle paste if field is empty or all content is selected (overwrite)
|
|
8632
|
+
if (isFieldEmpty || isAllSelected) {
|
|
8633
|
+
const trimmedValue = e.clipboardData.getData('text').trim();
|
|
8634
|
+
setLocalValue(trimmedValue);
|
|
8635
|
+
handleInput(trimmedValue);
|
|
8636
|
+
if (onPaste) {
|
|
8637
|
+
onPaste(e);
|
|
8638
|
+
}
|
|
8639
|
+
e.preventDefault();
|
|
8640
|
+
return;
|
|
8641
|
+
}
|
|
8642
|
+
|
|
8643
|
+
// Allow default paste behavior for normal text editing
|
|
8644
|
+
if (onPaste) {
|
|
8645
|
+
onPaste(e);
|
|
8646
|
+
}
|
|
8353
8647
|
};
|
|
8354
8648
|
const handleLocalInput = e => {
|
|
8355
8649
|
if (e.target.value === localValue) {
|
|
@@ -8364,6 +8658,11 @@ function Textfield(props) {
|
|
|
8364
8658
|
}
|
|
8365
8659
|
setLocalValue(value);
|
|
8366
8660
|
}, [value]);
|
|
8661
|
+
const handleOnKeyDown = e => {
|
|
8662
|
+
if (isCmdWithChar(e)) {
|
|
8663
|
+
handleInput.flush();
|
|
8664
|
+
}
|
|
8665
|
+
};
|
|
8367
8666
|
return jsxs("div", {
|
|
8368
8667
|
class: "bio-properties-panel-textfield",
|
|
8369
8668
|
children: [jsx("label", {
|
|
@@ -8386,7 +8685,9 @@ function Textfield(props) {
|
|
|
8386
8685
|
class: "bio-properties-panel-input",
|
|
8387
8686
|
onInput: handleLocalInput,
|
|
8388
8687
|
onFocus: onFocus,
|
|
8688
|
+
onKeyDown: handleOnKeyDown,
|
|
8389
8689
|
onBlur: handleOnBlur,
|
|
8690
|
+
onPaste: handleOnPaste,
|
|
8390
8691
|
placeholder: placeholder,
|
|
8391
8692
|
value: localValue
|
|
8392
8693
|
})]
|
|
@@ -8421,6 +8722,7 @@ function TextfieldEntry(props) {
|
|
|
8421
8722
|
validate,
|
|
8422
8723
|
onFocus,
|
|
8423
8724
|
onBlur,
|
|
8725
|
+
onPaste,
|
|
8424
8726
|
placeholder,
|
|
8425
8727
|
tooltip
|
|
8426
8728
|
} = props;
|
|
@@ -8456,6 +8758,7 @@ function TextfieldEntry(props) {
|
|
|
8456
8758
|
onInput: onInput,
|
|
8457
8759
|
onFocus: onFocus,
|
|
8458
8760
|
onBlur: onBlur,
|
|
8761
|
+
onPaste: onPaste,
|
|
8459
8762
|
placeholder: placeholder,
|
|
8460
8763
|
value: value,
|
|
8461
8764
|
tooltip: tooltip,
|
|
@@ -8766,6 +9069,25 @@ function cancel(event) {
|
|
|
8766
9069
|
event.preventDefault();
|
|
8767
9070
|
event.stopPropagation();
|
|
8768
9071
|
}
|
|
9072
|
+
|
|
9073
|
+
/**
|
|
9074
|
+
* @typedef {Object} FeelPopupProps
|
|
9075
|
+
* @property {string} entryId
|
|
9076
|
+
* @property {Function} onInput
|
|
9077
|
+
* @property {Function} onClose
|
|
9078
|
+
* @property {string} title
|
|
9079
|
+
* @property {'feel'|'feelers'} type
|
|
9080
|
+
* @property {string} value
|
|
9081
|
+
* @property {Array} [links]
|
|
9082
|
+
* @property {Array|Object} [variables]
|
|
9083
|
+
* @property {Object} [position]
|
|
9084
|
+
* @property {string} [hostLanguage]
|
|
9085
|
+
* @property {boolean} [singleLine]
|
|
9086
|
+
* @property {HTMLElement} [sourceElement]
|
|
9087
|
+
* @property {HTMLElement|string} [tooltipContainer]
|
|
9088
|
+
* @property {Object} [eventBus]
|
|
9089
|
+
*/
|
|
9090
|
+
|
|
8769
9091
|
const FEEL_POPUP_WIDTH = 700;
|
|
8770
9092
|
const FEEL_POPUP_HEIGHT = 250;
|
|
8771
9093
|
|