@gravity-ui/date-components 2.0.1 → 2.1.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/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/useDatePickerProps.js +2 -1
- 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/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/useDatePickerProps.js +2 -1
- 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
|
@@ -34,6 +34,8 @@ function useCalendarProps(props, state) {
|
|
|
34
34
|
},
|
|
35
35
|
extraProps: {
|
|
36
36
|
'aria-disabled': modeDisabled ? 'true' : undefined,
|
|
37
|
+
'aria-description': getAriaDescriptionForModeButton(state.mode, state.availableModes),
|
|
38
|
+
'aria-live': 'polite',
|
|
37
39
|
},
|
|
38
40
|
children: title,
|
|
39
41
|
};
|
|
@@ -109,3 +111,18 @@ function useCalendarProps(props, state) {
|
|
|
109
111
|
};
|
|
110
112
|
}
|
|
111
113
|
exports.useCalendarProps = useCalendarProps;
|
|
114
|
+
function getAriaDescriptionForModeButton(mode, availableModes) {
|
|
115
|
+
const nextModeIndex = availableModes.indexOf(mode) + 1;
|
|
116
|
+
const isModeLast = nextModeIndex === availableModes.length;
|
|
117
|
+
if (isModeLast) {
|
|
118
|
+
return undefined;
|
|
119
|
+
}
|
|
120
|
+
const ariaLabelMap = {
|
|
121
|
+
days: '',
|
|
122
|
+
months: (0, i18n_1.i18n)('Switch to months view'),
|
|
123
|
+
quarters: (0, i18n_1.i18n)('Switch to quarters view'),
|
|
124
|
+
years: (0, i18n_1.i18n)('Switch to years view'),
|
|
125
|
+
};
|
|
126
|
+
const nextMode = availableModes[nextModeIndex];
|
|
127
|
+
return ariaLabelMap[nextMode];
|
|
128
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const i18n: (key: "Previous" | "Next", params?: import("@gravity-ui/i18n").Params | undefined) => string;
|
|
1
|
+
export declare const i18n: (key: "Previous" | "Next" | "Switch to months view" | "Switch to quarters view" | "Switch to years view", params?: import("@gravity-ui/i18n").Params | undefined) => string;
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"Previous": "Назад",
|
|
3
|
-
"Next": "Вперёд"
|
|
3
|
+
"Next": "Вперёд",
|
|
4
|
+
"Switch to months view": "Переключиться на просмотр по месяцам",
|
|
5
|
+
"Switch to quarters view": "Переключиться на просмотр по кварталам",
|
|
6
|
+
"Switch to years view": "Переключиться на просмотр по годам"
|
|
4
7
|
}
|
|
@@ -9,6 +9,7 @@ const uikit_1 = require("@gravity-ui/uikit");
|
|
|
9
9
|
const Calendar_1 = require("../Calendar");
|
|
10
10
|
const DateField_1 = require("../DateField");
|
|
11
11
|
const MobileCalendar_1 = require("./MobileCalendar");
|
|
12
|
+
const StubButton_1 = require("./StubButton");
|
|
12
13
|
const useDatePickerProps_1 = require("./hooks/useDatePickerProps");
|
|
13
14
|
const useDatePickerState_1 = require("./hooks/useDatePickerState");
|
|
14
15
|
const utils_1 = require("./utils");
|
|
@@ -19,7 +20,8 @@ function DatePicker(_a) {
|
|
|
19
20
|
const state = (0, useDatePickerState_1.useDatePickerState)(props);
|
|
20
21
|
const { groupProps, fieldProps, calendarButtonProps, popupProps, calendarProps, timeInputProps } = (0, useDatePickerProps_1.useDatePickerProps)(state, props);
|
|
21
22
|
const isMobile = (0, uikit_1.useMobile)();
|
|
22
|
-
|
|
23
|
+
const isOnlyTime = state.hasTime && !state.hasDate;
|
|
24
|
+
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 })) : (!isOnlyTime && ((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, endContent: (0, jsx_runtime_1.jsxs)(react_1.default.Fragment, { children: [!isMobile && !isOnlyTime && ((0, jsx_runtime_1.jsx)(uikit_1.Button, Object.assign({}, calendarButtonProps, { children: (0, jsx_runtime_1.jsx)(uikit_1.Icon, { data: icons_1.Calendar }) }))), !isMobile && isOnlyTime && ((0, jsx_runtime_1.jsx)(StubButton_1.StubButton, { size: calendarButtonProps.size, icon: icons_1.Clock })), isMobile && ((0, jsx_runtime_1.jsx)(StubButton_1.StubButton, { size: calendarButtonProps.size, icon: isOnlyTime ? icons_1.Clock : icons_1.Calendar }))] }) })), (0, jsx_runtime_1.jsx)("input", { type: "text", hidden: true, name: props.name, value: state.value ? state.value.toISOString() : '',
|
|
23
25
|
// Ignore React warning
|
|
24
26
|
onChange: () => { } })] })));
|
|
25
27
|
}
|
|
@@ -1,29 +1,4 @@
|
|
|
1
1
|
.g-date-mobile-calendar {
|
|
2
|
-
position: relative;
|
|
3
|
-
display: inline-block;
|
|
4
|
-
width: 24px;
|
|
5
|
-
height: 24px;
|
|
6
|
-
}
|
|
7
|
-
.g-date-mobile-calendar_size_xs {
|
|
8
|
-
width: 20px;
|
|
9
|
-
height: 20px;
|
|
10
|
-
}
|
|
11
|
-
.g-date-mobile-calendar_size_m {
|
|
12
|
-
width: 28px;
|
|
13
|
-
height: 28px;
|
|
14
|
-
}
|
|
15
|
-
.g-date-mobile-calendar_size_l {
|
|
16
|
-
width: 36px;
|
|
17
|
-
height: 36px;
|
|
18
|
-
}
|
|
19
|
-
.g-date-mobile-calendar__button {
|
|
20
|
-
position: absolute;
|
|
21
|
-
inset: 0;
|
|
22
|
-
display: flex;
|
|
23
|
-
justify-content: center;
|
|
24
|
-
align-items: center;
|
|
25
|
-
}
|
|
26
|
-
.g-date-mobile-calendar__input {
|
|
27
2
|
position: absolute;
|
|
28
3
|
z-index: 1;
|
|
29
4
|
inset-block-start: 0;
|
|
@@ -37,7 +12,7 @@
|
|
|
37
12
|
opacity: 0;
|
|
38
13
|
border: none;
|
|
39
14
|
}
|
|
40
|
-
.g-date-mobile-
|
|
15
|
+
.g-date-mobile-calendar::-webkit-calendar-picker-indicator {
|
|
41
16
|
position: absolute;
|
|
42
17
|
inset-block-start: 0;
|
|
43
18
|
inset-inline-start: 0;
|
|
@@ -6,9 +6,4 @@ interface MobileCalendarProps {
|
|
|
6
6
|
state: DatePickerState;
|
|
7
7
|
}
|
|
8
8
|
export declare function MobileCalendar({ props, state }: MobileCalendarProps): import("react/jsx-runtime").JSX.Element;
|
|
9
|
-
interface MobileCalendarIconProps {
|
|
10
|
-
props: DatePickerProps;
|
|
11
|
-
state: DatePickerState;
|
|
12
|
-
}
|
|
13
|
-
export declare function MobileCalendarIcon({ props }: MobileCalendarIconProps): import("react/jsx-runtime").JSX.Element;
|
|
14
9
|
export {};
|
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.MobileCalendar = void 0;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
5
|
const date_utils_1 = require("@gravity-ui/date-utils");
|
|
6
|
-
const icons_1 = require("@gravity-ui/icons");
|
|
7
|
-
const uikit_1 = require("@gravity-ui/uikit");
|
|
8
6
|
const cn_1 = require("../../utils/cn");
|
|
9
7
|
const dates_1 = require("../utils/dates");
|
|
10
|
-
const getButtonSizeForInput_1 = require("../utils/getButtonSizeForInput");
|
|
11
8
|
require("./MobileCalendar.css");
|
|
12
9
|
const b = (0, cn_1.block)('mobile-calendar');
|
|
13
10
|
function MobileCalendar({ props, state }) {
|
|
@@ -19,7 +16,7 @@ function MobileCalendar({ props, state }) {
|
|
|
19
16
|
else if (state.hasTime) {
|
|
20
17
|
type = 'time';
|
|
21
18
|
}
|
|
22
|
-
return ((0, jsx_runtime_1.jsx)("input", { className: b(
|
|
19
|
+
return ((0, jsx_runtime_1.jsx)("input", { className: b(), disabled: props.disabled, type: type, value: formatNative(state.dateFieldState.displayValue, type), id: props.id, min: formatNative((_a = props.minValue) === null || _a === void 0 ? void 0 : _a.timeZone(state.timeZone), type), max: formatNative((_b = props.maxValue) === null || _b === void 0 ? void 0 : _b.timeZone(state.timeZone), type), tabIndex: -1, onChange: (e) => {
|
|
23
20
|
var _a, _b;
|
|
24
21
|
if (props.readOnly) {
|
|
25
22
|
return;
|
|
@@ -57,10 +54,6 @@ function MobileCalendar({ props, state }) {
|
|
|
57
54
|
} }));
|
|
58
55
|
}
|
|
59
56
|
exports.MobileCalendar = MobileCalendar;
|
|
60
|
-
function MobileCalendarIcon({ props }) {
|
|
61
|
-
return ((0, jsx_runtime_1.jsx)("span", { className: b({ size: (0, getButtonSizeForInput_1.getButtonSizeForInput)(props.size) }), children: (0, jsx_runtime_1.jsx)("span", { className: b('button'), children: (0, jsx_runtime_1.jsx)(uikit_1.Icon, { data: icons_1.Calendar }) }) }));
|
|
62
|
-
}
|
|
63
|
-
exports.MobileCalendarIcon = MobileCalendarIcon;
|
|
64
57
|
function getDateFormat(type) {
|
|
65
58
|
switch (type) {
|
|
66
59
|
case 'time': {
|
|
@@ -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,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.StubButton = void 0;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const uikit_1 = require("@gravity-ui/uikit");
|
|
6
|
+
const cn_1 = require("../../utils/cn");
|
|
7
|
+
require("./StubButton.css");
|
|
8
|
+
const b = (0, cn_1.block)('stub-button');
|
|
9
|
+
function StubButton({ size, icon }) {
|
|
10
|
+
return ((0, jsx_runtime_1.jsx)("span", { className: b({ size }), children: (0, jsx_runtime_1.jsx)("span", { className: b('icon'), children: (0, jsx_runtime_1.jsx)(uikit_1.Icon, { data: icon }) }) }));
|
|
11
|
+
}
|
|
12
|
+
exports.StubButton = StubButton;
|
|
@@ -33,9 +33,10 @@ function useDatePickerProps(state, _a) {
|
|
|
33
33
|
(_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
34
34
|
});
|
|
35
35
|
}
|
|
36
|
+
const onlyTime = state.hasTime && !state.hasDate;
|
|
36
37
|
return {
|
|
37
38
|
groupProps: Object.assign(Object.assign({ ref: groupRef, tabIndex: -1, role: 'group' }, focusWithinProps), { style: props.style, 'aria-disabled': state.disabled || undefined, onKeyDown: (e) => {
|
|
38
|
-
if (e.altKey && (e.key === 'ArrowDown' || e.key === 'ArrowUp')) {
|
|
39
|
+
if (!onlyTime && e.altKey && (e.key === 'ArrowDown' || e.key === 'ArrowUp')) {
|
|
39
40
|
e.preventDefault();
|
|
40
41
|
e.stopPropagation();
|
|
41
42
|
state.setOpen(true);
|
|
@@ -10,6 +10,7 @@ const cn_1 = require("../../utils/cn");
|
|
|
10
10
|
const Calendar_1 = require("../Calendar");
|
|
11
11
|
const DateField_1 = require("../DateField");
|
|
12
12
|
const MobileCalendar_1 = require("../DatePicker/MobileCalendar");
|
|
13
|
+
const StubButton_1 = require("../DatePicker/StubButton");
|
|
13
14
|
const useRelativeDatePickerProps_1 = require("./hooks/useRelativeDatePickerProps");
|
|
14
15
|
const useRelativeDatePickerState_1 = require("./hooks/useRelativeDatePickerState");
|
|
15
16
|
require("./RelativeDatePicker.css");
|
|
@@ -19,15 +20,16 @@ function RelativeDatePicker(props) {
|
|
|
19
20
|
const { groupProps, fieldProps, modeSwitcherProps, calendarButtonProps, popupProps, calendarProps, timeInputProps, } = (0, useRelativeDatePickerProps_1.useRelativeDatePickerProps)(state, props);
|
|
20
21
|
const anchorRef = react_1.default.useRef(null);
|
|
21
22
|
const isMobile = (0, uikit_1.useMobile)();
|
|
23
|
+
const isOnlyTime = state.datePickerState.hasTime && !state.datePickerState.hasDate;
|
|
22
24
|
return ((0, jsx_runtime_1.jsxs)("div", Object.assign({ ref: anchorRef, className: b(null, props.className) }, groupProps, { children: [isMobile && state.mode === 'absolute' && ((0, jsx_runtime_1.jsx)(MobileCalendar_1.MobileCalendar, { state: state.datePickerState, props: {
|
|
23
25
|
id: props.id,
|
|
24
26
|
disabled: props.disabled,
|
|
25
27
|
readOnly: props.readOnly,
|
|
26
28
|
placeholderValue: props.placeholderValue,
|
|
27
29
|
timeZone: props.timeZone,
|
|
28
|
-
} })), (0, jsx_runtime_1.jsx)(uikit_1.TextInput, Object.assign({}, fieldProps, { controlProps: Object.assign(Object.assign({}, fieldProps.controlProps), { disabled: isMobile && state.mode === 'absolute', className: b('input', { mobile: isMobile && state.mode === 'absolute' }) }), hasClear: props.hasClear && !(isMobile && state.mode === 'absolute'), startContent: (0, jsx_runtime_1.jsx)(uikit_1.Button, Object.assign({}, modeSwitcherProps, { children: (0, jsx_runtime_1.jsx)(uikit_1.Icon, { data: icons_1.Function }) })), endContent: (0, jsx_runtime_1.jsxs)(react_1.default.Fragment, { children: [!isMobile && ((0, jsx_runtime_1.jsx)(uikit_1.Button, Object.assign({}, calendarButtonProps, { children: (0, jsx_runtime_1.jsx)(uikit_1.Icon, { data: icons_1.Calendar }) }))), isMobile && state.mode === 'absolute' && ((0, jsx_runtime_1.jsx)(
|
|
30
|
+
} })), (0, jsx_runtime_1.jsx)(uikit_1.TextInput, Object.assign({}, fieldProps, { controlProps: Object.assign(Object.assign({}, fieldProps.controlProps), { disabled: isMobile && state.mode === 'absolute', className: b('input', { mobile: isMobile && state.mode === 'absolute' }) }), hasClear: props.hasClear && !(isMobile && state.mode === 'absolute'), startContent: (0, jsx_runtime_1.jsx)(uikit_1.Button, Object.assign({}, modeSwitcherProps, { children: (0, jsx_runtime_1.jsx)(uikit_1.Icon, { data: icons_1.Function }) })), endContent: (0, jsx_runtime_1.jsxs)(react_1.default.Fragment, { children: [!isMobile && !isOnlyTime && ((0, jsx_runtime_1.jsx)(uikit_1.Button, Object.assign({}, calendarButtonProps, { children: (0, jsx_runtime_1.jsx)(uikit_1.Icon, { data: icons_1.Calendar }) }))), !isMobile && isOnlyTime && ((0, jsx_runtime_1.jsx)(StubButton_1.StubButton, { size: calendarButtonProps.size, icon: icons_1.Clock })), isMobile && state.mode === 'absolute' && ((0, jsx_runtime_1.jsx)(StubButton_1.StubButton, { size: calendarButtonProps.size, icon: isOnlyTime ? icons_1.Clock : icons_1.Calendar }))] }) })), (0, jsx_runtime_1.jsx)("input", { type: "text", hidden: true, name: props.name, value: getNativeValue(state.value),
|
|
29
31
|
// Ignore React warning
|
|
30
|
-
onChange: () => { } }), !isMobile && ((0, jsx_runtime_1.jsx)(uikit_1.Popup, Object.assign({}, popupProps, { anchorRef: anchorRef, children: (0, jsx_runtime_1.jsxs)("div", { className: b('popup-content'), children: [typeof props.children === 'function' ? (props.children(calendarProps)) : ((0, jsx_runtime_1.jsx)(Calendar_1.Calendar, Object.assign({}, calendarProps))), state.datePickerState.hasTime && ((0, jsx_runtime_1.jsx)("div", { className: b('time-field-wrapper'), children: (0, jsx_runtime_1.jsx)(DateField_1.DateField, Object.assign({}, timeInputProps)) }))] }) })))] })));
|
|
32
|
+
onChange: () => { } }), !isMobile && !isOnlyTime && ((0, jsx_runtime_1.jsx)(uikit_1.Popup, Object.assign({}, popupProps, { anchorRef: anchorRef, children: (0, jsx_runtime_1.jsxs)("div", { className: b('popup-content'), children: [typeof props.children === 'function' ? (props.children(calendarProps)) : ((0, jsx_runtime_1.jsx)(Calendar_1.Calendar, Object.assign({}, calendarProps))), state.datePickerState.hasTime && ((0, jsx_runtime_1.jsx)("div", { className: b('time-field-wrapper'), children: (0, jsx_runtime_1.jsx)(DateField_1.DateField, Object.assign({}, timeInputProps)) }))] }) })))] })));
|
|
31
33
|
}
|
|
32
34
|
exports.RelativeDatePicker = RelativeDatePicker;
|
|
33
35
|
function getNativeValue(value) {
|
|
@@ -36,7 +36,7 @@ const data = [
|
|
|
36
36
|
get title() {
|
|
37
37
|
return (0, i18n_1.i18n)('Last 5 minutes');
|
|
38
38
|
},
|
|
39
|
-
from: 'now
|
|
39
|
+
from: 'now - 5m',
|
|
40
40
|
to: 'now',
|
|
41
41
|
},
|
|
42
42
|
{
|
|
@@ -64,8 +64,8 @@ const data = [
|
|
|
64
64
|
get title() {
|
|
65
65
|
return (0, i18n_1.i18n)('Previous month');
|
|
66
66
|
},
|
|
67
|
-
from: 'now
|
|
68
|
-
to: 'now
|
|
67
|
+
from: 'now - 1M/M',
|
|
68
|
+
to: 'now - 1M/M',
|
|
69
69
|
},
|
|
70
70
|
];
|
|
71
71
|
function PresetsExamples({ size }) {
|
|
@@ -30,6 +30,8 @@ export function useCalendarProps(props, state) {
|
|
|
30
30
|
},
|
|
31
31
|
extraProps: {
|
|
32
32
|
'aria-disabled': modeDisabled ? 'true' : undefined,
|
|
33
|
+
'aria-description': getAriaDescriptionForModeButton(state.mode, state.availableModes),
|
|
34
|
+
'aria-live': 'polite',
|
|
33
35
|
},
|
|
34
36
|
children: title,
|
|
35
37
|
};
|
|
@@ -104,3 +106,18 @@ export function useCalendarProps(props, state) {
|
|
|
104
106
|
previousButtonProps,
|
|
105
107
|
};
|
|
106
108
|
}
|
|
109
|
+
function getAriaDescriptionForModeButton(mode, availableModes) {
|
|
110
|
+
const nextModeIndex = availableModes.indexOf(mode) + 1;
|
|
111
|
+
const isModeLast = nextModeIndex === availableModes.length;
|
|
112
|
+
if (isModeLast) {
|
|
113
|
+
return undefined;
|
|
114
|
+
}
|
|
115
|
+
const ariaLabelMap = {
|
|
116
|
+
days: '',
|
|
117
|
+
months: i18n('Switch to months view'),
|
|
118
|
+
quarters: i18n('Switch to quarters view'),
|
|
119
|
+
years: i18n('Switch to years view'),
|
|
120
|
+
};
|
|
121
|
+
const nextMode = availableModes[nextModeIndex];
|
|
122
|
+
return ariaLabelMap[nextMode];
|
|
123
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const i18n: (key: "Previous" | "Next", params?: import("@gravity-ui/i18n").Params | undefined) => string;
|
|
1
|
+
export declare const i18n: (key: "Previous" | "Next" | "Switch to months view" | "Switch to quarters view" | "Switch to years view", params?: import("@gravity-ui/i18n").Params | undefined) => string;
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"Previous": "Назад",
|
|
3
|
-
"Next": "Вперёд"
|
|
3
|
+
"Next": "Вперёд",
|
|
4
|
+
"Switch to months view": "Переключиться на просмотр по месяцам",
|
|
5
|
+
"Switch to quarters view": "Переключиться на просмотр по кварталам",
|
|
6
|
+
"Switch to years view": "Переключиться на просмотр по годам"
|
|
4
7
|
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { __rest } from "tslib";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import React from 'react';
|
|
4
|
-
import { Calendar as CalendarIcon } from '@gravity-ui/icons';
|
|
4
|
+
import { Calendar as CalendarIcon, Clock as ClockIcon } from '@gravity-ui/icons';
|
|
5
5
|
import { Button, Icon, Popup, TextInput, useMobile } from '@gravity-ui/uikit';
|
|
6
6
|
import { Calendar } from '../Calendar';
|
|
7
7
|
import { DateField } from '../DateField';
|
|
8
|
-
import { MobileCalendar
|
|
8
|
+
import { MobileCalendar } from './MobileCalendar';
|
|
9
|
+
import { StubButton } from './StubButton';
|
|
9
10
|
import { useDatePickerProps } from './hooks/useDatePickerProps';
|
|
10
11
|
import { useDatePickerState } from './hooks/useDatePickerState';
|
|
11
12
|
import { b } from './utils';
|
|
@@ -16,7 +17,8 @@ export function DatePicker(_a) {
|
|
|
16
17
|
const state = useDatePickerState(props);
|
|
17
18
|
const { groupProps, fieldProps, calendarButtonProps, popupProps, calendarProps, timeInputProps } = useDatePickerProps(state, props);
|
|
18
19
|
const isMobile = useMobile();
|
|
19
|
-
|
|
20
|
+
const isOnlyTime = state.hasTime && !state.hasDate;
|
|
21
|
+
return (_jsxs("div", Object.assign({ className: b(null, className) }, groupProps, { children: [isMobile ? (_jsx(MobileCalendar, { props: props, state: state })) : (!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(calendarProps)) : (_jsx(Calendar, Object.assign({}, calendarProps))), state.hasTime && (_jsx("div", { className: b('time-field-wrapper'), children: _jsx(DateField, Object.assign({}, timeInputProps)) }))] }) })) }))), _jsx(TextInput, Object.assign({}, fieldProps, { className: b('field', { mobile: isMobile }), hasClear: !isMobile && fieldProps.hasClear, endContent: _jsxs(React.Fragment, { children: [!isMobile && !isOnlyTime && (_jsx(Button, Object.assign({}, calendarButtonProps, { children: _jsx(Icon, { data: CalendarIcon }) }))), !isMobile && isOnlyTime && (_jsx(StubButton, { size: calendarButtonProps.size, icon: ClockIcon })), isMobile && (_jsx(StubButton, { size: calendarButtonProps.size, icon: isOnlyTime ? ClockIcon : CalendarIcon }))] }) })), _jsx("input", { type: "text", hidden: true, name: props.name, value: state.value ? state.value.toISOString() : '',
|
|
20
22
|
// Ignore React warning
|
|
21
23
|
onChange: () => { } })] })));
|
|
22
24
|
}
|
|
@@ -1,29 +1,4 @@
|
|
|
1
1
|
.g-date-mobile-calendar {
|
|
2
|
-
position: relative;
|
|
3
|
-
display: inline-block;
|
|
4
|
-
width: 24px;
|
|
5
|
-
height: 24px;
|
|
6
|
-
}
|
|
7
|
-
.g-date-mobile-calendar_size_xs {
|
|
8
|
-
width: 20px;
|
|
9
|
-
height: 20px;
|
|
10
|
-
}
|
|
11
|
-
.g-date-mobile-calendar_size_m {
|
|
12
|
-
width: 28px;
|
|
13
|
-
height: 28px;
|
|
14
|
-
}
|
|
15
|
-
.g-date-mobile-calendar_size_l {
|
|
16
|
-
width: 36px;
|
|
17
|
-
height: 36px;
|
|
18
|
-
}
|
|
19
|
-
.g-date-mobile-calendar__button {
|
|
20
|
-
position: absolute;
|
|
21
|
-
inset: 0;
|
|
22
|
-
display: flex;
|
|
23
|
-
justify-content: center;
|
|
24
|
-
align-items: center;
|
|
25
|
-
}
|
|
26
|
-
.g-date-mobile-calendar__input {
|
|
27
2
|
position: absolute;
|
|
28
3
|
z-index: 1;
|
|
29
4
|
inset-block-start: 0;
|
|
@@ -37,7 +12,7 @@
|
|
|
37
12
|
opacity: 0;
|
|
38
13
|
border: none;
|
|
39
14
|
}
|
|
40
|
-
.g-date-mobile-
|
|
15
|
+
.g-date-mobile-calendar::-webkit-calendar-picker-indicator {
|
|
41
16
|
position: absolute;
|
|
42
17
|
inset-block-start: 0;
|
|
43
18
|
inset-inline-start: 0;
|
|
@@ -6,9 +6,4 @@ interface MobileCalendarProps {
|
|
|
6
6
|
state: DatePickerState;
|
|
7
7
|
}
|
|
8
8
|
export declare function MobileCalendar({ props, state }: MobileCalendarProps): import("react/jsx-runtime").JSX.Element;
|
|
9
|
-
interface MobileCalendarIconProps {
|
|
10
|
-
props: DatePickerProps;
|
|
11
|
-
state: DatePickerState;
|
|
12
|
-
}
|
|
13
|
-
export declare function MobileCalendarIcon({ props }: MobileCalendarIconProps): import("react/jsx-runtime").JSX.Element;
|
|
14
9
|
export {};
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { dateTime } from '@gravity-ui/date-utils';
|
|
3
|
-
import { Calendar as CalendarIcon } from '@gravity-ui/icons';
|
|
4
|
-
import { Icon } from '@gravity-ui/uikit';
|
|
5
3
|
import { block } from '../../utils/cn';
|
|
6
4
|
import { createPlaceholderValue, mergeDateTime } from '../utils/dates';
|
|
7
|
-
import { getButtonSizeForInput } from '../utils/getButtonSizeForInput';
|
|
8
5
|
import './MobileCalendar.css';
|
|
9
6
|
const b = block('mobile-calendar');
|
|
10
7
|
export function MobileCalendar({ props, state }) {
|
|
@@ -16,7 +13,7 @@ export function MobileCalendar({ props, state }) {
|
|
|
16
13
|
else if (state.hasTime) {
|
|
17
14
|
type = 'time';
|
|
18
15
|
}
|
|
19
|
-
return (_jsx("input", { className: b(
|
|
16
|
+
return (_jsx("input", { className: b(), disabled: props.disabled, type: type, value: formatNative(state.dateFieldState.displayValue, type), id: props.id, min: formatNative((_a = props.minValue) === null || _a === void 0 ? void 0 : _a.timeZone(state.timeZone), type), max: formatNative((_b = props.maxValue) === null || _b === void 0 ? void 0 : _b.timeZone(state.timeZone), type), tabIndex: -1, onChange: (e) => {
|
|
20
17
|
var _a, _b;
|
|
21
18
|
if (props.readOnly) {
|
|
22
19
|
return;
|
|
@@ -53,9 +50,6 @@ export function MobileCalendar({ props, state }) {
|
|
|
53
50
|
}
|
|
54
51
|
} }));
|
|
55
52
|
}
|
|
56
|
-
export function MobileCalendarIcon({ props }) {
|
|
57
|
-
return (_jsx("span", { className: b({ size: getButtonSizeForInput(props.size) }), children: _jsx("span", { className: b('button'), children: _jsx(Icon, { data: CalendarIcon }) }) }));
|
|
58
|
-
}
|
|
59
53
|
function getDateFormat(type) {
|
|
60
54
|
switch (type) {
|
|
61
55
|
case 'time': {
|
|
@@ -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
|
+
}
|
|
@@ -30,9 +30,10 @@ export function useDatePickerProps(state, _a) {
|
|
|
30
30
|
(_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
31
31
|
});
|
|
32
32
|
}
|
|
33
|
+
const onlyTime = state.hasTime && !state.hasDate;
|
|
33
34
|
return {
|
|
34
35
|
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')) {
|
|
36
|
+
if (!onlyTime && e.altKey && (e.key === 'ArrowDown' || e.key === 'ArrowUp')) {
|
|
36
37
|
e.preventDefault();
|
|
37
38
|
e.stopPropagation();
|
|
38
39
|
state.setOpen(true);
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import React from 'react';
|
|
3
|
-
import { Calendar as CalendarIcon, Function as FunctionIcon } from '@gravity-ui/icons';
|
|
3
|
+
import { Calendar as CalendarIcon, Clock as ClockIcon, Function as FunctionIcon, } from '@gravity-ui/icons';
|
|
4
4
|
import { Button, Icon, Popup, TextInput, useMobile } from '@gravity-ui/uikit';
|
|
5
5
|
import { block } from '../../utils/cn';
|
|
6
6
|
import { Calendar } from '../Calendar';
|
|
7
7
|
import { DateField } from '../DateField';
|
|
8
|
-
import { MobileCalendar
|
|
8
|
+
import { MobileCalendar } from '../DatePicker/MobileCalendar';
|
|
9
|
+
import { StubButton } from '../DatePicker/StubButton';
|
|
9
10
|
import { useRelativeDatePickerProps } from './hooks/useRelativeDatePickerProps';
|
|
10
11
|
import { useRelativeDatePickerState } from './hooks/useRelativeDatePickerState';
|
|
11
12
|
import './RelativeDatePicker.css';
|
|
@@ -15,15 +16,16 @@ export function RelativeDatePicker(props) {
|
|
|
15
16
|
const { groupProps, fieldProps, modeSwitcherProps, calendarButtonProps, popupProps, calendarProps, timeInputProps, } = useRelativeDatePickerProps(state, props);
|
|
16
17
|
const anchorRef = React.useRef(null);
|
|
17
18
|
const isMobile = useMobile();
|
|
19
|
+
const isOnlyTime = state.datePickerState.hasTime && !state.datePickerState.hasDate;
|
|
18
20
|
return (_jsxs("div", Object.assign({ ref: anchorRef, className: b(null, props.className) }, groupProps, { children: [isMobile && state.mode === 'absolute' && (_jsx(MobileCalendar, { state: state.datePickerState, props: {
|
|
19
21
|
id: props.id,
|
|
20
22
|
disabled: props.disabled,
|
|
21
23
|
readOnly: props.readOnly,
|
|
22
24
|
placeholderValue: props.placeholderValue,
|
|
23
25
|
timeZone: props.timeZone,
|
|
24
|
-
} })), _jsx(TextInput, Object.assign({}, fieldProps, { controlProps: Object.assign(Object.assign({}, fieldProps.controlProps), { disabled: isMobile && state.mode === 'absolute', className: b('input', { mobile: isMobile && state.mode === 'absolute' }) }), hasClear: props.hasClear && !(isMobile && state.mode === 'absolute'), startContent: _jsx(Button, Object.assign({}, modeSwitcherProps, { children: _jsx(Icon, { data: FunctionIcon }) })), endContent: _jsxs(React.Fragment, { children: [!isMobile && (_jsx(Button, Object.assign({}, calendarButtonProps, { children: _jsx(Icon, { data: CalendarIcon }) }))), isMobile && state.mode === 'absolute' && (_jsx(
|
|
26
|
+
} })), _jsx(TextInput, Object.assign({}, fieldProps, { controlProps: Object.assign(Object.assign({}, fieldProps.controlProps), { disabled: isMobile && state.mode === 'absolute', className: b('input', { mobile: isMobile && state.mode === 'absolute' }) }), hasClear: props.hasClear && !(isMobile && state.mode === 'absolute'), startContent: _jsx(Button, Object.assign({}, modeSwitcherProps, { children: _jsx(Icon, { data: FunctionIcon }) })), endContent: _jsxs(React.Fragment, { children: [!isMobile && !isOnlyTime && (_jsx(Button, Object.assign({}, calendarButtonProps, { children: _jsx(Icon, { data: CalendarIcon }) }))), !isMobile && isOnlyTime && (_jsx(StubButton, { size: calendarButtonProps.size, icon: ClockIcon })), isMobile && state.mode === 'absolute' && (_jsx(StubButton, { size: calendarButtonProps.size, icon: isOnlyTime ? ClockIcon : CalendarIcon }))] }) })), _jsx("input", { type: "text", hidden: true, name: props.name, value: getNativeValue(state.value),
|
|
25
27
|
// Ignore React warning
|
|
26
|
-
onChange: () => { } }), !isMobile && (_jsx(Popup, Object.assign({}, popupProps, { anchorRef: anchorRef, children: _jsxs("div", { className: b('popup-content'), children: [typeof props.children === 'function' ? (props.children(calendarProps)) : (_jsx(Calendar, Object.assign({}, calendarProps))), state.datePickerState.hasTime && (_jsx("div", { className: b('time-field-wrapper'), children: _jsx(DateField, Object.assign({}, timeInputProps)) }))] }) })))] })));
|
|
28
|
+
onChange: () => { } }), !isMobile && !isOnlyTime && (_jsx(Popup, Object.assign({}, popupProps, { anchorRef: anchorRef, children: _jsxs("div", { className: b('popup-content'), children: [typeof props.children === 'function' ? (props.children(calendarProps)) : (_jsx(Calendar, Object.assign({}, calendarProps))), state.datePickerState.hasTime && (_jsx("div", { className: b('time-field-wrapper'), children: _jsx(DateField, Object.assign({}, timeInputProps)) }))] }) })))] })));
|
|
27
29
|
}
|
|
28
30
|
function getNativeValue(value) {
|
|
29
31
|
if (!value) {
|
|
@@ -32,7 +32,7 @@ const data = [
|
|
|
32
32
|
get title() {
|
|
33
33
|
return i18n('Last 5 minutes');
|
|
34
34
|
},
|
|
35
|
-
from: 'now
|
|
35
|
+
from: 'now - 5m',
|
|
36
36
|
to: 'now',
|
|
37
37
|
},
|
|
38
38
|
{
|
|
@@ -60,8 +60,8 @@ const data = [
|
|
|
60
60
|
get title() {
|
|
61
61
|
return i18n('Previous month');
|
|
62
62
|
},
|
|
63
|
-
from: 'now
|
|
64
|
-
to: 'now
|
|
63
|
+
from: 'now - 1M/M',
|
|
64
|
+
to: 'now - 1M/M',
|
|
65
65
|
},
|
|
66
66
|
];
|
|
67
67
|
function PresetsExamples({ size }) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gravity-ui/date-components",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/cjs/index.js",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"@bem-react/classname": "^1.6.0",
|
|
49
49
|
"@gravity-ui/date-utils": "^2.0.1",
|
|
50
50
|
"@gravity-ui/icons": "^2.2.0",
|
|
51
|
-
"tslib": "2.6.2"
|
|
51
|
+
"tslib": "^2.6.2"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"@babel/preset-env": "^7.22.9",
|