@erxes/ui 3.2.19-2 → 3.2.20-1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@erxes/ui",
3
- "version": "3.2.19-2",
3
+ "version": "3.2.20-1",
4
4
  "description": "erxes design system: UI primitives, business modules, hooks and shared frontend state",
5
5
  "license": "AGPL-3.0-only",
6
6
  "repository": {
@@ -88,39 +88,58 @@ const getAnchorDate = (value: NormalizedValue) => {
88
88
  const defaultFormatMultiple = (count: number) =>
89
89
  `${count} ${count > 1 ? 'Days' : 'Day'}`;
90
90
 
91
- const formatDateMask = (value: string) => {
92
- const digits = value.replace(/\D/g, '').slice(0, 8);
91
+ const DATE_SEGMENT_LENGTHS = [4, 2, 2];
92
+ const DATE_SEPARATOR = /[-./]/;
93
+ const LOOSE_INPUT_FORMATS = [
94
+ DEFAULT_FORMAT,
95
+ 'YYYY-M-D',
96
+ 'YYYY-MM-D',
97
+ 'YYYY-M-DD',
98
+ ];
99
+
100
+ const splitDateSegments = (value: string) => {
101
+ const segments = [''];
93
102
 
94
- if (digits.length <= 4) {
95
- return digits;
103
+ for (const char of value) {
104
+ const index = segments.length - 1;
105
+ const isLastSegment = index === DATE_SEGMENT_LENGTHS.length - 1;
106
+
107
+ if (DATE_SEPARATOR.test(char)) {
108
+ if (segments[index] && !isLastSegment) segments.push('');
109
+ } else if (/\d/.test(char)) {
110
+ if (segments[index].length < DATE_SEGMENT_LENGTHS[index]) {
111
+ segments[index] += char;
112
+ } else if (!isLastSegment) {
113
+ segments.push(char);
114
+ }
115
+ }
96
116
  }
97
117
 
98
- const year = digits.slice(0, 4);
99
- const month = digits.slice(4, 6);
118
+ return segments;
119
+ };
120
+
121
+ const formatDateMask = (value: string) => {
122
+ const [year, month, day] = splitDateSegments(value);
100
123
 
101
124
  const normalizedMonth =
102
- month.length === 2
125
+ month?.length === 2
103
126
  ? String(Math.min(Number(month), 12)).padStart(2, '0')
104
127
  : month;
105
128
 
106
- if (digits.length <= 6) {
107
- return `${year}-${normalizedMonth}`;
108
- }
109
-
110
- const day = digits.slice(6, 8);
111
-
112
129
  const maxDay = dayjs(
113
- `${year}-${normalizedMonth}-01`,
114
- 'YYYY-MM-DD',
130
+ `${year}-${normalizedMonth?.padStart(2, '0')}-01`,
131
+ DEFAULT_FORMAT,
115
132
  true,
116
133
  ).daysInMonth();
117
134
 
118
135
  const normalizedDay =
119
- day.length === 2
136
+ day?.length === 2 && maxDay
120
137
  ? String(Math.min(Number(day), maxDay)).padStart(2, '0')
121
138
  : day;
122
139
 
123
- return `${year}-${normalizedMonth}-${normalizedDay}`;
140
+ return [year, normalizedMonth, normalizedDay]
141
+ .filter((segment) => segment !== undefined)
142
+ .join('-');
124
143
  };
125
144
 
126
145
  const isWithinBounds = (date: dayjs.Dayjs, minBound?: Date, maxBound?: Date) =>
@@ -155,9 +174,12 @@ const getCalendarDisabled = (
155
174
  ...(maxBound ? [{ after: maxBound }] : []),
156
175
  ];
157
176
 
177
+ const getInputFormats = (format: string) =>
178
+ format === DEFAULT_FORMAT ? LOOSE_INPUT_FORMATS : [format];
179
+
158
180
  const parseInputDate = (
159
181
  text: string,
160
- format: string,
182
+ format: string | string[],
161
183
  minBound?: Date,
162
184
  maxBound?: Date,
163
185
  ) => {
@@ -230,13 +252,30 @@ export const DatePicker = ({
230
252
  }
231
253
  };
232
254
 
255
+ const parseTypedDate = () => {
256
+ if (mode !== 'single' || !inputValue) return undefined;
257
+ const parsedDate = parseInputDate(
258
+ inputValue,
259
+ getInputFormats(format),
260
+ minBound,
261
+ maxBound,
262
+ );
263
+ return parsedDate && !dateMatchModifiers(parsedDate, calendarDisabled)
264
+ ? parsedDate
265
+ : undefined;
266
+ };
267
+
268
+ const commitTypedDate = (date: Date) => {
269
+ setInputValue(dayjs(date).format(format));
270
+ if (date.getTime() !== singleTime) onChange(date);
271
+ };
272
+
233
273
  const handleInputBlur = () => {
234
274
  setIsFocused(false);
235
- const parsedDate = dayjs(inputValue, format, true);
236
- if (
237
- !isWithinBounds(parsedDate, minBound, maxBound) ||
238
- dateMatchModifiers(parsedDate.toDate(), calendarDisabled)
239
- ) {
275
+ const parsedDate = parseTypedDate();
276
+ if (parsedDate) {
277
+ commitTypedDate(parsedDate);
278
+ } else {
240
279
  setInputValue(formatSingle());
241
280
  }
242
281
  };
@@ -273,6 +312,11 @@ export const DatePicker = ({
273
312
  if (!opensPopover && e.key !== 'Enter') return;
274
313
  e.preventDefault();
275
314
  e.stopPropagation();
315
+ const typedDate = e.key === 'Enter' ? parseTypedDate() : undefined;
316
+ if (typedDate && typedDate.getTime() !== singleTime) {
317
+ commitTypedDate(typedDate);
318
+ return;
319
+ }
276
320
  if (opensPopover) setIsOpen(true);
277
321
  };
278
322