@gravity-ui/date-components 1.0.0 → 1.1.1
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/dist/cjs/components/Calendar/Calendar.css +9 -1
- package/dist/cjs/components/Calendar/CalendarBase.js +9 -9
- package/dist/cjs/components/Calendar/hooks/types.d.ts +5 -2
- package/dist/cjs/components/Calendar/hooks/useCalendarCellProps.js +21 -16
- package/dist/cjs/components/Calendar/hooks/useCalendarGridProps.js +2 -7
- package/dist/cjs/components/Calendar/hooks/useCalendarProps.js +6 -3
- package/dist/cjs/components/Calendar/hooks/useCalendarState.js +69 -26
- package/dist/cjs/components/Calendar/hooks/useRangeCalendarState.js +16 -11
- package/dist/cjs/components/Calendar/utils.d.ts +3 -1
- package/dist/cjs/components/Calendar/utils.js +7 -1
- package/dist/cjs/components/DateField/hooks/useDateFieldProps.js +23 -16
- package/dist/cjs/components/DateField/hooks/useDateFieldState.d.ts +2 -0
- package/dist/cjs/components/DateField/hooks/useDateFieldState.js +49 -166
- package/dist/cjs/components/DateField/types.d.ts +1 -1
- package/dist/cjs/components/DateField/utils.d.ts +12 -9
- package/dist/cjs/components/DateField/utils.js +168 -25
- package/dist/cjs/components/DatePicker/DatePicker.css +6 -0
- package/dist/cjs/components/DatePicker/DatePicker.d.ts +4 -1
- package/dist/cjs/components/DatePicker/DatePicker.js +6 -33
- package/dist/cjs/components/DatePicker/MobileCalendar.js +4 -4
- package/dist/cjs/components/DatePicker/hooks/useDatePickerProps.d.ts +20 -0
- package/dist/cjs/components/DatePicker/hooks/useDatePickerProps.js +134 -0
- package/dist/cjs/components/DatePicker/hooks/useDatePickerState.d.ts +4 -5
- package/dist/cjs/components/DatePicker/hooks/useDatePickerState.js +18 -8
- package/dist/cjs/components/DatePicker/index.d.ts +1 -0
- package/dist/cjs/components/DatePicker/index.js +1 -0
- package/dist/cjs/components/RelativeDatePicker/RelativeDatePicker.css +1 -0
- package/dist/cjs/components/RelativeDatePicker/RelativeDatePicker.d.ts +3 -0
- package/dist/cjs/components/RelativeDatePicker/RelativeDatePicker.js +1 -1
- package/dist/cjs/components/RelativeDatePicker/hooks/useRelativeDatePickerProps.js +35 -27
- package/dist/cjs/components/utils/dates.d.ts +9 -0
- package/dist/cjs/components/utils/dates.js +28 -0
- package/dist/esm/components/Calendar/Calendar.css +9 -1
- package/dist/esm/components/Calendar/CalendarBase.js +10 -10
- package/dist/esm/components/Calendar/hooks/types.d.ts +5 -2
- package/dist/esm/components/Calendar/hooks/useCalendarCellProps.js +21 -16
- package/dist/esm/components/Calendar/hooks/useCalendarGridProps.js +2 -7
- package/dist/esm/components/Calendar/hooks/useCalendarProps.js +6 -3
- package/dist/esm/components/Calendar/hooks/useCalendarState.js +70 -27
- package/dist/esm/components/Calendar/hooks/useRangeCalendarState.js +16 -11
- package/dist/esm/components/Calendar/utils.d.ts +3 -1
- package/dist/esm/components/Calendar/utils.js +6 -0
- package/dist/esm/components/DateField/hooks/useDateFieldProps.js +23 -16
- package/dist/esm/components/DateField/hooks/useDateFieldState.d.ts +2 -0
- package/dist/esm/components/DateField/hooks/useDateFieldState.js +41 -158
- package/dist/esm/components/DateField/types.d.ts +1 -1
- package/dist/esm/components/DateField/utils.d.ts +12 -9
- package/dist/esm/components/DateField/utils.js +162 -21
- package/dist/esm/components/DatePicker/DatePicker.css +6 -0
- package/dist/esm/components/DatePicker/DatePicker.d.ts +4 -1
- package/dist/esm/components/DatePicker/DatePicker.js +8 -35
- package/dist/esm/components/DatePicker/MobileCalendar.js +1 -1
- package/dist/esm/components/DatePicker/hooks/useDatePickerProps.d.ts +20 -0
- package/dist/esm/components/DatePicker/hooks/useDatePickerProps.js +127 -0
- package/dist/esm/components/DatePicker/hooks/useDatePickerState.d.ts +4 -5
- package/dist/esm/components/DatePicker/hooks/useDatePickerState.js +17 -7
- package/dist/esm/components/DatePicker/index.d.ts +1 -0
- package/dist/esm/components/DatePicker/index.js +1 -0
- package/dist/esm/components/RelativeDatePicker/RelativeDatePicker.css +1 -0
- package/dist/esm/components/RelativeDatePicker/RelativeDatePicker.d.ts +3 -0
- package/dist/esm/components/RelativeDatePicker/RelativeDatePicker.js +1 -1
- package/dist/esm/components/RelativeDatePicker/hooks/useRelativeDatePickerProps.js +35 -27
- package/dist/esm/components/utils/dates.d.ts +9 -0
- package/dist/esm/components/utils/dates.js +22 -0
- package/package.json +8 -7
- package/dist/cjs/components/DatePicker/DesktopCalendar.d.ts +0 -15
- package/dist/cjs/components/DatePicker/DesktopCalendar.js +0 -56
- package/dist/esm/components/DatePicker/DesktopCalendar.d.ts +0 -15
- package/dist/esm/components/DatePicker/DesktopCalendar.js +0 -48
|
@@ -7,6 +7,7 @@ exports.useDateFieldState = void 0;
|
|
|
7
7
|
const react_1 = __importDefault(require("react"));
|
|
8
8
|
const date_utils_1 = require("@gravity-ui/date-utils");
|
|
9
9
|
const useControlledState_1 = require("../../hooks/useControlledState");
|
|
10
|
+
const dates_1 = require("../../utils/dates");
|
|
10
11
|
const utils_1 = require("../utils");
|
|
11
12
|
const EDITABLE_SEGMENTS = {
|
|
12
13
|
year: true,
|
|
@@ -18,11 +19,6 @@ const EDITABLE_SEGMENTS = {
|
|
|
18
19
|
dayPeriod: true,
|
|
19
20
|
weekday: true,
|
|
20
21
|
};
|
|
21
|
-
const TYPE_MAPPING = {
|
|
22
|
-
weekday: 'day',
|
|
23
|
-
day: 'date',
|
|
24
|
-
dayPeriod: 'hour',
|
|
25
|
-
};
|
|
26
22
|
const PAGE_STEP = {
|
|
27
23
|
year: 5,
|
|
28
24
|
month: 2,
|
|
@@ -36,7 +32,7 @@ function useDateFieldState(props) {
|
|
|
36
32
|
var _a;
|
|
37
33
|
const [value, setDate] = (0, useControlledState_1.useControlledState)(props.value, props.defaultValue, props.onUpdate);
|
|
38
34
|
const [placeholderDate, setPlaceholderDate] = react_1.default.useState(() => {
|
|
39
|
-
return (0,
|
|
35
|
+
return (0, dates_1.createPlaceholderValue)({
|
|
40
36
|
placeholderValue: props.placeholderValue,
|
|
41
37
|
timeZone: props.timeZone,
|
|
42
38
|
});
|
|
@@ -60,7 +56,7 @@ function useDateFieldState(props) {
|
|
|
60
56
|
Object.keys(validSegments).length === Object.keys(allSegments).length) {
|
|
61
57
|
validSegments = {};
|
|
62
58
|
setValidSegments(validSegments);
|
|
63
|
-
setPlaceholderDate((0,
|
|
59
|
+
setPlaceholderDate((0, dates_1.createPlaceholderValue)({ timeZone: props.timeZone }));
|
|
64
60
|
}
|
|
65
61
|
const displayValue = value &&
|
|
66
62
|
(0, date_utils_1.isValid)(value) &&
|
|
@@ -68,10 +64,7 @@ function useDateFieldState(props) {
|
|
|
68
64
|
? value
|
|
69
65
|
: placeholderDate;
|
|
70
66
|
const sectionsState = useSectionsState(sections, displayValue, validSegments);
|
|
71
|
-
const [selectedSections, setSelectedSections] = react_1.default.useState(
|
|
72
|
-
var _a, _b;
|
|
73
|
-
return (_b = (_a = sectionsState.editableSections[0]) === null || _a === void 0 ? void 0 : _a.previousEditableSection) !== null && _b !== void 0 ? _b : -1;
|
|
74
|
-
});
|
|
67
|
+
const [selectedSections, setSelectedSections] = react_1.default.useState(-1);
|
|
75
68
|
const selectedSectionIndexes = react_1.default.useMemo(() => {
|
|
76
69
|
if (selectedSections === -1) {
|
|
77
70
|
return null;
|
|
@@ -96,9 +89,14 @@ function useDateFieldState(props) {
|
|
|
96
89
|
return;
|
|
97
90
|
}
|
|
98
91
|
if (Object.keys(validSegments).length >= Object.keys(allSegments).length) {
|
|
99
|
-
|
|
92
|
+
if (!value || !newValue.isSame(value)) {
|
|
93
|
+
setDate(newValue);
|
|
94
|
+
}
|
|
100
95
|
}
|
|
101
96
|
else {
|
|
97
|
+
if (value) {
|
|
98
|
+
setDate(null);
|
|
99
|
+
}
|
|
102
100
|
setPlaceholderDate(newValue);
|
|
103
101
|
}
|
|
104
102
|
}
|
|
@@ -114,12 +112,12 @@ function useDateFieldState(props) {
|
|
|
114
112
|
}
|
|
115
113
|
function setSection(section, amount) {
|
|
116
114
|
markValid(section.type);
|
|
117
|
-
setValue(setSegment(section, displayValue, amount));
|
|
115
|
+
setValue((0, utils_1.setSegment)(section, displayValue, amount));
|
|
118
116
|
}
|
|
119
117
|
function adjustSection(sectionIndex, amount) {
|
|
120
118
|
const section = sectionsState.editableSections[sectionIndex];
|
|
121
119
|
if (validSegments[section.type]) {
|
|
122
|
-
setValue(addSegment(section, displayValue, amount));
|
|
120
|
+
setValue((0, utils_1.addSegment)(section, displayValue, amount));
|
|
123
121
|
}
|
|
124
122
|
else {
|
|
125
123
|
markValid(section.type);
|
|
@@ -130,7 +128,7 @@ function useDateFieldState(props) {
|
|
|
130
128
|
}
|
|
131
129
|
const enteredKeys = react_1.default.useRef('');
|
|
132
130
|
const validationState = props.validationState ||
|
|
133
|
-
((0,
|
|
131
|
+
((0, dates_1.isInvalid)(value, props.minValue, props.maxValue) ? 'invalid' : undefined) ||
|
|
134
132
|
(value && ((_a = props.isDateUnavailable) === null || _a === void 0 ? void 0 : _a.call(props, value)) ? 'invalid' : undefined);
|
|
135
133
|
return {
|
|
136
134
|
value: value !== null && value !== void 0 ? value : null,
|
|
@@ -225,6 +223,32 @@ function useDateFieldState(props) {
|
|
|
225
223
|
adjustSection(sectionIndex, -(PAGE_STEP[this.sections[sectionIndex].type] || 1));
|
|
226
224
|
}
|
|
227
225
|
},
|
|
226
|
+
incrementToMax() {
|
|
227
|
+
if (this.readOnly || this.disabled) {
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
enteredKeys.current = '';
|
|
231
|
+
const sectionIndex = getCurrentEditableSectionIndex(this.sections, selectedSections);
|
|
232
|
+
if (sectionIndex !== -1) {
|
|
233
|
+
const section = this.sections[sectionIndex];
|
|
234
|
+
if (typeof section.maxValue === 'number') {
|
|
235
|
+
setSection(section, section.maxValue);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
},
|
|
239
|
+
decrementToMin() {
|
|
240
|
+
if (this.readOnly || this.disabled) {
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
enteredKeys.current = '';
|
|
244
|
+
const sectionIndex = getCurrentEditableSectionIndex(this.sections, selectedSections);
|
|
245
|
+
if (sectionIndex !== -1) {
|
|
246
|
+
const section = this.sections[sectionIndex];
|
|
247
|
+
if (typeof section.minValue === 'number') {
|
|
248
|
+
setSection(section, section.minValue);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
},
|
|
228
252
|
clearSection() {
|
|
229
253
|
if (this.readOnly || this.disabled) {
|
|
230
254
|
return;
|
|
@@ -241,7 +265,7 @@ function useDateFieldState(props) {
|
|
|
241
265
|
const section = this.sections[sectionIndex];
|
|
242
266
|
delete validSegments[section.type];
|
|
243
267
|
setValidSegments(Object.assign({}, validSegments));
|
|
244
|
-
const placeholder = (0,
|
|
268
|
+
const placeholder = (0, dates_1.createPlaceholderValue)({
|
|
245
269
|
placeholderValue: props.placeholderValue,
|
|
246
270
|
timeZone: props.timeZone,
|
|
247
271
|
});
|
|
@@ -258,12 +282,9 @@ function useDateFieldState(props) {
|
|
|
258
282
|
}
|
|
259
283
|
}
|
|
260
284
|
else {
|
|
261
|
-
const type = getDurationUnitFromSectionType(section.type);
|
|
285
|
+
const type = (0, utils_1.getDurationUnitFromSectionType)(section.type);
|
|
262
286
|
currentValue = displayValue.set(type, placeholder[type]());
|
|
263
287
|
}
|
|
264
|
-
if (value) {
|
|
265
|
-
setDate(null);
|
|
266
|
-
}
|
|
267
288
|
setValue(currentValue);
|
|
268
289
|
},
|
|
269
290
|
clearAll() {
|
|
@@ -276,7 +297,7 @@ function useDateFieldState(props) {
|
|
|
276
297
|
if (value !== null) {
|
|
277
298
|
setDate(null);
|
|
278
299
|
}
|
|
279
|
-
setValue((0,
|
|
300
|
+
setValue((0, dates_1.createPlaceholderValue)({
|
|
280
301
|
placeholderValue: props.placeholderValue,
|
|
281
302
|
timeZone: props.timeZone,
|
|
282
303
|
}));
|
|
@@ -390,11 +411,12 @@ function useDateFieldState(props) {
|
|
|
390
411
|
}
|
|
391
412
|
},
|
|
392
413
|
setValueFromString(str) {
|
|
414
|
+
enteredKeys.current = '';
|
|
393
415
|
let date = parseDate({ input: str, format, timeZone: props.timeZone });
|
|
394
416
|
if ((0, date_utils_1.isValid)(date)) {
|
|
395
417
|
if (props.timeZone && !isDateStringWithTimeZone(str)) {
|
|
396
418
|
const time = parseDate({ input: str, format });
|
|
397
|
-
date = (0,
|
|
419
|
+
date = (0, dates_1.mergeDateTime)(date, time);
|
|
398
420
|
}
|
|
399
421
|
setDate(date);
|
|
400
422
|
return true;
|
|
@@ -414,64 +436,6 @@ function parseDate(options) {
|
|
|
414
436
|
function isDateStringWithTimeZone(str) {
|
|
415
437
|
return /z$/i.test(str) || /[+-]\d\d:\d\d$/.test(str);
|
|
416
438
|
}
|
|
417
|
-
function addSegment(section, date, amount) {
|
|
418
|
-
var _a;
|
|
419
|
-
let val = (_a = section.value) !== null && _a !== void 0 ? _a : 0;
|
|
420
|
-
if (section.type === 'dayPeriod') {
|
|
421
|
-
val = date.hour() + (date.hour() > 12 ? -12 : 12);
|
|
422
|
-
}
|
|
423
|
-
else {
|
|
424
|
-
val = val + amount;
|
|
425
|
-
const min = section.minValue;
|
|
426
|
-
const max = section.maxValue;
|
|
427
|
-
if (typeof min === 'number' && typeof max === 'number') {
|
|
428
|
-
const length = max - min + 1;
|
|
429
|
-
val = ((val - min + length) % length) + min;
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
const type = getDurationUnitFromSectionType(section.type);
|
|
433
|
-
return date.set(type, val);
|
|
434
|
-
}
|
|
435
|
-
function setSegment(section, date, amount) {
|
|
436
|
-
const type = section.type;
|
|
437
|
-
switch (type) {
|
|
438
|
-
case 'day':
|
|
439
|
-
case 'weekday':
|
|
440
|
-
case 'month':
|
|
441
|
-
case 'year': {
|
|
442
|
-
return date.set(getDurationUnitFromSectionType(type), amount);
|
|
443
|
-
}
|
|
444
|
-
case 'dayPeriod': {
|
|
445
|
-
const hours = date.hour();
|
|
446
|
-
const wasPM = hours >= 12;
|
|
447
|
-
const isPM = amount >= 12;
|
|
448
|
-
if (isPM === wasPM) {
|
|
449
|
-
return date;
|
|
450
|
-
}
|
|
451
|
-
return date.set('hour', wasPM ? hours - 12 : hours + 12);
|
|
452
|
-
}
|
|
453
|
-
case 'hour': {
|
|
454
|
-
// In 12 hour time, ensure that AM/PM does not change
|
|
455
|
-
let sectionAmount = amount;
|
|
456
|
-
if (section.minValue === 12 || section.maxValue === 11) {
|
|
457
|
-
const hours = date.hour();
|
|
458
|
-
const wasPM = hours >= 12;
|
|
459
|
-
if (!wasPM && sectionAmount === 12) {
|
|
460
|
-
sectionAmount = 0;
|
|
461
|
-
}
|
|
462
|
-
if (wasPM && sectionAmount < 12) {
|
|
463
|
-
sectionAmount += 12;
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
|
-
return date.set('hour', sectionAmount);
|
|
467
|
-
}
|
|
468
|
-
case 'minute':
|
|
469
|
-
case 'second': {
|
|
470
|
-
return date.set(type, amount);
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
return date;
|
|
474
|
-
}
|
|
475
439
|
function getCurrentEditableSectionIndex(sections, selectedSections) {
|
|
476
440
|
const currentIndex = selectedSections === 'all' || selectedSections === -1 ? 0 : selectedSections;
|
|
477
441
|
const section = sections[currentIndex];
|
|
@@ -521,9 +485,13 @@ function getEditableSections(sections, value, validSegments) {
|
|
|
521
485
|
let renderedValue = section.placeholder;
|
|
522
486
|
if ((isEditable && validSegments[section.type]) || section.type === 'timeZoneName') {
|
|
523
487
|
renderedValue = value.format(section.format);
|
|
488
|
+
if (section.contentType === 'digit' &&
|
|
489
|
+
renderedValue.length < section.placeholder.length) {
|
|
490
|
+
renderedValue = renderedValue.padStart(section.placeholder.length, '0');
|
|
491
|
+
}
|
|
524
492
|
}
|
|
525
493
|
const sectionLength = renderedValue.length;
|
|
526
|
-
const newSection = Object.assign(Object.assign(Object.assign({}, section), { value:
|
|
494
|
+
const newSection = Object.assign(Object.assign(Object.assign({}, section), { value: (0, utils_1.getSectionValue)(section, value), textValue: renderedValue, start: position, end: position + sectionLength, modified: false, previousEditableSection, nextEditableSection: previousEditableSection }), (0, utils_1.getSectionLimits)(section, value));
|
|
527
495
|
newSections.push(newSection);
|
|
528
496
|
if (isEditable) {
|
|
529
497
|
for (let j = Math.max(0, previousEditableSection); j <= i; j++) {
|
|
@@ -541,88 +509,3 @@ function getEditableSections(sections, value, validSegments) {
|
|
|
541
509
|
}
|
|
542
510
|
return newSections;
|
|
543
511
|
}
|
|
544
|
-
function getValue(date, type) {
|
|
545
|
-
switch (type) {
|
|
546
|
-
case 'year':
|
|
547
|
-
case 'month':
|
|
548
|
-
case 'hour':
|
|
549
|
-
case 'minute':
|
|
550
|
-
case 'second': {
|
|
551
|
-
return date[type]();
|
|
552
|
-
}
|
|
553
|
-
case 'day': {
|
|
554
|
-
return date.date();
|
|
555
|
-
}
|
|
556
|
-
case 'weekday': {
|
|
557
|
-
return date.day();
|
|
558
|
-
}
|
|
559
|
-
case 'dayPeriod': {
|
|
560
|
-
return date.hour() >= 12 ? 12 : 0;
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
return undefined;
|
|
564
|
-
}
|
|
565
|
-
function isHour12(section) {
|
|
566
|
-
if (section.type === 'hour') {
|
|
567
|
-
return (0, date_utils_1.dateTime)().set('hour', 15).format(section.format) !== '15';
|
|
568
|
-
}
|
|
569
|
-
return false;
|
|
570
|
-
}
|
|
571
|
-
function getSectionLimits(date, type, options) {
|
|
572
|
-
switch (type) {
|
|
573
|
-
case 'year': {
|
|
574
|
-
return {
|
|
575
|
-
minValue: 1,
|
|
576
|
-
maxValue: 9999,
|
|
577
|
-
};
|
|
578
|
-
}
|
|
579
|
-
case 'month': {
|
|
580
|
-
return {
|
|
581
|
-
minValue: 0,
|
|
582
|
-
maxValue: 11,
|
|
583
|
-
};
|
|
584
|
-
}
|
|
585
|
-
case 'weekday': {
|
|
586
|
-
return {
|
|
587
|
-
minValue: 0,
|
|
588
|
-
maxValue: 6,
|
|
589
|
-
};
|
|
590
|
-
}
|
|
591
|
-
case 'day': {
|
|
592
|
-
return {
|
|
593
|
-
minValue: 1,
|
|
594
|
-
maxValue: date ? date.daysInMonth() : 31,
|
|
595
|
-
};
|
|
596
|
-
}
|
|
597
|
-
case 'hour': {
|
|
598
|
-
if (options.hour12) {
|
|
599
|
-
const isPM = date.hour() >= 12;
|
|
600
|
-
return {
|
|
601
|
-
minValue: isPM ? 12 : 0,
|
|
602
|
-
maxValue: isPM ? 23 : 11,
|
|
603
|
-
};
|
|
604
|
-
}
|
|
605
|
-
return {
|
|
606
|
-
minValue: 0,
|
|
607
|
-
maxValue: 23,
|
|
608
|
-
};
|
|
609
|
-
}
|
|
610
|
-
case 'minute':
|
|
611
|
-
case 'second': {
|
|
612
|
-
return {
|
|
613
|
-
minValue: 0,
|
|
614
|
-
maxValue: 59,
|
|
615
|
-
};
|
|
616
|
-
}
|
|
617
|
-
}
|
|
618
|
-
return {};
|
|
619
|
-
}
|
|
620
|
-
function getDurationUnitFromSectionType(type) {
|
|
621
|
-
if (type === 'literal' || type === 'timeZoneName' || type === 'unknown') {
|
|
622
|
-
throw new Error(`${type} section does not have duration unit.`);
|
|
623
|
-
}
|
|
624
|
-
if (type in TYPE_MAPPING) {
|
|
625
|
-
return TYPE_MAPPING[type];
|
|
626
|
-
}
|
|
627
|
-
return type;
|
|
628
|
-
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type DateFieldSectionType =
|
|
1
|
+
export type DateFieldSectionType = Extract<Intl.DateTimeFormatPartTypes, 'day' | 'dayPeriod' | 'hour' | 'literal' | 'minute' | 'month' | 'second' | 'timeZoneName' | 'weekday' | 'year' | 'unknown'>;
|
|
2
2
|
export type DateFormatTokenMap = {
|
|
3
3
|
[formatToken: string]: DateFieldSectionType | {
|
|
4
4
|
sectionType: DateFieldSectionType;
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import type { DateTime } from '@gravity-ui/date-utils';
|
|
2
|
-
import type { DateFieldSectionWithoutPosition } from './types';
|
|
2
|
+
import type { DateFieldSection, DateFieldSectionType, DateFieldSectionWithoutPosition } from './types';
|
|
3
3
|
export declare const isMac: boolean;
|
|
4
4
|
export declare const CtrlCmd: string;
|
|
5
5
|
export declare function expandFormat(format: string): string;
|
|
6
|
+
export declare function getSectionLimits(section: DateFieldSectionWithoutPosition, date: DateTime): {
|
|
7
|
+
minValue: number;
|
|
8
|
+
maxValue: number;
|
|
9
|
+
} | {
|
|
10
|
+
minValue?: undefined;
|
|
11
|
+
maxValue?: undefined;
|
|
12
|
+
};
|
|
13
|
+
export declare function getSectionValue(sections: DateFieldSectionWithoutPosition, date: DateTime): number | undefined;
|
|
14
|
+
export declare function getDurationUnitFromSectionType(type: DateFieldSectionType): "year" | "month" | "day" | "date" | "hour" | "minute" | "second";
|
|
15
|
+
export declare function addSegment(section: DateFieldSection, date: DateTime, amount: number): DateTime;
|
|
16
|
+
export declare function setSegment(section: DateFieldSection, date: DateTime, amount: number): DateTime;
|
|
6
17
|
export declare function splitFormatIntoSections(format: string): DateFieldSectionWithoutPosition[];
|
|
7
|
-
interface PlaceholderValueOptions {
|
|
8
|
-
placeholderValue?: DateTime;
|
|
9
|
-
timeZone?: string;
|
|
10
|
-
}
|
|
11
|
-
export declare function createPlaceholderValue({ placeholderValue, timeZone }: PlaceholderValueOptions): DateTime;
|
|
12
|
-
export declare function isInvalid(value: DateTime | null | undefined, minValue: DateTime | undefined, maxValue: DateTime | undefined): boolean;
|
|
13
|
-
export declare function mergeDateTime(date: DateTime, time: DateTime): DateTime;
|
|
14
|
-
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.splitFormatIntoSections = exports.setSegment = exports.addSegment = exports.getDurationUnitFromSectionType = exports.getSectionValue = exports.getSectionLimits = exports.expandFormat = exports.CtrlCmd = exports.isMac = void 0;
|
|
4
4
|
const date_utils_1 = require("@gravity-ui/date-utils");
|
|
5
5
|
const i18n_1 = require("./i18n");
|
|
6
6
|
exports.isMac = window.navigator.userAgent.indexOf('Macintosh') >= 0;
|
|
@@ -81,6 +81,173 @@ function getDateSectionConfigFromFormatToken(formatToken) {
|
|
|
81
81
|
function isFourDigitYearFormat(format) {
|
|
82
82
|
return (0, date_utils_1.dateTime)().format(format).length === 4;
|
|
83
83
|
}
|
|
84
|
+
function isHour12(format) {
|
|
85
|
+
return (0, date_utils_1.dateTime)().set('hour', 15).format(format) !== '15';
|
|
86
|
+
}
|
|
87
|
+
function getSectionLimits(section, date) {
|
|
88
|
+
const { type, format } = section;
|
|
89
|
+
switch (type) {
|
|
90
|
+
case 'year': {
|
|
91
|
+
const isFourDigit = isFourDigitYearFormat(format);
|
|
92
|
+
return {
|
|
93
|
+
minValue: isFourDigit ? 1 : 0,
|
|
94
|
+
maxValue: isFourDigit ? 9999 : 99,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
case 'month': {
|
|
98
|
+
return {
|
|
99
|
+
minValue: 0,
|
|
100
|
+
maxValue: 11,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
case 'weekday': {
|
|
104
|
+
return {
|
|
105
|
+
minValue: 0,
|
|
106
|
+
maxValue: 6,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
case 'day': {
|
|
110
|
+
return {
|
|
111
|
+
minValue: 1,
|
|
112
|
+
maxValue: date ? date.daysInMonth() : 31,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
case 'hour': {
|
|
116
|
+
if (isHour12(format)) {
|
|
117
|
+
const isPM = date.hour() >= 12;
|
|
118
|
+
return {
|
|
119
|
+
minValue: isPM ? 12 : 0,
|
|
120
|
+
maxValue: isPM ? 23 : 11,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
minValue: 0,
|
|
125
|
+
maxValue: 23,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
case 'minute':
|
|
129
|
+
case 'second': {
|
|
130
|
+
return {
|
|
131
|
+
minValue: 0,
|
|
132
|
+
maxValue: 59,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return {};
|
|
137
|
+
}
|
|
138
|
+
exports.getSectionLimits = getSectionLimits;
|
|
139
|
+
function getSectionValue(sections, date) {
|
|
140
|
+
const type = sections.type;
|
|
141
|
+
switch (type) {
|
|
142
|
+
case 'year': {
|
|
143
|
+
return isFourDigitYearFormat(sections.format)
|
|
144
|
+
? date.year()
|
|
145
|
+
: Number(date.format(sections.format));
|
|
146
|
+
}
|
|
147
|
+
case 'month':
|
|
148
|
+
case 'hour':
|
|
149
|
+
case 'minute':
|
|
150
|
+
case 'second': {
|
|
151
|
+
return date[type]();
|
|
152
|
+
}
|
|
153
|
+
case 'day': {
|
|
154
|
+
return date.date();
|
|
155
|
+
}
|
|
156
|
+
case 'weekday': {
|
|
157
|
+
return date.day();
|
|
158
|
+
}
|
|
159
|
+
case 'dayPeriod': {
|
|
160
|
+
return date.hour() >= 12 ? 12 : 0;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return undefined;
|
|
164
|
+
}
|
|
165
|
+
exports.getSectionValue = getSectionValue;
|
|
166
|
+
const TYPE_MAPPING = {
|
|
167
|
+
weekday: 'day',
|
|
168
|
+
day: 'date',
|
|
169
|
+
dayPeriod: 'hour',
|
|
170
|
+
};
|
|
171
|
+
function getDurationUnitFromSectionType(type) {
|
|
172
|
+
if (type === 'literal' || type === 'timeZoneName' || type === 'unknown') {
|
|
173
|
+
throw new Error(`${type} section does not have duration unit.`);
|
|
174
|
+
}
|
|
175
|
+
if (type in TYPE_MAPPING) {
|
|
176
|
+
return TYPE_MAPPING[type];
|
|
177
|
+
}
|
|
178
|
+
return type;
|
|
179
|
+
}
|
|
180
|
+
exports.getDurationUnitFromSectionType = getDurationUnitFromSectionType;
|
|
181
|
+
function addSegment(section, date, amount) {
|
|
182
|
+
var _a;
|
|
183
|
+
let val = (_a = section.value) !== null && _a !== void 0 ? _a : 0;
|
|
184
|
+
if (section.type === 'dayPeriod') {
|
|
185
|
+
val = date.hour() + (date.hour() > 12 ? -12 : 12);
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
val = val + amount;
|
|
189
|
+
const min = section.minValue;
|
|
190
|
+
const max = section.maxValue;
|
|
191
|
+
if (typeof min === 'number' && typeof max === 'number') {
|
|
192
|
+
const length = max - min + 1;
|
|
193
|
+
val = ((val - min + length) % length) + min;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
if (section.type === 'year' && !isFourDigitYearFormat(section.format)) {
|
|
197
|
+
val = (0, date_utils_1.dateTime)({ input: `${val}`.padStart(2, '0'), format: section.format }).year();
|
|
198
|
+
}
|
|
199
|
+
const type = getDurationUnitFromSectionType(section.type);
|
|
200
|
+
return date.set(type, val);
|
|
201
|
+
}
|
|
202
|
+
exports.addSegment = addSegment;
|
|
203
|
+
function setSegment(section, date, amount) {
|
|
204
|
+
const type = section.type;
|
|
205
|
+
switch (type) {
|
|
206
|
+
case 'year': {
|
|
207
|
+
return date.set('year', isFourDigitYearFormat(section.format)
|
|
208
|
+
? amount
|
|
209
|
+
: (0, date_utils_1.dateTime)({
|
|
210
|
+
input: `${amount}`.padStart(2, '0'),
|
|
211
|
+
format: section.format,
|
|
212
|
+
}).year());
|
|
213
|
+
}
|
|
214
|
+
case 'day':
|
|
215
|
+
case 'weekday':
|
|
216
|
+
case 'month': {
|
|
217
|
+
return date.set(getDurationUnitFromSectionType(type), amount);
|
|
218
|
+
}
|
|
219
|
+
case 'dayPeriod': {
|
|
220
|
+
const hours = date.hour();
|
|
221
|
+
const wasPM = hours >= 12;
|
|
222
|
+
const isPM = amount >= 12;
|
|
223
|
+
if (isPM === wasPM) {
|
|
224
|
+
return date;
|
|
225
|
+
}
|
|
226
|
+
return date.set('hour', wasPM ? hours - 12 : hours + 12);
|
|
227
|
+
}
|
|
228
|
+
case 'hour': {
|
|
229
|
+
// In 12 hour time, ensure that AM/PM does not change
|
|
230
|
+
let sectionAmount = amount;
|
|
231
|
+
if (section.minValue === 12 || section.maxValue === 11) {
|
|
232
|
+
const hours = date.hour();
|
|
233
|
+
const wasPM = hours >= 12;
|
|
234
|
+
if (!wasPM && sectionAmount === 12) {
|
|
235
|
+
sectionAmount = 0;
|
|
236
|
+
}
|
|
237
|
+
if (wasPM && sectionAmount < 12) {
|
|
238
|
+
sectionAmount += 12;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
return date.set('hour', sectionAmount);
|
|
242
|
+
}
|
|
243
|
+
case 'minute':
|
|
244
|
+
case 'second': {
|
|
245
|
+
return date.set(type, amount);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
return date;
|
|
249
|
+
}
|
|
250
|
+
exports.setSegment = setSegment;
|
|
84
251
|
function doesSectionHaveLeadingZeros(contentType, sectionType, format) {
|
|
85
252
|
if (contentType !== 'digit') {
|
|
86
253
|
return false;
|
|
@@ -250,27 +417,3 @@ function getSectionOptions(section, token) {
|
|
|
250
417
|
}
|
|
251
418
|
return undefined;
|
|
252
419
|
}
|
|
253
|
-
function createPlaceholderValue({ placeholderValue, timeZone }) {
|
|
254
|
-
return (placeholderValue !== null && placeholderValue !== void 0 ? placeholderValue : (0, date_utils_1.dateTime)({ timeZone }).set('hour', 0).set('minute', 0).set('second', 0));
|
|
255
|
-
}
|
|
256
|
-
exports.createPlaceholderValue = createPlaceholderValue;
|
|
257
|
-
function isInvalid(value, minValue, maxValue) {
|
|
258
|
-
if (!value) {
|
|
259
|
-
return false;
|
|
260
|
-
}
|
|
261
|
-
if (minValue && value.isBefore(minValue)) {
|
|
262
|
-
return true;
|
|
263
|
-
}
|
|
264
|
-
if (maxValue && maxValue.isBefore(value)) {
|
|
265
|
-
return true;
|
|
266
|
-
}
|
|
267
|
-
return false;
|
|
268
|
-
}
|
|
269
|
-
exports.isInvalid = isInvalid;
|
|
270
|
-
function mergeDateTime(date, time) {
|
|
271
|
-
return date
|
|
272
|
-
.set('hours', time.hour())
|
|
273
|
-
.set('minutes', time.minute())
|
|
274
|
-
.set('seconds', time.second());
|
|
275
|
-
}
|
|
276
|
-
exports.mergeDateTime = mergeDateTime;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
.g-date-date-picker {
|
|
2
2
|
position: relative;
|
|
3
3
|
display: inline-block;
|
|
4
|
+
outline: none;
|
|
4
5
|
}
|
|
5
6
|
.g-date-date-picker__field {
|
|
6
7
|
width: 100%;
|
|
@@ -8,6 +9,11 @@
|
|
|
8
9
|
.g-date-date-picker__field_mobile {
|
|
9
10
|
pointer-events: none;
|
|
10
11
|
}
|
|
12
|
+
.g-date-date-picker__popup-anchor {
|
|
13
|
+
position: absolute;
|
|
14
|
+
z-index: -1;
|
|
15
|
+
inset: 0;
|
|
16
|
+
}
|
|
11
17
|
.g-date-date-picker__popup-content {
|
|
12
18
|
outline: none;
|
|
13
19
|
}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type CalendarProps } from '../Calendar';
|
|
1
3
|
import type { AccessibilityProps, DateFieldBase, DomProps, FocusableProps, KeyboardEvents, StyleProps, TextInputProps } from '../types';
|
|
2
4
|
import './DatePicker.css';
|
|
3
5
|
export interface DatePickerProps extends DateFieldBase, TextInputProps, FocusableProps, KeyboardEvents, DomProps, StyleProps, AccessibilityProps {
|
|
6
|
+
children?: (props: CalendarProps) => React.ReactNode;
|
|
4
7
|
}
|
|
5
|
-
export declare function DatePicker({ value, defaultValue, onUpdate, className,
|
|
8
|
+
export declare function DatePicker({ value, defaultValue, onUpdate, className, ...props }: DatePickerProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -17,50 +17,23 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
17
17
|
exports.DatePicker = void 0;
|
|
18
18
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
19
19
|
const react_1 = __importDefault(require("react"));
|
|
20
|
+
const icons_1 = require("@gravity-ui/icons");
|
|
20
21
|
const uikit_1 = require("@gravity-ui/uikit");
|
|
22
|
+
const Calendar_1 = require("../Calendar");
|
|
21
23
|
const DateField_1 = require("../DateField");
|
|
22
|
-
const DesktopCalendar_1 = require("./DesktopCalendar");
|
|
23
24
|
const MobileCalendar_1 = require("./MobileCalendar");
|
|
25
|
+
const useDatePickerProps_1 = require("./hooks/useDatePickerProps");
|
|
24
26
|
const useDatePickerState_1 = require("./hooks/useDatePickerState");
|
|
25
27
|
const utils_1 = require("./utils");
|
|
26
28
|
require("./DatePicker.css");
|
|
27
29
|
function DatePicker(_a) {
|
|
28
|
-
var { value, defaultValue, onUpdate, className
|
|
30
|
+
var { value, defaultValue, onUpdate, className } = _a, props = __rest(_a, ["value", "defaultValue", "onUpdate", "className"]);
|
|
29
31
|
const anchorRef = react_1.default.useRef(null);
|
|
30
32
|
const state = (0, useDatePickerState_1.useDatePickerState)(Object.assign(Object.assign({}, props), { value,
|
|
31
33
|
defaultValue,
|
|
32
34
|
onUpdate }));
|
|
35
|
+
const { groupProps, fieldProps, calendarButtonProps, popupProps, calendarProps, timeInputProps } = (0, useDatePickerProps_1.useDatePickerProps)(state, props);
|
|
33
36
|
const [isMobile] = (0, uikit_1.useMobile)();
|
|
34
|
-
|
|
35
|
-
const { focusWithinProps } = (0, uikit_1.useFocusWithin)({
|
|
36
|
-
onFocusWithin: onFocus,
|
|
37
|
-
onBlurWithin: onBlur,
|
|
38
|
-
onFocusWithinChange(isFocusWithin) {
|
|
39
|
-
setActive(isFocusWithin);
|
|
40
|
-
},
|
|
41
|
-
});
|
|
42
|
-
const fieldState = (0, DateField_1.useDateFieldState)({
|
|
43
|
-
value: state.value,
|
|
44
|
-
onUpdate: state.setValue,
|
|
45
|
-
disabled: state.disabled,
|
|
46
|
-
readOnly: state.readOnly,
|
|
47
|
-
validationState: props.validationState,
|
|
48
|
-
minValue: props.minValue,
|
|
49
|
-
maxValue: props.maxValue,
|
|
50
|
-
isDateUnavailable: props.isDateUnavailable,
|
|
51
|
-
format: state.format,
|
|
52
|
-
placeholderValue: props.placeholderValue,
|
|
53
|
-
timeZone: props.timeZone,
|
|
54
|
-
});
|
|
55
|
-
const { inputProps } = (0, DateField_1.useDateFieldProps)(fieldState, props);
|
|
56
|
-
return (
|
|
57
|
-
// eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions
|
|
58
|
-
(0, jsx_runtime_1.jsxs)("div", Object.assign({ ref: anchorRef, className: (0, utils_1.b)(null, className), style: props.style }, focusWithinProps, { role: "group", "aria-disabled": state.disabled || undefined, onKeyDown: (e) => {
|
|
59
|
-
if (e.altKey && (e.key === 'ArrowDown' || e.key === 'ArrowUp')) {
|
|
60
|
-
e.preventDefault();
|
|
61
|
-
e.stopPropagation();
|
|
62
|
-
state.setOpen(true);
|
|
63
|
-
}
|
|
64
|
-
}, children: [isMobile ? ((0, jsx_runtime_1.jsx)(MobileCalendar_1.MobileCalendar, { props: props, state: state })) : ((0, jsx_runtime_1.jsx)(DesktopCalendar_1.DesktopCalendar, { anchorRef: anchorRef, props: props, state: state })), (0, jsx_runtime_1.jsx)(uikit_1.TextInput, Object.assign({}, inputProps, { value: fieldState.isEmpty && !isActive && props.placeholder ? '' : inputProps.value, className: (0, utils_1.b)('field', { mobile: isMobile }), hasClear: !isMobile && inputProps.hasClear, rightContent: isMobile ? ((0, jsx_runtime_1.jsx)(MobileCalendar_1.MobileCalendarIcon, { props: props, state: state })) : ((0, jsx_runtime_1.jsx)(DesktopCalendar_1.DesktopCalendarButton, { props: props, state: state })) }))] })));
|
|
37
|
+
return ((0, jsx_runtime_1.jsxs)("div", Object.assign({ className: (0, utils_1.b)(null, className) }, groupProps, { children: [isMobile ? ((0, jsx_runtime_1.jsx)(MobileCalendar_1.MobileCalendar, { props: props, state: state })) : ((0, jsx_runtime_1.jsx)("div", { ref: anchorRef, className: (0, utils_1.b)('popup-anchor'), children: (0, jsx_runtime_1.jsx)(uikit_1.Popup, Object.assign({ anchorRef: anchorRef }, popupProps, { children: (0, jsx_runtime_1.jsxs)("div", { className: (0, utils_1.b)('popup-content'), children: [typeof props.children === 'function' ? (props.children(calendarProps)) : ((0, jsx_runtime_1.jsx)(Calendar_1.Calendar, Object.assign({}, calendarProps))), state.hasTime && ((0, jsx_runtime_1.jsx)("div", { className: (0, utils_1.b)('time-field-wrapper'), children: (0, jsx_runtime_1.jsx)(DateField_1.DateField, Object.assign({}, timeInputProps)) }))] }) })) })), (0, jsx_runtime_1.jsx)(uikit_1.TextInput, Object.assign({}, fieldProps, { className: (0, utils_1.b)('field', { mobile: isMobile }), hasClear: !isMobile && fieldProps.hasClear, rightContent: isMobile ? ((0, jsx_runtime_1.jsx)(MobileCalendar_1.MobileCalendarIcon, { props: props, state: state })) : ((0, jsx_runtime_1.jsx)(uikit_1.Button, Object.assign({}, calendarButtonProps, { children: (0, jsx_runtime_1.jsx)(uikit_1.Icon, { data: icons_1.Calendar }) }))) }))] })));
|
|
65
38
|
}
|
|
66
39
|
exports.DatePicker = DatePicker;
|