@progress/kendo-dateinputs-common 0.2.0-dev.202301131210 → 0.2.0-dev.202301161405

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.
@@ -600,8 +600,8 @@ var DateObject = /** @class */ (function () {
600
600
  var hasFixedFormat = (this.format === baseFormat) ||
601
601
  (this.format === originalFormat) ||
602
602
  (this.format.length === originalFormat.length);
603
- if (isInCaretMode) {
604
- var processedSegmentCharsCount = 0;
603
+ var processedSegmentCharsCount = 0;
604
+ if (isInCaretMode || (!isInCaretMode && !this.autoCorrectParts)) {
605
605
  for (var i = 0; i < baseDate.length; i++) {
606
606
  if (baseFormat[i] === symbol) {
607
607
  var existing = this.getExisting(symbol);
@@ -627,7 +627,7 @@ var DateObject = /** @class */ (function () {
627
627
  baseSuffix += baseDate[i];
628
628
  }
629
629
  }
630
- if (hasFixedFormat) {
630
+ if (hasFixedFormat && this.autoCorrectParts) {
631
631
  if (originalFormat.length < rawInputValue.length) {
632
632
  datePartText += currentChar;
633
633
  }
@@ -679,25 +679,41 @@ var DateObject = /** @class */ (function () {
679
679
  var lengthDiff = originalFormat.length - rawInputValue.length;
680
680
  var trimmedDatePartText = datePartText.substring(0, datePartText.length - lengthDiff);
681
681
  if (trimmedDatePartText && trimmedDatePartText.length > 0) {
682
+ var originalDatePartText = datePartText;
682
683
  datePartText = trimmedDatePartText;
684
+ if (prefix + datePartText + suffix !== rawInputValue) {
685
+ // move trimmed characters to the suffix
686
+ suffix = originalDatePartText.substring(datePartText.length) + suffix;
687
+ }
683
688
  }
684
689
  }
685
690
  }
686
691
  }
687
- else {
688
- for (var i = 0; i < baseDate.length; i++) {
689
- if (baseFormat[i] === symbol) {
690
- var existing = this.getExisting(symbol);
691
- current += existing ? baseDate[i] : '0';
692
- replaced = true;
693
- }
694
- else if (!replaced) {
695
- prefix += baseDate[i];
696
- }
697
- else {
698
- suffix += baseDate[i];
692
+ if (!isInCaretMode) {
693
+ if (this.autoCorrectParts) {
694
+ processedSegmentCharsCount = 0;
695
+ current = "";
696
+ datePartText = "";
697
+ prefix = "";
698
+ suffix = "";
699
+ replaced = false;
700
+ for (var i = 0; i < baseDate.length; i++) {
701
+ if (baseFormat[i] === symbol) {
702
+ var existing = this.getExisting(symbol);
703
+ current += existing ? baseDate[i] : '0';
704
+ replaced = true;
705
+ }
706
+ else if (!replaced) {
707
+ prefix += baseDate[i];
708
+ }
709
+ else {
710
+ suffix += baseDate[i];
711
+ }
699
712
  }
700
713
  }
714
+ else {
715
+ current = resetSegmentValue ? datePartText : current;
716
+ }
701
717
  }
702
718
  var parsedDate = null;
703
719
  var month = this.matchMonth(currentChar);
@@ -723,11 +739,12 @@ var DateObject = /** @class */ (function () {
723
739
  }
724
740
  var currentMaxLength = current.length - 3;
725
741
  var tryParse = true;
742
+ var middle = isInCaretMode ? datePartText : current;
726
743
  for (var i = Math.max(0, currentMaxLength); i <= current.length; i++) {
727
744
  if (!tryParse) {
728
745
  break;
729
746
  }
730
- var middle = resetSegmentValue ?
747
+ middle = resetSegmentValue ?
731
748
  currentChar :
732
749
  isInCaretMode ?
733
750
  datePartText :
@@ -756,11 +773,13 @@ var DateObject = /** @class */ (function () {
756
773
  // use the base prefix and suffix, e.g. convert the candidate date string
757
774
  // to "Thursday, February 1, 2022 3:04:05 AM"
758
775
  // as "EEEE, February..." is not parsable
759
- parsedDate = this.intl.parseDate(basePrefix + middle + baseSuffix, this.format, this.localeId);
760
- datePartText = middle;
776
+ if (this.autoCorrectParts) {
777
+ parsedDate = this.intl.parseDate(basePrefix + middle + baseSuffix, this.format, this.localeId);
778
+ datePartText = middle;
779
+ }
761
780
  }
762
781
  var isCurrentCharParsable = !isNaN(parseInt(currentChar, 10)) || (isInCaretMode && isDeleting && currentChar === "");
763
- if (!parsedDate && !isNaN(middleNumber) && isCurrentCharParsable) {
782
+ if (!parsedDate && !isNaN(middleNumber) && isCurrentCharParsable && this.autoCorrectParts) {
764
783
  if (symbol === MONTH_SYMBOL && !month) {
765
784
  // JS months start from 0 (January) instead of 1 (January)
766
785
  var monthNumber = middleNumber - JS_MONTH_OFFSET;
@@ -795,6 +814,26 @@ var DateObject = /** @class */ (function () {
795
814
  }
796
815
  this._value = parsedDate;
797
816
  this.setExisting(symbol, true);
817
+ this.resetInvalidDateSymbol(symbol);
818
+ if (!this.autoCorrectParts) {
819
+ if (symbol === "M") {
820
+ if (this.getExisting("M") && this.getExisting("y")) {
821
+ // changing from 28/Feb to 29/Feb to 29/March
822
+ this.setExisting("d", true);
823
+ this.resetInvalidDateSymbol("d");
824
+ }
825
+ }
826
+ else if (symbol === "d") {
827
+ if (this.getExisting("d") && this.getExisting("y")) {
828
+ // changing from 31/Jan to 31/Feb to 28/Feb
829
+ this.setExisting("M", true);
830
+ this.resetInvalidDateSymbol("M");
831
+ }
832
+ }
833
+ if (!this.hasInvalidDatePart()) {
834
+ this.markDatePartsAsExisting();
835
+ }
836
+ }
798
837
  if (isInCaretMode && switchToNext) {
799
838
  if (symbol === "M") {
800
839
  if (segmentLength <= MONTH_PART_WITH_WORDS_THRESHOLD) {
@@ -841,25 +880,30 @@ var DateObject = /** @class */ (function () {
841
880
  return extend(parseResult, { value: null, switchToNext: false });
842
881
  }
843
882
  if (!this.autoCorrectParts) {
844
- this.setExisting(symbol, false);
845
883
  var datePartValue = void 0;
846
- var textToParse = isInCaretMode ? datePartText : current;
884
+ var textToParse = isInCaretMode ? datePartText : middle;
847
885
  var parsedValue = parseToInt(textToParse);
848
886
  if (isNumber(parsedValue)) {
887
+ if ((symbol === "d" && (parsedValue <= 0 || parsedValue > 31)) ||
888
+ (symbol === "M" && (parsedValue < 0 || parsedValue > 11))) {
889
+ return extend(parseResult, { value: null, switchToNext: false });
890
+ }
849
891
  datePartValue = symbol === "M" ?
850
892
  clamp(parsedValue - JS_MONTH_OFFSET, 0, 12 - JS_MONTH_OFFSET) :
851
893
  parsedValue;
852
- }
853
- if (isNumber(datePartValue)) {
854
- var newDate = this.modifyDateSymbolWithValue(this.value, symbol, datePartValue);
855
894
  // if (!isEqual(newDate, this.value)) {
856
895
  this.setExisting(symbol, false);
857
896
  this.setInvalidDatePart(symbol, {
858
897
  value: datePartValue,
859
- date: cloneDate(newDate),
898
+ date: cloneDate(this.value),
860
899
  startDate: this._partiallyInvalidDate.startDate || cloneDate(this.value)
861
900
  });
862
901
  // }
902
+ return extend(parseResult, {
903
+ value: null,
904
+ switchToNext: false,
905
+ hasInvalidDatePart: true
906
+ });
863
907
  }
864
908
  }
865
909
  return extend(parseResult, { value: null, switchToNext: false });
@@ -1076,13 +1120,16 @@ var DateObject = /** @class */ (function () {
1076
1120
  }
1077
1121
  else {
1078
1122
  datePartText = (parseToInt(this.getInvalidDatePartValue(symbol)) + JS_MONTH_OFFSET).toString();
1079
- resultText = datePartText + resultText;
1123
+ var formattedDatePart = padZero(partsForSegment.length - datePartText.length) + datePartText;
1124
+ resultText = formattedDatePart + resultText;
1125
+ formatSymbolIndexModifier = partsForSegment.length - 1;
1080
1126
  ignoreFormatSymbolsCount = datePartText.length - partsForSegment.length;
1081
1127
  }
1082
1128
  }
1083
1129
  else {
1084
- resultText = datePartText + resultText;
1085
- formatSymbolIndexModifier = datePartText.length - 1;
1130
+ var formattedDatePart = padZero(partsForSegment.length - datePartText.length) + datePartText;
1131
+ resultText = formattedDatePart + resultText;
1132
+ formatSymbolIndexModifier = partsForSegment.length - 1;
1086
1133
  ignoreFormatSymbolsCount = datePartText.length - partsForSegment.length;
1087
1134
  }
1088
1135
  }
@@ -1173,13 +1220,34 @@ var DateObject = /** @class */ (function () {
1173
1220
  };
1174
1221
  DateObject.prototype.setInvalidDatePart = function (symbol, _a) {
1175
1222
  var _b = _a.value, value = _b === void 0 ? null : _b, _c = _a.date, date = _c === void 0 ? null : _c, _d = _a.startDateOffset, startDateOffset = _d === void 0 ? 0 : _d, _e = _a.startDate, startDate = _e === void 0 ? null : _e;
1223
+ var clampedValue = value;
1224
+ if (symbol === "d") {
1225
+ clampedValue = clamp(isPresent(value) ? value : 1, 1, 31);
1226
+ }
1227
+ else if (symbol === "M") {
1228
+ clampedValue = clamp(isPresent(value) ? value : 0, 0, 11);
1229
+ }
1176
1230
  if (this._partiallyInvalidDate.invalidDateParts[symbol]) {
1177
- this._partiallyInvalidDate.invalidDateParts[symbol].value = value;
1231
+ this._partiallyInvalidDate.invalidDateParts[symbol].value = clampedValue;
1178
1232
  this._partiallyInvalidDate.invalidDateParts[symbol].date = date;
1179
1233
  this._partiallyInvalidDate.invalidDateParts[symbol].startDateOffset = startDateOffset;
1180
1234
  this._partiallyInvalidDate.startDate = startDate;
1181
1235
  }
1182
1236
  };
1237
+ /**
1238
+ * @hidden
1239
+ */
1240
+ DateObject.prototype.hasInvalidDatePart = function () {
1241
+ var _this = this;
1242
+ var hasInvalidDatePart = false;
1243
+ Object.keys(this._partiallyInvalidDate.invalidDateParts).forEach(function (key) {
1244
+ if (_this._partiallyInvalidDate.invalidDateParts[key] &&
1245
+ isPresent(_this._partiallyInvalidDate.invalidDateParts[key].value)) {
1246
+ hasInvalidDatePart = true;
1247
+ }
1248
+ });
1249
+ return hasInvalidDatePart;
1250
+ };
1183
1251
  /**
1184
1252
  * @hidden
1185
1253
  */
@@ -344,6 +344,7 @@ var DateInput = /** @class */ (function (_super) {
344
344
  var lastParseResultHasNoValue = lastParseResult && !lastParseResult.value;
345
345
  var parsingFailedOnDelete = (hasCaret && (isBackspaceKey || isDeleteKey) && lastParseResultHasNoValue);
346
346
  var resetPart = lastParseResult ? lastParseResult.resetPart : false;
347
+ var hasInvalidDatePart = lastParseResult ? lastParseResult.hasInvalidDatePart : false;
347
348
  var hasDateValueChanged = !isEqual(oldDateObjectValue, this.dateObject.value);
348
349
  var symbolForSelection;
349
350
  var currentSelection = this.selection;
@@ -369,13 +370,14 @@ var DateInput = /** @class */ (function (_super) {
369
370
  }
370
371
  }
371
372
  else if (hasCaret) {
372
- if (hasDateValueChanged && isPresent(this.dateObject.getValue())) {
373
+ if ((hasDateValueChanged && isPresent(this.dateObject.getValue()) ||
374
+ (!hasDateValueChanged && switchPart && isPresent(this.dateObject.getValue())))) {
373
375
  if (switchPart) {
374
376
  this.switchDateSegment(1);
375
377
  }
376
378
  }
377
379
  else {
378
- if (lastParseResultHasNoValue) {
380
+ if (lastParseResultHasNoValue && !hasInvalidDatePart) {
379
381
  this.restorePreviousInputEventState();
380
382
  }
381
383
  }
@@ -388,20 +390,22 @@ var DateInput = /** @class */ (function (_super) {
388
390
  }
389
391
  else {
390
392
  // the input is not complete, not parsable or not updatable
391
- if (hasCaret && originalInteractionMode !== DateInputInteractionMode.Caret && hasDateValueChanged) {
393
+ if (originalInteractionMode !== DateInputInteractionMode.Caret && hasDateValueChanged) {
392
394
  }
393
- else if (hasCaret && originalInteractionMode !== DateInputInteractionMode.Caret) {
395
+ else if (originalInteractionMode !== DateInputInteractionMode.Caret) {
394
396
  symbolForSelection = this.currentFormat[currentSelection.start];
395
397
  this.forceUpdate();
396
398
  this.setSelection(this.selectionBySymbol(symbolForSelection));
397
399
  }
398
- else {
400
+ else if (!hasInvalidDatePart) {
399
401
  this.restorePreviousInputEventState();
400
402
  }
401
403
  }
402
404
  }
403
405
  else {
404
- this.restorePreviousInputEventState();
406
+ if (!hasInvalidDatePart) {
407
+ this.restorePreviousInputEventState();
408
+ }
405
409
  }
406
410
  }
407
411
  else if (this.options.autoSwitchParts && (switchPart || navigationOnly)) {
@@ -585,8 +585,8 @@ export class DateObject {
585
585
  const hasFixedFormat = (this.format === baseFormat) ||
586
586
  (this.format === originalFormat) ||
587
587
  (this.format.length === originalFormat.length);
588
- if (isInCaretMode) {
589
- let processedSegmentCharsCount = 0;
588
+ let processedSegmentCharsCount = 0;
589
+ if (isInCaretMode || (!isInCaretMode && !this.autoCorrectParts)) {
590
590
  for (let i = 0; i < baseDate.length; i++) {
591
591
  if (baseFormat[i] === symbol) {
592
592
  const existing = this.getExisting(symbol);
@@ -612,7 +612,7 @@ export class DateObject {
612
612
  baseSuffix += baseDate[i];
613
613
  }
614
614
  }
615
- if (hasFixedFormat) {
615
+ if (hasFixedFormat && this.autoCorrectParts) {
616
616
  if (originalFormat.length < rawInputValue.length) {
617
617
  datePartText += currentChar;
618
618
  }
@@ -664,25 +664,41 @@ export class DateObject {
664
664
  const lengthDiff = originalFormat.length - rawInputValue.length;
665
665
  const trimmedDatePartText = datePartText.substring(0, datePartText.length - lengthDiff);
666
666
  if (trimmedDatePartText && trimmedDatePartText.length > 0) {
667
+ const originalDatePartText = datePartText;
667
668
  datePartText = trimmedDatePartText;
669
+ if (prefix + datePartText + suffix !== rawInputValue) {
670
+ // move trimmed characters to the suffix
671
+ suffix = originalDatePartText.substring(datePartText.length) + suffix;
672
+ }
668
673
  }
669
674
  }
670
675
  }
671
676
  }
672
- else {
673
- for (let i = 0; i < baseDate.length; i++) {
674
- if (baseFormat[i] === symbol) {
675
- const existing = this.getExisting(symbol);
676
- current += existing ? baseDate[i] : '0';
677
- replaced = true;
678
- }
679
- else if (!replaced) {
680
- prefix += baseDate[i];
681
- }
682
- else {
683
- suffix += baseDate[i];
677
+ if (!isInCaretMode) {
678
+ if (this.autoCorrectParts) {
679
+ processedSegmentCharsCount = 0;
680
+ current = "";
681
+ datePartText = "";
682
+ prefix = "";
683
+ suffix = "";
684
+ replaced = false;
685
+ for (let i = 0; i < baseDate.length; i++) {
686
+ if (baseFormat[i] === symbol) {
687
+ const existing = this.getExisting(symbol);
688
+ current += existing ? baseDate[i] : '0';
689
+ replaced = true;
690
+ }
691
+ else if (!replaced) {
692
+ prefix += baseDate[i];
693
+ }
694
+ else {
695
+ suffix += baseDate[i];
696
+ }
684
697
  }
685
698
  }
699
+ else {
700
+ current = resetSegmentValue ? datePartText : current;
701
+ }
686
702
  }
687
703
  let parsedDate = null;
688
704
  const month = this.matchMonth(currentChar);
@@ -708,11 +724,12 @@ export class DateObject {
708
724
  }
709
725
  const currentMaxLength = current.length - 3;
710
726
  let tryParse = true;
727
+ let middle = isInCaretMode ? datePartText : current;
711
728
  for (let i = Math.max(0, currentMaxLength); i <= current.length; i++) {
712
729
  if (!tryParse) {
713
730
  break;
714
731
  }
715
- let middle = resetSegmentValue ?
732
+ middle = resetSegmentValue ?
716
733
  currentChar :
717
734
  isInCaretMode ?
718
735
  datePartText :
@@ -741,11 +758,13 @@ export class DateObject {
741
758
  // use the base prefix and suffix, e.g. convert the candidate date string
742
759
  // to "Thursday, February 1, 2022 3:04:05 AM"
743
760
  // as "EEEE, February..." is not parsable
744
- parsedDate = this.intl.parseDate(basePrefix + middle + baseSuffix, this.format, this.localeId);
745
- datePartText = middle;
761
+ if (this.autoCorrectParts) {
762
+ parsedDate = this.intl.parseDate(basePrefix + middle + baseSuffix, this.format, this.localeId);
763
+ datePartText = middle;
764
+ }
746
765
  }
747
766
  const isCurrentCharParsable = !isNaN(parseInt(currentChar, 10)) || (isInCaretMode && isDeleting && currentChar === "");
748
- if (!parsedDate && !isNaN(middleNumber) && isCurrentCharParsable) {
767
+ if (!parsedDate && !isNaN(middleNumber) && isCurrentCharParsable && this.autoCorrectParts) {
749
768
  if (symbol === MONTH_SYMBOL && !month) {
750
769
  // JS months start from 0 (January) instead of 1 (January)
751
770
  const monthNumber = middleNumber - JS_MONTH_OFFSET;
@@ -780,6 +799,26 @@ export class DateObject {
780
799
  }
781
800
  this._value = parsedDate;
782
801
  this.setExisting(symbol, true);
802
+ this.resetInvalidDateSymbol(symbol);
803
+ if (!this.autoCorrectParts) {
804
+ if (symbol === "M") {
805
+ if (this.getExisting("M") && this.getExisting("y")) {
806
+ // changing from 28/Feb to 29/Feb to 29/March
807
+ this.setExisting("d", true);
808
+ this.resetInvalidDateSymbol("d");
809
+ }
810
+ }
811
+ else if (symbol === "d") {
812
+ if (this.getExisting("d") && this.getExisting("y")) {
813
+ // changing from 31/Jan to 31/Feb to 28/Feb
814
+ this.setExisting("M", true);
815
+ this.resetInvalidDateSymbol("M");
816
+ }
817
+ }
818
+ if (!this.hasInvalidDatePart()) {
819
+ this.markDatePartsAsExisting();
820
+ }
821
+ }
783
822
  if (isInCaretMode && switchToNext) {
784
823
  if (symbol === "M") {
785
824
  if (segmentLength <= MONTH_PART_WITH_WORDS_THRESHOLD) {
@@ -826,25 +865,30 @@ export class DateObject {
826
865
  return extend(parseResult, { value: null, switchToNext: false });
827
866
  }
828
867
  if (!this.autoCorrectParts) {
829
- this.setExisting(symbol, false);
830
868
  let datePartValue;
831
- const textToParse = isInCaretMode ? datePartText : current;
869
+ const textToParse = isInCaretMode ? datePartText : middle;
832
870
  const parsedValue = parseToInt(textToParse);
833
871
  if (isNumber(parsedValue)) {
872
+ if ((symbol === "d" && (parsedValue <= 0 || parsedValue > 31)) ||
873
+ (symbol === "M" && (parsedValue < 0 || parsedValue > 11))) {
874
+ return extend(parseResult, { value: null, switchToNext: false });
875
+ }
834
876
  datePartValue = symbol === "M" ?
835
877
  clamp(parsedValue - JS_MONTH_OFFSET, 0, 12 - JS_MONTH_OFFSET) :
836
878
  parsedValue;
837
- }
838
- if (isNumber(datePartValue)) {
839
- const newDate = this.modifyDateSymbolWithValue(this.value, symbol, datePartValue);
840
879
  // if (!isEqual(newDate, this.value)) {
841
880
  this.setExisting(symbol, false);
842
881
  this.setInvalidDatePart(symbol, {
843
882
  value: datePartValue,
844
- date: cloneDate(newDate),
883
+ date: cloneDate(this.value),
845
884
  startDate: this._partiallyInvalidDate.startDate || cloneDate(this.value)
846
885
  });
847
886
  // }
887
+ return extend(parseResult, {
888
+ value: null,
889
+ switchToNext: false,
890
+ hasInvalidDatePart: true
891
+ });
848
892
  }
849
893
  }
850
894
  return extend(parseResult, { value: null, switchToNext: false });
@@ -1059,13 +1103,16 @@ export class DateObject {
1059
1103
  }
1060
1104
  else {
1061
1105
  datePartText = (parseToInt(this.getInvalidDatePartValue(symbol)) + JS_MONTH_OFFSET).toString();
1062
- resultText = datePartText + resultText;
1106
+ const formattedDatePart = padZero(partsForSegment.length - datePartText.length) + datePartText;
1107
+ resultText = formattedDatePart + resultText;
1108
+ formatSymbolIndexModifier = partsForSegment.length - 1;
1063
1109
  ignoreFormatSymbolsCount = datePartText.length - partsForSegment.length;
1064
1110
  }
1065
1111
  }
1066
1112
  else {
1067
- resultText = datePartText + resultText;
1068
- formatSymbolIndexModifier = datePartText.length - 1;
1113
+ const formattedDatePart = padZero(partsForSegment.length - datePartText.length) + datePartText;
1114
+ resultText = formattedDatePart + resultText;
1115
+ formatSymbolIndexModifier = partsForSegment.length - 1;
1069
1116
  ignoreFormatSymbolsCount = datePartText.length - partsForSegment.length;
1070
1117
  }
1071
1118
  }
@@ -1153,13 +1200,33 @@ export class DateObject {
1153
1200
  return (invalidDatePart || {}).value;
1154
1201
  }
1155
1202
  setInvalidDatePart(symbol, { value = null, date = null, startDateOffset = 0, startDate = null }) {
1203
+ let clampedValue = value;
1204
+ if (symbol === "d") {
1205
+ clampedValue = clamp(isPresent(value) ? value : 1, 1, 31);
1206
+ }
1207
+ else if (symbol === "M") {
1208
+ clampedValue = clamp(isPresent(value) ? value : 0, 0, 11);
1209
+ }
1156
1210
  if (this._partiallyInvalidDate.invalidDateParts[symbol]) {
1157
- this._partiallyInvalidDate.invalidDateParts[symbol].value = value;
1211
+ this._partiallyInvalidDate.invalidDateParts[symbol].value = clampedValue;
1158
1212
  this._partiallyInvalidDate.invalidDateParts[symbol].date = date;
1159
1213
  this._partiallyInvalidDate.invalidDateParts[symbol].startDateOffset = startDateOffset;
1160
1214
  this._partiallyInvalidDate.startDate = startDate;
1161
1215
  }
1162
1216
  }
1217
+ /**
1218
+ * @hidden
1219
+ */
1220
+ hasInvalidDatePart() {
1221
+ let hasInvalidDatePart = false;
1222
+ Object.keys(this._partiallyInvalidDate.invalidDateParts).forEach(key => {
1223
+ if (this._partiallyInvalidDate.invalidDateParts[key] &&
1224
+ isPresent(this._partiallyInvalidDate.invalidDateParts[key].value)) {
1225
+ hasInvalidDatePart = true;
1226
+ }
1227
+ });
1228
+ return hasInvalidDatePart;
1229
+ }
1163
1230
  /**
1164
1231
  * @hidden
1165
1232
  */
@@ -335,6 +335,7 @@ export class DateInput extends Observable {
335
335
  const lastParseResultHasNoValue = lastParseResult && !lastParseResult.value;
336
336
  const parsingFailedOnDelete = (hasCaret && (isBackspaceKey || isDeleteKey) && lastParseResultHasNoValue);
337
337
  const resetPart = lastParseResult ? lastParseResult.resetPart : false;
338
+ const hasInvalidDatePart = lastParseResult ? lastParseResult.hasInvalidDatePart : false;
338
339
  const hasDateValueChanged = !isEqual(oldDateObjectValue, this.dateObject.value);
339
340
  let symbolForSelection;
340
341
  const currentSelection = this.selection;
@@ -360,13 +361,14 @@ export class DateInput extends Observable {
360
361
  }
361
362
  }
362
363
  else if (hasCaret) {
363
- if (hasDateValueChanged && isPresent(this.dateObject.getValue())) {
364
+ if ((hasDateValueChanged && isPresent(this.dateObject.getValue()) ||
365
+ (!hasDateValueChanged && switchPart && isPresent(this.dateObject.getValue())))) {
364
366
  if (switchPart) {
365
367
  this.switchDateSegment(1);
366
368
  }
367
369
  }
368
370
  else {
369
- if (lastParseResultHasNoValue) {
371
+ if (lastParseResultHasNoValue && !hasInvalidDatePart) {
370
372
  this.restorePreviousInputEventState();
371
373
  }
372
374
  }
@@ -379,20 +381,22 @@ export class DateInput extends Observable {
379
381
  }
380
382
  else {
381
383
  // the input is not complete, not parsable or not updatable
382
- if (hasCaret && originalInteractionMode !== DateInputInteractionMode.Caret && hasDateValueChanged) {
384
+ if (originalInteractionMode !== DateInputInteractionMode.Caret && hasDateValueChanged) {
383
385
  }
384
- else if (hasCaret && originalInteractionMode !== DateInputInteractionMode.Caret) {
386
+ else if (originalInteractionMode !== DateInputInteractionMode.Caret) {
385
387
  symbolForSelection = this.currentFormat[currentSelection.start];
386
388
  this.forceUpdate();
387
389
  this.setSelection(this.selectionBySymbol(symbolForSelection));
388
390
  }
389
- else {
391
+ else if (!hasInvalidDatePart) {
390
392
  this.restorePreviousInputEventState();
391
393
  }
392
394
  }
393
395
  }
394
396
  else {
395
- this.restorePreviousInputEventState();
397
+ if (!hasInvalidDatePart) {
398
+ this.restorePreviousInputEventState();
399
+ }
396
400
  }
397
401
  }
398
402
  else if (this.options.autoSwitchParts && (switchPart || navigationOnly)) {
@@ -158,6 +158,10 @@ export declare class DateObject {
158
158
  startDateOffset?: number;
159
159
  startDate?: any;
160
160
  }): void;
161
+ /**
162
+ * @hidden
163
+ */
164
+ hasInvalidDatePart(): boolean;
161
165
  /**
162
166
  * @hidden
163
167
  */