@formio/js 5.3.3 → 5.3.5

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.
Files changed (52) hide show
  1. package/dist/formio.embed.js +1 -1
  2. package/dist/formio.embed.min.js +1 -1
  3. package/dist/formio.embed.min.js.LICENSE.txt +1 -1
  4. package/dist/formio.form.js +22 -22
  5. package/dist/formio.form.min.js +1 -1
  6. package/dist/formio.form.min.js.LICENSE.txt +2 -2
  7. package/dist/formio.full.js +22 -22
  8. package/dist/formio.full.min.js +1 -1
  9. package/dist/formio.full.min.js.LICENSE.txt +2 -2
  10. package/dist/formio.js +11 -11
  11. package/dist/formio.min.js +1 -1
  12. package/dist/formio.min.js.LICENSE.txt +2 -2
  13. package/dist/formio.utils.js +10 -10
  14. package/dist/formio.utils.min.js +1 -1
  15. package/dist/formio.utils.min.js.LICENSE.txt +2 -2
  16. package/lib/cjs/Element.d.ts +11 -0
  17. package/lib/cjs/Element.js +24 -0
  18. package/lib/cjs/Embed.js +1 -1
  19. package/lib/cjs/Formio.js +1 -1
  20. package/lib/cjs/Webform.js +7 -4
  21. package/lib/cjs/Wizard.js +15 -11
  22. package/lib/cjs/components/Components.js +3 -1
  23. package/lib/cjs/components/_classes/component/Component.d.ts +8 -0
  24. package/lib/cjs/components/_classes/component/Component.js +31 -18
  25. package/lib/cjs/components/_classes/nested/NestedComponent.js +5 -7
  26. package/lib/cjs/components/datagrid/DataGrid.js +21 -5
  27. package/lib/cjs/components/editgrid/EditGrid.js +2 -2
  28. package/lib/cjs/components/file/File.js +6 -5
  29. package/lib/cjs/components/form/Form.d.ts +1 -0
  30. package/lib/cjs/components/form/Form.js +18 -7
  31. package/lib/cjs/package.json +1 -1
  32. package/lib/cjs/utils/formUtils.d.ts +2 -2
  33. package/lib/cjs/utils/index.d.ts +2 -2
  34. package/lib/mjs/Element.d.ts +11 -0
  35. package/lib/mjs/Element.js +23 -0
  36. package/lib/mjs/Embed.js +1 -1
  37. package/lib/mjs/Formio.js +1 -1
  38. package/lib/mjs/Webform.js +5 -1
  39. package/lib/mjs/Wizard.js +9 -10
  40. package/lib/mjs/components/Components.js +3 -1
  41. package/lib/mjs/components/_classes/component/Component.d.ts +8 -0
  42. package/lib/mjs/components/_classes/component/Component.js +30 -18
  43. package/lib/mjs/components/_classes/nested/NestedComponent.js +5 -6
  44. package/lib/mjs/components/datagrid/DataGrid.js +21 -5
  45. package/lib/mjs/components/editgrid/EditGrid.js +1 -1
  46. package/lib/mjs/components/file/File.js +6 -5
  47. package/lib/mjs/components/form/Form.d.ts +1 -0
  48. package/lib/mjs/components/form/Form.js +16 -5
  49. package/lib/mjs/package.json +1 -1
  50. package/lib/mjs/utils/formUtils.d.ts +2 -2
  51. package/lib/mjs/utils/index.d.ts +2 -2
  52. package/package.json +2 -2
@@ -18,9 +18,9 @@
18
18
  * MIT licensed
19
19
  */
20
20
 
21
- /*! @license DOMPurify 3.3.3 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.3.3/LICENSE */
21
+ /*! @license DOMPurify 3.4.0 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.4.0/LICENSE */
22
22
 
23
- /*! formiojs v5.3.3 | https://unpkg.com/formiojs@5.3.3/LICENSE.txt */
23
+ /*! formiojs v5.3.5 | https://unpkg.com/formiojs@5.3.5/LICENSE.txt */
24
24
 
25
25
  /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */
26
26
 
