@bpmn-io/form-js-viewer 1.24.0 → 1.25.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.
@@ -285,7 +285,8 @@
285
285
  }
286
286
 
287
287
  .fjs-container .fjs-inline-label {
288
- align-items: center;
288
+ /* keep the input next to the first line of a wrapping label */
289
+ align-items: flex-start;
289
290
  display: flex;
290
291
  }
291
292
 
@@ -390,6 +391,11 @@
390
391
  line-height: var(--line-height-input);
391
392
  letter-spacing: var(--letter-spacing-input);
392
393
  color: var(--color-text);
394
+
395
+ /* wrap long option labels instead of cutting them off */
396
+ white-space: normal;
397
+ overflow: visible;
398
+ overflow-wrap: anywhere;
393
399
  }
394
400
 
395
401
  .fjs-container .fjs-form-field-checklist .fjs-form-field-label:first-child,
@@ -269,7 +269,8 @@
269
269
  }
270
270
 
271
271
  .fjs-container .fjs-inline-label {
272
- align-items: center;
272
+ /* keep the input next to the first line of a wrapping label */
273
+ align-items: flex-start;
273
274
  display: flex;
274
275
  }
275
276
 
@@ -350,6 +351,10 @@
350
351
  line-height: var(--line-height-input);
351
352
  letter-spacing: var(--letter-spacing-input);
352
353
  color: var(--color-text);
354
+ /* wrap long option labels instead of cutting them off */
355
+ white-space: normal;
356
+ overflow: visible;
357
+ overflow-wrap: anywhere;
353
358
  }
354
359
 
355
360
  .fjs-container .fjs-form-field-checklist .fjs-form-field-label:first-child,
package/dist/index.cjs CHANGED
@@ -59,7 +59,26 @@ const getFlavouredFeelVariableNames = (feelString, feelFlavour = 'expression', o
59
59
  // if using special depth accessors, use a more complex extraction
60
60
  return Array.from(_smartExtractVariableNames(node, depth, specialDepthAccessors));
61
61
  }
62
- if (depth === 0 && node.name === 'VariableName') return [node.variableName];
62
+ if (depth === 0 && node.name === 'VariableName') return [_cleanupVariableName(node.variableName)];
63
+
64
+ // skip function names - the function name is the only direct VariableName child of a
65
+ // FunctionInvocation (arguments are nested under Positional/NamedParameters), so drop it
66
+ if (node.name === 'FunctionInvocation') {
67
+ const args = node.children.filter(child => child.name !== 'VariableName');
68
+ return args.reduce((acc, child) => acc.concat(_unfoldVariables(child)), []);
69
+ }
70
+
71
+ // skip type names in instance of expressions
72
+ if (node.name === 'Type') {
73
+ return [];
74
+ }
75
+
76
+ // handle quantified (some...satisfies) and for expressions - exclude bound iteration variables
77
+ if (node.name === 'QuantifiedExpression' || node.name === 'ForExpression') {
78
+ const boundNames = _collectBoundVariableNames(node);
79
+ const variables = node.children.reduce((acc, child) => acc.concat(_unfoldVariables(child)), []);
80
+ return variables.filter(name => !boundNames.includes(name));
81
+ }
63
82
 
64
83
  // for any other kind of node, traverse its children and flatten the result
