@meta-1/design 0.0.160 → 0.0.162
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/package.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { forwardRef, useContext, useState } from "react";
|
|
1
|
+
import { forwardRef, type MouseEvent, useContext, useEffect, useState } from "react";
|
|
2
2
|
import { Cross2Icon } from "@radix-ui/react-icons";
|
|
3
3
|
import { addDays, format } from "date-fns";
|
|
4
4
|
import get from "lodash/get";
|
|
@@ -13,52 +13,128 @@ export type DatePickerProps = {
|
|
|
13
13
|
preset?: boolean;
|
|
14
14
|
className?: string;
|
|
15
15
|
allowClear?: boolean;
|
|
16
|
+
value?: Date;
|
|
17
|
+
onChange?: (value: Date | undefined) => void;
|
|
18
|
+
visible?: boolean;
|
|
19
|
+
onSelect?: (value: Date) => void;
|
|
16
20
|
};
|
|
17
21
|
|
|
18
22
|
export const DatePicker = forwardRef<HTMLDivElement, DatePickerProps>((props, _ref) => {
|
|
19
|
-
const {
|
|
20
|
-
|
|
23
|
+
const {
|
|
24
|
+
placeholder,
|
|
25
|
+
format: formatProp,
|
|
26
|
+
preset = false,
|
|
27
|
+
allowClear = false,
|
|
28
|
+
className,
|
|
29
|
+
value,
|
|
30
|
+
onChange,
|
|
31
|
+
visible,
|
|
32
|
+
onSelect,
|
|
33
|
+
} = props;
|
|
34
|
+
|
|
35
|
+
const hasValueProp = Object.hasOwn(props, "value");
|
|
36
|
+
const isValueControlled = hasValueProp;
|
|
37
|
+
const [internalDate, setInternalDate] = useState<Date | undefined>(value);
|
|
21
38
|
const [presetValue, setPresetValue] = useState<string>("");
|
|
39
|
+
const hasVisibleProp = Object.hasOwn(props, "visible");
|
|
40
|
+
const isOpenControlled = hasVisibleProp;
|
|
41
|
+
const [internalOpen, setInternalOpen] = useState(false);
|
|
42
|
+
|
|
43
|
+
useEffect(() => {
|
|
44
|
+
if (isValueControlled) {
|
|
45
|
+
setInternalDate(value);
|
|
46
|
+
}
|
|
47
|
+
}, [isValueControlled, value]);
|
|
22
48
|
|
|
23
49
|
const config = useContext(UIXContext);
|
|
24
50
|
const locale = get(config.locale, "DatePicker.locale");
|
|
25
|
-
const formatConfig =
|
|
51
|
+
const formatConfig = formatProp || get(config.locale, "DatePicker.format") || "yyyy-MM-dd";
|
|
26
52
|
const options = get(config.locale, "DatePicker.options");
|
|
53
|
+
const selectedDate = isValueControlled ? value : internalDate;
|
|
54
|
+
const popoverOpen = isOpenControlled ? visible : internalOpen;
|
|
27
55
|
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
56
|
+
const closePopover = () => {
|
|
57
|
+
if (!isOpenControlled) {
|
|
58
|
+
setInternalOpen(false);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const handleSelect = (nextDate?: Date) => {
|
|
63
|
+
if (!nextDate) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
if (!isValueControlled) {
|
|
67
|
+
setInternalDate(nextDate);
|
|
68
|
+
}
|
|
69
|
+
setPresetValue("");
|
|
70
|
+
onChange?.(nextDate);
|
|
71
|
+
closePopover();
|
|
72
|
+
onSelect?.(nextDate);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const handlePresetChange = (valueStr: string) => {
|
|
76
|
+
setPresetValue(valueStr);
|
|
77
|
+
const offset = Number.parseInt(valueStr, 10);
|
|
78
|
+
if (Number.isNaN(offset)) {
|
|
79
|
+
if (!isValueControlled) {
|
|
80
|
+
setInternalDate(undefined);
|
|
81
|
+
}
|
|
82
|
+
onChange?.(undefined);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const nextDate = addDays(new Date(), offset);
|
|
86
|
+
if (!isValueControlled) {
|
|
87
|
+
setInternalDate(nextDate);
|
|
88
|
+
}
|
|
89
|
+
onChange?.(nextDate);
|
|
90
|
+
closePopover();
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const handleClear = (event: MouseEvent<SVGSVGElement | HTMLSpanElement>) => {
|
|
94
|
+
event.preventDefault();
|
|
95
|
+
event.stopPropagation();
|
|
96
|
+
if (!isValueControlled) {
|
|
97
|
+
setInternalDate(undefined);
|
|
98
|
+
}
|
|
99
|
+
setPresetValue("");
|
|
100
|
+
onChange?.(undefined);
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const handleOpenChange = (nextOpen: boolean) => {
|
|
104
|
+
if (!isOpenControlled) {
|
|
105
|
+
setInternalOpen(nextOpen);
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const calendar = <Calendar locale={locale} mode="single" onSelect={handleSelect} selected={selectedDate} />;
|
|
39
110
|
|
|
40
111
|
return (
|
|
41
|
-
<Popover>
|
|
112
|
+
<Popover onOpenChange={handleOpenChange} open={popoverOpen}>
|
|
42
113
|
<PopoverTrigger asChild>
|
|
43
114
|
<Button
|
|
44
115
|
className={cn(
|
|
45
116
|
"group w-full justify-start space-x-1 text-left font-normal",
|
|
46
|
-
!
|
|
47
|
-
|
|
117
|
+
!selectedDate && "text-muted-foreground",
|
|
118
|
+
className,
|
|
48
119
|
)}
|
|
49
120
|
variant="outline"
|
|
50
121
|
>
|
|
51
122
|
<CalendarIcon className="mr-2 h-4 w-4" />
|
|
52
|
-
<span className="flex-1">{
|
|
53
|
-
{allowClear &&
|
|
54
|
-
<
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
123
|
+
<span className="flex-1">{selectedDate ? format(selectedDate, formatConfig) : placeholder}</span>
|
|
124
|
+
{allowClear && selectedDate ? (
|
|
125
|
+
<span
|
|
126
|
+
aria-label="Clear date"
|
|
127
|
+
className="hidden cursor-pointer items-center justify-center group-hover:flex"
|
|
128
|
+
onClick={handleClear}
|
|
129
|
+
onPointerDown={(pointerEvent) => {
|
|
130
|
+
pointerEvent.preventDefault();
|
|
131
|
+
pointerEvent.stopPropagation();
|
|
60
132
|
}}
|
|
61
|
-
|
|
133
|
+
role="button"
|
|
134
|
+
tabIndex={-1}
|
|
135
|
+
>
|
|
136
|
+
<Cross2Icon />
|
|
137
|
+
</span>
|
|
62
138
|
) : null}
|
|
63
139
|
</Button>
|
|
64
140
|
</PopoverTrigger>
|
|
@@ -67,10 +143,7 @@ export const DatePicker = forwardRef<HTMLDivElement, DatePickerProps>((props, _r
|
|
|
67
143
|
<>
|
|
68
144
|
<Select
|
|
69
145
|
className="w-full"
|
|
70
|
-
onChange={
|
|
71
|
-
setDate(addDays(new Date(), Number.parseInt(value, 10)));
|
|
72
|
-
setPresetValue(value);
|
|
73
|
-
}}
|
|
146
|
+
onChange={handlePresetChange}
|
|
74
147
|
options={options || []}
|
|
75
148
|
placeholder="请选择"
|
|
76
149
|
value={presetValue}
|