@bigbinary/neeto-atoms 1.0.60 → 1.0.61

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.
Files changed (77) hide show
  1. package/dist/{DataTable-BTdSpJfs.js → DataTable-DP06B8C7.js} +140 -124
  2. package/dist/{DataTable-BTdSpJfs.js.map → DataTable-DP06B8C7.js.map} +1 -1
  3. package/dist/{DatePicker-kulToqfM.js → DatePicker-mdjh5u40.js} +422 -157
  4. package/dist/DatePicker-mdjh5u40.js.map +1 -0
  5. package/dist/{Input-Bxs8n6xp.js → Input-B7twzkUr.js} +5 -3
  6. package/dist/Input-B7twzkUr.js.map +1 -0
  7. package/dist/{Pagination-C_X9kgc8.js → Pagination-BRd3WPJ_.js} +15 -4
  8. package/dist/Pagination-BRd3WPJ_.js.map +1 -0
  9. package/dist/{Select-BiyQTuiQ.js → Select-Zr8sFnAC.js} +46 -14
  10. package/dist/Select-Zr8sFnAC.js.map +1 -0
  11. package/dist/cjs/{DataTable-CCIIXb4B.js → DataTable-CXjAvPHV.js} +140 -124
  12. package/dist/cjs/{DataTable-CCIIXb4B.js.map → DataTable-CXjAvPHV.js.map} +1 -1
  13. package/dist/cjs/{DatePicker-BZd4rM2R.js → DatePicker-DpyYPJfR.js} +420 -155
  14. package/dist/cjs/DatePicker-DpyYPJfR.js.map +1 -0
  15. package/dist/cjs/{Input-BQh-GS_w.js → Input-Dwl5OhCq.js} +5 -3
  16. package/dist/cjs/Input-Dwl5OhCq.js.map +1 -0
  17. package/dist/cjs/{Pagination-DeWfLAq5.js → Pagination-8yFg8xR2.js} +15 -4
  18. package/dist/cjs/Pagination-8yFg8xR2.js.map +1 -0
  19. package/dist/cjs/{Select-DC23xcMU.js → Select-BJs-J8fs.js} +45 -13
  20. package/dist/cjs/Select-BJs-J8fs.js.map +1 -0
  21. package/dist/cjs/components/DataTable.js +1 -1
  22. package/dist/cjs/components/DatePicker.js +9 -9
  23. package/dist/cjs/components/Input.js +1 -1
  24. package/dist/cjs/components/Pagination.js +2 -1
  25. package/dist/cjs/components/Pagination.js.map +1 -1
  26. package/dist/cjs/components/Select.js +2 -2
  27. package/dist/cjs/components/index.js +5 -5
  28. package/dist/cjs/formik/ActionBlock.js +10 -4
  29. package/dist/cjs/formik/ActionBlock.js.map +1 -1
  30. package/dist/cjs/formik/Input.js +1 -1
  31. package/dist/cjs/formik/Select.js +2 -2
  32. package/dist/cjs/formik/index.js +3 -3
  33. package/dist/cjs/index.js +5 -5
  34. package/dist/cjs/primitives/Combobox.js +14 -2
  35. package/dist/cjs/primitives/Combobox.js.map +1 -1
  36. package/dist/components/DataTable/DataTable.d.ts +1 -1
  37. package/dist/components/DataTable/types.d.ts +1 -0
  38. package/dist/components/DataTable.js +1 -1
  39. package/dist/components/DatePicker/DatePickerField.d.ts +15 -0
  40. package/dist/components/DatePicker/DatePickerTrigger.d.ts +25 -0
  41. package/dist/components/DatePicker/RangeCalendar.d.ts +17 -0
  42. package/dist/components/DatePicker/types.d.ts +3 -3
  43. package/dist/components/DatePicker/useRangePicker.d.ts +28 -0
  44. package/dist/components/DatePicker/utils.d.ts +15 -0
  45. package/dist/components/DatePicker.js +9 -9
  46. package/dist/components/Input.js +1 -1
  47. package/dist/components/Pagination/Pagination.d.ts +5 -1
  48. package/dist/components/Pagination/hooks/usePaginationQueryParams.d.ts +11 -0
  49. package/dist/components/Pagination.js +2 -1
  50. package/dist/components/Pagination.js.map +1 -1
  51. package/dist/components/Select/MultiSelectCombobox.types.d.ts +1 -0
  52. package/dist/components/Select/MultiSelectDropdown.d.ts +2 -2
  53. package/dist/components/Select/OptionItem.d.ts +3 -2
  54. package/dist/components/Select/SelectCombobox.types.d.ts +2 -0
  55. package/dist/components/Select/hooks/useMultiSelectState.d.ts +3 -1
  56. package/dist/components/Select/hooks/useSelectState.d.ts +3 -1
  57. package/dist/components/Select/types.d.ts +7 -0
  58. package/dist/components/Select.js +2 -2
  59. package/dist/components/index.js +5 -5
  60. package/dist/formik/ActionBlock.js +10 -4
  61. package/dist/formik/ActionBlock.js.map +1 -1
  62. package/dist/formik/Input.js +1 -1
  63. package/dist/formik/Select.js +2 -2
  64. package/dist/formik/index.js +3 -3
  65. package/dist/index.js +5 -5
  66. package/dist/primitives/Combobox.d.ts +1 -1
  67. package/dist/primitives/Combobox.js +14 -2
  68. package/dist/primitives/Combobox.js.map +1 -1
  69. package/package.json +1 -1
  70. package/dist/DatePicker-kulToqfM.js.map +0 -1
  71. package/dist/Input-Bxs8n6xp.js.map +0 -1
  72. package/dist/Pagination-C_X9kgc8.js.map +0 -1
  73. package/dist/Select-BiyQTuiQ.js.map +0 -1
  74. package/dist/cjs/DatePicker-BZd4rM2R.js.map +0 -1
  75. package/dist/cjs/Input-BQh-GS_w.js.map +0 -1
  76. package/dist/cjs/Pagination-DeWfLAq5.js.map +0 -1
  77. package/dist/cjs/Select-DC23xcMU.js.map +0 -1