65
84
  if (node.children) {
@@ -184,6 +203,9 @@ const _buildSimpleFeelStructureTree = (parseTree, feelString) => {
184
203
  if (node.type.name === 'VariableName') {
185
204
  nodeRepresentation.variableName = feelString.slice(node.from, node.to);
186
205
  }
206
+ if (node.type.name === 'Name') {
207
+ nodeRepresentation.variableName = feelString.slice(node.from, node.to);
208
+ }
187
209
  stack.push(nodeRepresentation);
188
210
  },
189
211
  leave: () => {
@@ -233,6 +255,53 @@ const _extractFilterExpressions = tree => {
233
255
  return flattenedExpressionTree;
234
256
  };
235
257
 
258
+ /**
259
+ * FEEL keywords that may be incorrectly absorbed into variable names by the parser.
260
+ * For example, `variable1 not in (...)` parses as VariableName "variable1 not".
261
+ */
262
+ const FEEL_TRAILING_KEYWORDS = ['not'];
263
+
264
+ /**
265
+ * Cleans up a variable name by stripping trailing FEEL keywords that the parser
266
+ * may have incorrectly included as part of the variable name.
267
+ *
268
+ * @param {string} variableName - The raw variable name from the parse tree.
269
+ * @returns {string} The cleaned variable name.
270
+ */
271
+ const _cleanupVariableName = variableName => {
272
+ for (const keyword of FEEL_TRAILING_KEYWORDS) {
273
+ if (variableName.endsWith(' ' + keyword)) {
274
+ return variableName.slice(0, -(keyword.length + 1));
275
+ }
276
+ }
277
+ return variableName;
278
+ };
279
+
280
+ /**
281
+ * Collects the names of variables bound by iteration constructs (e.g. `for x in ...`, `some x in ...`).
282
+ * These are locally scoped and should be excluded from the extracted variable set.
283
+ *
284
+ * @param {Object} node - A QuantifiedExpression or ForExpression node.
285
+ * @returns {string[]} The bound variable names.
286
+ */
287
+ const _collectBoundVariableNames = node => {
288
+ const boundNames = [];
289
+ const collect = n => {
290
+ if (n.name === 'InExpression') {
291
+ // The Name node inside an InExpression is the bound iteration variable
292
+ const nameNode = n.children.find(child => child.name === 'Name');
293
+ if (nameNode && nameNode.variableName) {
294
+ boundNames.push(nameNode.variableName);
295
+ }
296
+ }
297
+ if (n.children) {
298
+ n.children.forEach(collect);
299
+ }
300
+ };
301
+ collect(node);
302
+ return boundNames;
303
+ };
304
+
236
305
  class FeelExpressionLanguage {
237
306
  constructor(eventBus) {
238
307
  this._eventBus = eventBus;
@@ -1891,10 +1960,13 @@ function Label(props) {
1891
1960
  class: classNames('fjs-form-field-label', {
1892
1961
  'fjs-incollapsible-label': !collapseOnEmpty
1893
1962
  }, props['class']),
1894
- children: [props.children, evaluatedLabel, required && jsxRuntime.jsx("span", {
1895
- class: "fjs-asterix",
1896
- "aria-hidden": true,
1897
- children: "*"
1963
+ children: [props.children, jsxRuntime.jsxs("span", {
1964
+ class: "fjs-label-content",
1965
+ children: [evaluatedLabel, required && jsxRuntime.jsx("span", {
1966
+ class: "fjs-asterix",
1967
+ "aria-hidden": true,
1968
+ children: "*"
1969
+ })]
1898
1970
  })]
1899
1971
  });
1900
1972
  }
@@ -6091,11 +6163,10 @@ function DocumentPreview(props) {
6091
6163
  if (!isValidDocumentEndpoint(finalEndpoint)) {
6092
6164
  return null;
6093
6165
  }
6094
- const requestInit = getDocumentRequestInit(documentEndpointBuilder, document);
6095
6166
  return jsxRuntime.jsx(DocumentRenderer, {
6096
6167
  documentMetadata: document,
6168
+ documentEndpointBuilder: documentEndpointBuilder,
6097
6169
  endpoint: finalEndpoint,
6098
- requestInit: requestInit,
6099
6170
  maxHeight: maxHeight,
6100
6171
  domId: `${domId}-${index}`
6101
6172
  }, document.documentId);
@@ -6277,9 +6348,9 @@ function ImageRenderer(props) {
6277
6348
  *
6278
6349
  * @param {Object} props
6279
6350
  * @param {DocumentMetadata} props.documentMetadata
6351
+ * @param {DocumentEndpointBuilder | null} props.documentEndpointBuilder
6280
6352
  * @param {string} props.endpoint
6281
6353
  * @param {string} props.domId
6282
- * @param {RequestInit|undefined} props.requestInit
6283
6354
  * @param {number|undefined} props.maxHeight
6284
6355
  *
6285
6356
  * @returns {import("preact").JSX.Element}
@@ -6287,10 +6358,10 @@ function ImageRenderer(props) {
6287
6358
  function DocumentRenderer(props) {
6288
6359
  const {
6289
6360
  documentMetadata,
6361
+ documentEndpointBuilder,
6290
6362
  endpoint,
6291
6363
  maxHeight,
6292
- domId,
6293
- requestInit
6364
+ domId
6294
6365
  } = props;
6295
6366
  const {
6296
6367
  metadata
@@ -6298,6 +6369,8 @@ function DocumentRenderer(props) {
6298
6369
  const [hasError, setHasError] = hooks.useState(false);
6299
6370
  const ref = hooks.useRef(null);
6300
6371
  const isInViewport = useInViewport(ref);
6372
+ const onError = hooks.useCallback(() => setHasError(true), []);
6373
+ const requestInit = hooks.useMemo(() => getDocumentRequestInit(documentEndpointBuilder, documentMetadata), [documentEndpointBuilder, documentMetadata]);
6301
6374
  const singleDocumentContainerClassName = `fjs-${type}-single-document-container`;
6302
6375
  const errorMessageId = `${domId}-error-message`;
6303
6376
  const errorMessage = 'Unable to download document';
@@ -6313,14 +6386,12 @@ function DocumentRenderer(props) {
6313
6386
  url: endpoint,
6314
6387
  alt: metadata.fileName,
6315
6388
  requestInit: requestInit,
6316
- onError: () => setHasError(true)
6389
+ onError: onError
6317
6390
  }), jsxRuntime.jsx(DownloadButton, {
6318
6391
  endpoint: endpoint,
6319
6392
  fileName: metadata.fileName,
6320
6393
  requestInit: requestInit,
6321
- onDownloadError: () => {
6322
- setHasError(true);
6323
- }
6394
+ onDownloadError: onError
6324
6395
  }), hasError ? jsxRuntime.jsx(Errors, {
6325
6396
  id: errorMessageId,
6326
6397
  errors: [errorMessage]
@@ -6338,7 +6409,7 @@ function DocumentRenderer(props) {
6338
6409
  url: endpoint,
6339
6410
  fileName: metadata.fileName,
6340
6411
  requestInit: requestInit,
6341
- onError: () => setHasError(true),
6412
+ onError: onError,
6342
6413
  errorMessageId: errorMessageId
6343
6414
  })
6344
6415
  });
@@ -6359,9 +6430,7 @@ function DocumentRenderer(props) {
6359
6430
  endpoint: endpoint,
6360
6431
  fileName: metadata.fileName,
6361
6432
  requestInit: requestInit,
6362
- onDownloadError: () => {
6363
- setHasError(true);
6364
- }
6433
+ onDownloadError: onError
6365
6434
  })]
6366
6435
  });
6367
6436
  }