@gravity-ui/date-components 2.8.3 → 2.10.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/Calendar.css +1 -1
- package/dist/cjs/components/CalendarView/CalendarView.js +3 -2
- package/dist/cjs/components/CalendarView/hooks/types.d.ts +2 -0
- package/dist/cjs/components/CalendarView/hooks/useCalendarCellProps.js +22 -19
- package/dist/cjs/components/CalendarView/hooks/useCalendarGridProps.js +2 -1
- package/dist/cjs/components/CalendarView/hooks/useCalendarProps.js +2 -1
- package/dist/cjs/components/CalendarView/hooks/useCalendarState.js +14 -8
- package/dist/cjs/components/CalendarView/hooks/useRangeCalendarState.js +1 -2
- package/dist/cjs/components/CalendarView/utils.d.ts +0 -1
- package/dist/cjs/components/CalendarView/utils.js +0 -10
- package/dist/cjs/components/DateField/hooks/useDateFieldProps.js +1 -4
- package/dist/cjs/components/RangeDatePicker/RangeDatePicker.js +1 -1
- package/dist/cjs/components/RelativeDateField/hooks/useRelativeDateFieldProps.js +1 -0
- package/dist/cjs/components/RelativeRangeDatePicker/RelativeRangeDatePicker.css +0 -34
- package/dist/cjs/components/RelativeRangeDatePicker/RelativeRangeDatePicker.d.ts +1 -30
- package/dist/cjs/components/RelativeRangeDatePicker/RelativeRangeDatePicker.js +16 -50
- package/dist/cjs/components/RelativeRangeDatePicker/components/Control/Control.css +34 -0
- package/dist/cjs/components/RelativeRangeDatePicker/components/Control/Control.d.ts +16 -0
- package/dist/cjs/components/RelativeRangeDatePicker/components/Control/Control.js +64 -0
- package/dist/cjs/components/RelativeRangeDatePicker/components/Control/i18n/en.json +3 -0
- package/dist/cjs/components/RelativeRangeDatePicker/components/Control/i18n/index.d.ts +1 -0
- package/dist/cjs/components/RelativeRangeDatePicker/components/Control/i18n/index.js +11 -0
- package/dist/cjs/components/RelativeRangeDatePicker/components/Control/i18n/ru.json +3 -0
- package/dist/cjs/components/RelativeRangeDatePicker/components/PickerDialog/PickerDialog.d.ts +1 -1
- package/dist/cjs/components/RelativeRangeDatePicker/components/PickerDialog/useRelativeRangeDatePickerDialogState.d.ts +1 -1
- package/dist/cjs/components/RelativeRangeDatePicker/components/Zones/Zones.js +2 -2
- package/dist/cjs/components/RelativeRangeDatePicker/i18n/en.json +1 -2
- package/dist/cjs/components/RelativeRangeDatePicker/i18n/index.d.ts +1 -1
- package/dist/cjs/components/RelativeRangeDatePicker/i18n/ru.json +1 -2
- package/dist/cjs/components/RelativeRangeDatePicker/types.d.ts +42 -0
- package/dist/cjs/components/RelativeRangeDatePicker/types.js +2 -0
- package/dist/cjs/components/utils/dates.d.ts +3 -0
- package/dist/cjs/components/utils/dates.js +18 -0
- package/dist/esm/components/CalendarView/Calendar.css +1 -1
- package/dist/esm/components/CalendarView/CalendarView.js +3 -2
- package/dist/esm/components/CalendarView/hooks/types.d.ts +2 -0
- package/dist/esm/components/CalendarView/hooks/useCalendarCellProps.js +22 -19
- package/dist/esm/components/CalendarView/hooks/useCalendarGridProps.js +2 -1
- package/dist/esm/components/CalendarView/hooks/useCalendarProps.js +2 -1
- package/dist/esm/components/CalendarView/hooks/useCalendarState.js +9 -3
- package/dist/esm/components/CalendarView/hooks/useRangeCalendarState.js +1 -2
- package/dist/esm/components/CalendarView/utils.d.ts +0 -1
- package/dist/esm/components/CalendarView/utils.js +0 -9
- package/dist/esm/components/DateField/hooks/useDateFieldProps.js +1 -4
- package/dist/esm/components/RangeDatePicker/RangeDatePicker.js +1 -1
- package/dist/esm/components/RelativeDateField/hooks/useRelativeDateFieldProps.js +1 -0
- package/dist/esm/components/RelativeRangeDatePicker/RelativeRangeDatePicker.css +0 -34
- package/dist/esm/components/RelativeRangeDatePicker/RelativeRangeDatePicker.d.ts +1 -30
- package/dist/esm/components/RelativeRangeDatePicker/RelativeRangeDatePicker.js +17 -51
- package/dist/esm/components/RelativeRangeDatePicker/components/Control/Control.css +34 -0
- package/dist/esm/components/RelativeRangeDatePicker/components/Control/Control.d.ts +16 -0
- package/dist/esm/components/RelativeRangeDatePicker/components/Control/Control.js +58 -0
- package/dist/esm/components/RelativeRangeDatePicker/components/Control/i18n/en.json +3 -0
- package/dist/esm/components/RelativeRangeDatePicker/components/Control/i18n/index.d.ts +1 -0
- package/dist/esm/components/RelativeRangeDatePicker/components/Control/i18n/index.js +5 -0
- package/dist/esm/components/RelativeRangeDatePicker/components/Control/i18n/ru.json +3 -0
- package/dist/esm/components/RelativeRangeDatePicker/components/PickerDialog/PickerDialog.d.ts +1 -1
- package/dist/esm/components/RelativeRangeDatePicker/components/PickerDialog/useRelativeRangeDatePickerDialogState.d.ts +1 -1
- package/dist/esm/components/RelativeRangeDatePicker/components/Zones/Zones.js +2 -2
- package/dist/esm/components/RelativeRangeDatePicker/i18n/en.json +1 -2
- package/dist/esm/components/RelativeRangeDatePicker/i18n/index.d.ts +1 -1
- package/dist/esm/components/RelativeRangeDatePicker/i18n/ru.json +1 -2
- package/dist/esm/components/RelativeRangeDatePicker/types.d.ts +42 -0
- package/dist/esm/components/RelativeRangeDatePicker/types.js +1 -0
- package/dist/esm/components/utils/dates.d.ts +3 -0
- package/dist/esm/components/utils/dates.js +15 -0
- package/package.json +1 -1
package/dist/cjs/components/RelativeRangeDatePicker/components/PickerDialog/PickerDialog.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { RelativeRangeDatePickerProps } from '../../RelativeRangeDatePicker';
|
|
2
1
|
import type { RelativeRangeDatePickerState } from '../../hooks/useRelativeRangeDatePickerState';
|
|
2
|
+
import type { RelativeRangeDatePickerProps } from '../../types';
|
|
3
3
|
import './PickerDialog.css';
|
|
4
4
|
export interface PickerDialogProps {
|
|
5
5
|
className?: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Value } from '../../../RelativeDatePicker';
|
|
2
|
-
import type { RelativeRangeDatePickerProps } from '../../RelativeRangeDatePicker';
|
|
3
2
|
import type { RelativeRangeDatePickerState } from '../../hooks/useRelativeRangeDatePickerState';
|
|
3
|
+
import type { RelativeRangeDatePickerProps } from '../../types';
|
|
4
4
|
export declare function useRelativeRangeDatePickerDialogState(state: RelativeRangeDatePickerState, props: RelativeRangeDatePickerProps): {
|
|
5
5
|
start: Value | null;
|
|
6
6
|
end: Value | null;
|
|
@@ -43,14 +43,14 @@ const b = (0, cn_1.block)('relative-range-date-picker-zones');
|
|
|
43
43
|
function Zones(props) {
|
|
44
44
|
const timeZone = (0, utils_1.normalizeTimeZone)(props.value);
|
|
45
45
|
const size = props.isMobile ? 'xl' : props.size;
|
|
46
|
-
return ((0, jsx_runtime_1.jsx)(uikit_1.Select, { value: [timeZone], options: zones, size: size, onUpdate: (v) => {
|
|
46
|
+
return ((0, jsx_runtime_1.jsx)(uikit_1.Select, { disabled: props.disabled, value: [timeZone], options: zones, size: size, onUpdate: (v) => {
|
|
47
47
|
const tz = v[0];
|
|
48
48
|
if (tz) {
|
|
49
49
|
props.onUpdate(tz);
|
|
50
50
|
}
|
|
51
51
|
}, width: "max", renderControl: (controlProps) => {
|
|
52
52
|
const value = timeZone === 'system' || timeZone === 'default' ? (0, i18n_1.i18n)(timeZone) : timeZone;
|
|
53
|
-
return ((0, jsx_runtime_1.jsxs)(uikit_1.Button, { onClick: controlProps.onClick, ref: controlProps.ref, view: "flat-secondary", width: "max", pin: "clear-clear", size: size, extraProps: {
|
|
53
|
+
return ((0, jsx_runtime_1.jsxs)(uikit_1.Button, { onClick: controlProps.onClick, ref: controlProps.ref, view: "flat-secondary", width: "max", pin: "clear-clear", size: size, disabled: props.disabled, extraProps: {
|
|
54
54
|
'aria-haspopup': 'listbox',
|
|
55
55
|
'aria-expanded': controlProps.open,
|
|
56
56
|
onKeyDown: controlProps.onKeyDown,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const i18n: (key: "\"From\"" | "\"From\" is required." | "\"To\"" | "\"To\" is required." | "\"From\" can't be after \"To\"." | "to"
|
|
1
|
+
export declare const i18n: (key: "\"From\"" | "\"From\" is required." | "\"To\"" | "\"To\" is required." | "\"From\" can't be after \"To\"." | "to", params?: import("@gravity-ui/i18n").Params | undefined) => string;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { DateTime } from '@gravity-ui/date-utils';
|
|
2
|
+
import type { Value } from '../RelativeDatePicker';
|
|
3
|
+
import type { AccessibilityProps, DomProps, FocusableProps, InputBase, InputDOMProps, RangeValue, StyleProps, TextInputProps, Validation } from '../types';
|
|
4
|
+
import type { Preset } from './components/Presets/defaultPresets';
|
|
5
|
+
import type { PresetTab } from './components/Presets/utils';
|
|
6
|
+
import type { RelativeRangeDatePickerStateOptions, RelativeRangeDatePickerValue } from './hooks/useRelativeRangeDatePickerState';
|
|
7
|
+
export type RelativeRangeDatePickerTriggerProps = Pick<React.InputHTMLAttributes<HTMLElement>, 'id' | 'role' | 'aria-controls' | 'aria-haspopup' | 'aria-expanded' | 'aria-label' | 'aria-labelledby' | 'aria-describedby' | 'aria-details' | 'onClick' | 'onKeyDown' | 'disabled' | 'readOnly'>;
|
|
8
|
+
export interface RelativeRangeDatePickerRenderControlProps {
|
|
9
|
+
ref: React.Ref<HTMLElement>;
|
|
10
|
+
value: RelativeRangeDatePickerValue | null;
|
|
11
|
+
title: string;
|
|
12
|
+
errorMessage?: React.ReactNode;
|
|
13
|
+
validationState?: 'invalid';
|
|
14
|
+
open: boolean;
|
|
15
|
+
triggerProps: RelativeRangeDatePickerTriggerProps;
|
|
16
|
+
}
|
|
17
|
+
export interface RelativeRangeDatePickerProps extends RelativeRangeDatePickerStateOptions, DomProps, AccessibilityProps, InputBase, InputDOMProps, TextInputProps, Validation, FocusableProps, StyleProps {
|
|
18
|
+
/** Format of the date when rendered in the input. [Available formats](https://day.js.org/docs/en/display/format) */
|
|
19
|
+
format?: string;
|
|
20
|
+
/** A placeholder date that controls the default values of each segment when the user first interacts with them. Defaults to today's date at midnight. */
|
|
21
|
+
placeholderValue?: DateTime;
|
|
22
|
+
/** Apply changes with button */
|
|
23
|
+
withApplyButton?: boolean;
|
|
24
|
+
/** Show time zone selector */
|
|
25
|
+
withZonesList?: boolean;
|
|
26
|
+
/** Show relative range presets */
|
|
27
|
+
withPresets?: boolean;
|
|
28
|
+
/** Custom preset tabs */
|
|
29
|
+
presetTabs?: PresetTab[];
|
|
30
|
+
/** Custom docs for presets, if empty array docs will be hidden */
|
|
31
|
+
docs?: Preset[];
|
|
32
|
+
/** Show selected relative values as absolute dates */
|
|
33
|
+
alwaysShowAsAbsolute?: boolean;
|
|
34
|
+
/** */
|
|
35
|
+
getRangeTitle?: (value: RangeValue<Value | null> | null, timeZone: string) => string;
|
|
36
|
+
/** Sets the CSS className for the popup element. */
|
|
37
|
+
popupClassName?: string;
|
|
38
|
+
/** Handler that is called when the popup's open state changes. */
|
|
39
|
+
onOpenChange?: (open: boolean) => void;
|
|
40
|
+
/** Used to render control. */
|
|
41
|
+
renderControl?: (props: RelativeRangeDatePickerRenderControlProps) => React.ReactElement;
|
|
42
|
+
}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import type { DateTime } from '@gravity-ui/date-utils';
|
|
2
|
+
export declare function isWeekend(date: DateTime): boolean;
|
|
2
3
|
export interface PlaceholderValueOptions {
|
|
3
4
|
placeholderValue?: DateTime;
|
|
4
5
|
timeZone?: string;
|
|
5
6
|
}
|
|
6
7
|
export declare function createPlaceholderValue({ placeholderValue, timeZone }: PlaceholderValueOptions): DateTime;
|
|
7
8
|
export declare function isInvalid(value: DateTime | null | undefined, minValue: DateTime | undefined, maxValue: DateTime | undefined): boolean;
|
|
9
|
+
export declare function constrainValue(value: DateTime, minValue: DateTime | undefined, maxValue: DateTime | undefined): DateTime;
|
|
8
10
|
export declare function mergeDateTime(date: DateTime, time: DateTime): DateTime;
|
|
11
|
+
export declare function formatDateTime(date: DateTime, format: string, timezone: string): string;
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isWeekend = isWeekend;
|
|
3
4
|
exports.createPlaceholderValue = createPlaceholderValue;
|
|
4
5
|
exports.isInvalid = isInvalid;
|
|
6
|
+
exports.constrainValue = constrainValue;
|
|
5
7
|
exports.mergeDateTime = mergeDateTime;
|
|
8
|
+
exports.formatDateTime = formatDateTime;
|
|
6
9
|
const date_utils_1 = require("@gravity-ui/date-utils");
|
|
10
|
+
function isWeekend(date) {
|
|
11
|
+
return [0, 6].includes(date.day());
|
|
12
|
+
}
|
|
7
13
|
function createPlaceholderValue({ placeholderValue, timeZone }) {
|
|
8
14
|
return (placeholderValue !== null && placeholderValue !== void 0 ? placeholderValue : (0, date_utils_1.dateTime)({ timeZone }).set('hour', 0).set('minute', 0).set('second', 0));
|
|
9
15
|
}
|
|
@@ -19,9 +25,21 @@ function isInvalid(value, minValue, maxValue) {
|
|
|
19
25
|
}
|
|
20
26
|
return false;
|
|
21
27
|
}
|
|
28
|
+
function constrainValue(value, minValue, maxValue) {
|
|
29
|
+
if (minValue && value.isBefore(minValue)) {
|
|
30
|
+
return minValue;
|
|
31
|
+
}
|
|
32
|
+
if (maxValue && maxValue.isBefore(value)) {
|
|
33
|
+
return maxValue;
|
|
34
|
+
}
|
|
35
|
+
return value;
|
|
36
|
+
}
|
|
22
37
|
function mergeDateTime(date, time) {
|
|
23
38
|
return date
|
|
24
39
|
.set('hours', time.hour())
|
|
25
40
|
.set('minutes', time.minute())
|
|
26
41
|
.set('seconds', time.second());
|
|
27
42
|
}
|
|
43
|
+
function formatDateTime(date, format, timezone) {
|
|
44
|
+
return (0, date_utils_1.dateTime)({ input: date, timeZone: timezone }).format(format);
|
|
45
|
+
}
|
|
@@ -4,6 +4,7 @@ import React from 'react';
|
|
|
4
4
|
import { ChevronLeft, ChevronRight } from '@gravity-ui/icons';
|
|
5
5
|
import { ArrowToggle, Button } from '@gravity-ui/uikit';
|
|
6
6
|
import { block } from '../../utils/cn';
|
|
7
|
+
import { formatDateTime } from '../utils/dates';
|
|
7
8
|
import { useCalendarCellProps } from './hooks/useCalendarCellProps';
|
|
8
9
|
import { useCalendarGridProps } from './hooks/useCalendarGridProps';
|
|
9
10
|
import { useCalendarProps } from './hooks/useCalendarProps';
|
|
@@ -56,14 +57,14 @@ function Content({ className, state, animation, onAnimationEnd }) {
|
|
|
56
57
|
function Weekdays({ state }) {
|
|
57
58
|
const weekdays = getWeekDays();
|
|
58
59
|
return (_jsx("div", { className: b('grid-row'), role: "row", children: weekdays.map((date) => {
|
|
59
|
-
return (_jsx("div", { className: b('weekday', { weekend: state.isWeekend(date) }), role: "columnheader", "aria-label": date
|
|
60
|
+
return (_jsx("div", { className: b('weekday', { weekend: state.isWeekend(date) }), role: "columnheader", "aria-label": formatDateTime(date, 'dddd', state.timeZone), children: formatDateTime(date, 'dd', state.timeZone) }, date.day()));
|
|
60
61
|
}) }));
|
|
61
62
|
}
|
|
62
63
|
function CalendarGridCells({ state }) {
|
|
63
64
|
const rowsInPeriod = state.mode === 'days' ? 6 : 4;
|
|
64
65
|
const columnsInRow = state.mode === 'days' ? 7 : 3 + (state.mode === 'quarters' ? 1 : 0);
|
|
65
66
|
const days = getDaysInPeriod(state.startDate, state.endDate, state.mode);
|
|
66
|
-
return (_jsx("div", { className: b('grid-rowgroup', { mode: state.mode }), role: "rowgroup", children: [...new Array(rowsInPeriod).keys()].map((rowIndex) => (_jsxs("div", { className: b('grid-row'), role: "row", children: [state.mode === 'quarters' ? (_jsx("span", { role: "rowheader", className: b('grid-rowgroup-header'), children: days[rowIndex * columnsInRow]
|
|
67
|
+
return (_jsx("div", { className: b('grid-rowgroup', { mode: state.mode }), role: "rowgroup", children: [...new Array(rowsInPeriod).keys()].map((rowIndex) => (_jsxs("div", { className: b('grid-row'), role: "row", children: [state.mode === 'quarters' ? (_jsx("span", { role: "rowheader", className: b('grid-rowgroup-header'), children: formatDateTime(days[rowIndex * columnsInRow], 'YYYY', state.timeZone) })) : null, days
|
|
67
68
|
.slice(rowIndex * columnsInRow, (rowIndex + 1) * columnsInRow)
|
|
68
69
|
.map((date) => {
|
|
69
70
|
return _jsx(CalendarCell, { date: date, state: state }, date.unix());
|
|
@@ -8,6 +8,8 @@ export interface CalendarStateOptionsBase extends InputBase {
|
|
|
8
8
|
maxValue?: DateTime;
|
|
9
9
|
/** Callback that is called for each date of the calendar. If it returns true, then the date is unavailable. */
|
|
10
10
|
isDateUnavailable?: (date: DateTime) => boolean;
|
|
11
|
+
/** Callback that is called for each date of the calendar. If it returns true, then the date is weekend. */
|
|
12
|
+
isWeekend?: (date: DateTime) => boolean;
|
|
11
13
|
/**
|
|
12
14
|
* Which timezone use to show values. Example: 'default', 'system', 'Europe/Amsterdam'.
|
|
13
15
|
* @default The timezone of the `value` or `defaultValue` or `focusedValue` or `defaultFocusedValue`, 'default' otherwise.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import { formatDateTime } from '../../utils/dates';
|
|
2
3
|
export function useCalendarCellProps(date, state) {
|
|
3
4
|
const ref = React.useRef(null);
|
|
4
5
|
const isFocused = state.isCellFocused(date);
|
|
@@ -20,7 +21,7 @@ export function useCalendarCellProps(date, state) {
|
|
|
20
21
|
const isSelectable = !isDisabled && !isUnavailable;
|
|
21
22
|
const isCurrent = state.isCurrent(date);
|
|
22
23
|
const isWeekend = state.isWeekend(date);
|
|
23
|
-
const label = getDateLabel(date, state
|
|
24
|
+
const label = getDateLabel(date, state);
|
|
24
25
|
const cellProps = {
|
|
25
26
|
role: 'gridcell',
|
|
26
27
|
'aria-selected': isSelected ? 'true' : undefined,
|
|
@@ -52,15 +53,15 @@ export function useCalendarCellProps(date, state) {
|
|
|
52
53
|
}
|
|
53
54
|
},
|
|
54
55
|
};
|
|
55
|
-
let formattedDate = date
|
|
56
|
+
let formattedDate = formatDateTime(date, 'D', state.timeZone);
|
|
56
57
|
if (state.mode === 'months') {
|
|
57
|
-
formattedDate = date
|
|
58
|
+
formattedDate = formatDateTime(date, 'MMM', state.timeZone);
|
|
58
59
|
}
|
|
59
60
|
else if (state.mode === 'quarters') {
|
|
60
|
-
formattedDate = date
|
|
61
|
+
formattedDate = formatDateTime(date, '[Q]Q', state.timeZone);
|
|
61
62
|
}
|
|
62
63
|
else if (state.mode === 'years') {
|
|
63
|
-
formattedDate = date
|
|
64
|
+
formattedDate = formatDateTime(date, 'YYYY', state.timeZone);
|
|
64
65
|
}
|
|
65
66
|
return {
|
|
66
67
|
cellProps,
|
|
@@ -77,19 +78,21 @@ export function useCalendarCellProps(date, state) {
|
|
|
77
78
|
isWeekend,
|
|
78
79
|
};
|
|
79
80
|
}
|
|
80
|
-
function getDateLabel(date,
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
81
|
+
function getDateLabel(date, state) {
|
|
82
|
+
switch (state.mode) {
|
|
83
|
+
case 'days': {
|
|
84
|
+
return `${formatDateTime(date, 'dddd', state.timeZone)}, ${formatDateTime(date, 'LL', state.timeZone)}`;
|
|
85
|
+
}
|
|
86
|
+
case 'months': {
|
|
87
|
+
return `${formatDateTime(date, 'MMMM YYYY', state.timeZone)}`;
|
|
88
|
+
}
|
|
89
|
+
case 'quarters': {
|
|
90
|
+
return `${formatDateTime(date, '[Q]Q YYYY', state.timeZone)}`;
|
|
91
|
+
}
|
|
92
|
+
case 'years': {
|
|
93
|
+
return `${formatDateTime(date, 'YYYY', state.timeZone)}`;
|
|
94
|
+
}
|
|
95
|
+
default:
|
|
96
|
+
return '';
|
|
93
97
|
}
|
|
94
|
-
return label;
|
|
95
98
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { useFocusWithin } from '@gravity-ui/uikit';
|
|
2
|
+
import { formatDateTime } from '../../utils/dates';
|
|
2
3
|
export function useCalendarGridProps(state) {
|
|
3
4
|
const { focusWithinProps } = useFocusWithin({
|
|
4
5
|
onFocusWithinChange: (isFocused) => {
|
|
@@ -7,7 +8,7 @@ export function useCalendarGridProps(state) {
|
|
|
7
8
|
});
|
|
8
9
|
const gridProps = Object.assign(Object.assign({ role: 'grid', 'aria-label': state.mode === 'years' || state.mode === 'quarters'
|
|
9
10
|
? `${state.startDate.year()} — ${state.endDate.year()}`
|
|
10
|
-
: state.focusedDate
|
|
11
|
+
: formatDateTime(state.focusedDate, state.mode === 'days' ? 'MMMM YYYY' : 'YYYY', state.timeZone), 'aria-disabled': state.disabled ? 'true' : undefined, 'aria-readonly': state.readOnly ? 'true' : undefined }, focusWithinProps), { onKeyDown: (e) => {
|
|
11
12
|
if (e.key === 'ArrowRight') {
|
|
12
13
|
e.preventDefault();
|
|
13
14
|
state.focusNextCell();
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { useFocusWithin } from '@gravity-ui/uikit';
|
|
3
|
+
import { formatDateTime } from '../../utils/dates';
|
|
3
4
|
import { i18n } from '../i18n';
|
|
4
5
|
const buttonDisabledClassName = 'yc-button_disabled g-button_disabled';
|
|
5
6
|
// eslint-disable-next-line complexity
|
|
6
7
|
export function useCalendarProps(props, state) {
|
|
7
8
|
const title = state.mode === 'years' || state.mode === 'quarters'
|
|
8
9
|
? `${state.startDate.year()} — ${state.endDate.year()}`
|
|
9
|
-
: state.focusedDate
|
|
10
|
+
: formatDateTime(state.focusedDate, state.mode === 'days' ? 'MMMM YYYY' : 'YYYY', state.timeZone);
|
|
10
11
|
const { focusWithinProps } = useFocusWithin({
|
|
11
12
|
onFocusWithin: props.onFocus,
|
|
12
13
|
onBlurWithin: props.onBlur,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { dateTime } from '@gravity-ui/date-utils';
|
|
3
3
|
import { useControlledState } from '@gravity-ui/uikit';
|
|
4
|
-
import { createPlaceholderValue, mergeDateTime } from '../../utils/dates';
|
|
4
|
+
import { constrainValue, createPlaceholderValue, isWeekend, mergeDateTime } from '../../utils/dates';
|
|
5
5
|
import { useDefaultTimeZone } from '../../utils/useDefaultTimeZone';
|
|
6
|
-
import { calendarLayouts
|
|
6
|
+
import { calendarLayouts } from '../utils';
|
|
7
7
|
const defaultModes = {
|
|
8
8
|
days: true,
|
|
9
9
|
months: true,
|
|
@@ -193,7 +193,13 @@ export function useCalendarState(props) {
|
|
|
193
193
|
return this.disabled || this.isInvalid(date);
|
|
194
194
|
},
|
|
195
195
|
isWeekend(date) {
|
|
196
|
-
|
|
196
|
+
if (this.mode !== 'days') {
|
|
197
|
+
return false;
|
|
198
|
+
}
|
|
199
|
+
if (typeof props.isWeekend === 'function') {
|
|
200
|
+
return props.isWeekend(date);
|
|
201
|
+
}
|
|
202
|
+
return isWeekend(date);
|
|
197
203
|
},
|
|
198
204
|
isCurrent(date) {
|
|
199
205
|
return dateTime({ timeZone }).isSame(date, this.mode);
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { __rest } from "tslib";
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import { useControlledState } from '@gravity-ui/uikit';
|
|
4
|
-
import { mergeDateTime } from '../../utils/dates';
|
|
4
|
+
import { constrainValue, mergeDateTime } from '../../utils/dates';
|
|
5
5
|
import { useDefaultTimeZone } from '../../utils/useDefaultTimeZone';
|
|
6
|
-
import { constrainValue } from '../utils';
|
|
7
6
|
import { useCalendarState } from './useCalendarState';
|
|
8
7
|
export function useRangeCalendarState(props) {
|
|
9
8
|
var _a;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { DateTime } from '@gravity-ui/date-utils';
|
|
2
2
|
import type { CalendarLayout } from './hooks/types';
|
|
3
|
-
export declare function constrainValue(value: DateTime, minValue: DateTime | undefined, maxValue: DateTime | undefined): DateTime;
|
|
4
3
|
export declare function getDaysInPeriod(startDate: DateTime, _endDate: DateTime, mode: CalendarLayout): DateTime[];
|
|
5
4
|
export declare function getWeekDays(): DateTime[];
|
|
6
5
|
export declare const calendarLayouts: CalendarLayout[];
|
|
@@ -1,13 +1,4 @@
|
|
|
1
1
|
import { dateTime } from '@gravity-ui/date-utils';
|
|
2
|
-
export function constrainValue(value, minValue, maxValue) {
|
|
3
|
-
if (minValue && value.isBefore(minValue)) {
|
|
4
|
-
return minValue;
|
|
5
|
-
}
|
|
6
|
-
if (maxValue && maxValue.isBefore(value)) {
|
|
7
|
-
return maxValue;
|
|
8
|
-
}
|
|
9
|
-
return value;
|
|
10
|
-
}
|
|
11
2
|
export function getDaysInPeriod(startDate, _endDate, mode) {
|
|
12
3
|
const days = [];
|
|
13
4
|
if (mode === 'days') {
|
|
@@ -34,10 +34,6 @@ export function useDateFieldProps(state, props) {
|
|
|
34
34
|
});
|
|
35
35
|
function syncSelectionFromDOM() {
|
|
36
36
|
var _a, _b;
|
|
37
|
-
if (state.readOnly) {
|
|
38
|
-
setSelectedSections(-1);
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
37
|
state.focusSectionInPosition((_b = (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.selectionStart) !== null && _b !== void 0 ? _b : 0);
|
|
42
38
|
setInnerState({});
|
|
43
39
|
}
|
|
@@ -159,6 +155,7 @@ export function useDateFieldProps(state, props) {
|
|
|
159
155
|
'aria-describedby': props['aria-describedby'] || undefined,
|
|
160
156
|
'aria-details': props['aria-details'] || undefined,
|
|
161
157
|
'aria-disabled': state.disabled || undefined,
|
|
158
|
+
readOnly: state.readOnly,
|
|
162
159
|
inputMode,
|
|
163
160
|
onClick() {
|
|
164
161
|
syncSelectionFromDOM();
|
|
@@ -19,7 +19,7 @@ export function RangeDatePicker(_a) {
|
|
|
19
19
|
const state = useRangeDatePickerState(props);
|
|
20
20
|
const { groupProps, fieldProps, calendarButtonProps, popupProps, calendarProps, timeInputProps } = useDatePickerProps(state, props);
|
|
21
21
|
const isOnlyTime = state.hasTime && !state.hasDate;
|
|
22
|
-
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'),
|
|
22
|
+
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'), endContent: _jsxs(React.Fragment, { children: [!isOnlyTime && (_jsx(Button, Object.assign({}, calendarButtonProps, { children: _jsx(Icon, { data: CalendarIcon }) }))), isOnlyTime && (_jsx(StubButton, { size: calendarButtonProps.size, icon: ClockIcon }))] }) })), _jsx(HiddenInput, { name: props.name, form: props.form, onReset: (v) => {
|
|
23
23
|
state.dateFieldState.setDate(v);
|
|
24
24
|
}, value: state.value, toStringValue: (v) => (v ? v.start.toISOString() : ''), disabled: state.disabled }), _jsx(HiddenInput, { name: props.name, form: props.form, value: state.value, toStringValue: (v) => (v ? v.end.toISOString() : ''), disabled: state.disabled })] })));
|
|
25
25
|
}
|
|
@@ -34,6 +34,7 @@ export function useRelativeDateFieldProps(state, props) {
|
|
|
34
34
|
'aria-describedby': props['aria-describedby'] || undefined,
|
|
35
35
|
'aria-details': props['aria-details'] || undefined,
|
|
36
36
|
'aria-disabled': state.disabled || undefined,
|
|
37
|
+
readOnly: state.readOnly,
|
|
37
38
|
},
|
|
38
39
|
},
|
|
39
40
|
calendarProps: {
|
|
@@ -2,40 +2,6 @@
|
|
|
2
2
|
position: relative;
|
|
3
3
|
display: inline-flex;
|
|
4
4
|
}
|
|
5
|
-
.g-date-relative-range-date-picker__input {
|
|
6
|
-
caret-color: transparent;
|
|
7
|
-
}
|
|
8
|
-
.g-date-relative-range-date-picker__input_mobile {
|
|
9
|
-
pointer-events: none;
|
|
10
|
-
}
|
|
11
|
-
.g-date-relative-range-date-picker__mobile-trigger {
|
|
12
|
-
--_--g-date-mobile-trigger-clear-width: 0px;
|
|
13
|
-
--_--g-date-mobile-trigger-errors-width: 0px;
|
|
14
|
-
--_--g-date-mobile-trigger-button-width: 24px;
|
|
15
|
-
position: absolute;
|
|
16
|
-
inset: 0;
|
|
17
|
-
inset-inline-end: calc(var(--g-spacing-2) + var(--_--g-date-mobile-trigger-button-width) + var(--_--g-date-mobile-trigger-clear-width) + var(--_--g-date-mobile-trigger-errors-width));
|
|
18
|
-
opacity: 0;
|
|
19
|
-
}
|
|
20
|
-
.g-date-relative-range-date-picker__mobile-trigger_size_s {
|
|
21
|
-
--_--g-date-mobile-trigger-button-width: 20px;
|
|
22
|
-
}
|
|
23
|
-
.g-date-relative-range-date-picker__mobile-trigger_size_l {
|
|
24
|
-
--_--g-date-mobile-trigger-button-width: 28px;
|
|
25
|
-
}
|
|
26
|
-
.g-date-relative-range-date-picker__mobile-trigger_size_xl {
|
|
27
|
-
--_--g-date-mobile-trigger-button-width: 36px;
|
|
28
|
-
}
|
|
29
|
-
.g-date-relative-range-date-picker__mobile-trigger_has-clear {
|
|
30
|
-
--_--g-date-mobile-trigger-clear-width: calc(
|
|
31
|
-
var(--_--g-date-mobile-trigger-button-width) + 2px
|
|
32
|
-
);
|
|
33
|
-
}
|
|
34
|
-
.g-date-relative-range-date-picker__mobile-trigger_has-errors {
|
|
35
|
-
--_--g-date-mobile-trigger-errors-width: calc(
|
|
36
|
-
var(--_--g-date-mobile-trigger-button-width) + 2px
|
|
37
|
-
);
|
|
38
|
-
}
|
|
39
5
|
.g-date-relative-range-date-picker__value-label {
|
|
40
6
|
display: flex;
|
|
41
7
|
width: 100%;
|
|
@@ -1,32 +1,3 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { Value } from '../RelativeDatePicker';
|
|
3
|
-
import type { DomProps, FocusableProps, InputBase, InputDOMProps, RangeValue, StyleProps, TextInputProps, Validation } from '../types';
|
|
4
|
-
import type { Preset } from './components/Presets/defaultPresets';
|
|
5
|
-
import type { PresetTab } from './components/Presets/utils';
|
|
6
|
-
import type { RelativeRangeDatePickerStateOptions } from './hooks/useRelativeRangeDatePickerState';
|
|
1
|
+
import type { RelativeRangeDatePickerProps } from './types';
|
|
7
2
|
import './RelativeRangeDatePicker.css';
|
|
8
|
-
export interface RelativeRangeDatePickerProps extends RelativeRangeDatePickerStateOptions, DomProps, InputBase, InputDOMProps, TextInputProps, Validation, FocusableProps, StyleProps {
|
|
9
|
-
/** Format of the date when rendered in the input. [Available formats](https://day.js.org/docs/en/display/format) */
|
|
10
|
-
format?: string;
|
|
11
|
-
/** A placeholder date that controls the default values of each segment when the user first interacts with them. Defaults to today's date at midnight. */
|
|
12
|
-
placeholderValue?: DateTime;
|
|
13
|
-
/** Apply changes with button */
|
|
14
|
-
withApplyButton?: boolean;
|
|
15
|
-
/** Show time zone selector */
|
|
16
|
-
withZonesList?: boolean;
|
|
17
|
-
/** Show relative range presets */
|
|
18
|
-
withPresets?: boolean;
|
|
19
|
-
/** Custom preset tabs */
|
|
20
|
-
presetTabs?: PresetTab[];
|
|
21
|
-
/** Custom docs for presets, if empty array docs will be hidden */
|
|
22
|
-
docs?: Preset[];
|
|
23
|
-
/** Show selected relative values as absolute dates */
|
|
24
|
-
alwaysShowAsAbsolute?: boolean;
|
|
25
|
-
/** */
|
|
26
|
-
getRangeTitle?: (value: RangeValue<Value | null> | null, timeZone: string) => string;
|
|
27
|
-
/** Sets the CSS className for the popup element. */
|
|
28
|
-
popupClassName?: string;
|
|
29
|
-
/** Handler that is called when the popup's open state changes. */
|
|
30
|
-
onOpenChange?: (open: boolean) => void;
|
|
31
|
-
}
|
|
32
3
|
export declare function RelativeRangeDatePicker(props: RelativeRangeDatePickerProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,19 +1,15 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import React from 'react';
|
|
4
|
-
import {
|
|
5
|
-
import { Button, Icon, TextInput, useControlledState, useFocusWithin, useMobile, } from '@gravity-ui/uikit';
|
|
4
|
+
import { useControlledState, useFocusWithin, useMobile } from '@gravity-ui/uikit';
|
|
6
5
|
import { block } from '../../utils/cn';
|
|
7
6
|
import { HiddenInput } from '../HiddenInput/HiddenInput';
|
|
8
|
-
import {
|
|
7
|
+
import { Control } from './components/Control/Control';
|
|
9
8
|
import { PickerDialog } from './components/PickerDialog/PickerDialog';
|
|
10
9
|
import { useRelativeRangeDatePickerState } from './hooks/useRelativeRangeDatePickerState';
|
|
11
|
-
import { i18n } from './i18n';
|
|
12
|
-
import { getDefaultTitle } from './utils';
|
|
13
10
|
import './RelativeRangeDatePicker.css';
|
|
14
11
|
const b = block('relative-range-date-picker');
|
|
15
12
|
export function RelativeRangeDatePicker(props) {
|
|
16
|
-
var _a;
|
|
17
13
|
const state = useRelativeRangeDatePickerState(props);
|
|
18
14
|
const isMobile = useMobile();
|
|
19
15
|
const anchorRef = React.useRef(null);
|
|
@@ -36,37 +32,14 @@ export function RelativeRangeDatePicker(props) {
|
|
|
36
32
|
}
|
|
37
33
|
},
|
|
38
34
|
});
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
alwaysShowAsAbsolute: alwaysShowAsAbsolute,
|
|
47
|
-
format,
|
|
48
|
-
presets: presetTabs === null || presetTabs === void 0 ? void 0 : presetTabs.flatMap(({ presets }) => presets),
|
|
49
|
-
}), [alwaysShowAsAbsolute, format, getRangeTitle, presetTabs, state.timeZone, state.value]);
|
|
50
|
-
const validationState = props.validationState || (state.isInvalid ? 'invalid' : undefined);
|
|
51
|
-
const errorMessage = (_a = props.errorMessage) !== null && _a !== void 0 ? _a : state.errors.join('\n');
|
|
52
|
-
return (_jsxs("div", Object.assign({ ref: anchorRef }, focusWithinProps, { className: b(null, props.className), style: props.style, children: [_jsx(TextInput, { id: props.id, autoFocus: props.autoFocus, controlRef: inputRef, value: text, placeholder: props.placeholder, onUpdate: (v) => {
|
|
53
|
-
if (!props.readOnly && !v) {
|
|
54
|
-
state.setValue(null, 'default');
|
|
35
|
+
return (_jsxs("div", Object.assign({ ref: anchorRef }, focusWithinProps, { className: b(null, props.className), style: props.style, children: [_jsx(Control, { props: props, state: state, open: open, isMobile: isMobile, ref: inputRef, onClick: () => {
|
|
36
|
+
if (props.disabled) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
if (!open) {
|
|
40
|
+
setIsActive(true);
|
|
41
|
+
setOpen(true);
|
|
55
42
|
}
|
|
56
|
-
}, controlProps: {
|
|
57
|
-
role: 'combobox',
|
|
58
|
-
'aria-expanded': open,
|
|
59
|
-
disabled: isMobile,
|
|
60
|
-
className: b('input', { mobile: isMobile }),
|
|
61
|
-
onClick: () => {
|
|
62
|
-
if (props.disabled) {
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
if (!open) {
|
|
66
|
-
setIsActive(true);
|
|
67
|
-
setOpen(true);
|
|
68
|
-
}
|
|
69
|
-
},
|
|
70
43
|
}, onKeyDown: (e) => {
|
|
71
44
|
if (props.disabled) {
|
|
72
45
|
return;
|
|
@@ -75,26 +48,19 @@ export function RelativeRangeDatePicker(props) {
|
|
|
75
48
|
e.preventDefault();
|
|
76
49
|
setOpen(true);
|
|
77
50
|
}
|
|
51
|
+
}, onClickCalendar: () => {
|
|
52
|
+
setIsActive(true);
|
|
53
|
+
setOpen(!open);
|
|
78
54
|
}, onFocus: () => {
|
|
79
55
|
if (!isActive) {
|
|
80
56
|
setIsActive(true);
|
|
81
57
|
setOpen(true);
|
|
82
58
|
}
|
|
83
|
-
},
|
|
84
|
-
|
|
85
|
-
'
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
setIsActive(true);
|
|
89
|
-
setOpen(!open);
|
|
90
|
-
}, children: _jsx(Icon, { data: CalendarIcon }) }) }), isMobile ? (_jsx("button", { className: b('mobile-trigger', {
|
|
91
|
-
'has-clear': Boolean(props.hasClear && state.value),
|
|
92
|
-
'has-errors': state.isInvalid && props.errorPlacement === 'inside',
|
|
93
|
-
size: props.size,
|
|
94
|
-
}), onClick: () => {
|
|
95
|
-
setIsActive(true);
|
|
96
|
-
setOpen(true);
|
|
97
|
-
} })) : null, _jsx(HiddenInput, { name: props.name, form: props.form, value: state.value, toStringValue: (v) => { var _a, _b; return (_b = (_a = v === null || v === void 0 ? void 0 : v.start) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : ''; }, disabled: props.disabled }), _jsx(HiddenInput, { name: props.name, form: props.form, value: state.value, toStringValue: (v) => { var _a; return getNativeValue((_a = v === null || v === void 0 ? void 0 : v.start) !== null && _a !== void 0 ? _a : null); }, disabled: props.disabled }), _jsx(HiddenInput, { name: props.name, form: props.form, value: state.value, toStringValue: (v) => { var _a, _b; return (_b = (_a = v === null || v === void 0 ? void 0 : v.end) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : ''; }, disabled: props.disabled }), _jsx(HiddenInput, { name: props.name, form: props.form, value: state.value, toStringValue: (v) => { var _a; return getNativeValue((_a = v === null || v === void 0 ? void 0 : v.end) !== null && _a !== void 0 ? _a : null); }, disabled: props.disabled }), _jsx(HiddenInput, { name: props.name, form: props.form, onReset: (v) => {
|
|
59
|
+
}, onUpdate: (v) => {
|
|
60
|
+
if (!props.readOnly && !v) {
|
|
61
|
+
state.setValue(null, 'default');
|
|
62
|
+
}
|
|
63
|
+
} }), _jsx(HiddenInput, { name: props.name, form: props.form, value: state.value, toStringValue: (v) => { var _a, _b; return (_b = (_a = v === null || v === void 0 ? void 0 : v.start) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : ''; }, disabled: props.disabled }), _jsx(HiddenInput, { name: props.name, form: props.form, value: state.value, toStringValue: (v) => { var _a; return getNativeValue((_a = v === null || v === void 0 ? void 0 : v.start) !== null && _a !== void 0 ? _a : null); }, disabled: props.disabled }), _jsx(HiddenInput, { name: props.name, form: props.form, value: state.value, toStringValue: (v) => { var _a, _b; return (_b = (_a = v === null || v === void 0 ? void 0 : v.end) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : ''; }, disabled: props.disabled }), _jsx(HiddenInput, { name: props.name, form: props.form, value: state.value, toStringValue: (v) => { var _a; return getNativeValue((_a = v === null || v === void 0 ? void 0 : v.end) !== null && _a !== void 0 ? _a : null); }, disabled: props.disabled }), _jsx(HiddenInput, { name: props.name, form: props.form, onReset: (v) => {
|
|
98
64
|
state.setValue(v.value, v.timeZone);
|
|
99
65
|
}, value: { value: state.value, timeZone: state.timeZone }, toStringValue: (v) => v.timeZone, disabled: props.disabled }), _jsx(PickerDialog, { state: state, props: props, open: open, onClose: () => {
|
|
100
66
|
setOpen(false);
|