@formio/js 5.0.0-rc.39 → 5.0.0-rc.41

Sign up to get free protection for your applications and to get access to all the features.
Files changed (130) hide show
  1. package/dist/formio.builder.css +2 -2
  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 +2 -2
  7. package/dist/formio.form.js +5373 -2370
  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 +25 -7
  11. package/dist/formio.full.css +2 -2
  12. package/dist/formio.full.js +5715 -2704
  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 +25 -7
  16. package/dist/formio.js +143 -61
  17. package/dist/formio.min.js +1 -1
  18. package/dist/formio.min.js.LICENSE.txt +13 -1
  19. package/dist/formio.utils.js +149 -96
  20. package/dist/formio.utils.min.js +1 -1
  21. package/dist/formio.utils.min.js.LICENSE.txt +4 -4
  22. package/lib/cjs/Element.js +1 -0
  23. package/lib/cjs/Embed.js +121 -121
  24. package/lib/cjs/Webform.js +36 -13
  25. package/lib/cjs/WebformBuilder.js +4 -2
  26. package/lib/cjs/Wizard.js +6 -1
  27. package/lib/cjs/components/_classes/component/Component.js +33 -22
  28. package/lib/cjs/components/_classes/component/editForm/Component.edit.logic.js +1 -1
  29. package/lib/cjs/components/_classes/component/editForm/Component.edit.validation.js +8 -0
  30. package/lib/cjs/components/_classes/component/fixtures/comp5.js +2 -2
  31. package/lib/cjs/components/_classes/multivalue/Multivalue.js +2 -2
  32. package/lib/cjs/components/_classes/nested/NestedComponent.js +2 -2
  33. package/lib/cjs/components/address/fixtures/comp3.js +1 -1
  34. package/lib/cjs/components/builder.js +0 -2
  35. package/lib/cjs/components/button/Button.js +7 -1
  36. package/lib/cjs/components/datagrid/DataGrid.js +16 -3
  37. package/lib/cjs/components/datagrid/fixtures/comp-with-allow-calculate-override.js +68 -0
  38. package/lib/cjs/components/datagrid/fixtures/comp6.js +1 -1
  39. package/lib/cjs/components/datagrid/fixtures/index.js +5 -1
  40. package/lib/cjs/components/datagrid/fixtures/two-comp-with-allow-calculate-override.js +104 -0
  41. package/lib/cjs/components/editgrid/EditGrid.js +11 -4
  42. package/lib/cjs/components/editgrid/fixtures/formsWithEditGridAndConditions.js +923 -0
  43. package/lib/cjs/components/file/File.js +2 -2
  44. package/lib/cjs/components/file/editForm/File.edit.file.js +1 -1
  45. package/lib/cjs/components/form/Form.js +1 -1
  46. package/lib/cjs/components/html/HTML.js +11 -2
  47. package/lib/cjs/components/html/fixtures/index.js +1 -3
  48. package/lib/cjs/components/index.js +0 -2
  49. package/lib/cjs/components/recaptcha/ReCaptcha.js +46 -46
  50. package/lib/cjs/components/select/Select.js +3 -1
  51. package/lib/cjs/components/select/fixtures/comp20.js +46 -0
  52. package/lib/cjs/components/select/fixtures/comp21.js +106 -0
  53. package/lib/cjs/components/select/fixtures/index.js +5 -1
  54. package/lib/cjs/components/selectboxes/SelectBoxes.js +1 -1
  55. package/lib/cjs/components/textfield/TextField.js +63 -3
  56. package/lib/cjs/providers/storage/s3.js +5 -3
  57. package/lib/cjs/providers/storage/uploadAdapter.js +1 -1
  58. package/lib/cjs/providers/storage/url.js +19 -13
  59. package/lib/cjs/templates/Templates.js +4 -4
  60. package/lib/cjs/translations/en.js +10 -6
  61. package/lib/cjs/utils/Evaluator.js +1 -1
  62. package/lib/cjs/utils/conditionOperators/IsEqualTo.js +2 -2
  63. package/lib/cjs/utils/formUtils.js +3 -3
  64. package/lib/cjs/utils/utils.js +4 -19
  65. package/lib/cjs/widgets/CalendarWidget.js +1 -1
  66. package/lib/mjs/Element.js +1 -0
  67. package/lib/mjs/Embed.js +1 -2
  68. package/lib/mjs/FormBuilder.js +1 -2
  69. package/lib/mjs/Webform.js +36 -13
  70. package/lib/mjs/WebformBuilder.js +4 -2
  71. package/lib/mjs/Wizard.js +6 -1
  72. package/lib/mjs/builders/Builders.js +1 -2
  73. package/lib/mjs/components/Components.js +1 -2
  74. package/lib/mjs/components/_classes/component/Component.js +33 -24
  75. package/lib/mjs/components/_classes/component/editForm/Component.edit.logic.js +1 -1
  76. package/lib/mjs/components/_classes/component/editForm/Component.edit.validation.js +8 -0
  77. package/lib/mjs/components/_classes/component/fixtures/comp5.js +2 -2
  78. package/lib/mjs/components/_classes/multivalue/Multivalue.js +2 -2
  79. package/lib/mjs/components/_classes/nested/NestedComponent.js +2 -2
  80. package/lib/mjs/components/address/fixtures/comp3.js +1 -1
  81. package/lib/mjs/components/builder.js +0 -2
  82. package/lib/mjs/components/button/Button.js +7 -1
  83. package/lib/mjs/components/datagrid/DataGrid.js +15 -3
  84. package/lib/mjs/components/datagrid/fixtures/comp-with-allow-calculate-override.js +66 -0
  85. package/lib/mjs/components/datagrid/fixtures/comp6.js +1 -1
  86. package/lib/mjs/components/datagrid/fixtures/index.js +3 -1
  87. package/lib/mjs/components/datagrid/fixtures/two-comp-with-allow-calculate-override.js +102 -0
  88. package/lib/mjs/components/editgrid/EditGrid.js +11 -4
  89. package/lib/mjs/components/editgrid/fixtures/formsWithEditGridAndConditions.js +921 -0
  90. package/lib/mjs/components/file/File.js +2 -2
  91. package/lib/mjs/components/file/editForm/File.edit.file.js +1 -1
  92. package/lib/mjs/components/form/Form.js +1 -1
  93. package/lib/mjs/components/html/HTML.js +10 -2
  94. package/lib/mjs/components/html/fixtures/index.js +1 -2
  95. package/lib/mjs/components/index.js +0 -2
  96. package/lib/mjs/components/recaptcha/ReCaptcha.js +32 -43
  97. package/lib/mjs/components/select/Select.js +3 -1
  98. package/lib/mjs/components/select/fixtures/comp20.js +44 -0
  99. package/lib/mjs/components/select/fixtures/comp21.js +104 -0
  100. package/lib/mjs/components/select/fixtures/index.js +3 -1
  101. package/lib/mjs/components/selectboxes/SelectBoxes.js +1 -1
  102. package/lib/mjs/components/textfield/TextField.js +62 -3
  103. package/lib/mjs/displays/Displays.js +1 -2
  104. package/lib/mjs/licenses/Licenses.js +1 -2
  105. package/lib/mjs/providers/Providers.js +1 -2
  106. package/lib/mjs/providers/storage/s3.js +5 -3
  107. package/lib/mjs/providers/storage/uploadAdapter.js +1 -1
  108. package/lib/mjs/providers/storage/url.js +19 -13
  109. package/lib/mjs/templates/Templates.js +1 -1
  110. package/lib/mjs/translations/en.js +10 -6
  111. package/lib/mjs/utils/Evaluator.js +1 -1
  112. package/lib/mjs/utils/conditionOperators/IsEqualTo.js +2 -2
  113. package/lib/mjs/utils/formUtils.js +3 -3
  114. package/lib/mjs/utils/utils.js +2 -16
  115. package/lib/mjs/widgets/CalendarWidget.js +1 -1
  116. package/package.json +23 -22
  117. package/lib/cjs/components/html/fixtures/comp3.js +0 -31
  118. package/lib/cjs/components/resource/Resource.form.js +0 -16
  119. package/lib/cjs/components/resource/Resource.js +0 -39
  120. package/lib/cjs/components/resource/editForm/Resource.edit.display.js +0 -102
  121. package/lib/cjs/components/resource/fixtures/comp1.js +0 -30
  122. package/lib/cjs/components/resource/fixtures/comp2.js +0 -31
  123. package/lib/cjs/components/resource/fixtures/index.js +0 -10
  124. package/lib/mjs/components/html/fixtures/comp3.js +0 -29
  125. package/lib/mjs/components/resource/Resource.form.js +0 -10
  126. package/lib/mjs/components/resource/Resource.js +0 -33
  127. package/lib/mjs/components/resource/editForm/Resource.edit.display.js +0 -100
  128. package/lib/mjs/components/resource/fixtures/comp1.js +0 -28
  129. package/lib/mjs/components/resource/fixtures/comp2.js +0 -29
  130. package/lib/mjs/components/resource/fixtures/index.js +0 -3
