@progress/kendo-dateinputs-common 0.2.0-dev.202301061353 → 0.2.0-dev.202301130811
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CODEOWNERS +2 -0
- package/dist/cdn/js/kendo-dateinputs-common.js +1 -1
- package/dist/cdn/main.js +1 -1
- package/dist/es/common/dateobject.js +280 -161
- package/dist/es/common/utils.js +1 -1
- package/dist/es/dateinput/dateinput.js +115 -46
- package/dist/es/dateinput/utils.js +10 -14
- package/dist/es2015/common/dateobject.js +280 -161
- package/dist/es2015/common/utils.js +1 -1
- package/dist/es2015/dateinput/dateinput.js +114 -45
- package/dist/es2015/dateinput/utils.js +10 -14
- package/dist/npm/common/dateobject.d.ts +6 -1
- package/dist/npm/common/dateobject.js +279 -160
- package/dist/npm/common/utils.d.ts +1 -1
- package/dist/npm/common/utils.js +1 -1
- package/dist/npm/dateinput/dateinput.d.ts +13 -2
- package/dist/npm/dateinput/dateinput.js +114 -45
- package/dist/npm/dateinput/utils.js +10 -14
- package/dist/systemjs/kendo-dateinputs-common.js +1 -1
- package/global-setup.js +4 -0
- package/jest.config.js +9 -0
- package/package.json +4 -4
|
@@ -2,7 +2,7 @@ import { DateObject } from '../common/dateobject';
|
|
|
2
2
|
import { approximateStringMatching } from './utils';
|
|
3
3
|
import { KeyCode } from '../common/keycode';
|
|
4
4
|
import { Key } from '../common/key';
|
|
5
|
-
import { extend, isPresent, isDocumentAvailable, millisecondDigitsInFormat, millisecondStepFor,
|
|
5
|
+
import { extend, isPresent, isDocumentAvailable, millisecondDigitsInFormat, millisecondStepFor, isValidDate } from '../common/utils';
|
|
6
6
|
import { Observable } from '../common/observable';
|
|
7
7
|
import { DateInputInteractionMode } from './interaction-mode';
|
|
8
8
|
import { isEqual, cloneDate } from '@progress/kendo-date-math';
|
|
@@ -71,15 +71,15 @@ export class DateInput extends Observable {
|
|
|
71
71
|
this.currentText = '';
|
|
72
72
|
this.currentFormat = '';
|
|
73
73
|
this.interactionMode = DateInputInteractionMode.None;
|
|
74
|
-
this.
|
|
74
|
+
this.previousElementSelection = { start: 0, end: 0 };
|
|
75
75
|
this.init(element, options);
|
|
76
76
|
}
|
|
77
77
|
get value() {
|
|
78
78
|
return this.dateObject && this.dateObject.getValue();
|
|
79
79
|
}
|
|
80
80
|
init(element, options) {
|
|
81
|
-
let dateValue =
|
|
82
|
-
if (!
|
|
81
|
+
let dateValue = isValidDate(this.options.value) ? cloneDate(this.options.value) : new Date(options.formattedValue);
|
|
82
|
+
if (!isValidDate(dateValue)) {
|
|
83
83
|
dateValue = null;
|
|
84
84
|
}
|
|
85
85
|
this.element = element;
|
|
@@ -92,6 +92,7 @@ export class DateInput extends Observable {
|
|
|
92
92
|
this.setTextAndFormat();
|
|
93
93
|
this.bindEvents();
|
|
94
94
|
this.resetSegmentValue = true;
|
|
95
|
+
this.interactionMode = DateInputInteractionMode.None;
|
|
95
96
|
this.forceUpdate();
|
|
96
97
|
}
|
|
97
98
|
destroy() {
|
|
@@ -146,8 +147,8 @@ export class DateInput extends Observable {
|
|
|
146
147
|
setOptions(options, refresh = false) {
|
|
147
148
|
this.options = extend(this.options, options);
|
|
148
149
|
if (refresh) {
|
|
149
|
-
this.
|
|
150
|
-
this.init(this.element, options);
|
|
150
|
+
this.unbindEvents();
|
|
151
|
+
this.init(this.element, this.options);
|
|
151
152
|
}
|
|
152
153
|
}
|
|
153
154
|
/**
|
|
@@ -263,33 +264,48 @@ export class DateInput extends Observable {
|
|
|
263
264
|
const hasCaret = this.isInCaretMode();
|
|
264
265
|
if (hasCaret && this.keyDownEvent.key === Key.SPACE) {
|
|
265
266
|
// do not allow custom "holes" in the date segments
|
|
266
|
-
this.
|
|
267
|
+
this.restorePreviousInputEventState();
|
|
267
268
|
return;
|
|
268
269
|
}
|
|
269
270
|
const oldDateObjectValue = this.dateObject && this.dateObject.getValue();
|
|
270
271
|
const { text: currentText, format: currentFormat } = this.dateObject.getTextAndFormat();
|
|
271
272
|
this.currentFormat = currentFormat;
|
|
272
|
-
|
|
273
|
+
let text = "";
|
|
274
|
+
if (hasCaret) {
|
|
275
|
+
if (isBackspaceKey || isDeleteKey) {
|
|
276
|
+
text = this.previousElementValue;
|
|
277
|
+
}
|
|
278
|
+
else if (originalInteractionMode === DateInputInteractionMode.Caret) {
|
|
279
|
+
text = this.previousElementValue;
|
|
280
|
+
}
|
|
281
|
+
else {
|
|
282
|
+
text = currentText;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
else {
|
|
286
|
+
text = currentText;
|
|
287
|
+
}
|
|
288
|
+
const newText = this.elementValue;
|
|
273
289
|
const diff = approximateStringMatching({
|
|
274
290
|
oldText: text,
|
|
275
|
-
newText:
|
|
291
|
+
newText: newText,
|
|
276
292
|
formatPattern: this.currentFormat,
|
|
277
293
|
selectionStart: this.selection.start,
|
|
278
294
|
isInCaretMode: hasCaret,
|
|
279
295
|
keyEvent: this.keyDownEvent
|
|
280
296
|
});
|
|
281
297
|
if (hasCaret && (!diff || diff.length === 0)) {
|
|
282
|
-
this.
|
|
298
|
+
this.restorePreviousInputEventState();
|
|
283
299
|
return;
|
|
284
300
|
}
|
|
285
301
|
else if (hasCaret && diff.length === 1) {
|
|
286
302
|
if (!diff[0] || !diff[0][0]) {
|
|
287
|
-
this.
|
|
303
|
+
this.restorePreviousInputEventState();
|
|
288
304
|
return;
|
|
289
305
|
}
|
|
290
306
|
else if (hasCaret && diff[0] &&
|
|
291
307
|
(diff[0][0] === Constants.formatSeparator || diff[0][1] === Constants.formatSeparator)) {
|
|
292
|
-
this.
|
|
308
|
+
this.restorePreviousInputEventState();
|
|
293
309
|
return;
|
|
294
310
|
}
|
|
295
311
|
}
|
|
@@ -304,7 +320,8 @@ export class DateInput extends Observable {
|
|
|
304
320
|
resetSegmentValue: this.resetSegmentValue,
|
|
305
321
|
cycleSegmentValue: !this.isInCaretMode(),
|
|
306
322
|
rawTextValue: this.element.value,
|
|
307
|
-
isDeleting: isBackspaceKey || isDeleteKey
|
|
323
|
+
isDeleting: isBackspaceKey || isDeleteKey,
|
|
324
|
+
originalFormat: this.currentFormat
|
|
308
325
|
});
|
|
309
326
|
parsePartsResults.push(parsePartResult);
|
|
310
327
|
switchPart = parsePartResult.switchToNext;
|
|
@@ -342,6 +359,25 @@ export class DateInput extends Observable {
|
|
|
342
359
|
}
|
|
343
360
|
}
|
|
344
361
|
}
|
|
362
|
+
else if (hasCaret) {
|
|
363
|
+
if (this.options.format.length !== this.currentFormat.length) {
|
|
364
|
+
if (hasDateValueChanged && isPresent(this.dateObject.getValue())) {
|
|
365
|
+
if (switchPart) {
|
|
366
|
+
this.switchDateSegment(1);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
else {
|
|
371
|
+
if (hasDateValueChanged) {
|
|
372
|
+
if (lastParseResultHasNoValue) {
|
|
373
|
+
this.restorePreviousInputEventState();
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
else {
|
|
377
|
+
this.restorePreviousInputEventState();
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
}
|
|
345
381
|
}
|
|
346
382
|
if (!switchPart && hasCaret && !isBackspaceKey && !isDeleteKey && !resetPart && lastParseResultHasNoValue) {
|
|
347
383
|
if (hasDateValueChanged) {
|
|
@@ -358,10 +394,13 @@ export class DateInput extends Observable {
|
|
|
358
394
|
this.setSelection(this.selectionBySymbol(symbolForSelection));
|
|
359
395
|
}
|
|
360
396
|
else {
|
|
361
|
-
this.
|
|
397
|
+
this.restorePreviousInputEventState();
|
|
362
398
|
}
|
|
363
399
|
}
|
|
364
400
|
}
|
|
401
|
+
else {
|
|
402
|
+
this.restorePreviousInputEventState();
|
|
403
|
+
}
|
|
365
404
|
}
|
|
366
405
|
else if (this.options.autoSwitchParts && (switchPart || navigationOnly)) {
|
|
367
406
|
if (!hasCaret) {
|
|
@@ -373,6 +412,12 @@ export class DateInput extends Observable {
|
|
|
373
412
|
event: e
|
|
374
413
|
});
|
|
375
414
|
this.triggerInputEnd({ event: e });
|
|
415
|
+
if (hasCaret) {
|
|
416
|
+
// a format like "F" can dynamically change the resolved format pattern based on the value, e.g.
|
|
417
|
+
// "Tuesday, February 1, 2022 3:04:05 AM" becomes
|
|
418
|
+
// "Wednesday, February 2, 2022 3:04:05 AM" giving a diff of 2 ("Tuesday".length - "Wednesday".length)
|
|
419
|
+
this.setTextAndFormat();
|
|
420
|
+
}
|
|
376
421
|
}
|
|
377
422
|
/**
|
|
378
423
|
* @hidden
|
|
@@ -418,6 +463,8 @@ export class DateInput extends Observable {
|
|
|
418
463
|
}
|
|
419
464
|
this.keyDownEvent = e;
|
|
420
465
|
this.previousElementValue = this.element.value;
|
|
466
|
+
const { start, end } = this.selection;
|
|
467
|
+
this.previousElementSelection = { start, end };
|
|
421
468
|
const autoSwitchKeys = (this.options.autoSwitchKeys || [])
|
|
422
469
|
.map(x => x.toString().toLowerCase().trim());
|
|
423
470
|
if (autoSwitchKeys.indexOf(e.keyCode.toString()) >= 0 ||
|
|
@@ -606,6 +653,14 @@ export class DateInput extends Observable {
|
|
|
606
653
|
if (start < 0) {
|
|
607
654
|
start = 0;
|
|
608
655
|
}
|
|
656
|
+
if (!this.options.autoCorrectParts && this.currentFormat.length !== this.currentText.length) {
|
|
657
|
+
if (this.currentFormat.length < this.currentText.length) {
|
|
658
|
+
end += this.currentText.length - this.currentFormat.length;
|
|
659
|
+
}
|
|
660
|
+
else {
|
|
661
|
+
end = Math.max(0, end - (this.currentFormat.length - this.currentText.length));
|
|
662
|
+
}
|
|
663
|
+
}
|
|
609
664
|
return { start, end };
|
|
610
665
|
}
|
|
611
666
|
/**
|
|
@@ -629,24 +684,36 @@ export class DateInput extends Observable {
|
|
|
629
684
|
const selection = this.selection;
|
|
630
685
|
if (this.isInCaretMode()) {
|
|
631
686
|
let start = selection.start;
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
687
|
+
const currentSymbol = this.currentFormat[start - (this.elementValue.length - this.currentFormat.length)];
|
|
688
|
+
let symbol = "";
|
|
689
|
+
let symbolCandidate = "";
|
|
690
|
+
if (offset < 0) {
|
|
691
|
+
for (let i = 0; i < start + offset; i++) {
|
|
692
|
+
symbolCandidate = this.currentFormat[i];
|
|
693
|
+
if (symbolCandidate !== Constants.formatSeparator &&
|
|
694
|
+
symbolCandidate !== currentSymbol) {
|
|
695
|
+
start = i;
|
|
696
|
+
symbol = symbolCandidate;
|
|
697
|
+
break;
|
|
698
|
+
}
|
|
638
699
|
}
|
|
639
700
|
}
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
701
|
+
else {
|
|
702
|
+
for (let i = start + offset; i < this.currentFormat.length; i++) {
|
|
703
|
+
symbolCandidate = this.currentFormat[i];
|
|
704
|
+
if (symbolCandidate !== Constants.formatSeparator &&
|
|
705
|
+
symbolCandidate !== currentSymbol) {
|
|
706
|
+
start = i;
|
|
707
|
+
symbol = symbolCandidate;
|
|
708
|
+
break;
|
|
709
|
+
}
|
|
645
710
|
}
|
|
646
711
|
}
|
|
647
712
|
if (symbol) {
|
|
648
713
|
this.forceUpdate();
|
|
649
714
|
this.setSelection(this.selectionBySymbol(symbol));
|
|
715
|
+
this.interactionMode = DateInputInteractionMode.Selection;
|
|
716
|
+
return;
|
|
650
717
|
}
|
|
651
718
|
}
|
|
652
719
|
let { start: selectionStart, end: selectionEnd } = this.selection;
|
|
@@ -800,7 +867,6 @@ export class DateInput extends Observable {
|
|
|
800
867
|
* @hidden
|
|
801
868
|
*/
|
|
802
869
|
setElementValue(value) {
|
|
803
|
-
this.previousElementValue = this.element.value;
|
|
804
870
|
this.element.value = value;
|
|
805
871
|
}
|
|
806
872
|
/**
|
|
@@ -836,23 +902,25 @@ export class DateInput extends Observable {
|
|
|
836
902
|
}
|
|
837
903
|
/* eslint-enable no-fallthrough */
|
|
838
904
|
}
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
}
|
|
851
|
-
else {
|
|
852
|
-
selectionOffset = -1;
|
|
853
|
-
}
|
|
905
|
+
/**
|
|
906
|
+
* @hidden
|
|
907
|
+
*/
|
|
908
|
+
restorePreviousInputEventState() {
|
|
909
|
+
this.restorePreviousElementValue();
|
|
910
|
+
this.restorePreviousElementSelection();
|
|
911
|
+
}
|
|
912
|
+
/**
|
|
913
|
+
* @hidden
|
|
914
|
+
*/
|
|
915
|
+
restorePreviousElementValue() {
|
|
854
916
|
this.setElementValue(this.previousElementValue || '');
|
|
855
|
-
|
|
917
|
+
}
|
|
918
|
+
/**
|
|
919
|
+
* @hidden
|
|
920
|
+
*/
|
|
921
|
+
restorePreviousElementSelection() {
|
|
922
|
+
const { start, end } = this.previousElementSelection;
|
|
923
|
+
this.setSelection({ start: start || 0, end: end || 0 });
|
|
856
924
|
}
|
|
857
925
|
writeValue(value) {
|
|
858
926
|
this.verifyValue(value);
|
|
@@ -860,7 +928,7 @@ export class DateInput extends Observable {
|
|
|
860
928
|
this.refreshElementValue();
|
|
861
929
|
}
|
|
862
930
|
verifyValue(value) {
|
|
863
|
-
if (value && !
|
|
931
|
+
if (value && !isValidDate(value)) {
|
|
864
932
|
throw new Error("The 'value' should be a valid JavaScript Date instance.");
|
|
865
933
|
}
|
|
866
934
|
}
|
|
@@ -878,6 +946,7 @@ export class DateInput extends Observable {
|
|
|
878
946
|
element.placeholder = this.options.placeholder;
|
|
879
947
|
}
|
|
880
948
|
const newElementValue = !showPlaceholder ? currentText : "";
|
|
949
|
+
this.previousElementValue = this.elementValue;
|
|
881
950
|
this.setElementValue(newElementValue);
|
|
882
951
|
if (this.isActive && !this.options.allowCaretMode && this.options.selectNearestSegmentOnFocus) {
|
|
883
952
|
this.selectNearestSegment(start);
|
|
@@ -959,10 +1028,10 @@ export class DateInput extends Observable {
|
|
|
959
1028
|
intlService: this.intl,
|
|
960
1029
|
formatPlaceholder: this.formatPlaceholder,
|
|
961
1030
|
format: this.inputFormat,
|
|
962
|
-
localeId: this.localeId,
|
|
963
1031
|
cycleTime: this.options.cycleTime,
|
|
964
1032
|
twoDigitYearMax: this.options.twoDigitYearMax,
|
|
965
|
-
autoCorrectParts: this.options.autoCorrectParts
|
|
1033
|
+
autoCorrectParts: this.options.autoCorrectParts,
|
|
1034
|
+
value: this.options.value
|
|
966
1035
|
}, options));
|
|
967
1036
|
return dateObject;
|
|
968
1037
|
}
|
|
@@ -52,27 +52,23 @@ export const approximateStringMatching = ({ oldText, newText, formatPattern, sel
|
|
|
52
52
|
Handle the typing over a literal as well.
|
|
53
53
|
*/
|
|
54
54
|
if ((isInCaretMode &&
|
|
55
|
-
newSegmentText.indexOf(oldSegmentText) === 0
|
|
55
|
+
(newSegmentText.indexOf(oldSegmentText) === 0 ||
|
|
56
|
+
formatPattern[selectionStart - 1] === Constants.formatSeparator)) ||
|
|
56
57
|
(!isInCaretMode &&
|
|
57
58
|
(newSegmentText.indexOf(oldSegmentText) === 0 ||
|
|
58
59
|
formatPattern[selectionStart - 1] === Constants.formatSeparator))) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
let symbol = formatPattern[0];
|
|
65
|
-
for (let i = Math.max(0, oldSegmentText.length - 1); i < formatPattern.length; i++) {
|
|
66
|
-
if (formatPattern[i] !== Constants.formatSeparator) {
|
|
67
|
-
symbol = formatPattern[i];
|
|
68
|
-
break;
|
|
69
|
-
}
|
|
60
|
+
let symbol = formatPattern[0];
|
|
61
|
+
for (let i = Math.max(0, oldSegmentText.length - 1); i < formatPattern.length; i++) {
|
|
62
|
+
if (formatPattern[i] !== Constants.formatSeparator) {
|
|
63
|
+
symbol = formatPattern[i];
|
|
64
|
+
break;
|
|
70
65
|
}
|
|
71
|
-
return [[symbol, newSegmentText[selectionStart - 1]]];
|
|
72
66
|
}
|
|
67
|
+
return [[symbol, newSegmentText[selectionStart - 1]]];
|
|
73
68
|
}
|
|
74
69
|
/* Handle the entering of a space or a separator for navigating to the next item. */
|
|
75
|
-
if (newSegmentText[newSegmentText.length - 1] === ' ' ||
|
|
70
|
+
if ((!isInCaretMode && newSegmentText[newSegmentText.length - 1] === ' ') ||
|
|
71
|
+
(!isInCaretMode && newSegmentText[newSegmentText.length - 1] === oldTextSeparator)) {
|
|
76
72
|
return [[formatPattern[selectionStart - 1], Constants.formatSeparator]];
|
|
77
73
|
}
|
|
78
74
|
/* Handle typing over a correctly selected part. */
|
|
@@ -63,13 +63,14 @@ export declare class DateObject {
|
|
|
63
63
|
/**
|
|
64
64
|
* @hidden
|
|
65
65
|
*/
|
|
66
|
-
parsePart({ symbol, currentChar, resetSegmentValue, cycleSegmentValue, rawTextValue, isDeleting }: {
|
|
66
|
+
parsePart({ symbol, currentChar, resetSegmentValue, cycleSegmentValue, rawTextValue: rawInputValue, isDeleting, originalFormat }: {
|
|
67
67
|
symbol: any;
|
|
68
68
|
currentChar: any;
|
|
69
69
|
resetSegmentValue: any;
|
|
70
70
|
cycleSegmentValue: any;
|
|
71
71
|
rawTextValue: any;
|
|
72
72
|
isDeleting: any;
|
|
73
|
+
originalFormat: any;
|
|
73
74
|
}): any;
|
|
74
75
|
/**
|
|
75
76
|
* @hidden
|
|
@@ -169,4 +170,8 @@ export declare class DateObject {
|
|
|
169
170
|
*/
|
|
170
171
|
modifyDateSymbolWithValue(date: any, symbol: any, value: any): Date;
|
|
171
172
|
markDatePartsAsExisting(): void;
|
|
173
|
+
/**
|
|
174
|
+
* @hidden
|
|
175
|
+
*/
|
|
176
|
+
getPartsForSegment(mask: any, partIndex: any): any[];
|
|
172
177
|
}
|