@kopexa/date-picker 1.2.1 → 1.4.0

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/index.d.mts CHANGED
@@ -4,3 +4,4 @@ export { DatePickerField, DatePickerFieldProps } from './date-picker-field.mjs';
4
4
  export { datePickerMessages } from './date-picker-messages.mjs';
5
5
  export { DatePickerValueChangeDetails, DateValue, parseDate } from '@ark-ui/react/date-picker';
6
6
  import 'react/jsx-runtime';
7
+ import 'react';
package/dist/index.d.ts CHANGED
@@ -4,3 +4,4 @@ export { DatePickerField, DatePickerFieldProps } from './date-picker-field.js';
4
4
  export { datePickerMessages } from './date-picker-messages.js';
5
5
  export { DatePickerValueChangeDetails, DateValue, parseDate } from '@ark-ui/react/date-picker';
6
6
  import 'react/jsx-runtime';
7
+ import 'react';
package/dist/index.js CHANGED
@@ -100,6 +100,11 @@ var datePickerMessages = (0, import_i18n.defineMessages)({
100
100
  id: "date-picker.select_date_and_time",
101
101
  defaultMessage: "Select date and time",
102
102
  description: "Placeholder for date+time input"
103
+ },
104
+ save: {
105
+ id: "date-picker.save",
106
+ defaultMessage: "Save",
107
+ description: "Button to commit the staged date selection (only shown when an onSave callback is provided)"
103
108
  }
104
109
  });
105
110
 
@@ -181,6 +186,55 @@ function XIcon({ className }) {
181
186
  }
182
187
  );
183
188
  }