@@ -579,8 +579,8 @@ export default class FileComponent extends Field {
579
579
  }
580
580
  valid = pattern.excludes.reduce((result, excludePattern) => {
581
581
  const exclude = new RegExp(excludePattern, 'i');
582
- return result && (_.isNil(file.type) || !exclude.test(file.type)) &&
583
- (_.isNil(file.name) || !exclude.test(file.name));
582
+ return result && (_.isNil(file.type) || exclude.test(file.type)) &&
583
+ (_.isNil(file.name) || exclude.test(file.name));
584
584
  }, valid);
585
585
  return valid;
586
586
  }
@@ -184,7 +184,7 @@ export default [
184
184
  input: true,
185
185
  key: 'fileNameTemplate',
186
186
  label: 'File Name Template',
187
- placeholder: '(optional) { {name} }-{ {guid} }"',
187
+ placeholder: '(optional) { {name} }-{ {guid} }',
188
188
  tooltip: 'Specify template for name of uploaded file(s). Regular template variables are available (`data`, `component`, `user`, `value`, `moment` etc.), also `fileName`, `guid` variables are available. `guid` part must be present, if not found in template, will be added at the end.',
189
189
  weight: 25
190
190
  },
@@ -609,7 +609,7 @@ export default class FormComponent extends Component {
609
609
  }
