@bigbinary/neeto-atoms 1.0.56 → 1.0.58
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/{DatePicker-D-0HMiNG.js → DatePicker-kulToqfM.js} +390 -133
- package/dist/DatePicker-kulToqfM.js.map +1 -0
- package/dist/Select-BiyQTuiQ.js.map +1 -1
- package/dist/TimePicker-DoL126Ql.js +444 -0
- package/dist/TimePicker-DoL126Ql.js.map +1 -0
- package/dist/{TimePickerPanel-zWmOy3Eo.js → TimePickerPanel--KDX5QwS.js} +116 -3
- package/dist/TimePickerPanel--KDX5QwS.js.map +1 -0
- package/dist/cjs/{DatePicker-JhQ7D2bu.js → DatePicker-BZd4rM2R.js} +388 -131
- package/dist/cjs/DatePicker-BZd4rM2R.js.map +1 -0
- package/dist/cjs/Select-DC23xcMU.js.map +1 -1
- package/dist/cjs/TimePicker-H3OpzvOm.js +446 -0
- package/dist/cjs/TimePicker-H3OpzvOm.js.map +1 -0
- package/dist/cjs/{TimePickerPanel-B5h5khbs.js → TimePickerPanel-DX6cjrSN.js} +130 -2
- package/dist/cjs/TimePickerPanel-DX6cjrSN.js.map +1 -0
- package/dist/cjs/components/DatePicker.js +5 -5
- package/dist/cjs/components/TimePicker.js +4 -2
- package/dist/cjs/components/TimePicker.js.map +1 -1
- package/dist/cjs/components/index.js +3 -3
- package/dist/cjs/formik/BlockNavigation.js.map +1 -1
- package/dist/cjs/index.js +5 -5
- package/dist/components/DatePicker/MonthPicker.d.ts +16 -0
- package/dist/components/DatePicker/YearPicker.d.ts +14 -0
- package/dist/components/DatePicker/constants.d.ts +2 -0
- package/dist/components/DatePicker/types.d.ts +21 -1
- package/dist/components/DatePicker/utils.d.ts +8 -0
- package/dist/components/DatePicker.js +5 -5
- package/dist/components/TimePicker/constants.d.ts +17 -0
- package/dist/components/TimePicker/index.d.ts +1 -1
- package/dist/components/TimePicker/types.d.ts +19 -4
- package/dist/components/TimePicker/utils.d.ts +13 -0
- package/dist/components/TimePicker.js +4 -2
- package/dist/components/TimePicker.js.map +1 -1
- package/dist/components/index.js +3 -3
- package/dist/formik/BlockNavigation.js.map +1 -1
- package/dist/hooks/useControlledOpen.d.ts +5 -0
- package/dist/hooks/useCursorRestore.d.ts +8 -0
- package/dist/hooks/useOutsideClickClose.d.ts +8 -0
- package/dist/index.js +5 -5
- package/package.json +1 -1
- package/dist/DatePicker-D-0HMiNG.js.map +0 -1
- package/dist/TimePicker-CSjiggpr.js +0 -301
- package/dist/TimePicker-CSjiggpr.js.map +0 -1
- package/dist/TimePickerPanel-zWmOy3Eo.js.map +0 -1
- package/dist/cjs/DatePicker-JhQ7D2bu.js.map +0 -1
- package/dist/cjs/TimePicker-CU7qJpoT.js +0 -303
- package/dist/cjs/TimePicker-CU7qJpoT.js.map +0 -1
- package/dist/cjs/TimePickerPanel-B5h5khbs.js.map +0 -1
- /package/dist/{hooks → components/Select/hooks}/useAsyncOptions.d.ts +0 -0
- /package/dist/{hooks → components/Select/hooks}/useCreatableItems.d.ts +0 -0
- /package/dist/{hooks → components/Select/hooks}/useLazyLoadSentinel.d.ts +0 -0
- /package/dist/{hooks → components/Select/hooks}/useMultiSelectOptions.d.ts +0 -0
- /package/dist/{hooks → components/Select/hooks}/useMultiSelectState.d.ts +0 -0
- /package/dist/{hooks → components/Select/hooks}/useSelectState.d.ts +0 -0
- /package/dist/{hooks → formik/BlockNavigation/hooks}/useNavPrompt.d.ts +0 -0
|
@@ -6,11 +6,13 @@ var primitives_Calendar = require('./primitives/Calendar.js');
|
|
|
6
6
|
var primitives_Popover = require('./primitives/Popover.js');
|
|
7
7
|
var primitives_Field = require('./primitives/Field.js');
|
|
8
8
|
var utils$1 = require('./utils-BhM0B89p.js');
|
|
9
|
+
var TimePickerPanel = require('./TimePickerPanel-DX6cjrSN.js');
|
|
9
10
|
var pureDayjs = require('dayjs');
|
|
10
11
|
var customParseFormat = require('dayjs/plugin/customParseFormat');
|
|
11
12
|
var utils = require('@bigbinary/neeto-commons-frontend/utils');
|
|
12
|
-
var TimePickerPanel = require('./TimePickerPanel-B5h5khbs.js');
|
|
13
13
|
var primitives_Button = require('./primitives/Button.js');
|
|
14
|
+
var chevronLeft = require('./chevron-left-BldoOh5p.js');
|
|
15
|
+
var chevronRight = require('./chevron-right-0jNdwX2Q.js');
|
|
14
16
|
var createLucideIcon = require('./createLucideIcon-D0tRgV6l.js');
|
|
15
17
|
var x = require('./x-Brw3FJst.js');
|
|
16
18
|
|
|
@@ -37,6 +39,11 @@ const Calendar = createLucideIcon.createLucideIcon("calendar", __iconNode);
|
|
|
37
39
|
|
|
38
40
|
const DEFAULT_DATE_FORMAT = "dd/MM/yyyy";
|
|
39
41
|
const DEFAULT_TIME_FORMAT = "HH:mm:ss";
|
|
42
|
+
const INITIAL_TIME_VALUE = {
|
|
43
|
+
hours: 0,
|
|
44
|
+
minutes: 0,
|
|
45
|
+
seconds: 0
|
|
46
|
+
};
|
|
40
47
|
const SIZE_CONFIG = {
|
|
41
48
|
small: {
|
|
42
49
|
trigger: "h-8 md:h-7",
|
|
@@ -130,6 +137,10 @@ const getDisplayFormat = (dateFormat, timeFormat, showTime) => {
|
|
|
130
137
|
const fmt = showTime ? `${dateFormat} ${timeFormat}` : dateFormat;
|
|
131
138
|
return normalizeToDateFnsFormat(fmt);
|
|
132
139
|
};
|
|
140
|
+
const getDatePlaceholder = (dateFormat, timeFormat, showTime, type) => {
|
|
141
|
+
const single = showTime ? `${dateFormat.toUpperCase()} ${timeFormat}` : dateFormat.toUpperCase();
|
|
142
|
+
return type === "range" ? `${single} - ${single}` : single;
|
|
143
|
+
};
|
|
133
144
|
const isDatePartComplete = (part, maskEnabled, singleDateLen) => maskEnabled ? part.length >= singleDateLen : part.length > 0;
|
|
134
145
|
const parseRangeText = (text, displayFormat, maskEnabled, singleDateLen) => {
|
|
135
146
|
const parts = text.split(" - ");
|
|
@@ -140,6 +151,43 @@ const parseRangeText = (text, displayFormat, maskEnabled, singleDateLen) => {
|
|
|
140
151
|
const to = parseDate(parts[1], displayFormat);
|
|
141
152
|
return from && to ? [from, to] : null;
|
|
142
153
|
};
|
|
154
|
+
const startOfWeek = (date, weekStartsOn = 0) => {
|
|
155
|
+
const d = new Date(date);
|
|
156
|
+
const diff = (d.getDay() - weekStartsOn + 7) % 7;
|
|
157
|
+
d.setDate(d.getDate() - diff);
|
|
158
|
+
d.setHours(0, 0, 0, 0);
|
|
159
|
+
return d;
|
|
160
|
+
};
|
|
161
|
+
const weekDaysFrom = (start) => Array.from({ length: 7 }, (_, i) => {
|
|
162
|
+
const d = new Date(start);
|
|
163
|
+
d.setDate(start.getDate() + i);
|
|
164
|
+
return d;
|
|
165
|
+
});
|
|
166
|
+
const isMonthDisabled = (monthDate, minDate, maxDate) => {
|
|
167
|
+
const monthStart = new Date(monthDate.getFullYear(), monthDate.getMonth(), 1);
|
|
168
|
+
const monthEnd = new Date(
|
|
169
|
+
monthDate.getFullYear(),
|
|
170
|
+
monthDate.getMonth() + 1,
|
|
171
|
+
0,
|
|
172
|
+
23,
|
|
173
|
+
59,
|
|
174
|
+
59,
|
|
175
|
+
999
|
|
176
|
+
);
|
|
177
|
+
if (maxDate && monthStart > maxDate) return true;
|
|
178
|
+
if (minDate && monthEnd < minDate) return true;
|
|
179
|
+
return false;
|
|
180
|
+
};
|
|
181
|
+
const isYearDisabled = (yearDate, minDate, maxDate) => {
|
|
182
|
+
const yearStart = new Date(yearDate.getFullYear(), 0, 1);
|
|
183
|
+
const yearEnd = new Date(yearDate.getFullYear(), 11, 31, 23, 59, 59, 999);
|
|
184
|
+
if (maxDate && yearStart > maxDate) return true;
|
|
185
|
+
if (minDate && yearEnd < minDate) return true;
|
|
186
|
+
return false;
|
|
187
|
+
};
|
|
188
|
+
const buildMonth = (year, month) => new Date(year, month, 1);
|
|
189
|
+
const isSameMonth = (a, b) => !!a && a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth();
|
|
190
|
+
const decadeStartFor = (year) => Math.floor(year / 10) * 10;
|
|
143
191
|
|
|
144
192
|
const TIMEZONE_OPTIONS = [
|
|
145
193
|
{ label: "Local", value: "" },
|
|
@@ -202,11 +250,136 @@ const DatePickerFooter = ({
|
|
|
202
250
|
};
|
|
203
251
|
DatePickerFooter.displayName = "DatePickerFooter";
|
|
204
252
|
|
|
253
|
+
const MonthPicker = ({
|
|
254
|
+
value,
|
|
255
|
+
displayedYear,
|
|
256
|
+
onYearChange,
|
|
257
|
+
onSelect,
|
|
258
|
+
isDisabled,
|
|
259
|
+
locale
|
|
260
|
+
}) => {
|
|
261
|
+
const months = Array.from(
|
|
262
|
+
{ length: 12 },
|
|
263
|
+
(_, m) => buildMonth(displayedYear, m)
|
|
264
|
+
);
|
|
265
|
+
const monthName = (date) => date.toLocaleString(locale, { month: "short" });
|
|
266
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-background flex w-[16rem] flex-col gap-3 p-2", children: [
|
|
267
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
268
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
269
|
+
primitives_Button.Button,
|
|
270
|
+
{
|
|
271
|
+
"aria-label": "Previous year",
|
|
272
|
+
size: "icon",
|
|
273
|
+
variant: "ghost",
|
|
274
|
+
onClick: () => onYearChange(displayedYear - 1),
|
|
275
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(chevronLeft.ChevronLeft, { className: "size-4 rtl:rotate-180" })
|
|
276
|
+
}
|
|
277
|
+
),
|
|
278
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium", children: displayedYear }),
|
|
279
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
280
|
+
primitives_Button.Button,
|
|
281
|
+
{
|
|
282
|
+
"aria-label": "Next year",
|
|
283
|
+
size: "icon",
|
|
284
|
+
variant: "ghost",
|
|
285
|
+
onClick: () => onYearChange(displayedYear + 1),
|
|
286
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(chevronRight.ChevronRight, { className: "size-4 rtl:rotate-180" })
|
|
287
|
+
}
|
|
288
|
+
)
|
|
289
|
+
] }),
|
|
290
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-3 gap-2", children: months.map((monthDate) => {
|
|
291
|
+
const disabled = isDisabled?.(monthDate) ?? false;
|
|
292
|
+
const selected = isSameMonth(value, monthDate);
|
|
293
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
294
|
+
"button",
|
|
295
|
+
{
|
|
296
|
+
"aria-pressed": selected,
|
|
297
|
+
className: utils$1.cn(
|
|
298
|
+
"rounded-md py-2 text-sm transition-colors",
|
|
299
|
+
"hover:bg-muted disabled:cursor-not-allowed disabled:opacity-50",
|
|
300
|
+
selected && "bg-primary text-primary-foreground hover:bg-primary"
|
|
301
|
+
),
|
|
302
|
+
disabled,
|
|
303
|
+
type: "button",
|
|
304
|
+
onClick: () => onSelect(monthDate),
|
|
305
|
+
children: monthName(monthDate)
|
|
306
|
+
},
|
|
307
|
+
monthDate.getMonth()
|
|
308
|
+
);
|
|
309
|
+
}) })
|
|
310
|
+
] });
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
const YearPicker = ({
|
|
314
|
+
value,
|
|
315
|
+
displayedYear,
|
|
316
|
+
onYearChange,
|
|
317
|
+
onSelect,
|
|
318
|
+
isDisabled
|
|
319
|
+
}) => {
|
|
320
|
+
const decadeStart = decadeStartFor(displayedYear);
|
|
321
|
+
const years = Array.from({ length: 12 }, (_, i) => decadeStart - 1 + i);
|
|
322
|
+
const selectedYear = value?.getFullYear();
|
|
323
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-background flex w-[16rem] flex-col gap-3 p-2", children: [
|
|
324
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
325
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
326
|
+
primitives_Button.Button,
|
|
327
|
+
{
|
|
328
|
+
"aria-label": "Previous decade",
|
|
329
|
+
size: "icon",
|
|
330
|
+
variant: "ghost",
|
|
331
|
+
onClick: () => onYearChange(decadeStart - 10),
|
|
332
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(chevronLeft.ChevronLeft, { className: "size-4 rtl:rotate-180" })
|
|
333
|
+
}
|
|
334
|
+
),
|
|
335
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm font-medium", children: [
|
|
336
|
+
decadeStart,
|
|
337
|
+
"-",
|
|
338
|
+
decadeStart + 9
|
|
339
|
+
] }),
|
|
340
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
341
|
+
primitives_Button.Button,
|
|
342
|
+
{
|
|
343
|
+
"aria-label": "Next decade",
|
|
344
|
+
size: "icon",
|
|
345
|
+
variant: "ghost",
|
|
346
|
+
onClick: () => onYearChange(decadeStart + 10),
|
|
347
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(chevronRight.ChevronRight, { className: "size-4 rtl:rotate-180" })
|
|
348
|
+
}
|
|
349
|
+
)
|
|
350
|
+
] }),
|
|
351
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-3 gap-2", children: years.map((year) => {
|
|
352
|
+
const yearDate = new Date(year, 0, 1);
|
|
353
|
+
const disabled = isDisabled?.(yearDate) ?? false;
|
|
354
|
+
const selected = selectedYear === year;
|
|
355
|
+
const outsideDecade = year < decadeStart || year > decadeStart + 9;
|
|
356
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
357
|
+
"button",
|
|
358
|
+
{
|
|
359
|
+
"aria-pressed": selected,
|
|
360
|
+
className: utils$1.cn(
|
|
361
|
+
"rounded-md py-2 text-sm transition-colors",
|
|
362
|
+
"hover:bg-muted disabled:cursor-not-allowed disabled:opacity-50",
|
|
363
|
+
outsideDecade && "text-muted-foreground",
|
|
364
|
+
selected && "bg-primary text-primary-foreground hover:bg-primary"
|
|
365
|
+
),
|
|
366
|
+
disabled,
|
|
367
|
+
type: "button",
|
|
368
|
+
onClick: () => onSelect(yearDate),
|
|
369
|
+
children: year
|
|
370
|
+
},
|
|
371
|
+
year
|
|
372
|
+
);
|
|
373
|
+
}) })
|
|
374
|
+
] });
|
|
375
|
+
};
|
|
376
|
+
|
|
205
377
|
const DatePicker = React.forwardRef(
|
|
206
378
|
({
|
|
207
379
|
value,
|
|
208
380
|
defaultValue,
|
|
209
381
|
onChange,
|
|
382
|
+
onBlur,
|
|
210
383
|
type = "date",
|
|
211
384
|
dateFormat = DEFAULT_DATE_FORMAT,
|
|
212
385
|
timeFormat = DEFAULT_TIME_FORMAT,
|
|
@@ -215,6 +388,7 @@ const DatePicker = React.forwardRef(
|
|
|
215
388
|
showSeconds = false,
|
|
216
389
|
minDate,
|
|
217
390
|
maxDate,
|
|
391
|
+
disabledDate,
|
|
218
392
|
placeholder,
|
|
219
393
|
label,
|
|
220
394
|
error,
|
|
@@ -227,9 +401,15 @@ const DatePicker = React.forwardRef(
|
|
|
227
401
|
onTimezoneChange,
|
|
228
402
|
onOk,
|
|
229
403
|
needConfirm = false,
|
|
404
|
+
open: openProp,
|
|
230
405
|
onOpenChange,
|
|
231
406
|
className,
|
|
232
|
-
labelProps
|
|
407
|
+
labelProps,
|
|
408
|
+
picker = "date",
|
|
409
|
+
side = "bottom",
|
|
410
|
+
align = "start",
|
|
411
|
+
trigger,
|
|
412
|
+
weekStartsOn = 0
|
|
233
413
|
}, ref) => {
|
|
234
414
|
const generatedId = React.useId();
|
|
235
415
|
const errorId = `error_${generatedId}`;
|
|
@@ -240,9 +420,10 @@ const DatePicker = React.forwardRef(
|
|
|
240
420
|
const popoverContentId = React.useRef(
|
|
241
421
|
`datepicker-popover-${generatedId}`
|
|
242
422
|
).current;
|
|
243
|
-
const
|
|
244
|
-
const [internalValue, setInternalValue] = React.useState(
|
|
245
|
-
|
|
423
|
+
const { open, setOpen } = TimePickerPanel.useControlledOpen(openProp, onOpenChange);
|
|
424
|
+
const [internalValue, setInternalValue] = React.useState(
|
|
425
|
+
coerceDateValue(defaultValue, type) ?? null
|
|
426
|
+
);
|
|
246
427
|
const [calendarMonth, setCalendarMonth] = React.useState(
|
|
247
428
|
(type === "date" ? value ?? defaultValue : null) ?? /* @__PURE__ */ new Date()
|
|
248
429
|
);
|
|
@@ -250,65 +431,47 @@ const DatePicker = React.forwardRef(
|
|
|
250
431
|
"from"
|
|
251
432
|
);
|
|
252
433
|
const [pendingDate, setPendingDate] = React.useState(null);
|
|
253
|
-
const [pendingTime, setPendingTime] = React.useState(
|
|
254
|
-
|
|
255
|
-
minutes: 0,
|
|
256
|
-
seconds: 0
|
|
257
|
-
});
|
|
434
|
+
const [pendingTime, setPendingTime] = React.useState(INITIAL_TIME_VALUE);
|
|
435
|
+
const currentValue = value !== void 0 ? coerceDateValue(value, type) : internalValue;
|
|
258
436
|
const displayFormat = getDisplayFormat(dateFormat, timeFormat, showTime);
|
|
259
437
|
const sizeConfig = SIZE_CONFIG[size];
|
|
260
438
|
const maskEnabled = TimePickerPanel.isFixedWidthFormat(displayFormat);
|
|
439
|
+
const defaultPlaceholder = getDatePlaceholder(
|
|
440
|
+
dateFormat,
|
|
441
|
+
timeFormat,
|
|
442
|
+
showTime,
|
|
443
|
+
type
|
|
444
|
+
);
|
|
261
445
|
const maskTemplate = React.useMemo(
|
|
262
446
|
() => maskEnabled ? type === "range" ? TimePickerPanel.buildRangeMaskTemplate(displayFormat) : TimePickerPanel.buildMaskTemplate(displayFormat) : null,
|
|
263
447
|
[displayFormat, type, maskEnabled]
|
|
264
448
|
);
|
|
265
|
-
const
|
|
266
|
-
|
|
449
|
+
const singleDateLen = React.useMemo(
|
|
450
|
+
() => TimePickerPanel.buildMaskTemplate(displayFormat).pattern.length,
|
|
451
|
+
[displayFormat]
|
|
452
|
+
);
|
|
453
|
+
const calendarDisabled = React.useCallback(
|
|
454
|
+
(date) => {
|
|
455
|
+
if (disabledDate?.(date)) return true;
|
|
456
|
+
if (minDate && date < new Date(new Date(minDate).setHours(0, 0, 0, 0)))
|
|
457
|
+
return true;
|
|
458
|
+
if (maxDate && date > new Date(new Date(maxDate).setHours(23, 59, 59, 999)))
|
|
459
|
+
return true;
|
|
460
|
+
return false;
|
|
461
|
+
},
|
|
462
|
+
[minDate, maxDate, disabledDate]
|
|
463
|
+
);
|
|
267
464
|
const getDisplayText = React.useCallback(() => {
|
|
268
|
-
if (type
|
|
269
|
-
|
|
270
|
-
if (!rangeValue || !rangeValue[0] && !rangeValue[1]) return "";
|
|
271
|
-
const from = rangeValue[0] ? formatDate(rangeValue[0], displayFormat) : "";
|
|
272
|
-
const to = rangeValue[1] ? formatDate(rangeValue[1], displayFormat) : "";
|
|
273
|
-
return `${from} - ${to}`;
|
|
465
|
+
if (type !== "range") {
|
|
466
|
+
return formatDate(currentValue, displayFormat);
|
|
274
467
|
}
|
|
275
|
-
|
|
468
|
+
const rangeValue = currentValue;
|
|
469
|
+
if (!rangeValue || !rangeValue[0] && !rangeValue[1]) return "";
|
|
470
|
+
const from = rangeValue[0] ? formatDate(rangeValue[0], displayFormat) : "";
|
|
471
|
+
const to = rangeValue[1] ? formatDate(rangeValue[1], displayFormat) : "";
|
|
472
|
+
return `${from} - ${to}`;
|
|
276
473
|
}, [currentValue, displayFormat, type]);
|
|
277
474
|
const [inputText, setInputText] = React.useState(() => getDisplayText());
|
|
278
|
-
React.useEffect(() => {
|
|
279
|
-
if (!open) setInputText(getDisplayText());
|
|
280
|
-
}, [getDisplayText, open]);
|
|
281
|
-
const closePopover = React.useCallback(() => {
|
|
282
|
-
setOpen(false);
|
|
283
|
-
onOpenChange?.(false);
|
|
284
|
-
setInputText(getDisplayText());
|
|
285
|
-
}, [onOpenChange, getDisplayText]);
|
|
286
|
-
const openPopover = React.useCallback(() => {
|
|
287
|
-
setOpen(true);
|
|
288
|
-
onOpenChange?.(true);
|
|
289
|
-
setRangeSelectionStep("from");
|
|
290
|
-
const dateVal = type === "date" ? currentValue : null;
|
|
291
|
-
if (dateVal) {
|
|
292
|
-
setCalendarMonth(dateVal);
|
|
293
|
-
setPendingDate(dateVal);
|
|
294
|
-
setPendingTime(TimePickerPanel.dateToTimeValue(dateVal));
|
|
295
|
-
} else {
|
|
296
|
-
setPendingDate(null);
|
|
297
|
-
setPendingTime({ hours: 0, minutes: 0, seconds: 0 });
|
|
298
|
-
}
|
|
299
|
-
}, [type, currentValue, onOpenChange]);
|
|
300
|
-
React.useEffect(() => {
|
|
301
|
-
if (!open) return;
|
|
302
|
-
const handlePointerDown = (e) => {
|
|
303
|
-
const target = e.target;
|
|
304
|
-
if (containerRef.current?.contains(target)) return;
|
|
305
|
-
const popoverEl = document.getElementById(popoverContentId);
|
|
306
|
-
if (popoverEl?.contains(target)) return;
|
|
307
|
-
closePopover();
|
|
308
|
-
};
|
|
309
|
-
document.addEventListener("pointerdown", handlePointerDown);
|
|
310
|
-
return () => document.removeEventListener("pointerdown", handlePointerDown);
|
|
311
|
-
}, [open, closePopover]);
|
|
312
475
|
const commitValue = (date) => {
|
|
313
476
|
if (date === null) {
|
|
314
477
|
setInternalValue(null);
|
|
@@ -336,16 +499,76 @@ const DatePicker = React.forwardRef(
|
|
|
336
499
|
onChange?.(toDayjs(converted), formatted);
|
|
337
500
|
setInputText(formatted);
|
|
338
501
|
};
|
|
502
|
+
const parseAndApplyRange = (text) => {
|
|
503
|
+
const parts = text.split(" - ");
|
|
504
|
+
if (!isDatePartComplete(parts[0] ?? "", maskEnabled, singleDateLen))
|
|
505
|
+
return;
|
|
506
|
+
const from = parseDate(parts[0], displayFormat);
|
|
507
|
+
if (from) setCalendarMonth(from);
|
|
508
|
+
const range = parseRangeText(
|
|
509
|
+
text,
|
|
510
|
+
displayFormat,
|
|
511
|
+
maskEnabled,
|
|
512
|
+
singleDateLen
|
|
513
|
+
);
|
|
514
|
+
if (range) commitValue(range);
|
|
515
|
+
};
|
|
516
|
+
const commitPendingOnClose = React.useCallback(() => {
|
|
517
|
+
const hasOkButton = showTime || needConfirm;
|
|
518
|
+
if (!hasOkButton || !pendingDate) {
|
|
519
|
+
setInputText(getDisplayText());
|
|
520
|
+
return;
|
|
521
|
+
}
|
|
522
|
+
const finalDate = showTime ? applyTimeToDate(pendingDate, pendingTime) : pendingDate;
|
|
523
|
+
const currentSingle = type === "date" ? currentValue : null;
|
|
524
|
+
const isSame = currentSingle && finalDate.getTime() === currentSingle.getTime();
|
|
525
|
+
if (isSame) {
|
|
526
|
+
setInputText(getDisplayText());
|
|
527
|
+
return;
|
|
528
|
+
}
|
|
529
|
+
commitValue(finalDate);
|
|
530
|
+
}, [
|
|
531
|
+
showTime,
|
|
532
|
+
needConfirm,
|
|
533
|
+
pendingDate,
|
|
534
|
+
pendingTime,
|
|
535
|
+
type,
|
|
536
|
+
currentValue,
|
|
537
|
+
getDisplayText,
|
|
538
|
+
onChange
|
|
539
|
+
]);
|
|
540
|
+
const closePopover = React.useCallback(() => {
|
|
541
|
+
commitPendingOnClose();
|
|
542
|
+
setOpen(false);
|
|
543
|
+
}, [commitPendingOnClose, setOpen]);
|
|
544
|
+
TimePickerPanel.useOutsideClickClose({
|
|
545
|
+
enabled: open,
|
|
546
|
+
containerRef,
|
|
547
|
+
popoverElementId: popoverContentId,
|
|
548
|
+
onClose: closePopover
|
|
549
|
+
});
|
|
550
|
+
const openPopover = () => {
|
|
551
|
+
setOpen(true);
|
|
552
|
+
setRangeSelectionStep("from");
|
|
553
|
+
const dateVal = type === "date" ? currentValue : null;
|
|
554
|
+
if (!dateVal) {
|
|
555
|
+
setPendingDate(null);
|
|
556
|
+
setPendingTime(INITIAL_TIME_VALUE);
|
|
557
|
+
return;
|
|
558
|
+
}
|
|
559
|
+
setCalendarMonth(dateVal);
|
|
560
|
+
setPendingDate(dateVal);
|
|
561
|
+
setPendingTime(TimePickerPanel.dateToTimeValue(dateVal));
|
|
562
|
+
};
|
|
339
563
|
const handleDateSelect = (selected) => {
|
|
340
564
|
if (!selected) return;
|
|
341
565
|
setCalendarMonth(selected);
|
|
342
566
|
if (showTime || needConfirm) {
|
|
343
567
|
setPendingDate(selected);
|
|
344
|
-
|
|
345
|
-
commitValue(selected);
|
|
346
|
-
setOpen(false);
|
|
347
|
-
onOpenChange?.(false);
|
|
568
|
+
return;
|
|
348
569
|
}
|
|
570
|
+
commitValue(selected);
|
|
571
|
+
setOpen(false);
|
|
349
572
|
};
|
|
350
573
|
const handleRangeSelect = (range) => {
|
|
351
574
|
if (!range) return;
|
|
@@ -354,34 +577,29 @@ const DatePicker = React.forwardRef(
|
|
|
354
577
|
if (rangeSelectionStep === "from") {
|
|
355
578
|
setInternalValue([from, null]);
|
|
356
579
|
setRangeSelectionStep("to");
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
onOpenChange?.(false);
|
|
365
|
-
}
|
|
366
|
-
} else if (from) {
|
|
367
|
-
setInternalValue([from, null]);
|
|
580
|
+
return;
|
|
581
|
+
}
|
|
582
|
+
setRangeSelectionStep("from");
|
|
583
|
+
if (from && to) {
|
|
584
|
+
if (showTime || needConfirm) {
|
|
585
|
+
setPendingDate(from);
|
|
586
|
+
return;
|
|
368
587
|
}
|
|
369
|
-
|
|
588
|
+
commitValue([from, to]);
|
|
589
|
+
setOpen(false);
|
|
590
|
+
return;
|
|
370
591
|
}
|
|
371
|
-
|
|
372
|
-
const handleTimeChange = (time) => {
|
|
373
|
-
setPendingTime(time);
|
|
592
|
+
if (from) setInternalValue([from, null]);
|
|
374
593
|
};
|
|
375
594
|
const handleNow = () => {
|
|
376
595
|
const now = toBrowserLocalDate(/* @__PURE__ */ new Date());
|
|
377
596
|
if (showTime || needConfirm) {
|
|
378
597
|
setPendingDate(now);
|
|
379
598
|
setPendingTime(TimePickerPanel.dateToTimeValue(now));
|
|
380
|
-
|
|
381
|
-
commitValue(now);
|
|
382
|
-
setOpen(false);
|
|
383
|
-
onOpenChange?.(false);
|
|
599
|
+
return;
|
|
384
600
|
}
|
|
601
|
+
commitValue(now);
|
|
602
|
+
setOpen(false);
|
|
385
603
|
};
|
|
386
604
|
const handleOk = () => {
|
|
387
605
|
if (pendingDate) {
|
|
@@ -390,40 +608,12 @@ const DatePicker = React.forwardRef(
|
|
|
390
608
|
onOk?.(finalDate);
|
|
391
609
|
}
|
|
392
610
|
setOpen(false);
|
|
393
|
-
onOpenChange?.(false);
|
|
394
611
|
};
|
|
395
612
|
const handleClear = (e) => {
|
|
396
613
|
e.stopPropagation();
|
|
397
614
|
e.preventDefault();
|
|
398
615
|
commitValue(null);
|
|
399
616
|
};
|
|
400
|
-
React.useLayoutEffect(() => {
|
|
401
|
-
if (cursorPosRef.current !== null && inputRef.current && document.activeElement === inputRef.current) {
|
|
402
|
-
inputRef.current.setSelectionRange(
|
|
403
|
-
cursorPosRef.current,
|
|
404
|
-
cursorPosRef.current
|
|
405
|
-
);
|
|
406
|
-
cursorPosRef.current = null;
|
|
407
|
-
}
|
|
408
|
-
});
|
|
409
|
-
const singleDateLen = React.useMemo(
|
|
410
|
-
() => TimePickerPanel.buildMaskTemplate(displayFormat).pattern.length,
|
|
411
|
-
[displayFormat]
|
|
412
|
-
);
|
|
413
|
-
const parseAndApplyRange = (text) => {
|
|
414
|
-
const parts = text.split(" - ");
|
|
415
|
-
if (!isDatePartComplete(parts[0] ?? "", maskEnabled, singleDateLen))
|
|
416
|
-
return;
|
|
417
|
-
const from = parseDate(parts[0], displayFormat);
|
|
418
|
-
if (from) setCalendarMonth(from);
|
|
419
|
-
const range = parseRangeText(
|
|
420
|
-
text,
|
|
421
|
-
displayFormat,
|
|
422
|
-
maskEnabled,
|
|
423
|
-
singleDateLen
|
|
424
|
-
);
|
|
425
|
-
if (range) commitValue(range);
|
|
426
|
-
};
|
|
427
617
|
const handleInputChange = (e) => {
|
|
428
618
|
let text = e.target.value;
|
|
429
619
|
if (maskTemplate) {
|
|
@@ -449,12 +639,18 @@ const DatePicker = React.forwardRef(
|
|
|
449
639
|
if (showTime || needConfirm) {
|
|
450
640
|
setPendingDate(parsed);
|
|
451
641
|
setPendingTime(TimePickerPanel.dateToTimeValue(parsed));
|
|
452
|
-
|
|
453
|
-
commitValue(parsed);
|
|
642
|
+
return;
|
|
454
643
|
}
|
|
644
|
+
commitValue(parsed);
|
|
455
645
|
};
|
|
456
646
|
const handleInputKeyDown = (e) => {
|
|
457
|
-
if (e.key === "Escape")
|
|
647
|
+
if (e.key === "Escape") {
|
|
648
|
+
setPendingDate(null);
|
|
649
|
+
setPendingTime(INITIAL_TIME_VALUE);
|
|
650
|
+
setInputText(getDisplayText());
|
|
651
|
+
setOpen(false);
|
|
652
|
+
return;
|
|
653
|
+
}
|
|
458
654
|
if (e.key !== "Enter") return;
|
|
459
655
|
if (type === "range") {
|
|
460
656
|
const range = parseRangeText(
|
|
@@ -469,31 +665,61 @@ const DatePicker = React.forwardRef(
|
|
|
469
665
|
if (parsed) commitValue(parsed);
|
|
470
666
|
}
|
|
471
667
|
setOpen(false);
|
|
472
|
-
onOpenChange?.(false);
|
|
473
668
|
};
|
|
474
|
-
const
|
|
475
|
-
|
|
669
|
+
const handleInputBlur = (e) => {
|
|
670
|
+
const next = e.relatedTarget;
|
|
671
|
+
if (next && containerRef.current?.contains(next)) return;
|
|
672
|
+
const popoverEl = document.getElementById(popoverContentId);
|
|
673
|
+
if (next && popoverEl?.contains(next)) return;
|
|
674
|
+
onBlur?.(e);
|
|
476
675
|
};
|
|
676
|
+
React.useEffect(() => {
|
|
677
|
+
if (!open) setInputText(getDisplayText());
|
|
678
|
+
}, [getDisplayText, open]);
|
|
679
|
+
TimePickerPanel.useCursorRestore([{ inputRef, cursorRef: cursorPosRef }]);
|
|
680
|
+
React.useEffect(() => {
|
|
681
|
+
if (!open || type !== "date") return;
|
|
682
|
+
const dateVal = currentValue;
|
|
683
|
+
if (dateVal instanceof Date) setCalendarMonth(dateVal);
|
|
684
|
+
}, [open]);
|
|
477
685
|
const hasField = !!(label || error || helpText);
|
|
478
686
|
const showFooter = showTime || needConfirm || !!onTimezoneChange;
|
|
479
687
|
const todayDate = toBrowserLocalDate(/* @__PURE__ */ new Date());
|
|
688
|
+
const handleGridPickerSelect = (date) => {
|
|
689
|
+
commitValue(date);
|
|
690
|
+
setOpen(false);
|
|
691
|
+
};
|
|
692
|
+
const handleSingleDateSelectWithPicker = (selected) => {
|
|
693
|
+
if (!selected) return handleDateSelect(void 0);
|
|
694
|
+
handleDateSelect(
|
|
695
|
+
picker === "week" ? startOfWeek(selected, weekStartsOn) : selected
|
|
696
|
+
);
|
|
697
|
+
};
|
|
698
|
+
const weekHighlightProps = (() => {
|
|
699
|
+
if (picker !== "week" || type !== "date" || !currentValue) return {};
|
|
700
|
+
const weekStart = startOfWeek(currentValue, weekStartsOn);
|
|
701
|
+
const weekDays = weekDaysFrom(weekStart);
|
|
702
|
+
return {
|
|
703
|
+
modifiers: {
|
|
704
|
+
weekStart: [weekDays[0]],
|
|
705
|
+
weekMiddle: weekDays.slice(1, 6),
|
|
706
|
+
weekEnd: [weekDays[6]]
|
|
707
|
+
},
|
|
708
|
+
modifiersClassNames: {
|
|
709
|
+
weekStart: "!bg-primary !text-primary-foreground !rounded-e-none hover:!bg-primary",
|
|
710
|
+
weekMiddle: "!bg-primary !text-primary-foreground !rounded-none hover:!bg-primary",
|
|
711
|
+
weekEnd: "!bg-primary !text-primary-foreground !rounded-s-none hover:!bg-primary"
|
|
712
|
+
}
|
|
713
|
+
};
|
|
714
|
+
})();
|
|
715
|
+
const weekRowHoverClassName = picker === "week" ? "[&_button]:!transition-none [&:hover_button]:!bg-primary [&:hover_button]:!text-primary-foreground [&:hover_button]:!rounded-none [&:hover_button]:cursor-pointer" : void 0;
|
|
480
716
|
const ariaDescribedBy = [error ? errorId : null, helpText ? helpTextId : null].filter(Boolean).join(" ") || void 0;
|
|
481
|
-
const
|
|
482
|
-
(date) => {
|
|
483
|
-
if (minDate && date < new Date(minDate.setHours(0, 0, 0, 0)))
|
|
484
|
-
return true;
|
|
485
|
-
if (maxDate && date > new Date(maxDate.setHours(23, 59, 59, 999)))
|
|
486
|
-
return true;
|
|
487
|
-
return false;
|
|
488
|
-
},
|
|
489
|
-
[minDate, maxDate]
|
|
490
|
-
);
|
|
491
|
-
const calendarSelected = React.useCallback(() => {
|
|
717
|
+
const calendarSelected = () => {
|
|
492
718
|
if (showTime || needConfirm) return pendingDate ?? void 0;
|
|
493
719
|
return currentValue ?? void 0;
|
|
494
|
-
}
|
|
495
|
-
const triggerContent = /* @__PURE__ */ jsxRuntime.jsxs(primitives_Popover.Popover, { open, children: [
|
|
496
|
-
/* @__PURE__ */ jsxRuntime.jsx(primitives_Popover.PopoverAnchor, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
720
|
+
};
|
|
721
|
+
const triggerContent = /* @__PURE__ */ jsxRuntime.jsxs(primitives_Popover.Popover, { open, onOpenChange: trigger ? setOpen : void 0, children: [
|
|
722
|
+
trigger ? /* @__PURE__ */ jsxRuntime.jsx(primitives_Popover.PopoverTrigger, { asChild: true, children: trigger }) : /* @__PURE__ */ jsxRuntime.jsx(primitives_Popover.PopoverAnchor, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
497
723
|
"div",
|
|
498
724
|
{
|
|
499
725
|
ref: containerRef,
|
|
@@ -509,7 +735,10 @@ const DatePicker = React.forwardRef(
|
|
|
509
735
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
510
736
|
Calendar,
|
|
511
737
|
{
|
|
512
|
-
className: utils$1.cn(
|
|
738
|
+
className: utils$1.cn(
|
|
739
|
+
"shrink-0 text-muted-foreground",
|
|
740
|
+
sizeConfig.icon
|
|
741
|
+
)
|
|
513
742
|
}
|
|
514
743
|
),
|
|
515
744
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -525,7 +754,10 @@ const DatePicker = React.forwardRef(
|
|
|
525
754
|
value: inputText,
|
|
526
755
|
onChange: handleInputChange,
|
|
527
756
|
onKeyDown: handleInputKeyDown,
|
|
528
|
-
onFocus:
|
|
757
|
+
onFocus: () => {
|
|
758
|
+
if (!open) openPopover();
|
|
759
|
+
},
|
|
760
|
+
onBlur: handleInputBlur,
|
|
529
761
|
className: utils$1.cn(
|
|
530
762
|
"min-w-0 flex-1 bg-transparent outline-none placeholder:text-muted-foreground",
|
|
531
763
|
"disabled:cursor-not-allowed",
|
|
@@ -557,14 +789,35 @@ const DatePicker = React.forwardRef(
|
|
|
557
789
|
{
|
|
558
790
|
id: popoverContentId,
|
|
559
791
|
className: "w-auto p-0",
|
|
560
|
-
align
|
|
792
|
+
align,
|
|
793
|
+
side,
|
|
561
794
|
onOpenAutoFocus: (e) => e.preventDefault(),
|
|
562
795
|
onCloseAutoFocus: (e) => e.preventDefault(),
|
|
563
796
|
onPointerDownOutside: (e) => e.preventDefault(),
|
|
564
797
|
onInteractOutside: (e) => e.preventDefault(),
|
|
565
798
|
children: [
|
|
566
799
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: utils$1.cn("flex", showTime && "flex-row"), children: [
|
|
567
|
-
type === "date" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
800
|
+
type === "date" && picker === "month" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
801
|
+
MonthPicker,
|
|
802
|
+
{
|
|
803
|
+
value: currentValue ?? null,
|
|
804
|
+
displayedYear: calendarMonth.getFullYear(),
|
|
805
|
+
onYearChange: (year) => setCalendarMonth(
|
|
806
|
+
new Date(year, calendarMonth.getMonth(), 1)
|
|
807
|
+
),
|
|
808
|
+
onSelect: handleGridPickerSelect,
|
|
809
|
+
isDisabled: (date) => isMonthDisabled(date, minDate, maxDate)
|
|
810
|
+
}
|
|
811
|
+
) : type === "date" && picker === "year" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
812
|
+
YearPicker,
|
|
813
|
+
{
|
|
814
|
+
value: currentValue ?? null,
|
|
815
|
+
displayedYear: calendarMonth.getFullYear(),
|
|
816
|
+
onYearChange: (year) => setCalendarMonth(new Date(year, 0, 1)),
|
|
817
|
+
onSelect: handleGridPickerSelect,
|
|
818
|
+
isDisabled: (date) => isYearDisabled(date, minDate, maxDate)
|
|
819
|
+
}
|
|
820
|
+
) : type === "date" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
568
821
|
primitives_Calendar.Calendar,
|
|
569
822
|
{
|
|
570
823
|
mode: "single",
|
|
@@ -573,8 +826,11 @@ const DatePicker = React.forwardRef(
|
|
|
573
826
|
month: calendarMonth,
|
|
574
827
|
onMonthChange: setCalendarMonth,
|
|
575
828
|
selected: calendarSelected(),
|
|
576
|
-
onSelect:
|
|
829
|
+
onSelect: handleSingleDateSelectWithPicker,
|
|
577
830
|
disabled: calendarDisabled,
|
|
831
|
+
weekStartsOn,
|
|
832
|
+
classNames: weekRowHoverClassName ? { week: utils$1.cn("mt-2 flex w-full", weekRowHoverClassName) } : void 0,
|
|
833
|
+
...weekHighlightProps,
|
|
578
834
|
...minDate && { fromDate: minDate },
|
|
579
835
|
...maxDate && { toDate: maxDate }
|
|
580
836
|
}
|
|
@@ -585,6 +841,7 @@ const DatePicker = React.forwardRef(
|
|
|
585
841
|
numberOfMonths: 2,
|
|
586
842
|
captionLayout: "dropdown",
|
|
587
843
|
today: todayDate,
|
|
844
|
+
weekStartsOn,
|
|
588
845
|
className: "[&_[data-outside][data-selected=true]]:!bg-transparent [&_[data-outside][data-selected=true]]:after:!bg-transparent [&_[data-outside]_button]:!bg-transparent [&_[data-outside]_button]:!text-muted-foreground",
|
|
589
846
|
month: calendarMonth,
|
|
590
847
|
onMonthChange: setCalendarMonth,
|
|
@@ -602,7 +859,7 @@ const DatePicker = React.forwardRef(
|
|
|
602
859
|
TimePickerPanel.TimePickerPanel,
|
|
603
860
|
{
|
|
604
861
|
value: pendingTime,
|
|
605
|
-
onChange:
|
|
862
|
+
onChange: setPendingTime,
|
|
606
863
|
format: timePickerFormat,
|
|
607
864
|
showSeconds,
|
|
608
865
|
disabled
|
|
@@ -658,4 +915,4 @@ const DatePicker = React.forwardRef(
|
|
|
658
915
|
DatePicker.displayName = "DatePicker";
|
|
659
916
|
|
|
660
917
|
exports.DatePicker = DatePicker;
|
|
661
|
-
//# sourceMappingURL=DatePicker-
|
|
918
|
+
//# sourceMappingURL=DatePicker-BZd4rM2R.js.map
|