189
+ function getDatePartOrder(locale) {
190
+ try {
191
+ const fmt = new Intl.DateTimeFormat(locale, {
192
+ day: "2-digit",
193
+ month: "2-digit",
194
+ year: "numeric"
195
+ });
196
+ return fmt.formatToParts(new Date(2024, 0, 1)).filter(
197
+ (p) => p.type === "day" || p.type === "month" || p.type === "year"
198
+ ).map((p) => p.type);
199
+ } catch {
200
+ return ["day", "month", "year"];
201
+ }
202
+ }
203
+ function finalizeDateParts(parts) {
204
+ var _a, _b, _c;
205
+ const day = (_a = parts.day) != null ? _a : 1;
206
+ const month = (_b = parts.month) != null ? _b : 1;
207
+ let year = (_c = parts.year) != null ? _c : (/* @__PURE__ */ new Date()).getFullYear();
208
+ if (year < 100) year = year < 50 ? 2e3 + year : 1900 + year;
209
+ if (month < 1 || month > 12) return void 0;
210
+ if (day < 1 || day > 31) return void 0;
211
+ return { year, month, day };
212
+ }
213
+ function parseLocalizedDate(value, locale) {
214
+ const trimmed = value.trim();
215
+ if (!trimmed) return void 0;
216
+ const order = getDatePartOrder(locale);
217
+ const segments = trimmed.split(/[./\-\s]+/).filter(Boolean);
218
+ if (segments.length === 3 && segments.every((s) => /^\d+$/.test(s))) {
219
+ const map2 = {};
220
+ order.forEach((field, i) => {
221
+ map2[field] = Number.parseInt(segments[i], 10);
222
+ });
223
+ return finalizeDateParts(map2);
224
+ }
225
+ const digits = trimmed.replace(/\D/g, "");
226
+ const widths = digits.length === 8 ? { day: 2, month: 2, year: 4 } : digits.length === 6 ? { day: 2, month: 2, year: 2 } : digits.length === 4 ? { day: 2, month: 2, year: 0 } : null;
227
+ if (!widths) return void 0;
228
+ let pos = 0;
229
+ const map = {};
230
+ for (const field of order) {
231
+ const w = widths[field];
232
+ if (w === 0) continue;
233
+ map[field] = Number.parseInt(digits.slice(pos, pos + w), 10);
234
+ pos += w;
235
+ }
236
+ return finalizeDateParts(map);
237
+ }
184
238
  var styles = {
185
239
  control: "relative flex items-center",
186
240
  input: "w-full h-9 rounded-md border bg-transparent pl-3 pr-9 text-sm outline-none focus:ring-2 focus:ring-ring",
@@ -204,9 +258,14 @@ var styles = {
204
258
  yearCellTrigger: "inline-flex items-center justify-center w-full py-2 text-sm rounded-md transition-colors hover:bg-muted data-[selected]:bg-primary data-[selected]:text-primary-foreground data-[disabled]:text-muted-foreground/30 data-[disabled]:pointer-events-none",
205
259
  footer: "flex items-center gap-1 pt-2 mt-2 border-t",
206
260
  footerButton: "text-sm px-2 py-1 rounded-md hover:bg-muted transition-colors",
261
+ footerSaveButton: "ml-auto text-sm px-3 py-1 rounded-md bg-primary text-primary-foreground hover:bg-primary/90 transition-colors",
207
262
  timeInput: "h-9 rounded-md border bg-transparent px-3 text-sm outline-none focus:ring-2 focus:ring-ring",
208
263
  label: "text-sm font-medium",
209
- timeTrigger: "flex-1 h-9 rounded-md border bg-transparent px-3 text-sm text-left hover:bg-muted transition-colors flex items-center justify-between"
264
+ timeTrigger: "flex-1 h-9 rounded-md border bg-transparent px-3 text-sm text-left hover:bg-muted transition-colors flex items-center justify-between",
265
+ defaultGhostTrigger: "inline-flex items-center gap-2 h-9 rounded-md px-2.5 text-sm font-normal text-foreground transition-colors hover:bg-muted focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[placeholder]:text-muted-foreground",
266
+ defaultGhostPlaceholder: "text-muted-foreground",
267
+ timeRow: "mt-2 pt-2 border-t flex items-center gap-2",
268
+ timeRowLabel: "text-xs text-muted-foreground"
210
269
  };
211
270
  function DayView() {
212
271
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_date_picker2.DatePickerView, { view: "day", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_date_picker2.DatePickerContext, { children: (api) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
@@ -311,9 +370,19 @@ function YearView() {
311
370
  )) }) })
312
371
  ] }) }) });
313
372
  }
373
+ function CalendarPanel() {
374
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
375
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DayView, {}),
376
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MonthView, {}),
377
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(YearView, {})
378
+ ] });
379
+ }
314
380
  function CalendarFooter({
315
381
  todayLabel,
316
- clearLabel
382
+ clearLabel,
383
+ saveLabel,
384
+ clearable = true,
385
+ onSave
317
386
  }) {
318
387
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_date_picker2.DatePickerContext, { children: (api) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: styles.footer, children: [
319
388
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
@@ -325,7 +394,7 @@ function CalendarFooter({
325
394
  children: todayLabel
326
395
  }
327
396
  ),
328
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
397
+ clearable && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
329
398
  "button",
330
399
  {
331
400
  type: "button",
@@ -333,6 +402,64 @@ function CalendarFooter({
333
402
  className: `${styles.footerButton} text-destructive`,
334
403
  children: clearLabel
335
404
  }
405
+ ),
406
+ onSave && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
407
+ "button",
408
+ {
409
+ type: "button",
410
+ onClick: () => {
411
+ onSave({
412
+ value: api.value,
413
+ valueAsString: api.valueAsString,
414
+ view: api.view
415
+ });
416
+ api.setOpen(false);
417
+ },
418
+ className: styles.footerSaveButton,
419
+ children: saveLabel
420
+ }
421
+ )
422
+ ] }) });
423
+ }
424
+ function DateTimeFooter({
425
+ todayLabel,
426
+ clearLabel,
427
+ saveLabel,
428
+ clearable = true,
429
+ onSelectNow,
430
+ onClear,
431
+ onSave
432
+ }) {
433
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_date_picker2.DatePickerContext, { children: (api) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: styles.footer, children: [
434
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
435
+ "button",
436
+ {
437
+ type: "button",
438
+ onClick: onSelectNow,
439
+ className: `${styles.footerButton} text-foreground`,
440
+ children: todayLabel
441
+ }
442
+ ),
443
+ clearable && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
444
+ "button",
445
+ {
446
+ type: "button",
447
+ onClick: onClear,
448
+ className: `${styles.footerButton} text-destructive`,
449
+ children: clearLabel
450
+ }
451
+ ),
452
+ onSave && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
453
+ "button",
454
+ {
455
+ type: "button",
456
+ onClick: () => {
457
+ onSave();
458
+ api.setOpen(false);
459
+ },
460
+ className: styles.footerSaveButton,
461
+ children: saveLabel
462
+ }
336
463
  )
