@formio/js 5.3.6 → 5.4.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 (132) hide show
  1. package/dist/formio.builder.css +31 -5
  2. package/dist/formio.builder.min.css +1 -1
  3. package/dist/formio.embed.css +1 -1
  4. package/dist/formio.embed.js +1 -1
  5. package/dist/formio.embed.min.css +1 -1
  6. package/dist/formio.embed.min.js +1 -1
  7. package/dist/formio.embed.min.js.LICENSE.txt +1 -1
  8. package/dist/formio.form.css +31 -5
  9. package/dist/formio.form.js +2837 -2818
  10. package/dist/formio.form.min.css +1 -1
  11. package/dist/formio.form.min.js +1 -1
  12. package/dist/formio.form.min.js.LICENSE.txt +1 -1
  13. package/dist/formio.full.css +31 -5
  14. package/dist/formio.full.js +3442 -3403
  15. package/dist/formio.full.min.css +1 -1
  16. package/dist/formio.full.min.js +1 -1
  17. package/dist/formio.full.min.js.LICENSE.txt +1 -1
  18. package/dist/formio.js +1152 -1154
  19. package/dist/formio.min.js +1 -1
  20. package/dist/formio.min.js.LICENSE.txt +1 -1
  21. package/dist/formio.utils.js +1084 -1086
  22. package/dist/formio.utils.min.js +1 -1
  23. package/dist/formio.utils.min.js.LICENSE.txt +1 -1
  24. package/lib/cjs/Embed.js +28 -1
  25. package/lib/cjs/Form.d.ts +4 -2
  26. package/lib/cjs/Form.js +2 -2
  27. package/lib/cjs/FormBuilder.d.ts +2 -2
  28. package/lib/cjs/FormBuilder.js +1 -1
  29. package/lib/cjs/Formio.js +1 -1
  30. package/lib/cjs/PDF.js +2 -0
  31. package/lib/cjs/PDFBuilder.js +6 -1
  32. package/lib/cjs/Webform.d.ts +1 -0
  33. package/lib/cjs/Webform.js +50 -1
  34. package/lib/cjs/WebformBuilder.js +29 -1
  35. package/lib/cjs/Wizard.d.ts +1 -0
  36. package/lib/cjs/Wizard.js +11 -0
  37. package/lib/cjs/components/Components.d.ts +3 -0
  38. package/lib/cjs/components/_classes/component/Component.d.ts +13 -3
  39. package/lib/cjs/components/_classes/component/Component.js +167 -47
  40. package/lib/cjs/components/_classes/component/editForm/Component.edit.conditional.js +1 -1
  41. package/lib/cjs/components/_classes/component/editForm/Component.edit.data.d.ts +7 -0
  42. package/lib/cjs/components/_classes/component/editForm/Component.edit.data.js +2 -1
  43. package/lib/cjs/components/_classes/component/editForm/utils.d.ts +1 -0
  44. package/lib/cjs/components/_classes/component/editForm/utils.js +3 -0
  45. package/lib/cjs/components/_classes/nested/NestedComponent.js +5 -0
  46. package/lib/cjs/components/address/Address.js +18 -0
  47. package/lib/cjs/components/datagrid/DataGrid.js +12 -2
  48. package/lib/cjs/components/datamap/DataMap.d.ts +1 -0
  49. package/lib/cjs/components/datamap/DataMap.js +37 -4
  50. package/lib/cjs/components/datetime/DateTime.js +11 -1
  51. package/lib/cjs/components/day/Day.d.ts +0 -15
  52. package/lib/cjs/components/day/Day.js +8 -17
  53. package/lib/cjs/components/editgrid/EditGrid.js +11 -1
  54. package/lib/cjs/components/fieldset/Fieldset.js +1 -0
  55. package/lib/cjs/components/file/File.d.ts +3 -1
  56. package/lib/cjs/components/file/File.js +62 -17
  57. package/lib/cjs/components/form/Form.js +3 -1
  58. package/lib/cjs/components/number/Number.d.ts +1 -0
  59. package/lib/cjs/components/number/Number.js +18 -0
  60. package/lib/cjs/components/select/Select.js +5 -1
  61. package/lib/cjs/components/signature/Signature.js +5 -5
  62. package/lib/cjs/components/signature/editForm/Signature.edit.display.d.ts +0 -6
  63. package/lib/cjs/components/signature/editForm/Signature.edit.display.js +0 -1
  64. package/lib/cjs/components/table/editForm/Table.edit.display.d.ts +27 -0
  65. package/lib/cjs/components/table/editForm/Table.edit.display.js +10 -0
  66. package/lib/cjs/formio.form.js +2 -5
  67. package/lib/cjs/package.json +1 -1
  68. package/lib/cjs/providers/storage/azure.js +9 -3
  69. package/lib/cjs/templates/index.d.ts +3 -0
  70. package/lib/cjs/translations/en.d.ts +2 -0
  71. package/lib/cjs/translations/en.js +2 -0
  72. package/lib/cjs/utils/i18n.d.ts +1 -0
  73. package/lib/cjs/utils/i18n.js +2 -0
  74. package/lib/cjs/utils/index.d.ts +1 -1
  75. package/lib/cjs/utils/utils.d.ts +1 -1
  76. package/lib/cjs/utils/utils.js +23 -6
  77. package/lib/cjs/widgets/CalendarWidget.js +1 -1
  78. package/lib/mjs/Embed.js +26 -1
  79. package/lib/mjs/Form.d.ts +4 -2
  80. package/lib/mjs/Form.js +2 -2
  81. package/lib/mjs/FormBuilder.d.ts +2 -2
  82. package/lib/mjs/FormBuilder.js +1 -1
  83. package/lib/mjs/Formio.js +1 -1
  84. package/lib/mjs/PDF.js +2 -0
  85. package/lib/mjs/PDFBuilder.js +6 -1
  86. package/lib/mjs/Webform.d.ts +1 -0
  87. package/lib/mjs/Webform.js +48 -1
  88. package/lib/mjs/WebformBuilder.js +28 -1
  89. package/lib/mjs/Wizard.d.ts +1 -0
  90. package/lib/mjs/Wizard.js +12 -1
  91. package/lib/mjs/components/Components.d.ts +3 -0
  92. package/lib/mjs/components/_classes/component/Component.d.ts +13 -3
  93. package/lib/mjs/components/_classes/component/Component.js +164 -46
  94. package/lib/mjs/components/_classes/component/editForm/Component.edit.conditional.js +1 -1
  95. package/lib/mjs/components/_classes/component/editForm/Component.edit.data.d.ts +7 -0
  96. package/lib/mjs/components/_classes/component/editForm/Component.edit.data.js +2 -1
  97. package/lib/mjs/components/_classes/component/editForm/utils.d.ts +1 -0
  98. package/lib/mjs/components/_classes/component/editForm/utils.js +3 -0
  99. package/lib/mjs/components/_classes/nested/NestedComponent.js +5 -0
  100. package/lib/mjs/components/address/Address.js +17 -0
  101. package/lib/mjs/components/datagrid/DataGrid.js +14 -1
  102. package/lib/mjs/components/datamap/DataMap.d.ts +1 -0
  103. package/lib/mjs/components/datamap/DataMap.js +36 -4
  104. package/lib/mjs/components/datetime/DateTime.js +11 -1
  105. package/lib/mjs/components/day/Day.d.ts +0 -15
  106. package/lib/mjs/components/day/Day.js +8 -17
  107. package/lib/mjs/components/editgrid/EditGrid.js +11 -1
  108. package/lib/mjs/components/fieldset/Fieldset.js +1 -0
  109. package/lib/mjs/components/file/File.d.ts +3 -1
  110. package/lib/mjs/components/file/File.js +60 -15
  111. package/lib/mjs/components/form/Form.js +3 -1
  112. package/lib/mjs/components/number/Number.d.ts +1 -0
  113. package/lib/mjs/components/number/Number.js +17 -0
  114. package/lib/mjs/components/select/Select.js +5 -1
  115. package/lib/mjs/components/signature/Signature.js +1 -1
  116. package/lib/mjs/components/signature/editForm/Signature.edit.display.d.ts +0 -6
  117. package/lib/mjs/components/signature/editForm/Signature.edit.display.js +0 -1
  118. package/lib/mjs/components/table/editForm/Table.edit.display.d.ts +27 -0
  119. package/lib/mjs/components/table/editForm/Table.edit.display.js +10 -0
  120. package/lib/mjs/formio.form.js +4 -7
  121. package/lib/mjs/package.json +1 -1
  122. package/lib/mjs/providers/storage/azure.js +9 -3
  123. package/lib/mjs/templates/index.d.ts +3 -0
  124. package/lib/mjs/translations/en.d.ts +2 -0
  125. package/lib/mjs/translations/en.js +2 -0
  126. package/lib/mjs/utils/i18n.d.ts +1 -0
  127. package/lib/mjs/utils/i18n.js +2 -0
  128. package/lib/mjs/utils/index.d.ts +1 -1
  129. package/lib/mjs/utils/utils.d.ts +1 -1
  130. package/lib/mjs/utils/utils.js +22 -6
  131. package/lib/mjs/widgets/CalendarWidget.js +2 -2
  132. package/package.json +8 -6
