@formio/js 5.6.1 → 5.7.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.
Files changed (104) hide show
  1. package/dist/formio.builder.css +5 -5
  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 +5 -5
  7. package/dist/formio.form.js +5195 -5189
  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 +4 -2
  11. package/dist/formio.full.css +5 -5
  12. package/dist/formio.full.js +6046 -6040
  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 +4 -2
  16. package/dist/formio.js +1193 -1187
  17. package/dist/formio.min.js +1 -1
  18. package/dist/formio.min.js.LICENSE.txt +4 -2
  19. package/dist/formio.utils.js +1084 -1078
  20. package/dist/formio.utils.min.js +1 -1
  21. package/dist/formio.utils.min.js.LICENSE.txt +4 -2
  22. package/lib/cjs/Embed.js +38 -25
  23. package/lib/cjs/Form.d.ts +8 -2
  24. package/lib/cjs/Form.js +1 -1
  25. package/lib/cjs/Formio.js +1 -1
  26. package/lib/cjs/PDF.d.ts +1 -0
  27. package/lib/cjs/PDF.js +21 -5
  28. package/lib/cjs/PDFBuilder.d.ts +1 -0
  29. package/lib/cjs/PDFBuilder.js +1 -0
  30. package/lib/cjs/Webform.d.ts +13 -1
  31. package/lib/cjs/Webform.js +79 -26
  32. package/lib/cjs/Wizard.d.ts +1 -1
  33. package/lib/cjs/Wizard.js +12 -6
  34. package/lib/cjs/components/_classes/component/Component.js +0 -65
  35. package/lib/cjs/components/_classes/nested/NestedComponent.form.js +13 -0
  36. package/lib/cjs/components/_classes/nested/NestedComponent.js +4 -0
  37. package/lib/cjs/components/content/editForm/Content.edit.display.js +8 -0
  38. package/lib/cjs/components/currency/editForm/Currency.edit.display.js +20 -0
  39. package/lib/cjs/components/day/editForm/Day.edit.display.js +8 -0
  40. package/lib/cjs/components/editgrid/EditGrid.d.ts +1 -0
  41. package/lib/cjs/components/editgrid/EditGrid.js +22 -2
  42. package/lib/cjs/components/email/editForm/Email.edit.display.js +12 -0
  43. package/lib/cjs/components/fieldset/editForm/Fieldset.edit.display.js +8 -0
  44. package/lib/cjs/components/file/editForm/File.edit.file.js +1 -1
  45. package/lib/cjs/components/form/Form.js +21 -1
  46. package/lib/cjs/components/hidden/Hidden.d.ts +0 -1
  47. package/lib/cjs/components/hidden/Hidden.js +1 -1
  48. package/lib/cjs/components/hidden/editForm/Hidden.edit.display.js +8 -0
  49. package/lib/cjs/components/html/editForm/HTML.edit.display.js +8 -0
  50. package/lib/cjs/components/number/Number.d.ts +11 -0
  51. package/lib/cjs/components/number/Number.js +35 -0
  52. package/lib/cjs/components/number/editForm/Number.edit.display.js +12 -0
  53. package/lib/cjs/components/password/editForm/Password.edit.display.js +12 -0
  54. package/lib/cjs/components/phonenumber/PhoneNumber.form.js +8 -0
  55. package/lib/cjs/components/select/editForm/Select.edit.data.d.ts +1 -1
  56. package/lib/cjs/components/select/editForm/Select.edit.data.js +1 -0
  57. package/lib/cjs/components/tabs/editForm/Tabs.edit.display.js +8 -0
  58. package/lib/cjs/components/textarea/editForm/TextArea.edit.display.js +12 -0
  59. package/lib/cjs/components/url/editForm/Url.edit.display.js +12 -0
  60. package/lib/cjs/components/well/editForm/Well.edit.display.js +8 -0
  61. package/lib/cjs/package.json +1 -1
  62. package/lib/cjs/utils/utils.js +6 -18
  63. package/lib/mjs/Embed.js +37 -24
  64. package/lib/mjs/Form.d.ts +8 -2
  65. package/lib/mjs/Form.js +1 -1
  66. package/lib/mjs/Formio.js +1 -1
  67. package/lib/mjs/PDF.d.ts +1 -0
  68. package/lib/mjs/PDF.js +21 -5
  69. package/lib/mjs/PDFBuilder.d.ts +1 -0
  70. package/lib/mjs/PDFBuilder.js +1 -0
  71. package/lib/mjs/Webform.d.ts +13 -1
  72. package/lib/mjs/Webform.js +75 -24
  73. package/lib/mjs/Wizard.d.ts +1 -1
  74. package/lib/mjs/Wizard.js +12 -6
  75. package/lib/mjs/components/_classes/component/Component.js +0 -65
  76. package/lib/mjs/components/_classes/nested/NestedComponent.form.js +13 -0
  77. package/lib/mjs/components/_classes/nested/NestedComponent.js +4 -0
  78. package/lib/mjs/components/content/editForm/Content.edit.display.js +8 -0
  79. package/lib/mjs/components/currency/editForm/Currency.edit.display.js +20 -0
  80. package/lib/mjs/components/day/editForm/Day.edit.display.js +8 -0
  81. package/lib/mjs/components/editgrid/EditGrid.d.ts +1 -0
  82. package/lib/mjs/components/editgrid/EditGrid.js +22 -2
  83. package/lib/mjs/components/email/editForm/Email.edit.display.js +12 -0
  84. package/lib/mjs/components/fieldset/editForm/Fieldset.edit.display.js +8 -0
  85. package/lib/mjs/components/file/editForm/File.edit.file.js +1 -1
  86. package/lib/mjs/components/form/Form.js +21 -1
  87. package/lib/mjs/components/hidden/Hidden.d.ts +0 -1
  88. package/lib/mjs/components/hidden/Hidden.js +1 -1
  89. package/lib/mjs/components/hidden/editForm/Hidden.edit.display.js +8 -0
  90. package/lib/mjs/components/html/editForm/HTML.edit.display.js +8 -0
  91. package/lib/mjs/components/number/Number.d.ts +11 -0
  92. package/lib/mjs/components/number/Number.js +34 -0
  93. package/lib/mjs/components/number/editForm/Number.edit.display.js +12 -0
  94. package/lib/mjs/components/password/editForm/Password.edit.display.js +12 -0
  95. package/lib/mjs/components/phonenumber/PhoneNumber.form.js +8 -0
  96. package/lib/mjs/components/select/editForm/Select.edit.data.d.ts +1 -1
  97. package/lib/mjs/components/select/editForm/Select.edit.data.js +1 -0
  98. package/lib/mjs/components/tabs/editForm/Tabs.edit.display.js +8 -0
  99. package/lib/mjs/components/textarea/editForm/TextArea.edit.display.js +12 -0
  100. package/lib/mjs/components/url/editForm/Url.edit.display.js +12 -0
  101. package/lib/mjs/components/well/editForm/Well.edit.display.js +8 -0
  102. package/lib/mjs/package.json +1 -1
  103. package/lib/mjs/utils/utils.js +6 -18
  104. package/package.json +1 -1