337
464
  ] }) });
338
465
  }
@@ -352,16 +479,49 @@ function DatePickerField({
352
479
  todayLabel: todayLabelProp,
353
480
  clearLabel: clearLabelProp,
354
481
  className,
355
- rootProps
482
+ rootProps,
483
+ variant = "input",
484
+ trigger,
485
+ formatValue,
486
+ onSave,
487
+ saveLabel: saveLabelProp
356
488
  }) {
357
489
  var _a;
358
490
  const intl = (0, import_i18n2.useSafeIntl)();
359
491
  const locale = (_a = localeProp != null ? localeProp : intl.locale) != null ? _a : "en-US";
360
492
  const todayLabel = todayLabelProp != null ? todayLabelProp : intl.formatMessage(datePickerMessages.today);
361
493
  const clearLabel = clearLabelProp != null ? clearLabelProp : intl.formatMessage(datePickerMessages.clear);
494
+ const saveLabel = saveLabelProp != null ? saveLabelProp : intl.formatMessage(datePickerMessages.save);
362
495
  const placeholder = placeholderProp != null ? placeholderProp : intl.formatMessage(
363
496
  showTime ? datePickerMessages.select_date_and_time : datePickerMessages.select_date
364
497
  );
498
+ if (variant === "trigger") {
499
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
500
+ DateTriggerPickerField,
501
+ {
502
+ label,
503
+ value,
504
+ defaultValue,
505
+ onValueChange,
506
+ showTime,
507
+ clearable,
508
+ locale,
509
+ min,
510
+ max,
511
+ disabled,
512
+ readOnly,
513
+ placeholder,
514
+ todayLabel,
515
+ clearLabel,
516
+ saveLabel,
517
+ className,
518
+ rootProps,
519
+ trigger,
520
+ formatValue,
521
+ onSave
522
+ }
523
+ );
524
+ }
365
525
  if (showTime) {
366
526
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
367
527
  DateTimePickerField,
@@ -379,8 +539,10 @@ function DatePickerField({
379
539
  placeholder,
380
540
  todayLabel,
381
541
  clearLabel,
542
+ saveLabel,
382
543
  className,
383
- rootProps
544
+ rootProps,
545
+ onSave
384
546
  }
385
547
  );
386
548
  }
@@ -398,6 +560,10 @@ function DatePickerField({
398
560
  selectionMode: "single",
399
561
  outsideDaySelectable: true,
400
562
  closeOnSelect: true,
563
+ parse: (input, details) => {
564
+ const parts = parseLocalizedDate(input, details.locale);
565
+ return parts ? new import_date.CalendarDate(parts.year, parts.month, parts.day) : void 0;
566
+ },
401
567
  className,
402
568
  ...rootProps,
403
569
  children: [
@@ -416,10 +582,17 @@ function DatePickerField({
416
582
  ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_date_picker2.DatePickerTrigger, { className: styles.trigger, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CalendarIcon, { className: "size-4" }) })
417
583
  ] }),