@@ -145,7 +145,7 @@ class Component extends Element_1.default {
145
145
  unique: false,
146
146
  },
147
147
  /**
148
- * The simple conditional settings for a component.
148
+ * the simple conditional settings for a component.
149
149
  */
150
150
  conditional: {
151
151
  show: null,
@@ -464,6 +464,16 @@ class Component extends Element_1.default {
464
464
  }
465
465
  return false;
466
466
  }
467
+ hasCondionallyHiddenLayoutParent() {
468
+ let currentParent = this.parent;
469
+ while (currentParent) {
470
+ if (currentParent._conditionallyHidden && utils_1.default.isLayoutComponent(currentParent) && currentParent.component.clearOnHide === true) {
471
+ return true;
472
+ }
473
+ currentParent = currentParent.parent;
474
+ }
475
+ return false;
476
+ }
467
477
  parentConditionallyHidden() {
468
478
  let currentParent = this.parent;
469
479
  while (currentParent) {
@@ -740,7 +750,7 @@ class Component extends Element_1.default {
740
750
  this._conditionallyClear = true;
741
751
  return this._conditionallyClear;
742
752
  }
743
- this._conditionallyClear = this.hasSetValue ? false : this.parentShouldConditionallyClear();
753
+ this._conditionallyClear = this.hasSetValue ? this.hasCondionallyHiddenLayoutParent() : this.parentShouldConditionallyClear();
744
754
  return this._conditionallyClear;
745
755
  }
746
756
  /**
@@ -995,8 +1005,20 @@ class Component extends Element_1.default {
995
1005
  return this.options.renderMode === 'html';
996
1006
  }
997
1007
  renderTemplate(name, data = {}, modeOption = '') {
998
- // Need to make this fall back to form if renderMode is not found similar to how we search templates.
1008
+ // Allow more specific template names
1009
+ const names = [
1010
+ `${name}-${this.component.type}-${this.key}`,
1011
+ `${name}-${this.component.type}`,
1012
+ `${name}-${this.key}`,
1013
+ `${name}`,
1014
+ ];
1015
+ // Allow template alters.
999
1016
  const mode = modeOption || this.options.renderMode || 'form';
1017
+ const { referenceAttributeName, template } = this.getTemplate(names, mode);
1018
+ if (referenceAttributeName) {
1019
+ this._referenceAttributeName = referenceAttributeName;
1020
+ }
1021
+ // Need to make this fall back to form if renderMode is not found similar to how we search templates.
1000
1022
  data.component = this.component;
1001
1023
  data.self = this;
1002
1024
  data.options = this.options;
@@ -1018,18 +1040,7 @@ class Component extends Element_1.default {
1018
1040
  };
1019
1041
  data.label = data.labelInfo || this.labelInfo;
1020
1042
  data.tooltip = this.getFormattedTooltip(this.component.tooltip);
1021
- // Allow more specific template names
1022
- const names = [
1023
- `${name}-${this.component.type}-${this.key}`,
1024
- `${name}-${this.component.type}`,
1025
- `${name}-${this.key}`,
1026
- `${name}`,
1027
- ];
1028
- // Allow template alters.
1029
- const { referenceAttributeName, template } = this.getTemplate(names, mode);
1030
- if (referenceAttributeName) {
1031
- this._referenceAttributeName = referenceAttributeName;
1032
- }
1043
+ data.customStyles = this.getCustomStyles(names);
1033
1044
  return this.hook(`render${name.charAt(0).toUpperCase() + name.substring(1, name.length)}`, this.interpolate(template, data), data, mode);
1034
1045
  }
1035
1046
  /**
@@ -1141,9 +1152,12 @@ class Component extends Element_1.default {
1141
1152
  * @returns {string} - The submission timezone.
1142
1153
  */
1143
1154
  get submissionTimezone() {
1144
- this.options.submissionTimezone =
1145
- this.options.submissionTimezone || lodash_1.default.get(this.root, 'options.submissionTimezone');
1146
- return this.options.submissionTimezone;
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'));
1147
1161
  }
1148
1162
  /**
1149
1163
  * Return the current timezone.
@@ -1158,6 +1172,7 @@ class Component extends Element_1.default {
1158
1172
  * @returns {string} - The current timezone.
1159
1173
  */
1160
1174
  getTimezone(settings) {
1175
+ settings = settings || {};
1161
1176
  if (settings.timezone) {
1162
1177
  return settings.timezone;
1163
1178
  }
@@ -1165,12 +1180,19 @@ class Component extends Element_1.default {
1165
1180
  return 'UTC';
1166
1181
  }
1167
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;
1168
1192
  if (submissionTimezone &&
1169
- (settings.displayInTimezone === 'submission' ||
1170
- ((this.options.pdf || this.options.server) && settings.displayInTimezone === 'viewer'))) {
1193
+ (mode === 'submission' || (staticSnapshot && (mode === 'viewer' || mode === 'location')))) {
1171
1194
  return submissionTimezone;
1172
1195
  }
1173
- // Return current timezone if none are provided.
1174
1196
  return (0, utils_2.currentTimezone)();
1175
1197
  }
1176
1198
  /**
@@ -1663,6 +1685,7 @@ class Component extends Element_1.default {
1663
1685
  * @returns {HTMLElement} - The created modal element.
1664
1686
  */
1665
1687
  createModal(element, attr, confirm) {
1688
+ var _a;
1666
1689
  const dialog = this.ce('div', attr || {});
1667
1690
  this.setContent(dialog, this.renderTemplate('dialog'));
1668
1691
  // Add refs to dialog, not "this".
@@ -1672,14 +1695,27 @@ class Component extends Element_1.default {
1672
1695
  dialogContents: 'single',
1673
1696
  dialogClose: 'single',
1674
1697
  });
1698
+ // Check if an element is inside shadow dom
1699
+ const isInShadowDOM = typeof ShadowRoot !== 'undefined' && ((_a = this.element) === null || _a === void 0 ? void 0 : _a.getRootNode()) instanceof ShadowRoot;
1700
+ // if we render shadow dom inside <iframe>'s we need to get the body from the current iframe,
1701
+ // not the general body. This is necessary to hide and show the scroll bar correctly.
1702
+ const body = isInShadowDOM ? this.element.getRootNode().host.ownerDocument.body : document.body;
1703
+ const rootEl = isInShadowDOM ? this.element.closest('.formio-form-wrapper') : document.body;
1704
+ const checkModal = (method) => {
1705
+ if (isInShadowDOM) {
1706
+ body.style.overflow = method === 'add' ? 'hidden' : '';
1707
+ return;
1708
+ }
1709
+ body.classList[method]('modal-open');
1710
+ };
1675
1711
  dialog.refs.dialogContents.appendChild(element);
1676
- document.body.appendChild(dialog);
1677
- document.body.classList.add('modal-open');
1712
+ rootEl.appendChild(dialog);
1713
+ checkModal('add');
1678
1714
  dialog.close = () => {
1679
- document.body.classList.remove('modal-open');
1715
+ checkModal('remove');
1680
1716
  dialog.dispatchEvent(new CustomEvent('close'));
1681
1717
  };
1682
- this.addEventListener(dialog, 'close', () => this.removeChildFrom(dialog, document.body));
1718
+ this.addEventListener(dialog, 'close', () => this.removeChildFrom(dialog, rootEl));
1683
1719
  const close = (event) => {
1684
1720
  event.preventDefault();
1685
1721
  dialog.close();
@@ -1750,6 +1786,21 @@ class Component extends Element_1.default {
1750
1786
  });
1751
1787
  return customCSS;
1752
1788
  }
