@formio/js 5.4.0-api98.1 → 5.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/formio.builder.css +26 -5
- package/dist/formio.builder.min.css +1 -1
- package/dist/formio.embed.js +1 -1
- package/dist/formio.embed.min.js +1 -1
- package/dist/formio.embed.min.js.LICENSE.txt +1 -1
- package/dist/formio.form.css +26 -5
- package/dist/formio.form.js +3462 -3448
- package/dist/formio.form.min.css +1 -1
- package/dist/formio.form.min.js +1 -1
- package/dist/formio.form.min.js.LICENSE.txt +2 -2
- package/dist/formio.full.css +26 -5
- package/dist/formio.full.js +4277 -4263
- package/dist/formio.full.min.css +1 -1
- package/dist/formio.full.min.js +1 -1
- package/dist/formio.full.min.js.LICENSE.txt +2 -2
- package/dist/formio.js +1738 -1724
- package/dist/formio.min.js +1 -1
- package/dist/formio.min.js.LICENSE.txt +2 -2
- package/dist/formio.utils.js +1631 -1617
- package/dist/formio.utils.min.js +1 -1
- package/dist/formio.utils.min.js.LICENSE.txt +2 -2
- package/lib/cjs/Element.d.ts +11 -0
- package/lib/cjs/Element.js +24 -0
- package/lib/cjs/Embed.js +23 -2
- package/lib/cjs/Form.d.ts +1 -1
- package/lib/cjs/Formio.js +1 -1
- package/lib/cjs/PDFBuilder.js +6 -1
- package/lib/cjs/Webform.d.ts +1 -1
- package/lib/cjs/Webform.js +9 -6
- package/lib/cjs/WebformBuilder.js +14 -1
- package/lib/cjs/Wizard.js +15 -11
- package/lib/cjs/components/Components.d.ts +3 -0
- package/lib/cjs/components/Components.js +3 -1
- package/lib/cjs/components/_classes/component/Component.d.ts +13 -0
- package/lib/cjs/components/_classes/component/Component.js +137 -44
- package/lib/cjs/components/_classes/component/editForm/Component.edit.conditional.js +1 -1
- package/lib/cjs/components/_classes/component/editForm/Component.edit.data.js +1 -1
- package/lib/cjs/components/_classes/component/editForm/utils.d.ts +1 -0
- package/lib/cjs/components/_classes/component/editForm/utils.js +3 -0
- package/lib/cjs/components/_classes/nested/NestedComponent.js +5 -7
- package/lib/cjs/components/address/Address.js +2 -0
- package/lib/cjs/components/button/Button.d.ts +1 -0
- package/lib/cjs/components/button/Button.js +22 -1
- package/lib/cjs/components/datagrid/DataGrid.js +35 -10
- package/lib/cjs/components/datamap/DataMap.d.ts +1 -4
- package/lib/cjs/components/datamap/DataMap.js +42 -10
- package/lib/cjs/components/datetime/DateTime.js +11 -1
- package/lib/cjs/components/datetime/editForm/DateTime.edit.date.d.ts +18 -1
- package/lib/cjs/components/datetime/editForm/DateTime.edit.date.js +3 -0
- package/lib/cjs/components/datetime/editForm/DateTime.edit.time.d.ts +13 -2
- package/lib/cjs/components/datetime/editForm/DateTime.edit.time.js +3 -0
- package/lib/cjs/components/day/Day.d.ts +0 -15
- package/lib/cjs/components/day/Day.js +8 -17
- package/lib/cjs/components/editgrid/EditGrid.js +13 -3
- package/lib/cjs/components/file/File.js +7 -6
- package/lib/cjs/components/form/Form.d.ts +1 -0
- package/lib/cjs/components/form/Form.js +20 -8
- package/lib/cjs/components/number/Number.d.ts +1 -0
- package/lib/cjs/components/number/Number.js +18 -0
- package/lib/cjs/components/select/Select.js +6 -3
- package/lib/cjs/components/signature/Signature.js +5 -5
- package/lib/cjs/components/signature/editForm/Signature.edit.display.d.ts +0 -6
- package/lib/cjs/components/signature/editForm/Signature.edit.display.js +0 -1
- package/lib/cjs/components/textfield/editForm/TextField.edit.display.d.ts +0 -10
- package/lib/cjs/components/textfield/editForm/TextField.edit.display.js +9 -23
- package/lib/cjs/formio.form.js +2 -5
- package/lib/cjs/package.json +1 -1
- package/lib/cjs/providers/address/GoogleAddressProvider.js +1 -1
- package/lib/cjs/providers/storage/azure.js +9 -3
- package/lib/cjs/translations/en.d.ts +1 -0
- package/lib/cjs/translations/en.js +3 -1
- package/lib/cjs/utils/formUtils.d.ts +2 -2
- package/lib/cjs/utils/index.d.ts +3 -3
- package/lib/cjs/utils/utils.d.ts +1 -1
- package/lib/cjs/utils/utils.js +28 -11
- package/lib/cjs/widgets/CalendarWidget.js +1 -1
- package/lib/mjs/Element.d.ts +11 -0
- package/lib/mjs/Element.js +23 -0
- package/lib/mjs/Embed.js +21 -2
- package/lib/mjs/Form.d.ts +1 -1
- package/lib/mjs/Formio.js +1 -1
- package/lib/mjs/PDFBuilder.js +6 -1
- package/lib/mjs/Webform.d.ts +1 -1
- package/lib/mjs/Webform.js +6 -3
- package/lib/mjs/WebformBuilder.js +13 -1
- package/lib/mjs/Wizard.js +9 -10
- package/lib/mjs/components/Components.d.ts +3 -0
- package/lib/mjs/components/Components.js +3 -1
- package/lib/mjs/components/_classes/component/Component.d.ts +13 -0
- package/lib/mjs/components/_classes/component/Component.js +135 -43
- package/lib/mjs/components/_classes/component/editForm/Component.edit.conditional.js +1 -1
- package/lib/mjs/components/_classes/component/editForm/Component.edit.data.js +1 -1
- package/lib/mjs/components/_classes/component/editForm/utils.d.ts +1 -0
- package/lib/mjs/components/_classes/component/editForm/utils.js +3 -0
- package/lib/mjs/components/_classes/nested/NestedComponent.js +5 -6
- package/lib/mjs/components/address/Address.js +2 -0
- package/lib/mjs/components/button/Button.d.ts +1 -0
- package/lib/mjs/components/button/Button.js +21 -1
- package/lib/mjs/components/datagrid/DataGrid.js +39 -11
- package/lib/mjs/components/datamap/DataMap.d.ts +1 -4
- package/lib/mjs/components/datamap/DataMap.js +41 -10
- package/lib/mjs/components/datetime/DateTime.js +11 -1
- package/lib/mjs/components/datetime/editForm/DateTime.edit.date.d.ts +18 -1
- package/lib/mjs/components/datetime/editForm/DateTime.edit.date.js +3 -0
- package/lib/mjs/components/datetime/editForm/DateTime.edit.time.d.ts +13 -2
- package/lib/mjs/components/datetime/editForm/DateTime.edit.time.js +3 -0
- package/lib/mjs/components/day/Day.d.ts +0 -15
- package/lib/mjs/components/day/Day.js +8 -17
- package/lib/mjs/components/editgrid/EditGrid.js +12 -2
- package/lib/mjs/components/file/File.js +7 -6
- package/lib/mjs/components/form/Form.d.ts +1 -0
- package/lib/mjs/components/form/Form.js +18 -6
- package/lib/mjs/components/number/Number.d.ts +1 -0
- package/lib/mjs/components/number/Number.js +17 -0
- package/lib/mjs/components/select/Select.js +6 -3
- package/lib/mjs/components/signature/Signature.js +1 -1
- package/lib/mjs/components/signature/editForm/Signature.edit.display.d.ts +0 -6
- package/lib/mjs/components/signature/editForm/Signature.edit.display.js +0 -1
- package/lib/mjs/components/textfield/editForm/TextField.edit.display.d.ts +0 -10
- package/lib/mjs/components/textfield/editForm/TextField.edit.display.js +9 -23
- package/lib/mjs/formio.form.js +4 -7
- package/lib/mjs/package.json +1 -1
- package/lib/mjs/providers/address/GoogleAddressProvider.js +1 -1
- package/lib/mjs/providers/storage/azure.js +9 -3
- package/lib/mjs/translations/en.d.ts +1 -0
- package/lib/mjs/translations/en.js +3 -1
- package/lib/mjs/utils/formUtils.d.ts +2 -2
- package/lib/mjs/utils/index.d.ts +3 -3
- package/lib/mjs/utils/utils.d.ts +1 -1
- package/lib/mjs/utils/utils.js +27 -11
- package/lib/mjs/widgets/CalendarWidget.js +2 -2
- package/package.json +8 -7
|
@@ -145,7 +145,7 @@ class Component extends Element_1.default {
|
|
|
145
145
|
unique: false,
|
|
146
146
|
},
|
|
147
147
|
/**
|
|
148
|
-
*
|
|
148
|
+
* the simple conditional settings for a component.
|
|
149
149
|
*/
|
|
150
150
|
conditional: {
|
|
151
151
|
show: null,
|
|
@@ -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
|
*
|
|
@@ -1134,9 +1152,12 @@ class Component extends Element_1.default {
|
|
|
1134
1152
|
* @returns {string} - The submission timezone.
|
|
1135
1153
|
*/
|
|
1136
1154
|
get submissionTimezone() {
|
|
1137
|
-
this.options.submissionTimezone
|
|
1138
|
-
this.options.submissionTimezone
|
|
1139
|
-
|
|
1155
|
+
if (!this.options.submissionTimezone) {
|
|
1156
|
+
this.options.submissionTimezone = lodash_1.default.get(this.root, 'options.submissionTimezone');
|
|
1157
|
+
}
|
|
1158
|
+
return (this.options.submissionTimezone ||
|
|
1159
|
+
lodash_1.default.get(this.root, '_submission.metadata.timezone') ||
|
|
1160
|
+
lodash_1.default.get(this.component, 'widget.submissionTimezone'));
|
|
1140
1161
|
}
|
|
1141
1162
|
/**
|
|
1142
1163
|
* Return the current timezone.
|
|
@@ -1151,6 +1172,7 @@ class Component extends Element_1.default {
|
|
|
1151
1172
|
* @returns {string} - The current timezone.
|
|
1152
1173
|
*/
|
|
1153
1174
|
getTimezone(settings) {
|
|
1175
|
+
settings = settings || {};
|
|
1154
1176
|
if (settings.timezone) {
|
|
1155
1177
|
return settings.timezone;
|
|
1156
1178
|
}
|
|
@@ -1158,12 +1180,19 @@ class Component extends Element_1.default {
|
|
|
1158
1180
|
return 'UTC';
|
|
1159
1181
|
}
|
|
1160
1182
|
const submissionTimezone = this.submissionTimezone;
|
|
1183
|
+
const mode = settings.displayInTimezone === '' || settings.displayInTimezone == null
|
|
1184
|
+
? 'viewer'
|
|
1185
|
+
: settings.displayInTimezone;
|
|
1186
|
+
if (this.options.pdf && submissionTimezone) {
|
|
1187
|
+
return submissionTimezone;
|
|
1188
|
+
}
|
|
1189
|
+
const staticSnapshot = this.options.server ||
|
|
1190
|
+
this.options.renderMode === 'html' ||
|
|
1191
|
+
!!this.options.viewAsHtml;
|
|
1161
1192
|
if (submissionTimezone &&
|
|
1162
|
-
(
|
|
1163
|
-
((this.options.pdf || this.options.server) && settings.displayInTimezone === 'viewer'))) {
|
|
1193
|
+
(mode === 'submission' || (staticSnapshot && (mode === 'viewer' || mode === 'location')))) {
|
|
1164
1194
|
return submissionTimezone;
|
|
1165
1195
|
}
|
|
1166
|
-
// Return current timezone if none are provided.
|
|
1167
1196
|
return (0, utils_2.currentTimezone)();
|
|
1168
1197
|
}
|
|
1169
1198
|
/**
|
|
@@ -1190,6 +1219,19 @@ class Component extends Element_1.default {
|
|
|
1190
1219
|
}
|
|
1191
1220
|
}
|
|
1192
1221
|
}
|
|
1222
|
+
/**
|
|
1223
|
+
* Announces a message to screen readers via the component's live region.
|
|
1224
|
+
* @param {string} message - The message to announce.
|
|
1225
|
+
*/
|
|
1226
|
+
announce(message) {
|
|
1227
|
+
const liveRegion = this.refs.liveRegion;
|
|
1228
|
+
if (liveRegion) {
|
|
1229
|
+
liveRegion.textContent = '';
|
|
1230
|
+
setTimeout(() => {
|
|
1231
|
+
liveRegion.textContent = message;
|
|
1232
|
+
}, 50);
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1193
1235
|
/**
|
|
1194
1236
|
* Opens the modal element.
|
|
1195
1237
|
* @param {string} template - The template to use for the modal dialog.
|
|
@@ -1323,6 +1365,7 @@ class Component extends Element_1.default {
|
|
|
1323
1365
|
this.loadRefs(element, {
|
|
1324
1366
|
messageContainer: 'single',
|
|
1325
1367
|
tooltip: 'multiple',
|
|
1368
|
+
liveRegion: 'single',
|
|
1326
1369
|
});
|
|
1327
1370
|
this.attachTooltips(this.refs.tooltip);
|
|
1328
1371
|
// Attach logic.
|
|
@@ -1567,13 +1610,13 @@ class Component extends Element_1.default {
|
|
|
1567
1610
|
value.forEach((val, index) => {
|
|
1568
1611
|
const widget = this.refs.input[index] && this.refs.input[index].widget;
|
|
1569
1612
|
if (widget) {
|
|
1570
|
-
values.push(widget.getValueAsString(val
|
|
1613
|
+
values.push(widget.getValueAsString(val));
|
|
1571
1614
|
}
|
|
1572
1615
|
});
|
|
1573
1616
|
return values;
|
|
1574
1617
|
}
|
|
1575
1618
|
const widget = this.refs.input[0].widget;
|
|
1576
|
-
return widget.getValueAsString(value
|
|
1619
|
+
return widget.getValueAsString(value);
|
|
1577
1620
|
}
|
|
1578
1621
|
/**
|
|
1579
1622
|
* Returns the value of the component as a string.
|
|
@@ -2312,29 +2355,24 @@ class Component extends Element_1.default {
|
|
|
2312
2355
|
* @returns {void}
|
|
2313
2356
|
*/
|
|
2314
2357
|
setErrorClasses(elements, dirty, hasErrors, hasMessages, element = this.element) {
|
|
2315
|
-
|
|
2316
|
-
elements.forEach((
|
|
2317
|
-
this.setElementInvalid(this.performInputMapping(
|
|
2358
|
+
var _a;
|
|
2359
|
+
elements.forEach((el) => {
|
|
2360
|
+
this.setElementInvalid(this.performInputMapping(el), hasErrors);
|
|
2318
2361
|
});
|
|
2319
2362
|
this.setInputWidgetErrorClasses(elements, hasErrors);
|
|
2320
2363
|
// do not set error classes for hidden components
|
|
2321
2364
|
if (!this.visible) {
|
|
2365
|
+
this.clearErrorClasses(element);
|
|
2322
2366
|
return;
|
|
2323
2367
|
}
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
else {
|
|
2333
|
-
this.addClass(element, 'has-error');
|
|
2334
|
-
}
|
|
2335
|
-
}
|
|
2336
|
-
if (hasMessages) {
|
|
2337
|
-
this.addClass(element, 'has-message');
|
|
2368
|
+
const wantHighlight = hasErrors && !!dirty && !!this.options.highlightErrors;
|
|
2369
|
+
const wantHasError = hasErrors && !wantHighlight;
|
|
2370
|
+
this.toggleClass(element, this.options.componentErrorClass, wantHighlight);
|
|
2371
|
+
this.toggleClass(element, 'has-error', wantHasError);
|
|
2372
|
+
this.toggleClass(element, 'has-message', hasMessages);
|
|
2373
|
+
// Preserve previous clearErrorClasses() behavior: drop the 'alert alert-danger' pair if left over.
|
|
2374
|
+
if ((_a = element === null || element === void 0 ? void 0 : element.classList) === null || _a === void 0 ? void 0 : _a.contains('alert-danger')) {
|
|
2375
|
+
this.removeClass(element, 'alert alert-danger');
|
|
2338
2376
|
}
|
|
2339
2377
|
}
|
|
2340
2378
|
/**
|
|
@@ -2584,12 +2622,61 @@ class Component extends Element_1.default {
|
|
|
2584
2622
|
{ type: 'styles', src: `${Formio_1.Formio.cdn.quill}/quill.${settings.theme}.css` },
|
|
2585
2623
|
], true);
|
|
2586
2624
|
// Lazy load the quill library.
|
|
2587
|
-
return Formio_1.Formio.requireLibrary('quill', 'Quill', lodash_1.default.get(this.options, 'editors.quill.src', `${Formio_1.Formio.cdn.quill}/quill.
|
|
2625
|
+
return Formio_1.Formio.requireLibrary('quill', 'Quill', lodash_1.default.get(this.options, 'editors.quill.src', `${Formio_1.Formio.cdn.quill}/quill.js`), true).then(() => {
|
|
2588
2626
|
return Formio_1.Formio.requireLibrary('quill-table', 'Quill', `${Formio_1.Formio.cdn.baseUrl}/quill/quill-table.js`, true).then(() => {
|
|
2589
2627
|
if (!element.parentNode) {
|
|
2590
2628
|
return Promise.reject();
|
|
2591
2629
|
}
|
|
2592
2630
|
this.quill = new Quill(element, isIEBrowser ? Object.assign(Object.assign({}, settings), { modules: {} }) : settings);
|
|
2631
|
+
const root = element.getRootNode();
|
|
2632
|
+
if (root instanceof ShadowRoot && root.getSelection) {
|
|
2633
|
+
const sel = this.quill.selection;
|
|
2634
|
+
// 1. getNativeRange: read selection from shadowRoot instead of document
|
|
2635
|
+
sel.getNativeRange = () => {
|
|
2636
|
+
const shadowSelection = root.getSelection();
|
|
2637
|
+
if (shadowSelection == null || shadowSelection.rangeCount <= 0)
|
|
2638
|
+
return null;
|
|
2639
|
+
const nativeRange = shadowSelection.getRangeAt(0);
|
|
2640
|
+
if (nativeRange == null)
|
|
2641
|
+
return null;
|
|
2642
|
+
return sel.normalizeNative(nativeRange);
|
|
2643
|
+
};
|
|
2644
|
+
// 2. hasFocus: check shadowRoot.activeElement instead of document.activeElement
|
|
2645
|
+
sel.hasFocus = () => {
|
|
2646
|
+
return root.activeElement === sel.root ||
|
|
2647
|
+
(root.activeElement != null && sel.root.contains(root.activeElement));
|
|
2648
|
+
};
|
|
2649
|
+
// 3. setNativeRange: use shadowRoot's selection to add/remove ranges
|
|
2650
|
+
const origSetNativeRange = sel.setNativeRange.bind(sel);
|
|
2651
|
+
sel.setNativeRange = (startNode, startOffset, endNode, endOffset, force) => {
|
|
2652
|
+
// Delegate to original logic for the null case (blur)
|
|
2653
|
+
if (startNode == null) {
|
|
2654
|
+
origSetNativeRange(null);
|
|
2655
|
+
return;
|
|
2656
|
+
}
|
|
2657
|
+
if (!sel.hasFocus()) {
|
|
2658
|
+
sel.root.focus({ preventScroll: true });
|
|
2659
|
+
}
|
|
2660
|
+
const shadowSelection = root.getSelection();
|
|
2661
|
+
if (shadowSelection == null)
|
|
2662
|
+
return;
|
|
2663
|
+
const { native } = sel.getNativeRange() || {};
|
|
2664
|
+
endNode = endNode !== null && endNode !== void 0 ? endNode : startNode;
|
|
2665
|
+
endOffset = endOffset !== null && endOffset !== void 0 ? endOffset : startOffset;
|
|
2666
|
+
if (native == null || force ||
|
|
2667
|
+
startNode !== native.startContainer || startOffset !== native.startOffset ||
|
|
2668
|
+
endNode !== native.endContainer || endOffset !== native.endOffset) {
|
|
2669
|
+
const range = document.createRange();
|
|
2670
|
+
range.setStart(startNode, startOffset);
|
|
2671
|
+
range.setEnd(endNode, endOffset);
|
|
2672
|
+
shadowSelection.removeAllRanges();
|
|
2673
|
+
shadowSelection.addRange(range);
|
|
2674
|
+
}
|
|
2675
|
+
};
|
|
2676
|
+
document.addEventListener('selectionchange', () => {
|
|
2677
|
+
sel.update();
|
|
2678
|
+
});
|
|
2679
|
+
}
|
|
2593
2680
|
/** This block of code adds the [source] capabilities. See https://codepen.io/anon/pen/ZyEjrQ */
|
|
2594
2681
|
const txtArea = document.createElement('textarea');
|
|
2595
2682
|
txtArea.setAttribute('class', 'quill-source-code');
|
|
@@ -2608,7 +2695,8 @@ class Component extends Element_1.default {
|
|
|
2608
2695
|
// Make sure to select cursor when they click on the element.
|
|
2609
2696
|
this.addEventListener(element, 'click', () => this.quill.focus());
|
|
2610
2697
|
// Allows users to skip toolbar items when tabbing though form
|
|
2611
|
-
const
|
|
2698
|
+
const queryRoot = element.getRootNode() || document;
|
|
2699
|
+
const elm = queryRoot.querySelectorAll('.ql-formats > button');
|
|
2612
2700
|
for (let i = 0; i < elm.length; i++) {
|
|
2613
2701
|
elm[i].setAttribute('tabindex', '-1');
|
|
2614
2702
|
}
|
|
@@ -3243,7 +3331,7 @@ class Component extends Element_1.default {
|
|
|
3243
3331
|
if (flags.silentCheck) {
|
|
3244
3332
|
return [];
|
|
3245
3333
|
}
|
|
3246
|
-
let isDirty = flags.dirty
|
|
3334
|
+
let isDirty = flags.dirty || this.dirty;
|
|
3247
3335
|
if (this.options.alwaysDirty) {
|
|
3248
3336
|
isDirty = true;
|
|
3249
3337
|
}
|
|
@@ -3450,22 +3538,27 @@ class Component extends Element_1.default {
|
|
|
3450
3538
|
}
|
|
3451
3539
|
});
|
|
3452
3540
|
this.addEventListener(element, 'blur', () => {
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
this.emit('blur', this);
|
|
3457
|
-
if (this.component.validateOn === 'blur') {
|
|
3458
|
-
(_b = (_a = this.root).triggerChange) === null || _b === void 0 ? void 0 : _b.call(_a, { fromBlur: true }, {
|
|
3459
|
-
instance: this,
|
|
3460
|
-
component: this.component,
|
|
3461
|
-
value: this.dataValue,
|
|
3462
|
-
flags: { fromBlur: true },
|
|
3463
|
-
});
|
|
3464
|
-
}
|
|
3465
|
-
this.root.focusedComponent = null;
|
|
3466
|
-
this.root.pendingBlur = null;
|
|
3467
|
-
});
|
|
3541
|
+
const root = this.root;
|
|
3542
|
+
if (!root) {
|
|
3543
|
+
return;
|
|
3468
3544
|
}
|
|
3545
|
+
root.pendingBlur = utils_1.default.delay(() => {
|
|
3546
|
+
var _a;
|
|
3547
|
+
if (!root) {
|
|
3548
|
+
return;
|
|
3549
|
+
}
|
|
3550
|
+
this.emit('blur', this);
|
|
3551
|
+
if (this.component.validateOn === 'blur') {
|
|
3552
|
+
(_a = root.triggerChange) === null || _a === void 0 ? void 0 : _a.call(root, { fromBlur: true }, {
|
|
3553
|
+
instance: this,
|
|
3554
|
+
component: this.component,
|
|
3555
|
+
value: this.dataValue,
|
|
3556
|
+
flags: { fromBlur: true },
|
|
3557
|
+
});
|
|
3558
|
+
}
|
|
3559
|
+
root.focusedComponent = null;
|
|
3560
|
+
root.pendingBlur = null;
|
|
3561
|
+
});
|
|
3469
3562
|
});
|
|
3470
3563
|
}
|
|
3471
3564
|
setCustomValidity(messages, dirty, external) {
|
|
@@ -49,5 +49,5 @@ exports.default = [
|
|
|
49
49
|
},
|
|
50
50
|
utils_1.default.javaScriptValue('Advanced Conditions', 'customConditional', 'conditional.json', 110, '<p>You must assign the <strong>show</strong> variable a boolean result.</p>' +
|
|
51
51
|
'<p><strong>Note: Advanced Conditional logic will override the results of the Simple Conditional logic.</strong></p>' +
|
|
52
|
-
'<h5>Example</h5><pre>show = !!data.showMe;</pre>', '<p><a href="https://help.form.io/userguide/form-building/logic-and-conditions" target="_blank" rel="noopener noreferrer">Click here for an example</a></p>'),
|
|
52
|
+
'<h5>Example</h5><pre>show = !!data.showMe;</pre>', '<p><a href="https://help.form.io/userguide/form-building/logic-and-conditions" target="_blank" rel="noopener noreferrer">Click here for an example</a></p>', utils_1.default.tokenVariableDescription()),
|
|
53
53
|
];
|
|
@@ -144,7 +144,7 @@ exports.default = [
|
|
|
144
144
|
input: true,
|
|
145
145
|
},
|
|
146
146
|
utils_1.default.javaScriptValue('Custom Default Value', 'customDefaultValue', 'customDefaultValue', 1000, '<p><h4>Example:</h4><pre>value = data.firstName + " " + data.lastName;</pre></p>', '<p><h4>Example:</h4><pre>{"cat": [{"var": "data.firstName"}, " ", {"var": "data.lastName"}]}</pre>'),
|
|
147
|
-
utils_1.default.javaScriptValue('Calculated Value', 'calculateValue', 'calculateValue', 1100, '<p><h4>Example:</h4><pre>value = data.a + data.b + data.c;</pre></p>', '<p><h4>Example:</h4><pre>{"+": [{"var": "data.a"}, {"var": "data.b"}, {"var": "data.c"}]}</pre><p><a href="https://help.form.io/userguide/form-building/logic-and-conditions#calculated-values" target="_blank" rel="noopener noreferrer">Click here for an example</a></p>',
|
|
147
|
+
utils_1.default.javaScriptValue('Calculated Value', 'calculateValue', 'calculateValue', 1100, '<p><h4>Example:</h4><pre>value = data.a + data.b + data.c;</pre></p>', '<p><h4>Example:</h4><pre>{"+": [{"var": "data.a"}, {"var": "data.b"}, {"var": "data.c"}]}</pre><p><a href="https://help.form.io/userguide/form-building/logic-and-conditions#calculated-values" target="_blank" rel="noopener noreferrer">Click here for an example</a></p>', utils_1.default.tokenVariableDescription()),
|
|
148
148
|
{
|
|
149
149
|
type: 'checkbox',
|
|
150
150
|
input: true,
|
|
@@ -2,6 +2,7 @@ export default EditFormUtils;
|
|
|
2
2
|
declare namespace EditFormUtils {
|
|
3
3
|
function sortAndFilterComponents(components: any): any;
|
|
4
4
|
function unifyComponents(objValue: any, srcValue: any): any;
|
|
5
|
+
function tokenVariableDescription(): string;
|
|
5
6
|
function logicVariablesTable(additional: any): {
|
|
6
7
|
type: string;
|
|
7
8
|
tag: string;
|
|
@@ -37,6 +37,9 @@ const EditFormUtils = {
|
|
|
37
37
|
}
|
|
38
38
|
return lodash_1.default.isEqual(objValue, srcValue);
|
|
39
39
|
},
|
|
40
|
+
tokenVariableDescription() {
|
|
41
|
+
return '<tr><th>token</th><td>The decoded JWT token for the authenticated user.</td></tr>';
|
|
42
|
+
},
|
|
40
43
|
logicVariablesTable(additional) {
|
|
41
44
|
additional = additional || '';
|
|
42
45
|
return {
|
|
@@ -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
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
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.
|
|
@@ -265,6 +265,8 @@ class AddressComponent extends Container_1.default {
|
|
|
265
265
|
this.restoreComponentsContext();
|
|
266
266
|
}
|
|
267
267
|
if (changed || (!lodash_1.default.isEmpty(value) && flags.fromSubmission)) {
|
|
268
|
+
// Recheck conditions on child components before redraw so their visibility is updated
|
|
269
|
+
this.getComponents().forEach((comp) => { var _a; return comp.checkConditions((_a = this.root) === null || _a === void 0 ? void 0 : _a.data); });
|
|
268
270
|
this.redraw();
|
|
269
271
|
}
|
|
270
272
|
return changed;
|
|
@@ -29,6 +29,7 @@ export default class ButtonComponent extends Field {
|
|
|
29
29
|
detach(element: any): void;
|
|
30
30
|
onClick(event: any): void;
|
|
31
31
|
openOauth(settings: any): void;
|
|
32
|
+
_handleOauthSessionExpired(): void;
|
|
32
33
|
get oauthComponentPath(): any;
|
|
33
34
|
focus(): void;
|
|
34
35
|
triggerCaptcha(): void;
|
|
@@ -371,6 +371,12 @@ class ButtonComponent extends Field_1.default {
|
|
|
371
371
|
}
|
|
372
372
|
openOauth(settings) {
|
|
373
373
|
var _a;
|
|
374
|
+
// this is if the temp session (storing the state and code verifiers) expires in the db
|
|
375
|
+
// and we need to fetch new oauth state
|
|
376
|
+
if (settings.sessionExpireAt && Date.now() >= settings.sessionExpireAt) {
|
|
377
|
+
this._handleOauthSessionExpired();
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
374
380
|
if (!((_a = this.root) === null || _a === void 0 ? void 0 : _a.formio)) {
|
|
375
381
|
console.warn('You must attach a Form API url to your form in order to use OAuth buttons.');
|
|
376
382
|
return;
|
|
@@ -386,7 +392,8 @@ class ButtonComponent extends Field_1.default {
|
|
|
386
392
|
if (settings.state) {
|
|
387
393
|
params.state = settings.state;
|
|
388
394
|
}
|
|
389
|
-
|
|
395
|
+
// okta requires both a state and a code challenge for PKCE
|
|
396
|
+
if (settings.code_challenge) {
|
|
390
397
|
params.code_challenge = settings.code_challenge;
|
|
391
398
|
params.code_challenge_method = 'S256';
|
|
392
399
|
}
|
|
@@ -429,6 +436,9 @@ class ButtonComponent extends Field_1.default {
|
|
|
429
436
|
(_b = this.root) === null || _b === void 0 ? void 0 : _b.setAlert('danger', 'OAuth state does not match. Please try logging in again.');
|
|
430
437
|
return;
|
|
431
438
|
}
|
|
439
|
+
if (settings.sessionId) {
|
|
440
|
+
params.sessionId = settings.sessionId;
|
|
441
|
+
}
|
|
432
442
|
// Depending on where the settings came from, submit to either the submission endpoint (old) or oauth endpoint (new).
|
|
433
443
|
let requestPromise = Promise.resolve();
|
|
434
444
|
if (lodash_1.default.has(this, 'root.form.config.oauth') &&
|
|
@@ -457,6 +467,11 @@ class ButtonComponent extends Field_1.default {
|
|
|
457
467
|
})
|
|
458
468
|
.catch((err) => {
|
|
459
469
|
var _a;
|
|
470
|
+
console.log(err);
|
|
471
|
+
if (settings.sessionExpireAt && Date.now() >= settings.sessionExpireAt) {
|
|
472
|
+
this._handleOauthSessionExpired();
|
|
473
|
+
return;
|
|
474
|
+
}
|
|
460
475
|
(_a = this.root) === null || _a === void 0 ? void 0 : _a.onSubmissionError(err);
|
|
461
476
|
});
|
|
462
477
|
}
|
|
@@ -472,6 +487,12 @@ class ButtonComponent extends Field_1.default {
|
|
|
472
487
|
}
|
|
473
488
|
}, 100);
|
|
474
489
|
}
|
|
490
|
+
_handleOauthSessionExpired() {
|
|
491
|
+
var _a;
|
|
492
|
+
(_a = this.root) === null || _a === void 0 ? void 0 : _a.setAlert('warning', this.t('oauthSessionExpired'));
|
|
493
|
+
this.loading = true;
|
|
494
|
+
setTimeout(() => window.location.reload(), 2000);
|
|
495
|
+
}
|
|
475
496
|
get oauthComponentPath() {
|
|
476
497
|
const pathArray = (0, utils_1.getArrayFromComponentPath)(this.path);
|
|
477
498
|
return lodash_1.default.chain(pathArray)
|
|
@@ -446,18 +446,26 @@ class DataGridComponent extends NestedArrayComponent_1.default {
|
|
|
446
446
|
component: this.component,
|
|
447
447
|
row,
|
|
448
448
|
});
|
|
449
|
-
(0, utils_1.screenReaderSpeech)('Row has been added');
|
|
450
449
|
this.checkConditions();
|
|
451
450
|
(_a = this.triggerChange) === null || _a === void 0 ? void 0 : _a.call(this, { modified: true, noPristineChangeOnModified: true });
|
|
452
451
|
this.redraw().then(() => {
|
|
453
452
|
this.focusOnNewRowElement(this.rows[index]);
|
|
453
|
+
this.announce(this.t('Row has been added'));
|
|
454
454
|
});
|
|
455
455
|
}
|
|
456
456
|
updateComponentsRowIndex(components, rowIndex) {
|
|
457
457
|
components.forEach((component, colIndex) => {
|
|
458
458
|
var _a;
|
|
459
|
-
|
|
460
|
-
|
|
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
|
-
|
|
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) {
|
|
@@ -478,15 +493,14 @@ class DataGridComponent extends NestedArrayComponent_1.default {
|
|
|
478
493
|
const flags = { isReordered: !makeEmpty, resetValue: makeEmpty };
|
|
479
494
|
this.splice(index, flags);
|
|
480
495
|
this.emit('dataGridDeleteRow', { index });
|
|
481
|
-
if (this.rows.length > 1) {
|
|
482
|
-
(0, utils_1.screenReaderSpeech)('Row has been deleted');
|
|
483
|
-
}
|
|
484
496
|
const [row,] = this.rows.splice(index, 1);
|
|
485
497
|
this.removeSubmissionMetadataRow(index);
|
|
486
498
|
this.removeRowComponents(row);
|
|
487
499
|
this.updateRowsComponents(index);
|
|
488
500
|
this.setValue(this.dataValue, flags);
|
|
489
|
-
this.redraw()
|
|
501
|
+
this.redraw().then(() => {
|
|
502
|
+
this.announce(this.t('Row has been deleted'));
|
|
503
|
+
});
|
|
490
504
|
}
|
|
491
505
|
removeRowComponents(row) {
|
|
492
506
|
lodash_1.default.each(row, (component) => this.removeComponent(component));
|
|
@@ -537,8 +551,9 @@ class DataGridComponent extends NestedArrayComponent_1.default {
|
|
|
537
551
|
options.rowIndex = rowIndex;
|
|
538
552
|
options.onChange = (flags, changed, modified) => {
|
|
539
553
|
var _a, _b, _c, _d;
|
|
540
|
-
|
|
541
|
-
|
|
554
|
+
const changedComponent = changed.component;
|
|
555
|
+
if ((changedComponent === null || changedComponent === void 0 ? void 0 : changedComponent.type) === 'form' && (changedComponent === null || changedComponent === void 0 ? void 0 : changedComponent.key)) {
|
|
556
|
+
const formComp = (0, utils_1.getComponent)(this.component.components, changedComponent.key);
|
|
542
557
|
lodash_1.default.set(formComp, 'components', changed.component.components);
|
|
543
558
|
}
|
|
544
559
|
// If we're in a nested form we need to ensure our changes are triggered upstream
|
|
@@ -546,8 +561,18 @@ class DataGridComponent extends NestedArrayComponent_1.default {
|
|
|
546
561
|
(_d = (_c = changed.instance.root).triggerChange) === null || _d === void 0 ? void 0 : _d.call(_c, flags, changed, modified);
|
|
547
562
|
}
|
|
548
563
|
else {
|
|
564
|
+
if (modified && !flags.noPristineChangeOnModified) {
|
|
565
|
+
this.pristine = false;
|
|
566
|
+
}
|
|
567
|
+
this.triggerRootChange(flags, {
|
|
568
|
+
instance: this,
|
|
569
|
+
component: this.component,
|
|
570
|
+
value: this.dataValue,
|
|
571
|
+
flags,
|
|
572
|
+
}, modified);
|
|
549
573
|
this.triggerRootChange(flags, changed, modified);
|
|
550
574
|
}
|
|
575
|
+
this.processRow('checkData', null, Object.assign(Object.assign({}, flags), { changed }), row, lodash_1.default.toArray(this.rows[rowIndex]));
|
|
551
576
|
};
|
|
552
577
|
let columnComponent;
|
|
553
578
|
if (this.builderMode) {
|
|
@@ -15,14 +15,11 @@ export default class DataMapComponent extends DataGridComponent {
|
|
|
15
15
|
disableBuilderActions: boolean;
|
|
16
16
|
};
|
|
17
17
|
get valueKey(): any;
|
|
18
|
-
get iteratableRows(): {
|
|
19
|
-
components: any;
|
|
20
|
-
data: any;
|
|
21
|
-
}[][];
|
|
22
18
|
hasHeader(): boolean;
|
|
23
19
|
getRowKey(rowIndex: any): string;
|
|
24
20
|
get defaultRowKey(): string;
|
|
25
21
|
getValueAsString(value: any, options: any): any;
|
|
22
|
+
findComponentInstance(key: any): any;
|
|
26
23
|
createRowComponents(row: any, rowIndex: any): {
|
|
27
24
|
__key: any;
|
|
28
25
|
};
|
|
@@ -123,15 +123,14 @@ class DataMapComponent extends DataGrid_1.default {
|
|
|
123
123
|
}
|
|
124
124
|
get iteratableRows() {
|
|
125
125
|
return this.rows.map((row) => {
|
|
126
|
-
return
|
|
127
|
-
components: row
|
|
128
|
-
data: row
|
|
129
|
-
}
|
|
126
|
+
return {
|
|
127
|
+
components: row,
|
|
128
|
+
data: lodash_1.default.mapValues(row, (comp) => comp.dataValue)
|
|
129
|
+
};
|
|
130
130
|
});
|
|
131
131
|
}
|
|
132
132
|
componentContext(component) {
|
|
133
|
-
return this.iteratableRows[component.row].
|
|
134
|
-
.data;
|
|
133
|
+
return this.iteratableRows[component.row].data[component.key];
|
|
135
134
|
}
|
|
136
135
|
hasHeader() {
|
|
137
136
|
return true;
|
|
@@ -186,10 +185,14 @@ class DataMapComponent extends DataGrid_1.default {
|
|
|
186
185
|
<tbody>
|
|
187
186
|
`;
|
|
188
187
|
result = Object.keys(value).reduce((result, key) => {
|
|
188
|
+
const componentInstance = this.findComponentInstance(key);
|
|
189
|
+
const viewValue = componentInstance
|
|
190
|
+
? componentInstance.getView(value[key], options)
|
|
191
|
+
: this.getView(value[key], options);
|
|
189
192
|
result += `
|
|
190
193
|
<tr>
|
|
191
194
|
<th style="padding: 5px 10px;">${key}</th>
|
|
192
|
-
<td style="width:100%;padding:5px 10px;">${
|
|
195
|
+
<td style="width:100%;padding:5px 10px;">${viewValue}</td>
|
|
193
196
|
</tr>
|
|
194
197
|
`;
|
|
195
198
|
return result;
|
|
@@ -209,6 +212,19 @@ class DataMapComponent extends DataGrid_1.default {
|
|
|
209
212
|
}
|
|
210
213
|
return typeof value === 'object' ? '[Complex Data]' : value;
|
|
211
214
|
}
|
|
215
|
+
findComponentInstance(key) {
|
|
216
|
+
var _a;
|
|
217
|
+
if (!this.rows || !this.rows.length) {
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
220
|
+
// Find component instance with matching key
|
|
221
|
+
const foundRow = lodash_1.default.find(this.rows, (row) => { var _a; return ((_a = row === null || row === void 0 ? void 0 : row[this.valueKey]) === null || _a === void 0 ? void 0 : _a.key) === key; });
|
|
222
|
+
if (foundRow === null || foundRow === void 0 ? void 0 : foundRow[this.valueKey]) {
|
|
223
|
+
return foundRow[this.valueKey];
|
|
224
|
+
}
|
|
225
|
+
// If not found by key, return the first row's value component as fallback
|
|
226
|
+
return ((_a = this.rows[0]) === null || _a === void 0 ? void 0 : _a[this.valueKey]) || null;
|
|
227
|
+
}
|
|
212
228
|
getDataValueAsTable(value, options) {
|
|
213
229
|
let result = `
|
|
214
230
|
<table border="1" style="width:100%">
|
|
@@ -216,10 +232,14 @@ class DataMapComponent extends DataGrid_1.default {
|
|
|
216
232
|
`;
|
|
217
233
|
if (this.visible && lodash_1.default.isObject(value)) {
|
|
218
234
|
Object.keys(value).forEach((key) => {
|
|
235
|
+
const componentInstance = this.findComponentInstance(key);
|
|
236
|
+
const viewValue = componentInstance
|
|
237
|
+
? componentInstance.getView(value[key], options)
|
|
238
|
+
: this.getView(value[key], options);
|
|
219
239
|
result += `
|
|
220
240
|
<tr>
|
|
221
241
|
<th style="padding: 5px 10px;">${key}</th>
|
|
222
|
-
<td style="width:100%;padding:5px 10px;">${
|
|
242
|
+
<td style="width:100%;padding:5px 10px;">${viewValue}</td>
|
|
223
243
|
</tr>
|
|
224
244
|
`;
|
|
225
245
|
});
|
|
@@ -254,9 +274,21 @@ class DataMapComponent extends DataGrid_1.default {
|
|
|
254
274
|
});
|
|
255
275
|
const valueComponent = lodash_1.default.clone(this.component.valueComponent);
|
|
256
276
|
valueComponent.key = key;
|
|
257
|
-
const componentOptions = this.options;
|
|
277
|
+
const componentOptions = lodash_1.default.clone(this.options);
|
|
258
278
|
componentOptions.row = options.row;
|
|
259
|
-
|
|
279
|
+
if (this.submissionTimezone) {
|
|
280
|
+
componentOptions.submissionTimezone = this.submissionTimezone;
|
|
281
|
+
if (valueComponent.type === 'datetime') {
|
|
282
|
+
valueComponent.widget = Object.assign(Object.assign({}, valueComponent.widget), { submissionTimezone: this.submissionTimezone });
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
const createdComponent = this.createComponent(valueComponent, componentOptions, this.dataValue);
|
|
286
|
+
// Ensure submissionTimezone is set on datetime component instance's widget and options
|
|
287
|
+
if ((createdComponent === null || createdComponent === void 0 ? void 0 : createdComponent.type) === 'datetime' && this.submissionTimezone) {
|
|
288
|
+
createdComponent.component.widget = Object.assign(Object.assign({}, createdComponent.component.widget), { submissionTimezone: this.submissionTimezone });
|
|
289
|
+
createdComponent.options.submissionTimezone = this.submissionTimezone;
|
|
290
|
+
}
|
|
291
|
+
components[this.valueKey] = createdComponent;
|
|
260
292
|
return components;
|
|
261
293
|
}
|
|
262
294
|
get canAddColumn() {
|