418
584
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_portal.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_date_picker2.DatePickerPositioner, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_date_picker2.DatePickerContent, { className: styles.content, children: [
419
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DayView, {}),
420
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MonthView, {}),
421
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(YearView, {}),
422
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CalendarFooter, { todayLabel, clearLabel })
585
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CalendarPanel, {}),
586
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
587
+ CalendarFooter,
588
+ {
589
+ todayLabel,
590
+ clearLabel,
591
+ saveLabel,
592
+ clearable,
593
+ onSave
594
+ }
595
+ )
423
596
  ] }) }) })
424
597
  ]
425
598
  }
@@ -439,14 +612,17 @@ function DateTimePickerField({
439
612
  placeholder: placeholderProp,
440
613
  todayLabel: todayLabelProp,
441
614
  clearLabel: clearLabelProp,
615
+ saveLabel: saveLabelProp,
442
616
  className,
443
- rootProps
617
+ rootProps,
618
+ onSave
444
619
  }) {
445
620
  var _a;
446
621
  const intl = (0, import_i18n2.useSafeIntl)();
447
622
  const locale = (_a = localeProp != null ? localeProp : intl.locale) != null ? _a : "en-US";
448
623
  const todayLabel = todayLabelProp != null ? todayLabelProp : intl.formatMessage(datePickerMessages.today);
449
624
  const clearLabel = clearLabelProp != null ? clearLabelProp : intl.formatMessage(datePickerMessages.clear);
625
+ const saveLabel = saveLabelProp != null ? saveLabelProp : intl.formatMessage(datePickerMessages.save);
450
626
  const placeholder = placeholderProp != null ? placeholderProp : intl.formatMessage(datePickerMessages.select_date_and_time);
451
627
  const [internalValue, setInternalValue] = (0, import_react.useState)(() => {
452
628
  const initial = valueProp != null ? valueProp : defaultValue;
@@ -517,6 +693,22 @@ function DateTimePickerField({
517
693
  view: "day"
518
694
  });
519
695
  }, [onValueChange]);
696
+ const handleSelectNow = (0, import_react.useCallback)(() => {
697
+ const now = /* @__PURE__ */ new Date();
698
+ const nowValue = new import_date.CalendarDateTime(
699
+ now.getFullYear(),
700
+ now.getMonth() + 1,
701
+ now.getDate(),
702
+ now.getHours(),
703
+ now.getMinutes()
704
+ );
705
+ setInternalValue([nowValue]);
706
+ onValueChange == null ? void 0 : onValueChange({
707
+ value: [nowValue],
708
+ valueAsString: [nowValue.toString()],
709
+ view: "day"
710
+ });
711
+ }, [onValueChange]);
520
712
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
521
713
  import_date_picker2.DatePickerRoot,
522
714
  {
@@ -530,13 +722,33 @@ function DateTimePickerField({
530
722
  selectionMode: "single",
531
723
  outsideDaySelectable: true,
532
724
  closeOnSelect: false,
725
+ parse: (input, details) => {
726
+ const parts = parseLocalizedDate(input, details.locale);
727
+ if (!parts) return void 0;
728
+ const prev = currentValue[0];
729
+ const hour = prev && "hour" in prev ? prev.hour : 0;
730
+ const minute = prev && "minute" in prev ? prev.minute : 0;
731
+ return new import_date.CalendarDateTime(
732
+ parts.year,
733
+ parts.month,
734
+ parts.day,
735
+ hour,
736
+ minute
737
+ );
738
+ },
533
739
  className,
534
740
  ...rootProps,
535
741
  children: [
536
742
  label && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_date_picker2.DatePickerLabel, { className: styles.label, children: label }),
537
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_date_picker2.DatePickerControl, { className: "flex items-center gap-1", children: [
743
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_date_picker2.DatePickerControl, { className: "flex items-center", children: [
538
744
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "relative flex-1 flex items-center", children: [
539
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_date_picker2.DatePickerInput, { className: styles.input, placeholder }),
745
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
746
+ import_date_picker2.DatePickerInput,
747
+ {
748
+ className: "w-full h-9 rounded-l-md border border-r-0 bg-transparent pl-3 pr-9 text-sm outline-none focus:ring-2 focus:ring-ring",
749
+ placeholder
750
+ }
751
+ ),
540
752
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_date_picker2.DatePickerTrigger, { className: styles.trigger, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CalendarIcon, { className: "size-4" }) })
541
753
  ] }),
542
754
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
@@ -547,23 +759,215 @@ function DateTimePickerField({
547
759
  onChange: handleTimeChange,
548
760
  disabled,
549
761
  readOnly,
550
- className: styles.timeInput
762
+ className: `h-9 border bg-transparent px-3 text-sm outline-none focus:ring-2 focus:ring-ring ${clearable && !disabled && !readOnly ? "border-r-0" : "rounded-r-md"}`
551
763
  }
552
764
  ),
553
765
  clearable && !disabled && !readOnly && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
554
- import_date_picker2.DatePickerClearTrigger,
766
+ "button",
555
767
  {
556
- className: "inline-flex items-center justify-center size-9 rounded-md border text-muted-foreground hover:text-foreground hover:bg-muted transition-colors",
768
+ type: "button",
769
+ className: "inline-flex items-center justify-center size-9 rounded-r-md border text-muted-foreground hover:text-foreground hover:bg-muted transition-colors",
557
770
  onClick: handleClear,
558
771
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(XIcon, { className: "size-4" })
559
772
  }
560
773
  )
561
774
  ] }),
