@gravity-ui/date-components 2.0.1 → 2.2.0
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/CalendarView/hooks/useCalendarProps.js +17 -0
- package/dist/cjs/components/CalendarView/i18n/en.json +4 -1
- package/dist/cjs/components/CalendarView/i18n/index.d.ts +1 -1
- package/dist/cjs/components/CalendarView/i18n/ru.json +4 -1
- package/dist/cjs/components/DateField/hooks/useBaseDateFieldState.d.ts +2 -2
- package/dist/cjs/components/DateField/hooks/useDateFieldProps.d.ts +2 -2
- package/dist/cjs/components/DateField/hooks/useDateFieldState.d.ts +1 -2
- package/dist/cjs/components/DateField/utils.js +2 -1
- package/dist/cjs/components/DatePicker/DatePicker.d.ts +3 -2
- package/dist/cjs/components/DatePicker/DatePicker.js +3 -1
- package/dist/cjs/components/DatePicker/MobileCalendar.css +1 -26
- package/dist/cjs/components/DatePicker/MobileCalendar.d.ts +0 -5
- package/dist/cjs/components/DatePicker/MobileCalendar.js +2 -9
- package/dist/cjs/components/DatePicker/StubButton.css +26 -0
- package/dist/cjs/components/DatePicker/StubButton.d.ts +8 -0
- package/dist/cjs/components/DatePicker/StubButton.js +12 -0
- package/dist/cjs/components/DatePicker/hooks/datePickerStateFactory.d.ts +49 -0
- package/dist/cjs/components/DatePicker/hooks/datePickerStateFactory.js +121 -0
- package/dist/cjs/components/DatePicker/hooks/useDatePickerProps.d.ts +9 -5
- package/dist/cjs/components/DatePicker/hooks/useDatePickerProps.js +4 -2
- package/dist/cjs/components/DatePicker/hooks/useDatePickerState.d.ts +2 -41
- package/dist/cjs/components/DatePicker/hooks/useDatePickerState.js +11 -131
- package/dist/cjs/components/DatePicker/{utils.js → utils/cn.js} +1 -1
- package/dist/cjs/components/DatePicker/utils/getDateTimeValue.d.ts +3 -0
- package/dist/cjs/components/DatePicker/utils/getDateTimeValue.js +10 -0
- package/dist/cjs/components/DatePicker/utils/index.d.ts +2 -0
- package/dist/cjs/components/DatePicker/utils/index.js +5 -0
- package/dist/cjs/components/RangeCalendar/RangeCalendar.d.ts +5 -10
- package/dist/cjs/components/RangeDateField/hooks/useRangeDateFieldState.d.ts +2 -2
- package/dist/cjs/components/RangeDatePicker/RangeDatePicker.css +22 -0
- package/dist/cjs/components/RangeDatePicker/RangeDatePicker.d.ts +6 -0
- package/dist/cjs/components/RangeDatePicker/RangeDatePicker.js +25 -0
- package/dist/cjs/components/RangeDatePicker/hooks/useRangeDatePickerState.d.ts +7 -0
- package/dist/cjs/components/RangeDatePicker/hooks/useRangeDatePickerState.js +28 -0
- package/dist/cjs/components/RangeDatePicker/index.d.ts +2 -0
- package/dist/cjs/components/RangeDatePicker/index.js +5 -0
- package/dist/cjs/components/RelativeDatePicker/RelativeDatePicker.js +4 -2
- package/dist/cjs/components/RelativeRangeDatePicker/components/Presets/PresetsDoc.js +3 -3
- package/dist/esm/components/CalendarView/hooks/useCalendarProps.js +17 -0
- package/dist/esm/components/CalendarView/i18n/en.json +4 -1
- package/dist/esm/components/CalendarView/i18n/index.d.ts +1 -1
- package/dist/esm/components/CalendarView/i18n/ru.json +4 -1
- package/dist/esm/components/DateField/hooks/useBaseDateFieldState.d.ts +2 -2
- package/dist/esm/components/DateField/hooks/useDateFieldProps.d.ts +2 -2
- package/dist/esm/components/DateField/hooks/useDateFieldState.d.ts +1 -2
- package/dist/esm/components/DateField/utils.js +2 -1
- package/dist/esm/components/DatePicker/DatePicker.d.ts +3 -2
- package/dist/esm/components/DatePicker/DatePicker.js +5 -3
- package/dist/esm/components/DatePicker/MobileCalendar.css +1 -26
- package/dist/esm/components/DatePicker/MobileCalendar.d.ts +0 -5
- package/dist/esm/components/DatePicker/MobileCalendar.js +1 -7
- package/dist/esm/components/DatePicker/StubButton.css +26 -0
- package/dist/esm/components/DatePicker/StubButton.d.ts +8 -0
- package/dist/esm/components/DatePicker/StubButton.js +8 -0
- package/dist/esm/components/DatePicker/hooks/datePickerStateFactory.d.ts +49 -0
- package/dist/esm/components/DatePicker/hooks/datePickerStateFactory.js +116 -0
- package/dist/esm/components/DatePicker/hooks/useDatePickerProps.d.ts +9 -5
- package/dist/esm/components/DatePicker/hooks/useDatePickerProps.js +4 -2
- package/dist/esm/components/DatePicker/hooks/useDatePickerState.d.ts +2 -41
- package/dist/esm/components/DatePicker/hooks/useDatePickerState.js +11 -129
- package/dist/esm/components/DatePicker/utils/cn.js +2 -0
- package/dist/esm/components/DatePicker/utils/getDateTimeValue.d.ts +3 -0
- package/dist/esm/components/DatePicker/utils/getDateTimeValue.js +6 -0
- package/dist/esm/components/DatePicker/utils/index.d.ts +2 -0
- package/dist/esm/components/DatePicker/utils/index.js +2 -0
- package/dist/esm/components/RangeCalendar/RangeCalendar.d.ts +5 -10
- package/dist/esm/components/RangeDateField/hooks/useRangeDateFieldState.d.ts +2 -2
- package/dist/esm/components/RangeDatePicker/RangeDatePicker.css +22 -0
- package/dist/esm/components/RangeDatePicker/RangeDatePicker.d.ts +6 -0
- package/dist/esm/components/RangeDatePicker/RangeDatePicker.js +21 -0
- package/dist/esm/components/RangeDatePicker/hooks/useRangeDatePickerState.d.ts +7 -0
- package/dist/esm/components/RangeDatePicker/hooks/useRangeDatePickerState.js +25 -0
- package/dist/esm/components/RangeDatePicker/index.d.ts +2 -0
- package/dist/esm/components/RangeDatePicker/index.js +2 -0
- package/dist/esm/components/RelativeDatePicker/RelativeDatePicker.js +6 -4
- package/dist/esm/components/RelativeRangeDatePicker/components/Presets/PresetsDoc.js +3 -3
- package/package.json +2 -2
- package/dist/esm/components/DatePicker/utils.js +0 -2
- /package/dist/cjs/components/DatePicker/{utils.d.ts → utils/cn.d.ts} +0 -0
- /package/dist/esm/components/DatePicker/{utils.d.ts → utils/cn.d.ts} +0 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
.g-date-stub-button {
|
|
2
|
+
position: relative;
|
|
3
|
+
display: inline-block;
|
|
4
|
+
width: 24px;
|
|
5
|
+
height: 24px;
|
|
6
|
+
}
|
|
7
|
+
.g-date-stub-button_size_xs {
|
|
8
|
+
width: 20px;
|
|
9
|
+
height: 20px;
|
|
10
|
+
}
|
|
11
|
+
.g-date-stub-button_size_m {
|
|
12
|
+
width: 28px;
|
|
13
|
+
height: 28px;
|
|
14
|
+
}
|
|
15
|
+
.g-date-stub-button_size_l {
|
|
16
|
+
width: 36px;
|
|
17
|
+
height: 36px;
|
|
18
|
+
}
|
|
19
|
+
.g-date-stub-button__icon {
|
|
20
|
+
position: absolute;
|
|
21
|
+
inset: 0;
|
|
22
|
+
display: flex;
|
|
23
|
+
justify-content: center;
|
|
24
|
+
align-items: center;
|
|
25
|
+
color: var(--g-color-text-secondary);
|
|
26
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ButtonSize, IconData } from '@gravity-ui/uikit';
|
|
2
|
+
import './StubButton.css';
|
|
3
|
+
interface StubButtonProps {
|
|
4
|
+
size?: ButtonSize;
|
|
5
|
+
icon: IconData;
|
|
6
|
+
}
|
|
7
|
+
export declare function StubButton({ size, icon }: StubButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Icon } from '@gravity-ui/uikit';
|
|
3
|
+
import { block } from '../../utils/cn';
|
|
4
|
+
import './StubButton.css';
|
|
5
|
+
const b = block('stub-button');
|
|
6
|
+
export function StubButton({ size, icon }) {
|
|
7
|
+
return (_jsx("span", { className: b({ size }), children: _jsx("span", { className: b('icon'), children: _jsx(Icon, { data: icon }) }) }));
|
|
8
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { DateTime } from '@gravity-ui/date-utils';
|
|
2
|
+
import type { DateFieldState } from '../../DateField';
|
|
3
|
+
import type { DateFieldBase } from '../../types';
|
|
4
|
+
export interface DatePickerState<T = DateTime> {
|
|
5
|
+
/** The currently selected date. */
|
|
6
|
+
value: T | null;
|
|
7
|
+
/** Sets the selected date. */
|
|
8
|
+
setValue: (value: T | null) => void;
|
|
9
|
+
/**
|
|
10
|
+
* The date portion of the value. This may be set prior to `value` if the user has
|
|
11
|
+
* selected a date but has not yet selected a time.
|
|
12
|
+
*/
|
|
13
|
+
dateValue: T | null;
|
|
14
|
+
/** Sets the date portion of the value. */
|
|
15
|
+
setDateValue: (value: T) => void;
|
|
16
|
+
/**
|
|
17
|
+
* The time portion of the value. This may be set prior to `value` if the user has
|
|
18
|
+
* selected a time but has not yet selected a date.
|
|
19
|
+
*/
|
|
20
|
+
timeValue: T | null;
|
|
21
|
+
/** Sets the time portion of the value. */
|
|
22
|
+
setTimeValue: (value: T | null) => void;
|
|
23
|
+
/** Whether the field is read only. */
|
|
24
|
+
readOnly?: boolean;
|
|
25
|
+
/** Whether the field is disabled. */
|
|
26
|
+
disabled?: boolean;
|
|
27
|
+
/** Format of the date when rendered in the input. */
|
|
28
|
+
format: string;
|
|
29
|
+
/** Whether the date picker supports selecting a date. */
|
|
30
|
+
hasDate: boolean;
|
|
31
|
+
/** Whether the date picker supports selecting a time. */
|
|
32
|
+
hasTime: boolean;
|
|
33
|
+
/** Format of the time when rendered in the input. */
|
|
34
|
+
timeFormat?: string;
|
|
35
|
+
timeZone: string;
|
|
36
|
+
/** Whether the calendar popover is currently open. */
|
|
37
|
+
isOpen: boolean;
|
|
38
|
+
/** Sets whether the calendar popover is open. */
|
|
39
|
+
setOpen: (isOpen: boolean) => void;
|
|
40
|
+
dateFieldState: DateFieldState<T>;
|
|
41
|
+
}
|
|
42
|
+
export interface DatePickerStateFactoryOptions<T, O extends DateFieldBase<T>> {
|
|
43
|
+
getPlaceholderTime: (placeholderValue: DateTime | undefined, timeZone?: string) => T;
|
|
44
|
+
mergeDateTime: (date: T, time: T) => T;
|
|
45
|
+
setTimezone: (date: T, timeZone: string) => T;
|
|
46
|
+
getDateTime: (date: T | null | undefined) => DateTime | undefined;
|
|
47
|
+
useDateFieldState: (props: O) => DateFieldState<T>;
|
|
48
|
+
}
|
|
49
|
+
export declare function datePickerStateFactory<T, O extends DateFieldBase<T>>({ getPlaceholderTime, mergeDateTime, setTimezone, getDateTime, useDateFieldState, }: DatePickerStateFactoryOptions<T, O>): (props: O) => DatePickerState<T>;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useControlledState } from '@gravity-ui/uikit';
|
|
3
|
+
import { useDefaultTimeZone } from '../../utils/useDefaultTimeZone';
|
|
4
|
+
export function datePickerStateFactory({ getPlaceholderTime, mergeDateTime, setTimezone, getDateTime, useDateFieldState, }) {
|
|
5
|
+
return function useDatePickerState(props) {
|
|
6
|
+
var _a;
|
|
7
|
+
const { disabled, readOnly } = props;
|
|
8
|
+
const [isOpen, setOpen] = React.useState(false);
|
|
9
|
+
const [value, setValue] = useControlledState(props.value, (_a = props.defaultValue) !== null && _a !== void 0 ? _a : null, props.onUpdate);
|
|
10
|
+
const [selectedDateInner, setSelectedDate] = React.useState(null);
|
|
11
|
+
const [selectedTimeInner, setSelectedTime] = React.useState(null);
|
|
12
|
+
const inputTimeZone = useDefaultTimeZone(getDateTime(props.value) || getDateTime(props.defaultValue) || props.placeholderValue);
|
|
13
|
+
const timeZone = props.timeZone || inputTimeZone;
|
|
14
|
+
let selectedDate = selectedDateInner;
|
|
15
|
+
let selectedTime = selectedTimeInner;
|
|
16
|
+
const format = props.format || 'L';
|
|
17
|
+
const commitValue = (date, time) => {
|
|
18
|
+
if (disabled || readOnly) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
setValue(setTimezone(mergeDateTime(date, time), inputTimeZone));
|
|
22
|
+
setSelectedDate(null);
|
|
23
|
+
setSelectedTime(null);
|
|
24
|
+
};
|
|
25
|
+
const dateFieldState = useDateFieldState(Object.assign(Object.assign({}, props), { value,
|
|
26
|
+
onUpdate(date) {
|
|
27
|
+
if (date) {
|
|
28
|
+
commitValue(date, date);
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
setValue(null);
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
disabled,
|
|
35
|
+
readOnly, validationState: props.validationState, minValue: props.minValue, maxValue: props.maxValue, isDateUnavailable: props.isDateUnavailable, format, placeholderValue: props.placeholderValue, timeZone }));
|
|
36
|
+
const timeFormat = React.useMemo(() => {
|
|
37
|
+
const hasSeconds = dateFieldState.sections.some((s) => s.type === 'second');
|
|
38
|
+
return hasSeconds ? 'LTS' : 'LT';
|
|
39
|
+
}, [dateFieldState.sections]);
|
|
40
|
+
if (value) {
|
|
41
|
+
selectedDate = setTimezone(value, timeZone);
|
|
42
|
+
if (dateFieldState.hasTime) {
|
|
43
|
+
selectedTime = setTimezone(value, timeZone);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// Intercept setValue to make sure the Time section is not changed by date selection in Calendar
|
|
47
|
+
const selectDate = (newValue) => {
|
|
48
|
+
if (disabled || readOnly) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const shouldClose = !dateFieldState.hasTime;
|
|
52
|
+
if (dateFieldState.hasTime) {
|
|
53
|
+
if (selectedTime || shouldClose) {
|
|
54
|
+
commitValue(newValue, selectedTime || newValue);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
setSelectedDate(newValue);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
commitValue(newValue, newValue);
|
|
62
|
+
}
|
|
63
|
+
if (shouldClose) {
|
|
64
|
+
setOpen(false);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
const selectTime = (newValue) => {
|
|
68
|
+
if (disabled || readOnly) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const newTime = newValue !== null && newValue !== void 0 ? newValue : getPlaceholderTime(props.placeholderValue, timeZone);
|
|
72
|
+
if (selectedDate) {
|
|
73
|
+
commitValue(selectedDate, newTime);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
setSelectedTime(newTime);
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
if (dateFieldState.hasTime && !selectedTime) {
|
|
80
|
+
selectedTime = dateFieldState.displayValue;
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
value,
|
|
84
|
+
setValue(newDate) {
|
|
85
|
+
if (props.readOnly || props.disabled) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
if (newDate) {
|
|
89
|
+
setValue(setTimezone(newDate, inputTimeZone));
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
setValue(null);
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
dateValue: selectedDate,
|
|
96
|
+
timeValue: selectedTime,
|
|
97
|
+
setDateValue: selectDate,
|
|
98
|
+
setTimeValue: selectTime,
|
|
99
|
+
disabled,
|
|
100
|
+
readOnly,
|
|
101
|
+
format,
|
|
102
|
+
hasDate: dateFieldState.hasDate,
|
|
103
|
+
hasTime: dateFieldState.hasTime,
|
|
104
|
+
timeFormat,
|
|
105
|
+
timeZone,
|
|
106
|
+
isOpen,
|
|
107
|
+
setOpen(newIsOpen) {
|
|
108
|
+
if (!newIsOpen && !value && selectedDate && dateFieldState.hasTime) {
|
|
109
|
+
commitValue(selectedDate, selectedTime || getPlaceholderTime(props.placeholderValue, props.timeZone));
|
|
110
|
+
}
|
|
111
|
+
setOpen(newIsOpen);
|
|
112
|
+
},
|
|
113
|
+
dateFieldState,
|
|
114
|
+
};
|
|
115
|
+
};
|
|
116
|
+
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import type { DateTime } from '@gravity-ui/date-utils';
|
|
2
3
|
import type { ButtonProps, PopupProps, TextInputProps } from '@gravity-ui/uikit';
|
|
3
|
-
import type {
|
|
4
|
+
import type { CalendarInstance, CalendarProps } from '../../Calendar';
|
|
4
5
|
import type { DateFieldProps } from '../../DateField';
|
|
6
|
+
import type { RangeValue } from '../../types';
|
|
5
7
|
import type { DatePickerProps } from '../DatePicker';
|
|
6
8
|
import type { DatePickerState } from './useDatePickerState';
|
|
7
|
-
interface
|
|
9
|
+
interface InnerDatePickerProps<T = DateTime> {
|
|
8
10
|
groupProps: React.HTMLAttributes<unknown> & {
|
|
9
11
|
ref: React.Ref<any>;
|
|
10
12
|
};
|
|
@@ -13,8 +15,10 @@ interface InnerRelativeDatePickerProps {
|
|
|
13
15
|
ref: React.Ref<HTMLButtonElement>;
|
|
14
16
|
};
|
|
15
17
|
popupProps: PopupProps;
|
|
16
|
-
calendarProps:
|
|
17
|
-
|
|
18
|
+
calendarProps: CalendarProps<T> & {
|
|
19
|
+
ref: React.Ref<CalendarInstance>;
|
|
20
|
+
};
|
|
21
|
+
timeInputProps: DateFieldProps<T>;
|
|
18
22
|
}
|
|
19
|
-
export declare function useDatePickerProps(state: DatePickerState
|
|
23
|
+
export declare function useDatePickerProps<T extends DateTime | RangeValue<DateTime>>(state: DatePickerState<T>, { onFocus, onBlur, ...props }: DatePickerProps<T>): InnerDatePickerProps<T>;
|
|
20
24
|
export {};
|
|
@@ -5,6 +5,7 @@ import { useDateFieldProps } from '../../DateField';
|
|
|
5
5
|
import { getButtonSizeForInput } from '../../utils/getButtonSizeForInput';
|
|
6
6
|
import { mergeProps } from '../../utils/mergeProps';
|
|
7
7
|
import { i18n } from '../i18n';
|
|
8
|
+
import { getDateTimeValue } from '../utils';
|
|
8
9
|
export function useDatePickerProps(state, _a) {
|
|
9
10
|
var { onFocus, onBlur } = _a, props = __rest(_a, ["onFocus", "onBlur"]);
|
|
10
11
|
const [isActive, setActive] = React.useState(false);
|
|
@@ -30,9 +31,10 @@ export function useDatePickerProps(state, _a) {
|
|
|
30
31
|
(_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
31
32
|
});
|
|
32
33
|
}
|
|
34
|
+
const onlyTime = state.hasTime && !state.hasDate;
|
|
33
35
|
return {
|
|
34
36
|
groupProps: Object.assign(Object.assign({ ref: groupRef, tabIndex: -1, role: 'group' }, focusWithinProps), { style: props.style, 'aria-disabled': state.disabled || undefined, onKeyDown: (e) => {
|
|
35
|
-
if (e.altKey && (e.key === 'ArrowDown' || e.key === 'ArrowUp')) {
|
|
37
|
+
if (!onlyTime && e.altKey && (e.key === 'ArrowDown' || e.key === 'ArrowUp')) {
|
|
36
38
|
e.preventDefault();
|
|
37
39
|
e.stopPropagation();
|
|
38
40
|
state.setOpen(true);
|
|
@@ -93,7 +95,7 @@ export function useDatePickerProps(state, _a) {
|
|
|
93
95
|
},
|
|
94
96
|
timeInputProps: {
|
|
95
97
|
value: state.timeValue,
|
|
96
|
-
placeholderValue: state.dateFieldState.displayValue,
|
|
98
|
+
placeholderValue: getDateTimeValue(state.dateFieldState.displayValue),
|
|
97
99
|
onUpdate: state.setTimeValue,
|
|
98
100
|
format: state.timeFormat,
|
|
99
101
|
readOnly: state.readOnly,
|
|
@@ -1,45 +1,6 @@
|
|
|
1
1
|
import type { DateTime } from '@gravity-ui/date-utils';
|
|
2
|
-
import type { DateFieldState } from '../../DateField';
|
|
3
2
|
import type { DateFieldBase } from '../../types';
|
|
4
|
-
export type
|
|
5
|
-
export interface DatePickerState {
|
|
6
|
-
/** The currently selected date. */
|
|
7
|
-
value: DateTime | null;
|
|
8
|
-
/** Sets the selected date. */
|
|
9
|
-
setValue: (value: DateTime | null) => void;
|
|
10
|
-
/**
|
|
11
|
-
* The date portion of the value. This may be set prior to `value` if the user has
|
|
12
|
-
* selected a date but has not yet selected a time.
|
|
13
|
-
*/
|
|
14
|
-
dateValue: DateTime | null;
|
|
15
|
-
/** Sets the date portion of the value. */
|
|
16
|
-
setDateValue: (value: DateTime) => void;
|
|
17
|
-
/**
|
|
18
|
-
* The time portion of the value. This may be set prior to `value` if the user has
|
|
19
|
-
* selected a time but has not yet selected a date.
|
|
20
|
-
*/
|
|
21
|
-
timeValue: DateTime | null;
|
|
22
|
-
/** Sets the time portion of the value. */
|
|
23
|
-
setTimeValue: (value: DateTime | null) => void;
|
|
24
|
-
/** Whether the field is read only. */
|
|
25
|
-
readOnly?: boolean;
|
|
26
|
-
/** Whether the field is disabled. */
|
|
27
|
-
disabled?: boolean;
|
|
28
|
-
/** Format of the date when rendered in the input. */
|
|
29
|
-
format: string;
|
|
30
|
-
/** Whether the date picker supports selecting a date. */
|
|
31
|
-
hasDate: boolean;
|
|
32
|
-
/** Whether the date picker supports selecting a time. */
|
|
33
|
-
hasTime: boolean;
|
|
34
|
-
/** Format of the time when rendered in the input. */
|
|
35
|
-
timeFormat?: string;
|
|
36
|
-
timeZone: string;
|
|
37
|
-
/** Whether the calendar popover is currently open. */
|
|
38
|
-
isOpen: boolean;
|
|
39
|
-
/** Sets whether the calendar popover is open. */
|
|
40
|
-
setOpen: (isOpen: boolean) => void;
|
|
41
|
-
dateFieldState: DateFieldState;
|
|
42
|
-
}
|
|
3
|
+
export type { DatePickerState } from './datePickerStateFactory';
|
|
43
4
|
export interface DatePickerStateOptions extends DateFieldBase {
|
|
44
5
|
}
|
|
45
|
-
export declare
|
|
6
|
+
export declare const useDatePickerState: (props: import("../../DateField").DateFieldStateOptions) => import("./datePickerStateFactory").DatePickerState<DateTime>;
|
|
@@ -1,132 +1,14 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { useControlledState } from '@gravity-ui/uikit';
|
|
3
1
|
import { useDateFieldState } from '../../DateField';
|
|
4
2
|
import { createPlaceholderValue, mergeDateTime } from '../../utils/dates';
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
let selectedTime = selectedTimeInner;
|
|
17
|
-
const format = props.format || 'L';
|
|
18
|
-
const commitValue = (date, time) => {
|
|
19
|
-
if (disabled || readOnly) {
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
setValue(mergeDateTime(date, time).timeZone(inputTimeZone));
|
|
23
|
-
setSelectedDate(null);
|
|
24
|
-
setSelectedTime(null);
|
|
25
|
-
};
|
|
26
|
-
const dateFieldState = useDateFieldState({
|
|
27
|
-
value,
|
|
28
|
-
onUpdate(date) {
|
|
29
|
-
if (date) {
|
|
30
|
-
commitValue(date, date);
|
|
31
|
-
}
|
|
32
|
-
else {
|
|
33
|
-
setValue(null);
|
|
34
|
-
}
|
|
35
|
-
},
|
|
36
|
-
disabled,
|
|
37
|
-
readOnly,
|
|
38
|
-
validationState: props.validationState,
|
|
39
|
-
minValue: props.minValue,
|
|
40
|
-
maxValue: props.maxValue,
|
|
41
|
-
isDateUnavailable: props.isDateUnavailable,
|
|
42
|
-
format,
|
|
43
|
-
placeholderValue: props.placeholderValue,
|
|
44
|
-
timeZone,
|
|
45
|
-
});
|
|
46
|
-
const timeFormat = React.useMemo(() => {
|
|
47
|
-
const hasSeconds = dateFieldState.sections.some((s) => s.type === 'second');
|
|
48
|
-
return hasSeconds ? 'LTS' : 'LT';
|
|
49
|
-
}, [dateFieldState.sections]);
|
|
50
|
-
if (value) {
|
|
51
|
-
selectedDate = value.timeZone(timeZone);
|
|
52
|
-
if (dateFieldState.hasTime) {
|
|
53
|
-
selectedTime = value.timeZone(timeZone);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
// Intercept setValue to make sure the Time section is not changed by date selection in Calendar
|
|
57
|
-
const selectDate = (newValue) => {
|
|
58
|
-
if (disabled || readOnly) {
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
const shouldClose = !dateFieldState.hasTime;
|
|
62
|
-
if (dateFieldState.hasTime) {
|
|
63
|
-
if (selectedTime || shouldClose) {
|
|
64
|
-
commitValue(newValue, selectedTime || newValue);
|
|
65
|
-
}
|
|
66
|
-
else {
|
|
67
|
-
setSelectedDate(newValue);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
else {
|
|
71
|
-
commitValue(newValue, newValue);
|
|
72
|
-
}
|
|
73
|
-
if (shouldClose) {
|
|
74
|
-
setOpen(false);
|
|
75
|
-
}
|
|
76
|
-
};
|
|
77
|
-
const selectTime = (newValue) => {
|
|
78
|
-
if (disabled || readOnly) {
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
const newTime = newValue !== null && newValue !== void 0 ? newValue : createPlaceholderValue({
|
|
82
|
-
placeholderValue: props.placeholderValue,
|
|
83
|
-
timeZone,
|
|
84
|
-
});
|
|
85
|
-
if (selectedDate) {
|
|
86
|
-
commitValue(selectedDate, newTime);
|
|
87
|
-
}
|
|
88
|
-
else {
|
|
89
|
-
setSelectedTime(newTime);
|
|
90
|
-
}
|
|
91
|
-
};
|
|
92
|
-
if (dateFieldState.hasTime && !selectedTime) {
|
|
93
|
-
selectedTime = dateFieldState.displayValue;
|
|
94
|
-
}
|
|
95
|
-
return {
|
|
96
|
-
value,
|
|
97
|
-
setValue(newDate) {
|
|
98
|
-
if (props.readOnly || props.disabled) {
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
if (newDate) {
|
|
102
|
-
setValue(newDate.timeZone(inputTimeZone));
|
|
103
|
-
}
|
|
104
|
-
else {
|
|
105
|
-
setValue(null);
|
|
106
|
-
}
|
|
107
|
-
},
|
|
108
|
-
dateValue: selectedDate,
|
|
109
|
-
timeValue: selectedTime,
|
|
110
|
-
setDateValue: selectDate,
|
|
111
|
-
setTimeValue: selectTime,
|
|
112
|
-
disabled,
|
|
113
|
-
readOnly,
|
|
114
|
-
format,
|
|
115
|
-
hasDate: dateFieldState.hasDate,
|
|
116
|
-
hasTime: dateFieldState.hasTime,
|
|
117
|
-
timeFormat,
|
|
118
|
-
timeZone,
|
|
119
|
-
isOpen,
|
|
120
|
-
setOpen(newIsOpen) {
|
|
121
|
-
if (!newIsOpen && !value && selectedDate && dateFieldState.hasTime) {
|
|
122
|
-
commitValue(selectedDate, selectedTime ||
|
|
123
|
-
createPlaceholderValue({
|
|
124
|
-
placeholderValue: props.placeholderValue,
|
|
125
|
-
timeZone: inputTimeZone,
|
|
126
|
-
}));
|
|
127
|
-
}
|
|
128
|
-
setOpen(newIsOpen);
|
|
129
|
-
},
|
|
130
|
-
dateFieldState,
|
|
131
|
-
};
|
|
3
|
+
import { getDateTimeValue } from '../utils';
|
|
4
|
+
import { datePickerStateFactory } from './datePickerStateFactory';
|
|
5
|
+
export const useDatePickerState = datePickerStateFactory({
|
|
6
|
+
getPlaceholderTime,
|
|
7
|
+
mergeDateTime,
|
|
8
|
+
setTimezone: (date, timeZone) => date.timeZone(timeZone),
|
|
9
|
+
getDateTime: getDateTimeValue,
|
|
10
|
+
useDateFieldState,
|
|
11
|
+
});
|
|
12
|
+
function getPlaceholderTime(placeholderValue, timeZone) {
|
|
13
|
+
return createPlaceholderValue({ placeholderValue, timeZone });
|
|
132
14
|
}
|
|
@@ -1,13 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
4
|
-
import type {
|
|
2
|
+
import type { DateTime } from '@gravity-ui/date-utils';
|
|
3
|
+
import type { CalendarProps } from '../Calendar/Calendar';
|
|
4
|
+
import type { CalendarInstance } from '../CalendarView/CalendarView';
|
|
5
|
+
import type { RangeValue } from '../types';
|
|
5
6
|
import '../CalendarView/Calendar.css';
|
|
6
|
-
export
|
|
7
|
-
/**
|
|
8
|
-
* The size of the element.
|
|
9
|
-
* @default m
|
|
10
|
-
*/
|
|
11
|
-
size?: CalendarSize;
|
|
12
|
-
}
|
|
7
|
+
export type RangeCalendarProps = CalendarProps<RangeValue<DateTime>>;
|
|
13
8
|
export declare const RangeCalendar: React.ForwardRefExoticComponent<RangeCalendarProps & React.RefAttributes<CalendarInstance>>;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { DateTime } from '@gravity-ui/date-utils';
|
|
2
|
-
import type {
|
|
2
|
+
import type { DateFieldState } from '../../DateField';
|
|
3
3
|
import type { DateFieldBase } from '../../types/datePicker';
|
|
4
4
|
import type { RangeValue } from '../../types/inputs';
|
|
5
5
|
export interface RangeDateFieldStateOptions extends DateFieldBase<RangeValue<DateTime>> {
|
|
6
6
|
delimiter?: string;
|
|
7
7
|
}
|
|
8
|
-
export type RangeDateFieldState =
|
|
8
|
+
export type RangeDateFieldState = DateFieldState<RangeValue<DateTime>>;
|
|
9
9
|
export declare function useRangeDateFieldState(props: RangeDateFieldStateOptions): RangeDateFieldState;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
.g-date-range-date-picker {
|
|
2
|
+
position: relative;
|
|
3
|
+
display: inline-block;
|
|
4
|
+
outline: none;
|
|
5
|
+
}
|
|
6
|
+
.g-date-range-date-picker__field {
|
|
7
|
+
width: 100%;
|
|
8
|
+
}
|
|
9
|
+
.g-date-range-date-picker__popup-anchor {
|
|
10
|
+
position: absolute;
|
|
11
|
+
z-index: -1;
|
|
12
|
+
inset: 0;
|
|
13
|
+
}
|
|
14
|
+
.g-date-range-date-picker__popup-content {
|
|
15
|
+
outline: none;
|
|
16
|
+
}
|
|
17
|
+
.g-date-range-date-picker__time-field {
|
|
18
|
+
width: 100%;
|
|
19
|
+
}
|
|
20
|
+
.g-date-range-date-picker__time-field-wrapper {
|
|
21
|
+
padding: 10px;
|
|
22
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { DateTime } from '@gravity-ui/date-utils';
|
|
2
|
+
import type { DatePickerProps } from '../DatePicker';
|
|
3
|
+
import type { RangeValue } from '../types';
|
|
4
|
+
import './RangeDatePicker.css';
|
|
5
|
+
export type RangeDatePickerProps = DatePickerProps<RangeValue<DateTime>>;
|
|
6
|
+
export declare function RangeDatePicker({ className, ...props }: RangeDatePickerProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { __rest } from "tslib";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { Calendar as CalendarIcon, Clock as ClockIcon } from '@gravity-ui/icons';
|
|
5
|
+
import { Button, Icon, Popup, TextInput } from '@gravity-ui/uikit';
|
|
6
|
+
import { block } from '../../utils/cn';
|
|
7
|
+
import { RangeCalendar } from '../Calendar';
|
|
8
|
+
import { useDatePickerProps } from '../DatePicker';
|
|
9
|
+
import { StubButton } from '../DatePicker/StubButton';
|
|
10
|
+
import { RangeDateField } from '../RangeDateField';
|
|
11
|
+
import { useRangeDatePickerState } from './hooks/useRangeDatePickerState';
|
|
12
|
+
import './RangeDatePicker.css';
|
|
13
|
+
const b = block('range-date-picker');
|
|
14
|
+
export function RangeDatePicker(_a) {
|
|
15
|
+
var { className } = _a, props = __rest(_a, ["className"]);
|
|
16
|
+
const anchorRef = React.useRef(null);
|
|
17
|
+
const state = useRangeDatePickerState(props);
|
|
18
|
+
const { groupProps, fieldProps, calendarButtonProps, popupProps, calendarProps, timeInputProps } = useDatePickerProps(state, props);
|
|
19
|
+
const isOnlyTime = state.hasTime && !state.hasDate;
|
|
20
|
+
return (_jsxs("div", Object.assign({ className: b(null, className) }, groupProps, { children: [!isOnlyTime && (_jsx("div", { ref: anchorRef, className: b('popup-anchor'), children: _jsx(Popup, Object.assign({ anchorRef: anchorRef }, popupProps, { children: _jsxs("div", { className: b('popup-content'), children: [typeof props.children === 'function' ? (props.children(Object.assign(Object.assign({}, calendarProps), { value: state.value }))) : (_jsx(RangeCalendar, Object.assign({}, calendarProps, { value: state.value }))), state.hasTime && (_jsx("div", { className: b('time-field-wrapper'), children: _jsx(RangeDateField, Object.assign({}, timeInputProps)) }))] }) })) })), _jsx(TextInput, Object.assign({}, fieldProps, { className: b('field'), hasClear: fieldProps.hasClear, endContent: _jsxs(React.Fragment, { children: [!isOnlyTime && (_jsx(Button, Object.assign({}, calendarButtonProps, { children: _jsx(Icon, { data: CalendarIcon }) }))), isOnlyTime && (_jsx(StubButton, { size: calendarButtonProps.size, icon: ClockIcon }))] }) }))] })));
|
|
21
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { DateTime } from '@gravity-ui/date-utils';
|
|
2
|
+
import type { DatePickerState } from '../../DatePicker';
|
|
3
|
+
import type { RangeDateFieldStateOptions } from '../../RangeDateField';
|
|
4
|
+
import type { RangeValue } from '../../types';
|
|
5
|
+
export type RangeDatePickerState = DatePickerState<RangeValue<DateTime>>;
|
|
6
|
+
export type RangeDatePickerStateOptions = RangeDateFieldStateOptions;
|
|
7
|
+
export declare const useRangeDatePickerState: (props: RangeDateFieldStateOptions) => DatePickerState<RangeValue<DateTime>>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { datePickerStateFactory } from '../../DatePicker/hooks/datePickerStateFactory';
|
|
2
|
+
import { getDateTimeValue } from '../../DatePicker/utils';
|
|
3
|
+
import { useRangeDateFieldState } from '../../RangeDateField';
|
|
4
|
+
import { createPlaceholderValue, mergeDateTime } from '../../utils/dates';
|
|
5
|
+
export const useRangeDatePickerState = datePickerStateFactory({
|
|
6
|
+
getPlaceholderTime,
|
|
7
|
+
mergeDateTime: mergeRangeDateTime,
|
|
8
|
+
setTimezone,
|
|
9
|
+
getDateTime: getDateTimeValue,
|
|
10
|
+
useDateFieldState: useRangeDateFieldState,
|
|
11
|
+
});
|
|
12
|
+
function getPlaceholderTime(placeholderValue, timeZone) {
|
|
13
|
+
const date = createPlaceholderValue({ placeholderValue, timeZone });
|
|
14
|
+
return { start: date, end: date };
|
|
15
|
+
}
|
|
16
|
+
function mergeRangeDateTime(date, time) {
|
|
17
|
+
const start = mergeDateTime(date.start, time.start);
|
|
18
|
+
const end = mergeDateTime(date.end, time.end);
|
|
19
|
+
return { start, end };
|
|
20
|
+
}
|
|
21
|
+
function setTimezone(date, timeZone) {
|
|
22
|
+
const start = date.start.timeZone(timeZone);
|
|
23
|
+
const end = date.end.timeZone(timeZone);
|
|
24
|
+
return { start, end };
|
|
25
|
+
}
|