@bpmn-io/properties-panel 3.44.0 → 3.45.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.js CHANGED
@@ -14,7 +14,7 @@ var autocomplete = require('@codemirror/autocomplete');
14
14
  var commands = require('@codemirror/commands');
15
15
  var langJson = require('@codemirror/lang-json');
16
16
  var lint = require('@codemirror/lint');
17
- var feelers = require('feelers');
17
+ var feelersEditor = require('@bpmn-io/feelers-editor');
18
18
  var Editor = require('@bpmn-io/feel-editor');
19
19
  var focusTrap = require('focus-trap');
20
20
 
@@ -180,6 +180,28 @@ OpenPopupIcon.defaultProps = {
180
180
  viewBox: "0 0 16 16"
181
181
  };
182
182
 
183
+ /**
184
+ * @typedef { {
185
+ * [key: string]: string;
186
+ * } } TranslateReplacements
187
+ */
188
+
189
+ /**
190
+ * A simple translation stub to be used for multi-language support.
191
+ * Can be easily replaced with a more sophisticated solution.
192
+ *
193
+ * @param {string} template to interpolate
194
+ * @param {TranslateReplacements} [replacements] a map with substitutes
195
+ *
196
+ * @return {string} the translated string
197
+ */
198
+ function translateFallback(template, replacements) {
199
+ replacements = replacements || {};
200
+ return template.replace(/{([^}]+)}/g, function (_, key) {
201
+ return replacements[key] || '{' + key + '}';
202
+ });
203
+ }
204
+
183
205
  /**
184
206
  * @typedef { {
185
207
  * getElementLabel: (element: object) => string,
@@ -191,13 +213,15 @@ OpenPopupIcon.defaultProps = {
191
213
 
192
214
  /**
193
215
  * @param {Object} props
194
- * @param {Object} props.element,
216
+ * @param {Object} props.element
195
217
  * @param {HeaderProvider} props.headerProvider
218
+ * @param {Function} [props.translate]
196
219
  */
