@bpmn-io/form-js-playground 1.8.7 → 1.8.8

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/LICENSE CHANGED
@@ -1,23 +1,23 @@
1
- Copyright (c) 2021-present Camunda Services GmbH
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining a copy of
4
- this software and associated documentation files (the "Software"), to deal in the
5
- Software without restriction, including without limitation the rights to use, copy,
6
- modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
7
- and to permit persons to whom the Software is furnished to do so, subject to the
8
- following conditions:
9
-
10
- The above copyright notice and this permission notice shall be included in all
11
- copies or substantial portions of the Software.
12
-
13
- The source code responsible for displaying the bpmn.io project watermark that
14
- links back to https://bpmn.io as part of rendered diagrams MUST NOT be
15
- removed or changed. When this software is being used in a website or application,
16
- the watermark must stay fully visible and not visually overlapped by other elements.
17
-
18
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
19
- INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
20
- PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22
- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
1
+ Copyright (c) 2021-present Camunda Services GmbH
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in the
5
+ Software without restriction, including without limitation the rights to use, copy,
6
+ modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
7
+ and to permit persons to whom the Software is furnished to do so, subject to the
8
+ following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ The source code responsible for displaying the bpmn.io project watermark that
14
+ links back to https://bpmn.io as part of rendered diagrams MUST NOT be
15
+ removed or changed. When this software is being used in a website or application,
16
+ the watermark must stay fully visible and not visually overlapped by other elements.
17
+
18
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
19
+ INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
20
+ PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
23
23
  OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1224,41 +1224,6 @@
1224
1224
  return result;
1225
1225
  }
1226
1226
 
1227
- /**
1228
- * Sort collection by criteria.
1229
- *
1230
- * @template T
1231
- *
1232
- * @param {Collection<T>} collection
1233
- * @param {Extractor<T, number | string>} extractor
1234
- *
1235
- * @return {Array}
1236
- */
1237
- function sortBy(collection, extractor) {
1238
- extractor = toExtractor(extractor);
1239
- let sorted = [];
1240
- forEach(collection, function (value, key) {
1241
- let disc = extractor(value, key);
1242
- let entry = {
1243
- d: disc,
1244
- v: value
1245
- };
1246
- for (var idx = 0; idx < sorted.length; idx++) {
1247
- let {
1248
- d
1249
- } = sorted[idx];
1250
- if (disc < d) {
1251
- sorted.splice(idx, 0, entry);
1252
- return;
1253
- }
1254
- }
1255
-
1256
- // not inserted, append (!)
1257
- sorted.push(entry);
1258
- });
1259
- return map(sorted, e => e.v);
1260
- }
1261
-
1262
1227
  /**
1263
1228
  * @param {string | ((e: any) => any) } extractor
1264
1229
  *
@@ -57810,24 +57775,26 @@
57810
57775
  }
57811
57776
  var lint = linter$1(cmFeelersLinter());
57812
57777
 
57813
- /**
57814
- * Creates a Feelers editor in the supplied container.
57815
- *
57816
- * @param {Object} config Configuration options for the Feelers editor.
57817
- * @param {DOMNode} [config.container] The DOM node that will contain the editor.
57818
- * @param {DOMNode|String} [config.tooltipContainer] The DOM node or CSS selector string for the tooltip container.
57819
- * @param {String} [config.hostLanguage] The host language for the editor (e.g., 'markdown').
57820
- * @param {Object} [config.hostLanguageParser] A custom parser for the host language.
57821
- * @param {Function} [config.onChange] Callback function that is called when the editor's content changes.
57822
- * @param {Function} [config.onKeyDown] Callback function that is called when a key is pressed within the editor.
57823
- * @param {Function} [config.onLint] Callback function that is called when linting messages are available.
57824
- * @param {Object} [config.contentAttributes] Additional attributes to set on the editor's content element.
57825
- * @param {Boolean} [config.readOnly] Set to true to make the editor read-only.
57826
- * @param {String} [config.value] Initial value of the editor.
57827
- * @param {Boolean} [config.enableGutters] Set to true to enable gutter decorations (e.g., line numbers).
57828
- * @param {Boolean} [config.darkMode] Set to true to use the dark theme for the editor.
57829
- *
57830
- * @returns {Object} editor An instance of the FeelersEditor class.
57778
+ /**
57779
+ * Creates a Feelers editor in the supplied container.
57780
+ *
57781
+ * @param {Object} config Configuration options for the Feelers editor.
57782
+ * @param {DOMNode} [config.container] The DOM node that will contain the editor.
57783
+ * @param {DOMNode|String} [config.tooltipContainer] The DOM node or CSS selector string for the tooltip container.
57784
+ * @param {String} [config.hostLanguage] The host language for the editor (e.g., 'markdown').
57785
+ * @param {Object} [config.hostLanguageParser] A custom parser for the host language.
57786
+ * @param {Function} [config.onChange] Callback function that is called when the editor's content changes.
57787
+ * @param {Function} [config.onKeyDown] Callback function that is called when a key is pressed within the editor.
57788
+ * @param {Function} [config.onLint] Callback function that is called when linting messages are available.
57789
+ * @param {Object} [config.contentAttributes] Additional attributes to set on the editor's content element.
57790
+ * @param {Boolean} [config.readOnly] Set to true to make the editor read-only.
57791
+ * @param {String} [config.value] Initial value of the editor.
57792
+ * @param {Boolean} [config.enableGutters] Set to true to enable gutter decorations (e.g., line numbers).
57793
+ * @param {Boolean} [config.singleLine] Set to true to limit the editor to a single line.
57794
+ * @param {Boolean} [config.lineWrap] Set to true to enable line wrapping.
57795
+ * @param {Boolean} [config.darkMode] Set to true to use the dark theme for the editor.
57796
+ *
57797
+ * @returns {Object} editor An instance of the FeelersEditor class.
57831
57798
  */
