@jetbrains/ring-ui 7.0.112 → 7.0.114
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.
|
|
@@ -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;
|
|
@@ -51,11 +51,11 @@ export const setCSSAnchorPositioning = ({ popup, anchor, uid, minWidth, top, lef
|
|
|
51
51
|
if (calculatedMinWidth !== null) {
|
|
52
52
|
popup.style.minWidth = `${calculatedMinWidth}px`;
|
|
53
53
|
}
|
|
54
|
-
if (top) {
|
|
55
|
-
popup.style.transform = `translateY(${top}px)
|
|
54
|
+
if (top || left) {
|
|
55
|
+
popup.style.transform = [top && `translateY(${top}px)`, left && `translateX(${left}px)`].filter(Boolean).join(' ');
|
|
56
56
|
}
|
|
57
|
-
|
|
58
|
-
popup.style.
|
|
57
|
+
else {
|
|
58
|
+
popup.style.removeProperty('transform');
|
|
59
59
|
}
|
|
60
60
|
// When all directions are BOTTOM, the `max-height: 100%` from CSS should stay applied so popup doesn't overflow the anchor RG-2754
|
|
61
61
|
const SHOULD_AUTO_SHRINK = directions.every(d => d.startsWith('BOTTOM'));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jetbrains/ring-ui",
|
|
3
|
-
"version": "7.0.
|
|
3
|
+
"version": "7.0.114",
|
|
4
4
|
"description": "JetBrains UI library",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "JetBrains"
|
|
@@ -112,16 +112,16 @@
|
|
|
112
112
|
"@jetbrains/rollup-css-plugin": "./packages/rollup-css-plugin",
|
|
113
113
|
"@jetbrains/stylelint-config": "^4.0.2",
|
|
114
114
|
"@jetbrains/typescript-plugin-css-modules": "^5.3.1",
|
|
115
|
-
"@primer/octicons": "^19.
|
|
115
|
+
"@primer/octicons": "^19.27.0",
|
|
116
116
|
"@rollup/plugin-babel": "^7.0.0",
|
|
117
117
|
"@rollup/plugin-json": "^6.1.0",
|
|
118
118
|
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
119
119
|
"@rollup/plugin-replace": "^6.0.3",
|
|
120
|
-
"@storybook/addon-a11y": "10.4.
|
|
121
|
-
"@storybook/addon-docs": "^10.4.
|
|
122
|
-
"@storybook/addon-themes": "^10.4.
|
|
120
|
+
"@storybook/addon-a11y": "10.4.1",
|
|
121
|
+
"@storybook/addon-docs": "^10.4.1",
|
|
122
|
+
"@storybook/addon-themes": "^10.4.1",
|
|
123
123
|
"@storybook/csf": "^0.1.13",
|
|
124
|
-
"@storybook/react-webpack5": "10.4.
|
|
124
|
+
"@storybook/react-webpack5": "10.4.1",
|
|
125
125
|
"@storybook/test-runner": "^0.24.4",
|
|
126
126
|
"@testing-library/dom": "^10.4.1",
|
|
127
127
|
"@testing-library/react": "^16.3.2",
|
|
@@ -129,14 +129,14 @@
|
|
|
129
129
|
"@types/chai-as-promised": "^8.0.2",
|
|
130
130
|
"@types/chai-dom": "1.11.3",
|
|
131
131
|
"@types/markdown-it": "^14.1.2",
|
|
132
|
-
"@types/react": "^19.2.
|
|
132
|
+
"@types/react": "^19.2.15",
|
|
133
133
|
"@types/react-dom": "^19.2.3",
|
|
134
134
|
"@types/webpack-env": "^1.18.8",
|
|
135
135
|
"@vitejs/plugin-react": "^6.0.2",
|
|
136
136
|
"@vitest/eslint-plugin": "^1.6.17",
|
|
137
137
|
"acorn": "^8.16.0",
|
|
138
138
|
"babel-plugin-require-context-hook": "^1.0.0",
|
|
139
|
-
"caniuse-lite": "^1.0.
|
|
139
|
+
"caniuse-lite": "^1.0.30001793",
|
|
140
140
|
"chai-as-promised": "^8.0.2",
|
|
141
141
|
"chai-dom": "^1.12.1",
|
|
142
142
|
"cheerio": "^1.2.0",
|
|
@@ -154,7 +154,7 @@
|
|
|
154
154
|
"eslint-plugin-prettier": "^5.5.5",
|
|
155
155
|
"eslint-plugin-react": "^7.37.5",
|
|
156
156
|
"eslint-plugin-react-hooks": "^7.1.1",
|
|
157
|
-
"eslint-plugin-storybook": "^10.4.
|
|
157
|
+
"eslint-plugin-storybook": "^10.4.1",
|
|
158
158
|
"eslint-plugin-unicorn": "^64.0.0",
|
|
159
159
|
"events": "^3.3.0",
|
|
160
160
|
"glob": "^13.0.6",
|
|
@@ -167,7 +167,7 @@
|
|
|
167
167
|
"jest-environment-jsdom": "^30.4.1",
|
|
168
168
|
"jest-teamcity": "^1.12.0",
|
|
169
169
|
"lint-staged": "^17.0.5",
|
|
170
|
-
"markdown-it": "^14.
|
|
170
|
+
"markdown-it": "^14.2.0",
|
|
171
171
|
"merge-options": "^3.0.4",
|
|
172
172
|
"pinst": "^3.0.0",
|
|
173
173
|
"prettier": "^3.8.3",
|
|
@@ -180,18 +180,18 @@
|
|
|
180
180
|
"rollup-plugin-clear": "^2.0.7",
|
|
181
181
|
"storage-mock": "^2.1.0",
|
|
182
182
|
"storybook": "10.4.1",
|
|
183
|
-
"stylelint": "^17.
|
|
183
|
+
"stylelint": "^17.12.0",
|
|
184
184
|
"stylelint-config-sass-guidelines": "^13.0.0",
|
|
185
185
|
"svg-inline-loader": "^0.8.2",
|
|
186
186
|
"teamcity-service-messages": "^0.1.14",
|
|
187
187
|
"terser-webpack-plugin": "^5.6.0",
|
|
188
188
|
"typed-css-modules": "^0.9.1",
|
|
189
189
|
"typescript": "~6.0.3",
|
|
190
|
-
"typescript-eslint": "^8.
|
|
191
|
-
"vite": "^8.0.
|
|
192
|
-
"vitest": "^4.1.
|
|
190
|
+
"typescript-eslint": "^8.60.0",
|
|
191
|
+
"vite": "^8.0.14",
|
|
192
|
+
"vitest": "^4.1.7",
|
|
193
193
|
"vitest-teamcity-reporter": "^0.4.1",
|
|
194
|
-
"webpack": "^5.
|
|
194
|
+
"webpack": "^5.107.1",
|
|
195
195
|
"webpack-cli": "^7.0.2",
|
|
196
196
|
"xmlappend": "^1.0.4"
|
|
197
197
|
},
|
|
@@ -233,7 +233,7 @@
|
|
|
233
233
|
"combokeys": "^3.0.1",
|
|
234
234
|
"css-loader": "^7.1.4",
|
|
235
235
|
"csstype": "^3.2.1",
|
|
236
|
-
"date-fns": "^4.
|
|
236
|
+
"date-fns": "^4.3.0",
|
|
237
237
|
"dequal": "^2.0.3",
|
|
238
238
|
"element-resize-detector": "^1.2.4",
|
|
239
239
|
"fastdom": "^1.0.12",
|
|
@@ -242,7 +242,7 @@
|
|
|
242
242
|
"highlight.js": "^10.7.2",
|
|
243
243
|
"just-debounce-it": "^3.2.0",
|
|
244
244
|
"memoize-one": "^6.0.0",
|
|
245
|
-
"postcss": "^8.5.
|
|
245
|
+
"postcss": "^8.5.15",
|
|
246
246
|
"postcss-calc": "^10.1.1",
|
|
247
247
|
"postcss-font-family-system-ui": "^5.0.0",
|
|
248
248
|
"postcss-loader": "^8.2.1",
|