610
610
  }
611
611
  isEmpty(value = this.dataValue) {
612
- return value === null || _.isEqual(value, this.emptyValue) || (this.areAllComponentsEmpty(value.data) && !value._id);
612
+ return value === null || _.isEqual(value, this.emptyValue) || (this.areAllComponentsEmpty(value?.data) && !value?._id);
613
613
  }
614
614
  areAllComponentsEmpty(data) {
615
615
  let res = true;
@@ -38,13 +38,13 @@ export default class HTMLComponent extends Component {
38
38
  return ` ${this.component.content} `;
39
39
  }
40
40
  const submission = _.get(this.root, 'submission', {});
41
- const content = this.component.content ? this.interpolate(this.sanitize(this.component.content, this.shouldSanitizeValue), {
41
+ const content = this.component.content ? this.interpolate(this.component.content, {
42
42
  metadata: submission.metadata || {},
43
43
  submission: submission,
44
44
  data: this.rootValue,
45
45
  row: this.data
46
46
  }) : '';
47
- return content;
47
+ return this.sanitize(content, this.shouldSanitizeValue);
48
48
  }
49
49
  get singleTags() {
50
50
  return ['br', 'img', 'hr'];
@@ -80,8 +80,16 @@ export default class HTMLComponent extends Component {
80
80
  render() {
81
81
  return super.render(this.renderContent());
82
82
  }
83
+ get dataReady() {
84
+ return this.root?.submissionReady || Promise.resolve();
85
+ }
83
86
  attach(element) {
84
87
  this.loadRefs(element, { html: 'single' });
88
+ this.dataReady.then(() => {
89
+ if (this.element) {
90
+ this.setContent(this.elemet, this.content);
91
+ }
92
+ });
85
93
  return super.attach(element);
86
94
  }
87
95
  }
@@ -1,4 +1,3 @@
1
1
  import comp1 from './comp1';
2
2
  import comp2 from './comp2';
3
- import comp3 from './comp3';
4
- export { comp1, comp2, comp3 };
3
+ export { comp1, comp2 };
@@ -31,7 +31,6 @@ import PasswordComponent from './password/Password';
31
31
  import PhoneNumberComponent from './phonenumber/PhoneNumber';
32
32
  import RadioComponent from './radio/Radio';
33
33
  import ReCaptchaComponent from './recaptcha/ReCaptcha';
34
- import ResourceComponent from './resource/Resource';
35
34
  import SelectBoxesComponent from './selectboxes/SelectBoxes';
36
35
  import SelectComponent from './select/Select';
37
36
  import SignatureComponent from './signature/Signature';
@@ -80,7 +79,6 @@ export default {
80
79
  phoneNumber: PhoneNumberComponent,
81
80
  radio: RadioComponent,
82
81
  recaptcha: ReCaptchaComponent,
83
- resource: ResourceComponent,
84
82
  select: SelectComponent,
85
83
  selectboxes: SelectBoxesComponent,
86
84
  signature: SignatureComponent,
@@ -55,7 +55,7 @@ export default class ReCaptchaComponent extends Component {
55
55
  get skipInEmail() {
56
56
  return true;
57
57
  }
58
- verify(actionName) {
58
+ async verify(actionName) {
59
59
  const siteKey = _get(this.root.form, 'settings.recaptcha.siteKey');
60
60
  if (!siteKey) {
61
61
  console.warn('There is no Site Key specified in settings in form JSON');
@@ -65,40 +65,34 @@ export default class ReCaptchaComponent extends Component {
65
65
  const recaptchaApiScriptUrl = `https://www.google.com/recaptcha/api.js?render=${_get(this.root.form, 'settings.recaptcha.siteKey')}`;
66
66
  this.recaptchaApiReady = Formio.requireLibrary('googleRecaptcha', 'grecaptcha', recaptchaApiScriptUrl, true);
67
67
  }
68
- if (this.recaptchaApiReady) {
68
+ try {
69
+ await this.recaptchaApiReady;
69
70
  this.recaptchaVerifiedPromise = new Promise((resolve, reject) => {
70
- this.recaptchaApiReady
71
- .then(() => {
72
- if (!this.isLoading) {
73
- this.isLoading = true;
74
- grecaptcha.ready(_debounce(() => {
75
- grecaptcha
76
- .execute(siteKey, {
77
- action: actionName
78
- })
79
- .then((token) => {
80
- return this.sendVerificationRequest(token).then(({ verificationResult, token }) => {
81
- this.recaptchaResult = {
82
- ...verificationResult,
83
- token,
84
- };
85
- this.updateValue(this.recaptchaResult);
86
- return resolve(verificationResult);
87
- });
88
- })
89
- .catch(() => {
90
- this.isLoading = false;
91
- });
92
- }, 1000));
93
- }
94
- })
95
- .catch(() => {
96
- return reject();
97
- });
98
- }).then(() => {
99
- this.isLoading = false;
71
+ if (!this.isLoading) {
72
+ this.isLoading = true;
73
+ grecaptcha.ready(_debounce(async () => {
74
+ try {
75
+ const token = await grecaptcha.execute(siteKey, { action: actionName });
76
+ const verificationResult = await this.sendVerificationRequest(token);
77
+ this.recaptchaResult = {
78
+ ...verificationResult,
79
+ token,
80
+ };
81
+ this.updateValue(this.recaptchaResult);
82
+ this.isLoading = false;
83
+ return resolve(verificationResult);
84
+ }
85
+ catch (err) {
86
+ this.isLoading = false;
87
+ reject(err);
88
+ }
89
+ }, 1000));
90
+ }
100
91
  });
101
92
  }
93
+ catch (err) {
94
+ this.loading = false;
95
+ }
102
96
  }
103
97
  beforeSubmit() {
104
98
  if (this.recaptchaVerifiedPromise) {
@@ -108,32 +102,27 @@ export default class ReCaptchaComponent extends Component {
108
102
  return super.beforeSubmit();
109
103
  }
110
104
  sendVerificationRequest(token) {
111
- return Formio.makeStaticRequest(`${Formio.projectUrl}/recaptcha?recaptchaToken=${token}`)
112
- .then((verificationResult) => ({ verificationResult, token }));
105
+ return Formio.makeStaticRequest(`${Formio.projectUrl}/recaptcha?recaptchaToken=${token}`);
113
106
  }
114
107
  checkComponentValidity(data, dirty, row, options = {}, errors = []) {
115
108
  data = data || this.rootValue;
116
109
  row = row || this.data;
117
110
  const { async = false } = options;
118
- // Verification could be async only
111
+ // Verification could be async only (which for now is only the case for server-side validation)
119
112
  if (!async) {
120
113
  return super.checkComponentValidity(data, dirty, row, options, errors);
121
114
  }
122
115
  const componentData = row[this.component.key];
123
116
  if (!componentData || !componentData.token) {
124
- this.setCustomValidity('ReCAPTCHA: Token is not specified in submission');
117
+ this.setCustomValidity(this.t('reCaptchaTokenNotSpecifiedError'));
125
118
  return Promise.resolve(false);
126
119
  }
127
120
  if (!componentData.success) {
128
- this.setCustomValidity('ReCAPTCHA: Token validation error');
121
+ this.setCustomValidity(this.t('reCaptchaTokenValidationError'));
129
122
  return Promise.resolve(false);
130
123
  }
131
- return this.hook('validateReCaptcha', componentData.token, () => Promise.resolve(true))
132
- .then((success) => success)
133
- .catch((err) => {
134
- this.setCustomValidity(err.message || err);
135
- return false;
136
- });
124
+ // Any further validation will 100% not run on the client
125
+ return Promise.resolve(true);
137
126
  }
138
127
  normalizeValue(newValue) {
139
128
  // If a recaptcha result has already been established, then do not allow it to be reset.
@@ -349,6 +349,7 @@ export default class SelectComponent extends ListComponent {
349
349
  }
350
350
  /* eslint-disable max-statements */
351
351
  setItems(items, fromSearch) {
352
+ this.selectItems = items;
352
353
  // If the items is a string, then parse as JSON.
353
354
  if (typeof items == 'string') {
354
355
  try {
@@ -817,7 +818,7 @@ export default class SelectComponent extends ListComponent {
817
818
  this.addFocusBlurEvents(input);
818
819
  this.triggerUpdate(null, true);
819
820
  if (this.visible) {
820
- this.setItems(this.selectOptions || []);
821
+ this.setItems(this.selectItems || []);
821
822
  }
822
823
  this.focusableElement = input;
823
824
  if (this.component.dataSrc === 'custom') {
@@ -1190,6 +1191,7 @@ export default class SelectComponent extends ListComponent {
1190
1191
  templateData[dataValueItemValue] = this.templateData[dataValueItemValue];
1191
1192
  });
1192
1193
  }
1194
+ templateData[value] = this.templateData[value];
1193
1195
  }
1194
1196
  _.set(submission.metadata.selectData, this.path, templateData);
1195
1197
  }
@@ -0,0 +1,44 @@
1
+ export default {
2
+ _id: '659fa81f4a40147c0ffb949b',
3
+ title: '7724',
4
+ name: '7724',
5
+ path: '7724',
6
+ type: 'form',
7
+ display: 'form',
8
+ components: [
9
+ {
10
+ label: 'Select',
11
+ widget: 'choicesjs',
12
+ tableView: true,
13
+ multiple: true,
14
+ data: {
15
+ values: [
16
+ {
17
+ label: 'Apple',
18
+ value: 'apple'
19
+ },
20
+ {
21
+ label: 'Orange',
22
+ value: 'orange'
23
+ },
24
+ {
25
+ label: 'Pear',
26
+ value: 'pear'
27
+ }
28
+ ]
29
+ },
30
+ key: 'select',
31
+ type: 'select',
32
+ input: true
33
+ },
34
+ {
35
+ type: 'button',
36
+ label: 'Submit',
37
+ key: 'submit',
38
+ disableOnInvalid: true,
39
+ input: true,
40
+ tableView: false
41
+ }
42
+ ],
43
+ project: '63cead09be0090345b109e22'
44
+ };
@@ -0,0 +1,104 @@
1
+ export default {
2
+ title: 'FIO-7632',
3
+ name: 'fio7632',
4
+ path: 'fio7632',
5
+ type: 'form',
6
+ display: 'form',
7
+ components: [
8
+ {
9
+ collapsible: false,
10
+ key: 'panel',
11
+ type: 'panel',
12
+ label: 'Panel',
13
+ input: false,
14
+ tableView: false,
15
+ components: [
16
+ {
17
+ label: 'Animals',
18
+ widget: 'html5',
19
+ tableView: true,
20
+ data: {
21
+ values: [
22
+ {
23
+ label: 'Dog',
24
+ value: 'dog',
25
+ },
26
+ {
27
+ label: 'Cat',
28
+ value: 'cat',
29
+ },
30
+ {
31
+ label: 'Horse',
32
+ value: 'horse',
33
+ },
34
+ ],
35
+ },
36
+ key: 'animals',
37
+ type: 'select',
38
+ input: true,
39
+ },
40
+ {
41
+ label: 'Checkbox',
42
+ tableView: false,
43
+ key: 'checkbox',
44
+ type: 'checkbox',
45
+ input: true,
46
+ },
47
+ {
48
+ label: 'Animals2',
49
+ widget: 'html5',
50
+ tableView: true,
51
+ data: {
52
+ values: [
53
+ {
54
+ label: 'Dog',
55
+ value: 'dog',
56
+ },
57
+ {
58
+ label: 'Cat',
59
+ value: 'cat',
60
+ },
61
+ {
62
+ label: 'Horse',
63
+ value: 'horse',
64
+ },
65
+ ],
66
+ },
67
+ calculateValue: 'if (data.checkbox === true) {\n value = data.animals;\n}',
68
+ key: 'animals2',
69
+ logic: [
70
+ {
71
+ name: 'disable',
72
+ trigger: {
73
+ type: 'javascript',
74
+ javascript: 'result = row.checkbox === true;',
75
+ },
76
+ actions: [
77
+ {
78
+ name: 'disable',
79
+ type: 'property',
80
+ property: {
81
+ label: 'Disabled',
82
+ value: 'disabled',
83
+ type: 'boolean',
84
+ },
85
+ state: true,
86
+ },
87
+ ],
88
+ },
89
+ ],
90
+ type: 'select',
91
+ input: true,
92
+ },
93
+ {
94
+ type: 'button',
95
+ label: 'Submit',
96
+ key: 'submit',
97
+ disableOnInvalid: true,
98
+ input: true,
99
+ tableView: false,
100
+ },
101
+ ],
102
+ },
103
+ ],
104
+ };
@@ -17,4 +17,6 @@ import comp16 from './comp16';
17
17
  import comp17 from './comp17';
18
18
  import comp18 from './comp18';
19
19
  import comp19 from './comp19';
20
- export { comp1, comp2, comp4, comp5, comp6, comp7, comp8, comp9, comp10, comp11, comp12, comp13, comp14, comp15, comp16, comp17, comp18, comp19 };
20
+ import comp20 from './comp20';
21
+ import comp21 from './comp21';
22
+ export { comp1, comp2, comp4, comp5, comp6, comp7, comp8, comp9, comp10, comp11, comp12, comp13, comp14, comp15, comp16, comp17, comp18, comp19, comp20, comp21 };
@@ -31,7 +31,7 @@ export default class SelectBoxesComponent extends RadioComponent {
31
31
  type: 'select',
32
32
  dataSrc: 'custom',
33
33
  valueProperty: 'value',
34
- valueType: 'string',
34
+ dataType: 'string',
35
35
  data: {
36
36
  custom: `values = ${classComp && classComp.values ? JSON.stringify(classComp.values) : []}`
37
37
  },
@@ -1,5 +1,6 @@
1
1
  import Input from '../_classes/input/Input';
2
2
  import { conformToMask } from '@formio/vanilla-text-mask';
3
+ import Inputmask from 'inputmask';
3
4
  import * as FormioUtils from '../../utils/utils';
4
5
  import _ from 'lodash';
5
6
  export default class TextFieldComponent extends Input {
@@ -148,8 +149,14 @@ export default class TextFieldComponent extends Input {
148
149
  const maskInput = this.refs.select ? this.refs.select[index] : null;
149
150
  const mask = this.getMaskPattern(value.maskName);
150
151
  if (textInput && maskInput && mask) {
151
- const placeholderChar = this.placeholderChar;
152
- textInput.value = conformToMask(textValue, FormioUtils.getInputMask(mask), { placeholderChar }).conformedValue;
152
+ if (textInput.inputmask) {
153
+ this.setInputMask(textInput, mask);
154
+ textInput.inputmask.setValue(textValue);
155
+ }
156
+ else {
157
+ const placeholderChar = this.placeholderChar;
158
+ textInput.value = conformToMask(textValue, FormioUtils.getInputMask(mask), { placeholderChar }).conformedValue;
159
+ }
153
160
  maskInput.value = value.maskName;
154
161
  }
155
162
  else {
@@ -180,7 +187,10 @@ export default class TextFieldComponent extends Input {
180
187
  if (displayMask && !valueMask) {
181
188
  return this.unmaskValue(value, displayMask);
182
189
  }
183
- if (this.refs.valueMaskInput?.mask) {
190
+ if (displayMask && displayMask !== valueMask) {
191
+ return Inputmask.format(Inputmask.unmask(value, displayMask), valueMask);
192
+ }
193
+ if (this.refs.valueMaskInput?.mask && this.refs.valueMaskInput.mask.textMaskInputElement) {
184
194
  this.refs.valueMaskInput.mask.textMaskInputElement.update(value);
185
195
  return this.refs.valueMaskInput?.value;
186
196
  }
@@ -193,6 +203,55 @@ export default class TextFieldComponent extends Input {
193
203
  maskName: maskInput ? maskInput.value : undefined
194
204
  };
195
205
  }
206
+ checkInputMaskValue(inputMask) {
207
+ let valid = true;
208
+ const maskValues = _.values(inputMask.split('').reduce((acc, el, i, mask) => {
209
+ if (el === '{' || el === '}') {
210
+ if (mask[i + 1] === '{' || mask[i + 1] === '}') {
211
+ valid = false;
212
+ }
213
+ acc[el] = (acc[el] ?? 0) + 1;
214
+ }
215
+ return acc;
216
+ }, {}));
217
+ if (maskValues[0] !== maskValues[1]) {
218
+ valid = false;
219
+ }
220
+ return valid;
221
+ }
222
+ setInputMask(input, inputMask, usePlaceholder) {
223
+ if (this.type !== 'textfield') {
224
+ super.setInputMask(input, inputMask, usePlaceholder);
225
+ return;
226
+ }
227
+ inputMask = inputMask || this.component.displayMask || this.component.inputMask;
228
+ const mask = FormioUtils.getInputMask(inputMask, this.placeholderChar);
229
+ this.defaultMask = mask;
230
+ if (input && inputMask) {
231
+ try {
232
+ //remove previous mask
233
+ if (input.mask) {
234
+ input.mask.remove();
235
+ }
236
+ if (this.checkInputMaskValue(inputMask)) {
237
+ input.mask = new Inputmask(inputMask, {
238
+ clearMaskOnLostFocus: !!this.component.placeholder,
239
+ showMaskOnHover: !this.component.placeholder,
240
+ placeholder: this.placeholderChar || '',
241
+ }).mask(input);
242
+ }
243
+ }
244
+ catch (e) {
245
+ console.warn(e);
246
+ }
247
+ if (mask.numeric) {
248
+ input.setAttribute('pattern', '\\d*');
249
+ }
250
+ if (this.component.placeholder) {
251
+ input.setAttribute('placeholder', this.component.placeholder);
252
+ }
253
+ }
254
+ }
196
255
  isHtmlRenderMode() {
197
256
  return super.isHtmlRenderMode() ||
198
257
  ((this.options.readOnly || this.disabled) &&
@@ -2,7 +2,7 @@ import _ from 'lodash';
2
2
  import pdf from '../PDF';
3
3
  import webform from '../Webform';
4
4
  import wizard from '../Wizard';
5
- class Displays {
5
+ export default class Displays {
6
6
  static displays = {
7
7
  pdf,
8
8
  webform,
@@ -21,4 +21,3 @@ class Displays {
21
21
  return Displays.displays;
22
22
  }
23
23
  }
24
- export default Displays;
@@ -1,5 +1,5 @@
1
1
  import _ from 'lodash';
2
- class Licenses {
2
+ export default class Licenses {
3
3
  static licenses = {};
4
4
  static addLicense(name, license) {
5
5
  Licenses.licenses[name] = license;
@@ -14,4 +14,3 @@ class Licenses {
14
14
  return Licenses.licenses;
15
15
  }
16
16
  }
17
- export default Licenses;
@@ -2,7 +2,7 @@ import _ from 'lodash';
2
2
  import address from './address';
3
3
  import auth from './auth';
4
4
  import storage from './storage';
5
- class Providers {
5
+ export default class Providers {
6
6
  static providers = {
7
7
  address,
8
8
  auth,
@@ -26,4 +26,3 @@ class Providers {
26
26
  }
27
27
  }
28
28
  }
29
- export default Providers;
@@ -31,9 +31,11 @@ function s3(formio) {
31
31
  else {
32
32
  xhr.openAndSetHeaders('PUT', response.signed);
33
33
  xhr.setRequestHeader('Content-Type', file.type);
34
- Object.keys(response.data.headers).forEach((key) => {
35
- xhr.setRequestHeader(key, response.data.headers[key]);
36
- });
34
+ if (response.data.headers) {
35
+ Object.keys(response.data.headers).forEach((key) => {
36
+ xhr.setRequestHeader(key, response.data.headers[key]);
37
+ });
38
+ }
37
39
  return file;
38
40
  }
39
41
  }
@@ -16,7 +16,7 @@ class FormioUploadAdapter {
16
16
  uploadStorage,
17
17
  file,
18
18
  uniqueName(file.name),
19
- uploadDir || '',
19
+ uploadDir || '', //should pass empty string if undefined
20
20
  (evt) => this.onUploadProgress(evt),
21
21
  uploadUrl,
22
22
  uploadOptions,
@@ -1,4 +1,18 @@
1
1
  function url(formio) {
2
+ function setOptions(options, xhr) {
3
+ const parsedOptions = typeof options === 'string' ? JSON.parse(options) : options;
4
+ for (const prop in parsedOptions) {
5
+ if (prop === 'headers') {
6
+ const headers = parsedOptions['headers'];
7
+ for (const header in headers) {
8
+ xhr.setRequestHeader(header, headers[header]);
9
+ }
10
+ }
11
+ else {
12
+ xhr[prop] = parsedOptions[prop];
13
+ }
14
+ }
15
+ }
2
16
  const xhrRequest = (url, name, query, data, options, progressCallback, abortCallback) => {
3
17
  return new Promise((resolve, reject) => {
4
18
  const xhr = new XMLHttpRequest();
@@ -57,18 +71,7 @@ function url(formio) {
57
71
  }
58
72
  //Overrides previous request props
59
73
  if (options) {
60
- const parsedOptions = typeof options === 'string' ? JSON.parse(options) : options;
61
- for (const prop in parsedOptions) {
62
- if (prop === 'headers') {
63
- const headers = parsedOptions['headers'];
64
- for (const header in headers) {
65
- xhr.setRequestHeader(header, headers[header]);
66
- }
67
- }
68
- else {
69
- xhr[prop] = parsedOptions[prop];
70
- }
71
- }
74
+ setOptions(options, xhr);
72
75
  }
73
76
  xhr.send(json ? data : fd);
74
77
  });
@@ -109,7 +112,7 @@ function url(formio) {
109
112
  return uploadRequest();
110
113
  }
111
114
  },
112
- deleteFile(fileInfo) {
115
+ deleteFile(fileInfo, options) {
113
116
  return new Promise((resolve, reject) => {
114
117
  const xhr = new XMLHttpRequest();
115
118
  xhr.open('DELETE', fileInfo.url, true);
@@ -121,6 +124,9 @@ function url(formio) {
121
124
  reject(xhr.response || 'Unable to delete file');
122
125
  }
123
126
  };
127
+ if (options) {
128
+ setOptions(options, xhr);
129
+ }
124
130
  xhr.send(null);
125
131
  });
126
132
  },
@@ -1,5 +1,5 @@
1
1
  import templates from './index';
2
- import { Template } from '@formio/core/template';
2
+ import { Template } from '@formio/core/experimental';
3
3
  Template.addTemplates(templates);
4
4
  Template.defaultTemplates = templates.bootstrap;
5
5
  export default Template;