57832
57799
  function FeelersEditor({
57833
57800
  container,
@@ -57842,6 +57809,7 @@
57842
57809
  value = '',
57843
57810
  enableGutters = false,
57844
57811
  singleLine = false,
57812
+ lineWrap = false,
57845
57813
  darkMode = false
57846
57814
  }) {
57847
57815
  const changeHandler = EditorView.updateListener.of(update => {
@@ -57881,7 +57849,7 @@
57881
57849
  const feelersLanguageSupport = createFeelersLanguageSupport(hostLanguageParser || hostLanguage && _getHostLanguageParser(hostLanguage));
57882
57850
  const extensions = [bracketMatching(), changeHandler, contentAttributesExtension, closeBrackets(), indentOnInput(), keyHandler, keymap.of([...defaultKeymap]), feelersLanguageSupport, lint, lintHandler, tooltipLayout, darkMode ? darkTheme : lightTheme, ...(enableGutters ? [
57883
57851
  // todo: adjust folding boundaries first foldGutter(),
57884
- lineNumbers()] : []), ...(singleLine ? [EditorState.transactionFilter.of(tr => tr.newDoc.lines > 1 ? [] : tr)] : [])];
57852
+ lineNumbers()] : []), ...(singleLine ? [EditorState.transactionFilter.of(tr => tr.newDoc.lines > 1 ? [] : tr)] : []), ...(lineWrap ? [EditorView.lineWrapping] : [])];
57885
57853
  if (readOnly) {
57886
57854
  extensions.push(EditorView.editable.of(false));
57887
57855
  }
@@ -57898,10 +57866,10 @@
57898
57866
  return this;
57899
57867
  }
57900
57868
 
57901
- /**
57902
- * Replaces the content of the Editor
57903
- *
57904
- * @param {String} value
57869
+ /**
57870
+ * Replaces the content of the Editor
57871
+ *
57872
+ * @param {String} value
57905
57873
  */
57906
57874
  FeelersEditor.prototype.setValue = function (value) {
57907
57875
  this._cmEditor.dispatch({
@@ -57913,8 +57881,8 @@
57913
57881
  });
57914
57882
  };
57915
57883
 
57916
- /**
57917
- * Sets the focus in the editor.
57884
+ /**
57885
+ * Sets the focus in the editor.
57918
57886
  */
57919
57887
  FeelersEditor.prototype.focus = function (position) {
57920
57888
  const cmEditor = this._cmEditor;
@@ -57933,12 +57901,12 @@
57933
57901
  }
57934
57902
  };
57935
57903
 
57936
- /**
57937
- * Returns the current selection ranges. If no text is selected, a single
57938
- * range with the start and end index at the cursor position will be returned.
57939
- *
57940
- * @returns {Object} selection
57941
- * @returns {Array} selection.ranges
57904
+ /**
57905
+ * Returns the current selection ranges. If no text is selected, a single
57906
+ * range with the start and end index at the cursor position will be returned.
57907
+ *
57908
+ * @returns {Object} selection
57909
+ * @returns {Array} selection.ranges
57942
57910
  */
57943
57911
  FeelersEditor.prototype.getSelection = function () {
57944
57912
  return this._cmEditor.state.selection;
@@ -60818,39 +60786,6 @@
60818
60786
  });
60819
60787
  return result;
60820
60788
  }
60821
- const type$h = 'button';
60822
- function Button(props) {
60823
- const {
60824
- disabled,
60825
- onFocus,
60826
- onBlur,
60827
- field
60828
- } = props;
60829
- const {
60830
- action = 'submit'
60831
- } = field;
60832
- return e("div", {
60833
- class: formFieldClasses(type$h),
60834
- children: e("button", {
60835
- class: "fjs-button",
60836
- type: action,
60837
- disabled: disabled,
60838
- onFocus: () => onFocus && onFocus(),
60839
- onBlur: () => onBlur && onBlur(),
60840
- children: field.label
60841
- })
60842
- });
60843
- }
60844
- Button.config = {
60845
- type: type$h,
60846
- keyed: false,
60847
- label: 'Button',
60848
- group: 'action',
60849
- create: (options = {}) => ({
60850
- action: 'submit',
60851
- ...options
60852
- })
60853
- };
60854
60789
  const FormRenderContext = D$2({
60855
60790
  Empty: props => {
60856
60791
  return null;
@@ -61886,6 +61821,42 @@
61886
61821
  }
61887
61822
  }, [field, options, onChange, memoizedValues, loadState]);
