@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
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
-
import { forwardRef, useId, useRef, useState, useMemo, useCallback, useEffect
|
|
2
|
+
import { forwardRef, useId, useRef, useState, useMemo, useCallback, useEffect } from 'react';
|
|
3
3
|
import { Calendar as Calendar$1 } from './primitives/Calendar.js';
|
|
4
|
-
import { Popover, PopoverAnchor, PopoverContent } from './primitives/Popover.js';
|
|
4
|
+
import { Popover, PopoverTrigger, PopoverAnchor, PopoverContent } from './primitives/Popover.js';
|
|
5
5
|
import { Field, FieldLabel, FieldContent, FieldError, FieldDescription } from './primitives/Field.js';
|
|
6
6
|
import { c as cn } from './utils-BJnb9o5c.js';
|
|
7
|
+
import { u as useControlledOpen, l as isFixedWidthFormat, m as buildRangeMaskTemplate, d as buildMaskTemplate, b as useOutsideClickClose, e as useCursorRestore, T as TimePickerPanel, j as applyMask, n as dateToTimeValue } from './TimePickerPanel--KDX5QwS.js';
|
|
7
8
|
import pureDayjs from 'dayjs';
|
|
8
9
|
import customParseFormat from 'dayjs/plugin/customParseFormat';
|
|
9
10
|
import { dayjs } from '@bigbinary/neeto-commons-frontend/utils';
|
|
10
|
-
import { i as isFixedWidthFormat, c as buildRangeMaskTemplate, b as buildMaskTemplate, d as dateToTimeValue, T as TimePickerPanel, a as applyMask } from './TimePickerPanel-zWmOy3Eo.js';
|
|
11
11
|
import { Button } from './primitives/Button.js';
|
|
12
|
+
import { C as ChevronLeft } from './chevron-left-BDoT8E2-.js';
|
|
13
|
+
import { C as ChevronRight } from './chevron-right-DQnrO-ek.js';
|
|
12
14
|
import { c as createLucideIcon } from './createLucideIcon-C8ycilSN.js';
|
|
13
15
|
import { X } from './x-_o2T3n6D.js';
|
|
14
16
|
|
|
@@ -30,6 +32,11 @@ const Calendar = createLucideIcon("calendar", __iconNode);
|
|
|
30
32
|
|
|
31
33
|
const DEFAULT_DATE_FORMAT = "dd/MM/yyyy";
|
|
32
34
|
const DEFAULT_TIME_FORMAT = "HH:mm:ss";
|
|
35
|
+
const INITIAL_TIME_VALUE = {
|
|
36
|
+
hours: 0,
|
|
37
|
+
minutes: 0,
|
|
38
|
+
seconds: 0
|
|
39
|
+
};
|
|
33
40
|
const SIZE_CONFIG = {
|
|
34
41
|
small: {
|
|
35
42
|
trigger: "h-8 md:h-7",
|
|
@@ -123,6 +130,10 @@ const getDisplayFormat = (dateFormat, timeFormat, showTime) => {
|
|
|
123
130
|
const fmt = showTime ? `${dateFormat} ${timeFormat}` : dateFormat;
|
|
124
131
|
return normalizeToDateFnsFormat(fmt);
|
|
125
132
|
};
|
|
133
|
+
const getDatePlaceholder = (dateFormat, timeFormat, showTime, type) => {
|
|
134
|
+
const single = showTime ? `${dateFormat.toUpperCase()} ${timeFormat}` : dateFormat.toUpperCase();
|
|
135
|
+
return type === "range" ? `${single} - ${single}` : single;
|
|
136
|
+
};
|
|
126
137
|
const isDatePartComplete = (part, maskEnabled, singleDateLen) => maskEnabled ? part.length >= singleDateLen : part.length > 0;
|
|
127
138
|
const parseRangeText = (text, displayFormat, maskEnabled, singleDateLen) => {
|
|
128
139
|
const parts = text.split(" - ");
|
|
@@ -133,6 +144,43 @@ const parseRangeText = (text, displayFormat, maskEnabled, singleDateLen) => {
|
|
|
133
144
|
const to = parseDate(parts[1], displayFormat);
|
|
134
145
|
return from && to ? [from, to] : null;
|
|
135
146
|
};
|
|
147
|
+
const startOfWeek = (date, weekStartsOn = 0) => {
|
|
148
|
+
const d = new Date(date);
|
|
149
|
+
const diff = (d.getDay() - weekStartsOn + 7) % 7;
|
|
150
|
+
d.setDate(d.getDate() - diff);
|
|
151
|
+
d.setHours(0, 0, 0, 0);
|
|
152
|
+
return d;
|
|
153
|
+
};
|
|
154
|
+
const weekDaysFrom = (start) => Array.from({ length: 7 }, (_, i) => {
|
|
155
|
+
const d = new Date(start);
|
|
156
|
+
d.setDate(start.getDate() + i);
|
|
157
|
+
return d;
|
|
158
|
+
});
|
|
159
|
+
const isMonthDisabled = (monthDate, minDate, maxDate) => {
|
|
160
|
+
const monthStart = new Date(monthDate.getFullYear(), monthDate.getMonth(), 1);
|
|
161
|
+
const monthEnd = new Date(
|
|
162
|
+
monthDate.getFullYear(),
|
|
163
|
+
monthDate.getMonth() + 1,
|
|
164
|
+
0,
|
|
165
|
+
23,
|
|
166
|
+
59,
|
|
167
|
+
59,
|
|
168
|
+
999
|
|
169
|
+
);
|
|
170
|
+
if (maxDate && monthStart > maxDate) return true;
|
|
171
|
+
if (minDate && monthEnd < minDate) return true;
|
|
172
|
+
return false;
|
|
173
|
+
};
|
|
174
|
+
const isYearDisabled = (yearDate, minDate, maxDate) => {
|
|
175
|
+
const yearStart = new Date(yearDate.getFullYear(), 0, 1);
|
|
176
|
+
const yearEnd = new Date(yearDate.getFullYear(), 11, 31, 23, 59, 59, 999);
|
|
177
|
+
if (maxDate && yearStart > maxDate) return true;
|
|
178
|
+
if (minDate && yearEnd < minDate) return true;
|
|
179
|
+
return false;
|
|
180
|
+
};
|
|
181
|
+
const buildMonth = (year, month) => new Date(year, month, 1);
|
|
182
|
+
const isSameMonth = (a, b) => !!a && a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth();
|
|
183
|
+
const decadeStartFor = (year) => Math.floor(year / 10) * 10;
|
|
136
184
|
|
|
137
185
|
const TIMEZONE_OPTIONS = [
|
|
138
186
|
{ label: "Local", value: "" },
|
|
@@ -195,11 +243,136 @@ const DatePickerFooter = ({
|
|
|
195
243
|
};
|
|
196
244
|
DatePickerFooter.displayName = "DatePickerFooter";
|
|
197
245
|
|
|
246
|
+
const MonthPicker = ({
|
|
247
|
+
value,
|
|
248
|
+
displayedYear,
|
|
249
|
+
onYearChange,
|
|
250
|
+
onSelect,
|
|
251
|
+
isDisabled,
|
|
252
|
+
locale
|
|
253
|
+
}) => {
|
|
254
|
+
const months = Array.from(
|
|
255
|
+
{ length: 12 },
|
|
256
|
+
(_, m) => buildMonth(displayedYear, m)
|
|
257
|
+
);
|
|
258
|
+
const monthName = (date) => date.toLocaleString(locale, { month: "short" });
|
|
259
|
+
return /* @__PURE__ */ jsxs("div", { className: "bg-background flex w-[16rem] flex-col gap-3 p-2", children: [
|
|
260
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
261
|
+
/* @__PURE__ */ jsx(
|
|
262
|
+
Button,
|
|
263
|
+
{
|
|
264
|
+
"aria-label": "Previous year",
|
|
265
|
+
size: "icon",
|
|
266
|
+
variant: "ghost",
|
|
267
|
+
onClick: () => onYearChange(displayedYear - 1),
|
|
268
|
+
children: /* @__PURE__ */ jsx(ChevronLeft, { className: "size-4 rtl:rotate-180" })
|
|
269
|
+
}
|
|
270
|
+
),
|
|
271
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: displayedYear }),
|
|
272
|
+
/* @__PURE__ */ jsx(
|
|
273
|
+
Button,
|
|
274
|
+
{
|
|
275
|
+
"aria-label": "Next year",
|
|
276
|
+
size: "icon",
|
|
277
|
+
variant: "ghost",
|
|
278
|
+
onClick: () => onYearChange(displayedYear + 1),
|
|
279
|
+
children: /* @__PURE__ */ jsx(ChevronRight, { className: "size-4 rtl:rotate-180" })
|
|
280
|
+
}
|
|
281
|
+
)
|
|
282
|
+
] }),
|
|
283
|
+
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-3 gap-2", children: months.map((monthDate) => {
|
|
284
|
+
const disabled = isDisabled?.(monthDate) ?? false;
|
|
285
|
+
const selected = isSameMonth(value, monthDate);
|
|
286
|
+
return /* @__PURE__ */ jsx(
|
|
287
|
+
"button",
|
|
288
|
+
{
|
|
289
|
+
"aria-pressed": selected,
|
|
290
|
+
className: cn(
|
|
291
|
+
"rounded-md py-2 text-sm transition-colors",
|
|
292
|
+
"hover:bg-muted disabled:cursor-not-allowed disabled:opacity-50",
|
|
293
|
+
selected && "bg-primary text-primary-foreground hover:bg-primary"
|
|
294
|
+
),
|
|
295
|
+
disabled,
|
|
296
|
+
type: "button",
|
|
297
|
+
onClick: () => onSelect(monthDate),
|
|
298
|
+
children: monthName(monthDate)
|
|
299
|
+
},
|
|
300
|
+
monthDate.getMonth()
|
|
301
|
+
);
|
|
302
|
+
}) })
|
|
303
|
+
] });
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
const YearPicker = ({
|
|
307
|
+
value,
|
|
308
|
+
displayedYear,
|
|
309
|
+
onYearChange,
|
|
310
|
+
onSelect,
|
|
311
|
+
isDisabled
|
|
312
|
+
}) => {
|
|
313
|
+
const decadeStart = decadeStartFor(displayedYear);
|
|
314
|
+
const years = Array.from({ length: 12 }, (_, i) => decadeStart - 1 + i);
|
|
315
|
+
const selectedYear = value?.getFullYear();
|
|
316
|
+
return /* @__PURE__ */ jsxs("div", { className: "bg-background flex w-[16rem] flex-col gap-3 p-2", children: [
|
|
317
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
318
|
+
/* @__PURE__ */ jsx(
|
|
319
|
+
Button,
|
|
320
|
+
{
|
|
321
|
+
"aria-label": "Previous decade",
|
|
322
|
+
size: "icon",
|
|
323
|
+
variant: "ghost",
|
|
324
|
+
onClick: () => onYearChange(decadeStart - 10),
|
|
325
|
+
children: /* @__PURE__ */ jsx(ChevronLeft, { className: "size-4 rtl:rotate-180" })
|
|
326
|
+
}
|
|
327
|
+
),
|
|
328
|
+
/* @__PURE__ */ jsxs("span", { className: "text-sm font-medium", children: [
|
|
329
|
+
decadeStart,
|
|
330
|
+
"-",
|
|
331
|
+
decadeStart + 9
|
|
332
|
+
] }),
|
|
333
|
+
/* @__PURE__ */ jsx(
|
|
334
|
+
Button,
|
|
335
|
+
{
|
|
336
|
+
"aria-label": "Next decade",
|
|
337
|
+
size: "icon",
|
|
338
|
+
variant: "ghost",
|
|
339
|
+
onClick: () => onYearChange(decadeStart + 10),
|
|
340
|
+
children: /* @__PURE__ */ jsx(ChevronRight, { className: "size-4 rtl:rotate-180" })
|
|
341
|
+
}
|
|
342
|
+
)
|
|
343
|
+
] }),
|
|
344
|
+
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-3 gap-2", children: years.map((year) => {
|
|
345
|
+
const yearDate = new Date(year, 0, 1);
|
|
346
|
+
const disabled = isDisabled?.(yearDate) ?? false;
|
|
347
|
+
const selected = selectedYear === year;
|
|
348
|
+
const outsideDecade = year < decadeStart || year > decadeStart + 9;
|
|
349
|
+
return /* @__PURE__ */ jsx(
|
|
350
|
+
"button",
|
|
351
|
+
{
|
|
352
|
+
"aria-pressed": selected,
|
|
353
|
+
className: cn(
|
|
354
|
+
"rounded-md py-2 text-sm transition-colors",
|
|
355
|
+
"hover:bg-muted disabled:cursor-not-allowed disabled:opacity-50",
|
|
356
|
+
outsideDecade && "text-muted-foreground",
|
|
357
|
+
selected && "bg-primary text-primary-foreground hover:bg-primary"
|
|
358
|
+
),
|
|
359
|
+
disabled,
|
|
360
|
+
type: "button",
|
|
361
|
+
onClick: () => onSelect(yearDate),
|
|
362
|
+
children: year
|
|
363
|
+
},
|
|
364
|
+
year
|
|
365
|
+
);
|
|
366
|
+
}) })
|
|
367
|
+
] });
|
|
368
|
+
};
|
|
369
|
+
|
|
198
370
|
const DatePicker = forwardRef(
|
|
199
371
|
({
|
|
200
372
|
value,
|
|
201
373
|
defaultValue,
|
|
202
374
|
onChange,
|
|
375
|
+
onBlur,
|
|
203
376
|
type = "date",
|
|
204
377
|
dateFormat = DEFAULT_DATE_FORMAT,
|
|
205
378
|
timeFormat = DEFAULT_TIME_FORMAT,
|
|
@@ -208,6 +381,7 @@ const DatePicker = forwardRef(
|
|
|
208
381
|
showSeconds = false,
|
|
209
382
|
minDate,
|
|
210
383
|
maxDate,
|
|
384
|
+
disabledDate,
|
|
211
385
|
placeholder,
|
|
212
386
|
label,
|
|
213
387
|
error,
|
|
@@ -220,9 +394,15 @@ const DatePicker = forwardRef(
|
|
|
220
394
|
onTimezoneChange,
|
|
221
395
|
onOk,
|
|
222
396
|
needConfirm = false,
|
|
397
|
+
open: openProp,
|
|
223
398
|
onOpenChange,
|
|
224
399
|
className,
|
|
225
|
-
labelProps
|
|
400
|
+
labelProps,
|
|
401
|
+
picker = "date",
|
|
402
|
+
side = "bottom",
|
|
403
|
+
align = "start",
|
|
404
|
+
trigger,
|
|
405
|
+
weekStartsOn = 0
|
|
226
406
|
}, ref) => {
|
|
227
407
|
const generatedId = useId();
|
|
228
408
|
const errorId = `error_${generatedId}`;
|
|
@@ -233,9 +413,10 @@ const DatePicker = forwardRef(
|
|
|
233
413
|
const popoverContentId = useRef(
|
|
234
414
|
`datepicker-popover-${generatedId}`
|
|
235
415
|
).current;
|
|
236
|
-
const
|
|
237
|
-
const [internalValue, setInternalValue] = useState(
|
|
238
|
-
|
|
416
|
+
const { open, setOpen } = useControlledOpen(openProp, onOpenChange);
|
|
417
|
+
const [internalValue, setInternalValue] = useState(
|
|
418
|
+
coerceDateValue(defaultValue, type) ?? null
|
|
419
|
+
);
|
|
239
420
|
const [calendarMonth, setCalendarMonth] = useState(
|
|
240
421
|
(type === "date" ? value ?? defaultValue : null) ?? /* @__PURE__ */ new Date()
|
|
241
422
|
);
|
|
@@ -243,65 +424,47 @@ const DatePicker = forwardRef(
|
|
|
243
424
|
"from"
|
|
244
425
|
);
|
|
245
426
|
const [pendingDate, setPendingDate] = useState(null);
|
|
246
|
-
const [pendingTime, setPendingTime] = useState(
|
|
247
|
-
|
|
248
|
-
minutes: 0,
|
|
249
|
-
seconds: 0
|
|
250
|
-
});
|
|
427
|
+
const [pendingTime, setPendingTime] = useState(INITIAL_TIME_VALUE);
|
|
428
|
+
const currentValue = value !== void 0 ? coerceDateValue(value, type) : internalValue;
|
|
251
429
|
const displayFormat = getDisplayFormat(dateFormat, timeFormat, showTime);
|
|
252
430
|
const sizeConfig = SIZE_CONFIG[size];
|
|
253
431
|
const maskEnabled = isFixedWidthFormat(displayFormat);
|
|
432
|
+
const defaultPlaceholder = getDatePlaceholder(
|
|
433
|
+
dateFormat,
|
|
434
|
+
timeFormat,
|
|
435
|
+
showTime,
|
|
436
|
+
type
|
|
437
|
+
);
|
|
254
438
|
const maskTemplate = useMemo(
|
|
255
439
|
() => maskEnabled ? type === "range" ? buildRangeMaskTemplate(displayFormat) : buildMaskTemplate(displayFormat) : null,
|
|
256
440
|
[displayFormat, type, maskEnabled]
|
|
257
441
|
);
|
|
258
|
-
const
|
|
259
|
-
|
|
442
|
+
const singleDateLen = useMemo(
|
|
443
|
+
() => buildMaskTemplate(displayFormat).pattern.length,
|
|
444
|
+
[displayFormat]
|
|
445
|
+
);
|
|
446
|
+
const calendarDisabled = useCallback(
|
|
447
|
+
(date) => {
|
|
448
|
+
if (disabledDate?.(date)) return true;
|
|
449
|
+
if (minDate && date < new Date(new Date(minDate).setHours(0, 0, 0, 0)))
|
|
450
|
+
return true;
|
|
451
|
+
if (maxDate && date > new Date(new Date(maxDate).setHours(23, 59, 59, 999)))
|
|
452
|
+
return true;
|
|
453
|
+
return false;
|
|
454
|
+
},
|
|
455
|
+
[minDate, maxDate, disabledDate]
|
|
456
|
+
);
|
|
260
457
|
const getDisplayText = useCallback(() => {
|
|
261
|
-
if (type
|
|
262
|
-
|
|
263
|
-
if (!rangeValue || !rangeValue[0] && !rangeValue[1]) return "";
|
|
264
|
-
const from = rangeValue[0] ? formatDate(rangeValue[0], displayFormat) : "";
|
|
265
|
-
const to = rangeValue[1] ? formatDate(rangeValue[1], displayFormat) : "";
|
|
266
|
-
return `${from} - ${to}`;
|
|
458
|
+
if (type !== "range") {
|
|
459
|
+
return formatDate(currentValue, displayFormat);
|
|
267
460
|
}
|
|
268
|
-
|
|
461
|
+
const rangeValue = currentValue;
|
|
462
|
+
if (!rangeValue || !rangeValue[0] && !rangeValue[1]) return "";
|
|
463
|
+
const from = rangeValue[0] ? formatDate(rangeValue[0], displayFormat) : "";
|
|
464
|
+
const to = rangeValue[1] ? formatDate(rangeValue[1], displayFormat) : "";
|
|
465
|
+
return `${from} - ${to}`;
|
|
269
466
|
}, [currentValue, displayFormat, type]);
|
|
270
467
|
const [inputText, setInputText] = useState(() => getDisplayText());
|
|
271
|
-
useEffect(() => {
|
|
272
|
-
if (!open) setInputText(getDisplayText());
|
|
273
|
-
}, [getDisplayText, open]);
|
|
274
|
-
const closePopover = useCallback(() => {
|
|
275
|
-
setOpen(false);
|
|
276
|
-
onOpenChange?.(false);
|
|
277
|
-
setInputText(getDisplayText());
|
|
278
|
-
}, [onOpenChange, getDisplayText]);
|
|
279
|
-
const openPopover = useCallback(() => {
|
|
280
|
-
setOpen(true);
|
|
281
|
-
onOpenChange?.(true);
|
|
282
|
-
setRangeSelectionStep("from");
|
|
283
|
-
const dateVal = type === "date" ? currentValue : null;
|
|
284
|
-
if (dateVal) {
|
|
285
|
-
setCalendarMonth(dateVal);
|
|
286
|
-
setPendingDate(dateVal);
|
|
287
|
-
setPendingTime(dateToTimeValue(dateVal));
|
|
288
|
-
} else {
|
|
289
|
-
setPendingDate(null);
|
|
290
|
-
setPendingTime({ hours: 0, minutes: 0, seconds: 0 });
|
|
291
|
-
}
|
|
292
|
-
}, [type, currentValue, onOpenChange]);
|
|
293
|
-
useEffect(() => {
|
|
294
|
-
if (!open) return;
|
|
295
|
-
const handlePointerDown = (e) => {
|
|
296
|
-
const target = e.target;
|
|
297
|
-
if (containerRef.current?.contains(target)) return;
|
|
298
|
-
const popoverEl = document.getElementById(popoverContentId);
|
|
299
|
-
if (popoverEl?.contains(target)) return;
|
|
300
|
-
closePopover();
|
|
301
|
-
};
|
|
302
|
-
document.addEventListener("pointerdown", handlePointerDown);
|
|
303
|
-
return () => document.removeEventListener("pointerdown", handlePointerDown);
|
|
304
|
-
}, [open, closePopover]);
|
|
305
468
|
const commitValue = (date) => {
|
|
306
469
|
if (date === null) {
|
|
307
470
|
setInternalValue(null);
|
|
@@ -329,16 +492,76 @@ const DatePicker = forwardRef(
|
|
|
329
492
|
onChange?.(toDayjs(converted), formatted);
|
|
330
493
|
setInputText(formatted);
|
|
331
494
|
};
|
|
495
|
+
const parseAndApplyRange = (text) => {
|
|
496
|
+
const parts = text.split(" - ");
|
|
497
|
+
if (!isDatePartComplete(parts[0] ?? "", maskEnabled, singleDateLen))
|
|
498
|
+
return;
|
|
499
|
+
const from = parseDate(parts[0], displayFormat);
|
|
500
|
+
if (from) setCalendarMonth(from);
|
|
501
|
+
const range = parseRangeText(
|
|
502
|
+
text,
|
|
503
|
+
displayFormat,
|
|
504
|
+
maskEnabled,
|
|
505
|
+
singleDateLen
|
|
506
|
+
);
|
|
507
|
+
if (range) commitValue(range);
|
|
508
|
+
};
|
|
509
|
+
const commitPendingOnClose = useCallback(() => {
|
|
510
|
+
const hasOkButton = showTime || needConfirm;
|
|
511
|
+
if (!hasOkButton || !pendingDate) {
|
|
512
|
+
setInputText(getDisplayText());
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
515
|
+
const finalDate = showTime ? applyTimeToDate(pendingDate, pendingTime) : pendingDate;
|
|
516
|
+
const currentSingle = type === "date" ? currentValue : null;
|
|
517
|
+
const isSame = currentSingle && finalDate.getTime() === currentSingle.getTime();
|
|
518
|
+
if (isSame) {
|
|
519
|
+
setInputText(getDisplayText());
|
|
520
|
+
return;
|
|
521
|
+
}
|
|
522
|
+
commitValue(finalDate);
|
|
523
|
+
}, [
|
|
524
|
+
showTime,
|
|
525
|
+
needConfirm,
|
|
526
|
+
pendingDate,
|
|
527
|
+
pendingTime,
|
|
528
|
+
type,
|
|
529
|
+
currentValue,
|
|
530
|
+
getDisplayText,
|
|
531
|
+
onChange
|
|
532
|
+
]);
|
|
533
|
+
const closePopover = useCallback(() => {
|
|
534
|
+
commitPendingOnClose();
|
|
535
|
+
setOpen(false);
|
|
536
|
+
}, [commitPendingOnClose, setOpen]);
|
|
537
|
+
useOutsideClickClose({
|
|
538
|
+
enabled: open,
|
|
539
|
+
containerRef,
|
|
540
|
+
popoverElementId: popoverContentId,
|
|
541
|
+
onClose: closePopover
|
|
542
|
+
});
|
|
543
|
+
const openPopover = () => {
|
|
544
|
+
setOpen(true);
|
|
545
|
+
setRangeSelectionStep("from");
|
|
546
|
+
const dateVal = type === "date" ? currentValue : null;
|
|
547
|
+
if (!dateVal) {
|
|
548
|
+
setPendingDate(null);
|
|
549
|
+
setPendingTime(INITIAL_TIME_VALUE);
|
|
550
|
+
return;
|
|
551
|
+
}
|
|
552
|
+
setCalendarMonth(dateVal);
|
|
553
|
+
setPendingDate(dateVal);
|
|
554
|
+
setPendingTime(dateToTimeValue(dateVal));
|
|
555
|
+
};
|
|
332
556
|
const handleDateSelect = (selected) => {
|
|
333
557
|
if (!selected) return;
|
|
334
558
|
setCalendarMonth(selected);
|
|
335
559
|
if (showTime || needConfirm) {
|
|
336
560
|
setPendingDate(selected);
|
|
337
|
-
|
|
338
|
-
commitValue(selected);
|
|
339
|
-
setOpen(false);
|
|
340
|
-
onOpenChange?.(false);
|
|
561
|
+
return;
|
|
341
562
|
}
|
|
563
|
+
commitValue(selected);
|
|
564
|
+
setOpen(false);
|
|
342
565
|
};
|
|
343
566
|
const handleRangeSelect = (range) => {
|
|
344
567
|
if (!range) return;
|
|
@@ -347,34 +570,29 @@ const DatePicker = forwardRef(
|
|
|
347
570
|
if (rangeSelectionStep === "from") {
|
|
348
571
|
setInternalValue([from, null]);
|
|
349
572
|
setRangeSelectionStep("to");
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
onOpenChange?.(false);
|
|
358
|
-
}
|
|
359
|
-
} else if (from) {
|
|
360
|
-
setInternalValue([from, null]);
|
|
573
|
+
return;
|
|
574
|
+
}
|
|
575
|
+
setRangeSelectionStep("from");
|
|
576
|
+
if (from && to) {
|
|
577
|
+
if (showTime || needConfirm) {
|
|
578
|
+
setPendingDate(from);
|
|
579
|
+
return;
|
|
361
580
|
}
|
|
362
|
-
|
|
581
|
+
commitValue([from, to]);
|
|
582
|
+
setOpen(false);
|
|
583
|
+
return;
|
|
363
584
|
}
|
|
364
|
-
|
|
365
|
-
const handleTimeChange = (time) => {
|
|
366
|
-
setPendingTime(time);
|
|
585
|
+
if (from) setInternalValue([from, null]);
|
|
367
586
|
};
|
|
368
587
|
const handleNow = () => {
|
|
369
588
|
const now = toBrowserLocalDate(/* @__PURE__ */ new Date());
|
|
370
589
|
if (showTime || needConfirm) {
|
|
371
590
|
setPendingDate(now);
|
|
372
591
|
setPendingTime(dateToTimeValue(now));
|
|
373
|
-
|
|
374
|
-
commitValue(now);
|
|
375
|
-
setOpen(false);
|
|
376
|
-
onOpenChange?.(false);
|
|
592
|
+
return;
|
|
377
593
|
}
|
|
594
|
+
commitValue(now);
|
|
595
|
+
setOpen(false);
|
|
378
596
|
};
|
|
379
597
|
const handleOk = () => {
|
|
380
598
|
if (pendingDate) {
|
|
@@ -383,40 +601,12 @@ const DatePicker = forwardRef(
|
|
|
383
601
|
onOk?.(finalDate);
|
|
384
602
|
}
|
|
385
603
|
setOpen(false);
|
|
386
|
-
onOpenChange?.(false);
|
|
387
604
|
};
|
|
388
605
|
const handleClear = (e) => {
|
|
389
606
|
e.stopPropagation();
|
|
390
607
|
e.preventDefault();
|
|
391
608
|
commitValue(null);
|
|
392
609
|
};
|
|
393
|
-
useLayoutEffect(() => {
|
|
394
|
-
if (cursorPosRef.current !== null && inputRef.current && document.activeElement === inputRef.current) {
|
|
395
|
-
inputRef.current.setSelectionRange(
|
|
396
|
-
cursorPosRef.current,
|
|
397
|
-
cursorPosRef.current
|
|
398
|
-
);
|
|
399
|
-
cursorPosRef.current = null;
|
|
400
|
-
}
|
|
401
|
-
});
|
|
402
|
-
const singleDateLen = useMemo(
|
|
403
|
-
() => buildMaskTemplate(displayFormat).pattern.length,
|
|
404
|
-
[displayFormat]
|
|
405
|
-
);
|
|
406
|
-
const parseAndApplyRange = (text) => {
|
|
407
|
-
const parts = text.split(" - ");
|
|
408
|
-
if (!isDatePartComplete(parts[0] ?? "", maskEnabled, singleDateLen))
|
|
409
|
-
return;
|
|
410
|
-
const from = parseDate(parts[0], displayFormat);
|
|
411
|
-
if (from) setCalendarMonth(from);
|
|
412
|
-
const range = parseRangeText(
|
|
413
|
-
text,
|
|
414
|
-
displayFormat,
|
|
415
|
-
maskEnabled,
|
|
416
|
-
singleDateLen
|
|
417
|
-
);
|
|
418
|
-
if (range) commitValue(range);
|
|
419
|
-
};
|
|
420
610
|
const handleInputChange = (e) => {
|
|
421
611
|
let text = e.target.value;
|
|
422
612
|
if (maskTemplate) {
|
|
@@ -442,12 +632,18 @@ const DatePicker = forwardRef(
|
|
|
442
632
|
if (showTime || needConfirm) {
|
|
443
633
|
setPendingDate(parsed);
|
|
444
634
|
setPendingTime(dateToTimeValue(parsed));
|
|
445
|
-
|
|
446
|
-
commitValue(parsed);
|
|
635
|
+
return;
|
|
447
636
|
}
|
|
637
|
+
commitValue(parsed);
|
|
448
638
|
};
|
|
449
639
|
const handleInputKeyDown = (e) => {
|
|
450
|
-
if (e.key === "Escape")
|
|
640
|
+
if (e.key === "Escape") {
|
|
641
|
+
setPendingDate(null);
|
|
642
|
+
setPendingTime(INITIAL_TIME_VALUE);
|
|
643
|
+
setInputText(getDisplayText());
|
|
644
|
+
setOpen(false);
|
|
645
|
+
return;
|
|
646
|
+
}
|
|
451
647
|
if (e.key !== "Enter") return;
|
|
452
648
|
if (type === "range") {
|
|
453
649
|
const range = parseRangeText(
|
|
@@ -462,31 +658,61 @@ const DatePicker = forwardRef(
|
|
|
462
658
|
if (parsed) commitValue(parsed);
|
|
463
659
|
}
|
|
464
660
|
setOpen(false);
|
|
465
|
-
onOpenChange?.(false);
|
|
466
661
|
};
|
|
467
|
-
const
|
|
468
|
-
|
|
662
|
+
const handleInputBlur = (e) => {
|
|
663
|
+
const next = e.relatedTarget;
|
|
664
|
+
if (next && containerRef.current?.contains(next)) return;
|
|
665
|
+
const popoverEl = document.getElementById(popoverContentId);
|
|
666
|
+
if (next && popoverEl?.contains(next)) return;
|
|
667
|
+
onBlur?.(e);
|
|
469
668
|
};
|
|
669
|
+
useEffect(() => {
|
|
670
|
+
if (!open) setInputText(getDisplayText());
|
|
671
|
+
}, [getDisplayText, open]);
|
|
672
|
+
useCursorRestore([{ inputRef, cursorRef: cursorPosRef }]);
|
|
673
|
+
useEffect(() => {
|
|
674
|
+
if (!open || type !== "date") return;
|
|
675
|
+
const dateVal = currentValue;
|
|
676
|
+
if (dateVal instanceof Date) setCalendarMonth(dateVal);
|
|
677
|
+
}, [open]);
|
|
470
678
|
const hasField = !!(label || error || helpText);
|
|
471
679
|
const showFooter = showTime || needConfirm || !!onTimezoneChange;
|
|
472
680
|
const todayDate = toBrowserLocalDate(/* @__PURE__ */ new Date());
|
|
681
|
+
const handleGridPickerSelect = (date) => {
|
|
682
|
+
commitValue(date);
|
|
683
|
+
setOpen(false);
|
|
684
|
+
};
|
|
685
|
+
const handleSingleDateSelectWithPicker = (selected) => {
|
|
686
|
+
if (!selected) return handleDateSelect(void 0);
|
|
687
|
+
handleDateSelect(
|
|
688
|
+
picker === "week" ? startOfWeek(selected, weekStartsOn) : selected
|
|
689
|
+
);
|
|
690
|
+
};
|
|
691
|
+
const weekHighlightProps = (() => {
|
|
692
|
+
if (picker !== "week" || type !== "date" || !currentValue) return {};
|
|
693
|
+
const weekStart = startOfWeek(currentValue, weekStartsOn);
|
|
694
|
+
const weekDays = weekDaysFrom(weekStart);
|
|
695
|
+
return {
|
|
696
|
+
modifiers: {
|
|
697
|
+
weekStart: [weekDays[0]],
|
|
698
|
+
weekMiddle: weekDays.slice(1, 6),
|
|
699
|
+
weekEnd: [weekDays[6]]
|
|
700
|
+
},
|
|
701
|
+
modifiersClassNames: {
|
|
702
|
+
weekStart: "!bg-primary !text-primary-foreground !rounded-e-none hover:!bg-primary",
|
|
703
|
+
weekMiddle: "!bg-primary !text-primary-foreground !rounded-none hover:!bg-primary",
|
|
704
|
+
weekEnd: "!bg-primary !text-primary-foreground !rounded-s-none hover:!bg-primary"
|
|
705
|
+
}
|
|
706
|
+
};
|
|
707
|
+
})();
|
|
708
|
+
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;
|
|
473
709
|
const ariaDescribedBy = [error ? errorId : null, helpText ? helpTextId : null].filter(Boolean).join(" ") || void 0;
|
|
474
|
-
const
|
|
475
|
-
(date) => {
|
|
476
|
-
if (minDate && date < new Date(minDate.setHours(0, 0, 0, 0)))
|
|
477
|
-
return true;
|
|
478
|
-
if (maxDate && date > new Date(maxDate.setHours(23, 59, 59, 999)))
|
|
479
|
-
return true;
|
|
480
|
-
return false;
|
|
481
|
-
},
|
|
482
|
-
[minDate, maxDate]
|
|
483
|
-
);
|
|
484
|
-
const calendarSelected = useCallback(() => {
|
|
710
|
+
const calendarSelected = () => {
|
|
485
711
|
if (showTime || needConfirm) return pendingDate ?? void 0;
|
|
486
712
|
return currentValue ?? void 0;
|
|
487
|
-
}
|
|
488
|
-
const triggerContent = /* @__PURE__ */ jsxs(Popover, { open, children: [
|
|
489
|
-
/* @__PURE__ */ jsx(PopoverAnchor, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
713
|
+
};
|
|
714
|
+
const triggerContent = /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: trigger ? setOpen : void 0, children: [
|
|
715
|
+
trigger ? /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: trigger }) : /* @__PURE__ */ jsx(PopoverAnchor, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
490
716
|
"div",
|
|
491
717
|
{
|
|
492
718
|
ref: containerRef,
|
|
@@ -502,7 +728,10 @@ const DatePicker = forwardRef(
|
|
|
502
728
|
/* @__PURE__ */ jsx(
|
|
503
729
|
Calendar,
|
|
504
730
|
{
|
|
505
|
-
className: cn(
|
|
731
|
+
className: cn(
|
|
732
|
+
"shrink-0 text-muted-foreground",
|
|
733
|
+
sizeConfig.icon
|
|
734
|
+
)
|
|
506
735
|
}
|
|
507
736
|
),
|
|
508
737
|
/* @__PURE__ */ jsx(
|
|
@@ -518,7 +747,10 @@ const DatePicker = forwardRef(
|
|
|
518
747
|
value: inputText,
|
|
519
748
|
onChange: handleInputChange,
|
|
520
749
|
onKeyDown: handleInputKeyDown,
|
|
521
|
-
onFocus:
|
|
750
|
+
onFocus: () => {
|
|
751
|
+
if (!open) openPopover();
|
|
752
|
+
},
|
|
753
|
+
onBlur: handleInputBlur,
|
|
522
754
|
className: cn(
|
|
523
755
|
"min-w-0 flex-1 bg-transparent outline-none placeholder:text-muted-foreground",
|
|
524
756
|
"disabled:cursor-not-allowed",
|
|
@@ -550,14 +782,35 @@ const DatePicker = forwardRef(
|
|
|
550
782
|
{
|
|
551
783
|
id: popoverContentId,
|
|
552
784
|
className: "w-auto p-0",
|
|
553
|
-
align
|
|
785
|
+
align,
|
|
786
|
+
side,
|
|
554
787
|
onOpenAutoFocus: (e) => e.preventDefault(),
|
|
555
788
|
onCloseAutoFocus: (e) => e.preventDefault(),
|
|
556
789
|
onPointerDownOutside: (e) => e.preventDefault(),
|
|
557
790
|
onInteractOutside: (e) => e.preventDefault(),
|
|
558
791
|
children: [
|
|
559
792
|
/* @__PURE__ */ jsxs("div", { className: cn("flex", showTime && "flex-row"), children: [
|
|
560
|
-
type === "date" ? /* @__PURE__ */ jsx(
|
|
793
|
+
type === "date" && picker === "month" ? /* @__PURE__ */ jsx(
|
|
794
|
+
MonthPicker,
|
|
795
|
+
{
|
|
796
|
+
value: currentValue ?? null,
|
|
797
|
+
displayedYear: calendarMonth.getFullYear(),
|
|
798
|
+
onYearChange: (year) => setCalendarMonth(
|
|
799
|
+
new Date(year, calendarMonth.getMonth(), 1)
|
|
800
|
+
),
|
|
801
|
+
onSelect: handleGridPickerSelect,
|
|
802
|
+
isDisabled: (date) => isMonthDisabled(date, minDate, maxDate)
|
|
803
|
+
}
|
|
804
|
+
) : type === "date" && picker === "year" ? /* @__PURE__ */ jsx(
|
|
805
|
+
YearPicker,
|
|
806
|
+
{
|
|
807
|
+
value: currentValue ?? null,
|
|
808
|
+
displayedYear: calendarMonth.getFullYear(),
|
|
809
|
+
onYearChange: (year) => setCalendarMonth(new Date(year, 0, 1)),
|
|
810
|
+
onSelect: handleGridPickerSelect,
|
|
811
|
+
isDisabled: (date) => isYearDisabled(date, minDate, maxDate)
|
|
812
|
+
}
|
|
813
|
+
) : type === "date" ? /* @__PURE__ */ jsx(
|
|
561
814
|
Calendar$1,
|
|
562
815
|
{
|
|
563
816
|
mode: "single",
|
|
@@ -566,8 +819,11 @@ const DatePicker = forwardRef(
|
|
|
566
819
|
month: calendarMonth,
|
|
567
820
|
onMonthChange: setCalendarMonth,
|
|
568
821
|
selected: calendarSelected(),
|
|
569
|
-
onSelect:
|
|
822
|
+
onSelect: handleSingleDateSelectWithPicker,
|
|
570
823
|
disabled: calendarDisabled,
|
|
824
|
+
weekStartsOn,
|
|
825
|
+
classNames: weekRowHoverClassName ? { week: cn("mt-2 flex w-full", weekRowHoverClassName) } : void 0,
|
|
826
|
+
...weekHighlightProps,
|
|
571
827
|
...minDate && { fromDate: minDate },
|
|
572
828
|
...maxDate && { toDate: maxDate }
|
|
573
829
|
}
|
|
@@ -578,6 +834,7 @@ const DatePicker = forwardRef(
|
|
|
578
834
|
numberOfMonths: 2,
|
|
579
835
|
captionLayout: "dropdown",
|
|
580
836
|
today: todayDate,
|
|
837
|
+
weekStartsOn,
|
|
581
838
|
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",
|
|
582
839
|
month: calendarMonth,
|
|
583
840
|
onMonthChange: setCalendarMonth,
|
|
@@ -595,7 +852,7 @@ const DatePicker = forwardRef(
|
|
|
595
852
|
TimePickerPanel,
|
|
596
853
|
{
|
|
597
854
|
value: pendingTime,
|
|
598
|
-
onChange:
|
|
855
|
+
onChange: setPendingTime,
|
|
599
856
|
format: timePickerFormat,
|
|
600
857
|
showSeconds,
|
|
601
858
|
disabled
|
|
@@ -651,4 +908,4 @@ const DatePicker = forwardRef(
|
|
|
651
908
|
DatePicker.displayName = "DatePicker";
|
|
652
909
|
|
|
653
910
|
export { DatePicker as D };
|
|
654
|
-
//# sourceMappingURL=DatePicker-
|
|
911
|
+
//# sourceMappingURL=DatePicker-kulToqfM.js.map
|