@bpmn-io/form-js-editor 1.11.3 → 1.13.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.es.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import Ids from 'ids';
2
- import { FormFieldRegistry as FormFieldRegistry$1, iconsByType, Label as Label$3, IFrame, Text as Text$1, Html, Table, ExpressionField, FormFields, sanitizeImageSource, getAncestryList, FormContext, FormRenderContext, FormComponent, getScrollContainer, Importer, PathRegistry, FormLayouter, FieldFactory, FeelExpressionLanguage, OPTIONS_SOURCES, OPTIONS_SOURCES_PATHS, clone, runRecursively, getSchemaVariables, DATETIME_SUBTYPES, DATE_LABEL_PATH, TIME_LABEL_PATH, DATETIME_SUBTYPE_PATH, DATETIME_SUBTYPES_LABELS, TIME_SERIALISING_FORMAT_PATH, TIME_SERIALISING_FORMATS, TIME_INTERVAL_PATH, TIME_USE24H_PATH, DATE_DISALLOW_PAST_PATH, TIME_SERIALISINGFORMAT_LABELS, getOptionsSource, OPTIONS_SOURCES_DEFAULTS, OPTIONS_SOURCES_LABELS, SECURITY_ATTRIBUTES_DEFINITIONS, createFormContainer, createInjector, MarkdownRendererModule, schemaVersion } from '@bpmn-io/form-js-viewer';
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, Importer, PathRegistry, FormLayouter, FieldFactory, FeelExpressionLanguage, OPTIONS_SOURCES, OPTIONS_SOURCES_PATHS, clone, runRecursively, getSchemaVariables, DATETIME_SUBTYPES, DATE_LABEL_PATH, TIME_LABEL_PATH, DATETIME_SUBTYPE_PATH, DATETIME_SUBTYPES_LABELS, TIME_SERIALISING_FORMAT_PATH, TIME_SERIALISING_FORMATS, TIME_INTERVAL_PATH, TIME_USE24H_PATH, DATE_DISALLOW_PAST_PATH, 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, without, isNil, has } from 'min-dash';
5
5
  import classnames from 'classnames';
@@ -9,7 +9,7 @@ import { createContext, Fragment, render, createElement } from 'preact';
9
9
  import * as React from 'preact/compat';
10
10
  import { createPortal, useRef as useRef$1, useContext as useContext$1, useEffect as useEffect$1, forwardRef } from 'preact/compat';
11
11
  import dragula from '@bpmn-io/draggle';
12
- import { classes, query, closest, event, matches, domify } from 'min-dom';
12
+ import { classes, query, event, domify } from 'min-dom';
13
13
  import { arrayMoveMutable } from 'array-move';
14
14
  import { FeelersEditor } from 'feelers';
15
15
  import FeelEditor from '@bpmn-io/feel-editor';
@@ -1182,7 +1182,37 @@ EditorExpressionField.config = {
1182
1182
  escapeGridRender: false
1183
1183
  };
1184
1184
 
1185
- const editorFormFields = [EditorIFrame, EditorText, EditorHtml, EditorTable, EditorExpressionField];
1185
+ function EditorDocumentPreview(props) {
1186
+ const {
1187
+ field,
1188
+ domId
1189
+ } = props;
1190
+ const {
1191
+ label
1192
+ } = field;
1193
+ const Icon = iconsByType(field.type);
1194
+ return jsxs("div", {
1195
+ class: editorFormFieldClasses(field.type),
1196
+ children: [jsx(Label$3, {
1197
+ id: domId,
1198
+ label: label
1199
+ }), jsx("div", {
1200
+ class: "fjs-documentPreview-placeholder",
1201
+ id: domId,
1202
+ children: jsxs("p", {
1203
+ class: "fjs-documentPreview-placeholder-text",
1204
+ children: [jsx(Icon, {
1205
+ width: "32",
1206
+ height: "24",
1207
+ viewBox: "0 0 56 56"
1208
+ }), "Document preview"]
1209
+ })
1210
+ })]
1211
+ });
1212
+ }
1213
+ EditorDocumentPreview.config = DocumentPreview.config;
1214
+
1215
+ const editorFormFields = [EditorIFrame, EditorText, EditorHtml, EditorTable, EditorExpressionField, EditorDocumentPreview];
1186
1216
 
1187
1217
  class EditorFormFields extends FormFields {
1188
1218
  constructor() {
@@ -2273,13 +2303,17 @@ function Element$1(props) {
2273
2303
  ref.current.focus();
2274
2304
  }
2275
2305
  }, [selection, field]);
2276
- function onClick(event) {
2277
- event.stopPropagation();
2278
- selection.toggle(field);
2279
-
2280
- // properly focus on field
2281
- ref.current.focus();
2282
- }
2306
+ const onClick = useCallback(event => {
2307
+ // TODO(nikku): refactor this to use proper DOM delegation
2308
+ const fieldEl = event.target.closest('[data-id]');
2309
+ if (!fieldEl) {
2310
+ return;
2311
+ }
2312
+ const id = fieldEl.dataset.id;
2313
+ if (id === field.id) {
2314
+ selection.toggle(field);
2315
+ }
2316
+ }, [field, selection]);
2283
2317
  const isSelected = selection.isSelected(field);