61888
61823
  }
61824
+ const type$h = 'button';
61825
+ function Button(props) {
61826
+ const {
61827
+ disabled,
61828
+ onFocus,
61829
+ onBlur,
61830
+ field
61831
+ } = props;
61832
+ const {
61833
+ action = 'submit'
61834
+ } = field;
61835
+ const evaluatedLabel = useSingleLineTemplateEvaluation(field.label || '', {
61836
+ debug: true
61837
+ });
61838
+ return e("div", {
61839
+ class: formFieldClasses(type$h),
61840
+ children: e("button", {
61841
+ class: "fjs-button",
61842
+ type: action,
61843
+ disabled: disabled,
61844
+ onFocus: () => onFocus && onFocus(),
61845
+ onBlur: () => onBlur && onBlur(),
61846
+ children: evaluatedLabel
61847
+ })
61848
+ });
61849
+ }
61850
+ Button.config = {
61851
+ type: type$h,
61852
+ keyed: false,
61853
+ label: 'Button',
61854
+ group: 'action',
61855
+ create: (options = {}) => ({
61856
+ action: 'submit',
61857
+ ...options
61858
+ })
61859
+ };
61889
61860
  function Description$2(props) {
61890
61861
  const {
61891
61862
  description,
@@ -66243,7 +66214,7 @@
66243
66214
  return this._formFields[type];
66244
66215
  }
66245
66216
  }
66246
- const EXPRESSION_PROPERTIES = ['alt', 'appearance.prefixAdorner', 'appearance.suffixAdorner', 'conditional.hide', 'description', 'label', 'source', 'readonly', 'text', 'validate.min', 'validate.max', 'validate.minLength', 'validate.maxLength', 'valuesExpression', 'url', 'dataSource', 'columnsExpression'];
66217
+ const EXPRESSION_PROPERTIES = ['alt', 'appearance.prefixAdorner', 'appearance.suffixAdorner', 'conditional.hide', 'description', 'label', 'source', 'readonly', 'text', 'validate.min', 'validate.max', 'validate.minLength', 'validate.maxLength', 'valuesExpression', 'url', 'dataSource', 'columnsExpression', 'expression'];
66247
66218
  const TEMPLATE_PROPERTIES = ['alt', 'appearance.prefixAdorner', 'appearance.suffixAdorner', 'description', 'label', 'source', 'text', 'content', 'url'];
66248
66219
 
66249
66220
  /**
@@ -67492,7 +67463,10 @@
67492
67463
  const localExpressionContextInfo = d(() => ({
67493
67464
  data: parentExpressionContextInfo.data,
67494
67465
  this: itemValue,
67495
- parent: buildExpressionContext(parentExpressionContextInfo),
67466
+ parent: buildExpressionContext({
67467
+ ...parentExpressionContextInfo,
67468
+ data: parentExpressionContextInfo.this
67469
+ }),
67496
67470
  i: [...parentExpressionContextInfo.i, itemIndex + 1]
67497
67471
  }), [itemIndex, parentExpressionContextInfo, itemValue]);
67498
67472
  return !showRemove ? e(LocalExpressionContext.Provider, {
@@ -68399,13 +68373,11 @@
68399
68373
  if (config.repeatable) {
68400
68374
  this._enforceDefaultPath(field);
68401
68375
  }
68402
- if (field.path) {
68403
- this._pathRegistry.claimPath(this._pathRegistry.getValuePath(field), {
68404
- isRepeatable: config.repeatable,
68405
- claimerId: field.id,
68406
- knownAncestorIds: getAncestryList(_parent, this._formFieldRegistry)
68407
- });
68408
- }
68376
+ this._pathRegistry.claimPath(this._pathRegistry.getValuePath(field), {
68377
+ isRepeatable: config.repeatable,
68378
+ claimerId: field.id,
68379
+ knownAncestorIds: getAncestryList(_parent, this._formFieldRegistry)
68380
+ });
68409
68381
  }
68410
68382
  return field;
68411
68383
  }
@@ -70715,12 +70687,7 @@
70715
70687
  */
70716
70688
  var variables = context => {
70717
70689
  const variables = context.state.facet(variablesFacet$1)[0];
70718
- const options = variables.map(v => ({
70719
- label: v.name,
70720
- type: 'variable',
70721
- info: v.info,
70722
- detail: v.detail
70723
- }));
70690
+ const options = variables.map(v => createVariableSuggestion(v));
70724
70691
 
70725
70692
  // In most cases, use what is typed before the cursor
70726
70693
  let nodeBefore = syntaxTree(context.state).resolve(context.pos, -1);
@@ -70747,6 +70714,54 @@
70747
70714
  }
70748
70715
  return result;
70749
70716
  };
