@bpmn-io/form-js-editor 1.17.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 +13 -1
- package/dist/assets/properties-panel.css +13 -1
- package/dist/index.cjs +400 -77
- package/dist/index.cjs.map +1 -1
- package/dist/index.es.js +401 -78
- package/dist/index.es.js.map +1 -1
- package/package.json +7 -7
package/dist/index.es.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
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
|
-
import { isArray, isFunction, isNumber, bind, assign, debounce, forEach, isString, uniqueBy, isObject, get, isDefined, set as set$1, reduce,
|
|
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';
|
|
5
5
|
import classnames from 'classnames';
|
|
6
6
|
import { jsxs, jsx, Fragment as Fragment$1 } from 'preact/jsx-runtime';
|
|
7
7
|
import { useContext, useRef, useEffect, useMemo, useState, useCallback, useLayoutEffect } from 'preact/hooks';
|
|
@@ -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
|
});
|
|
@@ -5442,23 +5502,32 @@ LaunchIcon.defaultProps = {
|
|
|
5442
5502
|
viewBox: "0 0 32 32"
|
|
5443
5503
|
};
|
|
5444
5504
|
var OpenPopupIcon = function OpenPopupIcon(props) {
|
|
5445
|
-
return
|
|
5505
|
+
return jsx("svg", {
|
|
5446
5506
|
...props,
|
|
5447
|
-
children:
|
|
5448
|
-
|
|
5449
|
-
|
|
5450
|
-
}), jsx("path", {
|
|
5451
|
-
fill: "currentColor",
|
|
5452
|
-
d: "M18 26H4V16h2v-2H4a2.006 2.006 0 0 0-2 2v10a2.006 2.006 0 0 0 2 2h14a2.006 2.006 0 0 0 2-2v-2h-2Z"
|
|
5453
|
-
})]
|
|
5507
|
+
children: jsx("path", {
|
|
5508
|
+
d: "M6 15v-1H2.7L7 9.7 6.3 9 2 13.3V10H1v5zm4-14v1h3.3L9 6.3l.7.7L14 2.7V6h1V1z"
|
|
5509
|
+
})
|
|
5454
5510
|
});
|
|
5455
5511
|
};
|
|
5456
5512
|
OpenPopupIcon.defaultProps = {
|
|
5457
5513
|
xmlns: "http://www.w3.org/2000/svg",
|
|
5458
|
-
|
|
5459
|
-
height: "16",
|
|
5460
|
-
viewBox: "0 0 32 32"
|
|
5514
|
+
viewBox: "0 0 16 16"
|
|
5461
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
|
+
*/
|
|
5462
5531
|
function Header(props) {
|
|
5463
5532
|
const {
|
|
5464
5533
|
element,
|
|
@@ -5486,11 +5555,9 @@ function Header(props) {
|
|
|
5486
5555
|
}), jsxs("div", {
|
|
5487
5556
|
class: "bio-properties-panel-header-labels",
|
|
5488
5557
|
children: [jsx("div", {
|
|
5489
|
-
title: type,
|
|
5490
5558
|
class: "bio-properties-panel-header-type",
|
|
5491
5559
|
children: type
|
|
5492
5560
|
}), label ? jsx("div", {
|
|
5493
|
-
title: label,
|
|
5494
5561
|
class: "bio-properties-panel-header-label",
|
|
5495
5562
|
children: label
|
|
5496
5563
|
}) : null]
|
|
@@ -5578,6 +5645,27 @@ function useTooltipContext(id, element) {
|
|
|
5578
5645
|
} = useContext(TooltipContext);
|
|
5579
5646
|
return getTooltipForId(id, element);
|
|
5580
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
|
+
*/
|
|
5581
5669
|
function TooltipWrapper(props) {
|
|
5582
5670
|
const {
|
|
5583
5671
|
forId,
|
|
@@ -5594,35 +5682,77 @@ function TooltipWrapper(props) {
|
|
|
5594
5682
|
forId: `bio-properties-panel-${forId}`
|
|
5595
5683
|
});
|
|
5596
5684
|
}
|
|
5685
|
+
|
|
5686
|
+
/**
|
|
5687
|
+
* @param {TooltipProps & {
|
|
5688
|
+
* forId: String,
|
|
5689
|
+
* value: String|Object
|
|
5690
|
+
* }} props
|
|
5691
|
+
*/
|
|
5597
5692
|
function Tooltip(props) {
|
|
5598
5693
|
const {
|
|
5599
5694
|
forId,
|
|
5600
5695
|
value,
|
|
5601
5696
|
parent,
|
|
5602
5697
|
direction = 'right',
|
|
5603
|
-
position
|
|
5698
|
+
position,
|
|
5699
|
+
showDelay = 250,
|
|
5700
|
+
hideDelay = 250
|
|
5604
5701
|
} = props;
|
|
5605
5702
|
const [visible, setVisible] = useState(false);
|
|
5606
|
-
|
|
5607
|
-
|
|
5608
|
-
const SHOW_DELAY = 200;
|
|
5609
|
-
let timeout = null;
|
|
5703
|
+
const showTimeoutRef = useRef(null);
|
|
5704
|
+
const hideTimeoutRef = useRef(null);
|
|
5610
5705
|
const wrapperRef = useRef(null);
|
|
5611
5706
|
const tooltipRef = useRef(null);
|
|
5612
5707
|
const show = (_, delay) => {
|
|
5708
|
+
clearTimeout(showTimeoutRef.current);
|
|
5709
|
+
clearTimeout(hideTimeoutRef.current);
|
|
5613
5710
|
if (visible) return;
|
|
5614
5711
|
if (delay) {
|
|
5615
|
-
|
|
5712
|
+
showTimeoutRef.current = setTimeout(() => {
|
|
5616
5713
|
setVisible(true);
|
|
5617
|
-
},
|
|
5714
|
+
}, showDelay);
|
|
5618
5715
|
} else {
|
|
5619
5716
|
setVisible(true);
|
|
5620
5717
|
}
|
|
5621
5718
|
};
|
|
5622
|
-
const
|
|
5623
|
-
|
|
5624
|
-
|
|
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
|
+
}
|
|
5625
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]);
|
|
5626
5756
|
const handleMouseLeave = ({
|
|
5627
5757
|
relatedTarget
|
|
5628
5758
|
}) => {
|
|
@@ -5630,23 +5760,32 @@ function Tooltip(props) {
|
|
|
5630
5760
|
if (relatedTarget === wrapperRef.current || relatedTarget === tooltipRef.current || relatedTarget?.parentElement === tooltipRef.current) {
|
|
5631
5761
|
return;
|
|
5632
5762
|
}
|
|
5633
|
-
|
|
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);
|
|
5634
5775
|
};
|
|
5635
5776
|
const handleFocusOut = e => {
|
|
5636
5777
|
const {
|
|
5637
|
-
|
|
5778
|
+
relatedTarget
|
|
5638
5779
|
} = e;
|
|
5639
5780
|
|
|
5640
|
-
// Don't hide
|
|
5641
|
-
|
|
5642
|
-
if (target === wrapperRef.current && isHovered) {
|
|
5643
|
-
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)) {
|
|
5644
5783
|
return;
|
|
5645
5784
|
}
|
|
5646
|
-
hide();
|
|
5785
|
+
hide(false);
|
|
5647
5786
|
};
|
|
5648
5787
|
const hideTooltipViaEscape = e => {
|
|
5649
|
-
e.code === 'Escape' && hide();
|
|
5788
|
+
e.code === 'Escape' && hide(false);
|
|
5650
5789
|
};
|
|
5651
5790
|
const renderTooltip = () => {
|
|
5652
5791
|
return jsxs("div", {
|
|
@@ -5657,6 +5796,7 @@ function Tooltip(props) {
|
|
|
5657
5796
|
style: position || getTooltipPosition(wrapperRef.current),
|
|
5658
5797
|
ref: tooltipRef,
|
|
5659
5798
|
onClick: e => e.stopPropagation(),
|
|
5799
|
+
onMouseEnter: handleTooltipMouseEnter,
|
|
5660
5800
|
onMouseLeave: handleMouseLeave,
|
|
5661
5801
|
children: [jsx("div", {
|
|
5662
5802
|
class: "bio-properties-panel-tooltip-content",
|
|
@@ -5670,7 +5810,7 @@ function Tooltip(props) {
|
|
|
5670
5810
|
class: "bio-properties-panel-tooltip-wrapper",
|
|
5671
5811
|
tabIndex: "0",
|
|
5672
5812
|
ref: wrapperRef,
|
|
5673
|
-
onMouseEnter:
|
|
5813
|
+
onMouseEnter: handleWrapperMouseEnter,
|
|
5674
5814
|
onMouseLeave: handleMouseLeave,
|
|
5675
5815
|
onFocus: show,
|
|
5676
5816
|
onBlur: handleFocusOut,
|
|
@@ -5948,6 +6088,10 @@ function useElementVisible(element) {
|
|
|
5948
6088
|
}, [element, visible]);
|
|
5949
6089
|
return visible;
|
|
5950
6090
|
}
|
|
6091
|
+
|
|
6092
|
+
/**
|
|
6093
|
+
* @param {import('../PropertiesPanel').GroupDefinition} props
|
|
6094
|
+
*/
|
|
5951
6095
|
function Group(props) {
|
|
5952
6096
|
const {
|
|
5953
6097
|
element,
|
|
@@ -6002,8 +6146,6 @@ function Group(props) {
|
|
|
6002
6146
|
class: classnames('bio-properties-panel-group-header', edited ? '' : 'empty', open ? 'open' : '', sticky && open ? 'sticky' : ''),
|
|
6003
6147
|
onClick: toggleOpen,
|
|
6004
6148
|
children: [jsx("div", {
|
|
6005
|
-
title: props.tooltip ? null : label,
|
|
6006
|
-
"data-title": label,
|
|
6007
6149
|
class: "bio-properties-panel-group-header-title",
|
|
6008
6150
|
children: jsx(TooltipWrapper, {
|
|
6009
6151
|
value: props.tooltip,
|
|
@@ -6207,9 +6349,11 @@ function PropertiesPanel$1(props) {
|
|
|
6207
6349
|
return get(layout, key, defaultValue);
|
|
6208
6350
|
};
|
|
6209
6351
|
const setLayoutForKey = (key, config) => {
|
|
6210
|
-
|
|
6211
|
-
|
|
6212
|
-
|
|
6352
|
+
setLayout(prevLayout => {
|
|
6353
|
+
const newLayout = assign({}, prevLayout);
|
|
6354
|
+
set$1(newLayout, key, config);
|
|
6355
|
+
return newLayout;
|
|
6356
|
+
});
|
|
6213
6357
|
};
|
|
6214
6358
|
const layoutContext = {
|
|
6215
6359
|
layout,
|
|
@@ -6408,7 +6552,6 @@ function CollapsibleEntry(props) {
|
|
|
6408
6552
|
class: "bio-properties-panel-collapsible-entry-header",
|
|
6409
6553
|
onClick: toggleOpen,
|
|
6410
6554
|
children: [jsx("div", {
|
|
6411
|
-
title: label || placeholderLabel,
|
|
6412
6555
|
class: classnames('bio-properties-panel-collapsible-entry-header-title', !label && 'empty'),
|
|
6413
6556
|
children: label || placeholderLabel
|
|
6414
6557
|
}), jsx("button", {
|
|
@@ -6444,6 +6587,10 @@ function CollapsibleEntry(props) {
|
|
|
6444
6587
|
})]
|
|
6445
6588
|
});
|
|
6446
6589
|
}
|
|
6590
|
+
|
|
6591
|
+
/**
|
|
6592
|
+
* @param {import('../PropertiesPanel').ListItemDefinition} props
|
|
6593
|
+
*/
|
|
6447
6594
|
function ListItem(props) {
|
|
6448
6595
|
const {
|
|
6449
6596
|
autoFocusEntry,
|
|
@@ -6545,8 +6692,6 @@ function ListGroup(props) {
|
|
|
6545
6692
|
class: classnames('bio-properties-panel-group-header', hasItems ? '' : 'empty', hasItems && open ? 'open' : '', sticky && open ? 'sticky' : ''),
|
|
6546
6693
|
onClick: hasItems ? toggleOpen : noop$6,
|
|
6547
6694
|
children: [jsx("div", {
|
|
6548
|
-
title: props.tooltip ? null : label,
|
|
6549
|
-
"data-title": label,
|
|
6550
6695
|
class: "bio-properties-panel-group-header-title",
|
|
6551
6696
|
children: jsx(TooltipWrapper, {
|
|
6552
6697
|
value: props.tooltip,
|
|
@@ -6615,6 +6760,13 @@ function getNewItemIds(newItems, oldItems) {
|
|
|
6615
6760
|
const oldIds = oldItems.map(item => item.id);
|
|
6616
6761
|
return newIds.filter(itemId => !oldIds.includes(itemId));
|
|
6617
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
|
+
*/
|
|
6618
6770
|
function Description$1(props) {
|
|
6619
6771
|
const {
|
|
6620
6772
|
element,
|
|
@@ -6744,6 +6896,16 @@ function isEdited$8(node) {
|
|
|
6744
6896
|
function prefixId$8(id) {
|
|
6745
6897
|
return `bio-properties-panel-${id}`;
|
|
6746
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
|
+
*/
|
|
6747
6909
|
function OpenPopupButton({
|
|
6748
6910
|
onClick,
|
|
6749
6911
|
title = 'Open pop-up editor'
|
|
@@ -6887,6 +7049,7 @@ const FeelEditor = forwardRef((props, ref) => {
|
|
|
6887
7049
|
enableGutters,
|
|
6888
7050
|
value,
|
|
6889
7051
|
onInput,
|
|
7052
|
+
onKeyDown: onKeyDownProp = noop$4,
|
|
6890
7053
|
onFeelToggle = noop$4,
|
|
6891
7054
|
onLint = noop$4,
|
|
6892
7055
|
onOpenPopup = noop$4,
|
|
@@ -6919,6 +7082,8 @@ const FeelEditor = forwardRef((props, ref) => {
|
|
|
6919
7082
|
* - AND the cursor is at the beginning of the input
|
|
6920
7083
|
*/
|
|
6921
7084
|
const onKeyDown = e => {
|
|
7085
|
+
// Call parent onKeyDown handler first
|
|
7086
|
+
onKeyDownProp(e);
|
|
6922
7087
|
if (e.key !== 'Backspace' || !editor) {
|
|
6923
7088
|
return;
|
|
6924
7089
|
}
|
|
@@ -7035,6 +7200,22 @@ function FeelIcon(props) {
|
|
|
7035
7200
|
children: jsx(FeelIcon$1, {})
|
|
7036
7201
|
});
|
|
7037
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
|
+
}
|
|
7038
7219
|
function ToggleSwitch(props) {
|
|
7039
7220
|
const {
|
|
7040
7221
|
id,
|
|
@@ -7346,7 +7527,7 @@ function FeelTextfield(props) {
|
|
|
7346
7527
|
element,
|
|
7347
7528
|
label,
|
|
7348
7529
|
hostLanguage,
|
|
7349
|
-
onInput,
|
|
7530
|
+
onInput: commitValue,
|
|
7350
7531
|
onBlur,
|
|
7351
7532
|
onError,
|
|
7352
7533
|
placeholder,
|
|
@@ -7362,6 +7543,12 @@ function FeelTextfield(props) {
|
|
|
7362
7543
|
const [localValue, setLocalValue] = useState(value);
|
|
7363
7544
|
const editorRef = useShowEntryEvent(id);
|
|
7364
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]);
|
|
7365
7552
|
const feelActive = isString(localValue) && localValue.startsWith('=') || feel === 'required';
|
|
7366
7553
|
const feelOnlyValue = isString(localValue) && localValue.startsWith('=') ? localValue.substring(1) : localValue;
|
|
7367
7554
|
const feelLanguageContext = useContext(FeelLanguageContext);
|
|
@@ -7381,13 +7568,7 @@ function FeelTextfield(props) {
|
|
|
7381
7568
|
/**
|
|
7382
7569
|
* @type { import('min-dash').DebouncedFunction }
|
|
7383
7570
|
*/
|
|
7384
|
-
const
|
|
7385
|
-
const handleInput = newValue => {
|
|
7386
|
-
// we don't commit empty FEEL expressions,
|
|
7387
|
-
// but instead serialize them as <undefined>
|
|
7388
|
-
const newModelValue = newValue === '' || newValue === '=' ? undefined : newValue;
|
|
7389
|
-
handleInputCallback(newModelValue);
|
|
7390
|
-
};
|
|
7571
|
+
const handleInput = useDebounce(onInput, debounce);
|
|
7391
7572
|
const handleFeelToggle = useStaticCallback(() => {
|
|
7392
7573
|
if (feel === 'required') {
|
|
7393
7574
|
return;
|
|
@@ -7400,7 +7581,7 @@ function FeelTextfield(props) {
|
|
|
7400
7581
|
handleInput(feelOnlyValue);
|
|
7401
7582
|
}
|
|
7402
7583
|
});
|
|
7403
|
-
const handleLocalInput = newValue => {
|
|
7584
|
+
const handleLocalInput = (newValue, useDebounce = true) => {
|
|
7404
7585
|
if (feelActive) {
|
|
7405
7586
|
newValue = '=' + newValue;
|
|
7406
7587
|
}
|
|
@@ -7408,23 +7589,33 @@ function FeelTextfield(props) {
|
|
|
7408
7589
|
return;
|
|
7409
7590
|
}
|
|
7410
7591
|
setLocalValue(newValue);
|
|
7411
|
-
|
|
7592
|
+
if (useDebounce) {
|
|
7593
|
+
handleInput(newValue);
|
|
7594
|
+
} else {
|
|
7595
|
+
onInput(newValue);
|
|
7596
|
+
}
|
|
7412
7597
|
if (!feelActive && isString(newValue) && newValue.startsWith('=')) {
|
|
7413
7598
|
// focus is behind `=` sign that will be removed
|
|
7414
7599
|
setFocus(-1);
|
|
7415
7600
|
}
|
|
7416
7601
|
};
|
|
7417
7602
|
const handleOnBlur = e => {
|
|
7603
|
+
handleInput.cancel?.();
|
|
7418
7604
|
if (e.target.type === 'checkbox') {
|
|
7419
7605
|
onInput(e.target.checked);
|
|
7420
7606
|
} else {
|
|
7421
7607
|
const trimmedValue = e.target.value.trim();
|
|
7422
|
-
|
|
7608
|
+
handleLocalInput(trimmedValue, false);
|
|
7423
7609
|
}
|
|
7424
7610
|
if (onBlur) {
|
|
7425
7611
|
onBlur(e);
|
|
7426
7612
|
}
|
|
7427
7613
|
};
|
|
7614
|
+
const handleOnKeyDown = e => {
|
|
7615
|
+
if (isCmdWithChar(e)) {
|
|
7616
|
+
handleInput.flush();
|
|
7617
|
+
}
|
|
7618
|
+
};
|
|
7428
7619
|
const handleLint = useStaticCallback((lint = []) => {
|
|
7429
7620
|
const syntaxError = lint.some(report => report.type === 'Syntax Error');
|
|
7430
7621
|
if (syntaxError) {
|
|
@@ -7491,12 +7682,26 @@ function FeelTextfield(props) {
|
|
|
7491
7682
|
if (feelActive || isPopupOpen) {
|
|
7492
7683
|
return;
|
|
7493
7684
|
}
|
|
7494
|
-
const
|
|
7495
|
-
if (
|
|
7685
|
+
const feelData = event.clipboardData.getData('application/FEEL');
|
|
7686
|
+
if (feelData) {
|
|
7496
7687
|
setTimeout(() => {
|
|
7497
7688
|
handleFeelToggle();
|
|
7498
7689
|
setFocus();
|
|
7499
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();
|
|
7500
7705
|
}
|
|
7501
7706
|
};
|
|
7502
7707
|
containerRef.current.addEventListener('copy', copyHandler);
|
|
@@ -7537,6 +7742,7 @@ function FeelTextfield(props) {
|
|
|
7537
7742
|
}), feelActive ? jsx(FeelEditor, {
|
|
7538
7743
|
name: id,
|
|
7539
7744
|
onInput: handleLocalInput,
|
|
7745
|
+
onKeyDown: handleOnKeyDown,
|
|
7540
7746
|
contentAttributes: {
|
|
7541
7747
|
'id': prefixId$5(id),
|
|
7542
7748
|
'aria-label': label
|
|
@@ -7559,6 +7765,7 @@ function FeelTextfield(props) {
|
|
|
7559
7765
|
...props,
|
|
7560
7766
|
popupOpen: isPopupOpen,
|
|
7561
7767
|
onInput: handleLocalInput,
|
|
7768
|
+
onKeyDown: handleOnKeyDown,
|
|
7562
7769
|
onBlur: handleOnBlur,
|
|
7563
7770
|
contentAttributes: {
|
|
7564
7771
|
'id': prefixId$5(id),
|
|
@@ -7577,6 +7784,7 @@ const OptionalFeelInput = forwardRef((props, ref) => {
|
|
|
7577
7784
|
id,
|
|
7578
7785
|
disabled,
|
|
7579
7786
|
onInput,
|
|
7787
|
+
onKeyDown,
|
|
7580
7788
|
value,
|
|
7581
7789
|
onFocus,
|
|
7582
7790
|
onBlur,
|
|
@@ -7612,6 +7820,7 @@ const OptionalFeelInput = forwardRef((props, ref) => {
|
|
|
7612
7820
|
class: "bio-properties-panel-input",
|
|
7613
7821
|
onInput: e => onInput(e.target.value),
|
|
7614
7822
|
onFocus: onFocus,
|
|
7823
|
+
onKeyDown: onKeyDown,
|
|
7615
7824
|
onBlur: onBlur,
|
|
7616
7825
|
placeholder: placeholder,
|
|
7617
7826
|
value: value || ''
|
|
@@ -7985,6 +8194,25 @@ function isEdited$5(node) {
|
|
|
7985
8194
|
function prefixId$5(id) {
|
|
7986
8195
|
return `bio-properties-panel-${id}`;
|
|
7987
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
|
+
*/
|
|
7988
8216
|
function Select(props) {
|
|
7989
8217
|
const {
|
|
7990
8218
|
id,
|
|
@@ -8150,12 +8378,13 @@ function TextArea(props) {
|
|
|
8150
8378
|
id,
|
|
8151
8379
|
label,
|
|
8152
8380
|
debounce,
|
|
8153
|
-
onInput,
|
|
8381
|
+
onInput: commitValue,
|
|
8154
8382
|
value = '',
|
|
8155
8383
|
disabled,
|
|
8156
8384
|
monospace,
|
|
8157
8385
|
onFocus,
|
|
8158
8386
|
onBlur,
|
|
8387
|
+
onPaste,
|
|
8159
8388
|
autoResize = true,
|
|
8160
8389
|
placeholder,
|
|
8161
8390
|
rows = autoResize ? 1 : 2,
|
|
@@ -8163,16 +8392,16 @@ function TextArea(props) {
|
|
|
8163
8392
|
} = props;
|
|
8164
8393
|
const [localValue, setLocalValue] = useState(value);
|
|
8165
8394
|
const ref = useShowEntryEvent(id);
|
|
8395
|
+
const onInput = useCallback(newValue => {
|
|
8396
|
+
const newModelValue = newValue === '' ? undefined : newValue;
|
|
8397
|
+
commitValue(newModelValue);
|
|
8398
|
+
}, [commitValue]);
|
|
8166
8399
|
const visible = useElementVisible(ref.current);
|
|
8167
8400
|
|
|
8168
8401
|
/**
|
|
8169
8402
|
* @type { import('min-dash').DebouncedFunction }
|
|
8170
8403
|
*/
|
|
8171
|
-
const
|
|
8172
|
-
const handleInput = newValue => {
|
|
8173
|
-
const newModelValue = newValue === '' ? undefined : newValue;
|
|
8174
|
-
handleInputCallback(newModelValue);
|
|
8175
|
-
};
|
|
8404
|
+
const handleInput = useDebounce(onInput, debounce);
|
|
8176
8405
|
const handleLocalInput = e => {
|
|
8177
8406
|
autoResize && resizeToContents(e.target);
|
|
8178
8407
|
if (e.target.value === localValue) {
|
|
@@ -8185,11 +8414,40 @@ function TextArea(props) {
|
|
|
8185
8414
|
const trimmedValue = e.target.value.trim();
|
|
8186
8415
|
|
|
8187
8416
|
// trim and commit on blur
|
|
8417
|
+
handleInput.cancel?.();
|
|
8188
8418
|
onInput(trimmedValue);
|
|
8419
|
+
setLocalValue(trimmedValue);
|
|
8189
8420
|
if (onBlur) {
|
|
8190
8421
|
onBlur(e);
|
|
8191
8422
|
}
|
|
8192
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
|
+
};
|
|
8193
8451
|
useLayoutEffect(() => {
|
|
8194
8452
|
autoResize && resizeToContents(ref.current);
|
|
8195
8453
|
}, []);
|
|
@@ -8221,7 +8479,9 @@ function TextArea(props) {
|
|
|
8221
8479
|
class: classnames('bio-properties-panel-input', monospace ? 'bio-properties-panel-input-monospace' : '', autoResize ? 'auto-resize' : ''),
|
|
8222
8480
|
onInput: handleLocalInput,
|
|
8223
8481
|
onFocus: onFocus,
|
|
8482
|
+
onKeyDown: handleOnKeyDown,
|
|
8224
8483
|
onBlur: handleOnBlur,
|
|
8484
|
+
onPaste: handleOnPaste,
|
|
8225
8485
|
placeholder: placeholder,
|
|
8226
8486
|
rows: rows,
|
|
8227
8487
|
value: localValue,
|
|
@@ -8242,6 +8502,7 @@ function TextArea(props) {
|
|
|
8242
8502
|
* @param {Function} props.setValue
|
|
8243
8503
|
* @param {Function} props.onFocus
|
|
8244
8504
|
* @param {Function} props.onBlur
|
|
8505
|
+
* @param {Function} props.onPaste
|
|
8245
8506
|
* @param {number} props.rows
|
|
8246
8507
|
* @param {boolean} props.monospace
|
|
8247
8508
|
* @param {Function} [props.validate]
|
|
@@ -8262,6 +8523,7 @@ function TextAreaEntry(props) {
|
|
|
8262
8523
|
validate,
|
|
8263
8524
|
onFocus,
|
|
8264
8525
|
onBlur,
|
|
8526
|
+
onPaste,
|
|
8265
8527
|
placeholder,
|
|
8266
8528
|
autoResize,
|
|
8267
8529
|
tooltip
|
|
@@ -8297,6 +8559,7 @@ function TextAreaEntry(props) {
|
|
|
8297
8559
|
onInput: onInput,
|
|
8298
8560
|
onFocus: onFocus,
|
|
8299
8561
|
onBlur: onBlur,
|
|
8562
|
+
onPaste: onPaste,
|
|
8300
8563
|
rows: rows,
|
|
8301
8564
|
debounce: debounce,
|
|
8302
8565
|
monospace: monospace,
|
|
@@ -8330,32 +8593,57 @@ function Textfield(props) {
|
|
|
8330
8593
|
disabled = false,
|
|
8331
8594
|
id,
|
|
8332
8595
|
label,
|
|
8333
|
-
onInput,
|
|
8596
|
+
onInput: commitValue,
|
|
8334
8597
|
onFocus,
|
|
8335
8598
|
onBlur,
|
|
8599
|
+
onPaste,
|
|
8336
8600
|
placeholder,
|
|
8337
8601
|
value = '',
|
|
8338
8602
|
tooltip
|
|
8339
8603
|
} = props;
|
|
8340
8604
|
const [localValue, setLocalValue] = useState(value || '');
|
|
8341
8605
|
const ref = useShowEntryEvent(id);
|
|
8606
|
+
const onInput = useCallback(newValue => {
|
|
8607
|
+
const newModelValue = newValue === '' ? undefined : newValue;
|
|
8608
|
+
commitValue(newModelValue);
|
|
8609
|
+
}, [commitValue]);
|
|
8342
8610
|
|
|
8343
8611
|
/**
|
|
8344
8612
|
* @type { import('min-dash').DebouncedFunction }
|
|
8345
8613
|
*/
|
|
8346
|
-
const
|
|
8614
|
+
const handleInput = useDebounce(onInput, debounce);
|
|
8347
8615
|
const handleOnBlur = e => {
|
|
8348
8616
|
const trimmedValue = e.target.value.trim();
|
|
8349
8617
|
|
|
8350
8618
|
// trim and commit on blur
|
|
8619
|
+
handleInput.cancel?.();
|
|
8351
8620
|
onInput(trimmedValue);
|
|
8621
|
+
setLocalValue(trimmedValue);
|
|
8352
8622
|
if (onBlur) {
|
|
8353
8623
|
onBlur(e);
|
|
8354
8624
|
}
|
|
8355
8625
|
};
|
|
8356
|
-
const
|
|
8357
|
-
const
|
|
8358
|
-
|
|
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
|
+
}
|
|
8359
8647
|
};
|
|
8360
8648
|
const handleLocalInput = e => {
|
|
8361
8649
|
if (e.target.value === localValue) {
|
|
@@ -8370,6 +8658,11 @@ function Textfield(props) {
|
|
|
8370
8658
|
}
|
|
8371
8659
|
setLocalValue(value);
|
|
8372
8660
|
}, [value]);
|
|
8661
|
+
const handleOnKeyDown = e => {
|
|
8662
|
+
if (isCmdWithChar(e)) {
|
|
8663
|
+
handleInput.flush();
|
|
8664
|
+
}
|
|
8665
|
+
};
|
|
8373
8666
|
return jsxs("div", {
|
|
8374
8667
|
class: "bio-properties-panel-textfield",
|
|
8375
8668
|
children: [jsx("label", {
|
|
@@ -8392,7 +8685,9 @@ function Textfield(props) {
|
|
|
8392
8685
|
class: "bio-properties-panel-input",
|
|
8393
8686
|
onInput: handleLocalInput,
|
|
8394
8687
|
onFocus: onFocus,
|
|
8688
|
+
onKeyDown: handleOnKeyDown,
|
|
8395
8689
|
onBlur: handleOnBlur,
|
|
8690
|
+
onPaste: handleOnPaste,
|
|
8396
8691
|
placeholder: placeholder,
|
|
8397
8692
|
value: localValue
|
|
8398
8693
|
})]
|
|
@@ -8427,6 +8722,7 @@ function TextfieldEntry(props) {
|
|
|
8427
8722
|
validate,
|
|
8428
8723
|
onFocus,
|
|
8429
8724
|
onBlur,
|
|
8725
|
+
onPaste,
|
|
8430
8726
|
placeholder,
|
|
8431
8727
|
tooltip
|
|
8432
8728
|
} = props;
|
|
@@ -8462,6 +8758,7 @@ function TextfieldEntry(props) {
|
|
|
8462
8758
|
onInput: onInput,
|
|
8463
8759
|
onFocus: onFocus,
|
|
8464
8760
|
onBlur: onBlur,
|
|
8761
|
+
onPaste: onPaste,
|
|
8465
8762
|
placeholder: placeholder,
|
|
8466
8763
|
value: value,
|
|
8467
8764
|
tooltip: tooltip,
|
|
@@ -8772,6 +9069,25 @@ function cancel(event) {
|
|
|
8772
9069
|
event.preventDefault();
|
|
8773
9070
|
event.stopPropagation();
|
|
8774
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
|
+
|
|
8775
9091
|
const FEEL_POPUP_WIDTH = 700;
|
|
8776
9092
|
const FEEL_POPUP_HEIGHT = 250;
|
|
8777
9093
|
|
|
@@ -11455,7 +11771,14 @@ function Value$1(props) {
|
|
|
11455
11771
|
if (error) {
|
|
11456
11772
|
return;
|
|
11457
11773
|
}
|
|
11774
|
+
const {
|
|
11775
|
+
defaultValue
|
|
11776
|
+
} = field;
|
|
11458
11777
|
const values = get(field, ['values']);
|
|
11778
|
+
const previousValue = get(field, ['values', index, 'value']);
|
|
11779
|
+
if (!isNil(defaultValue) && defaultValue === previousValue) {
|
|
11780
|
+
set$1(field, ['defaultValue'], value);
|
|
11781
|
+
}
|
|
11459
11782
|
return editField(field, 'values', set$1(values, [index, 'value'], value));
|
|
11460
11783
|
};
|
|
11461
11784
|
const getValue = () => {
|
|
@@ -12865,7 +13188,7 @@ function DocumentsDataSource(props) {
|
|
|
12865
13188
|
children: "When using Camunda Tasklist UI, additional document reference attributes are automatically handled. Modifying the document reference may affect the document preview functionality."
|
|
12866
13189
|
}), jsxs("p", {
|
|
12867
13190
|
children: ["Learn more in our", ' ', jsx("a", {
|
|
12868
|
-
href: "https://docs.camunda.io/docs/
|
|
13191
|
+
href: "https://docs.camunda.io/docs/components/modeler/forms/form-element-library/forms-element-library-document-preview/",
|
|
12869
13192
|
target: "_blank",
|
|
12870
13193
|
rel: "noopener noreferrer",
|
|
12871
13194
|
children: "documentation"
|
|
@@ -13477,7 +13800,7 @@ function CustomPropertiesGroup(field, editField) {
|
|
|
13477
13800
|
event.stopPropagation();
|
|
13478
13801
|
return editField(field, ['properties'], removeKey(properties, key));
|
|
13479
13802
|
};
|
|
13480
|
-
const id = `property-${index}`;
|
|
13803
|
+
const id = `property-${field.id}-${index}`;
|
|
13481
13804
|
return {
|
|
13482
13805
|
autoFocusEntry: id + '-key',
|
|
13483
13806
|
entries: CustomValueEntry({
|