@formio/js 5.2.4 → 5.2.6

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 (48) hide show
  1. package/dist/formio.builder.css +8 -0
  2. package/dist/formio.builder.min.css +1 -1
  3. package/dist/formio.embed.js +1 -1
  4. package/dist/formio.embed.min.js +1 -1
  5. package/dist/formio.embed.min.js.LICENSE.txt +1 -1
  6. package/dist/formio.form.css +8 -0
  7. package/dist/formio.form.js +10 -10
  8. package/dist/formio.form.min.css +1 -1
  9. package/dist/formio.form.min.js +1 -1
  10. package/dist/formio.form.min.js.LICENSE.txt +1 -1
  11. package/dist/formio.full.css +8 -0
  12. package/dist/formio.full.js +10 -10
  13. package/dist/formio.full.min.css +1 -1
  14. package/dist/formio.full.min.js +1 -1
  15. package/dist/formio.full.min.js.LICENSE.txt +1 -1
  16. package/dist/formio.js +3 -3
  17. package/dist/formio.min.js +1 -1
  18. package/dist/formio.min.js.LICENSE.txt +1 -1
  19. package/dist/formio.utils.js +2 -2
  20. package/dist/formio.utils.min.js +1 -1
  21. package/dist/formio.utils.min.js.LICENSE.txt +1 -1
  22. package/lib/cjs/Embed.js +1 -1
  23. package/lib/cjs/Formio.js +1 -1
  24. package/lib/cjs/components/_classes/component/Component.js +4 -1
  25. package/lib/cjs/components/_classes/nested/NestedComponent.d.ts +1 -1
  26. package/lib/cjs/components/_classes/nested/NestedComponent.js +43 -31
  27. package/lib/cjs/components/address/Address.d.ts +0 -1
  28. package/lib/cjs/components/datagrid/DataGrid.js +5 -1
  29. package/lib/cjs/components/day/Day.js +1 -1
  30. package/lib/cjs/components/editgrid/EditGrid.js +2 -0
  31. package/lib/cjs/package.json +1 -1
  32. package/lib/cjs/utils/index.d.ts +1 -0
  33. package/lib/cjs/utils/utils.d.ts +5 -0
  34. package/lib/cjs/utils/utils.js +18 -1
  35. package/lib/mjs/Embed.js +1 -1
  36. package/lib/mjs/Formio.js +1 -1
  37. package/lib/mjs/components/_classes/component/Component.js +4 -1
  38. package/lib/mjs/components/_classes/nested/NestedComponent.d.ts +1 -1
  39. package/lib/mjs/components/_classes/nested/NestedComponent.js +5 -9
  40. package/lib/mjs/components/address/Address.d.ts +0 -1
  41. package/lib/mjs/components/datagrid/DataGrid.js +6 -2
  42. package/lib/mjs/components/day/Day.js +1 -1
  43. package/lib/mjs/components/editgrid/EditGrid.js +3 -1
  44. package/lib/mjs/package.json +1 -1
  45. package/lib/mjs/utils/index.d.ts +1 -0
  46. package/lib/mjs/utils/utils.d.ts +5 -0
  47. package/lib/mjs/utils/utils.js +16 -0
  48. package/package.json +4 -3
@@ -22,7 +22,7 @@
22
22
 
23
23
  /*! @license DOMPurify 3.2.6 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.2.6/LICENSE */
24
24
 
25
- /*! formiojs v5.2.4 | https://unpkg.com/formiojs@5.2.4/LICENSE.txt */
25
+ /*! formiojs v5.2.6 | https://unpkg.com/formiojs@5.2.6/LICENSE.txt */
26
26
 
27
27
  /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */
28
28
 
package/lib/cjs/Embed.js CHANGED
@@ -419,7 +419,7 @@ Formio.formioReady = new Promise((ready, reject) => {
419
419
  _a._formioReady = ready;
420
420
  _a._formioReadyReject = reject;
421
421
  });
422
- Formio.version = '5.2.4';
422
+ Formio.version = '5.2.6';
423
423
  // Create a report.
