@jetbrains/ring-ui 7.0.113 → 7.0.115
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.
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type ReactNode } from 'react';
|
|
2
|
-
import type
|
|
2
|
+
import { type Locale } from 'date-fns';
|
|
3
3
|
declare const units: {
|
|
4
4
|
unit: number;
|
|
5
5
|
cellSize: number;
|
|
@@ -24,10 +24,11 @@ export declare const yearDuration: number;
|
|
|
24
24
|
export declare const yearScrollSpeed: number;
|
|
25
25
|
export declare const DOUBLE = 2;
|
|
26
26
|
export declare const HALF = 0.5;
|
|
27
|
-
export declare function parseTime(time: string): string | null;
|
|
27
|
+
export declare function parseTime(time: string | null | undefined): string | null;
|
|
28
28
|
export declare function shiftWeekArray<T>(arr: T[], startOfWeek: number): T[];
|
|
29
29
|
export declare function getWeekStartsOn(locale: Locale | undefined): number;
|
|
30
30
|
export declare function getDayNumInWeek(locale: Locale | undefined, day: number): number;
|
|
31
|
+
export declare function getDefaultScrollDate({ minDate, maxDate, parseDateInput, }: Pick<DatePopupBaseProps, 'minDate' | 'maxDate' | 'parseDateInput'>): Date;
|
|
31
32
|
export interface DateInputTranslations {
|
|
32
33
|
addFirstDate?: string;
|
|
33
34
|
addSecondDate?: string;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { add } from 'date-fns/add';
|
|
2
|
+
import { endOfDay } from 'date-fns';
|
|
2
3
|
import sniffer from '../global/sniffer';
|
|
3
4
|
const unit = 8; // px;
|
|
4
5
|
const units = {
|
|
@@ -29,14 +30,15 @@ export const yearScrollSpeed = yearDuration / (YEAR * units.cellSize);
|
|
|
29
30
|
export const DOUBLE = 2;
|
|
30
31
|
export const HALF = 0.5;
|
|
31
32
|
export function parseTime(time) {
|
|
32
|
-
|
|
33
|
+
if (!time)
|
|
34
|
+
return null;
|
|
33
35
|
if (/^([01][0-9]|2[0-3]):[0-5][0-9]$/.test(time)) {
|
|
34
|
-
|
|
36
|
+
return time;
|
|
35
37
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
+
if (/^([0-9]|2[0-3]):[0-5][0-9]$/.test(time)) {
|
|
39
|
+
return `0${time}`;
|
|
38
40
|
}
|
|
39
|
-
return
|
|
41
|
+
return null;
|
|
40
42
|
}
|
|
41
43
|
export function shiftWeekArray(arr, startOfWeek) {
|
|
42
44
|
const shiftTimes = startOfWeek - 1;
|
|
@@ -49,6 +51,25 @@ export function getDayNumInWeek(locale, day) {
|
|
|
49
51
|
const weekDays = shiftWeekArray(Object.values(weekdays), getWeekStartsOn(locale));
|
|
50
52
|
return weekDays.indexOf(day);
|
|
51
53
|
}
|
|
54
|
+
export function getDefaultScrollDate({ minDate, maxDate, parseDateInput, }) {
|
|
55
|
+
const minDateParsed = parseDateInput(minDate);
|
|
56
|
+
const maxDateParsed = parseDateInput(maxDate);
|
|
57
|
+
const maxDateEndOfDayNum = maxDateParsed ? Number(endOfDay(maxDateParsed)) : null;
|
|
58
|
+
const now = Date.now();
|
|
59
|
+
if (minDateParsed != null && maxDateEndOfDayNum != null) {
|
|
60
|
+
if (minDateParsed.getTime() <= now && now <= maxDateEndOfDayNum) {
|
|
61
|
+
return new Date(now);
|
|
62
|
+
}
|
|
63
|
+
return minDateParsed;
|
|
64
|
+
}
|
|
65
|
+
if (minDateParsed != null && minDateParsed.getTime() > now) {
|
|
66
|
+
return minDateParsed;
|
|
67
|
+
}
|
|
68
|
+
if (maxDateParsed != null && maxDateEndOfDayNum != null && maxDateEndOfDayNum < now) {
|
|
69
|
+
return maxDateParsed;
|
|
70
|
+
}
|
|
71
|
+
return new Date(now);
|
|
72
|
+
}
|
|
52
73
|
/**
|
|
53
74
|
* Safari on iPhone doesn't allow setting scrollTop while a scroll is in progress.
|
|
54
75
|
* If you do, the browser will overwrite it during the next scroll event.
|
|
@@ -97,8 +97,16 @@ export default class DatePicker extends PureComponent {
|
|
|
97
97
|
static contextType = I18nContext;
|
|
98
98
|
handleChange = (change) => {
|
|
99
99
|
const { onChange, withTime, applyTimeInput } = this.props;
|
|
100
|
-
|
|
101
|
-
|
|
100
|
+
if (withTime && !(change instanceof Date) && change && 'date' in change && 'time' in change) {
|
|
101
|
+
const { date, time } = change;
|
|
102
|
+
if (date) {
|
|
103
|
+
const dateWithTime = applyTimeInput(date, time);
|
|
104
|
+
onChange(dateWithTime);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
onChange(change);
|
|
109
|
+
}
|
|
102
110
|
};
|
|
103
111
|
clear = () => {
|
|
104
112
|
let change = null;
|
|
@@ -116,14 +124,18 @@ export default class DatePicker extends PureComponent {
|
|
|
116
124
|
this.popup?._onCloseAttempt();
|
|
117
125
|
};
|
|
118
126
|
parse = memoize((date) => {
|
|
119
|
-
|
|
127
|
+
let normalizedDate;
|
|
120
128
|
if (date instanceof Date) {
|
|
121
|
-
|
|
129
|
+
normalizedDate = date;
|
|
130
|
+
}
|
|
131
|
+
else if (typeof date === 'number') {
|
|
132
|
+
normalizedDate = new Date(date);
|
|
122
133
|
}
|
|
123
|
-
|
|
124
|
-
|
|
134
|
+
else {
|
|
135
|
+
const { parseDateInput } = this.props;
|
|
136
|
+
normalizedDate = parseDateInput(date);
|
|
125
137
|
}
|
|
126
|
-
return
|
|
138
|
+
return normalizedDate && isValid(normalizedDate) ? normalizedDate : null;
|
|
127
139
|
});
|
|
128
140
|
formatTime() {
|
|
129
141
|
const { displayTimeFormat, locale } = this.props;
|
|
@@ -7,13 +7,11 @@ export default class DatePopup extends Component<DatePopupProps, DatePopupState>
|
|
|
7
7
|
onChange(): void;
|
|
8
8
|
};
|
|
9
9
|
constructor(props: DatePopupProps);
|
|
10
|
-
componentDidUpdate(
|
|
10
|
+
componentDidUpdate(_prevProps: DatePopupBaseProps, prevState: DatePopupState): void;
|
|
11
11
|
componentWillUnmount(): void;
|
|
12
12
|
private animationCleanup;
|
|
13
13
|
isInTimeMode: () => boolean;
|
|
14
14
|
componentRef: React.RefObject<HTMLDivElement | null>;
|
|
15
|
-
parse(text: string | null | undefined, type: 'time'): string;
|
|
16
|
-
parse(text: Date | number | string | null | undefined, type?: 'date' | 'from' | 'to'): Date;
|
|
17
15
|
select(changes: DatePickerChange): void;
|
|
18
16
|
confirm(name: Field): void;
|
|
19
17
|
isValidDate: (parsedText: Date) => boolean;
|
|
@@ -9,7 +9,7 @@ import DateInput from './date-input';
|
|
|
9
9
|
import Months from './months';
|
|
10
10
|
import Years from './years';
|
|
11
11
|
import Weekdays from './weekdays';
|
|
12
|
-
import { parseTime, } from './consts';
|
|
12
|
+
import { parseTime, getDefaultScrollDate, } from './consts';
|
|
13
13
|
import { animateDate } from './animate-date';
|
|
14
14
|
import MonthNames from './month-names';
|
|
15
15
|
import styles from './date-picker.css';
|
|
@@ -24,21 +24,25 @@ export default class DatePopup extends Component {
|
|
|
24
24
|
hoverDate: null,
|
|
25
25
|
scrollDate: null,
|
|
26
26
|
};
|
|
27
|
-
const { range, withTime } = props;
|
|
27
|
+
const { range, withTime, parseDateInput } = props;
|
|
28
28
|
if (!range) {
|
|
29
|
-
const parsedDate =
|
|
29
|
+
const parsedDate = parseDateInput(props.date);
|
|
30
30
|
const active = withTime && parsedDate && !props.time ? 'time' : 'date';
|
|
31
|
-
this.state = {
|
|
31
|
+
this.state = {
|
|
32
|
+
...defaultState,
|
|
33
|
+
active,
|
|
34
|
+
scrollDate: { date: parsedDate ?? getDefaultScrollDate(props), source: 'other' },
|
|
35
|
+
};
|
|
32
36
|
}
|
|
33
37
|
else {
|
|
34
38
|
this.state = {
|
|
35
39
|
...defaultState,
|
|
36
40
|
active: props.from && !props.to ? 'to' : 'from',
|
|
37
|
-
scrollDate: { date:
|
|
41
|
+
scrollDate: { date: parseDateInput(props.from) ?? getDefaultScrollDate(props), source: 'other' },
|
|
38
42
|
};
|
|
39
43
|
}
|
|
40
44
|
}
|
|
41
|
-
componentDidUpdate(
|
|
45
|
+
componentDidUpdate(_prevProps, prevState) {
|
|
42
46
|
if (this.state.active !== prevState.active) {
|
|
43
47
|
if (this.state.text && prevState.active) {
|
|
44
48
|
this.confirm(prevState.active);
|
|
@@ -52,14 +56,8 @@ export default class DatePopup extends Component {
|
|
|
52
56
|
animationCleanup = null;
|
|
53
57
|
isInTimeMode = () => (!this.props.range && this.props.withTime) || false;
|
|
54
58
|
componentRef = React.createRef();
|
|
55
|
-
parse(text, type) {
|
|
56
|
-
if (type === 'time') {
|
|
57
|
-
return parseTime(String(text));
|
|
58
|
-
}
|
|
59
|
-
return this.props.parseDateInput(text);
|
|
60
|
-
}
|
|
61
59
|
select(changes) {
|
|
62
|
-
const { range, withTime } = this.props;
|
|
60
|
+
const { range, withTime, parseDateInput } = this.props;
|
|
63
61
|
const prevActive = this.state.active;
|
|
64
62
|
if (!range && !withTime) {
|
|
65
63
|
this.setState({
|
|
@@ -76,8 +74,8 @@ export default class DatePopup extends Component {
|
|
|
76
74
|
this.props.onComplete();
|
|
77
75
|
}
|
|
78
76
|
else if (!range && withTime) {
|
|
79
|
-
const date =
|
|
80
|
-
const time =
|
|
77
|
+
const date = parseDateInput(this.props.date);
|
|
78
|
+
const time = parseTime(this.props.time);
|
|
81
79
|
const changeToSubmit = {
|
|
82
80
|
date: changes.date || date,
|
|
83
81
|
time: changes.time || time,
|
|
@@ -97,8 +95,8 @@ export default class DatePopup extends Component {
|
|
|
97
95
|
...this.props,
|
|
98
96
|
...changes,
|
|
99
97
|
};
|
|
100
|
-
from =
|
|
101
|
-
to =
|
|
98
|
+
from = parseDateInput(from);
|
|
99
|
+
to = parseDateInput(to);
|
|
102
100
|
// proceed to setting the end by default
|
|
103
101
|
let active = 'to';
|
|
104
102
|
let complete = false;
|
|
@@ -133,15 +131,16 @@ export default class DatePopup extends Component {
|
|
|
133
131
|
const text = this.state.text;
|
|
134
132
|
let result;
|
|
135
133
|
if (name === 'time') {
|
|
136
|
-
result =
|
|
137
|
-
const time =
|
|
134
|
+
result = parseTime(text);
|
|
135
|
+
const time = parseTime('time' in this.props ? this.props.time : '');
|
|
138
136
|
const emptyCase = this.state.active === 'time' ? '00:00' : null;
|
|
139
137
|
result = result || time || emptyCase;
|
|
140
138
|
}
|
|
141
139
|
else {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
140
|
+
const { parseDateInput } = this.props;
|
|
141
|
+
result = parseDateInput(text);
|
|
142
|
+
if (!result || !this.isValidDate(result)) {
|
|
143
|
+
result = parseDateInput(name in this.props ? this.props[name] : '');
|
|
145
144
|
}
|
|
146
145
|
}
|
|
147
146
|
this.select({
|
|
@@ -149,10 +148,12 @@ export default class DatePopup extends Component {
|
|
|
149
148
|
});
|
|
150
149
|
}
|
|
151
150
|
isValidDate = (parsedText) => {
|
|
152
|
-
const minDate = this.
|
|
153
|
-
const
|
|
151
|
+
const { parseDateInput, minDate, maxDate } = this.props;
|
|
152
|
+
const parsedMinDate = parseDateInput(minDate);
|
|
153
|
+
const parsedMaxDate = parseDateInput(maxDate);
|
|
154
154
|
if (parsedText) {
|
|
155
|
-
return !((
|
|
155
|
+
return !((parsedMinDate && isBefore(parsedText, parsedMinDate)) ||
|
|
156
|
+
(parsedMaxDate && isAfter(parsedText, parsedMaxDate)));
|
|
156
157
|
}
|
|
157
158
|
return false;
|
|
158
159
|
};
|
|
@@ -160,8 +161,8 @@ export default class DatePopup extends Component {
|
|
|
160
161
|
handleActivate = memoize((name) => () => this.setState({ active: name }));
|
|
161
162
|
handleInput = (text, name) => {
|
|
162
163
|
if (name !== 'time') {
|
|
163
|
-
const parsed = this.
|
|
164
|
-
if (this.isValidDate(parsed)) {
|
|
164
|
+
const parsed = this.props.parseDateInput(text);
|
|
165
|
+
if (parsed && this.isValidDate(parsed)) {
|
|
165
166
|
this.animationCleanup?.();
|
|
166
167
|
const currentScrollDate = this.state.scrollDate?.date;
|
|
167
168
|
if (currentScrollDate != null) {
|
|
@@ -217,20 +218,20 @@ export default class DatePopup extends Component {
|
|
|
217
218
|
};
|
|
218
219
|
// eslint-disable-next-line complexity
|
|
219
220
|
render() {
|
|
220
|
-
const { range, locale } = this.props;
|
|
221
|
+
const { range, locale, parseDateInput } = this.props;
|
|
221
222
|
const { from, to, date, time, ...restProps } = this.props;
|
|
222
|
-
const parsedDate =
|
|
223
|
-
const parsedTo =
|
|
223
|
+
const parsedDate = parseDateInput(date);
|
|
224
|
+
const parsedTo = parseDateInput(to);
|
|
224
225
|
const names = range ? ['from', 'to'] : ['date'];
|
|
225
226
|
const dates = names.reduce((obj, key) => {
|
|
226
227
|
const value = this.props[key];
|
|
227
228
|
return {
|
|
228
229
|
...obj,
|
|
229
|
-
[key]:
|
|
230
|
+
[key]: parseDateInput(value),
|
|
230
231
|
};
|
|
231
232
|
}, {});
|
|
232
233
|
const activeDate = this.state.active !== 'time'
|
|
233
|
-
? this.state.hoverDate || (this.state.text ?
|
|
234
|
+
? this.state.hoverDate || (this.state.text ? parseDateInput(this.state.text) : null)
|
|
234
235
|
: this.state.hoverDate || null;
|
|
235
236
|
const currentRange = (range && dates.from && dates.to && [dates.from, dates.to]) || null;
|
|
236
237
|
let activeRange = null;
|