@bpmn-io/properties-panel 3.44.1 → 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.esm.js CHANGED
@@ -12,7 +12,7 @@ import { closeBrackets, closeBracketsKeymap } from '@codemirror/autocomplete';
12
12
  import { history, defaultKeymap, historyKeymap } from '@codemirror/commands';
13
13
  import { jsonParseLinter, json } from '@codemirror/lang-json';
14
14
  import { linter } from '@codemirror/lint';
15
- import { FeelersEditor } from 'feelers';
15
+ import { FeelersEditor } from '@bpmn-io/feelers-editor';
16
16
  import Editor from '@bpmn-io/feel-editor';
17
17
  import * as focusTrap from 'focus-trap';
18
18
 
@@ -159,6 +159,28 @@ OpenPopupIcon.defaultProps = {
159
159
  viewBox: "0 0 16 16"
160
160
  };
161
161
 
162
+ /**
163
+ * @typedef { {
164
+ * [key: string]: string;
165
+ * } } TranslateReplacements
166
+ */
167
+
168
+ /**
169
+ * A simple translation stub to be used for multi-language support.
170
+ * Can be easily replaced with a more sophisticated solution.
171
+ *
172
+ * @param {string} template to interpolate
173
+ * @param {TranslateReplacements} [replacements] a map with substitutes
174
+ *
175
+ * @return {string} the translated string
176
+ */
177
+ function translateFallback(template, replacements) {
178
+ replacements = replacements || {};
179
+ return template.replace(/{([^}]+)}/g, function (_, key) {
180
+ return replacements[key] || '{' + key + '}';
181
+ });
182
+ }
183
+
162
184
  /**
163
185
  * @typedef { {
164
186
  * getElementLabel: (element: object) => string,
@@ -170,13 +192,15 @@ OpenPopupIcon.defaultProps = {
170
192
 
171
193
  /**
172
194
  * @param {Object} props
173
- * @param {Object} props.element,
195
+ * @param {Object} props.element
174
196
  * @param {HeaderProvider} props.headerProvider
197
+ * @param {Function} [props.translate]
175
198
  */