424
424
  Formio.Report = {
425
425
  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.2.4';
14
+ sdk_1.Formio.version = '5.2.6';
15
15
  CDN_1.default.defaultCDN = sdk_1.Formio.version.includes('rc') ? 'https://cdn.test-form.io' : 'https://cdn.form.io';
16
16
  const isNil = (val) => val === null || val === undefined;
17
17
  sdk_1.Formio.prototype.uploadFile = function (storage, file, fileName, dir, progressCallback, url, options, fileKey, groupPermissions, groupId, uploadStartCallback, abortCallback, multipartOptions) {
@@ -2216,7 +2216,7 @@ class Component extends Element_1.default {
2216
2216
  setErrorClasses(elements, dirty, hasErrors, hasMessages, element = this.element) {
2217
2217
  this.clearErrorClasses();
2218
2218
  elements.forEach((element) => {
2219
- this.setElementInvalid(this.performInputMapping(element), false);
2219
+ this.setElementInvalid(this.performInputMapping(element), hasErrors);
2220
2220
  });
2221
2221
  this.setInputWidgetErrorClasses(elements, hasErrors);
2222
2222
  // do not set error classes for hidden components
@@ -2254,6 +2254,9 @@ class Component extends Element_1.default {
2254
2254
  else {
2255
2255
  this.removeClass(element, 'is-invalid');
2256
2256
  }
2257
+ if (this.type === 'radio' && !invalid) {
2258
+ return;
2259
+ }
2257
2260
  element.setAttribute('aria-invalid', invalid ? 'true' : 'false');
2258
2261
  }
2259
2262
  /**
@@ -149,7 +149,7 @@ export default class NestedComponent extends Field {
149
149
  beforeFocus(): void;
150
150
  render(children: any): string;
151
151
  renderComponents(components: any): any;
152
- attach(element: any): Promise<[void, void]>;
152
+ attach(element: any): Promise<void>;
153
153
  /**
154
154
  * Attach the logic to the components.
155
155
  * @param {import('@formio/core').Component[]} components - The components to attach logic to.
@@ -1,4 +1,13 @@
1
1
  'use strict';
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
2
11
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
12
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
13
  };
@@ -58,11 +67,12 @@ class NestedComponent extends Field_1.default {
58
67
  * @returns {void}
59
68
  */
60
69
  collapse(value) {
61
- const promise = this.redraw();
62
- if (!value) {
63
- this.checkValidity(this.data, !this.pristine);
64
- }
65
- return promise;
70
+ return __awaiter(this, void 0, void 0, function* () {
71
+ yield this.redraw();
72
+ if (!value) {
73
+ this.checkValidity(this.data, !this.pristine);
74
+ }
75
+ });
66
76
  }
67
77
  /**
68
78
  * Set collapsed state.
@@ -490,35 +500,37 @@ class NestedComponent extends Field_1.default {
490
500
  });
491
501
  }
492
502
  attach(element) {
493
- const superPromise = super.attach(element);
494
- this.loadRefs(element, {
495
- header: 'single',
496
- collapsed: this.collapsed,
497
- [this.nestedKey]: 'single',
498
- messageContainer: 'single-scope',
503
+ const _super = Object.create(null, {
504
+ attach: { get: () => super.attach }
499
505
  });
500
- let childPromise = Promise.resolve();
501
- if (this.refs[this.nestedKey]) {
502
- childPromise = this.attachComponents(this.refs[this.nestedKey]);
503
- }
504
- if (!this.visible) {
505
- this.attachComponentsLogic();
506
- }
507
- if (this.component.collapsible && this.refs.header) {
508
- this.addEventListener(this.refs.header, 'click', () => {
509
- this.collapsed = !this.collapsed;
506
+ return __awaiter(this, void 0, void 0, function* () {
507
+ yield _super.attach.call(this, element);
508
+ this.loadRefs(element, {
509
+ header: 'single',
510
+ collapsed: this.collapsed,
511
+ [this.nestedKey]: 'single',
512
+ messageContainer: 'single-scope',
510
513
  });
511
- this.addEventListener(this.refs.header, 'keydown', (e) => {
512
- if (e.keyCode === 13 || e.keyCode === 32) {
513
- e.preventDefault();
514
+ let childPromise = Promise.resolve();
515
+ if (this.refs[this.nestedKey]) {
516
+ childPromise = this.attachComponents(this.refs[this.nestedKey]);
517
+ }
518
+ if (!this.visible) {
519
+ this.attachComponentsLogic();
520
+ }
521
+ if (this.component.collapsible && this.refs.header) {
522
+ this.addEventListener(this.refs.header, 'click', () => {
514
523
  this.collapsed = !this.collapsed;
515
- }
516
- });
517
- }
518
- return Promise.all([
519
- superPromise,
520
- childPromise,
521
- ]);
524
+ });
525
+ this.addEventListener(this.refs.header, 'keydown', (e) => {
526
+ if (e.keyCode === 13 || e.keyCode === 32) {
527
+ e.preventDefault();
528
+ this.collapsed = !this.collapsed;
529
+ }
530
+ });
531
+ }
532
+ return yield childPromise;
533
+ });
522
534
  }
523
535
  /**
524
536
  * Attach the logic to the components.
@@ -72,7 +72,6 @@ export default class AddressComponent extends ContainerComponent {
72
72
  render(): string;
73
73
  onSelectAddress(address: any, element: any, index: any): void;
74
74
  addRow(): void;
75
- attach(element: any): Promise<void>;
76
75
  addChildComponent(component: any): void;
77
76
  clearAddress(element: any, index: any): void;
78
77
  getDisplayValue(value?: any): any;
@@ -396,6 +396,7 @@ class DataGridComponent extends NestedArrayComponent_1.default {
396
396
  component: this.component,
397
397
  row
398
398
  });
399
+ (0, utils_1.screenReaderSpeech)('Row has been added');
399
400
  this.checkConditions();
400
401
  (_a = this.triggerChange) === null || _a === void 0 ? void 0 : _a.call(this, { modified: true });
401
402
  this.redraw().then(() => {
@@ -423,7 +424,10 @@ class DataGridComponent extends NestedArrayComponent_1.default {
423
424
  const flags = { isReordered: !makeEmpty, resetValue: makeEmpty };
424
425
  this.splice(index, flags);
425
426
  this.emit('dataGridDeleteRow', { index });
426
- const [row] = this.rows.splice(index, 1);
427
+ if (this.rows.length > 1) {
428
+ (0, utils_1.screenReaderSpeech)('Row has been deleted');
429
+ }
430
+ const [row,] = this.rows.splice(index, 1);
427
431
  this.removeSubmissionMetadataRow(index);
428
432
  this.removeRowComponents(row);
429
433
  this.updateRowsComponents(index);
@@ -53,7 +53,7 @@ class DayComponent extends Field_1.default {
53
53
  return (0, utils_1.getComponentSavedTypes)(schema) || [utils_1.componentValueTypes.string];
54
54
  }
55
55
  constructor(component, options, data) {
56
- if (!options.inFormBuilder && !options.building) {
56
+ if (options && !options.inFormBuilder && !options.building) {
57
57
  if (component.maxDate && component.maxDate.indexOf('moment(') === -1) {
58
58
  component.maxDate = (0, moment_1.default)(component.maxDate, 'YYYY-MM-DD').toISOString();
59
59
  }
@@ -807,6 +807,7 @@ class EditGridComponent extends NestedArrayComponent_1.default {
807
807
  return false;
808
808
  }
809
809
  }
810
+ (0, utils_1.screenReaderSpeech)('Row has been saved');
810
811
  if (this.saveEditMode) {
811
812
  const dataValue = this.dataValue;
812
813
  if ((_b = (_a = this.root) === null || _a === void 0 ? void 0 : _a.focusedComponent) === null || _b === void 0 ? void 0 : _b.component.typeChangeEnabled) {
@@ -894,6 +895,7 @@ class EditGridComponent extends NestedArrayComponent_1.default {
894
895
  this.emit('editGridDeleteRow', {
895
896
  index: rowIndex
896
897
  });
898
+ (0, utils_1.screenReaderSpeech)('Row has been deleted');
897
899
  this.editRows.splice(rowIndex, 1);
898
900
  this.openWhenEmpty();
899
901
  this.updateRowsComponents(rowIndex);
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "type": "commonjs",
3
- "version": "5.2.4"
3
+ "version": "5.2.6"
4
4
  }
@@ -149,6 +149,7 @@ declare const FormioUtils: {
149
149
  isPromise(value: any): boolean;
150
150
  getFocusableElements(element: HTMLElement): NodeList<HTMLElement>;
151
151
  getComponentSavedTypes(fullSchema: import("@formio/core").Component): string[] | null;
152
+ screenReaderSpeech(text: string): void;
152
153
  firstNonNil: any;
153
154
  componentValueTypes: {
154
155
  number: string;
@@ -490,6 +490,11 @@ export function getFocusableElements(element: HTMLElement): NodeList<HTMLElement
490
490
  * @returns {Array<string>|null} - The saved types for the component
491
491
  */
492
492
  export function getComponentSavedTypes(fullSchema: import('@formio/core').Component): Array<string> | null;
493
+ /**
494
+ * Outputs text to screen reader
495
+ * @param {string} text The text to output to screen readers
496
+ */
497
+ export function screenReaderSpeech(text: string): void;
493
498
  /**
494
499
  * Map values through unfold and return first non-nil value.
495
500
  * @param {Array<T>} collection - The collection to map through unfold.;
@@ -4,7 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.getContextComponents = exports.observeOverload = exports.withSwitch = exports.firstNonNil = exports.unfold = exports.bootstrapVersion = exports.uniqueKey = exports.iterateKey = exports.delay = exports.fieldData = exports.getCurrencyAffixes = exports.getNumberDecimalLimit = exports.getNumberSeparators = exports.matchInputMask = exports.unmaskValue = exports.getInputMask = exports.convertFormatToMask = exports.convertFormatToMoment = exports.convertFormatToFlatpickr = exports.getLocaleDateFormatInfo = exports.formatOffset = exports.formatDate = exports.momentDate = exports.loadZones = exports.shouldLoadZones = exports.zonesLoaded = exports.offsetDate = exports.currentTimezone = exports.isValidDate = exports.getDateSetting = exports.guid = exports.uniqueName = exports.convertStringToHTMLElement = exports.unescapeHTML = exports.removeHTML = exports.setActionProperty = exports.checkTrigger = exports.checkCondition = exports.checkJsonConditional = exports.checkCustomConditional = exports.getComponentActualValue = exports.checkSimpleConditional = exports.checkCalculated = exports.isMongoId = exports.boolValue = exports.getScriptPlugin = exports.getElementRect = exports.getPropertyValue = exports.getRandomComponentId = exports.evaluate = void 0;
7
- exports.interpolateErrors = exports.getComponentSavedTypes = exports.componentValueTypes = exports.getFocusableElements = exports.isPromise = exports.getDataParentComponent = exports.getComponentPath = exports.getComponentPathWithoutIndicies = exports.getBrowserInfo = exports.getIEBrowserVersion = exports.round = exports.getStringFromComponentPath = exports.isChildOf = exports.getArrayFromComponentPath = exports.isInputComponent = exports.fastCloneDeep = exports.sanitize = exports.translateHTMLTemplate = exports.getContextButtons = void 0;
7
+ exports.screenReaderSpeech = exports.interpolateErrors = exports.getComponentSavedTypes = exports.componentValueTypes = exports.getFocusableElements = exports.isPromise = exports.getDataParentComponent = exports.getComponentPath = exports.getComponentPathWithoutIndicies = exports.getBrowserInfo = exports.getIEBrowserVersion = exports.round = exports.getStringFromComponentPath = exports.isChildOf = exports.getArrayFromComponentPath = exports.isInputComponent = exports.fastCloneDeep = exports.sanitize = exports.translateHTMLTemplate = exports.getContextButtons = void 0;
8
8
  /* global jQuery */
9
9
  const lodash_1 = __importDefault(require("lodash"));
10
10
  const moment_timezone_1 = __importDefault(require("moment-timezone/moment-timezone"));
@@ -1608,3 +1608,20 @@ const interpolateErrors = (component, errors, interpolateFn) => {
1608
1608
  });
1609
1609
  };
1610
1610
  exports.interpolateErrors = interpolateErrors;
1611
+ /**
1612
+ * Outputs text to screen reader
1613
+ * @param {string} text The text to output to screen readers
1614
+ */
1615
+ function screenReaderSpeech(text) {
1616
+ const ariaSpeechElement = document.createElement('div');
1617
+ ariaSpeechElement.setAttribute("style", "border: 0;clip: rect(0 0 0 0);height: 1px;margin: -1px;overflow: hidden;padding: 0;position: absolute;width: 1px;white-space: nowrap;");
1618
+ document.body.append(ariaSpeechElement);
1619
+ ariaSpeechElement.ariaLive = 'assertive';
1620
+ setTimeout(() => {
1621
+ ariaSpeechElement.textContent = text;
1622
+ setTimeout(() => {
1623
+ ariaSpeechElement.remove();
1624
+ }, 1000);
1625
+ }, 100);
1626
+ }
1627
+ exports.screenReaderSpeech = screenReaderSpeech;
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.2.4';
17
+ static version = '5.2.6';
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.2.4';
7
+ FormioCore.version = '5.2.6';
8
8
  CDN.defaultCDN = FormioCore.version.includes('rc') ? 'https://cdn.test-form.io' : 'https://cdn.form.io';
9
9
  const isNil = (val) => val === null || val === undefined;
10
10
  FormioCore.prototype.uploadFile = function (storage, file, fileName, dir, progressCallback, url, options, fileKey, groupPermissions, groupId, uploadStartCallback, abortCallback, multipartOptions) {
@@ -2211,7 +2211,7 @@ export default class Component extends Element {
2211
2211
  setErrorClasses(elements, dirty, hasErrors, hasMessages, element = this.element) {
2212
2212
  this.clearErrorClasses();
2213
2213
  elements.forEach((element) => {
2214
- this.setElementInvalid(this.performInputMapping(element), false);
2214
+ this.setElementInvalid(this.performInputMapping(element), hasErrors);
2215
2215
  });
2216
2216
  this.setInputWidgetErrorClasses(elements, hasErrors);
2217
2217
  // do not set error classes for hidden components
@@ -2249,6 +2249,9 @@ export default class Component extends Element {
2249
2249
  else {
2250
2250
  this.removeClass(element, 'is-invalid');
2251
2251
  }
2252
+ if (this.type === 'radio' && !invalid) {
2253
+ return;
2254
+ }
2252
2255
  element.setAttribute('aria-invalid', invalid ? 'true' : 'false');
2253
2256
  }
2254
2257
  /**
@@ -149,7 +149,7 @@ export default class NestedComponent extends Field {
149
149
  beforeFocus(): void;
150
150
  render(children: any): string;
151
151
  renderComponents(components: any): any;
152
- attach(element: any): Promise<[void, void]>;
152
+ attach(element: any): Promise<void>;
153
153
  /**
154
154
  * Attach the logic to the components.
155
155
  * @param {import('@formio/core').Component[]} components - The components to attach logic to.
@@ -53,12 +53,11 @@ export default class NestedComponent extends Field {
53
53
  * @param {boolean} value - The collapsed state.
54
54
  * @returns {void}
55
55
  */
56
- collapse(value) {
57
- const promise = this.redraw();
56
+ async collapse(value) {
57
+ await this.redraw();
58
58
  if (!value) {
59
59
  this.checkValidity(this.data, !this.pristine);
60
60
  }
61
- return promise;
62
61
  }
63
62
  /**
64
63
  * Set collapsed state.
@@ -485,8 +484,8 @@ export default class NestedComponent extends Field {
485
484
  components,
486
485
  });
487
486
  }
488
- attach(element) {
489
- const superPromise = super.attach(element);
487
+ async attach(element) {
488
+ await super.attach(element);
490
489
  this.loadRefs(element, {
491
490
  header: 'single',
492
491
  collapsed: this.collapsed,
@@ -511,10 +510,7 @@ export default class NestedComponent extends Field {
511
510
  }
512
511
  });
513
512
  }
514
- return Promise.all([
515
- superPromise,
516
- childPromise,
517
- ]);
513
+ return await childPromise;
518
514
  }
519
515
  /**
520
516
  * Attach the logic to the components.
@@ -72,7 +72,6 @@ export default class AddressComponent extends ContainerComponent {
72
72
  render(): string;
73
73
  onSelectAddress(address: any, element: any, index: any): void;
74
74
  addRow(): void;
75
- attach(element: any): Promise<void>;
76
75
  addChildComponent(component: any): void;
77
76
  clearAddress(element: any, index: any): void;
78
77
  getDisplayValue(value?: any): any;
@@ -1,6 +1,6 @@
1
1
  import _ from 'lodash';
2
2
  import NestedArrayComponent from '../_classes/nestedarray/NestedArrayComponent';
3
- import { fastCloneDeep, getFocusableElements, getComponent } from '../../utils';
3
+ import { fastCloneDeep, getFocusableElements, getComponent, eachComponent, screenReaderSpeech } from '../../utils';
4
4
  import dragula from 'dragula';
5
5
  export default class DataGridComponent extends NestedArrayComponent {
6
6
  static schema(...extend) {
@@ -392,6 +392,7 @@ export default class DataGridComponent extends NestedArrayComponent {
392
392
  component: this.component,
393
393
  row
394
394
  });
395
+ screenReaderSpeech('Row has been added');
395
396
  this.checkConditions();
396
397
  this.triggerChange?.({ modified: true });
397
398
  this.redraw().then(() => {
@@ -418,7 +419,10 @@ export default class DataGridComponent extends NestedArrayComponent {
418
419
  const flags = { isReordered: !makeEmpty, resetValue: makeEmpty };
419
420
  this.splice(index, flags);
420
421
  this.emit('dataGridDeleteRow', { index });
421
- const [row] = this.rows.splice(index, 1);
422
+ if (this.rows.length > 1) {
423
+ screenReaderSpeech('Row has been deleted');
424
+ }
425
+ const [row,] = this.rows.splice(index, 1);
422
426
  this.removeSubmissionMetadataRow(index);
423
427
  this.removeRowComponents(row);
424
428
  this.updateRowsComponents(index);
@@ -53,7 +53,7 @@ export default class DayComponent extends Field {
53
53
  // Empty value used before 9.3.x
54
54
  static oldEmptyValue = '00/00/0000';
55
55
  constructor(component, options, data) {
56
- if (!options.inFormBuilder && !options.building) {
56
+ if (options && !options.inFormBuilder && !options.building) {
57
57
  if (component.maxDate && component.maxDate.indexOf('moment(') === -1) {
58
58
  component.maxDate = moment(component.maxDate, 'YYYY-MM-DD').toISOString();
59
59
  }
@@ -4,7 +4,7 @@ import { editgrid as templates } from '@formio/bootstrap/components';
4
4
  import NestedArrayComponent from '../_classes/nestedarray/NestedArrayComponent';
5
5
  import Component from '../_classes/component/Component';
6
6
  import Alert from '../alert/Alert';
7
- import { fastCloneDeep, Evaluator, getArrayFromComponentPath, eachComponent } from '../../utils';
7
+ import { fastCloneDeep, Evaluator, getArrayFromComponentPath, eachComponent, screenReaderSpeech } from '../../utils';
8
8
  const EditRowState = {
9
9
  New: 'new',
10
10
  Editing: 'editing',
@@ -797,6 +797,7 @@ export default class EditGridComponent extends NestedArrayComponent {
797
797
  return false;
798
798
  }
799
799
  }
800
+ screenReaderSpeech('Row has been saved');
800
801
  if (this.saveEditMode) {
801
802
  const dataValue = this.dataValue;
802
803
  if (this.root?.focusedComponent?.component.typeChangeEnabled) {
@@ -883,6 +884,7 @@ export default class EditGridComponent extends NestedArrayComponent {
883
884
  this.emit('editGridDeleteRow', {
884
885
  index: rowIndex
885
886
  });
887
+ screenReaderSpeech('Row has been deleted');
886
888
  this.editRows.splice(rowIndex, 1);
887
889
  this.openWhenEmpty();
888
890
  this.updateRowsComponents(rowIndex);
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "type": "module",
3
- "version": "5.2.4"
3
+ "version": "5.2.6"
4
4
 
5
5
  }
@@ -149,6 +149,7 @@ declare const FormioUtils: {
149
149
  isPromise(value: any): boolean;
150
150
  getFocusableElements(element: HTMLElement): NodeList<HTMLElement>;
151
151
  getComponentSavedTypes(fullSchema: import("@formio/core").Component): string[] | null;
152
+ screenReaderSpeech(text: string): void;
152
153
  firstNonNil: any;
153
154
  componentValueTypes: {
154
155
  number: string;
@@ -490,6 +490,11 @@ export function getFocusableElements(element: HTMLElement): NodeList<HTMLElement
490
490
  * @returns {Array<string>|null} - The saved types for the component
491
491
  */
492
492
  export function getComponentSavedTypes(fullSchema: import('@formio/core').Component): Array<string> | null;
493
+ /**
494
+ * Outputs text to screen reader
495
+ * @param {string} text The text to output to screen readers
496
+ */
497
+ export function screenReaderSpeech(text: string): void;
493
498
  /**
494
499
  * Map values through unfold and return first non-nil value.
495
500
  * @param {Array<T>} collection - The collection to map through unfold.;
@@ -1532,3 +1532,19 @@ export const interpolateErrors = (component, errors, interpolateFn) => {
1532
1532
  return { ...error, message: unescapeHTML(interpolateFn(toInterpolate, context)), context: { ...context } };
1533
1533
  });
1534
1534
  };
1535
+ /**
1536
+ * Outputs text to screen reader
1537
+ * @param {string} text The text to output to screen readers
1538
+ */
1539
+ export function screenReaderSpeech(text) {
1540
+ const ariaSpeechElement = document.createElement('div');
1541
+ ariaSpeechElement.setAttribute("style", "border: 0;clip: rect(0 0 0 0);height: 1px;margin: -1px;overflow: hidden;padding: 0;position: absolute;width: 1px;white-space: nowrap;");
1542
+ document.body.append(ariaSpeechElement);
1543
+ ariaSpeechElement.ariaLive = 'assertive';
1544
+ setTimeout(() => {
1545
+ ariaSpeechElement.textContent = text;
1546
+ setTimeout(() => {
1547
+ ariaSpeechElement.remove();
1548
+ }, 1000);
1549
+ }, 100);
1550
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@formio/js",
3
- "version": "5.2.4",
3
+ "version": "5.2.6",
4
4
  "description": "JavaScript powered Forms with JSON Form Builder",
5
5
  "main": "lib/cjs/index.js",
6
6
  "exports": {
@@ -91,8 +91,8 @@
91
91
  "tippy.js": "^6.3.7",
92
92
  "uuid": "^9.0.0",
93
93
  "vanilla-picker": "^2.12.3",
94
- "@formio/bootstrap": "^3.1.3",
95
- "@formio/core": "^2.5.3"
94
+ "@formio/bootstrap": "^3.1.4",
95
+ "@formio/core": "^2.5.4"
96
96
  },
97
97
  "devDependencies": {
98
98
  "@types/node": "^22.15.19",
@@ -105,6 +105,7 @@
105
105
  "browser-env": "^3.3.0",
106
106
  "chai": "^4.3.7",
107
107
  "chance": "^1.1.9",
108
+ "cross-env": "^10.1.0",
108
109
  "ejs-loader": "^0.5.0",
109
110
  "escape-string-regexp": "^5.0.0",
110
111
  "eslint": "^8.57.0",