70717
+
70718
+ /**
70719
+ * @param {import('..').Variable} variable
70720
+ * @returns {import('@codemirror/autocomplete').Completion}
70721
+ */
70722
+ function createVariableSuggestion(variable) {
70723
+ if (variable.type === 'function') {
70724
+ return createFunctionVariable(variable);
70725
+ }
70726
+ return {
70727
+ label: variable.name,
70728
+ type: 'variable',
70729
+ info: variable.info,
70730
+ detail: variable.detail
70731
+ };
70732
+ }
70733
+
70734
+ /**
70735
+ * @param {import('..').Variable} variable
70736
+ * @returns {import('@codemirror/autocomplete').Completion}
70737
+ */
70738
+ function createFunctionVariable(variable) {
70739
+ const {
70740
+ name,
70741
+ info,
70742
+ detail,
70743
+ params = []
70744
+ } = variable;
70745
+ const paramsWithNames = params.map(({
70746
+ name,
70747
+ type
70748
+ }, index) => ({
70749
+ name: name || `param ${index + 1}`,
70750
+ type
70751
+ }));
70752
+ const template = `${name}(${paramsWithNames.map(p => '${' + p.name + '}').join(', ')})`;
70753
+ const paramsSignature = paramsWithNames.map(({
70754
+ name,
70755
+ type
70756
+ }) => type ? `${name}: ${type}` : name).join(', ');
70757
+ const label = `${name}(${paramsSignature})`;
70758
+ return snippetCompletion(template, {
70759
+ label,
70760
+ type: 'function',
70761
+ info,
70762
+ detail
70763
+ });
70764
+ }
70750
70765
  function autocompletion() {
70751
70766
  return [autocompletion$1({
70752
70767
  override: [variables, builtins, completeFromList(snippets.map(s => ({
@@ -70846,15 +70861,17 @@
70846
70861
 
70847
70862
  /**
70848
70863
  * @typedef {object} Variable
70849
- * @typedef {import('@codemirror/state').Extension} Extension
70850
70864
  * @property {string} name name or key of the variable
70851
70865
  * @property {string} [info] short information about the variable, e.g. type
70852
70866
  * @property {string} [detail] longer description of the variable content
70853
70867
  * @property {boolean} [isList] whether the variable is a list
70854
- * @property {array<Variable>} [schema] array of child variables if the variable is a context or list
70868
+ * @property {Array<Variable>} [schema] array of child variables if the variable is a context or list
70869
+ * @property {'function'|'variable'} [type] type of the variable
70870
+ * @property {Array<{name: string, type: string}>} [params] function parameters
70855
70871
  */
70856
70872
 
70857
70873
  const autocompletionConf = new Compartment();
70874
+ const placeholderConf = new Compartment();
70858
70875
 
70859
70876
  /**
70860
70877
  * Creates a FEEL editor in the supplied container
@@ -70880,6 +70897,7 @@
70880
70897
  onChange = () => {},
70881
70898
  onKeyDown = () => {},
70882
70899
  onLint = () => {},
70900
+ placeholder: placeholder$1 = '',
70883
70901
  readOnly = false,
70884
70902
  value = '',
70885
70903
  variables = []
@@ -70908,7 +70926,7 @@
70908
70926
  return tooltipContainer.getBoundingClientRect();
70909
70927
  }
70910
70928
  }) : [];
70911
- const extensions = [autocompletionConf.of(variablesFacet$1.of(variables)), autocompletion(), bracketMatching(), changeHandler, closeBrackets(), EditorView.contentAttributes.of(contentAttributes), indentOnInput(), keyHandler, keymap.of([...defaultKeymap]), language(), linter, lintHandler, tooltipLayout, theme, ...editorExtensions];
70929
+ const extensions = [autocompletionConf.of(variablesFacet$1.of(variables)), autocompletion(), bracketMatching(), changeHandler, closeBrackets(), EditorView.contentAttributes.of(contentAttributes), indentOnInput(), keyHandler, keymap.of([...defaultKeymap]), language(), linter, lintHandler, placeholderConf.of(placeholder(placeholder$1)), tooltipLayout, theme, ...editorExtensions];
70912
70930
  if (readOnly) {
70913
70931
  extensions.push(EditorView.editable.of(false));
70914
70932
  }
@@ -70979,6 +70997,17 @@
70979
70997
  });
70980
70998
  };
70981
70999
 
71000
+ /**
71001
+ * Update placeholder text.
71002
+ * @param {string} placeholder
71003
+ * @returns {void}
71004
+ */
71005
+ FeelEditor.prototype.setPlaceholder = function (placeholder$1) {
71006
+ this._cmEditor.dispatch({
71007
+ effects: placeholderConf.reconfigure(placeholder(placeholder$1))
71008
+ });
71009
+ };
71010
+
70982
71011
  /*!
70983
71012
  * tabbable 6.2.0
70984
71013
  * @license MIT, https://github.com/focus-trap/tabbable/blob/master/LICENSE
@@ -78718,6 +78747,21 @@
78718
78747
  height: "16",
78719
78748
  viewBox: "0 0 32 32"
78720
78749
  };
78750
+ var CloseIcon = function CloseIcon(props) {
78751
+ return e("svg", {
78752
+ ...props,
78753
+ children: e("path", {
78754
+ fillRule: "evenodd",
78755
+ 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",
78756
+ fill: "currentColor"
78757
+ })
78758
+ });
78759
+ };
78760
+ CloseIcon.defaultProps = {
78761
+ xmlns: "http://www.w3.org/2000/svg",
78762
+ width: "16",
78763
+ height: "16"
78764
+ };
78721
78765
  function Header(props) {
78722
78766
  const {
78723
78767
  element,
@@ -79418,7 +79462,8 @@
79418
79462
  tooltipContainer,
79419
79463
  enableGutters,
79420
79464
  hostLanguage,
79421
- singleLine
79465
+ singleLine,
79466
+ lineWrap: true
79422
79467
  });
79423
79468
  setEditor(editor);
79424
79469
  return () => {
@@ -79455,7 +79500,7 @@
79455
79500
  title: "Open pop-up editor",
79456
79501
  class: "bio-properties-panel-open-feel-popup",
79457
79502
  onClick: () => onPopupOpen('feelers'),
79458
- children: e(ExternalLinkIcon, {})
79503
+ children: e(PopupIcon, {})
79459
79504
  })]
79460
79505
  });
79461
79506
  });
@@ -79495,6 +79540,7 @@
79495
79540
  onFeelToggle = noop$5,
79496
79541
  onLint = noop$5,
79497
79542
  onPopupOpen = noop$5,
79543
+ placeholder,
79498
79544
  popupOpen,
79499
79545
  disabled,
79500
79546
  tooltipContainer,
@@ -79531,6 +79577,7 @@
79531
79577
  onChange: handleInput,
79532
79578
  onKeyDown: onKeyDown,
79533
79579
  onLint: onLint,
79580
+ placeholder: placeholder,
79534
79581
  tooltipContainer: tooltipContainer,
79535
79582
  value: localValue,
79536
79583
  variables: variables,
@@ -79560,6 +79607,12 @@
79560
79607
  }
79561
79608
  editor.setVariables(variables);
79562
79609
  }, [variables]);
79610
+ y(() => {
79611
+ if (!editor) {
79612
+ return;
79613
+ }
79614
+ editor.setPlaceholder(placeholder);
79615
+ }, [placeholder]);
79563
79616
  const handleClick = () => {
79564
79617
  ref.current.focus();
79565
79618
  };
@@ -79812,6 +79865,9 @@
79812
79865
  draggable,
79813
79866
  emit = () => {},
79814
79867
  title,
79868
+ showCloseButton = false,
79869
+ closeButtonTooltip = 'Close popup',
79870
+ onClose,
79815
79871
  ...rest
79816
79872
  } = props;
79817
79873
 
@@ -79882,7 +79938,12 @@
79882
79938
  }), e("div", {
79883
79939
  class: "bio-properties-panel-popup__title",
79884
79940
  children: title
79885
- }), children]
79941
+ }), children, showCloseButton && e("button", {
79942
+ title: closeButtonTooltip,
79943
+ class: "bio-properties-panel-popup__close",
79944
+ onClick: onClose,
79945
+ children: e(CloseIcon, {})
79946
+ })]
79886
79947
  });
79887
79948
  }
79888
79949
  function Body(props) {
@@ -80100,6 +80161,9 @@
80100
80161
  children: [e(Popup.Title, {
80101
80162
  title: title,
80102
80163
  emit: emit,
80164
+ showCloseButton: true,
80165
+ closeButtonTooltip: "Save and close",
80166
+ onClose: onClose,
80103
80167
  draggable: true,
80104
80168
  children: [type === 'feel' && e("a", {
80105
80169
  href: "https://docs.camunda.io/docs/components/modeler/feel/what-is-feel/",
@@ -80141,14 +80205,6 @@
80141
80205
  tooltipContainer: tooltipContainer
80142
80206
  })]
80143
80207
  })
80144
- }), e(Popup.Footer, {
80145
- children: e("button", {
80146
- type: "button",
80147
- onClick: () => onClose(),
80148
- title: "Close pop-up editor",
80149
- class: "bio-properties-panel-feel-popup__close-btn",
80150
- children: "Close"
80151
- })
80152
80208
  })]
80153
80209
  });
80154
80210
  }
@@ -80458,6 +80514,7 @@
80458
80514
  hostLanguage,
80459
80515
  onInput,
80460
80516
  onError,
80517
+ placeholder,
80461
80518
  feel,
80462
80519
  value = '',
80463
80520
  disabled = false,
@@ -80632,6 +80689,7 @@
80632
80689
  },
80633
80690
  onLint: handleLint,
80634
80691
  onPopupOpen: handlePopupOpen,
80692
+ placeholder: placeholder,
80635
80693
  value: feelOnlyValue,
80636
80694
  variables: variables,
80637
80695
  ref: editorRef,
@@ -80660,7 +80718,8 @@
80660
80718
  onInput,
80661
80719
  value,
80662
80720
  onFocus,
80663
- onBlur
80721
+ onBlur,
80722
+ placeholder
80664
80723
  } = props;
80665
80724
  const inputRef = s$1();
80666
80725
 
@@ -80693,6 +80752,7 @@
80693
80752
  onInput: e => onInput(e.target.value),
80694
80753
  onFocus: onFocus,
80695
80754
  onBlur: onBlur,
80755
+ placeholder: placeholder,
80696
80756
  value: value || ''
80697
80757
  });
80698
80758
  });
@@ -80750,7 +80810,8 @@
80750
80810
  onInput,
80751
80811
  value,
80752
80812
  onFocus,
80753
- onBlur
80813
+ onBlur,
80814
+ placeholder
80754
80815
  } = props;
80755
80816
  const inputRef = s$1();
80756
80817
 
@@ -80778,6 +80839,7 @@
80778
80839
  onInput: e => onInput(e.target.value),
80779
80840
  onFocus: onFocus,
80780
80841
  onBlur: onBlur,
80842
+ placeholder: placeholder,
80781
80843
  value: value || '',
80782
80844
  "data-gramm": "false"
80783
80845
  });
@@ -80873,6 +80935,7 @@
80873
80935
  * @param {Function} props.variables
80874
80936
  * @param {Function} props.onFocus
80875
80937
  * @param {Function} props.onBlur
80938
+ * @param {string} [props.placeholder]
80876
80939
  * @param {string|import('preact').Component} props.tooltip
80877
80940
  */
80878
80941
  function FeelEntry(props) {
@@ -80895,6 +80958,7 @@
80895
80958
  variables,
80896
80959
  onFocus,
80897
80960
  onBlur,
80961
+ placeholder,
80898
80962
  tooltip
80899
80963
  } = props;
80900
80964
  const [validationError, setValidationError] = l$1(null);
@@ -80938,6 +81002,7 @@
80938
81002
  onError: onError,
80939
81003
  onFocus: onFocus,
80940
81004
  onBlur: onBlur,
81005
+ placeholder: placeholder,
80941
81006
  example: example,
80942
81007
  hostLanguage: hostLanguage,
80943
81008
  singleLine: singleLine,
@@ -81125,7 +81190,6 @@
81125
81190
  * id: String,
81126
81191
  * items: Array<ListItemDefinition>,
81127
81192
  * label: String,
81128
- * shouldSort?: Boolean,
81129
81193
  * shouldOpen?: Boolean
81130
81194
  * } } ListGroupDefinition
81131
81195
  *
@@ -81453,6 +81517,7 @@
81453
81517
  } else if (isFunction$3(focusableInput.focus)) {
81454
81518
  focusableInput.focus();
81455
81519
  }
81520
+ focusableInput.scrollIntoView();
81456
81521
  }
81457
81522
  }
81458
81523
  }, [autoOpen, autoFocusEntry]);
@@ -81476,97 +81541,61 @@
81476
81541
  id,
81477
81542
  items,
81478
81543
  label,
81479
- shouldOpen = true,
81480
- shouldSort = true
81544
+ shouldOpen = true
81481
81545
  } = props;
81546
+ y(() => {
81547
+ if (props.shouldSort != undefined) {
81548
+ console.warn('the property \'shouldSort\' is no longer supported');
81549
+ }
81550
+ }, [props.shouldSort]);
81482
81551
  const groupRef = s$1(null);
81483
81552
  const [open, setOpen] = useLayoutState(['groups', id, 'open'], false);
81484
81553
  const [sticky, setSticky] = l$1(false);
81485
81554
  const onShow = A$1(() => setOpen(true), [setOpen]);
81486
- const [ordering, setOrdering] = l$1([]);
81487
- const [newItemAdded, setNewItemAdded] = l$1(false);
81555
+ const [localItems, setLocalItems] = l$1([]);
81556
+ const [newlyAddedItemIds, setNewlyAddedItemIds] = l$1([]);
81488
81557
 
81489
81558
  // Flag to mark that add button was clicked in the last render cycle
81490
81559
  const [addTriggered, setAddTriggered] = l$1(false);
81491
- const prevItems = usePrevious(items);
81492
81560
  const prevElement = usePrevious(element);
81493
81561
  const elementChanged = element !== prevElement;
81494
- const shouldHandleEffects = !elementChanged && (shouldSort || shouldOpen);
81562
+ const shouldHandleEffects = !elementChanged && shouldOpen;
81495
81563
 
81496
- // reset initial ordering when element changes (before first render)
81497
- if (elementChanged) {
81498
- setOrdering(createOrdering(shouldSort ? sortItems(items) : items));
81499
- }
81500
-
81501
- // keep ordering in sync to items - and open changes
81502
-
81503
- // (0) set initial ordering from given items
81564
+ // (0) delay setting items
81565
+ //
81566
+ // We need to this to align the render cycles of items
81567
+ // with the detection of newly added items.
81568
+ // This is important, because the autoOpen property can
81569
+ // only set per list item on its very first render.
81504
81570
  y(() => {
81505
- if (!prevItems || !shouldSort) {
81506
- setOrdering(createOrdering(items));
81507
- }
81508
- }, [items, element]);
81571
+ setLocalItems(items);
81572
+ }, [items]);
81509
81573
 