176
199
  function Header(props) {
177
200
  const {
178
201
  element,
179
- headerProvider
202
+ headerProvider,
203
+ translate = translateFallback
180
204
  } = props;
181
205
  const {
182
206
  getElementIcon,
@@ -212,7 +236,7 @@ function Header(props) {
212
236
  rel: "noreferrer",
213
237
  class: "bio-properties-panel-header-link",
214
238
  href: documentationRef,
215
- title: "Open documentation",
239
+ title: translate('Open documentation'),
216
240
  target: "_blank",
217
241
  children: jsx(ExternalLinkIcon, {})
218
242
  }) : null
@@ -842,7 +866,8 @@ function Group(props) {
842
866
  entries = [],
843
867
  id,
844
868
  label,
845
- shouldOpen = false
869
+ shouldOpen = false,
870
+ translate = translateFallback
846
871
  } = props;
847
872
  const groupRef = useRef(null);
848
873
  const [open, setOpen] = useLayoutState(['groups', id, 'open'], shouldOpen);
@@ -901,10 +926,11 @@ function Group(props) {
901
926
  class: "bio-properties-panel-group-header-buttons",
902
927
  children: [jsx(DataMarker, {
903
928
  edited: edited,
904
- hasErrors: hasErrors
929
+ hasErrors: hasErrors,
930
+ translate: translate
905
931
  }), jsx("button", {
906
932
  type: "button",
907
- title: "Toggle section",
933
+ title: translate('Toggle section'),
908
934
  class: "bio-properties-panel-group-header-button bio-properties-panel-arrow",
909
935
  children: jsx(ArrowIcon, {
910
936
  class: open ? 'bio-properties-panel-arrow-down' : 'bio-properties-panel-arrow-right'
@@ -933,17 +959,18 @@ function Group(props) {
933
959
  function DataMarker(props) {
934
960
  const {
935
961
  edited,
936
- hasErrors
962
+ hasErrors,
963
+ translate = translateFallback
937
964
  } = props;
938
965
  if (hasErrors) {
939
966
  return jsx("div", {
940
- title: "Section contains an error",
967
+ title: translate('Section contains an error'),
941
968
  class: "bio-properties-panel-dot bio-properties-panel-dot--error"
942
969
  });
943
970
  }
944
971
  if (edited) {
945
972
  return jsx("div", {
946
- title: "Section contains edits",
973
+ title: translate('Section contains edits'),
947
974
  class: "bio-properties-panel-dot"
948
975
  });
949
976
  }
@@ -1004,7 +1031,8 @@ const DEFAULT_TOOLTIP = {};
1004
1031
  * id: String,
1005
1032
  * items: Array<ListItemDefinition>,
1006
1033
  * label: String,
1007
- * shouldOpen?: Boolean
1034
+ * shouldOpen?: Boolean,
1035
+ * translate?: Function
1008
1036
  * } } ListGroupDefinition
1009
1037
  *
1010
1038
  * @typedef { {
@@ -1012,7 +1040,8 @@ const DEFAULT_TOOLTIP = {};
1012
1040
  * entries: Array<EntryDefinition>,
1013
1041
  * id: String,
1014
1042
  * label: String,
1015
- * shouldOpen?: Boolean
1043
+ * shouldOpen?: Boolean,
1044
+ * translate?: Function
1016
1045
  * } } GroupDefinition
1017
1046
  *
1018
1047
  * @typedef { {
@@ -1356,28 +1385,6 @@ function HeaderButton(props) {
1356
1385
  });
1357
1386
  }
1358
1387
 
1359
- /**
1360
- * @typedef { {
1361
- * [key: string]: string;
1362
- * } } TranslateReplacements
1363
- */
1364
-
1365
- /**
1366
- * A simple translation stub to be used for multi-language support.
1367
- * Can be easily replaced with a more sophisticated solution.
1368
- *
1369
- * @param {string} template to interpolate
1370
- * @param {TranslateReplacements} [replacements] a map with substitutes
1371
- *
1372
- * @return {string} the translated string
1373
- */
1374
- function translateFallback(template, replacements) {
1375
- replacements = replacements || {};
1376
- return template.replace(/{([^}]+)}/g, function (_, key) {
1377
- return replacements[key] || '{' + key + '}';
1378
- });
1379
- }
1380
-
1381
1388
  function CollapsibleEntry(props) {
1382
1389
  const {
1383
1390
  element,
@@ -1945,6 +1952,7 @@ function JsonEditor(props) {
1945
1952
  * @param {string} [props.placeholder]
1946
1953
  * @param {string} [props.tooltip]
1947
1954
  * @param {Function} [props.validate]
1955
+ * @param {Function} [props.translate]
1948
1956
  */
1949
1957
  function JsonEditorEntry(props) {
1950
1958
  const {
@@ -1958,24 +1966,25 @@ function JsonEditorEntry(props) {
1958
1966
  disabled,
1959
1967
  placeholder,
1960
1968
  tooltip,
1961
- validate
1969
+ validate,
1970
+ translate = translateFallback
1962
1971
  } = props;
1963
1972
  const globalError = useError(id);
1964
1973
  let value = getValue(element);
1965
- const [localError, setLocalError] = useState(() => computeError(validate, value));
1974
+ const [localError, setLocalError] = useState(() => computeError(validate, value, translate));
1966
1975
  const [editorValue, setEditorValue] = useState(value);
1967
1976
  useEffect(() => {
1968
1977
  if (value === editorValue) {
1969
1978
  return;
1970
1979
  }
1971
1980
  setEditorValue(value);
1972
- setLocalError(computeError(validate, value));
1981
+ setLocalError(computeError(validate, value, translate));
1973
1982
  }, [value, validate]);
1974
1983
  const onInput = useStaticCallback(newValue => {
1975
1984
  setEditorValue(newValue);
1976
1985
  const currentValue = getValue(element);
1977
1986
  if (newValue !== currentValue) {
1978
- const newValidationError = computeError(validate, newValue);
1987
+ const newValidationError = computeError(validate, newValue, translate);
1979
1988
  setValue(newValue, newValidationError);
1980
1989
  setLocalError(newValidationError);
1981
1990
  }
@@ -2014,15 +2023,15 @@ function isEdited$8(node) {
2014
2023
 
2015
2024
  // helpers /////////////////
2016
2025
 
2017
- function computeError(validate, value) {
2018
- return (isFunction(validate) ? validate(value) : null) || validateJson(value);
2026
+ function computeError(validate, value, translate) {
2027
+ return (isFunction(validate) ? validate(value) : null) || validateJson(value, translate);
2019
2028
  }
2020
- function validateJson(value) {
2029
+ function validateJson(value, translate = translateFallback) {
2021
2030
  if (!value || !value.trim()) return null;
2022
2031
  try {
2023
- return isObject(JSON.parse(value)) ? null : 'JSON contains errors';
2032
+ return isObject(JSON.parse(value)) ? null : translate('JSON contains errors');
2024
2033
  } catch (e) {
2025
- return 'JSON contains errors';
2034
+ return translate('JSON contains errors');
2026
2035
  }
2027
2036
  }
2028
2037
 
@@ -2032,13 +2041,14 @@ function validateJson(value) {
2032
2041
  * @param {Object} props
2033
2042
  * @param {Function} props.onClick - Callback to trigger when the button is clicked.
2034
2043
  * @param {string} [props.title] - Tooltip text for the button.
2035
- * @param {boolean} [props.disabled] - Whether the button is disabled.
2036
- * @param {string} [props.className] - Additional class names for the button.
2044
+ * @param {Function} [props.translate] - Translation function for built-in strings.
2037
2045
  */
2038
2046
  function OpenPopupButton({
2039
2047
  onClick,
2040
- title = 'Open pop-up editor'
2048
+ title,
2049
+ translate = translateFallback
2041
2050
  }) {
2051
+ title = title ?? translate('Open pop-up editor');
2042
2052
  return jsx("button", {
2043
2053
  type: "button",
2044
2054
  title: title,
@@ -2190,7 +2200,8 @@ const FeelEditor = forwardRef((props, ref) => {
2190
2200
  disabled,
2191
2201
  tooltipContainer,
2192
2202
  variables,
2193
- feelLanguageContext
2203
+ feelLanguageContext,
2204
+ translate = translateFallback
2194
2205
  } = props;
2195
2206
  const inputRef = useRef();
2196
2207
  const [editor, setEditor] = useState();
@@ -2282,14 +2293,15 @@ const FeelEditor = forwardRef((props, ref) => {
2282
2293
  class: classnames('bio-properties-panel-feel-editor-container', disabled ? 'disabled' : null, popupOpen ? 'popupOpen' : null),
2283
2294
  children: [popupOpen && jsx("div", {
2284
2295
  class: "bio-properties-panel-feel-editor__open-popup-placeholder",
2285
- children: "Opened in editor"
2296
+ children: translate('Opened in editor')
2286
2297
  }), jsx("div", {
2287
2298
  name: props.name,
2288
2299
  class: classnames('bio-properties-panel-input', localValue ? 'edited' : null),
2289
2300
  ref: inputRef,
2290
2301
  onClick: handleClick
2291
2302
  }), !disabled && jsx(OpenPopupButton, {
2292
- onClick: () => onOpenPopup('feel')
2303
+ onClick: () => onOpenPopup('feel'),
2304
+ translate: translate
2293
2305
  })]
2294
2306
  });
2295
2307
  });
@@ -2313,16 +2325,22 @@ const noop$3 = () => {};
2313
2325
  * @param {Object} props
2314
2326
  * @param {Object} props.label
2315
2327
  * @param {String} props.feel
2328
+ * @param {boolean} props.active
2329
+ * @param {boolean} props.disabled
2330
+ * @param {Function} props.onClick
2331
+ * @param {Function} props.translate
2332
+ * @returns {import('preact').Component}
2316
2333
  */
2317
2334
  function FeelIcon(props) {
2318
2335
  const {
2319
2336
  feel = false,
2320
2337
  active,
2321
2338
  disabled = false,
2322
- onClick = noop$3
2339
+ onClick = noop$3,
2340
+ translate = translateFallback
2323
2341
  } = props;
2324
- const feelRequiredLabel = 'FEEL expression is mandatory';
2325
- const feelOptionalLabel = `Click to ${active ? 'remove' : 'set a'} dynamic value with FEEL expression`;
2342
+ const feelRequiredLabel = translate('FEEL expression is mandatory');
2343
+ const feelOptionalLabel = translate(`Click to ${active ? 'remove' : 'set a'} dynamic value with FEEL expression`);
2326
2344
  const handleClick = e => {
2327
2345
  onClick(e);
2328
2346
 
@@ -2664,6 +2682,7 @@ const noop$2 = () => {};
2664
2682
  * @param {Array} props.variables
2665
2683
  * @param {string} [props.placeholder]
2666
2684
  * @param {string | import('preact').Component} props.tooltip
2685
+ * @param {Function} props.translate
2667
2686
  */
2668
2687
  function FeelTextfield(props) {
2669
2688
  const {
@@ -2683,7 +2702,8 @@ function FeelTextfield(props) {
2683
2702
  singleLine,
2684
2703
  tooltipContainer,
2685
2704
  OptionalComponent = OptionalFeelInput,
2686
- tooltip
2705
+ tooltip,
2706
+ translate
2687
2707
  } = props;
2688
2708
  const [localValue, setLocalValue] = useState(getInitialFeelLocalValue(feel, value));
2689
2709
  const editorRef = useShowEntryEvent(id);
@@ -2772,7 +2792,7 @@ function FeelTextfield(props) {
2772
2792
  const handleLint = useStaticCallback((lint = []) => {
2773
2793
  const syntaxError = lint.some(report => report.type === 'Syntax Error');
2774
2794
  if (syntaxError) {
2775
- onError('Unparsable FEEL expression.');
2795
+ onError(translate('Unparsable FEEL expression.'));
2776
2796
  } else {
2777
2797
  onError(undefined);
2778
2798
  }
@@ -2843,9 +2863,14 @@ function FeelTextfield(props) {
2843
2863
  });
2844
2864
  return;
2845
2865
  }
2846
- const input = event.target;
2847
- const isFieldEmpty = !input.value;
2848
- const isAllSelected = input.selectionStart === 0 && input.selectionEnd === input.value.length;
2866
+ const target = event.target;
2867
+
2868
+ // Skip for non-input/textArea elements (e.g. CodeMirror contenteditable)
2869
+ if (!(target instanceof HTMLInputElement) && !(target instanceof HTMLTextAreaElement)) {
2870
+ return;
2871
+ }
2872
+ const isFieldEmpty = !target.value;
2873
+ const isAllSelected = target.selectionStart === 0 && target.selectionEnd === target.value.length;
2849
2874
  if (isFieldEmpty || isAllSelected) {
2850
2875
  const textData = event.clipboardData.getData('text');
2851
2876
  const trimmedValue = textData.trim();
@@ -2882,7 +2907,8 @@ function FeelTextfield(props) {
2882
2907
  label: label,
2883
2908
  feel: feel,
2884
2909
  onClick: handleFeelToggle,
2885
- active: feelActive
2910
+ active: feelActive,
2911
+ translate: translate
2886
2912
  })]
2887
2913
  }), jsxs("div", {
2888
2914
  class: "bio-properties-panel-feel-container",
@@ -2913,7 +2939,8 @@ function FeelTextfield(props) {
2913
2939
  variables: variables,
2914
2940
  feelLanguageContext: feelLanguageContext,
2915
2941
  ref: editorRef,
2916
- tooltipContainer: tooltipContainer
2942
+ tooltipContainer: tooltipContainer,
2943
+ translate: translate
2917
2944
  }) : jsx(OptionalComponent, {
2918
2945
  ...props,
2919
2946
  popupOpen: isPopupOpen,
@@ -3182,7 +3209,8 @@ function FeelEntry(props) {
3182
3209
  onFocus,
3183
3210
  onBlur,
3184
3211
  placeholder,
3185
- tooltip
3212
+ tooltip,
3213
+ translate = translateFallback
3186
3214
  } = props;
3187
3215
  const [validationError, setValidationError] = useState(null);
3188
3216
  const [localError, setLocalError] = useState(null);
@@ -3231,6 +3259,7 @@ function FeelEntry(props) {
3231
3259
  hostLanguage: hostLanguage,
3232
3260
  singleLine: singleLine,
3233
3261
  show: show,
3262
+ translate: translate,
3234
3263
  value: value,
3235
3264
  variables: variables,
3236
3265
  tooltipContainer: tooltipContainer,
@@ -3644,6 +3673,7 @@ function prefixIdLabel(id) {
3644
3673
  * @param {Item[]} [props.items]
3645
3674
  * @param {boolean} [props.open]
3646
3675
  * @param {string|boolean} [props.autoFocusEntry] either a custom selector string or true to focus the first input
3676
+ * @param {Function} [props.translate]
3647
3677
  * @returns
3648
3678
  */
3649
3679
  function List(props) {
@@ -3708,7 +3738,9 @@ function List(props) {
3708
3738
  children: translate('Create')
3709
3739
  }) : null]
3710
3740
  }), hasItems && jsx("div", {
3711
- title: `List contains ${items.length} item${items.length != 1 ? 's' : ''}`,
3741
+ title: translate(`List contains {numOfItems} item${items.length != 1 ? 's' : ''}`, {
3742
+ numOfItems: items.length
3743
+ }),
3712
3744
  class: "bio-properties-panel-list-badge",
3713
3745
  children: items.length
3714
3746
  }), hasItems && jsx("button", {
@@ -3984,6 +4016,7 @@ function prefixId$4(id) {
3984
4016
  * @param {Function} [props.onBlur]
3985
4017
  * @param {Function} [props.onFocus]
3986
4018
  * @param {Function} props.setValue
4019
+ * @param {Function} [props.translate]
3987
4020
  */
3988
4021
  function Simple(props) {
3989
4022
  const {
@@ -3994,7 +4027,8 @@ function Simple(props) {
3994
4027
  id,
3995
4028
  onBlur,
3996
4029
  onFocus,
3997
- setValue
4030
+ setValue,
4031
+ translate = translateFallback
3998
4032
  } = props;
3999
4033
  const value = getValue(element);
4000
4034
  const [localValue, setLocalValue] = useState(value);
@@ -4022,7 +4056,7 @@ function Simple(props) {
4022
4056
  disabled: disabled,
4023
4057
  class: "bio-properties-panel-input",
4024
4058
  onInput: handleInput,
4025
- "aria-label": localValue || '<empty>',
4059
+ "aria-label": localValue || translate('<empty>'),
4026
4060
  onFocus: onFocus,
4027
4061
  onBlur: onBlur,
4028
4062
  value: localValue