@@ -210,6 +210,17 @@ export default class Element {
210
210
  * @returns {this} - The instance of the element.
211
211
  */
212
212
  removeClass(element: HTMLElement, className: string): this;
213
+ /**
214
+ * Idempotently add or remove a class on a DOM element based on a boolean.
215
+ * Skips the mutation when the element is already in the desired state, so
216
+ * callers can safely invoke it on every change without triggering redundant
217
+ * CSS transitions or attribute writes.
218
+ * @param {HTMLElement} element - The DOM element to toggle the class on.
219
+ * @param {string} className - The class name to add or remove.
220
+ * @param {boolean} want - TRUE to ensure the class is present, FALSE to ensure it is absent.
221
+ * @returns {this} - The instance of the element.
222
+ */
223
+ toggleClass(element: HTMLElement, className: string, want: boolean): this;
213
224
  /**
214
225
  * Empty's an HTML DOM element.
215
226
  * @param {HTMLElement} element - The element you wish to empty.
@@ -487,6 +487,30 @@ class Element {
487
487
  }
488
488
  return this;
489
489
  }
490
+ /**
491
+ * Idempotently add or remove a class on a DOM element based on a boolean.
492
+ * Skips the mutation when the element is already in the desired state, so
493
+ * callers can safely invoke it on every change without triggering redundant
494
+ * CSS transitions or attribute writes.
495
+ * @param {HTMLElement} element - The DOM element to toggle the class on.
496
+ * @param {string} className - The class name to add or remove.
497
+ * @param {boolean} want - TRUE to ensure the class is present, FALSE to ensure it is absent.
498
+ * @returns {this} - The instance of the element.
499
+ */
500
+ toggleClass(element, className, want) {
501
+ var _a;
502
+ if (!element || !className || !(element instanceof HTMLElement)) {
503
+ return this;
504
+ }
505
+ const has = !!((_a = element.classList) === null || _a === void 0 ? void 0 : _a.contains(className));
506
+ if (want && !has) {
507
+ this.addClass(element, className);
508
+ }
509
+ else if (!want && has) {
510
+ this.removeClass(element, className);
511
+ }
512
+ return this;
513
+ }
490
514
  /**
491
515
  * Empty's an HTML DOM element.
492
516
  * @param {HTMLElement} element - The element you wish to empty.
package/lib/cjs/Embed.js CHANGED
@@ -481,7 +481,7 @@ Formio.formioReady = new Promise((ready, reject) => {
481
481
  _a._formioReady = ready;
482
482
  _a._formioReadyReject = reject;
483
483
  });
484
- Formio.version = '5.3.3';
484
+ Formio.version = '5.3.5';
485
485
  // Create a report.
486
486
  Formio.Report = {
487
487
  create: (element, submission, options = {}) => __awaiter(void 0, void 0, void 0, function* () {
package/lib/cjs/Formio.js CHANGED
@@ -11,7 +11,7 @@ const CDN_1 = __importDefault(require("./CDN"));
11
11
  const providers_1 = __importDefault(require("./providers"));
12
12
  sdk_1.Formio.cdn = new CDN_1.default();
13
13
  sdk_1.Formio.Providers = providers_1.default;
14
- sdk_1.Formio.version = '5.3.3';
14
+ sdk_1.Formio.version = '5.3.5';
15
15
  CDN_1.default.defaultCDN = sdk_1.Formio.version.includes('rc')
16
16
  ? 'https://cdn.test-form.io'
17
17
  : 'https://cdn.form.io';
@@ -1030,7 +1030,7 @@ class Webform extends NestedDataComponent_1.default {
1030
1030
  * @returns {void|Array} - The errors that were set.
1031
1031
  */
1032
1032
  showErrors(errors, triggerEvent) {
1033
- var _a;
1033
+ var _a, _b;
1034
1034
  this.loading = false;
1035
1035
  if (!Array.isArray(errors)) {
1036
1036
  errors = [
@@ -1103,7 +1103,10 @@ class Webform extends NestedDataComponent_1.default {
1103
1103
  });
1104
1104
  }
1105
1105
  const errorsList = this.renderTemplate('errorsList', { errors: displayedErrors });
1106
- (_a = this.root) === null || _a === void 0 ? void 0 : _a.setAlert('danger', errorsList);
1106
+ // Only paint the alert from a subform when the root won't double paint it to avoid a painful flicker
1107
+ if (this === this.root || !((_a = this.root) === null || _a === void 0 ? void 0 : _a.submitted)) {
1108
+ (_b = this.root) === null || _b === void 0 ? void 0 : _b.setAlert('danger', errorsList);
1109
+ }
1107
1110
  if (triggerEvent) {
1108
1111
  this.emit('error', errors);
1109
1112
  }
@@ -1202,7 +1205,7 @@ class Webform extends NestedDataComponent_1.default {
1202
1205
  * @param {any} changes - The changes that have occured in the form.
1203
1206
  */
1204
1207
  onChange(flags, changed, modified, changes) {
1205
- var _a;
1208
+ var _a, _b;
1206
1209
  flags = flags || {};
1207
1210
  let isChangeEventEmitted = false;
1208
1211
  if (((_a = this.parent) === null || _a === void 0 ? void 0 : _a.subForm) === this) {
@@ -1222,7 +1225,7 @@ class Webform extends NestedDataComponent_1.default {
1222
1225
  flags.fromIframe ||
1223
1226
  (flags.fromSubmission && this.rootPristine && this.pristine && flags.changed);
1224
1227
  const errors = shouldValidate
1225
- ? this.validate(value.data, Object.assign(Object.assign({}, flags), { noValidate: false, process: 'change' }))
1228
+ ? this.validate(value.data, Object.assign(Object.assign({}, flags), { noValidate: false, process: 'change', dirty: (_b = flags.dirty) !== null && _b !== void 0 ? _b : this.submitted }))
1226
1229
  : [];
1227
1230
  value.isValid = (errors || []).filter((err) => !err.fromServer).length === 0;
1228
1231
  this.loading = false;
package/lib/cjs/Wizard.js CHANGED
@@ -188,6 +188,7 @@ class Wizard extends Webform_1.default {
188
188
  return this.renderTemplate(headerType, ctx);
189
189
  }
190
190
  render() {
191
+ var _a;
191
192
  const ctx = this.renderContext;
192
193
  if (this.component.id) {
193
194
  ctx.panels.forEach((panel) => {
@@ -206,7 +207,7 @@ class Wizard extends Webform_1.default {
206
207
  wizardHeaderLocation,
207
208
  wizardNav, components: this.renderComponents([
208
209
  ...this.prefixComps,
209
- ...this.currentPage.components,
210
+ ...((_a = this.currentPage) === null || _a === void 0 ? void 0 : _a.components) || [],
210
211
  ...this.suffixComps,
211
212
  ]) }), this.builderMode ? 'builder' : 'form');
212
213
  }
@@ -250,7 +251,7 @@ class Wizard extends Webform_1.default {
250
251
  * @returns {Promise} A promise that resolves when all components have been successfully attached.
251
252
  */
252
253
  attach(element) {
253
- var _a;
254
+ var _a, _b;
254
255
  this.setElement(element);
255
256
  this.loadRefs(element, {
256
257
  [this.wizardKey]: 'single',
@@ -268,7 +269,7 @@ class Wizard extends Webform_1.default {
268
269
  this.hook('attachWebform', element, this);
269
270
  const promises = this.attachComponents(this.refs[this.wizardKey], [
270
271
  ...this.prefixComps,
271
- ...this.currentPage.components,
272
+ ...((_b = this.currentPage) === null || _b === void 0 ? void 0 : _b.components) || [],
272
273
  ...this.suffixComps,
273
274
  ]);
274
275
  this.attachNav();
@@ -296,7 +297,8 @@ class Wizard extends Webform_1.default {
296
297
  isBreadcrumbClickable() {
297
298
  let currentPage = null;
298
299
  this.pages.map((page) => {
299
- if (lodash_1.default.isEqual(this.currentPage.component, page.component)) {
300
+ var _a;
301
+ if (lodash_1.default.isEqual((_a = this.currentPage) === null || _a === void 0 ? void 0 : _a.component, page.component)) {
300
302
  currentPage = page;
301
303
  }
302
304
  });
@@ -311,11 +313,12 @@ class Wizard extends Webform_1.default {
311
313
  isAllowPrevious() {
312
314
  let currentPage = null;
313
315
  this.pages.map((page) => {
314
- if (lodash_1.default.isEqual(this.currentPage.component, page.component)) {
316
+ var _a;
317
+ if (lodash_1.default.isEqual((_a = this.currentPage) === null || _a === void 0 ? void 0 : _a.component, page.component)) {
315
318
  currentPage = page;
316
319
  }
317
320
  });
318
- return lodash_1.default.get(currentPage.component, 'allowPrevious', this.options.allowPrevious);
321
+ return lodash_1.default.get(currentPage === null || currentPage === void 0 ? void 0 : currentPage.component, 'allowPrevious', this.options.allowPrevious);
319
322
  }
320
323
  /**
321
324
  * Handles navigate on 'Enter' key event in a wizard form.
@@ -544,7 +547,7 @@ class Wizard extends Webform_1.default {
544
547
  const forceShow = this.shouldForceShow(item);
545
548
  const forceHide = this.shouldForceHide(item);
546
549
  let isVisible = !page
547
- ? (0, utils_1.checkCondition)(item, data, data, this.component, this) && !item.hidden
550
+ ? ((0, utils_1.checkCondition)(item, data, data, this.component, this) && !item.hidden)
548
551
  : page.visible;
549
552
  if (forceShow) {
550
553
  isVisible = true;
@@ -615,8 +618,9 @@ class Wizard extends Webform_1.default {
615
618
  this._seenPages = this._seenPages.concat(parentNum);
616
619
  }
617
620
  return this.redraw().then(() => {
621
+ var _a;
618
622
  this.checkData(this.submission.data);
619
- this.triggerCaptcha(this.currentPage.components);
623
+ this.triggerCaptcha((_a = this.currentPage) === null || _a === void 0 ? void 0 : _a.components);
620
624
  const errors = this.submitted
621
625
  ? this.validate(this.localData, { dirty: true })
622
626
  : this.validateCurrentPage();
@@ -833,8 +837,7 @@ class Wizard extends Webform_1.default {
833
837
  return super.setForm(form, flags);
834
838
  }
835
839
  onSetForm(clonedForm, initialForm) {
836
- this.component.components =
837
- (this.parent ? initialForm.components : clonedForm.components) || [];
840
+ this.component.components = (this.parent ? initialForm.components : clonedForm.components) || [];
838
841
  this.setComponentSchema();
839
842
  }
840
843
  setEditMode(submission) {
@@ -944,11 +947,12 @@ class Wizard extends Webform_1.default {
944
947
  return super.rebuild().then(setCurrentPage);
945
948
  }
946
949
  checkValidity(data, dirty, row, currentPageOnly, childErrors = []) {
950
+ var _a;
947
951
  if (!this.checkCondition(row, data)) {
948
952
  this.setCustomValidity('');
949
953
  return true;
950
954
  }
951
- const components = !currentPageOnly || this.isLastPage() ? this.getComponents() : this.currentPage.components;
955
+ const components = !currentPageOnly || this.isLastPage() ? this.getComponents() : (_a = this.currentPage) === null || _a === void 0 ? void 0 : _a.components;
952
956
  return components.reduce((check, comp) => comp.checkValidity(data, dirty, row, currentPageOnly, childErrors) && check, true);
953
957
  }
954
958
  get errors() {
@@ -69,7 +69,9 @@ class Components {
69
69
  comp = new Component_1.default(component, options, data);
70
70
  }
71
71
  if (comp.path) {
72
- comp.componentsMap[comp.path] = comp;
72
+ comp.eachRootChildComponentsMap((map) => {
73
+ map[comp.path] = comp;
74
+ });
73
75
  }
74
76
  // Reset the componentMatches on the root element if any new component is created.
75
77
  let parent = comp.parent;
@@ -163,6 +163,14 @@ declare class Component extends Element {
163
163
  */
164
164
  info: any;
165
165
  get componentsMap(): object;
166
+ /**
167
+ * Walks this component's root chain, invoking `fn` with each ancestor root's
168
+ * `childComponentsMap`. Component registration is propagated up the wizard /
169
+ * nested-form chain at create time, so any code that mutates a registration
170
+ * (creation, removal, path-driven re-key) must update every map in the chain.
171
+ * @param {(map: object) => void} fn - Called once per root that exposes a `childComponentsMap`.
172
+ */
173
+ eachRootChildComponentsMap(fn: (map: object) => void): void;
166
174
  /**
167
175
  * Returns if the parent should conditionally clear.
168
176
  *
@@ -430,6 +430,24 @@ class Component extends Element_1.default {
430
430
  var _a;
431
431
  return ((_a = this.root) === null || _a === void 0 ? void 0 : _a.childComponentsMap) || {};
432
432
  }
433
+ /**
434
+ * Walks this component's root chain, invoking `fn` with each ancestor root's
435
+ * `childComponentsMap`. Component registration is propagated up the wizard /
436
+ * nested-form chain at create time, so any code that mutates a registration
437
+ * (creation, removal, path-driven re-key) must update every map in the chain.
438
+ * @param {(map: object) => void} fn - Called once per root that exposes a `childComponentsMap`.
439
+ */
440
+ eachRootChildComponentsMap(fn) {
441
+ let currentRoot = this.root;
442
+ let prevRootId = null;
443
+ while (currentRoot && currentRoot.id !== prevRootId) {
444
+ if (currentRoot.childComponentsMap) {
445
+ fn(currentRoot.childComponentsMap);
446
+ }
447
+ prevRootId = currentRoot.id;
448
+ currentRoot = currentRoot.root;
449
+ }
450
+ }
433
451
  /**
434
452
  * Returns if the parent should conditionally clear.
435
453
  *
@@ -2272,29 +2290,24 @@ class Component extends Element_1.default {
2272
2290
  * @returns {void}
2273
2291
  */
2274
2292
  setErrorClasses(elements, dirty, hasErrors, hasMessages, element = this.element) {
2275
- this.clearErrorClasses();
2276
- elements.forEach((element) => {
2277
- this.setElementInvalid(this.performInputMapping(element), hasErrors);
2293
+ var _a;
2294
+ elements.forEach((el) => {
2295
+ this.setElementInvalid(this.performInputMapping(el), hasErrors);
2278
2296
  });
2279
2297
  this.setInputWidgetErrorClasses(elements, hasErrors);
2280
2298
  // do not set error classes for hidden components
2281
2299
  if (!this.visible) {
2300
+ this.clearErrorClasses(element);
2282
2301
  return;
2283
2302
  }
2284
- if (hasErrors) {
2285
- // Add error classes
2286
- elements.forEach((input) => {
2287
- this.setElementInvalid(this.performInputMapping(input), true);
2288
- });
2289
- if (dirty && this.options.highlightErrors) {
2290
- this.addClass(element, this.options.componentErrorClass);
2291
- }
2292
- else {
2293
- this.addClass(element, 'has-error');
2294
- }
2295
- }
2296
- if (hasMessages) {
2297
- this.addClass(element, 'has-message');
2303
+ const wantHighlight = hasErrors && !!dirty && !!this.options.highlightErrors;
2304
+ const wantHasError = hasErrors && !wantHighlight;
2305
+ this.toggleClass(element, this.options.componentErrorClass, wantHighlight);
2306
+ this.toggleClass(element, 'has-error', wantHasError);
2307
+ this.toggleClass(element, 'has-message', hasMessages);
2308
+ // Preserve previous clearErrorClasses() behavior: drop the 'alert alert-danger' pair if left over.
2309
+ if ((_a = element === null || element === void 0 ? void 0 : element.classList) === null || _a === void 0 ? void 0 : _a.contains('alert-danger')) {
2310
+ this.removeClass(element, 'alert alert-danger');
2298
2311
  }
2299
2312
  }
2300
2313
  /**
@@ -3189,7 +3202,7 @@ class Component extends Element_1.default {
3189
3202
  if (flags.silentCheck) {
3190
3203
  return [];
3191
3204
  }
3192
- let isDirty = flags.dirty === false ? false : this.dirty || flags.dirty;
3205
+ let isDirty = flags.dirty || this.dirty;
3193
3206
  if (this.options.alwaysDirty) {
3194
3207
  isDirty = true;
3195
3208
  }
@@ -557,16 +557,14 @@ class NestedComponent extends Field_1.default {
557
557
  * @param {boolean} [all] - If set to TRUE will cascade remove all components.
558
558
  */
559
559
  removeComponent(component, components, all = false) {
560
- var _a, _b;
561
560
  components = components || this.components;
562
561
  component.destroy(all);
563
562
  lodash_1.default.remove(components, { id: component.id });
564
- if (this.componentsMap[component.path]) {
565
- delete this.componentsMap[component.path];
566
- }
567
- if ((_a = this.root) === null || _a === void 0 ? void 0 : _a.componentsMap[component.path]) {
568
- (_b = this.root) === null || _b === void 0 ? true : delete _b.componentsMap[component.path];
569
- }
563
+ component.eachRootChildComponentsMap((map) => {
564
+ if (map[component.path]) {
565
+ delete map[component.path];
566
+ }
567
+ });
570
568
  }
571
569
  /**
572
570
  * Removes a component provided the API key of that component.
@@ -456,8 +456,16 @@ class DataGridComponent extends NestedArrayComponent_1.default {
456
456
  updateComponentsRowIndex(components, rowIndex) {
457
457
  components.forEach((component, colIndex) => {
458
458
  var _a;
459
- if (this.componentsMap[component.paths.dataPath]) {
460
- delete this.componentsMap[component.paths.dataPath];
459
+ // The rowIndex setter cascades into descendants and regenerates their
460
+ // paths, but does not re-key them in componentsMap. Collect the slot
461
+ // and every descendant up front so we can re-key them after paths
462
+ // regenerate. Required for nested-form / sub-wizard scenarios where
463
+ // the outer wizard validates against its own componentsMap copy.
464
+ const entries = [{ instance: component, oldPath: component.paths.dataPath }];
465
+ if (typeof component.everyComponent === 'function') {
466
+ component.everyComponent((descendant) => {
467
+ entries.push({ instance: descendant, oldPath: descendant.paths.dataPath });
468
+ });
461
469
  }
462
470
  if ((_a = component.options) === null || _a === void 0 ? void 0 : _a.name) {
463
471
  const newName = `[${this.key}][${rowIndex}]`;
@@ -465,7 +473,14 @@ class DataGridComponent extends NestedArrayComponent_1.default {
465
473
  }
466
474
  component.rowIndex = rowIndex;
467
475
  component.row = `${rowIndex}-${colIndex}`;
468
- this.componentsMap[component.paths.dataPath] = component;
476
+ entries.forEach(({ instance, oldPath }) => {
477
+ instance.eachRootChildComponentsMap((map) => {
478
+ if (map[oldPath] === instance) {
479
+ delete map[oldPath];
480
+ }
481
+ map[instance.paths.dataPath] = instance;
482
+ });
483
+ });
469
484
  });
470
485
  }
471
486
  updateRowsComponents(rowIndex) {
@@ -537,8 +552,9 @@ class DataGridComponent extends NestedArrayComponent_1.default {
537
552
  options.rowIndex = rowIndex;
538
553
  options.onChange = (flags, changed, modified) => {
539
554
  var _a, _b, _c, _d, _e;
540
- if (changed.component.type === 'form') {
541
- const formComp = (0, utils_1.getComponent)(this.component.components, changed.component.key);
555
+ const changedComponent = changed.component;
556
+ if ((changedComponent === null || changedComponent === void 0 ? void 0 : changedComponent.type) === 'form' && (changedComponent === null || changedComponent === void 0 ? void 0 : changedComponent.key)) {
557
+ const formComp = (0, utils_1.getComponent)(this.component.components, changedComponent.key);
542
558
  lodash_1.default.set(formComp, 'components', changed.component.components);
543
559
  }
544
560
  // If we're in a nested form we need to ensure our changes are triggered upstream
@@ -814,7 +814,7 @@ class EditGridComponent extends NestedArrayComponent_1.default {
814
814
  }
815
815
  }
816
816
  saveRow(rowIndex, modified) {
817
- var _a, _b, _c;
817
+ var _a, _b, _c, _d;
818
818
  const editRow = this.editRows[rowIndex];
819
819
  if (this.options.readOnly) {
820
820
  return;
@@ -869,7 +869,7 @@ class EditGridComponent extends NestedArrayComponent_1.default {
869
869
  if (this.component.rowDrafts) {
870
870
  editRow.components.forEach((comp) => comp.setPristine(this.pristine));
871
871
  }
872
- this.checkValidity(null, true);
872
+ this.checkValidity(null, !this.component.rowDrafts || ((_d = this.root) === null || _d === void 0 ? void 0 : _d.submitted));
873
873
  this.redraw();
874
874
  if (editRow.alerts) {
875
875
  editRow.alerts = false;
@@ -946,16 +946,17 @@ class FileComponent extends Field_1.default {
946
946
  }
947
947
  uploadFile(fileToSync) {
948
948
  return __awaiter(this, void 0, void 0, function* () {
949
- return yield this.fileService.uploadFile(fileToSync.storage, fileToSync.file, fileToSync.name, fileToSync.dir,
949
+ const filePromise = this.fileService.uploadFile(fileToSync.storage, fileToSync.file, fileToSync.name, fileToSync.dir,
950
950
  // Progress callback
951
951
  this.updateProgress.bind(this, fileToSync), fileToSync.url, fileToSync.options, fileToSync.fileKey, fileToSync.groupPermissions, fileToSync.groupResourceId, () => {
952
- this.emit('fileUploadingStart');
952
+ this.emit('fileUploadingStart', filePromise);
953
953
  },
954
954
  // Abort upload callback
955
955
  (abort) => this.abortUploads.push({
956
956
  id: fileToSync.id,
957
957
  abort,
958
958
  }), this.getMultipartOptions(fileToSync));
959
+ return yield filePromise;
959
960
  });
960
961
  }
961
962
  upload() {
@@ -977,7 +978,7 @@ class FileComponent extends Field_1.default {
977
978
  fileToSync.message = this.t('Succefully uploaded');
978
979
  fileInfo.originalName = fileToSync.originalName;
979
980
  fileInfo.hash = fileToSync.hash;
980
- this.emit('fileUploadingEnd');
981
+ this.emit('fileUploadingEnd', Promise.resolve(fileInfo));
981
982
  }
982
983
  catch (response) {
983
984
  fileToSync.status = 'error';
@@ -988,8 +989,8 @@ class FileComponent extends Field_1.default {
988
989
  : response.type === 'abort'
989
990
  ? this.t('Request was aborted')
990
991
  : response.toString();
991
- this.emit('fileUploadingEnd');
992
- this.emit('fileUploadError', {
992
+ this.emit('fileUploadingEnd', Promise.reject(response));
993
+ this.emit(lodash_1.default.get(response, 'type') === 'abort' ? 'fileUploadCanceled' : 'fileUploadError', {
993
994
  fileToSync,
994
995
  response,
995
996
  });
@@ -42,6 +42,7 @@ export default class FormComponent extends Component {
42
42
  everyComponent(...args: any[]): any;
43
43
  setSubFormDisabled(subForm: any): void;
44
44
  updateSubWizards(subForm: any): void;
45
+ updateTopLevelComponentsMap(): void;
45
46
  setComponentsMap(): void;
46
47
  /**
47
48
  * Create a subform instance.
@@ -400,13 +400,22 @@ class FormComponent extends Component_1.default {
400
400
  this.emit('subWizardsUpdated', subForm);
401
401
  }
402
402
  }
403
+ updateTopLevelComponentsMap() {
404
+ let prevRootId = null;
405
+ let currentRoot = this.root;
406
+ const subFormComponentMap = this.subForm.componentsMap;
407
+ // update components map for all top forms
408
+ while (currentRoot && prevRootId !== currentRoot.id) {
409
+ lodash_1.default.assign(currentRoot.componentsMap, subFormComponentMap);
410
+ prevRootId = currentRoot.id;
411
+ currentRoot = currentRoot.root;
412
+ }
413
+ }
403
414
  setComponentsMap() {
404
415
  if (!this.subForm) {
405
416
  return;
406
417
  }
407
- const componentsMap = this.componentsMap;
408
- const formComponentsMap = this.subForm.componentsMap;
409
- lodash_1.default.assign(componentsMap, formComponentsMap);
418
+ this.updateTopLevelComponentsMap();
410
419
  }
411
420
  /**
412
421
  * Create a subform instance.
@@ -431,13 +440,13 @@ class FormComponent extends Component_1.default {
431
440
  // Render the form.
432
441
  return new Form_1.default(form, this.getSubOptions()).ready
433
442
  .then((instance) => {
434
- var _a, _b;
443
+ var _a;
435
444
  this.subForm = instance;
436
445
  this.subForm.currentForm = this;
437
446
  this.subForm.parentVisible = this.visible;
438
447
  this.setComponentsMap();
439
- this.component.components = (_a = this.subForm._form) === null || _a === void 0 ? void 0 : _a.components;
440
- this.component.display = (_b = this.subForm._form) === null || _b === void 0 ? void 0 : _b.display;
448
+ this.component.components = this.subForm.components.map((comp) => comp.component);
449
+ this.component.display = (_a = this.subForm._form) === null || _a === void 0 ? void 0 : _a.display;
441
450
  this.subForm.on('change', () => {
442
451
  var _a;
443
452
  if (this.subForm && !this.shouldConditionallyClear()) {
@@ -775,7 +784,9 @@ class FormComponent extends Component_1.default {
775
784
  }
776
785
  this.updateSubFormVisibility();
777
786
  this.clearOnHide();
778
- isNestedWizard ? this.rebuild() : this.redraw();
787
+ if (!isNestedWizard) {
788
+ this.redraw();
789
+ }
779
790
  }
780
791
  if (!value && isNestedWizard) {
781
792
  (_a = this.root) === null || _a === void 0 ? void 0 : _a.redraw();
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "type": "commonjs",
3
- "version": "5.3.3"
3
+ "version": "5.3.5"
4
4
  }
@@ -26,8 +26,8 @@ export const getBestMatch: typeof Utils.getBestMatch;
26
26
  export const getComponentFromPath: typeof Utils.getComponentFromPath;
27
27
  export const getComponentValue: typeof Utils.getComponentValue;
28
28
  export const findComponents: typeof Utils.findComponents;
29
- export const eachComponentDataAsync: (components: import("@formio/core").Component[], data: import("@formio/core").DataObject, fn: import("@formio/core").EachComponentDataAsyncCallback, includeAll?: boolean | undefined, local?: boolean | undefined, parent?: import("@formio/core").Component | undefined, parentPaths?: import("@formio/core").ComponentPaths | undefined, noScopeReset?: boolean | undefined, afterFn?: import("@formio/core").EachComponentDataAsyncCallback | undefined) => Promise<void>;
30
- export const eachComponentData: (components: import("@formio/core").Component[], data: import("@formio/core").DataObject, fn: import("@formio/core").EachComponentDataCallback, includeAll?: boolean | undefined, local?: boolean | undefined, parent?: import("@formio/core").Component | undefined, parentPaths?: import("@formio/core").ComponentPaths | undefined, noScopeReset?: boolean | undefined, afterFn?: import("@formio/core").EachComponentDataCallback | undefined) => void;
29
+ export const eachComponentDataAsync: (components: import("@formio/core").Component[], data: import("@formio/core").DataObject, fn: import("@formio/core").EachComponentDataAsyncCallback, includeAll?: boolean | undefined, local?: boolean | undefined, parent?: import("@formio/core").Component | undefined, parentPaths?: import("@formio/core").ComponentPaths | undefined, noScopeReset?: boolean | undefined, afterFn?: import("@formio/core").EachComponentDataAsyncCallback | undefined, localRoot?: import("@formio/core").LocalRoot | undefined) => Promise<void>;
30
+ export const eachComponentData: (components: import("@formio/core").Component[], data: import("@formio/core").DataObject, fn: import("@formio/core").EachComponentDataCallback, includeAll?: boolean | undefined, local?: boolean | undefined, parent?: import("@formio/core").Component | undefined, parentPaths?: import("@formio/core").ComponentPaths | undefined, noScopeReset?: boolean | undefined, afterFn?: import("@formio/core").EachComponentDataCallback | undefined, localRoot?: import("@formio/core").LocalRoot | undefined) => void;
31
31
  export const getComponentKey: typeof Utils.getComponentKey;
32
32
  export const getContextualRowPath: any;
33
33
  export const getContextualRowData: typeof Utils.getContextualRowData;
@@ -37,8 +37,8 @@ declare const FormioUtils: {
37
37
  getComponentFromPath: typeof import("@formio/core/lib/utils/formUtil").getComponentFromPath;
38
38
  getComponentValue: typeof import("@formio/core/lib/utils/formUtil").getComponentValue;
39
39
  findComponents: typeof import("@formio/core/lib/utils/formUtil").findComponents;
40
- eachComponentDataAsync: (components: import("@formio/core").Component[], data: import("@formio/core").DataObject, fn: import("@formio/core").EachComponentDataAsyncCallback, includeAll?: boolean | undefined, local?: boolean | undefined, parent?: import("@formio/core").Component | undefined, parentPaths?: import("@formio/core").ComponentPaths | undefined, noScopeReset?: boolean | undefined, afterFn?: import("@formio/core").EachComponentDataAsyncCallback | undefined) => Promise<void>;
41
- eachComponentData: (components: import("@formio/core").Component[], data: import("@formio/core").DataObject, fn: import("@formio/core").EachComponentDataCallback, includeAll?: boolean | undefined, local?: boolean | undefined, parent?: import("@formio/core").Component | undefined, parentPaths?: import("@formio/core").ComponentPaths | undefined, noScopeReset?: boolean | undefined, afterFn?: import("@formio/core").EachComponentDataCallback | undefined) => void;
40
+ eachComponentDataAsync: (components: import("@formio/core").Component[], data: import("@formio/core").DataObject, fn: import("@formio/core").EachComponentDataAsyncCallback, includeAll?: boolean | undefined, local?: boolean | undefined, parent?: import("@formio/core").Component | undefined, parentPaths?: import("@formio/core").ComponentPaths | undefined, noScopeReset?: boolean | undefined, afterFn?: import("@formio/core").EachComponentDataAsyncCallback | undefined, localRoot?: import("@formio/core").LocalRoot | undefined) => Promise<void>;
41
+ eachComponentData: (components: import("@formio/core").Component[], data: import("@formio/core").DataObject, fn: import("@formio/core").EachComponentDataCallback, includeAll?: boolean | undefined, local?: boolean | undefined, parent?: import("@formio/core").Component | undefined, parentPaths?: import("@formio/core").ComponentPaths | undefined, noScopeReset?: boolean | undefined, afterFn?: import("@formio/core").EachComponentDataCallback | undefined, localRoot?: import("@formio/core").LocalRoot | undefined) => void;
42
42
  getComponentKey: typeof import("@formio/core/lib/utils/formUtil").getComponentKey;
43
43
  getContextualRowPath: any;
44
44
  getContextualRowData: typeof import("@formio/core/lib/utils/formUtil").getContextualRowData;
@@ -210,6 +210,17 @@ export default class Element {
210
210
  * @returns {this} - The instance of the element.
211
211
  */
212
212
  removeClass(element: HTMLElement, className: string): this;
213
+ /**
214
+ * Idempotently add or remove a class on a DOM element based on a boolean.
215
+ * Skips the mutation when the element is already in the desired state, so
216
+ * callers can safely invoke it on every change without triggering redundant
217
+ * CSS transitions or attribute writes.
218
+ * @param {HTMLElement} element - The DOM element to toggle the class on.
219
+ * @param {string} className - The class name to add or remove.
220
+ * @param {boolean} want - TRUE to ensure the class is present, FALSE to ensure it is absent.
221
+ * @returns {this} - The instance of the element.
222
+ */
223
+ toggleClass(element: HTMLElement, className: string, want: boolean): this;
213
224
  /**
214
225
  * Empty's an HTML DOM element.
215
226
  * @param {HTMLElement} element - The element you wish to empty.
@@ -477,6 +477,29 @@ export default class Element {
477
477
  }
478
478
  return this;
479
479
  }
480
+ /**
481
+ * Idempotently add or remove a class on a DOM element based on a boolean.
482
+ * Skips the mutation when the element is already in the desired state, so
483
+ * callers can safely invoke it on every change without triggering redundant
484
+ * CSS transitions or attribute writes.
485
+ * @param {HTMLElement} element - The DOM element to toggle the class on.
486
+ * @param {string} className - The class name to add or remove.
487
+ * @param {boolean} want - TRUE to ensure the class is present, FALSE to ensure it is absent.
488
+ * @returns {this} - The instance of the element.
489
+ */
490
+ toggleClass(element, className, want) {
491
+ if (!element || !className || !(element instanceof HTMLElement)) {
492
+ return this;
493
+ }
494
+ const has = !!element.classList?.contains(className);
495
+ if (want && !has) {
496
+ this.addClass(element, className);
497
+ }
498
+ else if (!want && has) {
499
+ this.removeClass(element, className);
500
+ }
501
+ return this;
502
+ }
480
503
  /**
481
504
  * Empty's an HTML DOM element.
482
505
  * @param {HTMLElement} element - The element you wish to empty.
package/lib/mjs/Embed.js CHANGED
@@ -14,7 +14,7 @@ export class Formio {
14
14
  Formio._formioReady = ready;
15
15
  Formio._formioReadyReject = reject;
16
16
  });
17
- static version = '5.3.3';
17
+ static version = '5.3.5';
18
18
  static setLicense(license, norecurse = false) {
19
19
  Formio.license = license;
20
20
  if (!norecurse && Formio.FormioClass) {
package/lib/mjs/Formio.js CHANGED
@@ -4,7 +4,7 @@ import CDN from './CDN';
4
4
  import Providers from './providers';
5
5
  FormioCore.cdn = new CDN();
6
6
  FormioCore.Providers = Providers;
7
- FormioCore.version = '5.3.3';
7
+ FormioCore.version = '5.3.5';
8
8
  CDN.defaultCDN = FormioCore.version.includes('rc')
9
9
  ? 'https://cdn.test-form.io'
10
10
  : 'https://cdn.form.io';