81510
- // (1) items were added
81574
+ // (1) handle auto opening when items were added
81511
81575
  y(() => {
81512
81576
  // reset addTriggered flag
81513
81577
  setAddTriggered(false);
81514
- if (shouldHandleEffects && prevItems && items.length > prevItems.length) {
81515
- let add = [];
81516
- items.forEach(item => {
81517
- if (!ordering.includes(item.id)) {
81518
- add.push(item.id);
81519
- }
81520
- });
81521
- let newOrdering = ordering;
81522
-
81523
- // open if not open, configured and triggered by add button
81524
- //
81525
- // TODO(marstamm): remove once we refactor layout handling for listGroups.
81526
- // Ideally, opening should be handled as part of the `add` callback and
81527
- // not be a concern for the ListGroup component.
81528
- if (addTriggered && !open && shouldOpen) {
81529
- toggleOpen();
81530
- }
81578
+ if (shouldHandleEffects && localItems) {
81579
+ if (addTriggered) {
81580
+ const previousItemIds = localItems.map(item => item.id);
81581
+ const currentItemsIds = items.map(item => item.id);
81582
+ const newItemIds = currentItemsIds.filter(itemId => !previousItemIds.includes(itemId));
81531
81583
 
81532
- // filter when not open and configured
81533
- if (!open && shouldSort) {
81534
- newOrdering = createOrdering(sortItems(items));
81535
- }
81536
-
81537
- // add new items on top or bottom depending on sorting behavior
81538
- newOrdering = newOrdering.filter(item => !add.includes(item));
81539
- if (shouldSort) {
81540
- newOrdering.unshift(...add);
81584
+ // open if not open, configured and triggered by add button
81585
+ //
81586
+ // TODO(marstamm): remove once we refactor layout handling for listGroups.
81587
+ // Ideally, opening should be handled as part of the `add` callback and
81588
+ // not be a concern for the ListGroup component.
81589
+ if (!open && shouldOpen && newItemIds.length > 0) {
81590
+ toggleOpen();
81591
+ }
81592
+ setNewlyAddedItemIds(newItemIds);
81541
81593
  } else {
81542
- newOrdering.push(...add);
81594
+ // ignore newly added items that do not result from a triggered add
81595
+ setNewlyAddedItemIds([]);
81543
81596
  }
81544
- setOrdering(newOrdering);
81545
- setNewItemAdded(addTriggered);
81546
- } else {
81547
- setNewItemAdded(false);
81548
- }
81549
- }, [items, open, shouldHandleEffects, addTriggered]);
81550
-
81551
- // (2) sort items on open if shouldSort is set
81552
- y(() => {
81553
- if (shouldSort && open && !newItemAdded) {
81554
- setOrdering(createOrdering(sortItems(items)));
81555
- }
81556
- }, [open, shouldSort]);
81557
-
81558
- // (3) items were deleted
81559
- y(() => {
81560
- if (shouldHandleEffects && prevItems && items.length < prevItems.length) {
81561
- let keep = [];
81562
- ordering.forEach(o => {
81563
- if (getItem(items, o)) {
81564
- keep.push(o);
81565
- }
81566
- });
81567
- setOrdering(keep);
81568
81597
  }
81569
- }, [items, shouldHandleEffects]);
81598
+ }, [items, open, shouldHandleEffects, addTriggered, localItems]);
81570
81599
 