1789
+ /**
1790
+ * Build custom styles from the styles form option or global config.
1791
+ * @param {string[]} templateNames - The possible template names.
1792
+ * @returns {{ [refName: string]: string[] }} - The custom styles object for the named template.
1793
+ * @todo - Rename this to a better method name that doesn't clash
1794
+ */
1795
+ getCustomStyles(templateNames) {
1796
+ var _a;
1797
+ for (const name of templateNames) {
1798
+ if ((_a = this.options.styles) === null || _a === void 0 ? void 0 : _a[name]) {
1799
+ return this.options.styles[name];
1800
+ }
1801
+ }
1802
+ return {};
1803
+ }
1753
1804
  /**
1754
1805
  * Returns the component condition operator settings if available.
1755
1806
  * @returns {object} - The component condition operator settings.
@@ -2527,6 +2578,20 @@ class Component extends Element_1.default {
2527
2578
  return Promise.resolve(editor);
2528
2579
  }
2529
2580
  else {
2581
+ // Due to an issue with ckeditor not loading styles in the shadowdom (https://github.com/ckeditor/ckeditor5/issues/15824), we need to copy cke-styles to the shadowdom
2582
+ let current = element;
2583
+ while (current) {
2584
+ if (current instanceof ShadowRoot) {
2585
+ const ckeStyles = document.querySelector('style[data-cke="true"]');
2586
+ const clone = document.createElement('style');
2587
+ clone.setAttribute('data-cke', 'true');
2588
+ clone.textContent = ckeStyles.textContent;
2589
+ current.prepend(clone);
2590
+ break;
2591
+ }
2592
+ ;
2593
+ current = current.parentNode || current.host;
2594
+ }
2530
2595
  return ClassicEditor.create(element, settings).then((editor) => {
2531
2596
  editor.model.document.on('change', () => onChange(editor.data.get()));
2532
2597
  return editor;
@@ -2543,12 +2608,61 @@ class Component extends Element_1.default {
2543
2608
  { type: 'styles', src: `${Formio_1.Formio.cdn.quill}/quill.${settings.theme}.css` },
2544
2609
  ], true);
2545
2610
  // Lazy load the quill library.
2546
- return Formio_1.Formio.requireLibrary('quill', 'Quill', lodash_1.default.get(this.options, 'editors.quill.src', `${Formio_1.Formio.cdn.quill}/quill.min.js`), true).then(() => {
2611
+ 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(() => {
2547
2612
  return Formio_1.Formio.requireLibrary('quill-table', 'Quill', `${Formio_1.Formio.cdn.baseUrl}/quill/quill-table.js`, true).then(() => {
2548
2613
  if (!element.parentNode) {
2549
2614
  return Promise.reject();
2550
2615
  }
2551
2616
  this.quill = new Quill(element, isIEBrowser ? Object.assign(Object.assign({}, settings), { modules: {} }) : settings);
2617
+ const root = element.getRootNode();
2618
+ if (root instanceof ShadowRoot && root.getSelection) {
2619
+ const sel = this.quill.selection;
2620
+ // 1. getNativeRange: read selection from shadowRoot instead of document
2621
+ sel.getNativeRange = () => {
2622
+ const shadowSelection = root.getSelection();
2623
+ if (shadowSelection == null || shadowSelection.rangeCount <= 0)
2624
+ return null;
2625
+ const nativeRange = shadowSelection.getRangeAt(0);
2626
+ if (nativeRange == null)
2627
+ return null;
2628
+ return sel.normalizeNative(nativeRange);
2629
+ };
2630
+ // 2. hasFocus: check shadowRoot.activeElement instead of document.activeElement
2631
+ sel.hasFocus = () => {
2632
+ return root.activeElement === sel.root ||
2633
+ (root.activeElement != null && sel.root.contains(root.activeElement));
2634
+ };
2635
+ // 3. setNativeRange: use shadowRoot's selection to add/remove ranges
2636
+ const origSetNativeRange = sel.setNativeRange.bind(sel);
2637
+ sel.setNativeRange = (startNode, startOffset, endNode, endOffset, force) => {
2638
+ // Delegate to original logic for the null case (blur)
2639
+ if (startNode == null) {
2640
+ origSetNativeRange(null);
2641
+ return;
2642
+ }
2643
+ if (!sel.hasFocus()) {
2644
+ sel.root.focus({ preventScroll: true });
2645
+ }
2646
+ const shadowSelection = root.getSelection();
2647
+ if (shadowSelection == null)
2648
+ return;
2649
+ const { native } = sel.getNativeRange() || {};
2650
+ endNode = endNode !== null && endNode !== void 0 ? endNode : startNode;
2651
+ endOffset = endOffset !== null && endOffset !== void 0 ? endOffset : startOffset;
2652
+ if (native == null || force ||
2653
+ startNode !== native.startContainer || startOffset !== native.startOffset ||
2654
+ endNode !== native.endContainer || endOffset !== native.endOffset) {
2655
+ const range = document.createRange();
2656
+ range.setStart(startNode, startOffset);
2657
+ range.setEnd(endNode, endOffset);
2658
+ shadowSelection.removeAllRanges();
2659
+ shadowSelection.addRange(range);
2660
+ }
2661
+ };
2662
+ document.addEventListener('selectionchange', () => {
2663
+ sel.update();
2664
+ });
2665
+ }
2552
2666
  /** This block of code adds the [source] capabilities. See https://codepen.io/anon/pen/ZyEjrQ */