197
220
  function Header(props) {
198
221
  const {
199
222
  element,
200
- headerProvider
223
+ headerProvider,
224
+ translate = translateFallback
201
225
  } = props;
202
226
  const {
203
227
  getElementIcon,
@@ -233,7 +257,7 @@ function Header(props) {
233
257
  rel: "noreferrer",
234
258
  class: "bio-properties-panel-header-link",
235
259
  href: documentationRef,
236
- title: "Open documentation",
260
+ title: translate('Open documentation'),
237
261
  target: "_blank",
238
262
  children: jsxRuntime.jsx(ExternalLinkIcon, {})
239
263
  }) : null
@@ -863,7 +887,8 @@ function Group(props) {
863
887
  entries = [],
864
888
  id,
865
889
  label,
866
- shouldOpen = false
890
+ shouldOpen = false,
891
+ translate = translateFallback
867
892
  } = props;
868
893
  const groupRef = hooks.useRef(null);
869
894
  const [open, setOpen] = useLayoutState(['groups', id, 'open'], shouldOpen);
@@ -922,10 +947,11 @@ function Group(props) {
922
947
  class: "bio-properties-panel-group-header-buttons",
923
948
  children: [jsxRuntime.jsx(DataMarker, {
924
949
  edited: edited,
925
- hasErrors: hasErrors
950
+ hasErrors: hasErrors,
951
+ translate: translate
926
952
  }), jsxRuntime.jsx("button", {
927
953
  type: "button",
928
- title: "Toggle section",
954
+ title: translate('Toggle section'),
929
955
  class: "bio-properties-panel-group-header-button bio-properties-panel-arrow",
930
956
  children: jsxRuntime.jsx(ArrowIcon, {
931
957
  class: open ? 'bio-properties-panel-arrow-down' : 'bio-properties-panel-arrow-right'
@@ -954,17 +980,18 @@ function Group(props) {
954
980
  function DataMarker(props) {
955
981
  const {
956
982
  edited,
957
- hasErrors
983
+ hasErrors,
984
+ translate = translateFallback
958
985
  } = props;
959
986
  if (hasErrors) {
960
987
  return jsxRuntime.jsx("div", {
961
- title: "Section contains an error",
988
+ title: translate('Section contains an error'),
962
989
  class: "bio-properties-panel-dot bio-properties-panel-dot--error"
963
990
  });
964
991
  }
965
992
  if (edited) {
966
993
  return jsxRuntime.jsx("div", {
967
- title: "Section contains edits",
994
+ title: translate('Section contains edits'),
968
995
  class: "bio-properties-panel-dot"
969
996
  });
970
997
  }
@@ -1025,7 +1052,8 @@ const DEFAULT_TOOLTIP = {};
1025
1052
  * id: String,
1026
1053
  * items: Array<ListItemDefinition>,
1027
1054
  * label: String,
1028
- * shouldOpen?: Boolean
1055
+ * shouldOpen?: Boolean,
1056
+ * translate?: Function
1029
1057
  * } } ListGroupDefinition
1030
1058
  *
1031
1059
  * @typedef { {
@@ -1033,7 +1061,8 @@ const DEFAULT_TOOLTIP = {};
1033
1061
  * entries: Array<EntryDefinition>,
1034
1062
  * id: String,
1035
1063
  * label: String,
1036
- * shouldOpen?: Boolean
1064
+ * shouldOpen?: Boolean,
1065
+ * translate?: Function
1037
1066
  * } } GroupDefinition
1038
1067
  *
1039
1068
  * @typedef { {
@@ -1377,28 +1406,6 @@ function HeaderButton(props) {
1377
1406
  });
1378
1407
  }
1379
1408
 
1380
- /**
1381
- * @typedef { {
1382
- * [key: string]: string;
1383
- * } } TranslateReplacements
1384
- */
1385
-
1386
- /**
1387
- * A simple translation stub to be used for multi-language support.
1388
- * Can be easily replaced with a more sophisticated solution.
1389
- *
1390
- * @param {string} template to interpolate
1391
- * @param {TranslateReplacements} [replacements] a map with substitutes
1392
- *
1393
- * @return {string} the translated string
1394
- */
1395
- function translateFallback(template, replacements) {
1396
- replacements = replacements || {};
1397
- return template.replace(/{([^}]+)}/g, function (_, key) {
1398
- return replacements[key] || '{' + key + '}';
1399
- });
1400
- }
1401
-
1402
1409
  function CollapsibleEntry(props) {
1403
1410
  const {
1404
1411
  element,
@@ -1966,6 +1973,7 @@ function JsonEditor(props) {
1966
1973
  * @param {string} [props.placeholder]
1967
1974
  * @param {string} [props.tooltip]
1968
1975
  * @param {Function} [props.validate]
1976
+ * @param {Function} [props.translate]
1969
1977
  */
1970
1978
  function JsonEditorEntry(props) {
1971
1979
  const {
@@ -1979,24 +1987,25 @@ function JsonEditorEntry(props) {
1979
1987
  disabled,
1980
1988
  placeholder,
1981
1989
  tooltip,
1982
- validate
1990
+ validate,
1991
+ translate = translateFallback
1983
1992
  } = props;
1984
1993
  const globalError = useError(id);
1985
1994
  let value = getValue(element);
1986
- const [localError, setLocalError] = hooks.useState(() => computeError(validate, value));
1995
+ const [localError, setLocalError] = hooks.useState(() => computeError(validate, value, translate));
1987
1996
  const [editorValue, setEditorValue] = hooks.useState(value);
1988
1997
  hooks.useEffect(() => {
1989
1998
  if (value === editorValue) {
1990
1999
  return;
1991
2000
  }
1992
2001
  setEditorValue(value);
1993
- setLocalError(computeError(validate, value));
2002
+ setLocalError(computeError(validate, value, translate));
1994
2003
  }, [value, validate]);
1995
2004
  const onInput = useStaticCallback(newValue => {
1996
2005
  setEditorValue(newValue);
1997
2006
  const currentValue = getValue(element);
1998
2007
  if (newValue !== currentValue) {
1999
- const newValidationError = computeError(validate, newValue);
2008
+ const newValidationError = computeError(validate, newValue, translate);
2000
2009
  setValue(newValue, newValidationError);
2001
2010
  setLocalError(newValidationError);
2002
2011
  }
@@ -2035,15 +2044,15 @@ function isEdited$8(node) {
2035
2044
 
2036
2045
  // helpers /////////////////
2037
2046
 
2038
- function computeError(validate, value) {
2039
- return (minDash.isFunction(validate) ? validate(value) : null) || validateJson(value);
2047
+ function computeError(validate, value, translate) {
2048
+ return (minDash.isFunction(validate) ? validate(value) : null) || validateJson(value, translate);
2040
2049
  }
2041
- function validateJson(value) {
2050
+ function validateJson(value, translate = translateFallback) {
2042
2051
  if (!value || !value.trim()) return null;
2043
2052
  try {
2044
- return minDash.isObject(JSON.parse(value)) ? null : 'JSON contains errors';
2053
+ return minDash.isObject(JSON.parse(value)) ? null : translate('JSON contains errors');
2045
2054
  } catch (e) {
2046
- return 'JSON contains errors';
2055
+ return translate('JSON contains errors');
2047
2056
  }
2048
2057
  }
2049
2058
 
@@ -2053,13 +2062,14 @@ function validateJson(value) {
2053
2062
  * @param {Object} props
2054
2063
  * @param {Function} props.onClick - Callback to trigger when the button is clicked.
2055
2064
  * @param {string} [props.title] - Tooltip text for the button.
2056
- * @param {boolean} [props.disabled] - Whether the button is disabled.
2057
- * @param {string} [props.className] - Additional class names for the button.
2065
+ * @param {Function} [props.translate] - Translation function for built-in strings.
2058
2066
  */
2059
2067
  function OpenPopupButton({
2060
2068
  onClick,
2061
- title = 'Open pop-up editor'
2069
+ title,
2070
+ translate = translateFallback
2062
2071
  }) {
2072
+ title = title ?? translate('Open pop-up editor');
2063
2073
  return jsxRuntime.jsx("button", {
2064
2074
  type: "button",
2065
2075
  title: title,
@@ -2120,7 +2130,7 @@ const TemplatingEditor = compat.forwardRef((props, ref) => {
2120
2130
  });
2121
2131
  hooks.useEffect(() => {
2122
2132
  let editor;
2123
- editor = new feelers.FeelersEditor({
2133
+ editor = new feelersEditor.FeelersEditor({
2124
2134
  container: inputRef.current,
2125
2135
  onChange: handleInput,
2126
2136
  value: localValue,
@@ -2211,7 +2221,8 @@ const FeelEditor = compat.forwardRef((props, ref) => {
2211
2221
  disabled,
2212
2222
  tooltipContainer,
2213
2223
  variables,
2214
- feelLanguageContext
2224
+ feelLanguageContext,
2225
+ translate = translateFallback
2215
2226
  } = props;
2216
2227
  const inputRef = hooks.useRef();
2217
2228
  const [editor, setEditor] = hooks.useState();
@@ -2303,14 +2314,15 @@ const FeelEditor = compat.forwardRef((props, ref) => {
2303
2314
  class: classnames('bio-properties-panel-feel-editor-container', disabled ? 'disabled' : null, popupOpen ? 'popupOpen' : null),
2304
2315
  children: [popupOpen && jsxRuntime.jsx("div", {
2305
2316
  class: "bio-properties-panel-feel-editor__open-popup-placeholder",
2306
- children: "Opened in editor"
2317
+ children: translate('Opened in editor')
2307
2318
  }), jsxRuntime.jsx("div", {
2308
2319
  name: props.name,
2309
2320
  class: classnames('bio-properties-panel-input', localValue ? 'edited' : null),
2310
2321
  ref: inputRef,
2311
2322
  onClick: handleClick
2312
2323
  }), !disabled && jsxRuntime.jsx(OpenPopupButton, {
2313
- onClick: () => onOpenPopup('feel')
2324
+ onClick: () => onOpenPopup('feel'),
2325
+ translate: translate
2314
2326
  })]
2315
2327
  });
2316
2328
  });
@@ -2334,16 +2346,22 @@ const noop$3 = () => {};
2334
2346
  * @param {Object} props
2335
2347
  * @param {Object} props.label
2336
2348
  * @param {String} props.feel
2349
+ * @param {boolean} props.active
2350
+ * @param {boolean} props.disabled
2351
+ * @param {Function} props.onClick
2352
+ * @param {Function} props.translate
2353
+ * @returns {import('preact').Component}
2337
2354
  */
2338
2355
  function FeelIcon(props) {
2339
2356
  const {
2340
2357
  feel = false,
2341
2358
  active,
2342
2359
  disabled = false,
2343
- onClick = noop$3
2360
+ onClick = noop$3,
2361
+ translate = translateFallback
2344
2362
  } = props;
2345
- const feelRequiredLabel = 'FEEL expression is mandatory';
2346
- const feelOptionalLabel = `Click to ${active ? 'remove' : 'set a'} dynamic value with FEEL expression`;
2363
+ const feelRequiredLabel = translate('FEEL expression is mandatory');
2364
+ const feelOptionalLabel = translate(`Click to ${active ? 'remove' : 'set a'} dynamic value with FEEL expression`);
2347
2365
  const handleClick = e => {
2348
2366
  onClick(e);
2349
2367
 
@@ -2685,6 +2703,7 @@ const noop$2 = () => {};
2685
2703
  * @param {Array} props.variables
2686
2704
  * @param {string} [props.placeholder]
2687
2705
  * @param {string | import('preact').Component} props.tooltip
2706
+ * @param {Function} props.translate
2688
2707
  */
2689
2708
  function FeelTextfield(props) {
2690
2709
  const {
@@ -2704,7 +2723,8 @@ function FeelTextfield(props) {
2704
2723
  singleLine,
2705
2724
  tooltipContainer,
2706
2725
  OptionalComponent = OptionalFeelInput,
2707
- tooltip
2726
+ tooltip,
2727
+ translate
2708
2728
  } = props;
2709
2729
  const [localValue, setLocalValue] = hooks.useState(getInitialFeelLocalValue(feel, value));
2710
2730
  const editorRef = useShowEntryEvent(id);
@@ -2793,7 +2813,7 @@ function FeelTextfield(props) {
2793
2813
  const handleLint = useStaticCallback((lint = []) => {
2794
2814
  const syntaxError = lint.some(report => report.type === 'Syntax Error');
2795
2815
  if (syntaxError) {
2796
- onError('Unparsable FEEL expression.');
2816
+ onError(translate('Unparsable FEEL expression.'));
2797
2817
  } else {
2798
2818
  onError(undefined);
2799
2819
  }
@@ -2864,9 +2884,14 @@ function FeelTextfield(props) {
2864
2884
  });
2865
2885
  return;
2866
2886
  }
2867
- const input = event.target;
2868
- const isFieldEmpty = !input.value;
2869
- const isAllSelected = input.selectionStart === 0 && input.selectionEnd === input.value.length;
2887
+ const target = event.target;
2888
+
2889
+ // Skip for non-input/textArea elements (e.g. CodeMirror contenteditable)
2890
+ if (!(target instanceof HTMLInputElement) && !(target instanceof HTMLTextAreaElement)) {
2891
+ return;
2892
+ }
2893
+ const isFieldEmpty = !target.value;
2894
+ const isAllSelected = target.selectionStart === 0 && target.selectionEnd === target.value.length;
2870
2895
  if (isFieldEmpty || isAllSelected) {
2871
2896
  const textData = event.clipboardData.getData('text');
2872
2897
  const trimmedValue = textData.trim();
@@ -2903,7 +2928,8 @@ function FeelTextfield(props) {
2903
2928
  label: label,
2904
2929
  feel: feel,
2905
2930
  onClick: handleFeelToggle,
2906
- active: feelActive
2931
+ active: feelActive,
2932
+ translate: translate
2907
2933
  })]
2908
2934
  }), jsxRuntime.jsxs("div", {
2909
2935
  class: "bio-properties-panel-feel-container",
@@ -2934,7 +2960,8 @@ function FeelTextfield(props) {
2934
2960
  variables: variables,
2935
2961
  feelLanguageContext: feelLanguageContext,
2936
2962
  ref: editorRef,
2937
- tooltipContainer: tooltipContainer
2963
+ tooltipContainer: tooltipContainer,
2964
+ translate: translate
2938
2965
  }) : jsxRuntime.jsx(OptionalComponent, {
2939
2966
  ...props,
2940
2967
  popupOpen: isPopupOpen,
@@ -3203,7 +3230,8 @@ function FeelEntry(props) {
3203
3230
  onFocus,
3204
3231
  onBlur,
3205
3232
  placeholder,
3206
- tooltip
3233
+ tooltip,
3234
+ translate = translateFallback
3207
3235
  } = props;
3208
3236
  const [validationError, setValidationError] = hooks.useState(null);
3209
3237
  const [localError, setLocalError] = hooks.useState(null);
@@ -3252,6 +3280,7 @@ function FeelEntry(props) {
3252
3280
  hostLanguage: hostLanguage,
3253
3281
  singleLine: singleLine,
3254
3282
  show: show,
3283
+ translate: translate,
3255
3284
  value: value,
3256
3285
  variables: variables,
3257
3286
  tooltipContainer: tooltipContainer,
@@ -3665,6 +3694,7 @@ function prefixIdLabel(id) {
3665
3694
  * @param {Item[]} [props.items]
3666
3695
  * @param {boolean} [props.open]
3667
3696
  * @param {string|boolean} [props.autoFocusEntry] either a custom selector string or true to focus the first input
3697
+ * @param {Function} [props.translate]
3668
3698
  * @returns
3669
3699
  */
3670
3700
  function List(props) {
@@ -3678,6 +3708,7 @@ function List(props) {
3678
3708
  onAdd,
3679
3709
  onRemove,
3680
3710
  autoFocusEntry,
3711
+ translate = translateFallback,
3681
3712
  ...restProps
3682
3713
  } = props;
3683
3714
  const entryRef = hooks.useRef(null);
@@ -3720,20 +3751,22 @@ function List(props) {
3720
3751
  class: "bio-properties-panel-list-entry-header-buttons",
3721
3752
  children: [jsxRuntime.jsxs("button", {
3722
3753
  type: "button",
3723
- title: "Create new list item",
3754
+ title: translate('Create new list item'),
3724
3755
  onClick: addItem,
3725
3756
  class: "bio-properties-panel-add-entry",
3726
3757
  children: [jsxRuntime.jsx(CreateIcon, {}), !hasItems ? jsxRuntime.jsx("span", {
3727
3758
  class: "bio-properties-panel-add-entry-label",
3728
- children: "Create"
3759
+ children: translate('Create')
3729
3760
  }) : null]
3730
3761
  }), hasItems && jsxRuntime.jsx("div", {
3731
- title: `List contains ${items.length} item${items.length != 1 ? 's' : ''}`,
3762
+ title: translate(`List contains {numOfItems} item${items.length != 1 ? 's' : ''}`, {
3763
+ numOfItems: items.length
3764
+ }),
3732
3765
  class: "bio-properties-panel-list-badge",
3733
3766
  children: items.length
3734
3767
  }), hasItems && jsxRuntime.jsx("button", {
3735
3768
  type: "button",
3736
- title: "Toggle list item",
3769
+ title: translate('Toggle list item'),
3737
3770
  class: "bio-properties-panel-arrow",
3738
3771
  children: jsxRuntime.jsx(ArrowIcon, {
3739
3772
  class: open ? 'bio-properties-panel-arrow-down' : 'bio-properties-panel-arrow-right'
@@ -3749,7 +3782,8 @@ function List(props) {
3749
3782
  items: items,
3750
3783
  newItems: newItems,
3751
3784
  onRemove: onRemove,
3752
- open: open
3785
+ open: open,
3786
+ translate: translate
3753
3787
  })]
3754
3788
  });
3755
3789
  }
@@ -3763,6 +3797,7 @@ function ItemsList(props) {
3763
3797
  newItems,
3764
3798
  onRemove,
3765
3799
  open,
3800
+ translate,
3766
3801
  ...restProps
3767
3802
  } = props;
3768
3803
  const getKey = useKeyFactory();
@@ -3801,7 +3836,7 @@ function ItemsList(props) {
3801
3836
  open: item === newItem
3802
3837
  }), onRemove && jsxRuntime.jsx("button", {
3803
3838
  type: "button",
3804
- title: "Delete item",
3839
+ title: translate('Delete item'),
3805
3840
  class: "bio-properties-panel-remove-entry bio-properties-panel-remove-list-entry",
3806
3841
  onClick: () => onRemove && onRemove(item),
3807
3842
  children: jsxRuntime.jsx(DeleteIcon, {})
@@ -4002,6 +4037,7 @@ function prefixId$4(id) {
4002
4037
  * @param {Function} [props.onBlur]
4003
4038
  * @param {Function} [props.onFocus]
4004
4039
  * @param {Function} props.setValue
4040
+ * @param {Function} [props.translate]
4005
4041
  */
4006
4042
  function Simple(props) {
4007
4043
  const {
@@ -4012,7 +4048,8 @@ function Simple(props) {
4012
4048
  id,
4013
4049
  onBlur,
4014
4050
  onFocus,
4015
- setValue
4051
+ setValue,
4052
+ translate = translateFallback
4016
4053
  } = props;
4017
4054
  const value = getValue(element);
4018
4055
  const [localValue, setLocalValue] = hooks.useState(value);
@@ -4040,7 +4077,7 @@ function Simple(props) {
4040
4077
  disabled: disabled,
4041
4078
  class: "bio-properties-panel-input",
4042
4079
  onInput: handleInput,
4043
- "aria-label": localValue || '<empty>',
4080
+ "aria-label": localValue || translate('<empty>'),
4044
4081
  onFocus: onFocus,
4045
4082
  onBlur: onBlur,
4046
4083
  value: localValue