81571
81600
  // set css class when group is sticky to top
81572
81601
  useStickyIntersectionObserver(groupRef, 'div.bio-properties-panel-scroll-container', setSticky);
@@ -81638,8 +81667,7 @@
81638
81667
  class: classNames('bio-properties-panel-list', open && hasItems ? 'open' : ''),
81639
81668
  children: e(LayoutContext.Provider, {
81640
81669
  value: propertiesPanelContext,
81641
- children: ordering.map((o, index) => {
81642
- const item = getItem(items, o);
81670
+ children: localItems.map((item, index) => {
81643
81671
  if (!item) {
81644
81672
  return;
81645
81673
  }
@@ -81649,7 +81677,7 @@
81649
81677
 
81650
81678
  // if item was added, open it
81651
81679
  // Existing items will not be affected as autoOpen is only applied on first render
81652
- const autoOpen = newItemAdded;
81680
+ const autoOpen = newlyAddedItemIds.includes(item.id);
81653
81681
  return v$1(ListItem, {
81654
81682
  ...item,
81655
81683
  autoOpen: autoOpen,
@@ -81662,21 +81690,6 @@
81662
81690
  })]
81663
81691
  });
81664
81692
  }
81665
-
81666
- // helpers ////////////////////
81667
-
81668
- /**
81669
- * Sorts given items alphanumeric by label
81670
- */
81671
- function sortItems(items) {
81672
- return sortBy(items, i => i.label.toLowerCase());
81673
- }
81674
- function getItem(items, id) {
81675
- return find$1(items, i => i.id === id);
81676
- }
81677
- function createOrdering(items) {
81678
- return items.map(i => i.id);
81679
- }
81680
81693
  function Checkbox(props) {
81681
81694
  const {
81682
81695
  id,
@@ -81963,6 +81976,7 @@
81963
81976
  onFocus,
81964
81977
  onBlur,
81965
81978
  autoResize,
81979
+ placeholder,
81966
81980
  rows = autoResize ? 1 : 2,
81967
81981
  tooltip
81968
81982
  } = props;
@@ -82005,6 +82019,7 @@
82005
82019
  onInput: handleInput,
82006
82020
  onFocus: onFocus,
82007
82021
  onBlur: onBlur,
82022
+ placeholder: placeholder,
82008
82023
  rows: rows,
82009
82024
  value: localValue,
82010
82025
  disabled: disabled,
@@ -82044,6 +82059,7 @@
82044
82059
  validate,
82045
82060
  onFocus,
82046
82061
  onBlur,
82062
+ placeholder,
82047
82063
  autoResize,
82048
82064
  tooltip
82049
82065
  } = props;
@@ -82079,6 +82095,7 @@
82079
82095
  debounce: debounce,
82080
82096
  monospace: monospace,
82081
82097
  disabled: disabled,
82098
+ placeholder: placeholder,
82082
82099
  autoResize: autoResize,
82083
82100
  tooltip: tooltip,
82084
82101
  element: element
@@ -82110,6 +82127,7 @@
82110
82127
  onInput,
82111
82128
  onFocus,
82112
82129
  onBlur,
82130
+ placeholder,
82113
82131
  value = '',
82114
82132
  tooltip
82115
82133
  } = props;
@@ -82151,6 +82169,7 @@
82151
82169
  onInput: handleInput,
82152
82170
  onFocus: onFocus,
82153
82171
  onBlur: onBlur,
82172
+ placeholder: placeholder,
82154
82173
  value: localValue
82155
82174
  })]