2553
2667
  const txtArea = document.createElement('textarea');
2554
2668
  txtArea.setAttribute('class', 'quill-source-code');
@@ -2567,7 +2681,8 @@ class Component extends Element_1.default {
2567
2681
  // Make sure to select cursor when they click on the element.
2568
2682
  this.addEventListener(element, 'click', () => this.quill.focus());
2569
2683
  // Allows users to skip toolbar items when tabbing though form
2570
- const elm = document.querySelectorAll('.ql-formats > button');
2684
+ const queryRoot = element.getRootNode() || document;
2685
+ const elm = queryRoot.querySelectorAll('.ql-formats > button');
2571
2686
  for (let i = 0; i < elm.length; i++) {
2572
2687
  elm[i].setAttribute('tabindex', '-1');
2573
2688
  }
@@ -2581,7 +2696,7 @@ class Component extends Element_1.default {
2581
2696
  }
2582
2697
  get shouldSanitizeValue() {
2583
2698
  var _a;
2584
- // Sanitize value if sanitizing for thw whole content is turned off
2699
+ // Sanitize value if sanitizing for the whole content is turned off
2585
2700
  return ((_a = this.options) === null || _a === void 0 ? void 0 : _a.sanitize) !== false;
2586
2701
  }
2587
2702
  addAce(element, settings, onChange) {
@@ -2599,6 +2714,7 @@ class Component extends Element_1.default {
2599
2714
  editor.setOptions(settings);
2600
2715
  editor.getSession().setMode(settings.mode);
2601
2716
  editor.on('change', () => onChange(editor.getValue()));
2717
+ editor.renderer.attachToShadowRoot();
2602
2718
  if (settings.isUseWorkerDisabled) {
2603
2719
  editor.session.setUseWorker(false);
2604
2720
  }
@@ -2659,7 +2775,6 @@ class Component extends Element_1.default {
2659
2775
  return;
2660
2776
  }
2661
2777
  lodash_1.default.set(this._data, this.key, value);
2662
- return;
2663
2778
  }
2664
2779
  /**
2665
2780
  * Splice a value from the dataValue.
@@ -2707,9 +2822,9 @@ class Component extends Element_1.default {
2707
2822
  this.component.defaultValue !== undefined));
2708
2823
  }
2709
2824
  /**
2710
- * Determine if we should add a default value for this component.
2711
- * @returns {boolean} - TRUE if a default value should be set
2712
- */
2825
+ * Determine if we should add a default value for this component.
2826
+ * @returns {boolean} - TRUE if a default value should be set
2827
+ */
2713
2828
  get shouldAddDefaultValue() {
2714
2829
  return this.pristine && this.allowData && (this.hasDefaultValue || !this.options.noDefaults);
2715
2830
  }
@@ -3409,22 +3524,27 @@ class Component extends Element_1.default {
3409
3524
  }
3410
3525
  });
