@formio/js 5.1.0-dev.6082.6dd4100 → 5.1.0-dev.6086.0b0957a

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.
@@ -163,8 +163,18 @@ declare class Component extends Element {
163
163
  */
164
164
  info: any;
165
165
  get componentsMap(): object;
166
+ /**
167
+ * Returns if the parent should conditionally clear.
168
+ *
169
+ * @returns {boolean} - If the parent should conditionally clear.
170
+ */
166
171
  parentShouldConditionallyClear(): boolean;
167
172
  parentConditionallyHidden(): boolean;
173
+ /**
174
+ * Returns true if any of the parents default their component "hidden" property to true.
175
+ * @returns {boolean} - If any parent defaults the hidden property to true.
176
+ */
177
+ anyParentDefaultsHidden(): boolean;
168
178
  set data(value: any);
169
179
  get data(): any;
170
180
  mergeSchema(component?: {}): any;
@@ -228,8 +238,23 @@ declare class Component extends Element {
228
238
  get visible(): boolean;
229
239
  get logicallyHidden(): any;
230
240
  _logicallyHidden: any;
231
- shouldConditionallyClear(skipParent?: boolean): boolean;
232
- conditionallyHidden(skipParent?: boolean): boolean;
241
+ /**
242
+ * Determines if the component should clear its value when the root form is pristine.
243
+ * @returns {boolean} - If the component should clear its value when the root form is pristine.
244
+ */
245
+ shouldConditionallyClearOnPristine(): boolean;
246
+ /**
247
+ * Returns if the component should clear its value when conditionally hidden.
248
+ * @returns {boolean} - If the component should clear its value when conditionally hidden.
249
+ */
250
+ shouldConditionallyClear(): boolean;
251
+ _conditionallyClear: boolean | undefined;
252
+ /**
253
+ * Returns if the component is conditionally hidden.
254
+ * @returns {boolean} - If the component is conditionally hidden.
255
+ */
256
+ conditionallyHidden(): boolean;
257
+ _conditionallyHidden: boolean | undefined;
233
258
  set currentForm(instance: any);
234
259
  get currentForm(): any;
235
260
  _currentForm: any;
@@ -458,10 +458,16 @@ class Component extends Element_1.default {
458
458
  var _a;
459
459
  return ((_a = this.root) === null || _a === void 0 ? void 0 : _a.childComponentsMap) || {};
460
460
  }
461
+ /**
462
+ * Returns if the parent should conditionally clear.
463
+ *
464
+ * @returns {boolean} - If the parent should conditionally clear.
465
+ */
461
466
  parentShouldConditionallyClear() {
462
467
  let currentParent = this.parent;
463
468
  while (currentParent) {
464
- if (currentParent.shouldConditionallyClear(true)) {
469
+ if ((currentParent.allowData && currentParent._conditionallyClear) ||
470
+ (!currentParent.allowData && currentParent._conditionallyHidden)) {
465
471
  return true;
466
472
  }
467
473
  currentParent = currentParent.parent;
@@ -471,7 +477,21 @@ class Component extends Element_1.default {
471
477
  parentConditionallyHidden() {
472
478
  let currentParent = this.parent;
473
479
  while (currentParent) {
474
- if (currentParent.conditionallyHidden(true)) {
480
+ if (currentParent._conditionallyHidden) {
481
+ return true;
482
+ }
483
+ currentParent = currentParent.parent;
484
+ }
485
+ return false;
486
+ }
487
+ /**
488
+ * Returns true if any of the parents default their component "hidden" property to true.
489
+ * @returns {boolean} - If any parent defaults the hidden property to true.
490
+ */
491
+ anyParentDefaultsHidden() {
492
+ let currentParent = this.parent;
493
+ while (currentParent) {
494
+ if (currentParent.component.hidden) {
475
495
  return true;
476
496
  }
477
497
  currentParent = currentParent.parent;
@@ -689,48 +709,58 @@ class Component extends Element_1.default {
689
709
  }
690
710
  return this._logicallyHidden;
691
711
  }
692
- shouldConditionallyClear(skipParent = false) {
712
+ /**
713
+ * Determines if the component should clear its value when the root form is pristine.
714
+ * @returns {boolean} - If the component should clear its value when the root form is pristine.
715
+ */
716
+ shouldConditionallyClearOnPristine() {
717
+ // If the form is pristine, we should NOT clear the value of a conditionally hidden child component
718
+ // of a layout component that defaults to hidden using the "hidden" component property.
719
+ return !this.anyParentDefaultsHidden();
720
+ }
721
+ /**
722
+ * Returns if the component should clear its value when conditionally hidden.
723
+ * @returns {boolean} - If the component should clear its value when conditionally hidden.
724
+ */
725
+ shouldConditionallyClear() {
693
726
  // Skip if this component has clearOnHide set to false.
694
727
  if (this.component.clearOnHide === false) {
695
- return false;
728
+ this._conditionallyClear = false;
729
+ return this._conditionallyClear;
696
730
  }
697
731
  // If the component is logically hidden, then it is conditionally hidden and should clear.
698
732
  if (this.logicallyHidden) {
699
- return true;
733
+ this._conditionallyClear = true;
734
+ return this._conditionallyClear;
700
735
  }
701
736
  // If we have a condition and it is not conditionally visible, the it should conditionally clear.
702
- if (this.hasCondition() && !this.conditionallyVisible()) {
703
- return true;
704
- }
705
- if (skipParent) {
706
- // Stop recurrsion for the parent checks.
707
- return false;
708
- }
709
- // If this component has a set value, then it should ONLY clear if a parent is hidden
710
- // and has the clearOnHide set to true.
711
- if (this.hasSetValue) {
712
- return this.parentShouldConditionallyClear();
737
+ if (this.hasCondition() &&
738
+ !this.conditionallyVisible() &&
739
+ (!this.rootPristine || this.shouldConditionallyClearOnPristine())) {
740
+ this._conditionallyClear = true;
741
+ return this._conditionallyClear;
713
742
  }
714
- // Clear the value if the parent is conditionally hidden.
715
- return this.parentConditionallyHidden();
743
+ this._conditionallyClear = this.hasSetValue ? false : this.parentShouldConditionallyClear();
744
+ return this._conditionallyClear;
716
745
  }
717
- conditionallyHidden(skipParent = false) {
746
+ /**
747
+ * Returns if the component is conditionally hidden.
748
+ * @returns {boolean} - If the component is conditionally hidden.
749
+ */
750
+ conditionallyHidden() {
751
+ // If it is logically hidden, then it is conditionally hidden.
718
752
  if (this.logicallyHidden) {
719
- return true;
720
- }
721
- if (!this.hasCondition() && !skipParent) {
722
- return this.parentConditionallyHidden();
753
+ this._conditionallyHidden = true;
754
+ return this._conditionallyHidden;
723
755
  }
724
- // Return if we are not conditionally visible (conditionallyHidden)
725
- if (!this.conditionallyVisible()) {
726
- return true;
727
- }
728
- if (skipParent) {
729
- // Stop recurrsion for the parent checks.
730
- return false;
756
+ // If it has a condition, and is not conditionally visible, then it is conditionally hidden.
757
+ if (this.hasCondition() && !this.conditionallyVisible()) {
758
+ this._conditionallyHidden = true;
759
+ return this._conditionallyHidden;
731
760
  }
732
- // Check the parent.
733
- return this.parentConditionallyHidden();
761
+ // It is conditionally hidden if its parent is conditionally hidden.
762
+ this._conditionallyHidden = this.parentConditionallyHidden();
763
+ return this._conditionallyHidden;
734
764
  }
735
765
  get currentForm() {
736
766
  return this._currentForm;
@@ -98,7 +98,6 @@ export default class FormComponent extends Component {
98
98
  * @returns {void}
99
99
  */
100
100
  onSetSubFormValue(submission: object | null | undefined, flags: object | null | undefined): void;
101
- areAllComponentsEmpty(data: any): boolean;
102
101
  updateSubFormVisibility(): void;
103
102
  /**
104
103
  * Determines if this form is a Nested Wizard
@@ -101,6 +101,9 @@ class FormComponent extends Component_1.default {
101
101
  }
102
102
  return this.createSubForm();
103
103
  }
104
+ shouldConditionallyClearOnPristine() {
105
+ return !this.hasSetValue && super.shouldConditionallyClearOnPristine();
106
+ }
104
107
  get dataReady() {
105
108
  var _a;
106
109
  return ((_a = this.subForm) === null || _a === void 0 ? void 0 : _a.dataReady) || this.subFormReady || Promise.resolve();
@@ -290,11 +293,13 @@ class FormComponent extends Component_1.default {
290
293
  }
291
294
  this.subForm.attach(element);
292
295
  this.valueChanged = this.hasSetValue;
293
- if (!this.valueChanged && this.dataValue.state !== 'submitted') {
294
- this.setDefaultValue();
295
- }
296
- else {
297
- this.restoreValue();
296
+ if (!this.shouldConditionallyClear()) {
297
+ if (!this.valueChanged && this.dataValue.state !== 'submitted') {
298
+ this.setDefaultValue();
299
+ }
300
+ else {
301
+ this.restoreValue();
302
+ }
298
303
  }
299
304
  }
300
305
  if (!this.builderMode && this.component.modalEdit) {
@@ -411,7 +416,7 @@ class FormComponent extends Component_1.default {
411
416
  lodash_1.default.assign(componentsMap, formComponentsMap);
412
417
  this.component.components = this.subForm.components.map((comp) => comp.component);
413
418
  this.subForm.on('change', () => {
414
- if (this.subForm) {
419
+ if (this.subForm && !this.shouldConditionallyClear()) {
415
420
  this.dataValue = this.subForm.getValue();
416
421
  this.triggerChange({
417
422
  noEmit: true
@@ -679,20 +684,7 @@ class FormComponent extends Component_1.default {
679
684
  }
680
685
  }
681
686
  isEmpty(value = this.dataValue) {
682
- return value === null || lodash_1.default.isEqual(value, this.emptyValue) || (this.areAllComponentsEmpty(value === null || value === void 0 ? void 0 : value.data) && !(value === null || value === void 0 ? void 0 : value._id));
683
- }
684
- areAllComponentsEmpty(data) {
685
- let res = true;
686
- if (this.subForm) {
687
- this.subForm.everyComponent((comp) => {
688
- const componentValue = lodash_1.default.get(data, comp.key);
689
- res &= comp.isEmpty(componentValue);
690
- });
691
- }
692
- else {
693
- res = false;
694
- }
695
- return res;
687
+ return value === null || lodash_1.default.isEqual(value, this.emptyValue);
696
688
  }
697
689
  getValue() {
698
690
  if (this.subForm) {
@@ -102,8 +102,8 @@ class TextFieldComponent extends Input_1.default {
102
102
  if (((_c = this.component.widget) === null || _c === void 0 ? void 0 : _c.type) === 'calendar') {
103
103
  this.component.widget = Object.assign(Object.assign({}, this.component.widget), { readOnly: this.options.readOnly, timezone,
104
104
  displayInTimezone, locale: this.component.widget.locale || this.options.language, saveAs: 'text' });
105
- // update originalComponent to include widget settings after component initialization
106
- // originalComponent is used to restore the component (and widget) after evaluating field logic
105
+ // update originalComponent to include widget settings after component initialization
106
+ // originalComponent is used to restore the component (and widget) after evaluating field logic
107
107
  this.originalComponent = FormioUtils.fastCloneDeep(this.component);
108
108
  }
109
109
  }
@@ -490,15 +490,6 @@ export function getFocusableElements(element: HTMLElement): NodeList<HTMLElement
490
490
  * @returns {Array<string>|null} - The saved types for the component
491
491
  */
492
492
  export function getComponentSavedTypes(fullSchema: import('@formio/core').Component): Array<string> | null;
493
- /**
494
- * Checks if a string has timezone information encoded in it
495
- * Example: 2024-01-01T00:00:00Z -> true
496
- * Example: 2024-01-01T00:00:00+03:00 -> true
497
- * Example: 2011-05-03T00:00:00 -> false
498
- * @param {string} value the string value to check
499
- * @returns {boolean} if value has encoded timezone
500
- */
501
- export function hasEncodedTimezone(value: string): boolean;
502
493
  export * from "./formUtils";
503
494
  /**
504
495
  * Map values through unfold and return first non-nil value.
@@ -19,7 +19,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
19
19
  };
20
20
  Object.defineProperty(exports, "__esModule", { value: true });
21
21
  exports.firstNonNil = exports.unfold = exports.bootstrapVersion = exports.uniqueKey = exports.iterateKey = exports.delay = exports.fieldData = exports.getCurrencyAffixes = exports.getNumberDecimalLimit = exports.getNumberSeparators = exports.matchInputMask = exports.unmaskValue = exports.getInputMask = exports.convertFormatToMask = exports.convertFormatToMoment = exports.convertFormatToFlatpickr = exports.getLocaleDateFormatInfo = exports.formatOffset = exports.formatDate = exports.momentDate = exports.loadZones = exports.shouldLoadZones = exports.zonesLoaded = exports.offsetDate = exports.currentTimezone = exports.isValidDate = exports.getDateSetting = exports.guid = exports.uniqueName = exports.convertStringToHTMLElement = exports.unescapeHTML = exports.removeHTML = exports.setActionProperty = exports.checkTrigger = exports.checkCondition = exports.checkJsonConditional = exports.checkCustomConditional = exports.getComponentActualValue = exports.checkSimpleConditional = exports.checkCalculated = exports.isMongoId = exports.boolValue = exports.getScriptPlugin = exports.getElementRect = exports.getPropertyValue = exports.getRandomComponentId = exports.evaluate = exports.moment = exports.ConditionOperators = exports.jsonLogic = void 0;
22
- exports.hasEncodedTimezone = exports.interpolateErrors = exports.getComponentSavedTypes = exports.componentValueTypes = exports._ = exports.getFocusableElements = exports.isPromise = exports.getDataParentComponent = exports.getComponentPath = exports.getComponentPathWithoutIndicies = exports.getBrowserInfo = exports.getIEBrowserVersion = exports.round = exports.getStringFromComponentPath = exports.isChildOf = exports.getArrayFromComponentPath = exports.isInputComponent = exports.interpolate = exports.Evaluator = exports.fastCloneDeep = exports.sanitize = exports.translateHTMLTemplate = exports.getContextButtons = exports.getContextComponents = exports.observeOverload = exports.withSwitch = void 0;
22
+ exports.interpolateErrors = exports.getComponentSavedTypes = exports.componentValueTypes = exports._ = exports.getFocusableElements = exports.isPromise = exports.getDataParentComponent = exports.getComponentPath = exports.getComponentPathWithoutIndicies = exports.getBrowserInfo = exports.getIEBrowserVersion = exports.round = exports.getStringFromComponentPath = exports.isChildOf = exports.getArrayFromComponentPath = exports.isInputComponent = exports.interpolate = exports.Evaluator = exports.fastCloneDeep = exports.sanitize = exports.translateHTMLTemplate = exports.getContextButtons = exports.getContextComponents = exports.observeOverload = exports.withSwitch = void 0;
23
23
  const lodash_1 = __importDefault(require("lodash"));
24
24
  exports._ = lodash_1.default;
25
25
  const json_logic_js_1 = __importDefault(require("json-logic-js"));
@@ -1646,18 +1646,3 @@ const interpolateErrors = (component, errors, interpolateFn) => {
1646
1646
  });
1647
1647
  };
1648
1648
  exports.interpolateErrors = interpolateErrors;
1649
- /**
1650
- * Checks if a string has timezone information encoded in it
1651
- * Example: 2024-01-01T00:00:00Z -> true
1652
- * Example: 2024-01-01T00:00:00+03:00 -> true
1653
- * Example: 2011-05-03T00:00:00 -> false
1654
- * @param {string} value the string value to check
1655
- * @returns {boolean} if value has encoded timezone
1656
- */
1657
- function hasEncodedTimezone(value) {
1658
- if (typeof value !== 'string') {
1659
- return false;
1660
- }
1661
- return (value.substring(value.length - 1) === 'z' || value.substring(value.length - 1) === 'Z' || value.match(/[+|-][0-9]+:[0-9]+/));
1662
- }
1663
- exports.hasEncodedTimezone = hasEncodedTimezone;
@@ -286,11 +286,6 @@ class CalendarWidget extends InputWidget_1.default {
286
286
  value = value ? (0, utils_1.formatDate)(this.timezonesUrl, value, (0, utils_1.convertFormatToMoment)(this.settings.format), this.timezone, (0, utils_1.convertFormatToMoment)(this.valueMomentFormat)) : value;
287
287
  return super.setValue(value);
288
288
  }
289
- // If the component is a textfield that does not have timezone information included in the string value then skip
290
- // the timezone offset
291
- if (this.component.type === 'textfield' && !(utils_1.hasEncodedTimezone)(value)) {
292
- this.settings.skipOffset = true;
293
- }
294
289
  const zonesLoading = this.loadZones();
295
290
  if (value) {
296
291
  if (!saveAsText && this.settings.readOnly && !zonesLoading) {
@@ -458,7 +453,7 @@ class CalendarWidget extends InputWidget_1.default {
458
453
  return (date, format) => {
459
454
  // Only format this if this is the altFormat and the form is readOnly.
460
455
  if (this.settings.readOnly && (format === this.settings.altFormat)) {
461
- if (!this.settings.enableTime || this.loadZones() || this.settings.skipOffset) {
456
+ if (!this.settings.enableTime || this.loadZones()) {
462
457
  return Flatpickr.formatDate(date, format);
463
458
  }
464
459
  const currentValue = new Date(this.getValue());
@@ -163,8 +163,18 @@ declare class Component extends Element {
163
163
  */
164
164
  info: any;
165
165
  get componentsMap(): object;
166
+ /**
167
+ * Returns if the parent should conditionally clear.
168
+ *
169
+ * @returns {boolean} - If the parent should conditionally clear.
170
+ */
166
171
  parentShouldConditionallyClear(): boolean;
167
172
  parentConditionallyHidden(): boolean;
173
+ /**
174
+ * Returns true if any of the parents default their component "hidden" property to true.
175
+ * @returns {boolean} - If any parent defaults the hidden property to true.
176
+ */
177
+ anyParentDefaultsHidden(): boolean;
168
178
  set data(value: any);
169
179
  get data(): any;
170
180
  mergeSchema(component?: {}): any;
@@ -228,8 +238,23 @@ declare class Component extends Element {
228
238
  get visible(): boolean;
229
239
  get logicallyHidden(): any;
230
240
  _logicallyHidden: any;
231
- shouldConditionallyClear(skipParent?: boolean): boolean;
232
- conditionallyHidden(skipParent?: boolean): boolean;
241
+ /**
242
+ * Determines if the component should clear its value when the root form is pristine.
243
+ * @returns {boolean} - If the component should clear its value when the root form is pristine.
244
+ */
245
+ shouldConditionallyClearOnPristine(): boolean;
246
+ /**
247
+ * Returns if the component should clear its value when conditionally hidden.
248
+ * @returns {boolean} - If the component should clear its value when conditionally hidden.
249
+ */
250
+ shouldConditionallyClear(): boolean;
251
+ _conditionallyClear: boolean | undefined;
252
+ /**
253
+ * Returns if the component is conditionally hidden.
254
+ * @returns {boolean} - If the component is conditionally hidden.
255
+ */
256
+ conditionallyHidden(): boolean;
257
+ _conditionallyHidden: boolean | undefined;
233
258
  set currentForm(instance: any);
234
259
  get currentForm(): any;
235
260
  _currentForm: any;
@@ -422,10 +422,16 @@ export default class Component extends Element {
422
422
  get componentsMap() {
423
423
  return this.root?.childComponentsMap || {};
424
424
  }
425
+ /**
426
+ * Returns if the parent should conditionally clear.
427
+ *
428
+ * @returns {boolean} - If the parent should conditionally clear.
429
+ */
425
430
  parentShouldConditionallyClear() {
426
431
  let currentParent = this.parent;
427
432
  while (currentParent) {
428
- if (currentParent.shouldConditionallyClear(true)) {
433
+ if ((currentParent.allowData && currentParent._conditionallyClear) ||
434
+ (!currentParent.allowData && currentParent._conditionallyHidden)) {
429
435
  return true;
430
436
  }
431
437
  currentParent = currentParent.parent;
@@ -435,7 +441,21 @@ export default class Component extends Element {
435
441
  parentConditionallyHidden() {
436
442
  let currentParent = this.parent;
437
443
  while (currentParent) {
438
- if (currentParent.conditionallyHidden(true)) {
444
+ if (currentParent._conditionallyHidden) {
445
+ return true;
446
+ }
447
+ currentParent = currentParent.parent;
448
+ }
449
+ return false;
450
+ }
451
+ /**
452
+ * Returns true if any of the parents default their component "hidden" property to true.
453
+ * @returns {boolean} - If any parent defaults the hidden property to true.
454
+ */
455
+ anyParentDefaultsHidden() {
456
+ let currentParent = this.parent;
457
+ while (currentParent) {
458
+ if (currentParent.component.hidden) {
439
459
  return true;
440
460
  }
441
461
  currentParent = currentParent.parent;
@@ -653,48 +673,58 @@ export default class Component extends Element {
653
673
  }
654
674
  return this._logicallyHidden;
655
675
  }
656
- shouldConditionallyClear(skipParent = false) {
676
+ /**
677
+ * Determines if the component should clear its value when the root form is pristine.
678
+ * @returns {boolean} - If the component should clear its value when the root form is pristine.
679
+ */
680
+ shouldConditionallyClearOnPristine() {
681
+ // If the form is pristine, we should NOT clear the value of a conditionally hidden child component
682
+ // of a layout component that defaults to hidden using the "hidden" component property.
683
+ return !this.anyParentDefaultsHidden();
684
+ }
685
+ /**
686
+ * Returns if the component should clear its value when conditionally hidden.
687
+ * @returns {boolean} - If the component should clear its value when conditionally hidden.
688
+ */
689
+ shouldConditionallyClear() {
657
690
  // Skip if this component has clearOnHide set to false.
658
691
  if (this.component.clearOnHide === false) {
659
- return false;
692
+ this._conditionallyClear = false;
693
+ return this._conditionallyClear;
660
694
  }
661
695
  // If the component is logically hidden, then it is conditionally hidden and should clear.
662
696
  if (this.logicallyHidden) {
663
- return true;
697
+ this._conditionallyClear = true;
698
+ return this._conditionallyClear;
664
699
  }
665
700
  // If we have a condition and it is not conditionally visible, the it should conditionally clear.
666
- if (this.hasCondition() && !this.conditionallyVisible()) {
667
- return true;
668
- }
669
- if (skipParent) {
670
- // Stop recurrsion for the parent checks.
671
- return false;
672
- }
673
- // If this component has a set value, then it should ONLY clear if a parent is hidden
674
- // and has the clearOnHide set to true.
675
- if (this.hasSetValue) {
676
- return this.parentShouldConditionallyClear();
701
+ if (this.hasCondition() &&
702
+ !this.conditionallyVisible() &&
703
+ (!this.rootPristine || this.shouldConditionallyClearOnPristine())) {
704
+ this._conditionallyClear = true;
705
+ return this._conditionallyClear;
677
706
  }
678
- // Clear the value if the parent is conditionally hidden.
679
- return this.parentConditionallyHidden();
707
+ this._conditionallyClear = this.hasSetValue ? false : this.parentShouldConditionallyClear();
708
+ return this._conditionallyClear;
680
709
  }
681
- conditionallyHidden(skipParent = false) {
710
+ /**
711
+ * Returns if the component is conditionally hidden.
712
+ * @returns {boolean} - If the component is conditionally hidden.
713
+ */
714
+ conditionallyHidden() {
715
+ // If it is logically hidden, then it is conditionally hidden.
682
716
  if (this.logicallyHidden) {
683
- return true;
684
- }
685
- if (!this.hasCondition() && !skipParent) {
686
- return this.parentConditionallyHidden();
717
+ this._conditionallyHidden = true;
718
+ return this._conditionallyHidden;
687
719
  }
688
- // Return if we are not conditionally visible (conditionallyHidden)
689
- if (!this.conditionallyVisible()) {
690
- return true;
691
- }
692
- if (skipParent) {
693
- // Stop recurrsion for the parent checks.
694
- return false;
720
+ // If it has a condition, and is not conditionally visible, then it is conditionally hidden.
721
+ if (this.hasCondition() && !this.conditionallyVisible()) {
722
+ this._conditionallyHidden = true;
723
+ return this._conditionallyHidden;
695
724
  }
696
- // Check the parent.
697
- return this.parentConditionallyHidden();
725
+ // It is conditionally hidden if its parent is conditionally hidden.
726
+ this._conditionallyHidden = this.parentConditionallyHidden();
727
+ return this._conditionallyHidden;
698
728
  }
699
729
  get currentForm() {
700
730
  return this._currentForm;
@@ -98,7 +98,6 @@ export default class FormComponent extends Component {
98
98
  * @returns {void}
99
99
  */
100
100
  onSetSubFormValue(submission: object | null | undefined, flags: object | null | undefined): void;
101
- areAllComponentsEmpty(data: any): boolean;
102
101
  updateSubFormVisibility(): void;
103
102
  /**
104
103
  * Determines if this form is a Nested Wizard
@@ -96,6 +96,9 @@ export default class FormComponent extends Component {
96
96
  }
97
97
  return this.createSubForm();
98
98
  }
99
+ shouldConditionallyClearOnPristine() {
100
+ return !this.hasSetValue && super.shouldConditionallyClearOnPristine();
101
+ }
99
102
  get dataReady() {
100
103
  return this.subForm?.dataReady || this.subFormReady || Promise.resolve();
101
104
  }
@@ -286,11 +289,13 @@ export default class FormComponent extends Component {
286
289
  }
287
290
  this.subForm.attach(element);
288
291
  this.valueChanged = this.hasSetValue;
289
- if (!this.valueChanged && this.dataValue.state !== 'submitted') {
290
- this.setDefaultValue();
291
- }
292
- else {
293
- this.restoreValue();
292
+ if (!this.shouldConditionallyClear()) {
293
+ if (!this.valueChanged && this.dataValue.state !== 'submitted') {
294
+ this.setDefaultValue();
295
+ }
296
+ else {
297
+ this.restoreValue();
298
+ }
294
299
  }
295
300
  }
296
301
  if (!this.builderMode && this.component.modalEdit) {
@@ -405,7 +410,7 @@ export default class FormComponent extends Component {
405
410
  _.assign(componentsMap, formComponentsMap);
406
411
  this.component.components = this.subForm.components.map((comp) => comp.component);
407
412
  this.subForm.on('change', () => {
408
- if (this.subForm) {
413
+ if (this.subForm && !this.shouldConditionallyClear()) {
409
414
  this.dataValue = this.subForm.getValue();
410
415
  this.triggerChange({
411
416
  noEmit: true
@@ -668,20 +673,7 @@ export default class FormComponent extends Component {
668
673
  }
669
674
  }
670
675
  isEmpty(value = this.dataValue) {
671
- return value === null || _.isEqual(value, this.emptyValue) || (this.areAllComponentsEmpty(value?.data) && !value?._id);
672
- }
673
- areAllComponentsEmpty(data) {
674
- let res = true;
675
- if (this.subForm) {
676
- this.subForm.everyComponent((comp) => {
677
- const componentValue = _.get(data, comp.key);
678
- res &= comp.isEmpty(componentValue);
679
- });
680
- }
681
- else {
682
- res = false;
683
- }
684
- return res;
676
+ return value === null || _.isEqual(value, this.emptyValue);
685
677
  }
686
678
  getValue() {
687
679
  if (this.subForm) {
@@ -86,8 +86,8 @@ export default class TextFieldComponent extends Input {
86
86
  locale: this.component.widget.locale || this.options.language,
87
87
  saveAs: 'text'
88
88
  };
89
- // update originalComponent to include widget settings after component initialization
90
- // originalComponent is used to restore the component (and widget) after evaluating field logic
89
+ // update originalComponent to include widget settings after component initialization
90
+ // originalComponent is used to restore the component (and widget) after evaluating field logic
91
91
  this.originalComponent = FormioUtils.fastCloneDeep(this.component);
92
92
  }
93
93
  }
@@ -490,15 +490,6 @@ export function getFocusableElements(element: HTMLElement): NodeList<HTMLElement
490
490
  * @returns {Array<string>|null} - The saved types for the component
491
491
  */
492
492
  export function getComponentSavedTypes(fullSchema: import('@formio/core').Component): Array<string> | null;
493
- /**
494
- * Checks if a string has timezone information encoded in it
495
- * Example: 2024-01-01T00:00:00Z -> true
496
- * Example: 2024-01-01T00:00:00+03:00 -> true
497
- * Example: 2011-05-03T00:00:00 -> false
498
- * @param {string} value the string value to check
499
- * @returns {boolean} if value has encoded timezone
500
- */
501
- export function hasEncodedTimezone(value: string): boolean;
502
493
  export * from "./formUtils";
503
494
  /**
504
495
  * Map values through unfold and return first non-nil value.
@@ -1554,17 +1554,3 @@ export const interpolateErrors = (component, errors, interpolateFn) => {
1554
1554
  return { ...error, message: unescapeHTML(interpolateFn(toInterpolate, context)), context: { ...context } };
1555
1555
  });
1556
1556
  };
1557
- /**
1558
- * Checks if a string has timezone information encoded in it
1559
- * Example: 2024-01-01T00:00:00Z -> true
1560
- * Example: 2024-01-01T00:00:00+03:00 -> true
1561
- * Example: 2011-05-03T00:00:00 -> false
1562
- * @param {string} value the string value to check
1563
- * @returns {boolean} if value has encoded timezone
1564
- */
1565
- export function hasEncodedTimezone(value) {
1566
- if (typeof value !== 'string') {
1567
- return false;
1568
- }
1569
- return (value.substring(value.length - 1) === 'z' || value.substring(value.length - 1) === 'Z' || value.match(/[+|-][0-9]+:[0-9]+/));
1570
- }
@@ -1,6 +1,6 @@
1
1
  import { Formio } from '../Formio';
2
2
  import InputWidget from './InputWidget';
3
- import { convertFormatToFlatpickr, convertFormatToMask, convertFormatToMoment, formatDate, formatOffset, getBrowserInfo, getDateSetting, getLocaleDateFormatInfo, momentDate, zonesLoaded, shouldLoadZones, loadZones, hasEncodedTimezone, } from '../utils/utils';
3
+ import { convertFormatToFlatpickr, convertFormatToMask, convertFormatToMoment, formatDate, formatOffset, getBrowserInfo, getDateSetting, getLocaleDateFormatInfo, momentDate, zonesLoaded, shouldLoadZones, loadZones, } from '../utils/utils';
4
4
  import moment from 'moment';
5
5
  import _ from 'lodash';
6
6
  const DEFAULT_FORMAT = 'yyyy-MM-dd hh:mm a';
@@ -278,11 +278,6 @@ export default class CalendarWidget extends InputWidget {
278
278
  value = value ? formatDate(this.timezonesUrl, value, convertFormatToMoment(this.settings.format), this.timezone, convertFormatToMoment(this.valueMomentFormat)) : value;
279
279
  return super.setValue(value);
280
280
  }
281
- // If the component is a textfield that does not have timezone information included in the string value then skip
282
- // the timezone offset
283
- if (this.component.type === 'textfield' && !(hasEncodedTimezone)(value)) {
284
- this.settings.skipOffset = true;
285
- }
286
281
  const zonesLoading = this.loadZones();
287
282
  if (value) {
288
283
  if (!saveAsText && this.settings.readOnly && !zonesLoading) {
@@ -448,7 +443,7 @@ export default class CalendarWidget extends InputWidget {
448
443
  return (date, format) => {
449
444
  // Only format this if this is the altFormat and the form is readOnly.
450
445
  if (this.settings.readOnly && (format === this.settings.altFormat)) {
451
- if (!this.settings.enableTime || this.loadZones() || this.settings.skipOffset) {
446
+ if (!this.settings.enableTime || this.loadZones()) {
452
447
  return Flatpickr.formatDate(date, format);
453
448
  }
454
449
  const currentValue = new Date(this.getValue());