82156
82175
  });
@@ -82184,6 +82203,7 @@
82184
82203
  validate,
82185
82204
  onFocus,
82186
82205
  onBlur,
82206
+ placeholder,
82187
82207
  tooltip
82188
82208
  } = props;
82189
82209
  const globalError = useError(id);
@@ -82215,6 +82235,7 @@
82215
82235
  onInput: onInput,
82216
82236
  onFocus: onFocus,
82217
82237
  onBlur: onBlur,
82238
+ placeholder: placeholder,
82218
82239
  value: value,
82219
82240
  tooltip: tooltip,
82220
82241
  element: element
@@ -84940,8 +84961,7 @@
84940
84961
  });
84941
84962
  return {
84942
84963
  items,
84943
- add: addEntry,
84944
- shouldSort: false
84964
+ add: addEntry
84945
84965
  };
84946
84966
  }
84947
84967
 
@@ -85772,8 +85792,7 @@
85772
85792
  });
85773
85793
  return {
85774
85794
  items,
85775
- add: addEntry,
85776
- shouldSort: false
85795
+ add: addEntry
85777
85796
  };
85778
85797
  }
85779
85798
  function GeneralGroup(field, editField, getService) {
@@ -86269,8 +86288,7 @@
86269
86288
  id: 'custom-values',
86270
86289
  items,
86271
86290
  label: 'Custom properties',
86272
- tooltip: 'Add properties directly to the form schema, useful to configure functionality in custom-built task applications and form renderers.',
86273
- shouldSort: false
86291
+ tooltip: 'Add properties directly to the form schema, useful to configure functionality in custom-built task applications and form renderers.'
86274
86292
  };
86275
86293
  }
86276
86294
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bpmn-io/form-js-playground",
3
- "version": "1.8.7",
3
+ "version": "1.8.8",
4
4
  "description": "A form-js playground",
5
5
  "files": [
6
6
  "dist"
@@ -45,8 +45,8 @@
45
45
  "url": "https://github.com/bpmn-io"
46
46
  },
47
47
  "dependencies": {
48
- "@bpmn-io/form-js-editor": "^1.8.7",
49
- "@bpmn-io/form-js-viewer": "^1.8.7",
48
+ "@bpmn-io/form-js-editor": "^1.8.8",
49
+ "@bpmn-io/form-js-viewer": "^1.8.8",
50
50
  "@codemirror/autocomplete": "^6.16.0",
51
51
  "@codemirror/commands": "^6.5.0",
52
52
  "@codemirror/lang-json": "^6.0.1",
@@ -71,5 +71,5 @@
71
71
  "rollup-plugin-css-only": "^4.5.2",
72
72
  "style-loader": "^4.0.0"
73
73
  },
74
- "gitHead": "aaaaf358018b2410011613345a5e254fccdea891"
74
+ "gitHead": "7549b6d3423ae88e877510bb0c8ac27ab8d07758"
75
75
  }