3411
3526
  this.addEventListener(element, 'blur', () => {
3412
- if (this.root) {
3413
- this.root.pendingBlur = utils_1.default.delay(() => {
3414
- var _a, _b;
3415
- this.emit('blur', this);
3416
- if (this.component.validateOn === 'blur') {
3417
- (_b = (_a = this.root).triggerChange) === null || _b === void 0 ? void 0 : _b.call(_a, { fromBlur: true }, {
3418
- instance: this,
3419
- component: this.component,
3420
- value: this.dataValue,
3421
- flags: { fromBlur: true },
3422
- });
3423
- }
3424
- this.root.focusedComponent = null;
3425
- this.root.pendingBlur = null;
3426
- });
3527
+ const root = this.root;
3528
+ if (!root) {
3529
+ return;
3427
3530
  }
3531
+ root.pendingBlur = utils_1.default.delay(() => {
3532
+ var _a;
3533
+ if (!root) {
3534
+ return;
3535
+ }
3536
+ this.emit('blur', this);
3537
+ if (this.component.validateOn === 'blur') {
3538
+ (_a = root.triggerChange) === null || _a === void 0 ? void 0 : _a.call(root, { fromBlur: true }, {
3539
+ instance: this,
3540
+ component: this.component,
3541
+ value: this.dataValue,
3542
+ flags: { fromBlur: true },
3543
+ });
3544
+ }
3545
+ root.focusedComponent = null;
3546
+ root.pendingBlur = null;
3547
+ });
3428
3548
  });
3429
3549
  }