@@ -5,10 +5,30 @@ exports.default = [
5
5
  key: 'inputMask',
6
6
  ignore: true,
7
7
  },
8
+ {
9
+ key: 'widget.type',
10
+ ignore: true,
11
+ },
12
+ {
13
+ key: 'widget',
14
+ ignore: true,
15
+ },
16
+ {
17
+ key: 'inputMasks',
18
+ ignore: true,
19
+ },
8
20
  {
9
21
  key: 'allowMultipleMasks',
10
22
  ignore: true,
11
23
  },
24
+ {
25
+ key: 'labelWidth',
26
+ ignore: true,
27
+ },
28
+ {
29
+ key: 'labelMargin',
30
+ ignore: true,
31
+ },
12
32
  {
13
33
  key: 'showWordCount',
14
34
  ignore: true,
@@ -5,6 +5,14 @@ exports.default = [
5
5
  key: 'labelPosition',
6
6
  ignore: true,
7
7
  },
8
+ {
9
+ key: 'labelWidth',
10
+ ignore: true,
11
+ },
12
+ {
13
+ key: 'labelMargin',
14
+ ignore: true,
15
+ },
8
16
  {
9
17
  weight: 15,
10
18
  type: 'checkbox',
@@ -48,6 +48,7 @@ export default class EditGridComponent extends NestedArrayComponent {
48
48
  setVariableTypeComponents(): void;
49
49
  variableTypeComponentsIndexes: any[] | undefined;
50
50
  isOpen(editRow: any): boolean;
51
+ shouldBlockUnsavedOpenRows(): boolean;
51
52
  isComponentVisibleInSomeRow(component: any): any;
52
53
  visibleInHeader: any;
53
54
  flattenRowDataValue(dataValue: any): {};
@@ -315,6 +315,24 @@ class EditGridComponent extends NestedArrayComponent_1.default {
315
315
  isOpen(editRow) {
316
316
  return [EditRowState.New, EditRowState.Editing, EditRowState.Viewing].includes(editRow.state);
317
317
  }
318
+ shouldBlockUnsavedOpenRows() {
319
+ const openRows = this.editRows.filter((editRow) => this.isOpen(editRow));
320
+ if (!openRows.length) {
321
+ return false;
322
+ }
323
+ const isOnlyPristineOpenWhenEmptyRow = this.component.openWhenEmpty &&
324
+ openRows.length === 1 &&
325
+ openRows.every((row) => row.state === EditRowState.New) &&
326
+ openRows.every((row) => {
327
+ let isPristine = true;
328
+ (0, utils_1.eachComponent)(row.components, (comp) => {
329
+ isPristine =
330
+ comp.type === 'form' ? lodash_1.default.isEqual(comp.emptyValue, comp.dataValue) : comp.pristine;
331
+ });
332
+ return isPristine;
333
+ });
334
+ return !isOnlyPristineOpenWhenEmptyRow;
335
+ }
318
336
  isComponentVisibleInSomeRow(component) {
319
337
  const rows = this.editRows;
320
338
  const savedStates = [EditRowState.Saved, EditRowState.Editing, EditRowState.Draft];
@@ -1079,7 +1097,7 @@ class EditGridComponent extends NestedArrayComponent_1.default {
1079
1097
  if (valid === null) {
1080
1098
  editRow.errors.push({
1081
1099
  type: 'error',
1082
- message: this.t('componentInvalidRowValidation', { componentKey: this.key })
1100
+ message: this.t('componentInvalidRowValidation', { componentKey: this.key }),
1083
1101
  });
1084
1102
  }
1085
1103
  }
@@ -1152,7 +1170,9 @@ class EditGridComponent extends NestedArrayComponent_1.default {
1152
1170
  }
1153
1171
  return false;
1154
1172
  }
1155
- else if (rowsEditing && this.saveEditMode && !this.component.openWhenEmpty) {
1173
+ else if (rowsEditing &&
1174
+ this.saveEditMode &&
1175
+ (this.shouldBlockUnsavedOpenRows() || this.errors.length)) {
1156
1176
  this._errors = this.setCustomValidity(this.t(this.errorMessage('unsavedRowsError')), dirty);
1157
1177
  errors.push(...this._errors);
1158
1178
  return false;
@@ -9,6 +9,18 @@ exports.default = [
9
9
  key: 'allowMultipleMasks',
10
10
  ignore: true,
11
11
  },
12
+ {
13
+ key: 'inputMasks',
14
+ ignore: true,
15
+ },
16
+ {
17
+ key: 'widget.type',
18
+ ignore: true,
19
+ },
20
+ {
21
+ key: 'widget',
22
+ ignore: true,
23
+ },
12
24
  {
13
25
  key: 'showWordCount',
14
26
  ignore: true,
@@ -5,6 +5,14 @@ exports.default = [
5
5
  key: 'labelPosition',
6
6
  ignore: true,
7
7
  },
8
+ {
9
+ key: 'labelWidth',
10
+ ignore: true,
11
+ },
12
+ {
13
+ key: 'labelMargin',
14
+ ignore: true,
15
+ },
8
16
  {
9
17
  key: 'placeholder',
10
18
  ignore: true,
@@ -295,7 +295,7 @@ exports.default = [
295
295
  key: 'imageSize',
296
296
  label: 'Image Size',
297
297
  placeholder: '100',
298
- tooltip: 'The image size, in square pixels, for previewing images.',
298
+ tooltip: 'The image size, in square pixels, for previewing images. If explicitly set, the frame of the component must be large enough to allow for the specified size.',
299
299
  weight: 40,
300
300
  clearOnHide: false,
301
301
  conditional: {
@@ -273,7 +273,7 @@ class FormComponent extends Component_1.default {
273
273
  return super.attach(element);
274
274
  }
275
275
  return super.attach(element).then(() => {
276
- if (this.isSubFormLazyLoad() && !this.hasLoadedForm && !this.subFormLoading) {
276
+ if (this.isSubFormLazyLoad() && !this.subForm && !this.subFormLoading) {
277
277
  this.createSubForm(true);
278
278
  }
279
279
  if (!this.subFormReady) {
@@ -372,6 +372,26 @@ class FormComponent extends Component_1.default {
372
372
  }
373
373
  return super.redraw();
374
374
  }
375
+ /**
376
+ * Get Row Index. Declared so the setter below does not shadow the inherited getter.
377
+ * @returns {number} - The row index.
378
+ */
379
+ get rowIndex() {
380
+ return super.rowIndex;
381
+ }
382
+ /**
383
+ * Set Row Index to row and pass it down to the subform so that its components
384
+ * regenerate their paths. Unlike NestedComponent, the subform is not part of
385
+ * this.components, so the row index has to be forwarded explicitly.
386
+ * @param {number} value - The row index.
387
+ * @returns {void}
388
+ */
389
+ set rowIndex(value) {
390
+ super.rowIndex = value;
391
+ if (this.subForm) {
392
+ this.subForm.rowIndex = value;
393
+ }
394
+ }
375
395
  /**
376
396
  * Pass everyComponent to subform.
377
397
  * @param {any[]} args - Arguments to pass through to the subform's everyComponent method.
@@ -10,7 +10,6 @@ export default class HiddenComponent extends Input {
10
10
  };
11
11
  get inputInfo(): any;
12
12
  labelIsHidden(): boolean;
13
- get emptyValue(): string;
14
13
  setValue(value: any, flags?: {}): boolean;
15
14
  }
16
15
  import Input from '../_classes/input/Input';
@@ -48,7 +48,7 @@ class HiddenComponent extends Input_1.default {
48
48
  return true;
49
49
  }
50
50
  get emptyValue() {
51
- return '';
51
+ return null;
52
52
  }
53
53
  setValue(value, flags = {}) {
54
54
  return this.updateValue(value, flags);
@@ -5,6 +5,14 @@ exports.default = [
5
5
  key: 'labelPosition',
6
6
  ignore: true,
7
7
  },
8
+ {
9
+ key: 'labelWidth',
10
+ ignore: true,
11
+ },
12
+ {
13
+ key: 'labelMargin',
14
+ ignore: true,
15
+ },
8
16
  {
9
17
  key: 'placeholder',
10
18
  ignore: true,
@@ -5,6 +5,14 @@ exports.default = [
5
5
  key: 'labelPosition',
6
6
  ignore: true,
7
7
  },
8
+ {
9
+ key: 'labelWidth',
10
+ ignore: true,
11
+ },
12
+ {
13
+ key: 'labelMargin',
14
+ ignore: true,
15
+ },
8
16
  {
9
17
  key: 'placeholder',
10
18
  ignore: true,
@@ -51,5 +51,16 @@ export default class NumberComponent extends Input {
51
51
  focus(): void;
52
52
  getMaskedValue(value: any): any;
53
53
  getValueAsString(value: any, options: any): any;
54
+ setErrorClasses(elements: any, dirty: any, hasErrors: any, hasMessages: any, element?: any): void;
55
+ /**
56
+ * Points the invalid inputs at the rendered error messages through `aria-describedby`, so a
57
+ * screen reader announces what is wrong with the value. The base class only marks the input
58
+ * `aria-invalid`, which says the value was rejected but not why.
59
+ * @param {Array<HTMLElement>} elements - The input elements the errors apply to.
60
+ * @param {boolean} hasErrors - TRUE if the component currently has errors.
61
+ * @returns {void}
62
+ */
63
+ linkErrorMessages(elements: Array<HTMLElement>, hasErrors: boolean): void;
64
+ errorMessageIds: any[] | undefined;
54
65
  }
55
66
  import Input from '../_classes/input/Input';
@@ -271,5 +271,40 @@ class NumberComponent extends Input_1.default {
271
271
  element.value = this.getValueAsString(this.formatValue(this.parseValue(element.value)));
272
272
  });
273
273
  }
274
+ setErrorClasses(elements, dirty, hasErrors, hasMessages, element = this.element) {
275
+ super.setErrorClasses(elements, dirty, hasErrors, hasMessages, element);
276
+ this.linkErrorMessages(elements, hasErrors);
277
+ }
278
+ /**
279
+ * Points the invalid inputs at the rendered error messages through `aria-describedby`, so a
280
+ * screen reader announces what is wrong with the value. The base class only marks the input
281
+ * `aria-invalid`, which says the value was rejected but not why.
282
+ * @param {Array<HTMLElement>} elements - The input elements the errors apply to.
283
+ * @param {boolean} hasErrors - TRUE if the component currently has errors.
284
+ * @returns {void}
285
+ */
286
+ linkErrorMessages(elements, hasErrors) {
287
+ var _a;
288
+ const previousIds = this.errorMessageIds || [];
289
+ const renderedMessages = Array.from(((_a = this.refs.messageContainer) === null || _a === void 0 ? void 0 : _a.children) || []);
290
+ const errorIds = hasErrors ? renderedMessages.map((message) => message.id).filter(Boolean) : [];
291
+ const invalidInputs = hasErrors ? Array.from(elements || []) : [];
292
+ const isOwnErrorId = (id) => previousIds.includes(id) || errorIds.includes(id);
293
+ Array.from(this.refs.input || []).forEach((input) => {
294
+ const describedBy = (input.getAttribute('aria-describedby') || '')
295
+ .split(' ')
296
+ .filter((id) => id && !isOwnErrorId(id));
297
+ if (invalidInputs.includes(input)) {
298
+ describedBy.push(...errorIds);
299
+ }
300
+ if (describedBy.length) {
301
+ input.setAttribute('aria-describedby', describedBy.join(' '));
302
+ }
303
+ else {
304
+ input.removeAttribute('aria-describedby');
305
+ }
306
+ });
307
+ this.errorMessageIds = errorIds;
308
+ }
274
309
  }
275
310
  exports.default = NumberComponent;
@@ -13,6 +13,18 @@ exports.default = [
13
13
  key: 'allowMultipleMasks',
14
14
  ignore: true,
15
15
  },
16
+ {
17
+ key: 'inputMasks',
18
+ ignore: true,
19
+ },
20
+ {
21
+ key: 'widget.type',
22
+ ignore: true,
23
+ },
24
+ {
25
+ key: 'widget',
26
+ ignore: true,
27
+ },
16
28
  {
17
29
  key: 'showWordCount',
18
30
  ignore: true,
@@ -13,4 +13,16 @@ exports.default = [
13
13
  key: 'allowMultipleMasks',
14
14
  ignore: true,
15
15
  },
16
+ {
17
+ key: 'inputMasks',
18
+ ignore: true,
19
+ },
20
+ {
21
+ key: 'widget.type',
22
+ ignore: true,
23
+ },
24
+ {
25
+ key: 'widget',
26
+ ignore: true,
27
+ },
16
28
  ];
@@ -23,6 +23,14 @@ function default_1(...extend) {
23
23
  key: 'showCharCount',
24
24
  ignore: true,
25
25
  },
26
+ {
27
+ key: 'widget.type',
28
+ ignore: true,
29
+ },
30
+ {
31
+ key: 'widget',
32
+ ignore: true,
33
+ },
26
34
  ],
27
35
  },
28
36
  {
@@ -1057,6 +1057,7 @@ declare const _default: ({
1057
1057
  alwaysEnabled?: undefined;
1058
1058
  } | {
1059
1059
  key: string;
1060
+ type: string;
1060
1061
  conditional: {
1061
1062
  json: {
1062
1063
  and: ({
@@ -1107,7 +1108,6 @@ declare const _default: ({
1107
1108
  };
1108
1109
  };
1109
1110
  data?: undefined;
1110
- type?: undefined;
1111
1111
  as?: undefined;
1112
1112
  editor?: undefined;
1113
1113
  weight?: undefined;
@@ -625,6 +625,7 @@ exports.default = [
625
625
  },
626
626
  {
627
627
  key: 'selectData',
628
+ type: 'hidden',
628
629
  conditional: {
629
630
  json: {
630
631
  and: [
@@ -5,6 +5,14 @@ exports.default = [
5
5
  key: 'labelPosition',
6
6
  ignore: true,
7
7
  },
8
+ {
9
+ key: 'labelWidth',
10
+ ignore: true,
11
+ },
12
+ {
13
+ key: 'labelMargin',
14
+ ignore: true,
15
+ },
8
16
  {
9
17
  key: 'placeholder',
10
18
  ignore: true,
@@ -14,10 +14,22 @@ exports.default = [
14
14
  key: 'allowMultipleMasks',
15
15
  ignore: true,
16
16
  },
17
+ {
18
+ key: 'inputMasks',
19
+ ignore: true,
20
+ },
17
21
  {
18
22
  key: 'mask',
19
23
  ignore: true,
20
24
  },
25
+ {
26
+ key: 'widget.type',
27
+ ignore: true,
28
+ },
29
+ {
30
+ key: 'widget',
31
+ ignore: true,
32
+ },
21
33
  {
22
34
  type: 'number',
23
35
  input: true,
@@ -9,6 +9,18 @@ exports.default = [
9
9
  key: 'allowMultipleMasks',
10
10
  ignore: true,
11
11
  },
12
+ {
13
+ key: 'inputMasks',
14
+ ignore: true,
15
+ },
16
+ {
17
+ key: 'widget.type',
18
+ ignore: true,
19
+ },
20
+ {
21
+ key: 'widget',
22
+ ignore: true,
23
+ },
12
24
  {
13
25
  key: 'showWordCount',
14
26
  ignore: true,
@@ -5,6 +5,14 @@ exports.default = [
5
5
  key: 'labelPosition',
6
6
  ignore: true,
7
7
  },
8
+ {
9
+ key: 'labelWidth',
10
+ ignore: true,
11
+ },
12
+ {
13
+ key: 'labelMargin',
14
+ ignore: true,
15
+ },
8
16
  {
9
17
  key: 'placeholder',
10
18
  ignore: true,
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "type": "commonjs",
3
- "version": "5.6.1"
3
+ "version": "5.7.0"
4
4
  }
@@ -474,9 +474,7 @@ function setActionProperty(component, action, result, row, data, instance) {
474
474
  case 'string': {
475
475
  const safeData = escapeInterpolationDataStrings(data);
476
476
  const safeRow = escapeInterpolationDataStrings(row);
477
- const safeResult = typeof result === 'string'
478
- ? lodash_1.default.escape(result)
479
- : escapeInterpolationDataStrings(result);
477
+ const safeResult = typeof result === 'string' ? lodash_1.default.escape(result) : escapeInterpolationDataStrings(result);
480
478
  const evalData = {
481
479
  data: safeData,
482
480
  row: safeRow,
@@ -1777,21 +1775,11 @@ function getScreenReaderMessage(component, type, value) {
1777
1775
  }
1778
1776
  }
1779
1777
  }
1780
- else if (typeof value === 'number' || value === null) {
1781
- if (value != null && value !== '') {
1782
- if (!isNaN(max) && value > max) {
1783
- message += `Number cannot be greater than ${max}. `;
1784
- }
1785
- if (!isNaN(min) && value < min) {
1786
- message += `Number cannot be less than ${min}.`;
1787
- }
1788
- }
1789
- else {
1790
- if (!isNaN(min))
1791
- message += `Minimum value ${min}. `;
1792
- if (!isNaN(max))
1793
- message += `Maximum value ${max}. `;
1794
- }
1778
+ else if (value === null) {
1779
+ if (!isNaN(min))
1780
+ message += `Minimum value ${min}. `;
1781
+ if (!isNaN(max))
1782
+ message += `Maximum value ${max}. `;
1795
1783
  }
1796
1784
  return message.trim();
1797
1785
  }
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.6.1';
17
+ static version = '5.7.0';
18
18
  static setLicense(license, norecurse = false) {
19
19
  Formio.license = license;
20
20
  if (!norecurse && Formio.FormioClass) {
@@ -332,7 +332,10 @@ export class Formio {
332
332
  };
333
333
  });
334
334
  const id = Formio.config.id || `formio-${Math.random().toString(36).substring(7)}`;
335
- const hasQuillComponent = (components = []) => {
335
+ // Quill and CKEditor cannot run in the shadow DOM (https://github.com/quilljs/quill/issues/2021,
336
+ // https://github.com/ckeditor/ckeditor5/issues/15824), so fall back to the light DOM when the
337
+ // form contains one of them.
338
+ const hasShadowIncompatibleEditor = (components) => {
336
339
  if (!Array.isArray(components)) {
337
340
  return false;
338
341
  }
@@ -340,16 +343,38 @@ export class Formio {
340
343
  if (!component || typeof component !== 'object') {
341
344
  return false;
342
345
  }
343
- const isQuillTextarea = component.type === 'textarea' &&
344
- component.wysiwyg === true &&
345
- component.editor === 'quill';
346
- return (isQuillTextarea ||
347
- hasQuillComponent(component.components) ||
348
- hasQuillComponent(component.columns?.flatMap((column) => column.components || [])) ||
349
- hasQuillComponent(component.rows?.flatMap((row) => row.flatMap((cell) => cell.components || []))));
346
+ if (component.type === 'textarea') {
347
+ // A textarea with `wysiwyg` set and no explicit `editor` defaults to CKEditor at render time.
348
+ const editor = component.editor || (component.wysiwyg ? 'ckeditor' : '');
349
+ if (['quill', 'ckeditor'].includes(editor)) {
350
+ return true;
351
+ }
352
+ }
353
+ const children = (component.components || []).concat(component.columns?.flatMap((column) => column.components || []) || [], component.rows?.flatMap((row) => row.flatMap((cell) => cell.components || [])) || []);
354
+ return hasShadowIncompatibleEditor(children);
350
355
  });
351
356
  };
352
- const disableShadowForQuill = hasQuillComponent(Formio.config.form?.components);
357
+ const shouldSkipShadowDom = async () => {
358
+ if (Formio.config.form?.components) {
359
+ return hasShadowIncompatibleEditor(Formio.config.form.components);
360
+ }
361
+ const formUrl = Formio.config.src || (typeof Formio.config.form === 'string' ? Formio.config.form : '');
362
+ if (!formUrl) {
363
+ return false;
364
+ }
365
+ try {
366
+ const response = await fetch(formUrl);
367
+ if (!response.ok) {
368
+ throw new Error(`Request failed with status ${response.status}`);
369
+ }
370
+ const form = await response.json();
371
+ return hasShadowIncompatibleEditor(form?.components);
372
+ }
373
+ catch (err) {
374
+ Formio.debug('Could not load the form to check for shadow DOM support', err);
375
+ return false;
376
+ }
377
+ };
353
378
  // Create a new wrapper and add the element inside of a new wrapper.
354
379
  let wrapper = Formio.createElement('div', {
355
380
  id: `${id}-wrapper`,
@@ -358,20 +383,8 @@ export class Formio {
358
383
  // If we include the libraries, then we will attempt to run this in shadow dom.
359
384
  const useShadowDom = Formio.config.includeLibs &&
360
385
  !Formio.config.noshadow &&
361
- !disableShadowForQuill &&
362
- typeof wrapper.attachShadow === 'function';
363
- if (useShadowDom) {
364
- wrapper = wrapper.attachShadow({
365
- mode: 'open',
366
- });
367
- options.shadowRoot = wrapper;
368
- // Due to an issue with quill not loading styles in the shadowdom, we need to add quill styles and js to the shadowdom
369
- const quill = {
370
- js: `${Formio.cdn.quill}/quill.js`,
371
- css: `${Formio.cdn.quill}/quill.snow.css`,
372
- };
373
- await Formio.addLibrary(wrapper, quill, 'quill');
374
- }
386
+ typeof wrapper.attachShadow === 'function' &&
387
+ !(await shouldSkipShadowDom());
375
388
  element.parentNode.removeChild(element);
376
389
  wrapper.appendChild(element);
377
390
  // If this is inside of shadow dom, then we need to add the styles and scripts to the shadow dom.
package/lib/mjs/Form.d.ts CHANGED
@@ -45,7 +45,7 @@
45
45
  * @property {number} [saveDraftThrottle] - The throttle for the save draft feature.
46
46
  * @property {boolean} [readOnly] - Set this form to readOnly.
47
47
  * @property {boolean} [noAlerts] - Disable the alerts dialog.
48
- * @property {{[key: string]: string} | { translationsUrl: string }} [i18n] - The translation file for this rendering.
48
+ * @property {{[key: string]: string} | { translationsUrl: string } | { resource: { form: string, codeComponent: string, mapComponent: string } }} [i18n] - The translations for this rendering: inline, a hosted file, or a Form.io language resource (one submission per language).
49
49
  * @property {string} [template] - Custom logic for creation of elements.
50
50
  * @property {boolean} [noDefaults] - Exclude default values from the settings.
51
51
  * @property {any} [fileService] - The file service for this form.
@@ -198,12 +198,18 @@ export type FormOptions = {
198
198
  */
199
199
  noAlerts?: boolean | undefined;
200
200
  /**
201
- * - The translation file for this rendering.
201
+ * - The translations for this rendering: inline, a hosted file, or a Form.io language resource (one submission per language).
202
202
  */
203
203
  i18n?: {
204
204
  [key: string]: string;
205
205
  } | {
206
206
  translationsUrl: string;
207
+ } | {
208
+ resource: {
209
+ form: string;
210
+ codeComponent: string;
211
+ mapComponent: string;
212
+ };
207
213
  } | undefined;
208
214
  /**
209
215
  * - Custom logic for creation of elements.
package/lib/mjs/Form.js CHANGED
@@ -50,7 +50,7 @@ import FormioUtils from './utils';
50
50
  * @property {number} [saveDraftThrottle] - The throttle for the save draft feature.
51
51
  * @property {boolean} [readOnly] - Set this form to readOnly.
52
52
  * @property {boolean} [noAlerts] - Disable the alerts dialog.
53
- * @property {{[key: string]: string} | { translationsUrl: string }} [i18n] - The translation file for this rendering.
53
+ * @property {{[key: string]: string} | { translationsUrl: string } | { resource: { form: string, codeComponent: string, mapComponent: string } }} [i18n] - The translations for this rendering: inline, a hosted file, or a Form.io language resource (one submission per language).
54
54
  * @property {string} [template] - Custom logic for creation of elements.
55
55
  * @property {boolean} [noDefaults] - Exclude default values from the settings.
56
56
  * @property {any} [fileService] - The file service for this form.
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.6.1';
7
+ FormioCore.version = '5.7.0';
8
8
  CDN.defaultCDN = FormioCore.version.includes('rc')
9
9
  ? 'https://cdn.test-form.io'
10
10
  : 'https://cdn.form.io';
package/lib/mjs/PDF.d.ts CHANGED
@@ -2,6 +2,7 @@ export default class PDF extends Webform {
2
2
  constructor(element: any, options: any);
3
3
  components: any[];
4
4
  init(): void;
5
+ forwardRefreshEventsToIframe(): void;
5
6
  render(): any;
6
7
  submitButton: any;
7
8
  attachComponents(element: any, components: any, container: any): Promise<void>;