@bpmn-io/form-js-viewer 1.21.2 → 1.23.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
@@ -13,7 +13,7 @@ import { createPortal } from 'preact/compat';
13
13
  import DOMPurify from 'dompurify';
14
14
  import { Injector } from 'didi';
15
15
  import { parseExpression, parseUnaryTests, evaluate, unaryTest } from '@bpmn-io/feelin';
16
- import { evaluate as evaluate$1, parser, buildSimpleTree } from 'feelers';
16
+ import { evaluate as evaluate$1, parseToSimpleTree } from 'feelers';
17
17
  import { marked } from 'marked';
18
18
 
19
19
  const getFlavouredFeelVariableNames = (feelString, feelFlavour = 'expression', options = {}) => {
@@ -356,7 +356,7 @@ class FeelersTemplating {
356
356
  * @param {Object} options
357
357
  * @param {boolean} [options.debug = false]
358
358
  * @param {boolean} [options.strict = false]
359
- * @param {Function} [options.buildDebugString]
359
+ * @param {(error: Error) => string} [options.buildDebugString]
360
360
  * @param {Function} [options.sanitizer]
361
361
  *
362
362
  * @returns
@@ -383,20 +383,19 @@ class FeelersTemplating {
383
383
  */
384
384
 
385
385
  /**
386
- * Extracts all feel expressions in the template along with their depth in the syntax tree.
387
- * The depth is incremented for child expressions of loops to account for context drilling.
388
- * @name extractExpressionsWithDepth
389
- * @param {string} template - A feelers template string.
390
- * @returns {Array<ExpressionWithDepth>} An array of objects, each containing the depth and the extracted expression.
391
- *
392
- * @example
393
- * const template = "Hello {{user}}, you have:{{#loop items}}\n- {{amount}} {{name}}{{/loop}}.";
394
- * const extractedExpressions = _extractExpressionsWithDepth(template);
395
- */
386
+ * Extracts all feel expressions in the template along with their depth in the syntax tree.
387
+ * The depth is incremented for child expressions of loops to account for context drilling.
388
+ * @name _extractExpressionsWithDepth
389
+ * @param {string} template - A feelers template string.
390
+ * @returns {Array<ExpressionWithDepth>} An array of objects, each containing the depth and the extracted expression.
391
+ *
392
+ * @example
393
+ * const template = "Hello {{user}}, you have:{{#loop items}}\n- {{amount}} {{name}}{{/loop}}.";
394
+ * const extractedExpressions = _extractExpressionsWithDepth(template);
395
+ */
396
396
  _extractExpressionsWithDepth(template) {
397
397
  // build simplified feelers syntax tree
398
- const parseTree = parser.parse(template);
399
- const tree = buildSimpleTree(parseTree, template);
398
+ const tree = parseToSimpleTree(template);
400
399
  return function _traverse(n, depth = 0) {
401
400
  if (['Feel', 'FeelBlock'].includes(n.name)) {
402
401
  return [{
@@ -843,6 +842,50 @@ function runRecursively(formField, fn) {
843
842
  });
844
843
  fn(formField);
845
844
  }
845
+
846
+ /**
847
+ * Returns a copy of `target` with the value at `path` removed, pruning any
848
+ * ancestor that becomes empty. Pure: the input is not mutated and untouched
849
+ * sibling branches keep their original references (path-cloning).
850
+ *
851
+ * Pruning rules:
852
+ * - An object ancestor is removed when it has no own keys left.
853
+ * - An array ancestor is removed when every entry is nullish. Arrays are
854
+ * never compacted; `delete` leaves a sparse hole so sibling indexes stay
855
+ * stable.
856
+ *
857
+ * @template T
858
+ * @param {T} target
859
+ * @param {Array<string|number>} path
860
+ * @returns {T}
861
+ */
862
+ function pruneAt(target, path) {
863
+ if (!path.length) {
864
+ return target;
865
+ }
866
+ const cloneContainer = c => Array.isArray(c) ? c.slice() : {
867
+ ...c
868
+ };
869
+ const clones = [cloneContainer(target)];
870
+ for (let i = 0; i < path.length - 1; i++) {
871
+ const next = clones[i][path[i]];
872
+ if (next == null || typeof next !== 'object') {
873
+ return target;
874
+ }
875
+ const cloned = cloneContainer(next);
876
+ clones[i][path[i]] = cloned;
877
+ clones.push(cloned);
878
+ }
879
+ delete clones[clones.length - 1][path[path.length - 1]];
880
+ for (let i = clones.length - 1; i > 0; i--) {
881
+ if (Object.values(clones[i]).every(v => v == null)) {
882
+ delete clones[i - 1][path[i - 1]];
883
+ } else {
884
+ break;
885
+ }
886
+ }
887
+ return clones[0];
888
+ }
846
889
  function wrapObjectKeysWithUnderscores(obj) {
847
890
  const newObj = {};
848
891
  for (const [key, value] of Object.entries(obj)) {
@@ -3766,6 +3809,11 @@ function willKeyProduceValidNumber(key, previousValue, caretIndex, selectionWidt
3766
3809
  function isNullEquivalentValue(value) {
3767
3810
  return value === undefined || value === null || value === '';
3768
3811
  }
3812
+ function serializeToInputString(value) {
3813
+ if (value === undefined || value === null) return '';
3814
+ if (typeof value !== 'string' && typeof value !== 'number') return '';
3815
+ return value.toString();
3816
+ }
3769
3817
 
3770
3818
  const type$d = 'number';
3771
3819
  function Numberfield(props) {
@@ -3849,7 +3897,7 @@ function Numberfield(props) {
3849
3897
  const outerValueChanged = previousValue != value;
3850
3898
  const outerValueEqualsCache = sanitize(value) === sanitize(cachedValue);
3851
3899
  if (outerValueChanged && !outerValueEqualsCache) {
3852
- setValue(value && value.toString() || '');
3900
+ setValue(serializeToInputString(value));
3853
3901
  }
3854
3902
 
3855
3903
  // caches the value an increment/decrement operation will be based on
@@ -7454,9 +7502,16 @@ class UpdateFieldInstanceValidationHandler {
7454
7502
  } = this._form._getState();
7455
7503
  context.oldErrors = clone(errors);
7456
7504
  const fieldErrors = this._validator.validateFieldInstance(fieldInstance, value);
7457
- const updatedErrors = set(errors, [id, ...Object.values(indexes || {})], fieldErrors.length ? fieldErrors : undefined);
7505
+ const errorPath = [id, ...Object.values(indexes || {})];
7506
+ let nextErrors;
7507
+ if (fieldErrors.length) {
7508
+ set(errors, errorPath, fieldErrors);
7509
+ nextErrors = errors;
7510
+ } else {
7511
+ nextErrors = pruneAt(errors, errorPath);
7512
+ }
7458
7513
  this._form._setState({
7459
- errors: updatedErrors
7514
+ errors: nextErrors
7460
7515
  });
7461
7516
  }
7462
7517
  revert(context) {
@@ -9817,11 +9872,18 @@ class Form {
9817
9872
  const validator = this.get('validator');
9818
9873
  const fieldErrors = validator.validateFieldInstance(fieldInstance, value);
9819
9874
  set(data, valuePath, value);
9820
- set(errors, [id, ...Object.values(indexes || {})], fieldErrors.length ? fieldErrors : undefined);
9875
+ const errorPath = [id, ...Object.values(indexes || {})];
9876
+ let nextErrors;
9877
+ if (fieldErrors.length) {
9878
+ set(errors, errorPath, fieldErrors);
9879
+ nextErrors = errors;
9880
+ } else {
9881
+ nextErrors = pruneAt(errors, errorPath);
9882
+ }
9821
9883
  this._emit('field.updated', update);
9822
9884
  this._setState({
9823
9885
  data: clone(data),
9824
- errors: clone(errors)
9886
+ errors: clone(nextErrors)
9825
9887
  });
9826
9888
  }
9827
9889
 
@@ -9997,5 +10059,5 @@ function createForm(options) {
9997
10059
  });
9998
10060
  }
9999
10061
 
10000
- export { ALLOW_ATTRIBUTE, Button, Checkbox, Checklist, ConditionChecker, DATETIME_SUBTYPES, DATETIME_SUBTYPES_LABELS, DATETIME_SUBTYPE_PATH, DATE_DISALLOW_PAST_PATH, DATE_LABEL_PATH, Datetime, Default, Description, DocumentPreview, DynamicList, Errors, ExpressionField, ExpressionFieldModule, ExpressionLanguageModule, ExpressionLoopPreventer, FeelExpressionLanguage, FeelersTemplating, FieldFactory, FilePicker, Form, FormComponent, FormContext, FormField, FormFieldRegistry, FormFields, FormLayouter, FormRenderContext, Group, Html, IFrame, Image, Importer, Label, LocalExpressionContext, MINUTES_IN_DAY, MarkdownRenderer, MarkdownRendererModule, Numberfield, OPTIONS_SOURCES, OPTIONS_SOURCES_DEFAULTS, OPTIONS_SOURCES_LABELS, OPTIONS_SOURCES_PATHS, OPTIONS_SOURCE_DEFAULT, PathRegistry, Radio, RenderModule, RepeatRenderManager, RepeatRenderModule, SANDBOX_ATTRIBUTE, SECURITY_ATTRIBUTES_DEFINITIONS, Select, Separator, Spacer, TEXT_VIEW_DEFAULT_TEXT, TIME_INTERVAL_PATH, TIME_LABEL_PATH, TIME_SERIALISINGFORMAT_LABELS, TIME_SERIALISING_FORMATS, TIME_SERIALISING_FORMAT_PATH, TIME_USE24H_PATH, Table, Taglist, Text, Textarea, Textfield, ViewerCommands, ViewerCommandsModule, buildExpressionContext, clone, createForm, createFormContainer, createInjector, escapeHTML, formFields, generateIdForType, generateIndexForType, getAncestryList, getOptionsSource, getSchemaVariables, getScrollContainer, hasEqualValue, iconsByType, isRequired, pathParse, pathsEqual, runExpressionEvaluation, runRecursively, runUnaryTestEvaluation, sanitizeDateTimePickerValue, sanitizeHTML, sanitizeIFrameSource, sanitizeImageSource, sanitizeMultiSelectValue, sanitizeSingleSelectValue, schemaVersion, useExpressionEvaluation, useSingleLineTemplateEvaluation, useTemplateEvaluation, wrapCSSStyles, wrapObjectKeysWithUnderscores };
10062
+ export { ALLOW_ATTRIBUTE, Button, Checkbox, Checklist, ConditionChecker, DATETIME_SUBTYPES, DATETIME_SUBTYPES_LABELS, DATETIME_SUBTYPE_PATH, DATE_DISALLOW_PAST_PATH, DATE_LABEL_PATH, Datetime, Default, Description, DocumentPreview, DynamicList, Errors, ExpressionField, ExpressionFieldModule, ExpressionLanguageModule, ExpressionLoopPreventer, FeelExpressionLanguage, FeelersTemplating, FieldFactory, FilePicker, Form, FormComponent, FormContext, FormField, FormFieldRegistry, FormFields, FormLayouter, FormRenderContext, Group, Html, IFrame, Image, Importer, Label, LocalExpressionContext, MINUTES_IN_DAY, MarkdownRenderer, MarkdownRendererModule, Numberfield, OPTIONS_SOURCES, OPTIONS_SOURCES_DEFAULTS, OPTIONS_SOURCES_LABELS, OPTIONS_SOURCES_PATHS, OPTIONS_SOURCE_DEFAULT, PathRegistry, Radio, RenderModule, RepeatRenderManager, RepeatRenderModule, SANDBOX_ATTRIBUTE, SECURITY_ATTRIBUTES_DEFINITIONS, Select, Separator, Spacer, TEXT_VIEW_DEFAULT_TEXT, TIME_INTERVAL_PATH, TIME_LABEL_PATH, TIME_SERIALISINGFORMAT_LABELS, TIME_SERIALISING_FORMATS, TIME_SERIALISING_FORMAT_PATH, TIME_USE24H_PATH, Table, Taglist, Text, Textarea, Textfield, ViewerCommands, ViewerCommandsModule, buildExpressionContext, clone, createForm, createFormContainer, createInjector, escapeHTML, formFields, generateIdForType, generateIndexForType, getAncestryList, getOptionsSource, getSchemaVariables, getScrollContainer, hasEqualValue, iconsByType, isRequired, pathParse, pathsEqual, pruneAt, runExpressionEvaluation, runRecursively, runUnaryTestEvaluation, sanitizeDateTimePickerValue, sanitizeHTML, sanitizeIFrameSource, sanitizeImageSource, sanitizeMultiSelectValue, sanitizeSingleSelectValue, schemaVersion, useExpressionEvaluation, useSingleLineTemplateEvaluation, useTemplateEvaluation, wrapCSSStyles, wrapObjectKeysWithUnderscores };
10001
10063
  //# sourceMappingURL=index.es.js.map