3430
3550
  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
  ];
@@ -82,6 +82,7 @@ declare const _default: ({
82
82
  inline?: undefined;
83
83
  defaultValue?: undefined;
84
84
  values?: undefined;
85
+ customConditional?: undefined;
85
86
  logic?: undefined;
86
87
  dataSrc?: undefined;
87
88
  valueProperty?: undefined;
@@ -101,6 +102,7 @@ declare const _default: ({
101
102
  inline?: undefined;
102
103
  defaultValue?: undefined;
103
104
  values?: undefined;
105
+ customConditional?: undefined;
104
106
  logic?: undefined;
105
107
  dataSrc?: undefined;
106
108
  valueProperty?: undefined;
@@ -126,6 +128,7 @@ declare const _default: ({
126
128
  value: string;
127
129
  })[];
128
130
  placeholder?: undefined;
131
+ customConditional?: undefined;
129
132
  logic?: undefined;
130
133
  dataSrc?: undefined;
131
134
  valueProperty?: undefined;
@@ -141,6 +144,7 @@ declare const _default: ({
141
144
  tooltip: string;
142
145
  key: string;
143
146
  input: boolean;
147
+ customConditional: string;
144
148
  logic: ({
145
149
  name: string;
146
150
  trigger: {
@@ -211,6 +215,7 @@ declare const _default: ({
211
215
  inline?: undefined;
212
216
  defaultValue?: undefined;
213
217
  values?: undefined;
218
+ customConditional?: undefined;
214
219
  logic?: undefined;
215
220
  as?: undefined;
216
221
  editor?: undefined;
@@ -226,6 +231,7 @@ declare const _default: ({
226
231
  placeholder?: undefined;
227
232
  inline?: undefined;
228
233
  values?: undefined;
234
+ customConditional?: undefined;
229
235
  logic?: undefined;
230
236
  dataSrc?: undefined;
231
237
  valueProperty?: undefined;
@@ -248,6 +254,7 @@ declare const _default: ({
248
254
  placeholder?: undefined;
249
255
  inline?: undefined;
250
256
  values?: undefined;
257
+ customConditional?: undefined;
251
258
  logic?: undefined;
252
259
  dataSrc?: undefined;
253
260
  valueProperty?: undefined;
@@ -60,6 +60,7 @@ exports.default = [
60
60
  tooltip: 'Encrypt this field on the server. This is two way encryption which is not suitable for passwords.',
61
61
  key: 'encrypted',
62
62
  input: true,
63
+ customConditional: 'show = data.encrypted;',
63
64
  logic: [
64
65
  {
65
66
  name: 'disabled',
@@ -143,7 +144,7 @@ exports.default = [
143
144
  input: true,
144
145
  },
145
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>'),
146
- 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>', '<tr><th>token</th><td>The decoded JWT token for the authenticated user.</td></tr>'),
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()),
147
148
  {
148
149
  type: 'checkbox',
149
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 {
@@ -833,6 +833,11 @@ class NestedComponent extends Field_1.default {
833
833
  else if (value && component.hasValue(value)) {
834
834
  return component.setValue(lodash_1.default.get(value, component.key), flags);
835
835
  }
836
+ // if no value is provided and noDefault flag, set empty value
837
+ else if (flags.noDefault && component.allowData) {
838
+ flags.resetValue = true;
839
+ return component.setValue(component.emptyValue, flags);
840
+ }
836
841
  else if ((!this.rootPristine || component.visible) &&
837
842
  (flags.resetValue || component.shouldAddDefaultValue)) {
838
843
  flags.noValidate = !flags.dirty;
@@ -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;
@@ -403,6 +405,7 @@ class AddressComponent extends Container_1.default {
403
405
  super.redraw();
404
406
  }
405
407
  attach(element) {
408
+ var _a;
406
409
  const result = (this.builderMode || this.manualMode ? super.attach : Field_1.default.prototype.attach).call(this, element);
407
410
  if (!this.builderMode) {
408
411
  if (!this.provider && this.component.provider) {
@@ -418,6 +421,20 @@ class AddressComponent extends Container_1.default {
418
421
  [AddressComponent.removeValueIconRef]: 'multiple',
419
422
  [AddressComponent.searchInputRef]: 'multiple',
420
423
  });
424
+ // We define a container for rendering autocomplete.
425
+ // If isInShadowDOM=true then we render it in shadow dom otherwise in the document body.
426
+ const isInShadowDOM = typeof ShadowRoot !== 'undefined' && ((_a = this.element) === null || _a === void 0 ? void 0 : _a.getRootNode()) instanceof ShadowRoot;
427
+ let container;
428
+ if (isInShadowDOM) {
429
+ const shadowRoot = this.element.getRootNode();
430
+ container = document.createElement('div');
431
+ const target = shadowRoot.querySelector('.formio-form-wrapper');
432
+ target.appendChild(container);
433
+ }
434
+ else {
435
+ container = document.createElement('div');
436
+ document.body.appendChild(container);
437
+ }
421
438
  this.searchInput.forEach((element, index) => {
422
439
  if (!this.builderMode && element && this.provider) {
423
440
  if (this.component.provider === 'google') {
@@ -426,6 +443,7 @@ class AddressComponent extends Container_1.default {
426
443
  else {
427
444
  (0, autocompleter_1.default)({
428
445
  input: element,
446
+ container,
429
447
  debounceWaitMs: 300,
430
448
  fetch: (text, update) => {
431
449
  const query = text;
@@ -551,7 +551,7 @@ class DataGridComponent extends NestedArrayComponent_1.default {
551
551
  options.row = `${rowIndex}-${colIndex}`;
552
552
  options.rowIndex = rowIndex;
553
553
  options.onChange = (flags, changed, modified) => {
554
- var _a, _b, _c, _d, _e;
554
+ var _a, _b, _c, _d;
555
555
  const changedComponent = changed.component;
556
556
  if ((changedComponent === null || changedComponent === void 0 ? void 0 : changedComponent.type) === 'form' && (changedComponent === null || changedComponent === void 0 ? void 0 : changedComponent.key)) {
557
557
  const formComp = (0, utils_1.getComponent)(this.component.components, changedComponent.key);
@@ -562,8 +562,18 @@ class DataGridComponent extends NestedArrayComponent_1.default {
562
562
  (_d = (_c = changed.instance.root).triggerChange) === null || _d === void 0 ? void 0 : _d.call(_c, flags, changed, modified);
563
563
  }
564
564
  else {
565
- (_e = this.triggerChange) === null || _e === void 0 ? void 0 : _e.call(this, { modified });
565
+ if (modified && !flags.noPristineChangeOnModified) {
566
+ this.pristine = false;
567
+ }
568
+ this.triggerRootChange(flags, {
569
+ instance: this,
570
+ component: this.component,
571
+ value: this.dataValue,
572
+ flags,
573
+ }, modified);
574
+ this.triggerRootChange(flags, changed, modified);
566
575
  }
576
+ this.processRow('checkData', null, Object.assign(Object.assign({}, flags), { changed }), row, lodash_1.default.toArray(this.rows[rowIndex]));
567
577
  };
568
578
  let columnComponent;
569
579
  if (this.builderMode) {
@@ -19,6 +19,7 @@ export default class DataMapComponent extends DataGridComponent {
19
19
  getRowKey(rowIndex: any): string;
20
20
  get defaultRowKey(): string;
21
21
  getValueAsString(value: any, options: any): any;
22
+ findComponentInstance(key: any): any;
22
23
  createRowComponents(row: any, rowIndex: any): {
23
24
  __key: any;
24
25
  };
@@ -185,10 +185,14 @@ class DataMapComponent extends DataGrid_1.default {
185
185
  <tbody>
186
186
  `;
187
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);
188
192
  result += `
189
193
  <tr>
190
194
  <th style="padding: 5px 10px;">${key}</th>
191
- <td style="width:100%;padding:5px 10px;">${this.getView(value[key], options)}</td>
195
+ <td style="width:100%;padding:5px 10px;">${viewValue}</td>
192
196
  </tr>
193
197
  `;
194
198
  return result;
@@ -208,6 +212,19 @@ class DataMapComponent extends DataGrid_1.default {
208
212
  }
209
213
  return typeof value === 'object' ? '[Complex Data]' : value;
210
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
+ }
211
228
  getDataValueAsTable(value, options) {
212
229
  let result = `
213
230
  <table border="1" style="width:100%">
@@ -215,10 +232,14 @@ class DataMapComponent extends DataGrid_1.default {
215
232
  `;
216
233
  if (this.visible && lodash_1.default.isObject(value)) {
217
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);
218
239
  result += `
219
240
  <tr>
220
241
  <th style="padding: 5px 10px;">${key}</th>
221
- <td style="width:100%;padding:5px 10px;">${this.getView(value[key], options)}</td>
242
+ <td style="width:100%;padding:5px 10px;">${viewValue}</td>
222
243
  </tr>
223
244
  `;
224
245
  });
@@ -253,9 +274,21 @@ class DataMapComponent extends DataGrid_1.default {
253
274
  });
254
275
  const valueComponent = lodash_1.default.clone(this.component.valueComponent);
255
276
  valueComponent.key = key;
256
- const componentOptions = this.options;
277
+ const componentOptions = lodash_1.default.clone(this.options);
257
278
  componentOptions.row = options.row;
258
- components[this.valueKey] = this.createComponent(valueComponent, componentOptions, this.dataValue);
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;
259
292
  return components;
260
293
  }
261
294
  get canAddColumn() {
@@ -139,6 +139,13 @@ class DateTimeComponent extends Input_1.default {
139
139
  get momentFormat() {
140
140
  return utils_1.default.convertFormatToMoment(this.component.format);
141
141
  }
142
+ get timezone() {
143
+ const widget = this.component.widget;
144
+ if (widget && widget.type === 'calendar') {
145
+ return this.getTimezone(widget);
146
+ }
147
+ return super.timezone;
148
+ }
142
149
  isEmpty(value = this.dataValue) {
143
150
  if (value && value.toString() === 'Invalid Date') {
144
151
  return true;
@@ -170,7 +177,10 @@ class DateTimeComponent extends Input_1.default {
170
177
  let format = utils_1.default.convertFormatToMoment(this.component.format);
171
178
  format += format.match(/z$/) ? '' : ' z';
172
179
  const timezone = this.timezone;
173
- if (value && !this.attached && timezone) {
180
+ const useTimezoneAwareFormat = value &&
181
+ timezone &&
182
+ (this.options.pdf || (options === null || options === void 0 ? void 0 : options.email));
183
+ if (useTimezoneAwareFormat) {
174
184
  if (Array.isArray(value) && this.component.multiple) {
175
185
  return value
176
186
  .map((item) => lodash_1.default.trim(utils_1.default.momentDate(item, format, timezone, options).format(format)))