562
775
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_portal.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_date_picker2.DatePickerPositioner, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_date_picker2.DatePickerContent, { className: styles.content, children: [
563
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DayView, {}),
564
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MonthView, {}),
565
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(YearView, {}),
566
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CalendarFooter, { todayLabel, clearLabel })
776
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CalendarPanel, {}),
777
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
778
+ DateTimeFooter,
779
+ {
780
+ todayLabel,
781
+ clearLabel,
782
+ saveLabel,
783
+ clearable,
784
+ onSelectNow: handleSelectNow,
785
+ onClear: handleClear,
786
+ onSave: onSave ? () => onSave({
787
+ value: currentValue,
788
+ valueAsString: currentValue.map((v) => v.toString()),
789
+ view: "day"
790
+ }) : void 0
791
+ }
792
+ )
793
+ ] }) }) })
794
+ ]
795
+ }
796
+ );
797
+ }
798
+ function DateTriggerPickerField({
799
+ label,
800
+ value: valueProp,
801
+ defaultValue,
802
+ onValueChange,
803
+ showTime = false,
804
+ clearable = true,
805
+ locale: localeProp,
806
+ min,
807
+ max,
808
+ disabled,
809
+ readOnly,
810
+ placeholder: placeholderProp,
811
+ todayLabel: todayLabelProp,
812
+ clearLabel: clearLabelProp,
813
+ saveLabel: saveLabelProp,
814
+ className,
815
+ rootProps,
816
+ trigger,
817
+ formatValue,
818
+ onSave
819
+ }) {
820
+ var _a;
821
+ const intl = (0, import_i18n2.useSafeIntl)();
822
+ const locale = (_a = localeProp != null ? localeProp : intl.locale) != null ? _a : "en-US";
823
+ const todayLabel = todayLabelProp != null ? todayLabelProp : intl.formatMessage(datePickerMessages.today);
824
+ const clearLabel = clearLabelProp != null ? clearLabelProp : intl.formatMessage(datePickerMessages.clear);
825
+ const saveLabel = saveLabelProp != null ? saveLabelProp : intl.formatMessage(datePickerMessages.save);
826
+ const placeholder = placeholderProp != null ? placeholderProp : intl.formatMessage(
827
+ showTime ? datePickerMessages.select_date_and_time : datePickerMessages.select_date
828
+ );
829
+ const [draft, setDraft] = (0, import_react.useState)(
830
+ () => {
831
+ var _a2;
832
+ return (_a2 = valueProp != null ? valueProp : defaultValue) != null ? _a2 : [];
833
+ }
834
+ );
835
+ const [committed, setCommitted] = (0, import_react.useState)(
836
+ () => {
837
+ var _a2;
838
+ return (_a2 = valueProp != null ? valueProp : defaultValue) != null ? _a2 : [];
839
+ }
840
+ );
841
+ (0, import_react.useEffect)(() => {
842
+ if (valueProp !== void 0) {
843
+ setCommitted(valueProp);
844
+ if (!onSave) setDraft(valueProp);
845
+ }
846
+ }, [valueProp, onSave]);
847
+ const currentValue = onSave ? draft : valueProp != null ? valueProp : draft;
848
+ const handleDateChange = (0, import_react.useCallback)(
849
+ (details) => {
850
+ const next = details.value[0];
851
+ if (!showTime || !next) {
852
+ setDraft(details.value);
853
+ onValueChange == null ? void 0 : onValueChange(details);
854
+ return;
855
+ }
856
+ const prev = currentValue[0];
857
+ const prevHour = prev && "hour" in prev ? prev.hour : 0;
858
+ const prevMinute = prev && "minute" in prev ? prev.minute : 0;
859
+ const merged = new import_date.CalendarDateTime(
860
+ next.year,
861
+ next.month,
862
+ next.day,
863
+ prevHour,
864
+ prevMinute
865
+ );
866
+ setDraft([merged]);
867
+ onValueChange == null ? void 0 : onValueChange({ ...details, value: [merged] });
868
+ },
869
+ [currentValue, onValueChange, showTime]
870
+ );
871
+ const handleTimeChange = (0, import_react.useCallback)(
872
+ (e) => {
873
+ const [hours, minutes] = e.currentTarget.value.split(":").map(Number);
874
+ const prev = currentValue[0];
875
+ const base = prev && "hour" in prev ? prev : prev ? new import_date.CalendarDateTime(prev.year, prev.month, prev.day, 0, 0) : (() => {
876
+ const now = /* @__PURE__ */ new Date();
877
+ return new import_date.CalendarDateTime(
878
+ now.getFullYear(),
879
+ now.getMonth() + 1,
880
+ now.getDate(),
881
+ 0,
882
+ 0
883
+ );
884
+ })();
885
+ const updated = base.set({ hour: hours, minute: minutes });
886
+ setDraft([updated]);
887
+ onValueChange == null ? void 0 : onValueChange({
888
+ value: [updated],
889
+ valueAsString: [updated.toString()],
890
+ view: "day"
891
+ });
892
+ },
893
+ [currentValue, onValueChange]
894
+ );
895
+ const userOnOpenChange = rootProps == null ? void 0 : rootProps.onOpenChange;
896
+ const handleOpenChange = (0, import_react.useCallback)(
897
+ (details) => {
898
+ if (onSave && details.open) {
899
+ setDraft(committed);
900
+ }
901
+ userOnOpenChange == null ? void 0 : userOnOpenChange(details);
902
+ },
903
+ [committed, onSave, userOnOpenChange]
904
+ );
905
+ const handleSaveCommit = (0, import_react.useCallback)(
906
+ (details) => {
907
+ setCommitted(details.value);
908
+ onSave == null ? void 0 : onSave(details);
909
+ },
910
+ [onSave]
911
+ );
912
+ const formatter = (0, import_react.useMemo)(() => {
913
+ if (formatValue) return formatValue;
914
+ const fmt = new Intl.DateTimeFormat(
915
+ locale,
916
+ showTime ? { dateStyle: "medium", timeStyle: "short" } : { dateStyle: "medium" }
917
+ );
918
+ return (v) => fmt.format(v.toDate((0, import_date.getLocalTimeZone)()));
919
+ }, [formatValue, locale, showTime]);
920
+ const timeValue = currentValue[0] && "hour" in currentValue[0] ? `${String(currentValue[0].hour).padStart(2, "0")}:${String(currentValue[0].minute).padStart(2, "0")}` : "";
921
+ const triggerElement = trigger != null ? trigger : onSave ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { type: "button", className: styles.defaultGhostTrigger, children: [
922
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CalendarIcon, { className: "size-4 shrink-0 opacity-70" }),
923
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: committed[0] ? formatter(committed[0]) : placeholder })
924
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { type: "button", className: styles.defaultGhostTrigger, children: [
925
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CalendarIcon, { className: "size-4 shrink-0 opacity-70" }),
926
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_date_picker2.DatePickerValueText, { placeholder, children: ({ value }) => formatter(value) })
927
+ ] });
928
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
929
+ import_date_picker2.DatePickerRoot,
930
+ {
931
+ value: currentValue,
932
+ defaultValue,
933
+ onValueChange: handleDateChange,
934
+ locale,
935
+ min,
936
+ max,
937
+ disabled,
938
+ readOnly,
939
+ selectionMode: "single",
940
+ outsideDaySelectable: true,
941
+ closeOnSelect: !showTime && !onSave,
942
+ className,
943
+ ...rootProps,
944
+ onOpenChange: handleOpenChange,
945
+ children: [
946
+ label && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_date_picker2.DatePickerLabel, { className: styles.label, children: label }),
947
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_date_picker2.DatePickerControl, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_date_picker2.DatePickerTrigger, { asChild: true, children: triggerElement }) }),
948
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_portal.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_date_picker2.DatePickerPositioner, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_date_picker2.DatePickerContent, { className: styles.content, children: [
949
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CalendarPanel, {}),
950
+ showTime && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: styles.timeRow, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
951
+ "input",
952
+ {
953
+ type: "time",
954
+ value: timeValue,
955
+ onChange: handleTimeChange,
956
+ disabled,
957
+ readOnly,
958
+ className: styles.timeInput
959
+ }
960
+ ) }),
961
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
962
+ CalendarFooter,
963
+ {
964
+ todayLabel,
965
+ clearLabel,
966
+ saveLabel,
967
+ clearable,
968
+ onSave: onSave ? handleSaveCommit : void 0
969
+ }
970
+ )
567
971
  ] }) }) })
568
972
  ]
569
973
  }
package/dist/index.mjs CHANGED
@@ -1,10 +1,10 @@
1
1
  "use client";
2
2
  import {
3
3
  DatePickerField
4
- } from "./chunk-VYQ6BFFN.mjs";
4
+ } from "./chunk-BA6CJAOH.mjs";
5
5
  import {
6
6
  datePickerMessages
7
- } from "./chunk-HPM5Y2V6.mjs";
7
+ } from "./chunk-6IFLG64O.mjs";
8
8
  import {
9
9
  date_picker_exports,
10
10
  parseDate
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kopexa/date-picker",
3
- "version": "1.2.1",
3
+ "version": "1.4.0",
4
4
  "description": "DatePicker component for selecting dates and times",
5
5
  "keywords": [
6
6
  "date-picker",
@@ -30,7 +30,7 @@
30
30
  "dependencies": {
31
31
  "@ark-ui/react": "^5.35.0",
32
32
  "@internationalized/date": "^3.12.1",
33
- "@kopexa/i18n": "17.14.2"
33
+ "@kopexa/i18n": "17.14.4"
34
34
  },
35
35
  "clean-package": "../../../clean-package.config.json",
36
36
  "module": "dist/index.mjs",