@@ -1,18 +1,18 @@
1
1
  import { jsxs, jsx } from 'react/jsx-runtime';
2
- import { forwardRef, useId, useRef, useState, useMemo, useCallback, useEffect } from 'react';
2
+ import { forwardRef, useState, useCallback, useMemo, useId, useRef, useEffect } from 'react';
3
3
  import { Calendar as Calendar$1 } from './primitives/Calendar.js';
4
- import { Popover, PopoverTrigger, PopoverAnchor, PopoverContent } from './primitives/Popover.js';
5
- import { Field, FieldLabel, FieldContent, FieldError, FieldDescription } from './primitives/Field.js';
4
+ import { PopoverAnchor, Popover, PopoverTrigger, PopoverContent } from './primitives/Popover.js';
6
5
  import { c as cn } from './utils-BJnb9o5c.js';
7
6
  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';
8
7
  import pureDayjs from 'dayjs';
9
8
  import customParseFormat from 'dayjs/plugin/customParseFormat';
10
9
  import { dayjs } from '@bigbinary/neeto-commons-frontend/utils';
11
10
  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';
11
+ import { Field, FieldLabel, FieldContent, FieldError, FieldDescription } from './primitives/Field.js';
14
12
  import { c as createLucideIcon } from './createLucideIcon-C8ycilSN.js';
15
13
  import { X } from './x-_o2T3n6D.js';
14
+ import { C as ChevronLeft } from './chevron-left-BDoT8E2-.js';
15
+ import { C as ChevronRight } from './chevron-right-DQnrO-ek.js';
16
16
 
17
17
  /**
18
18
  * @license lucide-react v0.577.0 - ISC
@@ -86,6 +86,12 @@ const coerceDateValue = (value, type) => {
86
86
  }
87
87
  return toNativeDate(value);
88
88
  };
89
+ const getInitialCalendarMonth = (value, defaultValue, type) => {
90
+ const initial = coerceDateValue(value ?? defaultValue, type);
91
+ if (initial instanceof Date) return initial;
92
+ if (Array.isArray(initial) && initial[0] instanceof Date) return initial[0];
93
+ return /* @__PURE__ */ new Date();
94
+ };
89
95
  const normalizeToDayjsFormat = (fmt) => fmt.replace(/\byyyy\b/g, "YYYY").replace(/\byy\b/g, "YY").replace(/\bdd\b/g, "DD").replace(/\bd\b/g, "D");
90
96
  const normalizeToDateFnsFormat = (fmt) => fmt.replace(/YYYY/g, "yyyy").replace(/YY/g, "yy").replace(/DD/g, "dd").replace(/\bD\b/g, "d");