2284
2318
  const classString = useMemo(() => {
2285
2319
  const classes = [];
@@ -2671,6 +2705,34 @@ class Renderer {
2671
2705
  container,
2672
2706
  compact = false
2673
2707
  } = renderConfig;
2708
+ eventBus.on('form.init', function () {
2709
+ // emit <canvas.init> so dependent components can hook in
2710
+ // this is required to register keyboard bindings
2711
+ eventBus.fire('canvas.init', {
2712
+ svg: container,
2713
+ viewport: null
2714
+ });
2715
+ });
2716
+
2717
+ // focus container on over if no selection
2718
+ container.addEventListener('mouseover', function () {
2719
+ if (document.activeElement === document.body) {
2720
+ container.focus({
2721
+ preventScroll: true
2722
+ });
2723
+ }
2724
+ });
2725
+
2726
+ // ensure we focus the container if the users clicks
2727
+ // inside; this follows input focus handling closely
2728
+ container.addEventListener('click', function (event) {
2729
+ // force focus when clicking container
2730
+ if (!container.contains(document.activeElement)) {
2731
+ container.focus({
2732
+ preventScroll: true
2733
+ });
2734
+ }
2735
+ });
2674
2736
  const App = () => {
2675
2737
  const [state, setState] = useState(formEditor._getState());
2676
2738
  const formEditorContext = {
@@ -3108,8 +3170,8 @@ function isRedo(event) {
3108
3170
 
3109
3171
  var KEYDOWN_EVENT = 'keyboard.keydown',
3110
3172
  KEYUP_EVENT = 'keyboard.keyup';
3111
- var HANDLE_MODIFIER_ATTRIBUTE = 'input-handle-modified-keys';
3112
3173
  var DEFAULT_PRIORITY$2 = 1000;
3174
+ var compatMessage = 'Keyboard binding is now implicit; explicit binding to an element got removed. For more information, see https://github.com/bpmn-io/diagram-js/issues/661';
3113
3175
 
3114
3176
  /**
3115
3177
  * A keyboard abstraction that may be activated and
@@ -3129,16 +3191,16 @@ var DEFAULT_PRIORITY$2 = 1000;
3129
3191
  *
3130
3192
  * All events contain one field which is node.
3131
3193
  *
3132
- * A default binding for the keyboard may be specified via the
3133
- * `keyboard.bindTo` configuration option.
3194
+ * Specify the initial keyboard binding state via the
3195
+ * `keyboard.bind=true|false` configuration option.
3134
3196
  *
3135
3197
  * @param {Object} config
3136
- * @param {EventTarget} [config.bindTo]
3198
+ * @param {boolean} [config.bind]
3137
3199
  * @param {EventBus} eventBus
3138
3200
  */
3139
3201
  function Keyboard(config, eventBus) {
3140
3202
  var self = this;
3141
- this._config = config || {};
3203
+ this._config = config = config || {};
3142
3204
  this._eventBus = eventBus;
3143
3205
  this._keydownHandler = this._keydownHandler.bind(this);
3144
3206
  this._keyupHandler = this._keyupHandler.bind(this);
@@ -3148,16 +3210,16 @@ function Keyboard(config, eventBus) {
3148
3210
  self._fire('destroy');
3149
3211
  self.unbind();
3150
3212
  });
3151
- eventBus.on('diagram.init', function () {
3152
- self._fire('init');
3153
- });
3154
- eventBus.on('attach', function () {
3155
- if (config && config.bindTo) {
3156
- self.bind(config.bindTo);
3213
+ if (config.bindTo) {
3214
+ console.error('unsupported configuration <keyboard.bindTo>', new Error(compatMessage));
3215
+ }
3216
+ var bind = config && config.bind !== false;
3217
+ eventBus.on('canvas.init', function (event) {
3218
+ self._target = event.svg;
3219
+ if (bind) {
3220
+ self.bind();
3157
3221
  }
3158
- });
3159
- eventBus.on('detach', function () {
3160
- self.unbind();
3222
+ self._fire('init');
3161
3223
  });
3162
3224
  }
3163
3225
  Keyboard.$inject = ['config.keyboard', 'eventBus'];
@@ -3181,35 +3243,29 @@ Keyboard.prototype._keyHandler = function (event, type) {
3181
3243
  }
3182
3244
  };
3183
3245
  Keyboard.prototype._isEventIgnored = function (event) {
3184
- if (event.defaultPrevented) {
3185
- return true;
3186
- }
3187
- return (isInput(event.target) || isButton(event.target) && isKey([' ', 'Enter'], event)) && this._isModifiedKeyIgnored(event);
3188
- };
3189
- Keyboard.prototype._isModifiedKeyIgnored = function (event) {
3190
- if (!isCmd(event)) {
3191
- return true;
3192
- }
3193
- var allowedModifiers = this._getAllowedModifiers(event.target);
3194
- return allowedModifiers.indexOf(event.key) === -1;
3195
- };
3196
- Keyboard.prototype._getAllowedModifiers = function (element) {
3197
- var modifierContainer = closest(element, '[' + HANDLE_MODIFIER_ATTRIBUTE + ']', true);
3198
- if (!modifierContainer || this._node && !this._node.contains(modifierContainer)) {
3199
- return [];
3200
- }
3201
- return modifierContainer.getAttribute(HANDLE_MODIFIER_ATTRIBUTE).split(',');
3246
+ return false;
3202
3247
  };
3203
3248
 
3204
3249
  /**
3205
3250
  * Bind keyboard events to the given DOM node.
3206
3251
  *
3252
+ * @overlord
3253
+ * @deprecated No longer in use since version 15.0.0.
3254
+ *
3207
3255
  * @param {EventTarget} node
3208
3256
  */
3257
+ /**
3258
+ * Bind keyboard events to the canvas node.
3259
+ */
3209
3260
  Keyboard.prototype.bind = function (node) {
3261
+ // legacy <node> argument provided
3262
+ if (node) {
3263
+ console.error('unsupported argument <node>', new Error(compatMessage));
3264
+ }
3265
+
3210
3266
  // make sure that the keyboard is only bound once to the DOM
3211
3267
  this.unbind();
3212
- this._node = node;
3268
+ node = this._node = this._target;
3213
3269
 
3214
3270
  // bind key events
3215
3271
  event.bind(node, 'keydown', this._keydownHandler);
@@ -3276,15 +3332,6 @@ Keyboard.prototype.isCmd = isCmd;
3276
3332
  Keyboard.prototype.isShift = isShift;
3277
3333
  Keyboard.prototype.isKey = isKey;
3278
3334
 
3279
- // helpers ///////
3280
-
3281
- function isInput(target) {
3282
- return target && (matches(target, 'input, textarea') || target.contentEditable === 'true');
3283
- }
3284
- function isButton(target) {
3285
- return target && matches(target, 'button, input[type=submit], input[type=button], a[href], [aria-role=button]');
3286
- }
3287
-
3288
3335
  var LOW_PRIORITY$1 = 500;
3289
3336
 
3290
3337
  /**
@@ -3448,7 +3495,7 @@ class FormEditorKeyboardBindings {
3448
3495
  const {
3449
3496
  keyEvent
3450
3497
  } = context;
3451
- if (isCmd(keyEvent) && !isShift(keyEvent) && isKey(KEYS_UNDO, keyEvent)) {
3498
+ if (isUndo(keyEvent)) {
3452
3499
  editorActions.trigger('undo');
3453
3500
  return true;
3454
3501
  }
@@ -3461,7 +3508,7 @@ class FormEditorKeyboardBindings {
3461
3508
  const {
3462
3509
  keyEvent
3463
3510
  } = context;
3464
- if (isCmd(keyEvent) && (isKey(KEYS_REDO, keyEvent) || isKey(KEYS_UNDO, keyEvent) && isShift(keyEvent))) {
3511
+ if (isRedo(keyEvent)) {
3465
3512
  editorActions.trigger('redo');
3466
3513
  return true;
3467
3514
  }
@@ -5276,6 +5323,21 @@ ArrowIcon.defaultProps = {
5276
5323
  width: "16",
5277
5324
  height: "16"
5278
5325
  };
5326
+ var CloseIcon = function CloseIcon(props) {
5327
+ return jsx("svg", {
5328
+ ...props,
5329
+ children: jsx("path", {
5330
+ fillRule: "evenodd",
5331
+ d: "m12 4.7-.7-.7L8 7.3 4.7 4l-.7.7L7.3 8 4 11.3l.7.7L8 8.7l3.3 3.3.7-.7L8.7 8 12 4.7Z",
5332
+ fill: "currentColor"
5333
+ })
5334
+ });
5335
+ };
5336
+ CloseIcon.defaultProps = {
5337
+ xmlns: "http://www.w3.org/2000/svg",
5338
+ width: "16",
5339
+ height: "16"
5340
+ };
5279
5341
  var CreateIcon = function CreateIcon(props) {
5280
5342
  return jsx("svg", {
5281
5343
  ...props,
@@ -5363,26 +5425,17 @@ FeelIcon$1.defaultProps = {
5363
5425
  fill: "none",
5364
5426
  xmlns: "http://www.w3.org/2000/svg"
5365
5427
  };
5366
- var HelpIcon = function HelpIcon(props) {
5428
+ var LaunchIcon = function LaunchIcon(props) {
5367
5429
  return jsxs("svg", {
5368
5430
  ...props,
5369
5431
  children: [jsx("path", {
5370
- d: "M16 2a14 14 0 1 0 14 14A14 14 0 0 0 16 2Zm0 26a12 12 0 1 1 12-12 12 12 0 0 1-12 12Z"
5371
- }), jsx("circle", {
5372
- cx: "16",
5373
- cy: "23.5",
5374
- r: "1.5"
5432
+ d: "M26 28H6a2.003 2.003 0 0 1-2-2V6a2.003 2.003 0 0 1 2-2h10v2H6v20h20V16h2v10a2.003 2.003 0 0 1-2 2Z"
5375
5433
  }), jsx("path", {
5376
- d: "M17 8h-1.5a4.49 4.49 0 0 0-4.5 4.5v.5h2v-.5a2.5 2.5 0 0 1 2.5-2.5H17a2.5 2.5 0 0 1 0 5h-2v4.5h2V17a4.5 4.5 0 0 0 0-9Z"
5377
- }), jsx("path", {
5378
- style: {
5379
- fill: "none"
5380
- },
5381
- d: "M0 0h32v32H0z"
5434
+ d: "M20 2v2h6.586L18 12.586 19.414 14 28 5.414V12h2V2H20z"
5382
5435
  })]
5383
5436
  });
5384
5437
  };
5385
- HelpIcon.defaultProps = {
5438
+ LaunchIcon.defaultProps = {
5386
5439
  xmlns: "http://www.w3.org/2000/svg",
5387
5440
  viewBox: "0 0 32 32"
5388
5441
  };
@@ -5404,21 +5457,6 @@ PopupIcon.defaultProps = {
5404
5457
  height: "16",
5405
5458
  viewBox: "0 0 32 32"
5406
5459
  };
5407
- var CloseIcon = function CloseIcon(props) {
5408
- return jsx("svg", {
5409
- ...props,
5410
- children: jsx("path", {
5411
- fillRule: "evenodd",
5412
- d: "m12 4.7-.7-.7L8 7.3 4.7 4l-.7.7L7.3 8 4 11.3l.7.7L8 8.7l3.3 3.3.7-.7L8.7 8 12 4.7Z",
5413
- fill: "currentColor"
5414
- })
5415
- });
5416
- };
5417
- CloseIcon.defaultProps = {
5418
- xmlns: "http://www.w3.org/2000/svg",
5419
- width: "16",
5420
- height: "16"
5421
- };
5422
5460
  function Header(props) {
5423
5461
  const {
5424
5462
  element,
@@ -5457,7 +5495,7 @@ function Header(props) {
5457
5495
  }), jsx("div", {
5458
5496
  class: "bio-properties-panel-header-actions",
5459
5497
  children: documentationRef ? jsx("a", {
5460
- rel: "noopener",
5498
+ rel: "noreferrer",
5461
5499
  class: "bio-properties-panel-header-link",
5462
5500
  href: documentationRef,
5463
5501
  title: "Open documentation",
@@ -5475,19 +5513,19 @@ const ErrorsContext = createContext({
5475
5513
  errors: {}
5476
5514
  });
5477
5515
 
5478
- /**
5479
- * @typedef {Function} <propertiesPanel.showEntry> callback
5480
- *
5481
- * @example
5482
- *
5483
- * useEvent('propertiesPanel.showEntry', ({ focus = false, ...rest }) => {
5484
- * // ...
5485
- * });
5486
- *
5487
- * @param {Object} context
5488
- * @param {boolean} [context.focus]
5489
- *
5490
- * @returns void
5516
+ /**
5517
+ * @typedef {Function} <propertiesPanel.showEntry> callback
5518
+ *
5519
+ * @example
5520
+ *
5521
+ * useEvent('propertiesPanel.showEntry', ({ focus = false, ...rest }) => {
5522
+ * // ...
5523
+ * });
5524
+ *
5525
+ * @param {Object} context
5526
+ * @param {boolean} [context.focus]
5527
+ *
5528
+ * @returns void
5491
5529
  */
5492
5530
 
5493
5531
  const EventContext = createContext({
@@ -5504,20 +5542,20 @@ const TooltipContext = createContext({
5504
5542
  getTooltipForId: () => {}
5505
5543
  });
5506
5544
 
5507
- /**
5508
- * Accesses the global TooltipContext and returns a tooltip for a given id and element.
5509
- *
5510
- * @example
5511
- * ```jsx
5512
- * function TextField(props) {
5513
- * const tooltip = useTooltipContext('input1', element);
5514
- * }
5515
- * ```
5516
- *
5517
- * @param {string} id
5518
- * @param {object} element
5519
- *
5520
- * @returns {string}
5545
+ /**
5546
+ * Accesses the global TooltipContext and returns a tooltip for a given id and element.
5547
+ *
5548
+ * @example
5549
+ * ```jsx
5550
+ * function TextField(props) {
5551
+ * const tooltip = useTooltipContext('input1', element);
5552
+ * }
5553
+ * ```
5554
+ *
5555
+ * @param {string} id
5556
+ * @param {object} element
5557
+ *
5558
+ * @returns {string}
5521
5559
  */
5522
5560
  function useTooltipContext(id, element) {
5523
5561
  const {
@@ -5669,20 +5707,20 @@ function prefixId$9(id) {
5669
5707
  return `bio-properties-panel-${id}`;
5670
5708
  }
5671
5709
 
5672
- /**
5673
- * Accesses the global DescriptionContext and returns a description for a given id and element.
5674
- *
5675
- * @example
5676
- * ```jsx
5677
- * function TextField(props) {
5678
- * const description = useDescriptionContext('input1', element);
5679
- * }
5680
- * ```
5681
- *
5682
- * @param {string} id
5683
- * @param {object} element
5684
- *
5685
- * @returns {string}
5710
+ /**
5711
+ * Accesses the global DescriptionContext and returns a description for a given id and element.
5712
+ *
5713
+ * @example
5714
+ * ```jsx
5715
+ * function TextField(props) {
5716
+ * const description = useDescriptionContext('input1', element);
5717
+ * }
5718
+ * ```
5719
+ *
5720
+ * @param {string} id
5721
+ * @param {object} element
5722
+ *
5723
+ * @returns {string}
5686
5724
  */
5687
5725
  function useDescriptionContext(id, element) {
5688
5726
  const {
@@ -5703,11 +5741,11 @@ function useErrors() {
5703
5741
  return errors;
5704
5742
  }
5705
5743
 
5706
- /**
5707
- * Subscribe to an event immediately. Update subscription after inputs changed.
5708
- *
5709
- * @param {string} event
5710
- * @param {Function} callback
5744
+ /**
5745
+ * Subscribe to an event immediately. Update subscription after inputs changed.
5746
+ *
5747
+ * @param {string} event
5748
+ * @param {Function} callback
5711
5749
  */
5712
5750
  function useEvent(event, callback, eventBus) {
5713
5751
  const eventContext = useContext(EventContext);
@@ -5737,20 +5775,20 @@ function useEvent(event, callback, eventBus) {
5737
5775
  }, [callback, event, eventBus]);
5738
5776
  }
5739
5777
 
5740
- /**
5741
- * Creates a state that persists in the global LayoutContext.
5742
- *
5743
- * @example
5744
- * ```jsx
5745
- * function Group(props) {
5746
- * const [ open, setOpen ] = useLayoutState([ 'groups', 'foo', 'open' ], false);
5747
- * }
5748
- * ```
5749
- *
5750
- * @param {(string|number)[]} path
5751
- * @param {any} [defaultValue]
5752
- *
5753
- * @returns {[ any, Function ]}
5778
+ /**
5779
+ * Creates a state that persists in the global LayoutContext.
5780
+ *
5781
+ * @example
5782
+ * ```jsx
5783
+ * function Group(props) {
5784
+ * const [ open, setOpen ] = useLayoutState([ 'groups', 'foo', 'open' ], false);
5785
+ * }
5786
+ * ```
5787
+ *
5788
+ * @param {(string|number)[]} path
5789
+ * @param {any} [defaultValue]
5790
+ *
5791
+ * @returns {[ any, Function ]}
5754
5792
  */
5755
5793
  function useLayoutState(path, defaultValue) {
5756
5794
  const {
@@ -5764,11 +5802,11 @@ function useLayoutState(path, defaultValue) {
5764
5802
  return [layoutForKey, setState];
5765
5803
  }
5766
5804
 
5767
- /**
5768
- * @pinussilvestrus: we need to introduce our own hook to persist the previous
5769
- * state on updates.
5770
- *
5771
- * cf. https://reactjs.org/docs/hooks-faq.html#how-to-get-the-previous-props-or-state
5805
+ /**
5806
+ * @pinussilvestrus: we need to introduce our own hook to persist the previous
5807
+ * state on updates.
5808
+ *
5809
+ * cf. https://reactjs.org/docs/hooks-faq.html#how-to-get-the-previous-props-or-state
5772
5810
  */
5773
5811
 
5774
5812
  function usePrevious(value) {
@@ -5779,12 +5817,12 @@ function usePrevious(value) {
5779
5817
  return ref.current;
5780
5818
  }
5781
5819
 
5782
- /**
5783
- * Subscribe to `propertiesPanel.showEntry`.
5784
- *
5785
- * @param {string} id
5786
- *
5787
- * @returns {import('preact').Ref}
5820
+ /**
5821
+ * Subscribe to `propertiesPanel.showEntry`.
5822
+ *
5823
+ * @param {string} id
5824
+ *
5825
+ * @returns {import('preact').Ref}
5788
5826
  */
5789
5827
  function useShowEntryEvent(id) {
5790
5828
  const {
@@ -5815,20 +5853,20 @@ function useShowEntryEvent(id) {
5815
5853
  return ref;
5816
5854
  }
5817
5855
 
5818
- /**
5819
- * @callback setSticky
5820
- * @param {boolean} value
5856
+ /**
5857
+ * @callback setSticky
5858
+ * @param {boolean} value
5821
5859
  */
5822
5860
 
5823
- /**
5824
- * Use IntersectionObserver to identify when DOM element is in sticky mode.
5825
- * If sticky is observered setSticky(true) will be called.
5826
- * If sticky mode is left, setSticky(false) will be called.
5827
- *
5828
- *
5829
- * @param {Object} ref
5830
- * @param {string} scrollContainerSelector
5831
- * @param {setSticky} setSticky
5861
+ /**
5862
+ * Use IntersectionObserver to identify when DOM element is in sticky mode.
5863
+ * If sticky is observered setSticky(true) will be called.
5864
+ * If sticky mode is left, setSticky(false) will be called.
5865
+ *
5866
+ *
5867
+ * @param {Object} ref
5868
+ * @param {string} scrollContainerSelector
5869
+ * @param {setSticky} setSticky
5832
5870
  */
5833
5871
  function useStickyIntersectionObserver(ref, scrollContainerSelector, setSticky) {
5834
5872
  const [scrollContainer, setScrollContainer] = useState(query(scrollContainerSelector));
@@ -5882,19 +5920,19 @@ function useStickyIntersectionObserver(ref, scrollContainerSelector, setSticky)
5882
5920
  }, [ref.current, scrollContainer, setSticky]);
5883
5921
  }
5884
5922
 
5885
- /**
5886
- * Creates a static function reference with changing body.
5887
- * This is necessary when external libraries require a callback function
5888
- * that has references to state variables.
5889
- *
5890
- * Usage:
5891
- * const callback = useStaticCallback((val) => {val === currentState});
5892
- *
5893
- * The `callback` reference is static and can be safely used in external
5894
- * libraries or as a prop that does not cause rerendering of children.
5895
- *
5896
- * @param {Function} callback function with changing reference
5897
- * @returns {Function} static function reference
5923
+ /**
5924
+ * Creates a static function reference with changing body.
5925
+ * This is necessary when external libraries require a callback function
5926
+ * that has references to state variables.
5927
+ *
5928
+ * Usage:
5929
+ * const callback = useStaticCallback((val) => {val === currentState});
5930
+ *
5931
+ * The `callback` reference is static and can be safely used in external
5932
+ * libraries or as a prop that does not cause rerendering of children.
5933
+ *
5934
+ * @param {Function} callback function with changing reference
5935
+ * @returns {Function} static function reference
5898
5936
  */
5899
5937
  function useStaticCallback(callback) {
5900
5938
  const callbackRef = useRef(callback);
@@ -6035,13 +6073,13 @@ function DataMarker(props) {
6035
6073
  return null;
6036
6074
  }
6037
6075
 
6038
- /**
6039
- * @typedef { {
6040
- * text: (element: object) => string,
6041
- * icon?: (element: Object) => import('preact').Component
6042
- * } } PlaceholderDefinition
6043
- *
6044
- * @param { PlaceholderDefinition } props
6076
+ /**
6077
+ * @typedef { {
6078
+ * text: (element: object) => string,
6079
+ * icon?: (element: Object) => import('preact').Component
6080
+ * } } PlaceholderDefinition
6081
+ *
6082
+ * @param { PlaceholderDefinition } props
6045
6083
  */
6046
6084
  function Placeholder(props) {
6047
6085
  const {
@@ -6078,9 +6116,9 @@ function Description$1(props) {
6078
6116
  }
6079
6117
  const noop$6 = () => {};
6080
6118
 
6081
- /**
6082
- * Buffer `.focus()` calls while the editor is not initialized.
6083
- * Set Focus inside when the editor is ready.
6119
+ /**
6120
+ * Buffer `.focus()` calls while the editor is not initialized.
6121
+ * Set Focus inside when the editor is ready.
6084
6122
  */
6085
6123
  const useBufferedFocus$1 = function (editor, ref) {
6086
6124
  const [buffer, setBuffer] = useState(undefined);
@@ -6180,9 +6218,9 @@ const CodeEditor$1 = forwardRef((props, ref) => {
6180
6218
  });
6181
6219
  const noop$5 = () => {};
6182
6220
 
6183
- /**
6184
- * Buffer `.focus()` calls while the editor is not initialized.
6185
- * Set Focus inside when the editor is ready.
6221
+ /**
6222
+ * Buffer `.focus()` calls while the editor is not initialized.
6223
+ * Set Focus inside when the editor is ready.
6186
6224
  */
6187
6225
  const useBufferedFocus = function (editor, ref) {
6188
6226
  const [buffer, setBuffer] = useState(undefined);
@@ -6231,10 +6269,10 @@ const CodeEditor = forwardRef((props, ref) => {
6231
6269
  useEffect(() => {
6232
6270
  let editor;
6233
6271
 
6234
- /* Trigger FEEL toggle when
6235
- *
6236
- * - `backspace` is pressed
6237
- * - AND the cursor is at the beginning of the input
6272
+ /* Trigger FEEL toggle when
6273
+ *
6274
+ * - `backspace` is pressed
6275
+ * - AND the cursor is at the beginning of the input
6238
6276
  */
6239
6277
  const onKeyDown = e => {
6240
6278
  if (e.key !== 'Backspace' || !editor) {
@@ -6323,10 +6361,10 @@ function FeelIndicator(props) {
6323
6361
  }
6324
6362
  const noop$4 = () => {};
6325
6363
 
6326
- /**
6327
- * @param {Object} props
6328
- * @param {Object} props.label
6329
- * @param {String} props.feel
6364
+ /**
6365
+ * @param {Object} props
6366
+ * @param {Object} props.label
6367
+ * @param {String} props.feel
6330
6368
  */
6331
6369
  function FeelIcon(props) {
6332
6370
  const {
@@ -6360,22 +6398,22 @@ const FeelPopupContext = createContext({
6360
6398
  source: null
6361
6399
  });
6362
6400
 
6363
- /**
6364
- * Add a dragger that calls back the passed function with
6365
- * { event, delta } on drag.
6366
- *
6367
- * @example
6368
- *
6369
- * function dragMove(event, delta) {
6370
- * // we are dragging (!!)
6371
- * }
6372
- *
6373
- * domElement.addEventListener('dragstart', dragger(dragMove));
6374
- *
6375
- * @param {Function} fn
6376
- * @param {Element} [dragPreview]
6377
- *
6378
- * @return {Function} drag start callback function
6401
+ /**
6402
+ * Add a dragger that calls back the passed function with
6403
+ * { event, delta } on drag.
6404
+ *
6405
+ * @example
6406
+ *
6407
+ * function dragMove(event, delta) {
6408
+ * // we are dragging (!!)
6409
+ * }
6410
+ *
6411
+ * domElement.addEventListener('dragstart', dragger(dragMove));
6412
+ *
6413
+ * @param {Function} fn
6414
+ * @param {Element} [dragPreview]
6415
+ *
6416
+ * @return {Function} drag start callback function
6379
6417
  */
6380
6418
  function createDragger(fn, dragPreview) {
6381
6419
  let self;
@@ -6429,23 +6467,23 @@ function emptyCanvas() {
6429
6467
  }
6430
6468
  const noop$3 = () => {};
6431
6469
 
6432
- /**
6433
- * A generic popup component.
6434
- *
6435
- * @param {Object} props
6436
- * @param {HTMLElement} [props.container]
6437
- * @param {string} [props.className]
6438
- * @param {boolean} [props.delayInitialFocus]
6439
- * @param {{x: number, y: number}} [props.position]
6440
- * @param {number} [props.width]
6441
- * @param {number} [props.height]
6442
- * @param {Function} props.onClose
6443
- * @param {Function} [props.onPostActivate]
6444
- * @param {Function} [props.onPostDeactivate]
6445
- * @param {boolean} [props.returnFocus]
6446
- * @param {boolean} [props.closeOnEscape]
6447
- * @param {string} props.title
6448
- * @param {Ref} [ref]
6470
+ /**
6471
+ * A generic popup component.
6472
+ *
6473
+ * @param {Object} props
6474
+ * @param {HTMLElement} [props.container]
6475
+ * @param {string} [props.className]
6476
+ * @param {boolean} [props.delayInitialFocus]
6477
+ * @param {{x: number, y: number}} [props.position]
6478
+ * @param {number} [props.width]
6479
+ * @param {number} [props.height]
6480
+ * @param {Function} props.onClose
6481
+ * @param {Function} [props.onPostActivate]
6482
+ * @param {Function} [props.onPostDeactivate]
6483
+ * @param {boolean} [props.returnFocus]
6484
+ * @param {boolean} [props.closeOnEscape]
6485
+ * @param {string} props.title
6486
+ * @param {Ref} [ref]
6449
6487
  */
6450
6488
  function PopupComponent(props, globalRef) {
6451
6489
  const {
@@ -6663,12 +6701,12 @@ function getContainerNode(node) {
6663
6701
  const FEEL_POPUP_WIDTH = 700;
6664
6702
  const FEEL_POPUP_HEIGHT = 250;
6665
6703
 
6666
- /**
6667
- * FEEL popup component, built as a singleton. Emits lifecycle events as follows:
6668
- * - `feelPopup.open` - fired before the popup is mounted
6669
- * - `feelPopup.opened` - fired after the popup is mounted. Event context contains the DOM node of the popup
6670
- * - `feelPopup.close` - fired before the popup is unmounted. Event context contains the DOM node of the popup
6671
- * - `feelPopup.closed` - fired after the popup is unmounted
6704
+ /**
6705
+ * FEEL popup component, built as a singleton. Emits lifecycle events as follows:
6706
+ * - `feelPopup.open` - fired before the popup is mounted
6707
+ * - `feelPopup.opened` - fired after the popup is mounted. Event context contains the DOM node of the popup
6708
+ * - `feelPopup.close` - fired before the popup is unmounted. Event context contains the DOM node of the popup
6709
+ * - `feelPopup.closed` - fired after the popup is unmounted
6672
6710
  */
6673
6711
  function FEELPopupRoot(props) {
6674
6712
  const {
@@ -6678,7 +6716,8 @@ function FEELPopupRoot(props) {
6678
6716
  on() {},
6679
6717
  off() {}
6680
6718
  },
6681
- popupContainer
6719
+ popupContainer,
6720
+ getPopupLinks = () => []
6682
6721
  } = props;
6683
6722
  const prevElement = usePrevious(element);
6684
6723
  const [popupConfig, setPopupConfig] = useState({});
@@ -6753,6 +6792,7 @@ function FEELPopupRoot(props) {
6753
6792
  children: [open && jsx(FeelPopupComponent, {
6754
6793
  onClose: handleClose,
6755
6794
  container: popupContainer,
6795
+ getLinks: getPopupLinks,
6756
6796
  sourceElement: sourceElement,
6757
6797
  emit: emit,
6758
6798
  ...popupConfig
@@ -6762,6 +6802,7 @@ function FEELPopupRoot(props) {
6762
6802
  function FeelPopupComponent(props) {
6763
6803
  const {
6764
6804
  container,
6805
+ getLinks,
6765
6806
  id,
6766
6807
  hostLanguage,
6767
6808
  onInput,
@@ -6832,24 +6873,24 @@ function FeelPopupComponent(props) {
6832
6873
  height: FEEL_POPUP_HEIGHT,
6833
6874
  width: FEEL_POPUP_WIDTH,
6834
6875
  ref: popupRef,
6835
- children: [jsxs(Popup.Title, {
6876
+ children: [jsx(Popup.Title, {
6836
6877
  title: title,
6837
6878
  emit: emit,
6838
6879
  showCloseButton: true,
6839
6880
  closeButtonTooltip: "Save and close",
6840
6881
  onClose: onClose,
6841
6882
  draggable: true,
6842
- children: [type === 'feel' && jsxs("a", {
6843
- href: "https://docs.camunda.io/docs/components/modeler/feel/what-is-feel/",
6844
- target: "_blank",
6845
- class: "bio-properties-panel-feel-popup__title-link",
6846
- children: ["Learn FEEL expressions", jsx(HelpIcon, {})]
6847
- }), type === 'feelers' && jsxs("a", {
6848
- href: "https://docs.camunda.io/docs/components/modeler/forms/configuration/forms-config-templating-syntax/",
6849
- target: "_blank",
6850
- class: "bio-properties-panel-feel-popup__title-link",
6851
- children: ["Learn templating", jsx(HelpIcon, {})]
6852
- })]
6883
+ children: jsx(Fragment$1, {
6884
+ children: getLinks(type).map((link, index) => {
6885
+ return jsxs("a", {
6886
+ rel: "noreferrer",
6887
+ href: link.href,
6888
+ target: "_blank",
6889
+ class: "bio-properties-panel-feel-popup__title-link",
6890
+ children: [link.title, jsx(LaunchIcon, {})]
6891
+ }, index);
6892
+ })
6893
+ })
6853
6894
  }), jsx(Popup.Body, {
6854
6895
  children: jsxs("div", {
6855
6896
  onKeyDownCapture: onKeyDownCapture,
@@ -6892,11 +6933,11 @@ function autoCompletionOpen(element) {
6892
6933
  return element.closest('.cm-editor').querySelector('.cm-tooltip-autocomplete');
6893
6934
  }
6894
6935
 
6895
- /**
6896
- * This hook behaves like useEffect, but does not trigger on the first render.
6897
- *
6898
- * @param {Function} effect
6899
- * @param {Array} deps
6936
+ /**
6937
+ * This hook behaves like useEffect, but does not trigger on the first render.
6938
+ *
6939
+ * @param {Function} effect
6940
+ * @param {Array} deps
6900
6941
  */
6901
6942
  function useUpdateEffect(effect, deps) {
6902
6943
  const isMounted = useRef(false);
@@ -6973,19 +7014,19 @@ function ToggleSwitch(props) {
6973
7014
  });
6974
7015
  }
6975
7016
 
6976
- /**
6977
- * @param {Object} props
6978
- * @param {Object} props.element
6979
- * @param {String} props.id
6980
- * @param {String} props.description
6981
- * @param {String} props.label
6982
- * @param {String} props.switcherLabel
6983
- * @param {Boolean} props.inline
6984
- * @param {Function} props.getValue
6985
- * @param {Function} props.setValue
6986
- * @param {Function} props.onFocus
6987
- * @param {Function} props.onBlur
6988
- * @param {string|import('preact').Component} props.tooltip
7017
+ /**
7018
+ * @param {Object} props
7019
+ * @param {Object} props.element
7020
+ * @param {String} props.id
7021
+ * @param {String} props.description
7022
+ * @param {String} props.label
7023
+ * @param {String} props.switcherLabel
7024
+ * @param {Boolean} props.inline
7025
+ * @param {Function} props.getValue
7026
+ * @param {Function} props.setValue
7027
+ * @param {Function} props.onFocus
7028
+ * @param {Function} props.onBlur
7029
+ * @param {string|import('preact').Component} props.tooltip
6989
7030
  */
6990
7031
  function ToggleSwitchEntry(props) {
6991
7032
  const {
@@ -7092,22 +7133,22 @@ function NumberField(props) {
7092
7133
  });
7093
7134
  }
7094
7135
 
7095
- /**
7096
- * @param {Object} props
7097
- * @param {Boolean} props.debounce
7098
- * @param {String} props.description
7099
- * @param {Boolean} props.disabled
7100
- * @param {Object} props.element
7101
- * @param {Function} props.getValue
7102
- * @param {String} props.id
7103
- * @param {String} props.label
7104
- * @param {String} props.max
7105
- * @param {String} props.min
7106
- * @param {Function} props.setValue
7107
- * @param {Function} props.onFocus
7108
- * @param {Function} props.onBlur
7109
- * @param {String} props.step
7110
- * @param {Function} props.validate
7136
+ /**
7137
+ * @param {Object} props
7138
+ * @param {Boolean} props.debounce
7139
+ * @param {String} props.description
7140
+ * @param {Boolean} props.disabled
7141
+ * @param {Object} props.element
7142
+ * @param {Function} props.getValue
7143
+ * @param {String} props.id
7144
+ * @param {String} props.label
7145
+ * @param {String} props.max
7146
+ * @param {String} props.min
7147
+ * @param {Function} props.setValue
7148
+ * @param {Function} props.onFocus
7149
+ * @param {Function} props.onBlur
7150
+ * @param {String} props.step
7151
+ * @param {Function} props.validate
7111
7152
  */
7112
7153
  function NumberFieldEntry(props) {
7113
7154
  const {
@@ -7592,26 +7633,26 @@ forwardRef((props, ref) => {
7592
7633
  });
7593
7634
  });
7594
7635
 
7595
- /**
7596
- * @param {Object} props
7597
- * @param {Object} props.element
7598
- * @param {String} props.id
7599
- * @param {String} props.description
7600
- * @param {Boolean} props.debounce
7601
- * @param {Boolean} props.disabled
7602
- * @param {Boolean} props.feel
7603
- * @param {String} props.label
7604
- * @param {Function} props.getValue
7605
- * @param {Function} props.setValue
7606
- * @param {Function} props.tooltipContainer
7607
- * @param {Function} props.validate
7608
- * @param {Function} props.show
7609
- * @param {Function} props.example
7610
- * @param {Function} props.variables
7611
- * @param {Function} props.onFocus
7612
- * @param {Function} props.onBlur
7613
- * @param {string} [props.placeholder]
7614
- * @param {string|import('preact').Component} props.tooltip
7636
+ /**
7637
+ * @param {Object} props
7638
+ * @param {Object} props.element
7639
+ * @param {String} props.id
7640
+ * @param {String} props.description
7641
+ * @param {Boolean} props.debounce
7642
+ * @param {Boolean} props.disabled
7643
+ * @param {Boolean} props.feel
7644
+ * @param {String} props.label
7645
+ * @param {Function} props.getValue
7646
+ * @param {Function} props.setValue
7647
+ * @param {Function} props.tooltipContainer
7648
+ * @param {Function} props.validate
7649
+ * @param {Function} props.show
7650
+ * @param {Function} props.example
7651
+ * @param {Function} props.variables
7652
+ * @param {Function} props.onFocus
7653
+ * @param {Function} props.onBlur
7654
+ * @param {string} [props.placeholder]
7655
+ * @param {string|import('preact').Component} props.tooltip
7615
7656
  */
7616
7657
  function FeelEntry(props) {
7617
7658
  const {
@@ -7698,27 +7739,27 @@ function FeelEntry(props) {
7698
7739
  });
7699
7740
  }
7700
7741
 
7701
- /**
7702
- * @param {Object} props
7703
- * @param {Object} props.element
7704
- * @param {String} props.id
7705
- * @param {String} props.description
7706
- * @param {Boolean} props.debounce
7707
- * @param {Boolean} props.disabled
7708
- * @param {String} props.max
7709
- * @param {String} props.min
7710
- * @param {String} props.step
7711
- * @param {Boolean} props.feel
7712
- * @param {String} props.label
7713
- * @param {Function} props.getValue
7714
- * @param {Function} props.setValue
7715
- * @param {Function} props.tooltipContainer
7716
- * @param {Function} props.validate
7717
- * @param {Function} props.show
7718
- * @param {Function} props.example
7719
- * @param {Function} props.variables
7720
- * @param {Function} props.onFocus
7721
- * @param {Function} props.onBlur
7742
+ /**
7743
+ * @param {Object} props
7744
+ * @param {Object} props.element
7745
+ * @param {String} props.id
7746
+ * @param {String} props.description
7747
+ * @param {Boolean} props.debounce
7748
+ * @param {Boolean} props.disabled
7749
+ * @param {String} props.max
7750
+ * @param {String} props.min
7751
+ * @param {String} props.step
7752
+ * @param {Boolean} props.feel
7753
+ * @param {String} props.label
7754
+ * @param {Function} props.getValue
7755
+ * @param {Function} props.setValue
7756
+ * @param {Function} props.tooltipContainer
7757
+ * @param {Function} props.validate
7758
+ * @param {Function} props.show
7759
+ * @param {Function} props.example
7760
+ * @param {Function} props.variables
7761
+ * @param {Function} props.onFocus
7762
+ * @param {Function} props.onBlur
7722
7763
  */
7723
7764
  function FeelNumberEntry(props) {
7724
7765
  return jsx(FeelEntry, {
@@ -7728,24 +7769,24 @@ function FeelNumberEntry(props) {
7728
7769
  });
7729
7770
  }
7730
7771
 
7731
- /**
7732
- * @param {Object} props
7733
- * @param {Object} props.element
7734
- * @param {String} props.id
7735
- * @param {String} props.description
7736
- * @param {Boolean} props.debounce
7737
- * @param {Boolean} props.disabled
7738
- * @param {Boolean} props.feel
7739
- * @param {String} props.label
7740
- * @param {Function} props.getValue
7741
- * @param {Function} props.setValue
7742
- * @param {Function} props.tooltipContainer
7743
- * @param {Function} props.validate
7744
- * @param {Function} props.show
7745
- * @param {Function} props.example
7746
- * @param {Function} props.variables
7747
- * @param {Function} props.onFocus
7748
- * @param {Function} props.onBlur
7772
+ /**
7773
+ * @param {Object} props
7774
+ * @param {Object} props.element
7775
+ * @param {String} props.id
7776
+ * @param {String} props.description
7777
+ * @param {Boolean} props.debounce
7778
+ * @param {Boolean} props.disabled
7779
+ * @param {Boolean} props.feel
7780
+ * @param {String} props.label
7781
+ * @param {Function} props.getValue
7782
+ * @param {Function} props.setValue
7783
+ * @param {Function} props.tooltipContainer
7784
+ * @param {Function} props.validate
7785
+ * @param {Function} props.show
7786
+ * @param {Function} props.example
7787
+ * @param {Function} props.variables
7788
+ * @param {Function} props.onFocus
7789
+ * @param {Function} props.onBlur
7749
7790
  */
7750
7791
  function FeelToggleSwitchEntry(props) {
7751
7792
  return jsx(FeelEntry, {
@@ -7755,26 +7796,26 @@ function FeelToggleSwitchEntry(props) {
7755
7796
  });
7756
7797
  }
7757
7798
 
7758
- /**
7759
- * @param {Object} props
7760
- * @param {Object} props.element
7761
- * @param {String} props.id
7762
- * @param {String} props.description
7763
- * @param {String} props.hostLanguage
7764
- * @param {Boolean} props.singleLine
7765
- * @param {Boolean} props.debounce
7766
- * @param {Boolean} props.disabled
7767
- * @param {Boolean} props.feel
7768
- * @param {String} props.label
7769
- * @param {Function} props.getValue
7770
- * @param {Function} props.setValue
7771
- * @param {Function} props.tooltipContainer
7772
- * @param {Function} props.validate
7773
- * @param {Function} props.show
7774
- * @param {Function} props.example
7775
- * @param {Function} props.variables
7776
- * @param {Function} props.onFocus
7777
- * @param {Function} props.onBlur
7799
+ /**
7800
+ * @param {Object} props
7801
+ * @param {Object} props.element
7802
+ * @param {String} props.id
7803
+ * @param {String} props.description
7804
+ * @param {String} props.hostLanguage
7805
+ * @param {Boolean} props.singleLine
7806
+ * @param {Boolean} props.debounce
7807
+ * @param {Boolean} props.disabled
7808
+ * @param {Boolean} props.feel
7809
+ * @param {String} props.label
7810
+ * @param {Function} props.getValue
7811
+ * @param {Function} props.setValue
7812
+ * @param {Function} props.tooltipContainer
7813
+ * @param {Function} props.validate
7814
+ * @param {Function} props.show
7815
+ * @param {Function} props.example
7816
+ * @param {Function} props.variables
7817
+ * @param {Function} props.onFocus
7818
+ * @param {Function} props.onBlur
7778
7819
  */
7779
7820
  function FeelTemplatingEntry(props) {
7780
7821
  return jsx(FeelEntry, {
@@ -7842,84 +7883,85 @@ const DEFAULT_LAYOUT = {};
7842
7883
  const DEFAULT_DESCRIPTION = {};
7843
7884
  const DEFAULT_TOOLTIP = {};
7844
7885
 
7845
- /**
7846
- * @typedef { {
7847
- * component: import('preact').Component,
7848
- * id: String,
7849
- * isEdited?: Function
7850
- * } } EntryDefinition
7851
- *
7852
- * @typedef { {
7853
- * autoFocusEntry: String,
7854
- * autoOpen?: Boolean,
7855
- * entries: Array<EntryDefinition>,
7856
- * id: String,
7857
- * label: String,
7858
- * remove: (event: MouseEvent) => void
7859
- * } } ListItemDefinition
7860
- *
7861
- * @typedef { {
7862
- * add: (event: MouseEvent) => void,
7863
- * component: import('preact').Component,
7864
- * element: Object,
7865
- * id: String,
7866
- * items: Array<ListItemDefinition>,
7867
- * label: String,
7868
- * shouldOpen?: Boolean
7869
- * } } ListGroupDefinition
7870
- *
7871
- * @typedef { {
7872
- * component?: import('preact').Component,
7873
- * entries: Array<EntryDefinition>,
7874
- * id: String,
7875
- * label: String,
7876
- * shouldOpen?: Boolean
7877
- * } } GroupDefinition
7878
- *
7879
- * @typedef { {
7880
- * [id: String]: GetDescriptionFunction
7881
- * } } DescriptionConfig
7882
- *
7883
- * @typedef { {
7884
- * [id: String]: GetTooltipFunction
7885
- * } } TooltipConfig
7886
- *
7887
- * @callback { {
7888
- * @param {string} id
7889
- * @param {Object} element
7890
- * @returns {string}
7891
- * } } GetDescriptionFunction
7892
- *
7893
- * @callback { {
7894
- * @param {string} id
7895
- * @param {Object} element
7896
- * @returns {string}
7897
- * } } GetTooltipFunction
7898
- *
7899
- * @typedef { {
7900
- * getEmpty: (element: object) => import('./components/Placeholder').PlaceholderDefinition,
7901
- * getMultiple: (element: Object) => import('./components/Placeholder').PlaceholderDefinition
7902
- * } } PlaceholderProvider
7903
- *
7886
+ /**
7887
+ * @typedef { {
7888
+ * component: import('preact').Component,
7889
+ * id: String,
7890
+ * isEdited?: Function
7891
+ * } } EntryDefinition
7892
+ *
7893
+ * @typedef { {
7894
+ * autoFocusEntry: String,
7895
+ * autoOpen?: Boolean,
7896
+ * entries: Array<EntryDefinition>,
7897
+ * id: String,
7898
+ * label: String,
7899
+ * remove: (event: MouseEvent) => void
7900
+ * } } ListItemDefinition
7901
+ *
7902
+ * @typedef { {
7903
+ * add: (event: MouseEvent) => void,
7904
+ * component: import('preact').Component,
7905
+ * element: Object,
7906
+ * id: String,
7907
+ * items: Array<ListItemDefinition>,
7908
+ * label: String,
7909
+ * shouldOpen?: Boolean
7910
+ * } } ListGroupDefinition
7911
+ *
7912
+ * @typedef { {
7913
+ * component?: import('preact').Component,
7914
+ * entries: Array<EntryDefinition>,
7915
+ * id: String,
7916
+ * label: String,
7917
+ * shouldOpen?: Boolean
7918
+ * } } GroupDefinition
7919
+ *
7920
+ * @typedef { {
7921
+ * [id: String]: GetDescriptionFunction
7922
+ * } } DescriptionConfig
7923
+ *
7924
+ * @typedef { {
7925
+ * [id: String]: GetTooltipFunction
7926
+ * } } TooltipConfig
7927
+ *
7928
+ * @callback { {
7929
+ * @param {string} id
7930
+ * @param {Object} element
7931
+ * @returns {string}
7932
+ * } } GetDescriptionFunction
7933
+ *
7934
+ * @callback { {
7935
+ * @param {string} id
7936
+ * @param {Object} element
7937
+ * @returns {string}
7938
+ * } } GetTooltipFunction
7939
+ *
7940
+ * @typedef { {
7941
+ * getEmpty: (element: object) => import('./components/Placeholder').PlaceholderDefinition,
7942
+ * getMultiple: (element: Object) => import('./components/Placeholder').PlaceholderDefinition
7943
+ * } } PlaceholderProvider
7944
+ *
7904
7945
  */
7905
7946
 
7906
- /**
7907
- * A basic properties panel component. Describes *how* content will be rendered, accepts
7908
- * data from implementor to describe *what* will be rendered.
7909
- *
7910
- * @param {Object} props
7911
- * @param {Object|Array} props.element
7912
- * @param {import('./components/Header').HeaderProvider} props.headerProvider
7913
- * @param {PlaceholderProvider} [props.placeholderProvider]
7914
- * @param {Array<GroupDefinition|ListGroupDefinition>} props.groups
7915
- * @param {Object} [props.layoutConfig]
7916
- * @param {Function} [props.layoutChanged]
7917
- * @param {DescriptionConfig} [props.descriptionConfig]
7918
- * @param {Function} [props.descriptionLoaded]
7919
- * @param {TooltipConfig} [props.tooltipConfig]
7920
- * @param {Function} [props.tooltipLoaded]
7921
- * @param {HTMLElement} [props.feelPopupContainer]
7922
- * @param {Object} [props.eventBus]
7947
+ /**
7948
+ * A basic properties panel component. Describes *how* content will be rendered, accepts
7949
+ * data from implementor to describe *what* will be rendered.
7950
+ *
7951
+ * @param {Object} props
7952
+ * @param {Object|Array} props.element
7953
+ * @param {import('./components/Header').HeaderProvider} props.headerProvider
7954
+ * @param {PlaceholderProvider} [props.placeholderProvider]
7955
+ * @param {Array<GroupDefinition|ListGroupDefinition>} props.groups
7956
+ * @param {Object} [props.layoutConfig]
7957
+ * @param {Function} [props.layoutChanged]
7958
+ * @param {DescriptionConfig} [props.descriptionConfig]
7959
+ * @param {Function} [props.descriptionLoaded]
7960
+ * @param {TooltipConfig} [props.tooltipConfig]
7961
+ * @param {Function} [props.tooltipLoaded]
7962
+ * @param {HTMLElement} [props.feelPopupContainer]
7963
+ * @param {Function} [props.getFeelPopupLinks]
7964
+ * @param {Object} [props.eventBus]
7923
7965
  */
7924
7966
  function PropertiesPanel$1(props) {
7925
7967
  const {
@@ -7934,6 +7976,7 @@ function PropertiesPanel$1(props) {
7934
7976
  tooltipConfig,
7935
7977
  tooltipLoaded,
7936
7978
  feelPopupContainer,
7979
+ getFeelPopupLinks,
7937
7980
  eventBus
7938
7981
  } = props;
7939
7982
 
@@ -8038,6 +8081,7 @@ function PropertiesPanel$1(props) {
8038
8081
  element: element,
8039
8082
  eventBus: eventBus,
8040
8083
  popupContainer: feelPopupContainer,
8084
+ getPopupLinks: getFeelPopupLinks,
8041
8085
  children: jsxs("div", {
8042
8086
  class: "bio-properties-panel",
8043
8087
  children: [jsx(Header, {
@@ -8090,11 +8134,11 @@ function createTooltipContext(overrides = {}) {
8090
8134
 
8091
8135
  // hooks //////////////////
8092
8136
 
8093
- /**
8094
- * This hook behaves like useLayoutEffect, but does not trigger on the first render.
8095
- *
8096
- * @param {Function} effect
8097
- * @param {Array} deps
8137
+ /**
8138
+ * This hook behaves like useLayoutEffect, but does not trigger on the first render.
8139
+ *
8140
+ * @param {Function} effect
8141
+ * @param {Array} deps
8098
8142
  */
8099
8143
  function useUpdateLayoutEffect(effect, deps) {
8100
8144
  const isMounted = useRef(false);
@@ -8107,20 +8151,20 @@ function useUpdateLayoutEffect(effect, deps) {
8107
8151
  }, deps);
8108
8152
  }
8109
8153
 
8110
- /**
8111
- * @typedef { {
8112
- * [key: string]: string;
8113
- * } } TranslateReplacements
8154
+ /**
8155
+ * @typedef { {
8156
+ * [key: string]: string;
8157
+ * } } TranslateReplacements
8114
8158
  */
8115
8159
 
8116
- /**
8117
- * A simple translation stub to be used for multi-language support.
8118
- * Can be easily replaced with a more sophisticated solution.
8119
- *
8120
- * @param {string} template to interpolate
8121
- * @param {TranslateReplacements} [replacements] a map with substitutes
8122
- *
8123
- * @return {string} the translated string
8160
+ /**
8161
+ * A simple translation stub to be used for multi-language support.
8162
+ * Can be easily replaced with a more sophisticated solution.
8163
+ *
8164
+ * @param {string} template to interpolate
8165
+ * @param {TranslateReplacements} [replacements] a map with substitutes
8166
+ *
8167
+ * @return {string} the translated string
8124
8168
  */
8125
8169
  function translateFallback(template, replacements) {
8126
8170
  replacements = replacements || {};
@@ -8229,8 +8273,8 @@ function ListItem(props) {
8229
8273
  }
8230
8274
  const noop$1 = () => {};
8231
8275
 
8232
- /**
8233
- * @param {import('../PropertiesPanel').ListGroupDefinition} props
8276
+ /**
8277
+ * @param {import('../PropertiesPanel').ListGroupDefinition} props
8234
8278
  */
8235
8279
  function ListGroup(props) {
8236
8280
  const {
@@ -8421,18 +8465,18 @@ function Checkbox(props) {
8421
8465
  });
8422
8466
  }
8423
8467
 
8424
- /**
8425
- * @param {Object} props
8426
- * @param {Object} props.element
8427
- * @param {String} props.id
8428
- * @param {String} props.description
8429
- * @param {String} props.label
8430
- * @param {Function} props.getValue
8431
- * @param {Function} props.setValue
8432
- * @param {Function} props.onFocus
8433
- * @param {Function} props.onBlur
8434
- * @param {string|import('preact').Component} props.tooltip
8435
- * @param {boolean} [props.disabled]
8468
+ /**
8469
+ * @param {Object} props
8470
+ * @param {Object} props.element
8471
+ * @param {String} props.id
8472
+ * @param {String} props.description
8473
+ * @param {String} props.label
8474
+ * @param {Function} props.getValue
8475
+ * @param {Function} props.setValue
8476
+ * @param {Function} props.onFocus
8477
+ * @param {Function} props.onBlur
8478
+ * @param {string|import('preact').Component} props.tooltip
8479
+ * @param {boolean} [props.disabled]
8436
8480
  */
8437
8481
  function CheckboxEntry(props) {
8438
8482
  const {
@@ -8552,20 +8596,20 @@ function Select(props) {
8552
8596
  });
8553
8597
  }
8554
8598
 
8555
- /**
8556
- * @param {object} props
8557
- * @param {object} props.element
8558
- * @param {string} props.id
8559
- * @param {string} [props.description]
8560
- * @param {string} props.label
8561
- * @param {Function} props.getValue
8562
- * @param {Function} props.setValue
8563
- * @param {Function} props.onFocus
8564
- * @param {Function} props.onBlur
8565
- * @param {Function} props.getOptions
8566
- * @param {boolean} [props.disabled]
8567
- * @param {Function} [props.validate]
8568
- * @param {string|import('preact').Component} props.tooltip
8599
+ /**
8600
+ * @param {object} props
8601
+ * @param {object} props.element
8602
+ * @param {string} props.id
8603
+ * @param {string} [props.description]
8604
+ * @param {string} props.label
8605
+ * @param {Function} props.getValue
8606
+ * @param {Function} props.setValue
8607
+ * @param {Function} props.onFocus
8608
+ * @param {Function} props.onBlur
8609
+ * @param {Function} props.getOptions
8610
+ * @param {boolean} [props.disabled]
8611
+ * @param {Function} [props.validate]
8612
+ * @param {string|import('preact').Component} props.tooltip
8569
8613
  */
8570
8614
  function SelectEntry(props) {
8571
8615
  const {
@@ -8856,20 +8900,20 @@ function Textfield(props) {
8856
8900
  });
8857
8901
  }
8858
8902
 
8859
- /**
8860
- * @param {Object} props
8861
- * @param {Object} props.element
8862
- * @param {String} props.id
8863
- * @param {String} props.description
8864
- * @param {Boolean} props.debounce
8865
- * @param {Boolean} props.disabled
8866
- * @param {String} props.label
8867
- * @param {Function} props.getValue
8868
- * @param {Function} props.setValue
8869
- * @param {Function} props.onFocus
8870
- * @param {Function} props.onBlur
8871
- * @param {string|import('preact').Component} props.tooltip
8872
- * @param {Function} props.validate
8903
+ /**
8904
+ * @param {Object} props
8905
+ * @param {Object} props.element
8906
+ * @param {String} props.id
8907
+ * @param {String} props.description
8908
+ * @param {Boolean} props.debounce
8909
+ * @param {Boolean} props.disabled
8910
+ * @param {String} props.label
8911
+ * @param {Function} props.getValue
8912
+ * @param {Function} props.setValue
8913
+ * @param {Function} props.onFocus
8914
+ * @param {Function} props.onBlur
8915
+ * @param {string|import('preact').Component} props.tooltip
8916
+ * @param {Function} props.validate
8873
8917
  */
8874
8918
  function TextfieldEntry(props) {
8875
8919
  const {
@@ -8944,20 +8988,20 @@ class FeelPopupModule {
8944
8988
  this._eventBus = eventBus;
8945
8989
  }
8946
8990
 
8947
- /**
8948
- * Check if the FEEL popup is open.
8949
- * @return {Boolean}
8991
+ /**
8992
+ * Check if the FEEL popup is open.
8993
+ * @return {Boolean}
8950
8994
  */
8951
8995
  isOpen() {
8952
8996
  return this._eventBus.fire('feelPopup._isOpen');
8953
8997
  }
8954
8998
 
8955
- /**
8956
- * Open the FEEL popup.
8957
- *
8958
- * @param {String} entryId
8959
- * @param {Object} popupConfig
8960
- * @param {HTMLElement} sourceElement
8999
+ /**
9000
+ * Open the FEEL popup.
9001
+ *
9002
+ * @param {String} entryId
9003
+ * @param {Object} popupConfig
9004
+ * @param {HTMLElement} sourceElement
8961
9005
  */
8962
9006
  open(entryId, popupConfig, sourceElement) {
8963
9007
  return this._eventBus.fire('feelPopup._open', {
@@ -8967,8 +9011,8 @@ class FeelPopupModule {
8967
9011
  });
8968
9012
  }
8969
9013
 
8970
- /**
8971
- * Close the FEEL popup.
9014
+ /**
9015
+ * Close the FEEL popup.
8972
9016
  */
8973
9017
  close() {
8974
9018
  return this._eventBus.fire('feelPopup._close');
@@ -9465,7 +9509,7 @@ function isProhibitedPath(path) {
9465
9509
  const prohibitedSegments = ['__proto__', 'prototype', 'constructor'];
9466
9510
  return path.split('.').some(segment => prohibitedSegments.includes(segment));
9467
9511
  }
9468
- const LABELED_NON_INPUTS = ['button', 'group', 'dynamiclist', 'iframe', 'table'];
9512
+ const LABELED_NON_INPUTS = ['button', 'group', 'dynamiclist', 'iframe', 'table', 'documentPreview'];
9469
9513
  const INPUTS = ['checkbox', 'checklist', 'datetime', 'number', 'radio', 'select', 'taglist', 'textfield', 'textarea', 'filepicker'];
9470
9514
  const OPTIONS_INPUTS = ['checklist', 'radio', 'select', 'taglist'];
9471
9515
  function hasEntryConfigured(formFieldDefinition, entryId) {
@@ -10312,7 +10356,7 @@ function LabelEntry(props) {
10312
10356
  return field.type === 'datetime' && (field.subtype === DATETIME_SUBTYPES.TIME || field.subtype === DATETIME_SUBTYPES.DATETIME);
10313
10357
  }
10314
10358
  });
10315
- const isSimplyLabled = field => {
10359
+ const isSimplyLabeled = field => {
10316
10360
  return [...INPUTS.filter(input => input !== 'datetime'), ...LABELED_NON_INPUTS].includes(field.type);
10317
10361
  };
10318
10362
  entries.push({
@@ -10321,7 +10365,7 @@ function LabelEntry(props) {
10321
10365
  editField,
10322
10366
  field,
10323
10367
  isEdited: isEdited$6,
10324
- isDefaultVisible: isSimplyLabled
10368
+ isDefaultVisible: isSimplyLabeled
10325
10369
  });
10326
10370
  return entries;
10327
10371
  }
@@ -10425,6 +10469,7 @@ function getLabelText(type) {
10425
10469
  case 'table':
10426
10470
  return 'Table label';
10427
10471
  case 'iframe':
10472
+ case 'documentPreview':
10428
10473
  return 'Title';
10429
10474
  default:
10430
10475
  return 'Field label';
@@ -10481,7 +10526,7 @@ function Height(props) {
10481
10526
  id,
10482
10527
  getValue,
10483
10528
  setValue,
10484
- validate: validate$7
10529
+ validate: validate$a
10485
10530
  });
10486
10531
  }
10487
10532
 
@@ -10491,7 +10536,7 @@ function Height(props) {
10491
10536
  * @param {number|void} value
10492
10537
  * @returns {string|null}
10493
10538
  */
10494
- const validate$7 = value => {
10539
+ const validate$a = value => {
10495
10540
  if (typeof value !== 'number') {
10496
10541
  return 'A number is required.';
10497
10542
  }
@@ -10556,7 +10601,7 @@ function Url(props) {
10556
10601
  setValue,
10557
10602
  singleLine: true,
10558
10603
  tooltip: getTooltip$1(),
10559
- validate: validate$6,
10604
+ validate: validate$9,
10560
10605
  variables
10561
10606
  });
10562
10607
  }
@@ -10583,7 +10628,7 @@ function getTooltip$1() {
10583
10628
  * @param {string|void} value
10584
10629
  * @returns {string|null}
10585
10630
  */
10586
- const validate$6 = value => {
10631
+ const validate$9 = value => {
10587
10632
  if (!value || value.startsWith('=')) {
10588
10633
  return;
10589
10634
  }
@@ -10674,7 +10719,7 @@ function Text(props) {
10674
10719
  };
10675
10720
  return FeelTemplatingEntry({
10676
10721
  debounce,
10677
- description: description$2,
10722
+ description: description$4,
10678
10723
  element: field,
10679
10724
  getValue,
10680
10725
  id,
@@ -10684,7 +10729,7 @@ function Text(props) {
10684
10729
  variables
10685
10730
  });
10686
10731
  }
10687
- const description$2 = jsxs(Fragment$1, {
10732
+ const description$4 = jsxs(Fragment$1, {
10688
10733
  children: ["Supports markdown and templating.", ' ', jsx("a", {
10689
10734
  href: "https://docs.camunda.io/docs/components/modeler/forms/form-element-library/forms-element-library-text/",
10690
10735
  target: "_blank",
@@ -10726,13 +10771,13 @@ function Content(props) {
10726
10771
  };
10727
10772
  return FeelTemplatingEntry({
10728
10773
  debounce,
10729
- description: description$1,
10774
+ description: description$3,
10730
10775
  element: field,
10731
10776
  getValue,
10732
10777
  id,
10733
10778
  label: 'Content',
10734
10779
  hostLanguage: 'html',
10735
- validate: validate$5,
10780
+ validate: validate$8,
10736
10781
  setValue,
10737
10782
  variables
10738
10783
  });
@@ -10740,7 +10785,7 @@ function Content(props) {
10740
10785
 
10741
10786
  // helpers //////////
10742
10787
 
10743
- const description$1 = jsxs(Fragment$1, {
10788
+ const description$3 = jsxs(Fragment$1, {
10744
10789
  children: ["Supports HTML, styling, and templating. Styles are automatically scoped to the HTML component.", ' ', jsx("a", {
10745
10790
  href: "https://docs.camunda.io/docs/components/modeler/forms/form-element-library/forms-element-library-html/",
10746
10791
  target: "_blank",
@@ -10752,7 +10797,7 @@ const description$1 = jsxs(Fragment$1, {
10752
10797
  * @param {string|void} value
10753
10798
  * @returns {string|null}
10754
10799
  */
10755
- const validate$5 = value => {
10800
+ const validate$8 = value => {
10756
10801
  // allow empty state
10757
10802
  if (typeof value !== 'string' || value === '') {
10758
10803
  return null;
@@ -11591,7 +11636,7 @@ function InputValuesKey(props) {
11591
11636
  id,
11592
11637
  label: 'Input values key',
11593
11638
  setValue,
11594
- validate: validate$4
11639
+ validate: validate$7
11595
11640
  });
11596
11641
  }
11597
11642
 
@@ -11601,7 +11646,7 @@ function InputValuesKey(props) {
11601
11646
  * @param {string|void} value
11602
11647
  * @returns {string|null}
11603
11648
  */
11604
- const validate$4 = value => {
11649
+ const validate$7 = value => {
11605
11650
  if (typeof value !== 'string' || value.length === 0) {
11606
11651
  return 'Must not be empty.';
11607
11652
  }
@@ -12044,7 +12089,7 @@ function Source(props) {
12044
12089
  setValue,
12045
12090
  singleLine: true,
12046
12091
  variables,
12047
- validate: validate$3
12092
+ validate: validate$6
12048
12093
  });
12049
12094
  }
12050
12095
 
@@ -12054,7 +12099,7 @@ function Source(props) {
12054
12099
  * @param {string|void} value
12055
12100
  * @returns {string|null}
12056
12101
  */
12057
- const validate$3 = value => {
12102
+ const validate$6 = value => {
12058
12103
  if (!isString(value) || value.length === 0) {
12059
12104
  return 'Must not be empty.';
12060
12105
  }
@@ -12158,7 +12203,7 @@ function RowCount(props) {
12158
12203
  id,
12159
12204
  getValue,
12160
12205
  setValue,
12161
- validate: validate$2
12206
+ validate: validate$5
12162
12207
  });
12163
12208
  }
12164
12209
 
@@ -12168,7 +12213,7 @@ function RowCount(props) {
12168
12213
  * @param {string|void} value
12169
12214
  * @returns {string|null}
12170
12215
  */
12171
- const validate$2 = value => {
12216
+ const validate$5 = value => {
12172
12217
  if (isNil(value)) {
12173
12218
  return null;
12174
12219
  }
@@ -12342,7 +12387,7 @@ function ColumnsExpression(props) {
12342
12387
  setValue,
12343
12388
  singleLine: true,
12344
12389
  variables,
12345
- validate: validate$1
12390
+ validate: validate$4
12346
12391
  });
12347
12392
  }
12348
12393
 
@@ -12352,7 +12397,7 @@ function ColumnsExpression(props) {
12352
12397
  * @param {string|void} value
12353
12398
  * @returns {string|null}
12354
12399
  */
12355
- const validate$1 = value => {
12400
+ const validate$4 = value => {
12356
12401
  if (!isString(value) || value.length === 0 || value === '=') {
12357
12402
  return 'Must not be empty.';
12358
12403
  }
@@ -12450,7 +12495,7 @@ function Key(props) {
12450
12495
  id,
12451
12496
  label: 'Key',
12452
12497
  setValue,
12453
- validate
12498
+ validate: validate$3
12454
12499
  });
12455
12500
  }
12456
12501
 
@@ -12460,7 +12505,7 @@ function Key(props) {
12460
12505
  * @param {string|void} value
12461
12506
  * @returns {string|null}
12462
12507
  */
12463
- function validate(value) {
12508
+ function validate$3(value) {
12464
12509
  if (!isString(value) || value.length === 0) {
12465
12510
  return 'Must not be empty.';
12466
12511
  }
@@ -12598,13 +12643,13 @@ function Accept(props) {
12598
12643
  singleLine: true,
12599
12644
  setValue,
12600
12645
  variables,
12601
- description
12646
+ description: description$2
12602
12647
  });
12603
12648
  }
12604
12649
 
12605
12650
  // helpers //////////
12606
12651
 
12607
- const description = jsxs(Fragment$1, {
12652
+ const description$2 = jsxs(Fragment$1, {
12608
12653
  children: ["A comma-separated list of", ' ', jsx("a", {
12609
12654
  href: "https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#unique_file_type_specifiers",
12610
12655
  target: "_blank",
@@ -12658,6 +12703,236 @@ function Multiple(props) {
12658
12703
  });
12659
12704
  }
12660
12705
 
12706
+ function DocumentsDataSourceEntry(props) {
12707
+ const {
12708
+ editField,
12709
+ field
12710
+ } = props;
12711
+ const entries = [];
12712
+ entries.push({
12713
+ id: 'dataSource',
12714
+ component: DocumentsDataSource,
12715
+ editField: editField,
12716
+ field: field,
12717
+ isEdited: isEdited$6,
12718
+ isDefaultVisible: field => field.type === 'documentPreview'
12719
+ });
12720
+ return entries;
12721
+ }
12722
+ function DocumentsDataSource(props) {
12723
+ const {
12724
+ editField,
12725
+ field,
12726
+ id
12727
+ } = props;
12728
+ const debounce = useService('debounce');
12729
+ const variables = useVariables().map(name => ({
12730
+ name
12731
+ }));
12732
+ const path = ['dataSource'];
12733
+ const getValue = () => {
12734
+ return get(field, path, '');
12735
+ };
12736
+ const setValue = value => {
12737
+ return editField(field, path, value);
12738
+ };
12739
+ const schema = `[
12740
+ {
12741
+ "documentId": "u123",
12742
+ "metadata": {
12743
+ "fileName": "Document.pdf",
12744
+ "contentType": "application/pdf"
12745
+ }
12746
+ }
12747
+ ]`;
12748
+ const tooltip = jsxs("div", {
12749
+ children: [jsx("p", {
12750
+ children: "A source is a JSON object containing metadata for a document or an array of documents."
12751
+ }), jsx("p", {
12752
+ children: "Each entry must include a document ID, name, and MIME type."
12753
+ }), jsx("p", {
12754
+ children: "Additional details are optional. The expected format is as follows:"
12755
+ }), jsx("pre", {
12756
+ children: jsx("code", {
12757
+ children: schema
12758
+ })
12759
+ })]
12760
+ });
12761
+ return FeelTemplatingEntry({
12762
+ debounce,
12763
+ element: field,
12764
+ getValue,
12765
+ id,
12766
+ label: 'Document reference',
12767
+ feel: 'required',
12768
+ singleLine: true,
12769
+ setValue,
12770
+ variables,
12771
+ tooltip,
12772
+ validate: validate$2
12773
+ });
12774
+ }
12775
+
12776
+ // helpers //////////
12777
+
12778
+ /**
12779
+ * @param {string|undefined} value
12780
+ * @returns {string|null}
12781
+ */
12782
+ const validate$2 = value => {
12783
+ if (typeof value !== 'string' || value.length === 0) {
12784
+ return 'The document data source is required.';
12785
+ }
12786
+ };
12787
+
12788
+ function EndpointKeyEntry(props) {
12789
+ const {
12790
+ editField,
12791
+ field
12792
+ } = props;
12793
+ const entries = [];
12794
+ entries.push({
12795
+ id: 'endpointKey',
12796
+ component: EndpointKey,
12797
+ editField: editField,
12798
+ field: field,
12799
+ isEdited: isEdited$6,
12800
+ isDefaultVisible: field => field.type === 'documentPreview'
12801
+ });
12802
+ return entries;
12803
+ }
12804
+ function EndpointKey(props) {
12805
+ const {
12806
+ editField,
12807
+ field,
12808
+ id
12809
+ } = props;
12810
+ const debounce = useService('debounce');
12811
+ const variables = useVariables().map(name => ({
12812
+ name
12813
+ }));
12814
+ const path = ['endpointKey'];
12815
+ const getValue = () => {
12816
+ return get(field, path, '');
12817
+ };
12818
+ const setValue = value => {
12819
+ return editField(field, path, value);
12820
+ };
12821
+ const tooltip = jsxs("div", {
12822
+ children: [jsx("p", {
12823
+ children: "Enter a context key that generates a string with the API endpoint to download a document."
12824
+ }), jsxs("p", {
12825
+ children: ["The string must contain ", jsx("code", {
12826
+ children: '{ documentId }'
12827
+ }), ", which will be replaced with the document ID from the document's reference."]
12828
+ }), jsx("p", {
12829
+ children: "If you're using the Camunda Tasklist, this variable is automatically added to the context for you."
12830
+ }), jsxs("p", {
12831
+ children: ["For more details, see the", ' ', jsx("a", {
12832
+ href: "https://docs.camunda.io",
12833
+ rel: "noopener noreferrer",
12834
+ target: "_blank",
12835
+ children: "Camunda documentation"
12836
+ })]
12837
+ })]
12838
+ });
12839
+ return FeelTemplatingEntry({
12840
+ debounce,
12841
+ element: field,
12842
+ getValue,
12843
+ id,
12844
+ label: 'Document URL',
12845
+ feel: 'required',
12846
+ singleLine: true,
12847
+ setValue,
12848
+ variables,
12849
+ description: description$1,
12850
+ tooltip,
12851
+ validate: validate$1
12852
+ });
12853
+ }
12854
+
12855
+ // helpers //////////
12856
+
12857
+ /**
12858
+ * @param {string|undefined} value
12859
+ * @returns {string|null}
12860
+ */
12861
+ const validate$1 = value => {
12862
+ if (typeof value !== 'string' || value.length === 0) {
12863
+ return 'The document reference is required.';
12864
+ }
12865
+ };
12866
+ const description$1 = jsx(Fragment$1, {
12867
+ children: "Define an API URL for downloading a document"
12868
+ });
12869
+
12870
+ function MaxHeightEntry(props) {
12871
+ const {
12872
+ editField,
12873
+ field
12874
+ } = props;
12875
+ const entries = [];
12876
+ entries.push({
12877
+ id: 'maxHeight',
12878
+ component: MaxHeight,
12879
+ editField: editField,
12880
+ field: field,
12881
+ isEdited: isEdited$7,
12882
+ isDefaultVisible: field => field.type === 'documentPreview'
12883
+ });
12884
+ return entries;
12885
+ }
12886
+ function MaxHeight(props) {
12887
+ const {
12888
+ editField,
12889
+ field,
12890
+ id
12891
+ } = props;
12892
+ const debounce = useService('debounce');
12893
+ const path = ['maxHeight'];
12894
+ const getValue = () => {
12895
+ return get(field, path, '');
12896
+ };
12897
+ const setValue = value => {
12898
+ return editField(field, path, value);
12899
+ };
12900
+ return NumberFieldEntry({
12901
+ debounce,
12902
+ label: 'Max height of preview container',
12903
+ element: field,
12904
+ id,
12905
+ getValue,
12906
+ setValue,
12907
+ validate,
12908
+ description
12909
+ });
12910
+ }
12911
+
12912
+ // helpers //////////
12913
+
12914
+ /**
12915
+ * @param {string|number|undefined} value
12916
+ * @returns {string|null}
12917
+ */
12918
+ const validate = value => {
12919
+ if (value === undefined || value === '') {
12920
+ return null;
12921
+ }
12922
+ if (typeof value === 'string') {
12923
+ return 'Value must be a number.';
12924
+ }
12925
+ if (!Number.isInteger(value)) {
12926
+ return 'Should be an integer.';
12927
+ }
12928
+ if (value < 1) {
12929
+ return 'Should be greater than zero.';
12930
+ }
12931
+ };
12932
+ const description = jsx(Fragment$1, {
12933
+ children: "Documents with height that exceeds the defined value will be vertically scrollable"
12934
+ });
12935
+
12661
12936
  function GeneralGroup(field, editField, getService) {
12662
12937
  const entries = [...IdEntry({
12663
12938
  field,
@@ -12745,6 +13020,9 @@ function GeneralGroup(field, editField, getService) {
12745
13020
  }), ...RowCountEntry({
12746
13021
  field,
12747
13022
  editField
13023
+ }), ...DocumentsDataSourceEntry({
13024
+ field,
13025
+ editField
12748
13026
  })];
12749
13027
  if (entries.length === 0) {
12750
13028
  return null;
@@ -13202,6 +13480,9 @@ function AppearanceGroup(field, editField, getService) {
13202
13480
  }), ...LayouterAppearanceEntry({
13203
13481
  field,
13204
13482
  editField
13483
+ }), ...MaxHeightEntry({
13484
+ field,
13485
+ editField
13205
13486
  })];
13206
13487
  if (!entries.length) {
13207
13488
  return null;
@@ -13370,6 +13651,21 @@ const TOOLTIP_TEXT = `"List of items" defines a constant, predefined set of form
13370
13651
  "Expression" defines options that are populated from a FEEL expression.
13371
13652
  `;
13372
13653
 
13654
+ function DownloadSettings(field, editField) {
13655
+ const entries = [...EndpointKeyEntry({
13656
+ field,
13657
+ editField
13658
+ })];
13659
+ if (!entries.length) {
13660
+ return null;
13661
+ }
13662
+ return {
13663
+ id: 'downloadSettings',
13664
+ label: 'Download settings',
13665
+ entries
13666
+ };
13667
+ }
13668
+
13373
13669
  class PropertiesProvider {
13374
13670
  constructor(propertiesPanel, injector) {
13375
13671
  this._injector = injector;
@@ -13405,7 +13701,7 @@ class PropertiesProvider {
13405
13701
  return groups;
13406
13702
  }
13407
13703
  const getService = (type, strict = true) => this._injector.get(type, strict);
13408
- groups = [...groups, GeneralGroup(field, editField, getService), ...OptionsGroups(field, editField, getService), ...TableHeaderGroups(field, editField), SecurityAttributesGroup(field, editField), ConditionGroup(field, editField), LayoutGroup(field, editField), AppearanceGroup(field, editField), SerializationGroup(field, editField), ConstraintsGroup(field, editField), ValidationGroup(field, editField), CustomPropertiesGroup(field, editField)].filter(group => group != null);
13704
+ groups = [...groups, GeneralGroup(field, editField, getService), DownloadSettings(field, editField), ...OptionsGroups(field, editField, getService), ...TableHeaderGroups(field, editField), SecurityAttributesGroup(field, editField), ConditionGroup(field, editField), LayoutGroup(field, editField), AppearanceGroup(field, editField), SerializationGroup(field, editField), ConstraintsGroup(field, editField), ValidationGroup(field, editField), CustomPropertiesGroup(field, editField)].filter(group => group != null);
13409
13705
  this._filterVisibleEntries(groups, field, getService);
13410
13706
 
13411
13707
  // contract: if a group has no entries or items, it should not be displayed at all
@@ -13568,7 +13864,7 @@ class FormEditor {
13568
13864
  * @type {Element}
13569
13865
  */
13570
13866
  this._container = createFormContainer();
13571
- this._container.setAttribute('input-handle-modified-keys', 'z,y');
13867
+ this._container.setAttribute('tabindex', '0');
13572
13868
  const {
13573
13869
  container,
13574
13870
  exporter,