@kopexa/date-picker 1.3.0 → 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-HPM5Y2V6.mjs → chunk-6IFLG64O.mjs} +5 -0
- package/dist/{chunk-RWJEVZ4B.mjs → chunk-BA6CJAOH.mjs} +115 -24
- package/dist/date-picker-field.d.mts +14 -1
- package/dist/date-picker-field.d.ts +14 -1
- package/dist/date-picker-field.js +113 -22
- package/dist/date-picker-field.mjs +2 -2
- package/dist/date-picker-messages.d.mts +5 -0
- package/dist/date-picker-messages.d.ts +5 -0
- package/dist/date-picker-messages.js +5 -0
- package/dist/date-picker-messages.mjs +1 -1
- package/dist/index.js +113 -22
- package/dist/index.mjs +2 -2
- package/package.json +2 -2
|
@@ -27,6 +27,11 @@ var datePickerMessages = defineMessages({
|
|
|
27
27
|
id: "date-picker.select_date_and_time",
|
|
28
28
|
defaultMessage: "Select date and time",
|
|
29
29
|
description: "Placeholder for date+time input"
|
|
30
|
+
},
|
|
31
|
+
save: {
|
|
32
|
+
id: "date-picker.save",
|
|
33
|
+
defaultMessage: "Save",
|
|
34
|
+
description: "Button to commit the staged date selection (only shown when an onSave callback is provided)"
|
|
30
35
|
}
|
|
31
36
|
});
|
|
32
37
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import {
|
|
3
3
|
datePickerMessages
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-6IFLG64O.mjs";
|
|
5
5
|
|
|
6
6
|
// src/date-picker-field.tsx
|
|
7
7
|
import {
|
|
@@ -36,7 +36,12 @@ import {
|
|
|
36
36
|
getLocalTimeZone
|
|
37
37
|
} from "@internationalized/date";
|
|
38
38
|
import { useSafeIntl } from "@kopexa/i18n";
|
|
39
|
-
import {
|
|
39
|
+
import {
|
|
40
|
+
useCallback,
|
|
41
|
+
useEffect,
|
|
42
|
+
useMemo,
|
|
43
|
+
useState
|
|
44
|
+
} from "react";
|
|
40
45
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
41
46
|
function CalendarIcon({ className }) {
|
|
42
47
|
return /* @__PURE__ */ jsxs(
|
|
@@ -186,6 +191,7 @@ var styles = {
|
|
|
186
191
|
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",
|
|
187
192
|
footer: "flex items-center gap-1 pt-2 mt-2 border-t",
|
|
188
193
|
footerButton: "text-sm px-2 py-1 rounded-md hover:bg-muted transition-colors",
|
|
194
|
+
footerSaveButton: "ml-auto text-sm px-3 py-1 rounded-md bg-primary text-primary-foreground hover:bg-primary/90 transition-colors",
|
|
189
195
|
timeInput: "h-9 rounded-md border bg-transparent px-3 text-sm outline-none focus:ring-2 focus:ring-ring",
|
|
190
196
|
label: "text-sm font-medium",
|
|
191
197
|
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",
|
|
@@ -307,7 +313,9 @@ function CalendarPanel() {
|
|
|
307
313
|
function CalendarFooter({
|
|
308
314
|
todayLabel,
|
|
309
315
|
clearLabel,
|
|
310
|
-
|
|
316
|
+
saveLabel,
|
|
317
|
+
clearable = true,
|
|
318
|
+
onSave
|
|
311
319
|
}) {
|
|
312
320
|
return /* @__PURE__ */ jsx(DatePickerContext, { children: (api) => /* @__PURE__ */ jsxs("div", { className: styles.footer, children: [
|
|
313
321
|
/* @__PURE__ */ jsx(
|
|
@@ -327,17 +335,35 @@ function CalendarFooter({
|
|
|
327
335
|
className: `${styles.footerButton} text-destructive`,
|
|
328
336
|
children: clearLabel
|
|
329
337
|
}
|
|
338
|
+
),
|
|
339
|
+
onSave && /* @__PURE__ */ jsx(
|
|
340
|
+
"button",
|
|
341
|
+
{
|
|
342
|
+
type: "button",
|
|
343
|
+
onClick: () => {
|
|
344
|
+
onSave({
|
|
345
|
+
value: api.value,
|
|
346
|
+
valueAsString: api.valueAsString,
|
|
347
|
+
view: api.view
|
|
348
|
+
});
|
|
349
|
+
api.setOpen(false);
|
|
350
|
+
},
|
|
351
|
+
className: styles.footerSaveButton,
|
|
352
|
+
children: saveLabel
|
|
353
|
+
}
|
|
330
354
|
)
|
|
331
355
|
] }) });
|
|
332
356
|
}
|
|
333
357
|
function DateTimeFooter({
|
|
334
358
|
todayLabel,
|
|
335
359
|
clearLabel,
|
|
360
|
+
saveLabel,
|
|
336
361
|
clearable = true,
|
|
337
362
|
onSelectNow,
|
|
338
|
-
onClear
|
|
363
|
+
onClear,
|
|
364
|
+
onSave
|
|
339
365
|
}) {
|
|
340
|
-
return /* @__PURE__ */ jsxs("div", { className: styles.footer, children: [
|
|
366
|
+
return /* @__PURE__ */ jsx(DatePickerContext, { children: (api) => /* @__PURE__ */ jsxs("div", { className: styles.footer, children: [
|
|
341
367
|
/* @__PURE__ */ jsx(
|
|
342
368
|
"button",
|
|
343
369
|
{
|
|
@@ -355,8 +381,20 @@ function DateTimeFooter({
|
|
|
355
381
|
className: `${styles.footerButton} text-destructive`,
|
|
356
382
|
children: clearLabel
|
|
357
383
|
}
|
|
384
|
+
),
|
|
385
|
+
onSave && /* @__PURE__ */ jsx(
|
|
386
|
+
"button",
|
|
387
|
+
{
|
|
388
|
+
type: "button",
|
|
389
|
+
onClick: () => {
|
|
390
|
+
onSave();
|
|
391
|
+
api.setOpen(false);
|
|
392
|
+
},
|
|
393
|
+
className: styles.footerSaveButton,
|
|
394
|
+
children: saveLabel
|
|
395
|
+
}
|
|
358
396
|
)
|
|
359
|
-
] });
|
|
397
|
+
] }) });
|
|
360
398
|
}
|
|
361
399
|
function DatePickerField({
|
|
362
400
|
label,
|
|
@@ -377,13 +415,16 @@ function DatePickerField({
|
|
|
377
415
|
rootProps,
|
|
378
416
|
variant = "input",
|
|
379
417
|
trigger,
|
|
380
|
-
formatValue
|
|
418
|
+
formatValue,
|
|
419
|
+
onSave,
|
|
420
|
+
saveLabel: saveLabelProp
|
|
381
421
|
}) {
|
|
382
422
|
var _a;
|
|
383
423
|
const intl = useSafeIntl();
|
|
384
424
|
const locale = (_a = localeProp != null ? localeProp : intl.locale) != null ? _a : "en-US";
|
|
385
425
|
const todayLabel = todayLabelProp != null ? todayLabelProp : intl.formatMessage(datePickerMessages.today);
|
|
386
426
|
const clearLabel = clearLabelProp != null ? clearLabelProp : intl.formatMessage(datePickerMessages.clear);
|
|
427
|
+
const saveLabel = saveLabelProp != null ? saveLabelProp : intl.formatMessage(datePickerMessages.save);
|
|
387
428
|
const placeholder = placeholderProp != null ? placeholderProp : intl.formatMessage(
|
|
388
429
|
showTime ? datePickerMessages.select_date_and_time : datePickerMessages.select_date
|
|
389
430
|
);
|
|
@@ -405,10 +446,12 @@ function DatePickerField({
|
|
|
405
446
|
placeholder,
|
|
406
447
|
todayLabel,
|
|
407
448
|
clearLabel,
|
|
449
|
+
saveLabel,
|
|
408
450
|
className,
|
|
409
451
|
rootProps,
|
|
410
452
|
trigger,
|
|
411
|
-
formatValue
|
|
453
|
+
formatValue,
|
|
454
|
+
onSave
|
|
412
455
|
}
|
|
413
456
|
);
|
|
414
457
|
}
|
|
@@ -429,8 +472,10 @@ function DatePickerField({
|
|
|
429
472
|
placeholder,
|
|
430
473
|
todayLabel,
|
|
431
474
|
clearLabel,
|
|
475
|
+
saveLabel,
|
|
432
476
|
className,
|
|
433
|
-
rootProps
|
|
477
|
+
rootProps,
|
|
478
|
+
onSave
|
|
434
479
|
}
|
|
435
480
|
);
|
|
436
481
|
}
|
|
@@ -476,7 +521,9 @@ function DatePickerField({
|
|
|
476
521
|
{
|
|
477
522
|
todayLabel,
|
|
478
523
|
clearLabel,
|
|
479
|
-
|
|
524
|
+
saveLabel,
|
|
525
|
+
clearable,
|
|
526
|
+
onSave
|
|
480
527
|
}
|
|
481
528
|
)
|
|
482
529
|
] }) }) })
|
|
@@ -498,14 +545,17 @@ function DateTimePickerField({
|
|
|
498
545
|
placeholder: placeholderProp,
|
|
499
546
|
todayLabel: todayLabelProp,
|
|
500
547
|
clearLabel: clearLabelProp,
|
|
548
|
+
saveLabel: saveLabelProp,
|
|
501
549
|
className,
|
|
502
|
-
rootProps
|
|
550
|
+
rootProps,
|
|
551
|
+
onSave
|
|
503
552
|
}) {
|
|
504
553
|
var _a;
|
|
505
554
|
const intl = useSafeIntl();
|
|
506
555
|
const locale = (_a = localeProp != null ? localeProp : intl.locale) != null ? _a : "en-US";
|
|
507
556
|
const todayLabel = todayLabelProp != null ? todayLabelProp : intl.formatMessage(datePickerMessages.today);
|
|
508
557
|
const clearLabel = clearLabelProp != null ? clearLabelProp : intl.formatMessage(datePickerMessages.clear);
|
|
558
|
+
const saveLabel = saveLabelProp != null ? saveLabelProp : intl.formatMessage(datePickerMessages.save);
|
|
509
559
|
const placeholder = placeholderProp != null ? placeholderProp : intl.formatMessage(datePickerMessages.select_date_and_time);
|
|
510
560
|
const [internalValue, setInternalValue] = useState(() => {
|
|
511
561
|
const initial = valueProp != null ? valueProp : defaultValue;
|
|
@@ -662,9 +712,15 @@ function DateTimePickerField({
|
|
|
662
712
|
{
|
|
663
713
|
todayLabel,
|
|
664
714
|
clearLabel,
|
|
715
|
+
saveLabel,
|
|
665
716
|
clearable,
|
|
666
717
|
onSelectNow: handleSelectNow,
|
|
667
|
-
onClear: handleClear
|
|
718
|
+
onClear: handleClear,
|
|
719
|
+
onSave: onSave ? () => onSave({
|
|
720
|
+
value: currentValue,
|
|
721
|
+
valueAsString: currentValue.map((v) => v.toString()),
|
|
722
|
+
view: "day"
|
|
723
|
+
}) : void 0
|
|
668
724
|
}
|
|
669
725
|
)
|
|
670
726
|
] }) }) })
|
|
@@ -687,34 +743,46 @@ function DateTriggerPickerField({
|
|
|
687
743
|
placeholder: placeholderProp,
|
|
688
744
|
todayLabel: todayLabelProp,
|
|
689
745
|
clearLabel: clearLabelProp,
|
|
746
|
+
saveLabel: saveLabelProp,
|
|
690
747
|
className,
|
|
691
748
|
rootProps,
|
|
692
749
|
trigger,
|
|
693
|
-
formatValue
|
|
750
|
+
formatValue,
|
|
751
|
+
onSave
|
|
694
752
|
}) {
|
|
695
753
|
var _a;
|
|
696
754
|
const intl = useSafeIntl();
|
|
697
755
|
const locale = (_a = localeProp != null ? localeProp : intl.locale) != null ? _a : "en-US";
|
|
698
756
|
const todayLabel = todayLabelProp != null ? todayLabelProp : intl.formatMessage(datePickerMessages.today);
|
|
699
757
|
const clearLabel = clearLabelProp != null ? clearLabelProp : intl.formatMessage(datePickerMessages.clear);
|
|
758
|
+
const saveLabel = saveLabelProp != null ? saveLabelProp : intl.formatMessage(datePickerMessages.save);
|
|
700
759
|
const placeholder = placeholderProp != null ? placeholderProp : intl.formatMessage(
|
|
701
760
|
showTime ? datePickerMessages.select_date_and_time : datePickerMessages.select_date
|
|
702
761
|
);
|
|
703
|
-
const [
|
|
762
|
+
const [draft, setDraft] = useState(
|
|
704
763
|
() => {
|
|
705
764
|
var _a2;
|
|
706
765
|
return (_a2 = valueProp != null ? valueProp : defaultValue) != null ? _a2 : [];
|
|
707
766
|
}
|
|
708
767
|
);
|
|
709
|
-
const
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
768
|
+
const [committed, setCommitted] = useState(
|
|
769
|
+
() => {
|
|
770
|
+
var _a2;
|
|
771
|
+
return (_a2 = valueProp != null ? valueProp : defaultValue) != null ? _a2 : [];
|
|
772
|
+
}
|
|
773
|
+
);
|
|
774
|
+
useEffect(() => {
|
|
775
|
+
if (valueProp !== void 0) {
|
|
776
|
+
setCommitted(valueProp);
|
|
777
|
+
if (!onSave) setDraft(valueProp);
|
|
778
|
+
}
|
|
779
|
+
}, [valueProp, onSave]);
|
|
780
|
+
const currentValue = onSave ? draft : valueProp != null ? valueProp : draft;
|
|
713
781
|
const handleDateChange = useCallback(
|
|
714
782
|
(details) => {
|
|
715
783
|
const next = details.value[0];
|
|
716
784
|
if (!showTime || !next) {
|
|
717
|
-
|
|
785
|
+
setDraft(details.value);
|
|
718
786
|
onValueChange == null ? void 0 : onValueChange(details);
|
|
719
787
|
return;
|
|
720
788
|
}
|
|
@@ -728,7 +796,7 @@ function DateTriggerPickerField({
|
|
|
728
796
|
prevHour,
|
|
729
797
|
prevMinute
|
|
730
798
|
);
|
|
731
|
-
|
|
799
|
+
setDraft([merged]);
|
|
732
800
|
onValueChange == null ? void 0 : onValueChange({ ...details, value: [merged] });
|
|
733
801
|
},
|
|
734
802
|
[currentValue, onValueChange, showTime]
|
|
@@ -748,7 +816,7 @@ function DateTriggerPickerField({
|
|
|
748
816
|
);
|
|
749
817
|
})();
|
|
750
818
|
const updated = base.set({ hour: hours, minute: minutes });
|
|
751
|
-
|
|
819
|
+
setDraft([updated]);
|
|
752
820
|
onValueChange == null ? void 0 : onValueChange({
|
|
753
821
|
value: [updated],
|
|
754
822
|
valueAsString: [updated.toString()],
|
|
@@ -757,6 +825,23 @@ function DateTriggerPickerField({
|
|
|
757
825
|
},
|
|
758
826
|
[currentValue, onValueChange]
|
|
759
827
|
);
|
|
828
|
+
const userOnOpenChange = rootProps == null ? void 0 : rootProps.onOpenChange;
|
|
829
|
+
const handleOpenChange = useCallback(
|
|
830
|
+
(details) => {
|
|
831
|
+
if (onSave && details.open) {
|
|
832
|
+
setDraft(committed);
|
|
833
|
+
}
|
|
834
|
+
userOnOpenChange == null ? void 0 : userOnOpenChange(details);
|
|
835
|
+
},
|
|
836
|
+
[committed, onSave, userOnOpenChange]
|
|
837
|
+
);
|
|
838
|
+
const handleSaveCommit = useCallback(
|
|
839
|
+
(details) => {
|
|
840
|
+
setCommitted(details.value);
|
|
841
|
+
onSave == null ? void 0 : onSave(details);
|
|
842
|
+
},
|
|
843
|
+
[onSave]
|
|
844
|
+
);
|
|
760
845
|
const formatter = useMemo(() => {
|
|
761
846
|
if (formatValue) return formatValue;
|
|
762
847
|
const fmt = new Intl.DateTimeFormat(
|
|
@@ -766,7 +851,10 @@ function DateTriggerPickerField({
|
|
|
766
851
|
return (v) => fmt.format(v.toDate(getLocalTimeZone()));
|
|
767
852
|
}, [formatValue, locale, showTime]);
|
|
768
853
|
const timeValue = currentValue[0] && "hour" in currentValue[0] ? `${String(currentValue[0].hour).padStart(2, "0")}:${String(currentValue[0].minute).padStart(2, "0")}` : "";
|
|
769
|
-
const triggerElement = trigger != null ? trigger : /* @__PURE__ */ jsxs("button", { type: "button", className: styles.defaultGhostTrigger, children: [
|
|
854
|
+
const triggerElement = trigger != null ? trigger : onSave ? /* @__PURE__ */ jsxs("button", { type: "button", className: styles.defaultGhostTrigger, children: [
|
|
855
|
+
/* @__PURE__ */ jsx(CalendarIcon, { className: "size-4 shrink-0 opacity-70" }),
|
|
856
|
+
/* @__PURE__ */ jsx("span", { children: committed[0] ? formatter(committed[0]) : placeholder })
|
|
857
|
+
] }) : /* @__PURE__ */ jsxs("button", { type: "button", className: styles.defaultGhostTrigger, children: [
|
|
770
858
|
/* @__PURE__ */ jsx(CalendarIcon, { className: "size-4 shrink-0 opacity-70" }),
|
|
771
859
|
/* @__PURE__ */ jsx(DatePickerValueText, { placeholder, children: ({ value }) => formatter(value) })
|
|
772
860
|
] });
|
|
@@ -783,9 +871,10 @@ function DateTriggerPickerField({
|
|
|
783
871
|
readOnly,
|
|
784
872
|
selectionMode: "single",
|
|
785
873
|
outsideDaySelectable: true,
|
|
786
|
-
closeOnSelect: !showTime,
|
|
874
|
+
closeOnSelect: !showTime && !onSave,
|
|
787
875
|
className,
|
|
788
876
|
...rootProps,
|
|
877
|
+
onOpenChange: handleOpenChange,
|
|
789
878
|
children: [
|
|
790
879
|
label && /* @__PURE__ */ jsx(DatePickerLabel, { className: styles.label, children: label }),
|
|
791
880
|
/* @__PURE__ */ jsx(DatePickerControl, { children: /* @__PURE__ */ jsx(DatePickerTrigger, { asChild: true, children: triggerElement }) }),
|
|
@@ -807,7 +896,9 @@ function DateTriggerPickerField({
|
|
|
807
896
|
{
|
|
808
897
|
todayLabel,
|
|
809
898
|
clearLabel,
|
|
810
|
-
|
|
899
|
+
saveLabel,
|
|
900
|
+
clearable,
|
|
901
|
+
onSave: onSave ? handleSaveCommit : void 0
|
|
811
902
|
}
|
|
812
903
|
)
|
|
813
904
|
] }) }) })
|
|
@@ -59,7 +59,20 @@ type DatePickerFieldProps = {
|
|
|
59
59
|
* picker's locale, including time when `showTime` is true.
|
|
60
60
|
*/
|
|
61
61
|
formatValue?: (value: DateValue) => string;
|
|
62
|
+
/**
|
|
63
|
+
* When provided, a "Save" button is rendered in the popover footer.
|
|
64
|
+
* `onValueChange` still fires per interaction so the picker stays
|
|
65
|
+
* controllable, but `onSave` is the explicit commit signal — callers
|
|
66
|
+
* that need draft-then-commit semantics (e.g. avoiding a save on every
|
|
67
|
+
* minute increment of the time picker) should listen here instead of
|
|
68
|
+
* `onValueChange`. Clicking Save also closes the popover.
|
|
69
|
+
*/
|
|
70
|
+
onSave?: (details: DatePickerValueChangeDetails) => void;
|
|
71
|
+
/**
|
|
72
|
+
* Override the Save button label. Defaults to the i18n message.
|
|
73
|
+
*/
|
|
74
|
+
saveLabel?: string;
|
|
62
75
|
};
|
|
63
|
-
declare function DatePickerField({ label, value, defaultValue, onValueChange, showTime, clearable, locale: localeProp, min, max, disabled, readOnly, placeholder: placeholderProp, todayLabel: todayLabelProp, clearLabel: clearLabelProp, className, rootProps, variant, trigger, formatValue, }: DatePickerFieldProps): react_jsx_runtime.JSX.Element;
|
|
76
|
+
declare function DatePickerField({ label, value, defaultValue, onValueChange, showTime, clearable, locale: localeProp, min, max, disabled, readOnly, placeholder: placeholderProp, todayLabel: todayLabelProp, clearLabel: clearLabelProp, className, rootProps, variant, trigger, formatValue, onSave, saveLabel: saveLabelProp, }: DatePickerFieldProps): react_jsx_runtime.JSX.Element;
|
|
64
77
|
|
|
65
78
|
export { DatePickerField, type DatePickerFieldProps };
|
|
@@ -59,7 +59,20 @@ type DatePickerFieldProps = {
|
|
|
59
59
|
* picker's locale, including time when `showTime` is true.
|
|
60
60
|
*/
|
|
61
61
|
formatValue?: (value: DateValue) => string;
|
|
62
|
+
/**
|
|
63
|
+
* When provided, a "Save" button is rendered in the popover footer.
|
|
64
|
+
* `onValueChange` still fires per interaction so the picker stays
|
|
65
|
+
* controllable, but `onSave` is the explicit commit signal — callers
|
|
66
|
+
* that need draft-then-commit semantics (e.g. avoiding a save on every
|
|
67
|
+
* minute increment of the time picker) should listen here instead of
|
|
68
|
+
* `onValueChange`. Clicking Save also closes the popover.
|
|
69
|
+
*/
|
|
70
|
+
onSave?: (details: DatePickerValueChangeDetails) => void;
|
|
71
|
+
/**
|
|
72
|
+
* Override the Save button label. Defaults to the i18n message.
|
|
73
|
+
*/
|
|
74
|
+
saveLabel?: string;
|
|
62
75
|
};
|
|
63
|
-
declare function DatePickerField({ label, value, defaultValue, onValueChange, showTime, clearable, locale: localeProp, min, max, disabled, readOnly, placeholder: placeholderProp, todayLabel: todayLabelProp, clearLabel: clearLabelProp, className, rootProps, variant, trigger, formatValue, }: DatePickerFieldProps): react_jsx_runtime.JSX.Element;
|
|
76
|
+
declare function DatePickerField({ label, value, defaultValue, onValueChange, showTime, clearable, locale: localeProp, min, max, disabled, readOnly, placeholder: placeholderProp, todayLabel: todayLabelProp, clearLabel: clearLabelProp, className, rootProps, variant, trigger, formatValue, onSave, saveLabel: saveLabelProp, }: DatePickerFieldProps): react_jsx_runtime.JSX.Element;
|
|
64
77
|
|
|
65
78
|
export { DatePickerField, type DatePickerFieldProps };
|
|
@@ -58,6 +58,11 @@ var datePickerMessages = (0, import_i18n.defineMessages)({
|
|
|
58
58
|
id: "date-picker.select_date_and_time",
|
|
59
59
|
defaultMessage: "Select date and time",
|
|
60
60
|
description: "Placeholder for date+time input"
|
|
61
|
+
},
|
|
62
|
+
save: {
|
|
63
|
+
id: "date-picker.save",
|
|
64
|
+
defaultMessage: "Save",
|
|
65
|
+
description: "Button to commit the staged date selection (only shown when an onSave callback is provided)"
|
|
61
66
|
}
|
|
62
67
|
});
|
|
63
68
|
|
|
@@ -211,6 +216,7 @@ var styles = {
|
|
|
211
216
|
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",
|
|
212
217
|
footer: "flex items-center gap-1 pt-2 mt-2 border-t",
|
|
213
218
|
footerButton: "text-sm px-2 py-1 rounded-md hover:bg-muted transition-colors",
|
|
219
|
+
footerSaveButton: "ml-auto text-sm px-3 py-1 rounded-md bg-primary text-primary-foreground hover:bg-primary/90 transition-colors",
|
|
214
220
|
timeInput: "h-9 rounded-md border bg-transparent px-3 text-sm outline-none focus:ring-2 focus:ring-ring",
|
|
215
221
|
label: "text-sm font-medium",
|
|
216
222
|
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",
|
|
@@ -332,7 +338,9 @@ function CalendarPanel() {
|
|
|
332
338
|
function CalendarFooter({
|
|
333
339
|
todayLabel,
|
|
334
340
|
clearLabel,
|
|
335
|
-
|
|
341
|
+
saveLabel,
|
|
342
|
+
clearable = true,
|
|
343
|
+
onSave
|
|
336
344
|
}) {
|
|
337
345
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_date_picker.DatePickerContext, { children: (api) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: styles.footer, children: [
|
|
338
346
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
@@ -352,17 +360,35 @@ function CalendarFooter({
|
|
|
352
360
|
className: `${styles.footerButton} text-destructive`,
|
|
353
361
|
children: clearLabel
|
|
354
362
|
}
|
|
363
|
+
),
|
|
364
|
+
onSave && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
365
|
+
"button",
|
|
366
|
+
{
|
|
367
|
+
type: "button",
|
|
368
|
+
onClick: () => {
|
|
369
|
+
onSave({
|
|
370
|
+
value: api.value,
|
|
371
|
+
valueAsString: api.valueAsString,
|
|
372
|
+
view: api.view
|
|
373
|
+
});
|
|
374
|
+
api.setOpen(false);
|
|
375
|
+
},
|
|
376
|
+
className: styles.footerSaveButton,
|
|
377
|
+
children: saveLabel
|
|
378
|
+
}
|
|
355
379
|
)
|
|
356
380
|
] }) });
|
|
357
381
|
}
|
|
358
382
|
function DateTimeFooter({
|
|
359
383
|
todayLabel,
|
|
360
384
|
clearLabel,
|
|
385
|
+
saveLabel,
|
|
361
386
|
clearable = true,
|
|
362
387
|
onSelectNow,
|
|
363
|
-
onClear
|
|
388
|
+
onClear,
|
|
389
|
+
onSave
|
|
364
390
|
}) {
|
|
365
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: styles.footer, children: [
|
|
391
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_date_picker.DatePickerContext, { children: (api) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: styles.footer, children: [
|
|
366
392
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
367
393
|
"button",
|
|
368
394
|
{
|
|
@@ -380,8 +406,20 @@ function DateTimeFooter({
|
|
|
380
406
|
className: `${styles.footerButton} text-destructive`,
|
|
381
407
|
children: clearLabel
|
|
382
408
|
}
|
|
409
|
+
),
|
|
410
|
+
onSave && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
411
|
+
"button",
|
|
412
|
+
{
|
|
413
|
+
type: "button",
|
|
414
|
+
onClick: () => {
|
|
415
|
+
onSave();
|
|
416
|
+
api.setOpen(false);
|
|
417
|
+
},
|
|
418
|
+
className: styles.footerSaveButton,
|
|
419
|
+
children: saveLabel
|
|
420
|
+
}
|
|
383
421
|
)
|
|
384
|
-
] });
|
|
422
|
+
] }) });
|
|
385
423
|
}
|
|
386
424
|
function DatePickerField({
|
|
387
425
|
label,
|
|
@@ -402,13 +440,16 @@ function DatePickerField({
|
|
|
402
440
|
rootProps,
|
|
403
441
|
variant = "input",
|
|
404
442
|
trigger,
|
|
405
|
-
formatValue
|
|
443
|
+
formatValue,
|
|
444
|
+
onSave,
|
|
445
|
+
saveLabel: saveLabelProp
|
|
406
446
|
}) {
|
|
407
447
|
var _a;
|
|
408
448
|
const intl = (0, import_i18n2.useSafeIntl)();
|
|
409
449
|
const locale = (_a = localeProp != null ? localeProp : intl.locale) != null ? _a : "en-US";
|
|
410
450
|
const todayLabel = todayLabelProp != null ? todayLabelProp : intl.formatMessage(datePickerMessages.today);
|
|
411
451
|
const clearLabel = clearLabelProp != null ? clearLabelProp : intl.formatMessage(datePickerMessages.clear);
|
|
452
|
+
const saveLabel = saveLabelProp != null ? saveLabelProp : intl.formatMessage(datePickerMessages.save);
|
|
412
453
|
const placeholder = placeholderProp != null ? placeholderProp : intl.formatMessage(
|
|
413
454
|
showTime ? datePickerMessages.select_date_and_time : datePickerMessages.select_date
|
|
414
455
|
);
|
|
@@ -430,10 +471,12 @@ function DatePickerField({
|
|
|
430
471
|
placeholder,
|
|
431
472
|
todayLabel,
|
|
432
473
|
clearLabel,
|
|
474
|
+
saveLabel,
|
|
433
475
|
className,
|
|
434
476
|
rootProps,
|
|
435
477
|
trigger,
|
|
436
|
-
formatValue
|
|
478
|
+
formatValue,
|
|
479
|
+
onSave
|
|
437
480
|
}
|
|
438
481
|
);
|
|
439
482
|
}
|
|
@@ -454,8 +497,10 @@ function DatePickerField({
|
|
|
454
497
|
placeholder,
|
|
455
498
|
todayLabel,
|
|
456
499
|
clearLabel,
|
|
500
|
+
saveLabel,
|
|
457
501
|
className,
|
|
458
|
-
rootProps
|
|
502
|
+
rootProps,
|
|
503
|
+
onSave
|
|
459
504
|
}
|
|
460
505
|
);
|
|
461
506
|
}
|
|
@@ -501,7 +546,9 @@ function DatePickerField({
|
|
|
501
546
|
{
|
|
502
547
|
todayLabel,
|
|
503
548
|
clearLabel,
|
|
504
|
-
|
|
549
|
+
saveLabel,
|
|
550
|
+
clearable,
|
|
551
|
+
onSave
|
|
505
552
|
}
|
|
506
553
|
)
|
|
507
554
|
] }) }) })
|
|
@@ -523,14 +570,17 @@ function DateTimePickerField({
|
|
|
523
570
|
placeholder: placeholderProp,
|
|
524
571
|
todayLabel: todayLabelProp,
|
|
525
572
|
clearLabel: clearLabelProp,
|
|
573
|
+
saveLabel: saveLabelProp,
|
|
526
574
|
className,
|
|
527
|
-
rootProps
|
|
575
|
+
rootProps,
|
|
576
|
+
onSave
|
|
528
577
|
}) {
|
|
529
578
|
var _a;
|
|
530
579
|
const intl = (0, import_i18n2.useSafeIntl)();
|
|
531
580
|
const locale = (_a = localeProp != null ? localeProp : intl.locale) != null ? _a : "en-US";
|
|
532
581
|
const todayLabel = todayLabelProp != null ? todayLabelProp : intl.formatMessage(datePickerMessages.today);
|
|
533
582
|
const clearLabel = clearLabelProp != null ? clearLabelProp : intl.formatMessage(datePickerMessages.clear);
|
|
583
|
+
const saveLabel = saveLabelProp != null ? saveLabelProp : intl.formatMessage(datePickerMessages.save);
|
|
534
584
|
const placeholder = placeholderProp != null ? placeholderProp : intl.formatMessage(datePickerMessages.select_date_and_time);
|
|
535
585
|
const [internalValue, setInternalValue] = (0, import_react.useState)(() => {
|
|
536
586
|
const initial = valueProp != null ? valueProp : defaultValue;
|
|
@@ -687,9 +737,15 @@ function DateTimePickerField({
|
|
|
687
737
|
{
|
|
688
738
|
todayLabel,
|
|
689
739
|
clearLabel,
|
|
740
|
+
saveLabel,
|
|
690
741
|
clearable,
|
|
691
742
|
onSelectNow: handleSelectNow,
|
|
692
|
-
onClear: handleClear
|
|
743
|
+
onClear: handleClear,
|
|
744
|
+
onSave: onSave ? () => onSave({
|
|
745
|
+
value: currentValue,
|
|
746
|
+
valueAsString: currentValue.map((v) => v.toString()),
|
|
747
|
+
view: "day"
|
|
748
|
+
}) : void 0
|
|
693
749
|
}
|
|
694
750
|
)
|
|
695
751
|
] }) }) })
|
|
@@ -712,34 +768,46 @@ function DateTriggerPickerField({
|
|
|
712
768
|
placeholder: placeholderProp,
|
|
713
769
|
todayLabel: todayLabelProp,
|
|
714
770
|
clearLabel: clearLabelProp,
|
|
771
|
+
saveLabel: saveLabelProp,
|
|
715
772
|
className,
|
|
716
773
|
rootProps,
|
|
717
774
|
trigger,
|
|
718
|
-
formatValue
|
|
775
|
+
formatValue,
|
|
776
|
+
onSave
|
|
719
777
|
}) {
|
|
720
778
|
var _a;
|
|
721
779
|
const intl = (0, import_i18n2.useSafeIntl)();
|
|
722
780
|
const locale = (_a = localeProp != null ? localeProp : intl.locale) != null ? _a : "en-US";
|
|
723
781
|
const todayLabel = todayLabelProp != null ? todayLabelProp : intl.formatMessage(datePickerMessages.today);
|
|
724
782
|
const clearLabel = clearLabelProp != null ? clearLabelProp : intl.formatMessage(datePickerMessages.clear);
|
|
783
|
+
const saveLabel = saveLabelProp != null ? saveLabelProp : intl.formatMessage(datePickerMessages.save);
|
|
725
784
|
const placeholder = placeholderProp != null ? placeholderProp : intl.formatMessage(
|
|
726
785
|
showTime ? datePickerMessages.select_date_and_time : datePickerMessages.select_date
|
|
727
786
|
);
|
|
728
|
-
const [
|
|
787
|
+
const [draft, setDraft] = (0, import_react.useState)(
|
|
729
788
|
() => {
|
|
730
789
|
var _a2;
|
|
731
790
|
return (_a2 = valueProp != null ? valueProp : defaultValue) != null ? _a2 : [];
|
|
732
791
|
}
|
|
733
792
|
);
|
|
734
|
-
const
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
793
|
+
const [committed, setCommitted] = (0, import_react.useState)(
|
|
794
|
+
() => {
|
|
795
|
+
var _a2;
|
|
796
|
+
return (_a2 = valueProp != null ? valueProp : defaultValue) != null ? _a2 : [];
|
|
797
|
+
}
|
|
798
|
+
);
|
|
799
|
+
(0, import_react.useEffect)(() => {
|
|
800
|
+
if (valueProp !== void 0) {
|
|
801
|
+
setCommitted(valueProp);
|
|
802
|
+
if (!onSave) setDraft(valueProp);
|
|
803
|
+
}
|
|
804
|
+
}, [valueProp, onSave]);
|
|
805
|
+
const currentValue = onSave ? draft : valueProp != null ? valueProp : draft;
|
|
738
806
|
const handleDateChange = (0, import_react.useCallback)(
|
|
739
807
|
(details) => {
|
|
740
808
|
const next = details.value[0];
|
|
741
809
|
if (!showTime || !next) {
|
|
742
|
-
|
|
810
|
+
setDraft(details.value);
|
|
743
811
|
onValueChange == null ? void 0 : onValueChange(details);
|
|
744
812
|
return;
|
|
745
813
|
}
|
|
@@ -753,7 +821,7 @@ function DateTriggerPickerField({
|
|
|
753
821
|
prevHour,
|
|
754
822
|
prevMinute
|
|
755
823
|
);
|
|
756
|
-
|
|
824
|
+
setDraft([merged]);
|
|
757
825
|
onValueChange == null ? void 0 : onValueChange({ ...details, value: [merged] });
|
|
758
826
|
},
|
|
759
827
|
[currentValue, onValueChange, showTime]
|
|
@@ -773,7 +841,7 @@ function DateTriggerPickerField({
|
|
|
773
841
|
);
|
|
774
842
|
})();
|
|
775
843
|
const updated = base.set({ hour: hours, minute: minutes });
|
|
776
|
-
|
|
844
|
+
setDraft([updated]);
|
|
777
845
|
onValueChange == null ? void 0 : onValueChange({
|
|
778
846
|
value: [updated],
|
|
779
847
|
valueAsString: [updated.toString()],
|
|
@@ -782,6 +850,23 @@ function DateTriggerPickerField({
|
|
|
782
850
|
},
|
|
783
851
|
[currentValue, onValueChange]
|
|
784
852
|
);
|
|
853
|
+
const userOnOpenChange = rootProps == null ? void 0 : rootProps.onOpenChange;
|
|
854
|
+
const handleOpenChange = (0, import_react.useCallback)(
|
|
855
|
+
(details) => {
|
|
856
|
+
if (onSave && details.open) {
|
|
857
|
+
setDraft(committed);
|
|
858
|
+
}
|
|
859
|
+
userOnOpenChange == null ? void 0 : userOnOpenChange(details);
|
|
860
|
+
},
|
|
861
|
+
[committed, onSave, userOnOpenChange]
|
|
862
|
+
);
|
|
863
|
+
const handleSaveCommit = (0, import_react.useCallback)(
|
|
864
|
+
(details) => {
|
|
865
|
+
setCommitted(details.value);
|
|
866
|
+
onSave == null ? void 0 : onSave(details);
|
|
867
|
+
},
|
|
868
|
+
[onSave]
|
|
869
|
+
);
|
|
785
870
|
const formatter = (0, import_react.useMemo)(() => {
|
|
786
871
|
if (formatValue) return formatValue;
|
|
787
872
|
const fmt = new Intl.DateTimeFormat(
|
|
@@ -791,7 +876,10 @@ function DateTriggerPickerField({
|
|
|
791
876
|
return (v) => fmt.format(v.toDate((0, import_date.getLocalTimeZone)()));
|
|
792
877
|
}, [formatValue, locale, showTime]);
|
|
793
878
|
const timeValue = currentValue[0] && "hour" in currentValue[0] ? `${String(currentValue[0].hour).padStart(2, "0")}:${String(currentValue[0].minute).padStart(2, "0")}` : "";
|
|
794
|
-
const triggerElement = trigger != null ? trigger : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { type: "button", className: styles.defaultGhostTrigger, children: [
|
|
879
|
+
const triggerElement = trigger != null ? trigger : onSave ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { type: "button", className: styles.defaultGhostTrigger, children: [
|
|
880
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CalendarIcon, { className: "size-4 shrink-0 opacity-70" }),
|
|
881
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: committed[0] ? formatter(committed[0]) : placeholder })
|
|
882
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { type: "button", className: styles.defaultGhostTrigger, children: [
|
|
795
883
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CalendarIcon, { className: "size-4 shrink-0 opacity-70" }),
|
|
796
884
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_date_picker.DatePickerValueText, { placeholder, children: ({ value }) => formatter(value) })
|
|
797
885
|
] });
|
|
@@ -808,9 +896,10 @@ function DateTriggerPickerField({
|
|
|
808
896
|
readOnly,
|
|
809
897
|
selectionMode: "single",
|
|
810
898
|
outsideDaySelectable: true,
|
|
811
|
-
closeOnSelect: !showTime,
|
|
899
|
+
closeOnSelect: !showTime && !onSave,
|
|
812
900
|
className,
|
|
813
901
|
...rootProps,
|
|
902
|
+
onOpenChange: handleOpenChange,
|
|
814
903
|
children: [
|
|
815
904
|
label && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_date_picker.DatePickerLabel, { className: styles.label, children: label }),
|
|
816
905
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_date_picker.DatePickerControl, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_date_picker.DatePickerTrigger, { asChild: true, children: triggerElement }) }),
|
|
@@ -832,7 +921,9 @@ function DateTriggerPickerField({
|
|
|
832
921
|
{
|
|
833
922
|
todayLabel,
|
|
834
923
|
clearLabel,
|
|
835
|
-
|
|
924
|
+
saveLabel,
|
|
925
|
+
clearable,
|
|
926
|
+
onSave: onSave ? handleSaveCommit : void 0
|
|
836
927
|
}
|
|
837
928
|
)
|
|
838
929
|
] }) }) })
|
|
@@ -50,6 +50,11 @@ var datePickerMessages = (0, import_i18n.defineMessages)({
|
|
|
50
50
|
id: "date-picker.select_date_and_time",
|
|
51
51
|
defaultMessage: "Select date and time",
|
|
52
52
|
description: "Placeholder for date+time input"
|
|
53
|
+
},
|
|
54
|
+
save: {
|
|
55
|
+
id: "date-picker.save",
|
|
56
|
+
defaultMessage: "Save",
|
|
57
|
+
description: "Button to commit the staged date selection (only shown when an onSave callback is provided)"
|
|
53
58
|
}
|
|
54
59
|
});
|
|
55
60
|
// Annotate the CommonJS export names for ESM import in node:
|
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
|
|
|
@@ -253,6 +258,7 @@ var styles = {
|
|
|
253
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",
|
|
254
259
|
footer: "flex items-center gap-1 pt-2 mt-2 border-t",
|
|
255
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",
|
|
256
262
|
timeInput: "h-9 rounded-md border bg-transparent px-3 text-sm outline-none focus:ring-2 focus:ring-ring",
|
|
257
263
|
label: "text-sm font-medium",
|
|
258
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",
|
|
@@ -374,7 +380,9 @@ function CalendarPanel() {
|
|
|
374
380
|
function CalendarFooter({
|
|
375
381
|
todayLabel,
|
|
376
382
|
clearLabel,
|
|
377
|
-
|
|
383
|
+
saveLabel,
|
|
384
|
+
clearable = true,
|
|
385
|
+
onSave
|
|
378
386
|
}) {
|
|
379
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: [
|
|
380
388
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
@@ -394,17 +402,35 @@ function CalendarFooter({
|
|
|
394
402
|
className: `${styles.footerButton} text-destructive`,
|
|
395
403
|
children: clearLabel
|
|
396
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
|
+
}
|
|
397
421
|
)
|
|
398
422
|
] }) });
|
|
399
423
|
}
|
|
400
424
|
function DateTimeFooter({
|
|
401
425
|
todayLabel,
|
|
402
426
|
clearLabel,
|
|
427
|
+
saveLabel,
|
|
403
428
|
clearable = true,
|
|
404
429
|
onSelectNow,
|
|
405
|
-
onClear
|
|
430
|
+
onClear,
|
|
431
|
+
onSave
|
|
406
432
|
}) {
|
|
407
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: styles.footer, children: [
|
|
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: [
|
|
408
434
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
409
435
|
"button",
|
|
410
436
|
{
|
|
@@ -422,8 +448,20 @@ function DateTimeFooter({
|
|
|
422
448
|
className: `${styles.footerButton} text-destructive`,
|
|
423
449
|
children: clearLabel
|
|
424
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
|
+
}
|
|
425
463
|
)
|
|
426
|
-
] });
|
|
464
|
+
] }) });
|
|
427
465
|
}
|
|
428
466
|
function DatePickerField({
|
|
429
467
|
label,
|
|
@@ -444,13 +482,16 @@ function DatePickerField({
|
|
|
444
482
|
rootProps,
|
|
445
483
|
variant = "input",
|
|
446
484
|
trigger,
|
|
447
|
-
formatValue
|
|
485
|
+
formatValue,
|
|
486
|
+
onSave,
|
|
487
|
+
saveLabel: saveLabelProp
|
|
448
488
|
}) {
|
|
449
489
|
var _a;
|
|
450
490
|
const intl = (0, import_i18n2.useSafeIntl)();
|
|
451
491
|
const locale = (_a = localeProp != null ? localeProp : intl.locale) != null ? _a : "en-US";
|
|
452
492
|
const todayLabel = todayLabelProp != null ? todayLabelProp : intl.formatMessage(datePickerMessages.today);
|
|
453
493
|
const clearLabel = clearLabelProp != null ? clearLabelProp : intl.formatMessage(datePickerMessages.clear);
|
|
494
|
+
const saveLabel = saveLabelProp != null ? saveLabelProp : intl.formatMessage(datePickerMessages.save);
|
|
454
495
|
const placeholder = placeholderProp != null ? placeholderProp : intl.formatMessage(
|
|
455
496
|
showTime ? datePickerMessages.select_date_and_time : datePickerMessages.select_date
|
|
456
497
|
);
|
|
@@ -472,10 +513,12 @@ function DatePickerField({
|
|
|
472
513
|
placeholder,
|
|
473
514
|
todayLabel,
|
|
474
515
|
clearLabel,
|
|
516
|
+
saveLabel,
|
|
475
517
|
className,
|
|
476
518
|
rootProps,
|
|
477
519
|
trigger,
|
|
478
|
-
formatValue
|
|
520
|
+
formatValue,
|
|
521
|
+
onSave
|
|
479
522
|
}
|
|
480
523
|
);
|
|
481
524
|
}
|
|
@@ -496,8 +539,10 @@ function DatePickerField({
|
|
|
496
539
|
placeholder,
|
|
497
540
|
todayLabel,
|
|
498
541
|
clearLabel,
|
|
542
|
+
saveLabel,
|
|
499
543
|
className,
|
|
500
|
-
rootProps
|
|
544
|
+
rootProps,
|
|
545
|
+
onSave
|
|
501
546
|
}
|
|
502
547
|
);
|
|
503
548
|
}
|
|
@@ -543,7 +588,9 @@ function DatePickerField({
|
|
|
543
588
|
{
|
|
544
589
|
todayLabel,
|
|
545
590
|
clearLabel,
|
|
546
|
-
|
|
591
|
+
saveLabel,
|
|
592
|
+
clearable,
|
|
593
|
+
onSave
|
|
547
594
|
}
|
|
548
595
|
)
|
|
549
596
|
] }) }) })
|
|
@@ -565,14 +612,17 @@ function DateTimePickerField({
|
|
|
565
612
|
placeholder: placeholderProp,
|
|
566
613
|
todayLabel: todayLabelProp,
|
|
567
614
|
clearLabel: clearLabelProp,
|
|
615
|
+
saveLabel: saveLabelProp,
|
|
568
616
|
className,
|
|
569
|
-
rootProps
|
|
617
|
+
rootProps,
|
|
618
|
+
onSave
|
|
570
619
|
}) {
|
|
571
620
|
var _a;
|
|
572
621
|
const intl = (0, import_i18n2.useSafeIntl)();
|
|
573
622
|
const locale = (_a = localeProp != null ? localeProp : intl.locale) != null ? _a : "en-US";
|
|
574
623
|
const todayLabel = todayLabelProp != null ? todayLabelProp : intl.formatMessage(datePickerMessages.today);
|
|
575
624
|
const clearLabel = clearLabelProp != null ? clearLabelProp : intl.formatMessage(datePickerMessages.clear);
|
|
625
|
+
const saveLabel = saveLabelProp != null ? saveLabelProp : intl.formatMessage(datePickerMessages.save);
|
|
576
626
|
const placeholder = placeholderProp != null ? placeholderProp : intl.formatMessage(datePickerMessages.select_date_and_time);
|
|
577
627
|
const [internalValue, setInternalValue] = (0, import_react.useState)(() => {
|
|
578
628
|
const initial = valueProp != null ? valueProp : defaultValue;
|
|
@@ -729,9 +779,15 @@ function DateTimePickerField({
|
|
|
729
779
|
{
|
|
730
780
|
todayLabel,
|
|
731
781
|
clearLabel,
|
|
782
|
+
saveLabel,
|
|
732
783
|
clearable,
|
|
733
784
|
onSelectNow: handleSelectNow,
|
|
734
|
-
onClear: handleClear
|
|
785
|
+
onClear: handleClear,
|
|
786
|
+
onSave: onSave ? () => onSave({
|
|
787
|
+
value: currentValue,
|
|
788
|
+
valueAsString: currentValue.map((v) => v.toString()),
|
|
789
|
+
view: "day"
|
|
790
|
+
}) : void 0
|
|
735
791
|
}
|
|
736
792
|
)
|
|
737
793
|
] }) }) })
|
|
@@ -754,34 +810,46 @@ function DateTriggerPickerField({
|
|
|
754
810
|
placeholder: placeholderProp,
|
|
755
811
|
todayLabel: todayLabelProp,
|
|
756
812
|
clearLabel: clearLabelProp,
|
|
813
|
+
saveLabel: saveLabelProp,
|
|
757
814
|
className,
|
|
758
815
|
rootProps,
|
|
759
816
|
trigger,
|
|
760
|
-
formatValue
|
|
817
|
+
formatValue,
|
|
818
|
+
onSave
|
|
761
819
|
}) {
|
|
762
820
|
var _a;
|
|
763
821
|
const intl = (0, import_i18n2.useSafeIntl)();
|
|
764
822
|
const locale = (_a = localeProp != null ? localeProp : intl.locale) != null ? _a : "en-US";
|
|
765
823
|
const todayLabel = todayLabelProp != null ? todayLabelProp : intl.formatMessage(datePickerMessages.today);
|
|
766
824
|
const clearLabel = clearLabelProp != null ? clearLabelProp : intl.formatMessage(datePickerMessages.clear);
|
|
825
|
+
const saveLabel = saveLabelProp != null ? saveLabelProp : intl.formatMessage(datePickerMessages.save);
|
|
767
826
|
const placeholder = placeholderProp != null ? placeholderProp : intl.formatMessage(
|
|
768
827
|
showTime ? datePickerMessages.select_date_and_time : datePickerMessages.select_date
|
|
769
828
|
);
|
|
770
|
-
const [
|
|
829
|
+
const [draft, setDraft] = (0, import_react.useState)(
|
|
771
830
|
() => {
|
|
772
831
|
var _a2;
|
|
773
832
|
return (_a2 = valueProp != null ? valueProp : defaultValue) != null ? _a2 : [];
|
|
774
833
|
}
|
|
775
834
|
);
|
|
776
|
-
const
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
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;
|
|
780
848
|
const handleDateChange = (0, import_react.useCallback)(
|
|
781
849
|
(details) => {
|
|
782
850
|
const next = details.value[0];
|
|
783
851
|
if (!showTime || !next) {
|
|
784
|
-
|
|
852
|
+
setDraft(details.value);
|
|
785
853
|
onValueChange == null ? void 0 : onValueChange(details);
|
|
786
854
|
return;
|
|
787
855
|
}
|
|
@@ -795,7 +863,7 @@ function DateTriggerPickerField({
|
|
|
795
863
|
prevHour,
|
|
796
864
|
prevMinute
|
|
797
865
|
);
|
|
798
|
-
|
|
866
|
+
setDraft([merged]);
|
|
799
867
|
onValueChange == null ? void 0 : onValueChange({ ...details, value: [merged] });
|
|
800
868
|
},
|
|
801
869
|
[currentValue, onValueChange, showTime]
|
|
@@ -815,7 +883,7 @@ function DateTriggerPickerField({
|
|
|
815
883
|
);
|
|
816
884
|
})();
|
|
817
885
|
const updated = base.set({ hour: hours, minute: minutes });
|
|
818
|
-
|
|
886
|
+
setDraft([updated]);
|
|
819
887
|
onValueChange == null ? void 0 : onValueChange({
|
|
820
888
|
value: [updated],
|
|
821
889
|
valueAsString: [updated.toString()],
|
|
@@ -824,6 +892,23 @@ function DateTriggerPickerField({
|
|
|
824
892
|
},
|
|
825
893
|
[currentValue, onValueChange]
|
|
826
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
|
+
);
|
|
827
912
|
const formatter = (0, import_react.useMemo)(() => {
|
|
828
913
|
if (formatValue) return formatValue;
|
|
829
914
|
const fmt = new Intl.DateTimeFormat(
|
|
@@ -833,7 +918,10 @@ function DateTriggerPickerField({
|
|
|
833
918
|
return (v) => fmt.format(v.toDate((0, import_date.getLocalTimeZone)()));
|
|
834
919
|
}, [formatValue, locale, showTime]);
|
|
835
920
|
const timeValue = currentValue[0] && "hour" in currentValue[0] ? `${String(currentValue[0].hour).padStart(2, "0")}:${String(currentValue[0].minute).padStart(2, "0")}` : "";
|
|
836
|
-
const triggerElement = trigger != null ? trigger : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { type: "button", className: styles.defaultGhostTrigger, children: [
|
|
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: [
|
|
837
925
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CalendarIcon, { className: "size-4 shrink-0 opacity-70" }),
|
|
838
926
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_date_picker2.DatePickerValueText, { placeholder, children: ({ value }) => formatter(value) })
|
|
839
927
|
] });
|
|
@@ -850,9 +938,10 @@ function DateTriggerPickerField({
|
|
|
850
938
|
readOnly,
|
|
851
939
|
selectionMode: "single",
|
|
852
940
|
outsideDaySelectable: true,
|
|
853
|
-
closeOnSelect: !showTime,
|
|
941
|
+
closeOnSelect: !showTime && !onSave,
|
|
854
942
|
className,
|
|
855
943
|
...rootProps,
|
|
944
|
+
onOpenChange: handleOpenChange,
|
|
856
945
|
children: [
|
|
857
946
|
label && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_date_picker2.DatePickerLabel, { className: styles.label, children: label }),
|
|
858
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 }) }),
|
|
@@ -874,7 +963,9 @@ function DateTriggerPickerField({
|
|
|
874
963
|
{
|
|
875
964
|
todayLabel,
|
|
876
965
|
clearLabel,
|
|
877
|
-
|
|
966
|
+
saveLabel,
|
|
967
|
+
clearable,
|
|
968
|
+
onSave: onSave ? handleSaveCommit : void 0
|
|
878
969
|
}
|
|
879
970
|
)
|
|
880
971
|
] }) }) })
|
package/dist/index.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kopexa/date-picker",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.1",
|
|
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.
|
|
33
|
+
"@kopexa/i18n": "17.15.0"
|
|
34
34
|
},
|
|
35
35
|
"clean-package": "../../../clean-package.config.json",
|
|
36
36
|
"module": "dist/index.mjs",
|