-
Notifications
You must be signed in to change notification settings - Fork 18
/
utils.ts
88 lines (80 loc) · 2.81 KB
/
utils.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import { DateTimeFormatPart, DateTimeFormatPartTypes, InputSelection } from './types.js';
import { Direction } from './constants.js';
const IterablePartTypes: DateTimeFormatPartTypes[] = ['year', 'day', 'month', 'hour', 'minute', 'second', 'weekday', 'dayPeriod', 'fractionalSecond'];
const isAllowedPart = (part: DateTimeFormatPart): boolean => IterablePartTypes.includes(part.type);
/**
* Get a part index based on the selection
* @param selection Selection, containing selectionStart and selectionEnd
* @param parts The list of parts
* @returns index
*/
export const getSelectedPartIndex = (selection: InputSelection, parts: DateTimeFormatPart[]): number => {
const selectionEnd = selection.selectionEnd || 0;
let accumulator = 0;
// Get the closest part to selectionEnd
for (let i = 0; i < parts.length; i += 1) {
const part = parts[i];
accumulator += part.value.length;
if (accumulator >= selectionEnd && isAllowedPart(part)) {
return i;
}
}
return 0;
};
/**
* Get next available part index based on the selection, direction and input value
* @param selection Selection, containing selectionStart and selectionEnd
* @param parts The list of parts
* @param inputValue The date time string value
* @param direction Get the previous or the next part index
* @returns index
*/
export const getNextSelectedPartIndex = (selection: InputSelection, parts: DateTimeFormatPart[], inputValue: string, direction: Direction = Direction.Up): number => {
let selectedIndex: number;
const { selectionEnd, selectionStart } = selection;
if (selectionStart === 0 && selectionEnd === inputValue.length) {
// Full text selected
selectedIndex = direction === Direction.Up ? -1 : parts.length;
}
else if (selectionEnd === 0) {
// Cursor at the start of the text
selectedIndex = -1;
direction = Direction.Up;
}
else if (selectionEnd === inputValue.length && selectionEnd === selectionStart) {
// cursor at the end of the text
selectedIndex = parts.length;
direction = Direction.Down;
}
else {
selectedIndex = getSelectedPartIndex(selection, parts);
}
for (let i = selectedIndex + direction; direction === Direction.Up ? i < parts.length : i >= 0; i += direction) {
if (isAllowedPart(parts[i])) {
return i;
}
}
return selectedIndex;
};
/**
* Get part selectionStart and selectionEnd indexes
* @param index Part index
* @param parts The list of parts
* @returns selection
*/
export const selectPart = (index = 0, parts: DateTimeFormatPart[]): InputSelection => {
let selectionStart = 0;
let selectionEnd = 0;
for (let i = 0; i < parts.length; i += 1) {
const part = parts[i];
selectionEnd += part.value.length;
if (i === index) {
break;
}
selectionStart = selectionEnd;
}
return {
selectionStart,
selectionEnd
};
};