91
97
  const formatDate = (date, formatStr) => {
@@ -121,11 +127,7 @@ const applyTimeToDate = (date, time) => {
121
127
  result.setHours(time.hours, time.minutes, time.seconds ?? 0, 0);
122
128
  return result;
123
129
  };
124
- const applyTimezone = (date) => {
125
- const dateStr = pureDayjs(date).format("YYYY-MM-DD HH:mm:ss");
126
- return dayjs(dateStr).toDate();
127
- };
128
- const toDayjs = (date) => dayjs(date);
130
+ const toUserTzDayjs = (date) => dayjs(pureDayjs(date).format("YYYY-MM-DD HH:mm:ss"));
129
131
  const getDisplayFormat = (dateFormat, timeFormat, showTime) => {
130
132
  const fmt = showTime ? `${dateFormat} ${timeFormat}` : dateFormat;
131
133
  return normalizeToDateFnsFormat(fmt);
@@ -180,6 +182,34 @@ const isYearDisabled = (yearDate, minDate, maxDate) => {
180
182
  };
181
183
  const buildMonth = (year, month) => new Date(year, month, 1);
182
184
  const isSameMonth = (a, b) => !!a && a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth();
185
+ const isSameDay = (a, b) => !!a && !!b && a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
186
+ const orderRange = (from, to) => {
187
+ if (from && to && from.getTime() > to.getTime()) return [to, from];
188
+ return [from, to];
189
+ };
190
+ const parseGridcellDay = (target) => {
191
+ const el = target;
192
+ const cell = el?.closest('[role="gridcell"][data-day]');
193
+ const dayAttr = cell?.getAttribute("data-day");
194
+ if (!dayAttr) return null;
195
+ const parsed = new Date(dayAttr);
196
+ return Number.isNaN(parsed.getTime()) ? null : parsed;
197
+ };
198
+ const computeRangePreview = ({
199
+ pendingRange,
200
+ committed,
201
+ hoveredDate,
202
+ rangeStep
203
+ }) => {
204
+ let from = pendingRange ? pendingRange[0] : committed?.[0] ?? null;
205
+ let to = pendingRange ? pendingRange[1] : committed?.[1] ?? null;
206
+ if (hoveredDate) {
207
+ if (rangeStep === "from") from = hoveredDate;
208
+ else if (!isSameDay(from, hoveredDate)) to = hoveredDate;
209
+ }
210
+ [from, to] = orderRange(from, to);
211
+ return { from, to };
212
+ };
183
213
  const decadeStartFor = (year) => Math.floor(year / 10) * 10;
184
214
 
185
215
  const TIMEZONE_OPTIONS = [
@@ -243,6 +273,136 @@ const DatePickerFooter = ({
243
273
  };
244
274
  DatePickerFooter.displayName = "DatePickerFooter";
245
275
 
276
+ const DatePickerField = forwardRef(
277
+ ({
278
+ disabled,
279
+ error,
280
+ className,
281
+ label,
282
+ required,
283
+ helpText,
284
+ labelProps,
285
+ errorId,
286
+ helpTextId,
287
+ children
288
+ }, ref) => /* @__PURE__ */ jsxs(
289
+ Field,
290
+ {
291
+ ref,
292
+ "data-disabled": disabled || void 0,
293
+ "data-invalid": !!error || void 0,
294
+ className,
295
+ children: [
296
+ label && /* @__PURE__ */ jsxs(
297
+ FieldLabel,
298
+ {
299
+ ...labelProps,
300
+ children: [
301
+ label,
302
+ required && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "text-destructive", children: "*" })
303
+ ]
304
+ }
305
+ ),
306
+ /* @__PURE__ */ jsxs(FieldContent, { children: [
307
+ children,
308
+ !!error && /* @__PURE__ */ jsx(FieldError, { id: errorId, children: error }),
309
+ helpText && /* @__PURE__ */ jsx(FieldDescription, { id: helpTextId, children: helpText })
310
+ ] })
311
+ ]
312
+ }
313
+ )
314
+ );
315
+ DatePickerField.displayName = "DatePickerField";
316
+
317
+ const DatePickerTrigger = forwardRef(
318
+ ({
319
+ containerRef,
320
+ inputRef,
321
+ disabled,
322
+ error,
323
+ hasField,
324
+ className,
325
+ triggerSizeClass,
326
+ inputSizeClass,
327
+ iconSizeClass,
328
+ label,
329
+ ariaDescribedBy,
330
+ placeholder,
331
+ inputText,
332
+ allowClear,
333
+ timezone,
334
+ onInputChange,
335
+ onInputKeyDown,
336
+ onInputFocus,
337
+ onInputBlur,
338
+ onClear
339
+ }, _ref) => /* @__PURE__ */ jsx(PopoverAnchor, { asChild: true, children: /* @__PURE__ */ jsxs(
340
+ "div",
341
+ {
342
+ ref: containerRef,
343
+ className: cn(
344
+ "relative flex w-full cursor-text items-center gap-2 rounded-md border border-input bg-background pe-8 ps-3",
345
+ "focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2",
346
+ disabled && "cursor-not-allowed opacity-50",
347
+ !!error && "border-destructive ring-destructive/20 ring-3",
348
+ triggerSizeClass,
349
+ !hasField && className
350
+ ),
351
+ onClick: () => {
352
+ if (disabled) return;
353
+ inputRef.current?.focus();
354
+ },
355
+ children: [
356
+ /* @__PURE__ */ jsx(
357
+ Calendar,
358
+ {
359
+ className: cn("shrink-0 text-muted-foreground", iconSizeClass)
360
+ }
361
+ ),
362
+ /* @__PURE__ */ jsx(
363
+ "input",
364
+ {
365
+ ref: inputRef,
366
+ type: "text",
367
+ disabled,
368
+ "aria-label": label || "Pick a date",
369
+ "aria-describedby": ariaDescribedBy,
370
+ "aria-invalid": !!error || void 0,
371
+ placeholder,
372
+ value: inputText,
373
+ onChange: onInputChange,
374
+ onKeyDown: onInputKeyDown,
375
+ onFocus: onInputFocus,
376
+ onBlur: onInputBlur,
377
+ className: cn(
378
+ "min-w-0 flex-1 bg-transparent outline-none placeholder:text-muted-foreground",
379
+ "disabled:cursor-not-allowed",
380
+ inputSizeClass
381
+ )
382
+ }
383
+ ),
384
+ timezone && /* @__PURE__ */ jsx("span", { className: "shrink-0 rounded bg-muted px-1.5 py-0.5 text-xs text-muted-foreground", children: timezone.toUpperCase() }),
385
+ allowClear && /* @__PURE__ */ jsx(
386
+ "button",
387
+ {
388
+ type: "button",
389
+ onPointerDown: (e) => e.preventDefault(),
390
+ onClick: onClear,
391
+ className: cn(
392
+ "absolute inset-y-0 end-2 flex items-center text-muted-foreground hover:text-foreground focus:outline-none",
393
+ !(inputText && !disabled) && "invisible"
394
+ ),
395
+ "aria-label": "Clear date",
396
+ tabIndex: -1,
397
+ children: /* @__PURE__ */ jsx(X, { className: iconSizeClass })
398
+ }
399
+ )
400
+ ]
401
+ }
402
+ ) })
403
+ );
404
+ DatePickerTrigger.displayName = "DatePickerTrigger";
405
+
246
406
  const MonthPicker = ({
247
407
  value,
248
408
  displayedYear,
@@ -303,6 +463,129 @@ const MonthPicker = ({
303
463
  ] });
304
464
  };
305
465
 
466
+ const RangeCalendar = ({
467
+ todayDate,
468
+ weekStartsOn,
469
+ month,
470
+ onMonthChange,
471
+ selected,
472
+ onSelect,
473
+ disabled,
474
+ fromDate,
475
+ toDate,
476
+ onHoverIn,
477
+ onHoverOut
478
+ }) => /* @__PURE__ */ jsx("div", { onMouseOver: onHoverIn, onMouseLeave: onHoverOut, children: /* @__PURE__ */ jsx(
479
+ Calendar$1,
480
+ {
481
+ mode: "range",
482
+ numberOfMonths: 2,
483
+ captionLayout: "dropdown",
484
+ today: todayDate,
485
+ weekStartsOn,
486
+ 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",
487
+ month,
488
+ onMonthChange,
489
+ selected,
490
+ onSelect,
491
+ disabled,
492
+ ...fromDate && { fromDate },
493
+ ...toDate && { toDate }
494
+ }
495
+ ) });
496
+
497
+ const useRangePicker = ({
498
+ currentValue,
499
+ showTime,
500
+ needConfirm,
501
+ commitValue,
502
+ setPendingDate,
503
+ setOpen
504
+ }) => {
505
+ const [pendingRange, setPendingRange] = useState(null);
506
+ const [rangeSelectionStep, setRangeSelectionStep] = useState(
507
+ "from"
508
+ );
509
+ const [hoveredDate, setHoveredDate] = useState(null);
510
+ const committed = currentValue ?? null;
511
+ const resetTransientState = useCallback(() => {
512
+ setPendingRange(null);
513
+ setRangeSelectionStep("from");
514
+ setHoveredDate(null);
515
+ }, []);
516
+ const handleRangeSelect = useCallback(
517
+ (_range, triggerDate) => {
518
+ if (!triggerDate) return;
519
+ if (rangeSelectionStep === "from" || !pendingRange?.[0]) {
520
+ const existingTo = pendingRange?.[1] ?? committed?.[1] ?? null;
521
+ const nextTo = existingTo && triggerDate <= existingTo ? existingTo : null;
522
+ setPendingRange([triggerDate, nextTo]);
523
+ setRangeSelectionStep("to");
524
+ return;
525
+ }
526
+ const [from, to] = orderRange(pendingRange[0], triggerDate);
527
+ setRangeSelectionStep("from");
528
+ setPendingRange(null);
529
+ if (showTime || needConfirm) {
530
+ setPendingDate(from);
531
+ return;
532
+ }
533
+ commitValue([from, to]);
534
+ setOpen(false);
535
+ },
536
+ [
537
+ rangeSelectionStep,
538
+ pendingRange,
539
+ committed,
540
+ showTime,
541
+ needConfirm,
542
+ commitValue,
543
+ setPendingDate,
544
+ setOpen
545
+ ]
546
+ );
547
+ const handleHoverIn = useCallback(
548
+ (e) => {
549
+ const parsed = parseGridcellDay(e.target);
550
+ if (!parsed) return;
551
+ if (hoveredDate && hoveredDate.getTime() === parsed.getTime()) return;
552
+ setHoveredDate(parsed);
553
+ },
554
+ [hoveredDate]
555
+ );
556
+ const handleHoverOut = useCallback(() => setHoveredDate(null), []);
557
+ const memoizedRangeSelected = useMemo(() => {
558
+ const { from, to } = computeRangePreview({
559
+ pendingRange,
560
+ committed,
561
+ hoveredDate,
562
+ rangeStep: rangeSelectionStep
563
+ });
564
+ if (!from && !to) return void 0;
565
+ return { from: from ?? void 0, to: to ?? void 0 };
566
+ }, [pendingRange, committed, hoveredDate, rangeSelectionStep]);
567
+ const getPreviewParts = useCallback(
568
+ () => computeRangePreview({
569
+ pendingRange,
570
+ committed,
571
+ hoveredDate,
572
+ rangeStep: rangeSelectionStep
573
+ }),
574
+ [pendingRange, committed, hoveredDate, rangeSelectionStep]
575
+ );
576
+ return {
577
+ pendingRange,
578
+ rangeSelectionStep,
579
+ hoveredDate,
580
+ handleRangeSelect,
581
+ handleHoverIn,
582
+ handleHoverOut,
583
+ memoizedRangeSelected,
584
+ getPreviewParts,
585
+ resetTransientState
586
+ };
587
+ };
588
+
306
589
  const YearPicker = ({
307
590
  value,
308
591
  displayedYear,
@@ -418,14 +701,22 @@ const DatePicker = forwardRef(
418
701
  coerceDateValue(defaultValue, type) ?? null
419
702
  );
420
703
  const [calendarMonth, setCalendarMonth] = useState(
421
- (type === "date" ? value ?? defaultValue : null) ?? /* @__PURE__ */ new Date()
422
- );
423
- const [rangeSelectionStep, setRangeSelectionStep] = useState(
424
- "from"
704
+ () => getInitialCalendarMonth(value, defaultValue, type)
425
705
  );
426
706
  const [pendingDate, setPendingDate] = useState(null);
427
707
  const [pendingTime, setPendingTime] = useState(INITIAL_TIME_VALUE);
428
- const currentValue = value !== void 0 ? coerceDateValue(value, type) : internalValue;
708
+ const currentValue = useMemo(
709
+ () => value !== void 0 ? coerceDateValue(value, type) : internalValue,
710
+ [value, type, internalValue]
711
+ );
712
+ const normalizedMinDate = useMemo(
713
+ () => toNativeDate(minDate) ?? void 0,
714
+ [minDate]
715
+ );
716
+ const normalizedMaxDate = useMemo(
717
+ () => toNativeDate(maxDate) ?? void 0,
718
+ [maxDate]
719
+ );
429
720
  const displayFormat = getDisplayFormat(dateFormat, timeFormat, showTime);
430
721
  const sizeConfig = SIZE_CONFIG[size];
431
722
  const maskEnabled = isFixedWidthFormat(displayFormat);
@@ -446,13 +737,13 @@ const DatePicker = forwardRef(
446
737
  const calendarDisabled = useCallback(
447
738
  (date) => {
448
739
  if (disabledDate?.(date)) return true;
449
- if (minDate && date < new Date(new Date(minDate).setHours(0, 0, 0, 0)))
740
+ if (normalizedMinDate && date < new Date(new Date(normalizedMinDate).setHours(0, 0, 0, 0)))
450
741
  return true;
451
- if (maxDate && date > new Date(new Date(maxDate).setHours(23, 59, 59, 999)))
742
+ if (normalizedMaxDate && date > new Date(new Date(normalizedMaxDate).setHours(23, 59, 59, 999)))
452
743
  return true;
453
744
  return false;
454
745
  },
455
- [minDate, maxDate, disabledDate]
746
+ [normalizedMinDate, normalizedMaxDate, disabledDate]
456
747
  );
457
748
  const getDisplayText = useCallback(() => {
458
749
  if (type !== "range") {
@@ -468,36 +759,73 @@ const DatePicker = forwardRef(
468
759
  const commitValue = (date) => {
469
760
  if (date === null) {
470
761
  setInternalValue(null);
471
- onChange?.(null, "");
762
+ if (type === "range") {
763
+ onChange?.([null, null], ["", ""]);
764
+ } else {
765
+ onChange?.(null, "");
766
+ }
472
767
  setInputText("");
473
768
  return;
474
769
  }
770
+ const toSerializableDayjs = (d) => {
771
+ const userTzDayjs = toUserTzDayjs(d);
772
+ if (showTime) return userTzDayjs;
773
+ return userTzDayjs.hour(12).minute(0).second(0).millisecond(0);
774
+ };
475
775
  if (Array.isArray(date)) {
476
776
  setInternalValue(date);
477
- const converted2 = [
478
- applyTimezone(date[0]),
479
- applyTimezone(date[1])
480
- ];
481
777
  const formatted2 = [
482
778
  formatDate(date[0], displayFormat),
483
779
  formatDate(date[1], displayFormat)
484
780
  ];
485
- onChange?.([toDayjs(converted2[0]), toDayjs(converted2[1])], formatted2);
781
+ onChange?.(
782
+ [toSerializableDayjs(date[0]), toSerializableDayjs(date[1])],
783
+ formatted2
784
+ );
486
785
  setInputText(`${formatted2[0]} - ${formatted2[1]}`);
487
786
  return;
488
787
  }
489
788
  setInternalValue(date);
490
- const converted = applyTimezone(date);
491
789
  const formatted = formatDate(date, displayFormat);
492
- onChange?.(toDayjs(converted), formatted);
790
+ onChange?.(toSerializableDayjs(date), formatted);
493
791
  setInputText(formatted);
494
792
  };
495
- const parseAndApplyRange = (text) => {
793
+ const {
794
+ pendingRange,
795
+ handleRangeSelect,
796
+ handleHoverIn,
797
+ handleHoverOut,
798
+ memoizedRangeSelected,
799
+ getPreviewParts,
800
+ resetTransientState
801
+ } = useRangePicker({
802
+ currentValue,
803
+ showTime,
804
+ needConfirm,
805
+ commitValue,
806
+ setPendingDate,
807
+ setOpen
808
+ });
809
+ useEffect(() => {
810
+ if (type !== "range" || !open) return;
811
+ const { from, to } = getPreviewParts();
812
+ const fromText = from ? formatDate(from, displayFormat) : "";
813
+ const toText = to ? formatDate(to, displayFormat) : "";
814
+ setInputText(fromText || toText ? `${fromText} - ${toText}` : "");
815
+ }, [type, open, getPreviewParts, displayFormat]);
816
+ const parseAndApplyRange = (text, cursorPos) => {
496
817
  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);
818
+ const separatorIdx = text.indexOf(" - ");
819
+ const editingTo = separatorIdx >= 0 && cursorPos !== null && cursorPos > separatorIdx + 2;
820
+ if (editingTo) {
821
+ const to = parseDate(parts[1] ?? "", displayFormat);
822
+ if (to) setCalendarMonth(to);
823
+ } else {
824
+ if (!isDatePartComplete(parts[0] ?? "", maskEnabled, singleDateLen))
825
+ return;
826
+ const from = parseDate(parts[0] ?? "", displayFormat);
827
+ if (from) setCalendarMonth(from);
828
+ }
501
829
  const range = parseRangeText(
502
830
  text,
503
831
  displayFormat,
@@ -531,9 +859,20 @@ const DatePicker = forwardRef(
531
859
  onChange
532
860
  ]);
533
861
  const closePopover = useCallback(() => {
534
- commitPendingOnClose();
862
+ if (type === "range" && pendingRange?.[0] && pendingRange?.[1]) {
863
+ commitValue([pendingRange[0], pendingRange[1]]);
864
+ } else {
865
+ commitPendingOnClose();
866
+ }
867
+ resetTransientState();
535
868
  setOpen(false);
536
- }, [commitPendingOnClose, setOpen]);
869
+ }, [
870
+ commitPendingOnClose,
871
+ setOpen,
872
+ type,
873
+ pendingRange,
874
+ resetTransientState
875
+ ]);
537
876
  useOutsideClickClose({
538
877
  enabled: open,
539
878
  containerRef,
@@ -542,7 +881,7 @@ const DatePicker = forwardRef(
542
881
  });
543
882
  const openPopover = () => {
544
883
  setOpen(true);
545
- setRangeSelectionStep("from");
884
+ resetTransientState();
546
885
  const dateVal = type === "date" ? currentValue : null;
547
886
  if (!dateVal) {
548
887
  setPendingDate(null);
@@ -563,27 +902,6 @@ const DatePicker = forwardRef(
563
902
  commitValue(selected);
564
903
  setOpen(false);
565
904
  };
566
- const handleRangeSelect = (range) => {
567
- if (!range) return;
568
- const from = range.from ?? null;
569
- const to = range.to ?? null;
570
- if (rangeSelectionStep === "from") {
571
- setInternalValue([from, null]);
572
- setRangeSelectionStep("to");
573
- return;
574
- }
575
- setRangeSelectionStep("from");
576
- if (from && to) {
577
- if (showTime || needConfirm) {
578
- setPendingDate(from);
579
- return;
580
- }
581
- commitValue([from, to]);
582
- setOpen(false);
583
- return;
584
- }
585
- if (from) setInternalValue([from, null]);
586
- };
587
905
  const handleNow = () => {
588
906
  const now = toBrowserLocalDate(/* @__PURE__ */ new Date());
589
907
  if (showTime || needConfirm) {
@@ -621,7 +939,7 @@ const DatePicker = forwardRef(
621
939
  }
622
940
  setInputText(text);
623
941
  if (type === "range") {
624
- parseAndApplyRange(text);
942
+ parseAndApplyRange(text, e.target.selectionStart);
625
943
  return;
626
944
  }
627
945
  const isComplete = maskTemplate ? text.length >= maskTemplate.pattern.length : true;
@@ -712,71 +1030,33 @@ const DatePicker = forwardRef(
712
1030
  return currentValue ?? void 0;
713
1031
  };
714
1032
  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(
716
- "div",
1033
+ trigger ? /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: trigger }) : /* @__PURE__ */ jsx(
1034
+ DatePickerTrigger,
717
1035
  {
718
- ref: containerRef,
719
- className: cn(
720
- "relative flex w-full items-center gap-2 rounded-md border border-input bg-background pe-8 ps-3",
721
- "focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2",
722
- disabled && "cursor-not-allowed opacity-50",
723
- !!error && "border-destructive ring-destructive/20 ring-3",
724
- sizeConfig.trigger,
725
- !hasField && className
726
- ),
727
- children: [
728
- /* @__PURE__ */ jsx(
729
- Calendar,
730
- {
731
- className: cn(
732
- "shrink-0 text-muted-foreground",
733
- sizeConfig.icon
734
- )
735
- }
736
- ),
737
- /* @__PURE__ */ jsx(
738
- "input",
739
- {
740
- ref: inputRef,
741
- type: "text",
742
- disabled,
743
- "aria-label": label || "Pick a date",
744
- "aria-describedby": ariaDescribedBy,
745
- "aria-invalid": !!error || void 0,
746
- placeholder: placeholder ?? defaultPlaceholder,
747
- value: inputText,
748
- onChange: handleInputChange,
749
- onKeyDown: handleInputKeyDown,
750
- onFocus: () => {
751
- if (!open) openPopover();
752
- },
753
- onBlur: handleInputBlur,
754
- className: cn(
755
- "min-w-0 flex-1 bg-transparent outline-none placeholder:text-muted-foreground",
756
- "disabled:cursor-not-allowed",
757
- sizeConfig.input
758
- )
759
- }
760
- ),
761
- timezone && /* @__PURE__ */ jsx("span", { className: "shrink-0 rounded bg-muted px-1.5 py-0.5 text-xs text-muted-foreground", children: timezone.toUpperCase() }),
762
- allowClear && /* @__PURE__ */ jsx(
763
- "button",
764
- {
765
- type: "button",
766
- onPointerDown: (e) => e.preventDefault(),
767
- onClick: handleClear,
768
- className: cn(
769
- "absolute inset-y-0 end-2 flex items-center text-muted-foreground hover:text-foreground focus:outline-none",
770
- !(inputText && !disabled) && "invisible"
771
- ),
772
- "aria-label": "Clear date",
773
- tabIndex: -1,
774
- children: /* @__PURE__ */ jsx(X, { className: sizeConfig.icon })
775
- }
776
- )
777
- ]
1036
+ containerRef,
1037
+ inputRef,
1038
+ disabled,
1039
+ error,
1040
+ hasField,
1041
+ className,
1042
+ triggerSizeClass: sizeConfig.trigger,
1043
+ inputSizeClass: sizeConfig.input,
1044
+ iconSizeClass: sizeConfig.icon,
1045
+ label,
1046
+ ariaDescribedBy,
1047
+ placeholder: placeholder ?? defaultPlaceholder,
1048
+ inputText,
1049
+ allowClear,
1050
+ timezone,
1051
+ onInputChange: handleInputChange,
1052
+ onInputKeyDown: handleInputKeyDown,
1053
+ onInputFocus: () => {
1054
+ if (!open) openPopover();
1055
+ },
1056
+ onInputBlur: handleInputBlur,
1057
+ onClear: handleClear
778
1058
  }
779
- ) }),
1059
+ ),
780
1060
  open && /* @__PURE__ */ jsxs(
781
1061
  PopoverContent,
782
1062
  {
@@ -799,7 +1079,7 @@ const DatePicker = forwardRef(
799
1079
  new Date(year, calendarMonth.getMonth(), 1)
800
1080
  ),
801
1081
  onSelect: handleGridPickerSelect,
802
- isDisabled: (date) => isMonthDisabled(date, minDate, maxDate)
1082
+ isDisabled: (date) => isMonthDisabled(date, normalizedMinDate, normalizedMaxDate)
803
1083
  }
804
1084
  ) : type === "date" && picker === "year" ? /* @__PURE__ */ jsx(
805
1085
  YearPicker,
@@ -808,7 +1088,7 @@ const DatePicker = forwardRef(
808
1088
  displayedYear: calendarMonth.getFullYear(),
809
1089
  onYearChange: (year) => setCalendarMonth(new Date(year, 0, 1)),
810
1090
  onSelect: handleGridPickerSelect,
811
- isDisabled: (date) => isYearDisabled(date, minDate, maxDate)
1091
+ isDisabled: (date) => isYearDisabled(date, normalizedMinDate, normalizedMaxDate)
812
1092
  }
813
1093
  ) : type === "date" ? /* @__PURE__ */ jsx(
814
1094
  Calendar$1,
@@ -824,28 +1104,23 @@ const DatePicker = forwardRef(
824
1104
  weekStartsOn,
825
1105
  classNames: weekRowHoverClassName ? { week: cn("mt-2 flex w-full", weekRowHoverClassName) } : void 0,
826
1106
  ...weekHighlightProps,
827
- ...minDate && { fromDate: minDate },
828
- ...maxDate && { toDate: maxDate }
1107
+ ...normalizedMinDate && { fromDate: normalizedMinDate },
1108
+ ...normalizedMaxDate && { toDate: normalizedMaxDate }
829
1109
  }
830
1110
  ) : /* @__PURE__ */ jsx(
831
- Calendar$1,
1111
+ RangeCalendar,
832
1112
  {
833
- mode: "range",
834
- numberOfMonths: 2,
835
- captionLayout: "dropdown",
836
- today: todayDate,
1113
+ todayDate,
837
1114
  weekStartsOn,
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",
839
1115
  month: calendarMonth,
840
1116
  onMonthChange: setCalendarMonth,
841
- selected: currentValue ? {
842
- from: currentValue[0] ?? void 0,
843
- to: currentValue[1] ?? void 0
844
- } : void 0,
1117
+ selected: memoizedRangeSelected,
845
1118
  onSelect: handleRangeSelect,
846
1119
  disabled: calendarDisabled,
847
- ...minDate && { fromDate: minDate },
848
- ...maxDate && { toDate: maxDate }
1120
+ fromDate: normalizedMinDate,
1121
+ toDate: normalizedMaxDate,
1122
+ onHoverIn: handleHoverIn,
1123
+ onHoverOut: handleHoverOut
849
1124
  }
850
1125
  ),
851
1126
  showTime && /* @__PURE__ */ jsx("div", { className: "border-inline-start border-border", children: /* @__PURE__ */ jsx(
@@ -877,30 +1152,20 @@ const DatePicker = forwardRef(
877
1152
  if (!hasField) {
878
1153
  return /* @__PURE__ */ jsx("div", { ref, className, children: triggerContent });
879
1154
  }
880
- return /* @__PURE__ */ jsxs(
881
- Field,
1155
+ return /* @__PURE__ */ jsx(
1156
+ DatePickerField,
882
1157
  {
883
1158
  ref,
884
- "data-disabled": disabled || void 0,
885
- "data-invalid": !!error || void 0,
1159
+ disabled,
1160
+ error,
886
1161
  className,
887
- children: [
888
- label && /* @__PURE__ */ jsxs(
889
- FieldLabel,
890
- {
891
- ...labelProps,
892
- children: [
893
- label,
894
- required && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "text-destructive", children: "*" })
895
- ]
896
- }
897
- ),
898
- /* @__PURE__ */ jsxs(FieldContent, { children: [
899
- triggerContent,
900
- !!error && /* @__PURE__ */ jsx(FieldError, { id: errorId, children: error }),
901
- helpText && /* @__PURE__ */ jsx(FieldDescription, { id: helpTextId, children: helpText })
902
- ] })
903
- ]
1162
+ label,
1163
+ required,
1164
+ helpText,
1165
+ labelProps,
1166
+ errorId,
1167
+ helpTextId,
1168
+ children: triggerContent
904
1169
  }
905
1170
  );
906
1171
  }
@@ -908,4 +1173,4 @@ const DatePicker = forwardRef(
908
1173
  DatePicker.displayName = "DatePicker";
909
1174
 
910
1175
  export { DatePicker as D };
911
- //# sourceMappingURL=DatePicker-kulToqfM.js.map
1176
+ //# sourceMappingURL=DatePicker-mdjh5u40.js.map