@gravity-ui/date-components 1.0.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/LICENSE +21 -0
- package/README.md +15 -0
- package/dist/cjs/components/Calendar/Calendar.css +220 -0
- package/dist/cjs/components/Calendar/Calendar.d.ts +13 -0
- package/dist/cjs/components/Calendar/Calendar.js +15 -0
- package/dist/cjs/components/Calendar/CalendarBase.d.ts +18 -0
- package/dist/cjs/components/Calendar/CalendarBase.js +89 -0
- package/dist/cjs/components/Calendar/RangeCalendar.d.ts +13 -0
- package/dist/cjs/components/Calendar/RangeCalendar.js +22 -0
- package/dist/cjs/components/Calendar/hooks/types.d.ts +124 -0
- package/dist/cjs/components/Calendar/hooks/types.js +2 -0
- package/dist/cjs/components/Calendar/hooks/useCalendarCellProps.d.ts +19 -0
- package/dist/cjs/components/Calendar/hooks/useCalendarCellProps.js +98 -0
- package/dist/cjs/components/Calendar/hooks/useCalendarGridProps.d.ts +5 -0
- package/dist/cjs/components/Calendar/hooks/useCalendarGridProps.js +57 -0
- package/dist/cjs/components/Calendar/hooks/useCalendarProps.d.ts +10 -0
- package/dist/cjs/components/Calendar/hooks/useCalendarProps.js +110 -0
- package/dist/cjs/components/Calendar/hooks/useCalendarState.d.ts +7 -0
- package/dist/cjs/components/Calendar/hooks/useCalendarState.js +178 -0
- package/dist/cjs/components/Calendar/hooks/useRangeCalendarState.d.ts +7 -0
- package/dist/cjs/components/Calendar/hooks/useRangeCalendarState.js +82 -0
- package/dist/cjs/components/Calendar/i18n/en.json +4 -0
- package/dist/cjs/components/Calendar/i18n/index.d.ts +1 -0
- package/dist/cjs/components/Calendar/i18n/index.js +11 -0
- package/dist/cjs/components/Calendar/i18n/ru.json +4 -0
- package/dist/cjs/components/Calendar/index.d.ts +8 -0
- package/dist/cjs/components/Calendar/index.js +23 -0
- package/dist/cjs/components/Calendar/utils.d.ts +4 -0
- package/dist/cjs/components/Calendar/utils.js +40 -0
- package/dist/cjs/components/DateField/DateField.css +4 -0
- package/dist/cjs/components/DateField/DateField.d.ts +6 -0
- package/dist/cjs/components/DateField/DateField.js +38 -0
- package/dist/cjs/components/DateField/hooks/useDateFieldProps.d.ts +6 -0
- package/dist/cjs/components/DateField/hooks/useDateFieldProps.js +203 -0
- package/dist/cjs/components/DateField/hooks/useDateFieldState.d.ts +67 -0
- package/dist/cjs/components/DateField/hooks/useDateFieldState.js +628 -0
- package/dist/cjs/components/DateField/i18n/en.json +10 -0
- package/dist/cjs/components/DateField/i18n/index.d.ts +1 -0
- package/dist/cjs/components/DateField/i18n/index.js +11 -0
- package/dist/cjs/components/DateField/i18n/ru.json +10 -0
- package/dist/cjs/components/DateField/index.d.ts +3 -0
- package/dist/cjs/components/DateField/index.js +19 -0
- package/dist/cjs/components/DateField/types.d.ts +67 -0
- package/dist/cjs/components/DateField/types.js +2 -0
- package/dist/cjs/components/DateField/utils.d.ts +14 -0
- package/dist/cjs/components/DateField/utils.js +276 -0
- package/dist/cjs/components/DatePicker/DatePicker.css +19 -0
- package/dist/cjs/components/DatePicker/DatePicker.d.ts +5 -0
- package/dist/cjs/components/DatePicker/DatePicker.js +66 -0
- package/dist/cjs/components/DatePicker/DesktopCalendar.d.ts +15 -0
- package/dist/cjs/components/DatePicker/DesktopCalendar.js +56 -0
- package/dist/cjs/components/DatePicker/MobileCalendar.css +49 -0
- package/dist/cjs/components/DatePicker/MobileCalendar.d.ts +14 -0
- package/dist/cjs/components/DatePicker/MobileCalendar.js +78 -0
- package/dist/cjs/components/DatePicker/hooks/useDatePickerState.d.ts +45 -0
- package/dist/cjs/components/DatePicker/hooks/useDatePickerState.js +114 -0
- package/dist/cjs/components/DatePicker/i18n/en.json +3 -0
- package/dist/cjs/components/DatePicker/i18n/index.d.ts +1 -0
- package/dist/cjs/components/DatePicker/i18n/index.js +11 -0
- package/dist/cjs/components/DatePicker/i18n/ru.json +3 -0
- package/dist/cjs/components/DatePicker/index.d.ts +2 -0
- package/dist/cjs/components/DatePicker/index.js +18 -0
- package/dist/cjs/components/DatePicker/utils.d.ts +1 -0
- package/dist/cjs/components/DatePicker/utils.js +5 -0
- package/dist/cjs/components/RelativeDateField/RelativeDateField.css +16 -0
- package/dist/cjs/components/RelativeDateField/RelativeDateField.d.ts +11 -0
- package/dist/cjs/components/RelativeDateField/RelativeDateField.js +37 -0
- package/dist/cjs/components/RelativeDateField/hooks/useRelativeDateFieldProps.d.ts +12 -0
- package/dist/cjs/components/RelativeDateField/hooks/useRelativeDateFieldProps.js +66 -0
- package/dist/cjs/components/RelativeDateField/hooks/useRelativeDateFieldState.d.ts +30 -0
- package/dist/cjs/components/RelativeDateField/hooks/useRelativeDateFieldState.js +66 -0
- package/dist/cjs/components/RelativeDateField/index.d.ts +3 -0
- package/dist/cjs/components/RelativeDateField/index.js +19 -0
- package/dist/cjs/components/RelativeDatePicker/RelativeDatePicker.css +16 -0
- package/dist/cjs/components/RelativeDatePicker/RelativeDatePicker.d.ts +6 -0
- package/dist/cjs/components/RelativeDatePicker/RelativeDatePicker.js +32 -0
- package/dist/cjs/components/RelativeDatePicker/hooks/useRelativeDatePickerProps.d.ts +17 -0
- package/dist/cjs/components/RelativeDatePicker/hooks/useRelativeDatePickerProps.js +175 -0
- package/dist/cjs/components/RelativeDatePicker/hooks/useRelativeDatePickerState.d.ts +36 -0
- package/dist/cjs/components/RelativeDatePicker/hooks/useRelativeDatePickerState.js +109 -0
- package/dist/cjs/components/RelativeDatePicker/i18n/en.json +4 -0
- package/dist/cjs/components/RelativeDatePicker/i18n/index.d.ts +1 -0
- package/dist/cjs/components/RelativeDatePicker/i18n/index.js +11 -0
- package/dist/cjs/components/RelativeDatePicker/i18n/ru.json +4 -0
- package/dist/cjs/components/RelativeDatePicker/index.d.ts +3 -0
- package/dist/cjs/components/RelativeDatePicker/index.js +19 -0
- package/dist/cjs/components/hooks/useControlledState.d.ts +1 -0
- package/dist/cjs/components/hooks/useControlledState.js +30 -0
- package/dist/cjs/components/index.d.ts +5 -0
- package/dist/cjs/components/index.js +21 -0
- package/dist/cjs/components/types/datePicker.d.ts +16 -0
- package/dist/cjs/components/types/datePicker.js +2 -0
- package/dist/cjs/components/types/events.d.ts +17 -0
- package/dist/cjs/components/types/events.js +2 -0
- package/dist/cjs/components/types/index.d.ts +4 -0
- package/dist/cjs/components/types/index.js +2 -0
- package/dist/cjs/components/types/inputs.d.ts +79 -0
- package/dist/cjs/components/types/inputs.js +2 -0
- package/dist/cjs/components/types/style.d.ts +7 -0
- package/dist/cjs/components/types/style.js +2 -0
- package/dist/cjs/components/utils/getButtonSizeForInput.d.ts +2 -0
- package/dist/cjs/components/utils/getButtonSizeForInput.js +20 -0
- package/dist/cjs/components/utils/mergeProps.d.ts +13 -0
- package/dist/cjs/components/utils/mergeProps.js +47 -0
- package/dist/cjs/components/variables.css +0 -0
- package/dist/cjs/index.d.ts +1 -0
- package/dist/cjs/index.js +17 -0
- package/dist/cjs/utils/cn.d.ts +2 -0
- package/dist/cjs/utils/cn.js +6 -0
- package/dist/esm/components/Calendar/Calendar.css +220 -0
- package/dist/esm/components/Calendar/Calendar.d.ts +13 -0
- package/dist/esm/components/Calendar/Calendar.js +9 -0
- package/dist/esm/components/Calendar/CalendarBase.d.ts +18 -0
- package/dist/esm/components/Calendar/CalendarBase.js +83 -0
- package/dist/esm/components/Calendar/RangeCalendar.d.ts +13 -0
- package/dist/esm/components/Calendar/RangeCalendar.js +16 -0
- package/dist/esm/components/Calendar/hooks/types.d.ts +124 -0
- package/dist/esm/components/Calendar/hooks/types.js +1 -0
- package/dist/esm/components/Calendar/hooks/useCalendarCellProps.d.ts +19 -0
- package/dist/esm/components/Calendar/hooks/useCalendarCellProps.js +91 -0
- package/dist/esm/components/Calendar/hooks/useCalendarGridProps.d.ts +5 -0
- package/dist/esm/components/Calendar/hooks/useCalendarGridProps.js +54 -0
- package/dist/esm/components/Calendar/hooks/useCalendarProps.d.ts +10 -0
- package/dist/esm/components/Calendar/hooks/useCalendarProps.js +103 -0
- package/dist/esm/components/Calendar/hooks/useCalendarState.d.ts +7 -0
- package/dist/esm/components/Calendar/hooks/useCalendarState.js +171 -0
- package/dist/esm/components/Calendar/hooks/useRangeCalendarState.d.ts +7 -0
- package/dist/esm/components/Calendar/hooks/useRangeCalendarState.js +75 -0
- package/dist/esm/components/Calendar/i18n/en.json +4 -0
- package/dist/esm/components/Calendar/i18n/index.d.ts +1 -0
- package/dist/esm/components/Calendar/i18n/index.js +5 -0
- package/dist/esm/components/Calendar/i18n/ru.json +4 -0
- package/dist/esm/components/Calendar/index.d.ts +8 -0
- package/dist/esm/components/Calendar/index.js +7 -0
- package/dist/esm/components/Calendar/utils.d.ts +4 -0
- package/dist/esm/components/Calendar/utils.js +34 -0
- package/dist/esm/components/DateField/DateField.css +4 -0
- package/dist/esm/components/DateField/DateField.d.ts +6 -0
- package/dist/esm/components/DateField/DateField.js +31 -0
- package/dist/esm/components/DateField/hooks/useDateFieldProps.d.ts +6 -0
- package/dist/esm/components/DateField/hooks/useDateFieldProps.js +196 -0
- package/dist/esm/components/DateField/hooks/useDateFieldState.d.ts +67 -0
- package/dist/esm/components/DateField/hooks/useDateFieldState.js +621 -0
- package/dist/esm/components/DateField/i18n/en.json +10 -0
- package/dist/esm/components/DateField/i18n/index.d.ts +1 -0
- package/dist/esm/components/DateField/i18n/index.js +5 -0
- package/dist/esm/components/DateField/i18n/ru.json +10 -0
- package/dist/esm/components/DateField/index.d.ts +3 -0
- package/dist/esm/components/DateField/index.js +3 -0
- package/dist/esm/components/DateField/types.d.ts +67 -0
- package/dist/esm/components/DateField/types.js +1 -0
- package/dist/esm/components/DateField/utils.d.ts +14 -0
- package/dist/esm/components/DateField/utils.js +268 -0
- package/dist/esm/components/DatePicker/DatePicker.css +19 -0
- package/dist/esm/components/DatePicker/DatePicker.d.ts +5 -0
- package/dist/esm/components/DatePicker/DatePicker.js +59 -0
- package/dist/esm/components/DatePicker/DesktopCalendar.d.ts +15 -0
- package/dist/esm/components/DatePicker/DesktopCalendar.js +48 -0
- package/dist/esm/components/DatePicker/MobileCalendar.css +49 -0
- package/dist/esm/components/DatePicker/MobileCalendar.d.ts +14 -0
- package/dist/esm/components/DatePicker/MobileCalendar.js +73 -0
- package/dist/esm/components/DatePicker/hooks/useDatePickerState.d.ts +45 -0
- package/dist/esm/components/DatePicker/hooks/useDatePickerState.js +107 -0
- package/dist/esm/components/DatePicker/i18n/en.json +3 -0
- package/dist/esm/components/DatePicker/i18n/index.d.ts +1 -0
- package/dist/esm/components/DatePicker/i18n/index.js +5 -0
- package/dist/esm/components/DatePicker/i18n/ru.json +3 -0
- package/dist/esm/components/DatePicker/index.d.ts +2 -0
- package/dist/esm/components/DatePicker/index.js +2 -0
- package/dist/esm/components/DatePicker/utils.d.ts +1 -0
- package/dist/esm/components/DatePicker/utils.js +2 -0
- package/dist/esm/components/RelativeDateField/RelativeDateField.css +16 -0
- package/dist/esm/components/RelativeDateField/RelativeDateField.d.ts +11 -0
- package/dist/esm/components/RelativeDateField/RelativeDateField.js +30 -0
- package/dist/esm/components/RelativeDateField/hooks/useRelativeDateFieldProps.d.ts +12 -0
- package/dist/esm/components/RelativeDateField/hooks/useRelativeDateFieldProps.js +59 -0
- package/dist/esm/components/RelativeDateField/hooks/useRelativeDateFieldState.d.ts +30 -0
- package/dist/esm/components/RelativeDateField/hooks/useRelativeDateFieldState.js +59 -0
- package/dist/esm/components/RelativeDateField/index.d.ts +3 -0
- package/dist/esm/components/RelativeDateField/index.js +3 -0
- package/dist/esm/components/RelativeDatePicker/RelativeDatePicker.css +16 -0
- package/dist/esm/components/RelativeDatePicker/RelativeDatePicker.d.ts +6 -0
- package/dist/esm/components/RelativeDatePicker/RelativeDatePicker.js +25 -0
- package/dist/esm/components/RelativeDatePicker/hooks/useRelativeDatePickerProps.d.ts +17 -0
- package/dist/esm/components/RelativeDatePicker/hooks/useRelativeDatePickerProps.js +168 -0
- package/dist/esm/components/RelativeDatePicker/hooks/useRelativeDatePickerState.d.ts +36 -0
- package/dist/esm/components/RelativeDatePicker/hooks/useRelativeDatePickerState.js +102 -0
- package/dist/esm/components/RelativeDatePicker/i18n/en.json +4 -0
- package/dist/esm/components/RelativeDatePicker/i18n/index.d.ts +1 -0
- package/dist/esm/components/RelativeDatePicker/i18n/index.js +5 -0
- package/dist/esm/components/RelativeDatePicker/i18n/ru.json +4 -0
- package/dist/esm/components/RelativeDatePicker/index.d.ts +3 -0
- package/dist/esm/components/RelativeDatePicker/index.js +3 -0
- package/dist/esm/components/hooks/useControlledState.d.ts +1 -0
- package/dist/esm/components/hooks/useControlledState.js +23 -0
- package/dist/esm/components/index.d.ts +5 -0
- package/dist/esm/components/index.js +5 -0
- package/dist/esm/components/types/datePicker.d.ts +16 -0
- package/dist/esm/components/types/datePicker.js +1 -0
- package/dist/esm/components/types/events.d.ts +17 -0
- package/dist/esm/components/types/events.js +1 -0
- package/dist/esm/components/types/index.d.ts +4 -0
- package/dist/esm/components/types/index.js +1 -0
- package/dist/esm/components/types/inputs.d.ts +79 -0
- package/dist/esm/components/types/inputs.js +1 -0
- package/dist/esm/components/types/style.d.ts +7 -0
- package/dist/esm/components/types/style.js +1 -0
- package/dist/esm/components/utils/getButtonSizeForInput.d.ts +2 -0
- package/dist/esm/components/utils/getButtonSizeForInput.js +16 -0
- package/dist/esm/components/utils/mergeProps.d.ts +13 -0
- package/dist/esm/components/utils/mergeProps.js +43 -0
- package/dist/esm/components/variables.css +0 -0
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/utils/cn.d.ts +2 -0
- package/dist/esm/utils/cn.js +3 -0
- package/package.json +119 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
export type DateFieldSectionType = Exclude<Intl.DateTimeFormatPartTypes, 'era'>;
|
|
2
|
+
export type DateFormatTokenMap = {
|
|
3
|
+
[formatToken: string]: DateFieldSectionType | {
|
|
4
|
+
sectionType: DateFieldSectionType;
|
|
5
|
+
contentType: 'digit' | 'letter';
|
|
6
|
+
};
|
|
7
|
+
};
|
|
8
|
+
export interface DateFieldSection {
|
|
9
|
+
value: number | undefined;
|
|
10
|
+
/**
|
|
11
|
+
* Value of the section, as rendered inside the input.
|
|
12
|
+
* For example, in the date `May 25, 1995`, the value of the month section is "May".
|
|
13
|
+
*/
|
|
14
|
+
textValue: string;
|
|
15
|
+
/**
|
|
16
|
+
* Format token used to parse the value of this section from the date object.
|
|
17
|
+
* For example, in the format `MMMM D, YYYY`, the format of the month section is "MMMM".
|
|
18
|
+
*/
|
|
19
|
+
format: string;
|
|
20
|
+
/**
|
|
21
|
+
* Placeholder rendered when the value of this section is empty.
|
|
22
|
+
*/
|
|
23
|
+
placeholder: string;
|
|
24
|
+
/**
|
|
25
|
+
* Type of the section.
|
|
26
|
+
*/
|
|
27
|
+
type: DateFieldSectionType;
|
|
28
|
+
/**
|
|
29
|
+
* Type of content of the section.
|
|
30
|
+
* Will determine if we should apply a digit-based editing or a letter-based editing.
|
|
31
|
+
*/
|
|
32
|
+
contentType: 'digit' | 'letter';
|
|
33
|
+
/**
|
|
34
|
+
* Available values
|
|
35
|
+
*/
|
|
36
|
+
options?: string[];
|
|
37
|
+
/** The minimum numeric value for the segment, if applicable. */
|
|
38
|
+
minValue?: number;
|
|
39
|
+
/** The maximum numeric value for the segment, if applicable. */
|
|
40
|
+
maxValue?: number;
|
|
41
|
+
/**
|
|
42
|
+
* If `true`, the value of this section is supposed to have leading zeroes.
|
|
43
|
+
* For example, the value `1` should be rendered as "01" instead of "1".
|
|
44
|
+
*/
|
|
45
|
+
hasLeadingZeros: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* If `true`, the section value has been modified since the last time the sections were generated from a valid date.
|
|
48
|
+
* When we can generate a valid date from the section, we don't directly pass it to `onChange`,
|
|
49
|
+
* Otherwise, we would lose all the information contained in the original date, things like:
|
|
50
|
+
* - time if the format does not contain it
|
|
51
|
+
* - timezone / UTC
|
|
52
|
+
*
|
|
53
|
+
* To avoid losing that information, we transfer the values of the modified sections from the newly generated date to the original date.
|
|
54
|
+
*/
|
|
55
|
+
modified: boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Start index of the section in the format
|
|
58
|
+
*/
|
|
59
|
+
start: number;
|
|
60
|
+
/**
|
|
61
|
+
* End index of the section in the format
|
|
62
|
+
*/
|
|
63
|
+
end: number;
|
|
64
|
+
previousEditableSection: number;
|
|
65
|
+
nextEditableSection: number;
|
|
66
|
+
}
|
|
67
|
+
export type DateFieldSectionWithoutPosition<TSection extends DateFieldSection = DateFieldSection> = Omit<TSection, 'start' | 'end' | 'value' | 'textValue' | 'modified' | 'previousEditableSection' | 'nextEditableSection'>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { DateTime } from '@gravity-ui/date-utils';
|
|
2
|
+
import type { DateFieldSectionWithoutPosition } from './types';
|
|
3
|
+
export declare const isMac: boolean;
|
|
4
|
+
export declare const CtrlCmd: string;
|
|
5
|
+
export declare function expandFormat(format: string): string;
|
|
6
|
+
export declare function splitFormatIntoSections(format: string): DateFieldSectionWithoutPosition[];
|
|
7
|
+
interface PlaceholderValueOptions {
|
|
8
|
+
placeholderValue?: DateTime;
|
|
9
|
+
timeZone?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function createPlaceholderValue({ placeholderValue, timeZone }: PlaceholderValueOptions): DateTime;
|
|
12
|
+
export declare function isInvalid(value: DateTime | null | undefined, minValue: DateTime | undefined, maxValue: DateTime | undefined): boolean;
|
|
13
|
+
export declare function mergeDateTime(date: DateTime, time: DateTime): DateTime;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import { dateTime, settings } from '@gravity-ui/date-utils';
|
|
2
|
+
import { i18n } from './i18n';
|
|
3
|
+
export const isMac = window.navigator.userAgent.indexOf('Macintosh') >= 0;
|
|
4
|
+
export const CtrlCmd = isMac ? 'metaKey' : 'ctrlKey';
|
|
5
|
+
export function expandFormat(format) {
|
|
6
|
+
const localeFormats = settings.getLocaleData().formats;
|
|
7
|
+
const getShortLocalizedFormatFromLongLocalizedFormat = (formatBis) => formatBis.replace(/(\[[^\]]+])|(MMMM|MM|DD|dddd)/g, (_, escapeSequence, localizedFormat) => escapeSequence || localizedFormat.slice(1));
|
|
8
|
+
return format.replace(/(\[[^\]]+])|(LTS?|l{1,4}|L{1,4})/g, (_, escapeSequence, localizedFormat) => {
|
|
9
|
+
const LongLocalizedFormat = localizedFormat && localizedFormat.toUpperCase();
|
|
10
|
+
return (escapeSequence ||
|
|
11
|
+
localeFormats[localizedFormat] ||
|
|
12
|
+
getShortLocalizedFormatFromLongLocalizedFormat(localeFormats[LongLocalizedFormat]));
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
const escapedCharacters = { start: '[', end: ']' };
|
|
16
|
+
const formatTokenMap = {
|
|
17
|
+
// Year
|
|
18
|
+
YY: 'year',
|
|
19
|
+
YYYY: 'year',
|
|
20
|
+
// Month
|
|
21
|
+
M: 'month',
|
|
22
|
+
MM: 'month',
|
|
23
|
+
MMM: { sectionType: 'month', contentType: 'letter' },
|
|
24
|
+
MMMM: { sectionType: 'month', contentType: 'letter' },
|
|
25
|
+
// Day of the month
|
|
26
|
+
D: 'day',
|
|
27
|
+
DD: 'day',
|
|
28
|
+
Do: 'day',
|
|
29
|
+
// Day of the week
|
|
30
|
+
d: 'weekday',
|
|
31
|
+
dd: { sectionType: 'weekday', contentType: 'letter' },
|
|
32
|
+
ddd: { sectionType: 'weekday', contentType: 'letter' },
|
|
33
|
+
dddd: { sectionType: 'weekday', contentType: 'letter' },
|
|
34
|
+
// Day period AM, PM
|
|
35
|
+
A: { sectionType: 'dayPeriod', contentType: 'letter' },
|
|
36
|
+
a: { sectionType: 'dayPeriod', contentType: 'letter' },
|
|
37
|
+
// Hours
|
|
38
|
+
H: 'hour',
|
|
39
|
+
HH: 'hour',
|
|
40
|
+
h: 'hour',
|
|
41
|
+
hh: 'hour',
|
|
42
|
+
// Minutes
|
|
43
|
+
m: 'minute',
|
|
44
|
+
mm: 'minute',
|
|
45
|
+
// Seconds
|
|
46
|
+
s: 'second',
|
|
47
|
+
ss: 'second',
|
|
48
|
+
// Timezone
|
|
49
|
+
z: { sectionType: 'timeZoneName', contentType: 'letter' },
|
|
50
|
+
zzz: { sectionType: 'timeZoneName', contentType: 'letter' },
|
|
51
|
+
Z: { sectionType: 'timeZoneName', contentType: 'letter' },
|
|
52
|
+
ZZ: { sectionType: 'timeZoneName', contentType: 'letter' },
|
|
53
|
+
};
|
|
54
|
+
function getDateSectionConfigFromFormatToken(formatToken) {
|
|
55
|
+
const config = formatTokenMap[formatToken];
|
|
56
|
+
if (!config) {
|
|
57
|
+
console.error([
|
|
58
|
+
`The token "${formatToken}" is not supported by the Date field.`,
|
|
59
|
+
'Please try using another token.',
|
|
60
|
+
].join('\n'));
|
|
61
|
+
return {
|
|
62
|
+
type: 'literal',
|
|
63
|
+
contentType: 'letter',
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
if (typeof config === 'string') {
|
|
67
|
+
return {
|
|
68
|
+
type: config,
|
|
69
|
+
contentType: 'digit',
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
type: config.sectionType,
|
|
74
|
+
contentType: config.contentType,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
function isFourDigitYearFormat(format) {
|
|
78
|
+
return dateTime().format(format).length === 4;
|
|
79
|
+
}
|
|
80
|
+
function doesSectionHaveLeadingZeros(contentType, sectionType, format) {
|
|
81
|
+
if (contentType !== 'digit') {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
switch (sectionType) {
|
|
85
|
+
case 'year': {
|
|
86
|
+
if (isFourDigitYearFormat(format)) {
|
|
87
|
+
const formatted0001 = dateTime().set('year', 1).format(format);
|
|
88
|
+
return formatted0001 === '0001';
|
|
89
|
+
}
|
|
90
|
+
const formatted2001 = dateTime().set('year', 2001).format(format);
|
|
91
|
+
return formatted2001 === '01';
|
|
92
|
+
}
|
|
93
|
+
case 'month': {
|
|
94
|
+
return dateTime().startOf('year').format(format).length > 1;
|
|
95
|
+
}
|
|
96
|
+
case 'day': {
|
|
97
|
+
return dateTime().startOf('month').format(format).length > 1;
|
|
98
|
+
}
|
|
99
|
+
case 'weekday': {
|
|
100
|
+
return dateTime().startOf('week').format(format).length > 1;
|
|
101
|
+
}
|
|
102
|
+
case 'hour': {
|
|
103
|
+
return dateTime().set('hour', 1).format(format).length > 1;
|
|
104
|
+
}
|
|
105
|
+
case 'minute': {
|
|
106
|
+
return dateTime().set('minute', 1).format(format).length > 1;
|
|
107
|
+
}
|
|
108
|
+
case 'second': {
|
|
109
|
+
return dateTime().set('second', 1).format(format).length > 1;
|
|
110
|
+
}
|
|
111
|
+
default: {
|
|
112
|
+
throw new Error('Invalid section type');
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
function getSectionPlaceholder(sectionConfig, currentTokenValue) {
|
|
117
|
+
switch (sectionConfig.type) {
|
|
118
|
+
case 'year': {
|
|
119
|
+
return i18n('year_placeholder').repeat(dateTime().format(currentTokenValue).length);
|
|
120
|
+
}
|
|
121
|
+
case 'month': {
|
|
122
|
+
return i18n('month_placeholder').repeat(sectionConfig.contentType === 'letter' ? 4 : 2);
|
|
123
|
+
}
|
|
124
|
+
case 'day': {
|
|
125
|
+
return i18n('day_placeholder').repeat(2);
|
|
126
|
+
}
|
|
127
|
+
case 'weekday': {
|
|
128
|
+
return i18n('weekday_placeholder').repeat(sectionConfig.contentType === 'letter' ? 4 : 2);
|
|
129
|
+
}
|
|
130
|
+
case 'hour': {
|
|
131
|
+
return i18n('hour_placeholder').repeat(2);
|
|
132
|
+
}
|
|
133
|
+
case 'minute': {
|
|
134
|
+
return i18n('minute_placeholder').repeat(2);
|
|
135
|
+
}
|
|
136
|
+
case 'second': {
|
|
137
|
+
return i18n('second_placeholder').repeat(2);
|
|
138
|
+
}
|
|
139
|
+
case 'dayPeriod': {
|
|
140
|
+
return i18n('dayPeriod_placeholder');
|
|
141
|
+
}
|
|
142
|
+
default: {
|
|
143
|
+
return currentTokenValue;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
export function splitFormatIntoSections(format) {
|
|
148
|
+
const sections = [];
|
|
149
|
+
const expandedFormat = expandFormat(format);
|
|
150
|
+
let currentTokenValue = '';
|
|
151
|
+
let isSeparator = false;
|
|
152
|
+
let isInEscapeBoundary = false;
|
|
153
|
+
for (let i = 0; i < expandedFormat.length; i++) {
|
|
154
|
+
const char = expandedFormat[i];
|
|
155
|
+
if (isInEscapeBoundary) {
|
|
156
|
+
if (char === escapedCharacters.end) {
|
|
157
|
+
isInEscapeBoundary = false;
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
currentTokenValue += char;
|
|
161
|
+
}
|
|
162
|
+
else if (char.match(/[a-zA-Z]/)) {
|
|
163
|
+
if (isSeparator) {
|
|
164
|
+
addLiteralSection(sections, currentTokenValue);
|
|
165
|
+
currentTokenValue = '';
|
|
166
|
+
}
|
|
167
|
+
isSeparator = false;
|
|
168
|
+
currentTokenValue += char;
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
if (!isSeparator) {
|
|
172
|
+
addFormatSection(sections, currentTokenValue);
|
|
173
|
+
currentTokenValue = '';
|
|
174
|
+
}
|
|
175
|
+
isSeparator = true;
|
|
176
|
+
if (char === escapedCharacters.start) {
|
|
177
|
+
isInEscapeBoundary = true;
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
currentTokenValue += char;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
if (currentTokenValue) {
|
|
185
|
+
if (isSeparator) {
|
|
186
|
+
addLiteralSection(sections, currentTokenValue);
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
addFormatSection(sections, currentTokenValue);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return sections;
|
|
193
|
+
}
|
|
194
|
+
function addFormatSection(sections, token) {
|
|
195
|
+
if (!token) {
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
const sectionConfig = getDateSectionConfigFromFormatToken(token);
|
|
199
|
+
const hasLeadingZeros = doesSectionHaveLeadingZeros(sectionConfig.contentType, sectionConfig.type, token);
|
|
200
|
+
sections.push(Object.assign(Object.assign({}, sectionConfig), { format: token, placeholder: getSectionPlaceholder(sectionConfig, token), options: getSectionOptions(sectionConfig, token), hasLeadingZeros }));
|
|
201
|
+
}
|
|
202
|
+
function addLiteralSection(sections, token) {
|
|
203
|
+
if (!token) {
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
sections.push({
|
|
207
|
+
type: 'literal',
|
|
208
|
+
contentType: 'letter',
|
|
209
|
+
format: token,
|
|
210
|
+
placeholder: token,
|
|
211
|
+
hasLeadingZeros: false,
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
function getSectionOptions(section, token) {
|
|
215
|
+
switch (section.type) {
|
|
216
|
+
case 'month': {
|
|
217
|
+
const format = section.contentType === 'letter' ? token : 'MMMM';
|
|
218
|
+
let date = dateTime().startOf('year');
|
|
219
|
+
const options = [];
|
|
220
|
+
for (let i = 0; i < 12; i++) {
|
|
221
|
+
options.push(date.format(format).toLocaleUpperCase());
|
|
222
|
+
date = date.add(1, 'months');
|
|
223
|
+
}
|
|
224
|
+
return options;
|
|
225
|
+
}
|
|
226
|
+
case 'dayPeriod': {
|
|
227
|
+
const amDayPeriod = dateTime().hour(0);
|
|
228
|
+
const pmDayPeriod = amDayPeriod.hour(12);
|
|
229
|
+
const options = [
|
|
230
|
+
amDayPeriod.format(token).toLocaleUpperCase(),
|
|
231
|
+
pmDayPeriod.format(token).toLocaleUpperCase(),
|
|
232
|
+
];
|
|
233
|
+
return options;
|
|
234
|
+
}
|
|
235
|
+
case 'weekday': {
|
|
236
|
+
const format = section.contentType === 'letter' ? token : 'dddd';
|
|
237
|
+
let date = dateTime().day(0);
|
|
238
|
+
const options = [];
|
|
239
|
+
for (let i = 0; i < 7; i++) {
|
|
240
|
+
options.push(date.format(format).toLocaleUpperCase());
|
|
241
|
+
date = date.add(1, 'day');
|
|
242
|
+
}
|
|
243
|
+
return options;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
return undefined;
|
|
247
|
+
}
|
|
248
|
+
export function createPlaceholderValue({ placeholderValue, timeZone }) {
|
|
249
|
+
return (placeholderValue !== null && placeholderValue !== void 0 ? placeholderValue : dateTime({ timeZone }).set('hour', 0).set('minute', 0).set('second', 0));
|
|
250
|
+
}
|
|
251
|
+
export function isInvalid(value, minValue, maxValue) {
|
|
252
|
+
if (!value) {
|
|
253
|
+
return false;
|
|
254
|
+
}
|
|
255
|
+
if (minValue && value.isBefore(minValue)) {
|
|
256
|
+
return true;
|
|
257
|
+
}
|
|
258
|
+
if (maxValue && maxValue.isBefore(value)) {
|
|
259
|
+
return true;
|
|
260
|
+
}
|
|
261
|
+
return false;
|
|
262
|
+
}
|
|
263
|
+
export function mergeDateTime(date, time) {
|
|
264
|
+
return date
|
|
265
|
+
.set('hours', time.hour())
|
|
266
|
+
.set('minutes', time.minute())
|
|
267
|
+
.set('seconds', time.second());
|
|
268
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
.g-date-date-picker {
|
|
2
|
+
position: relative;
|
|
3
|
+
display: inline-block;
|
|
4
|
+
}
|
|
5
|
+
.g-date-date-picker__field {
|
|
6
|
+
width: 100%;
|
|
7
|
+
}
|
|
8
|
+
.g-date-date-picker__field_mobile {
|
|
9
|
+
pointer-events: none;
|
|
10
|
+
}
|
|
11
|
+
.g-date-date-picker__popup-content {
|
|
12
|
+
outline: none;
|
|
13
|
+
}
|
|
14
|
+
.g-date-date-picker__time-field {
|
|
15
|
+
width: 100%;
|
|
16
|
+
}
|
|
17
|
+
.g-date-date-picker__time-field-wrapper {
|
|
18
|
+
padding: 10px;
|
|
19
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { AccessibilityProps, DateFieldBase, DomProps, FocusableProps, KeyboardEvents, StyleProps, TextInputProps } from '../types';
|
|
2
|
+
import './DatePicker.css';
|
|
3
|
+
export interface DatePickerProps extends DateFieldBase, TextInputProps, FocusableProps, KeyboardEvents, DomProps, StyleProps, AccessibilityProps {
|
|
4
|
+
}
|
|
5
|
+
export declare function DatePicker({ value, defaultValue, onUpdate, className, onFocus, onBlur, ...props }: DatePickerProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
2
|
+
var t = {};
|
|
3
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
4
|
+
t[p] = s[p];
|
|
5
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
6
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
7
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
8
|
+
t[p[i]] = s[p[i]];
|
|
9
|
+
}
|
|
10
|
+
return t;
|
|
11
|
+
};
|
|
12
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
13
|
+
import React from 'react';
|
|
14
|
+
import { TextInput, useFocusWithin, useMobile } from '@gravity-ui/uikit';
|
|
15
|
+
import { useDateFieldProps, useDateFieldState } from '../DateField';
|
|
16
|
+
import { DesktopCalendar, DesktopCalendarButton } from './DesktopCalendar';
|
|
17
|
+
import { MobileCalendar, MobileCalendarIcon } from './MobileCalendar';
|
|
18
|
+
import { useDatePickerState } from './hooks/useDatePickerState';
|
|
19
|
+
import { b } from './utils';
|
|
20
|
+
import './DatePicker.css';
|
|
21
|
+
export function DatePicker(_a) {
|
|
22
|
+
var { value, defaultValue, onUpdate, className, onFocus, onBlur } = _a, props = __rest(_a, ["value", "defaultValue", "onUpdate", "className", "onFocus", "onBlur"]);
|
|
23
|
+
const anchorRef = React.useRef(null);
|
|
24
|
+
const state = useDatePickerState(Object.assign(Object.assign({}, props), { value,
|
|
25
|
+
defaultValue,
|
|
26
|
+
onUpdate }));
|
|
27
|
+
const [isMobile] = useMobile();
|
|
28
|
+
const [isActive, setActive] = React.useState(false);
|
|
29
|
+
const { focusWithinProps } = useFocusWithin({
|
|
30
|
+
onFocusWithin: onFocus,
|
|
31
|
+
onBlurWithin: onBlur,
|
|
32
|
+
onFocusWithinChange(isFocusWithin) {
|
|
33
|
+
setActive(isFocusWithin);
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
const fieldState = useDateFieldState({
|
|
37
|
+
value: state.value,
|
|
38
|
+
onUpdate: state.setValue,
|
|
39
|
+
disabled: state.disabled,
|
|
40
|
+
readOnly: state.readOnly,
|
|
41
|
+
validationState: props.validationState,
|
|
42
|
+
minValue: props.minValue,
|
|
43
|
+
maxValue: props.maxValue,
|
|
44
|
+
isDateUnavailable: props.isDateUnavailable,
|
|
45
|
+
format: state.format,
|
|
46
|
+
placeholderValue: props.placeholderValue,
|
|
47
|
+
timeZone: props.timeZone,
|
|
48
|
+
});
|
|
49
|
+
const { inputProps } = useDateFieldProps(fieldState, props);
|
|
50
|
+
return (
|
|
51
|
+
// eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions
|
|
52
|
+
_jsxs("div", Object.assign({ ref: anchorRef, className: b(null, className), style: props.style }, focusWithinProps, { role: "group", "aria-disabled": state.disabled || undefined, onKeyDown: (e) => {
|
|
53
|
+
if (e.altKey && (e.key === 'ArrowDown' || e.key === 'ArrowUp')) {
|
|
54
|
+
e.preventDefault();
|
|
55
|
+
e.stopPropagation();
|
|
56
|
+
state.setOpen(true);
|
|
57
|
+
}
|
|
58
|
+
}, children: [isMobile ? (_jsx(MobileCalendar, { props: props, state: state })) : (_jsx(DesktopCalendar, { anchorRef: anchorRef, props: props, state: state })), _jsx(TextInput, Object.assign({}, inputProps, { value: fieldState.isEmpty && !isActive && props.placeholder ? '' : inputProps.value, className: b('field', { mobile: isMobile }), hasClear: !isMobile && inputProps.hasClear, rightContent: isMobile ? (_jsx(MobileCalendarIcon, { props: props, state: state })) : (_jsx(DesktopCalendarButton, { props: props, state: state })) }))] })));
|
|
59
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { DatePickerProps } from './DatePicker';
|
|
3
|
+
import type { DatePickerState } from './hooks/useDatePickerState';
|
|
4
|
+
interface DesktopCalendarProps {
|
|
5
|
+
anchorRef: React.RefObject<HTMLElement>;
|
|
6
|
+
props: DatePickerProps;
|
|
7
|
+
state: DatePickerState;
|
|
8
|
+
}
|
|
9
|
+
export declare function DesktopCalendar({ anchorRef, props, state }: DesktopCalendarProps): import("react/jsx-runtime").JSX.Element | null;
|
|
10
|
+
interface DesktopCalendarButtonProps {
|
|
11
|
+
props: DatePickerProps;
|
|
12
|
+
state: DatePickerState;
|
|
13
|
+
}
|
|
14
|
+
export declare function DesktopCalendarButton({ props, state }: DesktopCalendarButtonProps): import("react/jsx-runtime").JSX.Element | null;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { Calendar as CalendarIcon } from '@gravity-ui/icons';
|
|
4
|
+
import { Button, Icon, Popup, useFocusWithin } from '@gravity-ui/uikit';
|
|
5
|
+
import { Calendar } from '../Calendar';
|
|
6
|
+
import { DateField } from '../DateField';
|
|
7
|
+
import { getButtonSizeForInput } from '../utils/getButtonSizeForInput';
|
|
8
|
+
import { i18n } from './i18n';
|
|
9
|
+
import { b } from './utils';
|
|
10
|
+
export function DesktopCalendar({ anchorRef, props, state }) {
|
|
11
|
+
var _a;
|
|
12
|
+
const { focusWithinProps } = useFocusWithin({
|
|
13
|
+
isDisabled: !state.isOpen,
|
|
14
|
+
onBlurWithin: () => {
|
|
15
|
+
state.setOpen(false);
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
if (!state.hasDate) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
return (_jsx(Popup, { open: state.isOpen, anchorRef: anchorRef, onClose: () => {
|
|
22
|
+
state.setOpen(false);
|
|
23
|
+
}, restoreFocus: true, children: _jsxs("div", Object.assign({}, focusWithinProps, { className: b('popup-content'), children: [_jsx(Calendar
|
|
24
|
+
// eslint-disable-next-line jsx-a11y/no-autofocus
|
|
25
|
+
, {
|
|
26
|
+
// eslint-disable-next-line jsx-a11y/no-autofocus
|
|
27
|
+
autoFocus: true, size: props.size === 's' ? 'm' : props.size, disabled: props.disabled, readOnly: props.readOnly, onUpdate: (d) => {
|
|
28
|
+
state.setDateValue(d);
|
|
29
|
+
}, defaultFocusedValue: (_a = state.dateValue) !== null && _a !== void 0 ? _a : undefined, value: state.dateValue, minValue: props.minValue, maxValue: props.maxValue, isDateUnavailable: props.isDateUnavailable, timeZone: props.timeZone }), state.hasTime && (_jsx("div", { className: b('time-field-wrapper'), children: _jsx(DateField, { className: b('time-field'), size: props.size, readOnly: props.readOnly, value: state.timeValue, onUpdate: state.setTimeValue, placeholderValue: props.placeholderValue, minValue: props.minValue, maxValue: props.maxValue, timeZone: props.timeZone, format: state.timeFormat }) }))] })) }));
|
|
30
|
+
}
|
|
31
|
+
export function DesktopCalendarButton({ props, state }) {
|
|
32
|
+
const wasOpenBeforeClickRef = React.useRef(false);
|
|
33
|
+
if (!state.hasDate) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
return (_jsx(Button, { view: "flat", size: getButtonSizeForInput(props.size), disabled: props.disabled, extraProps: {
|
|
37
|
+
'aria-label': i18n('Calendar'),
|
|
38
|
+
'aria-haspopup': 'dialog',
|
|
39
|
+
'aria-expanded': state.isOpen,
|
|
40
|
+
}, onFocus: () => {
|
|
41
|
+
wasOpenBeforeClickRef.current = state.isOpen;
|
|
42
|
+
}, onClick: () => {
|
|
43
|
+
if (!wasOpenBeforeClickRef.current) {
|
|
44
|
+
state.setOpen(true);
|
|
45
|
+
}
|
|
46
|
+
wasOpenBeforeClickRef.current = false;
|
|
47
|
+
}, children: _jsx(Icon, { data: CalendarIcon }) }));
|
|
48
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
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
|
+
position: absolute;
|
|
28
|
+
z-index: 1;
|
|
29
|
+
top: 0;
|
|
30
|
+
left: 0;
|
|
31
|
+
box-sizing: border-box;
|
|
32
|
+
width: 100%;
|
|
33
|
+
height: 100%;
|
|
34
|
+
margin: 0;
|
|
35
|
+
padding: 0;
|
|
36
|
+
cursor: pointer;
|
|
37
|
+
opacity: 0;
|
|
38
|
+
border: none;
|
|
39
|
+
}
|
|
40
|
+
.g-date-mobile-calendar__input::-webkit-calendar-picker-indicator {
|
|
41
|
+
position: absolute;
|
|
42
|
+
top: 0;
|
|
43
|
+
left: 0;
|
|
44
|
+
width: 100%;
|
|
45
|
+
height: 100%;
|
|
46
|
+
margin: 0;
|
|
47
|
+
padding: 0;
|
|
48
|
+
cursor: pointer;
|
|
49
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { DatePickerProps } from './DatePicker';
|
|
2
|
+
import type { DatePickerState } from './hooks/useDatePickerState';
|
|
3
|
+
import './MobileCalendar.css';
|
|
4
|
+
interface MobileCalendarProps {
|
|
5
|
+
props: DatePickerProps;
|
|
6
|
+
state: DatePickerState;
|
|
7
|
+
}
|
|
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
|
+
export {};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
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
|
+
import { block } from '../../utils/cn';
|
|
6
|
+
import { createPlaceholderValue, mergeDateTime } from '../DateField/utils';
|
|
7
|
+
import { getButtonSizeForInput } from '../utils/getButtonSizeForInput';
|
|
8
|
+
import './MobileCalendar.css';
|
|
9
|
+
const b = block('mobile-calendar');
|
|
10
|
+
export function MobileCalendar({ props, state }) {
|
|
11
|
+
let type = 'date';
|
|
12
|
+
if (state.hasTime && state.hasDate) {
|
|
13
|
+
type = 'datetime-local';
|
|
14
|
+
}
|
|
15
|
+
else if (state.hasTime) {
|
|
16
|
+
type = 'time';
|
|
17
|
+
}
|
|
18
|
+
return (_jsx("input", { className: b('input'), disabled: props.disabled, type: type, value: formatNative(state.value || props.placeholderValue, type), id: props.id, min: formatNative(props.minValue, type), max: formatNative(props.maxValue, type), tabIndex: -1, onChange: (e) => {
|
|
19
|
+
if (props.readOnly) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const newValue = e.target.value;
|
|
23
|
+
if (newValue) {
|
|
24
|
+
const localDate = dateTime({ input: newValue, format: getDateFormat(type) });
|
|
25
|
+
let newDate = state.hasDate
|
|
26
|
+
? dateTime({
|
|
27
|
+
input: newValue,
|
|
28
|
+
format: getDateFormat(type),
|
|
29
|
+
timeZone: props.timeZone,
|
|
30
|
+
})
|
|
31
|
+
: createPlaceholderValue({
|
|
32
|
+
placeholderValue: props.placeholderValue,
|
|
33
|
+
timeZone: props.timeZone,
|
|
34
|
+
});
|
|
35
|
+
if (state.hasTime) {
|
|
36
|
+
newDate = mergeDateTime(newDate, localDate);
|
|
37
|
+
}
|
|
38
|
+
else if (state.dateValue) {
|
|
39
|
+
newDate = mergeDateTime(newDate, state.dateValue);
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
newDate = newDate.set('hours', 0).set('minutes', 0).set('seconds', 0);
|
|
43
|
+
}
|
|
44
|
+
state.setValue(newDate);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
state.setValue(null);
|
|
48
|
+
}
|
|
49
|
+
} }));
|
|
50
|
+
}
|
|
51
|
+
export function MobileCalendarIcon({ props }) {
|
|
52
|
+
return (_jsx("span", { className: b({ size: getButtonSizeForInput(props.size) }), children: _jsx("span", { className: b('button'), children: _jsx(Icon, { data: CalendarIcon }) }) }));
|
|
53
|
+
}
|
|
54
|
+
function getDateFormat(type) {
|
|
55
|
+
switch (type) {
|
|
56
|
+
case 'time': {
|
|
57
|
+
return 'HH:mm';
|
|
58
|
+
}
|
|
59
|
+
case 'datetime-local': {
|
|
60
|
+
return 'YYYY-MM-DDTHH:mm';
|
|
61
|
+
}
|
|
62
|
+
default: {
|
|
63
|
+
return 'YYYY-MM-DD';
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
function formatNative(date, type) {
|
|
68
|
+
if (!date) {
|
|
69
|
+
return '';
|
|
70
|
+
}
|
|
71
|
+
const format = getDateFormat(type);
|
|
72
|
+
return date.format(format);
|
|
73
|
+
}
|