@fangxinyan/lumina 0.6.14 → 0.6.16
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/{Calendar-RUTPKREW.css → Calendar-I6NHCXIB.css} +65 -0
- package/dist/Calendar.cjs +2 -2
- package/dist/Calendar.d.cts +2 -0
- package/dist/Calendar.d.ts +2 -0
- package/dist/Calendar.js +1 -1
- package/dist/DatePicker-VDVSIARF.css +60 -0
- package/dist/DatePicker.cjs +16 -0
- package/dist/DatePicker.d.cts +49 -0
- package/dist/DatePicker.d.ts +49 -0
- package/dist/DatePicker.js +7 -0
- package/dist/DateTimePicker-DRX7XA74.css +224 -0
- package/dist/DateTimePicker.cjs +16 -0
- package/dist/DateTimePicker.d.cts +61 -0
- package/dist/DateTimePicker.d.ts +61 -0
- package/dist/DateTimePicker.js +7 -0
- package/dist/TimePicker-ZBJOXH3U.css +151 -0
- package/dist/TimePicker.cjs +15 -0
- package/dist/TimePicker.d.cts +63 -0
- package/dist/TimePicker.d.ts +63 -0
- package/dist/TimePicker.js +6 -0
- package/dist/chunk-32FWB5NO.cjs +505 -0
- package/dist/chunk-4KDABJSY.cjs +241 -0
- package/dist/chunk-DU4VSUBF.js +393 -0
- package/dist/chunk-FKP5D5IS.js +271 -0
- package/dist/chunk-I7TOBKJO.js +219 -0
- package/dist/chunk-KHRYPNUV.cjs +293 -0
- package/dist/chunk-SFEWMO45.cjs +415 -0
- package/dist/chunk-YPE6CDXQ.js +483 -0
- package/dist/index.cjs +66 -51
- package/dist/index.d.cts +4 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +15 -12
- package/dist/styles.css +439 -0
- package/docs/llms/calendar.md +2 -1
- package/docs/llms/datepicker.md +69 -0
- package/docs/llms/datetimepicker.md +83 -0
- package/docs/llms/timepicker.md +81 -0
- package/docs/llms.md +5 -2
- package/package.json +7 -3
- package/dist/chunk-XG5D777V.js +0 -90
- package/dist/chunk-ZBTGYTQE.cjs +0 -112
|
@@ -0,0 +1,505 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkYB3IWIOJ_cjs = require('./chunk-YB3IWIOJ.cjs');
|
|
4
|
+
var chunkVS3I5OKA_cjs = require('./chunk-VS3I5OKA.cjs');
|
|
5
|
+
var chunkSW2HMNCA_cjs = require('./chunk-SW2HMNCA.cjs');
|
|
6
|
+
var chunk4KDABJSY_cjs = require('./chunk-4KDABJSY.cjs');
|
|
7
|
+
require('./tokens-RYJ3DFTU.css');
|
|
8
|
+
require('./shared-NJHRNLRH.css');
|
|
9
|
+
require('./DateTimePicker-DRX7XA74.css');
|
|
10
|
+
var React = require('react');
|
|
11
|
+
var reactDom = require('react-dom');
|
|
12
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
13
|
+
|
|
14
|
+
function _interopNamespace(e) {
|
|
15
|
+
if (e && e.__esModule) return e;
|
|
16
|
+
var n = Object.create(null);
|
|
17
|
+
if (e) {
|
|
18
|
+
Object.keys(e).forEach(function (k) {
|
|
19
|
+
if (k !== 'default') {
|
|
20
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
21
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
22
|
+
enumerable: true,
|
|
23
|
+
get: function () { return e[k]; }
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
n.default = e;
|
|
29
|
+
return Object.freeze(n);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
var React__namespace = /*#__PURE__*/_interopNamespace(React);
|
|
33
|
+
|
|
34
|
+
var pad = (value) => String(value).padStart(2, "0");
|
|
35
|
+
var clampStep = (value) => {
|
|
36
|
+
if (!Number.isFinite(value) || !value || value < 1) return 1;
|
|
37
|
+
return Math.floor(value);
|
|
38
|
+
};
|
|
39
|
+
var isValidDate = (date) => date instanceof Date && !Number.isNaN(date.getTime());
|
|
40
|
+
var startOfDay = (date) => new Date(date.getFullYear(), date.getMonth(), date.getDate());
|
|
41
|
+
var isSameDay = (a, b) => a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
|
|
42
|
+
var normalizeDateTime = (date, includeSecond) => {
|
|
43
|
+
const normalized = new Date(date);
|
|
44
|
+
if (!includeSecond) normalized.setSeconds(0);
|
|
45
|
+
normalized.setMilliseconds(0);
|
|
46
|
+
return normalized;
|
|
47
|
+
};
|
|
48
|
+
var getTimeParts = (date) => ({
|
|
49
|
+
hour: date.getHours(),
|
|
50
|
+
minute: date.getMinutes(),
|
|
51
|
+
second: date.getSeconds()
|
|
52
|
+
});
|
|
53
|
+
var composeDateTime = (date, time, includeSecond) => {
|
|
54
|
+
const next = new Date(date);
|
|
55
|
+
next.setHours(time.hour, time.minute, includeSecond ? time.second : 0, 0);
|
|
56
|
+
return next;
|
|
57
|
+
};
|
|
58
|
+
var composeTime = (base, key, value) => ({
|
|
59
|
+
hour: key === "hour" ? value : base.hour,
|
|
60
|
+
minute: key === "minute" ? value : base.minute,
|
|
61
|
+
second: key === "second" ? value : base.second
|
|
62
|
+
});
|
|
63
|
+
var byDistanceFrom = (preferred) => (a, b) => Math.abs(a - preferred) - Math.abs(b - preferred) || a - b;
|
|
64
|
+
var buildOptions = (max, step, selected) => {
|
|
65
|
+
const safeStep = clampStep(step);
|
|
66
|
+
const values = [];
|
|
67
|
+
for (let value = 0; value <= max; value += safeStep) {
|
|
68
|
+
values.push(value);
|
|
69
|
+
}
|
|
70
|
+
if (selected != null && !values.includes(selected)) {
|
|
71
|
+
values.push(selected);
|
|
72
|
+
values.sort((a, b) => a - b);
|
|
73
|
+
}
|
|
74
|
+
return values;
|
|
75
|
+
};
|
|
76
|
+
var formatDateTime = (date, format, includeSecond) => {
|
|
77
|
+
if (!isValidDate(date)) return "";
|
|
78
|
+
if (typeof format === "function") return format(date);
|
|
79
|
+
const year = String(date.getFullYear());
|
|
80
|
+
const month = pad(date.getMonth() + 1);
|
|
81
|
+
const day = pad(date.getDate());
|
|
82
|
+
const base = `${year}-${month}-${day} ${pad(date.getHours())}:${pad(date.getMinutes())}`;
|
|
83
|
+
return includeSecond ? `${base}:${pad(date.getSeconds())}` : base;
|
|
84
|
+
};
|
|
85
|
+
var parseDateTimeInput = (input, includeSecond) => {
|
|
86
|
+
const text = input.trim();
|
|
87
|
+
if (!text) return null;
|
|
88
|
+
const match = text.match(
|
|
89
|
+
/^(\d{4})[-/.年](\d{1,2})[-/.月](\d{1,2})日?(?:\s+|T)(\d{1,2}):(\d{1,2})(?::(\d{1,2}))?$/
|
|
90
|
+
);
|
|
91
|
+
if (!match) return null;
|
|
92
|
+
const year = Number(match[1]);
|
|
93
|
+
const month = Number(match[2]);
|
|
94
|
+
const day = Number(match[3]);
|
|
95
|
+
const hour = Number(match[4]);
|
|
96
|
+
const minute = Number(match[5]);
|
|
97
|
+
const second = match[6] == null || !includeSecond ? 0 : Number(match[6]);
|
|
98
|
+
if (hour < 0 || hour > 23 || minute < 0 || minute > 59 || second < 0 || second > 59) {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
const date = new Date(year, month - 1, day, hour, minute, second, 0);
|
|
102
|
+
if (date.getFullYear() !== year || date.getMonth() !== month - 1 || date.getDate() !== day) {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
return date;
|
|
106
|
+
};
|
|
107
|
+
var getNow = (includeSecond) => normalizeDateTime(/* @__PURE__ */ new Date(), includeSecond);
|
|
108
|
+
var DateTimePicker = React__namespace.forwardRef(
|
|
109
|
+
({
|
|
110
|
+
value,
|
|
111
|
+
defaultValue = null,
|
|
112
|
+
onChange,
|
|
113
|
+
format = "YYYY-MM-DD HH:mm",
|
|
114
|
+
showSecond,
|
|
115
|
+
placeholder = "\u8BF7\u9009\u62E9\u65E5\u671F\u65F6\u95F4",
|
|
116
|
+
disabled,
|
|
117
|
+
readOnly,
|
|
118
|
+
invalid,
|
|
119
|
+
size = "md",
|
|
120
|
+
allowClear,
|
|
121
|
+
hourStep = 1,
|
|
122
|
+
minuteStep = 1,
|
|
123
|
+
secondStep = 1,
|
|
124
|
+
min,
|
|
125
|
+
max,
|
|
126
|
+
disabledDate,
|
|
127
|
+
disabledTime,
|
|
128
|
+
placement = "bottom",
|
|
129
|
+
open: openProp,
|
|
130
|
+
defaultOpen = false,
|
|
131
|
+
onOpenChange,
|
|
132
|
+
popupClassName = "",
|
|
133
|
+
dropdownClassName = "",
|
|
134
|
+
className = "",
|
|
135
|
+
onKeyDown,
|
|
136
|
+
...rest
|
|
137
|
+
}, ref) => {
|
|
138
|
+
const includeSecond = showSecond ?? format === "YYYY-MM-DD HH:mm:ss";
|
|
139
|
+
const controlled = value !== void 0;
|
|
140
|
+
const initial = isValidDate(defaultValue) ? normalizeDateTime(defaultValue, includeSecond) : null;
|
|
141
|
+
const [inner, setInner] = React__namespace.useState(initial);
|
|
142
|
+
const current = controlled ? isValidDate(value) ? normalizeDateTime(value, includeSecond) : null : inner;
|
|
143
|
+
const currentTime = current?.getTime() ?? null;
|
|
144
|
+
const formattedCurrent = React__namespace.useMemo(
|
|
145
|
+
() => currentTime == null ? "" : formatDateTime(new Date(currentTime), format, includeSecond),
|
|
146
|
+
[currentTime, format, includeSecond]
|
|
147
|
+
);
|
|
148
|
+
const scrollSignature = currentTime == null ? "" : String(currentTime);
|
|
149
|
+
const [draft, setDraft] = React__namespace.useState(formattedCurrent);
|
|
150
|
+
React__namespace.useEffect(() => {
|
|
151
|
+
setDraft(formattedCurrent);
|
|
152
|
+
}, [formattedCurrent]);
|
|
153
|
+
const openControlled = openProp !== void 0;
|
|
154
|
+
const [innerOpen, setInnerOpen] = React__namespace.useState(defaultOpen);
|
|
155
|
+
const open = openControlled ? !!openProp : innerOpen;
|
|
156
|
+
const [compactPanel, setCompactPanel] = React__namespace.useState(false);
|
|
157
|
+
const [calendarViewDate, setCalendarViewDate] = React__namespace.useState(null);
|
|
158
|
+
const wasOpenRef = React__namespace.useRef(false);
|
|
159
|
+
const scrollSignatureRef = React__namespace.useRef(null);
|
|
160
|
+
const scrollFramesRef = React__namespace.useRef(/* @__PURE__ */ new Map());
|
|
161
|
+
const setOpen = React__namespace.useCallback(
|
|
162
|
+
(next) => {
|
|
163
|
+
if (disabled || readOnly) return;
|
|
164
|
+
if (!openControlled) setInnerOpen(next);
|
|
165
|
+
onOpenChange?.(next);
|
|
166
|
+
},
|
|
167
|
+
[disabled, onOpenChange, openControlled, readOnly]
|
|
168
|
+
);
|
|
169
|
+
const rootRef = React__namespace.useRef(null);
|
|
170
|
+
const panelRef = React__namespace.useRef(null);
|
|
171
|
+
const { triggerRef, floatingStyle } = chunkYB3IWIOJ_cjs.useFloating({
|
|
172
|
+
open,
|
|
173
|
+
placement,
|
|
174
|
+
panelWidth: compactPanel ? 332 : 476,
|
|
175
|
+
panelHeight: compactPanel ? includeSecond ? 492 : 468 : 328
|
|
176
|
+
});
|
|
177
|
+
const setRootRef = React__namespace.useCallback(
|
|
178
|
+
(node) => {
|
|
179
|
+
rootRef.current = node;
|
|
180
|
+
triggerRef.current = node;
|
|
181
|
+
if (typeof ref === "function") ref(node);
|
|
182
|
+
else if (ref) ref.current = node;
|
|
183
|
+
},
|
|
184
|
+
[ref, triggerRef]
|
|
185
|
+
);
|
|
186
|
+
React__namespace.useEffect(() => {
|
|
187
|
+
if (typeof window === "undefined") return;
|
|
188
|
+
const media = window.matchMedia("(max-width: 640px)");
|
|
189
|
+
const update = () => setCompactPanel(media.matches);
|
|
190
|
+
update();
|
|
191
|
+
media.addEventListener?.("change", update);
|
|
192
|
+
return () => media.removeEventListener?.("change", update);
|
|
193
|
+
}, []);
|
|
194
|
+
const normalizedMin = React__namespace.useMemo(
|
|
195
|
+
() => isValidDate(min) ? normalizeDateTime(min, includeSecond) : void 0,
|
|
196
|
+
[includeSecond, min]
|
|
197
|
+
);
|
|
198
|
+
const normalizedMax = React__namespace.useMemo(
|
|
199
|
+
() => isValidDate(max) ? normalizeDateTime(max, includeSecond) : void 0,
|
|
200
|
+
[includeSecond, max]
|
|
201
|
+
);
|
|
202
|
+
const isDisabledDay = React__namespace.useCallback(
|
|
203
|
+
(date) => {
|
|
204
|
+
const day = startOfDay(date);
|
|
205
|
+
if (normalizedMin && day < startOfDay(normalizedMin)) return true;
|
|
206
|
+
if (normalizedMax && day > startOfDay(normalizedMax)) return true;
|
|
207
|
+
return disabledDate?.(day) ?? false;
|
|
208
|
+
},
|
|
209
|
+
[disabledDate, normalizedMax, normalizedMin]
|
|
210
|
+
);
|
|
211
|
+
const isDisabledDateTime = React__namespace.useCallback(
|
|
212
|
+
(date) => {
|
|
213
|
+
const normalized = normalizeDateTime(date, includeSecond);
|
|
214
|
+
if (isDisabledDay(normalized)) return true;
|
|
215
|
+
if (normalizedMin && normalized < normalizedMin) return true;
|
|
216
|
+
if (normalizedMax && normalized > normalizedMax) return true;
|
|
217
|
+
return disabledTime?.(getTimeParts(normalized), startOfDay(normalized)) ?? false;
|
|
218
|
+
},
|
|
219
|
+
[disabledTime, includeSecond, isDisabledDay, normalizedMax, normalizedMin]
|
|
220
|
+
);
|
|
221
|
+
const commit = React__namespace.useCallback(
|
|
222
|
+
(next, close = false) => {
|
|
223
|
+
if (!next) {
|
|
224
|
+
if (!controlled) setInner(null);
|
|
225
|
+
setDraft("");
|
|
226
|
+
onChange?.(null, "");
|
|
227
|
+
if (close) setOpen(false);
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
const normalized = normalizeDateTime(next, includeSecond);
|
|
231
|
+
if (isDisabledDateTime(normalized)) return;
|
|
232
|
+
if (!controlled) setInner(normalized);
|
|
233
|
+
const nextString = formatDateTime(normalized, format, includeSecond);
|
|
234
|
+
setDraft(nextString);
|
|
235
|
+
onChange?.(normalized, nextString);
|
|
236
|
+
if (close) setOpen(false);
|
|
237
|
+
},
|
|
238
|
+
[controlled, format, includeSecond, isDisabledDateTime, onChange, setOpen]
|
|
239
|
+
);
|
|
240
|
+
React__namespace.useEffect(() => {
|
|
241
|
+
if (!open) return;
|
|
242
|
+
const onDown = (event) => {
|
|
243
|
+
const target = event.target;
|
|
244
|
+
if (rootRef.current?.contains(target)) return;
|
|
245
|
+
if (panelRef.current?.contains(target)) return;
|
|
246
|
+
setOpen(false);
|
|
247
|
+
};
|
|
248
|
+
const onDocKey = (event) => {
|
|
249
|
+
if (event.key === "Escape") setOpen(false);
|
|
250
|
+
};
|
|
251
|
+
document.addEventListener("mousedown", onDown);
|
|
252
|
+
document.addEventListener("keydown", onDocKey);
|
|
253
|
+
return () => {
|
|
254
|
+
document.removeEventListener("mousedown", onDown);
|
|
255
|
+
document.removeEventListener("keydown", onDocKey);
|
|
256
|
+
};
|
|
257
|
+
}, [open, setOpen]);
|
|
258
|
+
const scrollListTo = React__namespace.useCallback(
|
|
259
|
+
(list, top, animate) => {
|
|
260
|
+
const frame = scrollFramesRef.current.get(list);
|
|
261
|
+
if (frame != null) cancelAnimationFrame(frame);
|
|
262
|
+
if (!animate) {
|
|
263
|
+
list.scrollTop = top;
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
const start = list.scrollTop;
|
|
267
|
+
const distance = top - start;
|
|
268
|
+
if (Math.abs(distance) < 1) {
|
|
269
|
+
list.scrollTop = top;
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
const startedAt = performance.now();
|
|
273
|
+
const duration = 180;
|
|
274
|
+
const tick = (now) => {
|
|
275
|
+
const progress = Math.min((now - startedAt) / duration, 1);
|
|
276
|
+
const eased = 1 - Math.pow(1 - progress, 3);
|
|
277
|
+
list.scrollTop = start + distance * eased;
|
|
278
|
+
if (progress < 1) {
|
|
279
|
+
scrollFramesRef.current.set(list, requestAnimationFrame(tick));
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
scrollFramesRef.current.delete(list);
|
|
283
|
+
list.scrollTop = top;
|
|
284
|
+
};
|
|
285
|
+
scrollFramesRef.current.set(list, requestAnimationFrame(tick));
|
|
286
|
+
},
|
|
287
|
+
[]
|
|
288
|
+
);
|
|
289
|
+
React__namespace.useEffect(() => {
|
|
290
|
+
if (!open) return;
|
|
291
|
+
const shouldAnimate = wasOpenRef.current && scrollSignatureRef.current != null && scrollSignatureRef.current !== scrollSignature;
|
|
292
|
+
requestAnimationFrame(() => {
|
|
293
|
+
panelRef.current?.querySelectorAll(".date-time-picker-time-list").forEach((list) => {
|
|
294
|
+
const selected = list.querySelector(".date-time-picker-time-option.selected");
|
|
295
|
+
if (!selected) return;
|
|
296
|
+
const top = selected.offsetTop - list.offsetTop - list.clientHeight / 2 + selected.offsetHeight / 2;
|
|
297
|
+
scrollListTo(list, top, shouldAnimate);
|
|
298
|
+
});
|
|
299
|
+
});
|
|
300
|
+
wasOpenRef.current = open;
|
|
301
|
+
scrollSignatureRef.current = scrollSignature;
|
|
302
|
+
}, [open, scrollListTo, scrollSignature]);
|
|
303
|
+
React__namespace.useEffect(() => {
|
|
304
|
+
if (open) return;
|
|
305
|
+
wasOpenRef.current = false;
|
|
306
|
+
scrollSignatureRef.current = null;
|
|
307
|
+
setCalendarViewDate(null);
|
|
308
|
+
}, [open]);
|
|
309
|
+
React__namespace.useEffect(
|
|
310
|
+
() => () => {
|
|
311
|
+
scrollFramesRef.current.forEach((frame) => cancelAnimationFrame(frame));
|
|
312
|
+
scrollFramesRef.current.clear();
|
|
313
|
+
},
|
|
314
|
+
[]
|
|
315
|
+
);
|
|
316
|
+
const panelBase = current ?? getNow(includeSecond);
|
|
317
|
+
const selectedDay = startOfDay(panelBase);
|
|
318
|
+
const timeParts = getTimeParts(panelBase);
|
|
319
|
+
const hourOptions = buildOptions(23, hourStep, timeParts.hour);
|
|
320
|
+
const minuteOptions = buildOptions(59, minuteStep, timeParts.minute);
|
|
321
|
+
const secondOptions = buildOptions(59, secondStep, timeParts.second);
|
|
322
|
+
const findAvailableTime = (key, value2) => {
|
|
323
|
+
const preferred = composeTime(timeParts, key, value2);
|
|
324
|
+
if (!isDisabledDateTime(composeDateTime(selectedDay, preferred, includeSecond))) {
|
|
325
|
+
return preferred;
|
|
326
|
+
}
|
|
327
|
+
const hours = key === "hour" ? [value2] : [...hourOptions].sort(byDistanceFrom(timeParts.hour));
|
|
328
|
+
const minutes = key === "minute" ? [value2] : [...minuteOptions].sort(byDistanceFrom(timeParts.minute));
|
|
329
|
+
const seconds = key === "second" ? [value2] : includeSecond ? [...secondOptions].sort(byDistanceFrom(timeParts.second)) : [0];
|
|
330
|
+
for (const hour of hours) {
|
|
331
|
+
for (const minute of minutes) {
|
|
332
|
+
for (const second of seconds) {
|
|
333
|
+
const candidate = { hour, minute, second };
|
|
334
|
+
if (!isDisabledDateTime(composeDateTime(selectedDay, candidate, includeSecond))) {
|
|
335
|
+
return candidate;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
return null;
|
|
341
|
+
};
|
|
342
|
+
const handleDatePick = (date) => {
|
|
343
|
+
const next = composeDateTime(date, timeParts, includeSecond);
|
|
344
|
+
if (normalizedMin && isSameDay(next, normalizedMin) && next < normalizedMin) {
|
|
345
|
+
commit(normalizedMin);
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
if (normalizedMax && isSameDay(next, normalizedMax) && next > normalizedMax) {
|
|
349
|
+
commit(normalizedMax);
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
commit(next);
|
|
353
|
+
};
|
|
354
|
+
const pickTime = (key, nextValue) => {
|
|
355
|
+
const nextTime = findAvailableTime(key, nextValue);
|
|
356
|
+
if (nextTime) commit(composeDateTime(selectedDay, nextTime, includeSecond));
|
|
357
|
+
};
|
|
358
|
+
const handleInputChange = (next) => {
|
|
359
|
+
setDraft(next);
|
|
360
|
+
if (next.trim() === "") commit(null);
|
|
361
|
+
};
|
|
362
|
+
const handleInputBlur = () => {
|
|
363
|
+
if (!draft.trim()) {
|
|
364
|
+
setDraft(formatDateTime(current, format, includeSecond));
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
367
|
+
if (typeof format === "function") {
|
|
368
|
+
setDraft(formatDateTime(current, format, includeSecond));
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
371
|
+
const parsed = parseDateTimeInput(draft, includeSecond);
|
|
372
|
+
if (!parsed || isDisabledDateTime(parsed)) {
|
|
373
|
+
setDraft(formatDateTime(current, format, includeSecond));
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
commit(parsed);
|
|
377
|
+
};
|
|
378
|
+
const handleRootKeyDown = (event) => {
|
|
379
|
+
onKeyDown?.(event);
|
|
380
|
+
if (event.defaultPrevented) return;
|
|
381
|
+
if ((event.key === "ArrowDown" || event.key === "Enter") && !open) {
|
|
382
|
+
event.preventDefault();
|
|
383
|
+
setOpen(true);
|
|
384
|
+
}
|
|
385
|
+
if (event.key === "Escape" && open) {
|
|
386
|
+
event.preventDefault();
|
|
387
|
+
setOpen(false);
|
|
388
|
+
}
|
|
389
|
+
};
|
|
390
|
+
const renderTimeColumn = (label, key, options) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "date-time-picker-time-column", children: [
|
|
391
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "date-time-picker-time-label", children: label }),
|
|
392
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "date-time-picker-time-list", role: "listbox", "aria-label": label, children: options.map((option) => {
|
|
393
|
+
const selected = timeParts[key] === option;
|
|
394
|
+
const optionDisabled = findAvailableTime(key, option) == null;
|
|
395
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
396
|
+
"button",
|
|
397
|
+
{
|
|
398
|
+
type: "button",
|
|
399
|
+
role: "option",
|
|
400
|
+
"aria-selected": selected,
|
|
401
|
+
disabled: optionDisabled,
|
|
402
|
+
className: `date-time-picker-time-option ${selected ? "selected" : ""}`,
|
|
403
|
+
onClick: () => pickTime(key, option),
|
|
404
|
+
children: pad(option)
|
|
405
|
+
},
|
|
406
|
+
option
|
|
407
|
+
);
|
|
408
|
+
}) })
|
|
409
|
+
] });
|
|
410
|
+
const today = getNow(includeSecond);
|
|
411
|
+
const mergedPanelClassName = [popupClassName, dropdownClassName].filter(Boolean).join(" ");
|
|
412
|
+
const rootClassName = [
|
|
413
|
+
"date-time-picker",
|
|
414
|
+
size,
|
|
415
|
+
open && "open",
|
|
416
|
+
disabled && "disabled",
|
|
417
|
+
readOnly && "readonly",
|
|
418
|
+
invalid && "invalid",
|
|
419
|
+
className
|
|
420
|
+
].filter(Boolean).join(" ");
|
|
421
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: setRootRef, className: rootClassName, onKeyDown: handleRootKeyDown, ...rest, children: [
|
|
422
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
423
|
+
chunkVS3I5OKA_cjs.Input,
|
|
424
|
+
{
|
|
425
|
+
value: draft,
|
|
426
|
+
size,
|
|
427
|
+
placeholder,
|
|
428
|
+
disabled,
|
|
429
|
+
readOnly,
|
|
430
|
+
invalid,
|
|
431
|
+
allowClear,
|
|
432
|
+
leadingIcon: "calendar",
|
|
433
|
+
onFocus: () => setOpen(true),
|
|
434
|
+
onClick: () => setOpen(true),
|
|
435
|
+
onValueChange: handleInputChange,
|
|
436
|
+
onBlur: handleInputBlur,
|
|
437
|
+
inputMode: "numeric",
|
|
438
|
+
"aria-expanded": open,
|
|
439
|
+
"aria-haspopup": "dialog"
|
|
440
|
+
}
|
|
441
|
+
),
|
|
442
|
+
open && !disabled && !readOnly && typeof document !== "undefined" && reactDom.createPortal(
|
|
443
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
444
|
+
"div",
|
|
445
|
+
{
|
|
446
|
+
ref: panelRef,
|
|
447
|
+
className: `date-time-picker-panel ${includeSecond ? "with-second" : "without-second"} ${mergedPanelClassName}`,
|
|
448
|
+
role: "dialog",
|
|
449
|
+
style: floatingStyle,
|
|
450
|
+
children: [
|
|
451
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "date-time-picker-body", children: [
|
|
452
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
453
|
+
chunk4KDABJSY_cjs.Calendar,
|
|
454
|
+
{
|
|
455
|
+
value: selectedDay,
|
|
456
|
+
viewDate: calendarViewDate ?? void 0,
|
|
457
|
+
min: normalizedMin ? startOfDay(normalizedMin) : void 0,
|
|
458
|
+
max: normalizedMax ? startOfDay(normalizedMax) : void 0,
|
|
459
|
+
disabledDate: isDisabledDay,
|
|
460
|
+
onChange: handleDatePick
|
|
461
|
+
}
|
|
462
|
+
),
|
|
463
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "date-time-picker-time", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "date-time-picker-time-columns", children: [
|
|
464
|
+
renderTimeColumn("\u65F6", "hour", hourOptions),
|
|
465
|
+
renderTimeColumn("\u5206", "minute", minuteOptions),
|
|
466
|
+
includeSecond && renderTimeColumn("\u79D2", "second", secondOptions)
|
|
467
|
+
] }) })
|
|
468
|
+
] }),
|
|
469
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "date-time-picker-footer", children: [
|
|
470
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
471
|
+
chunkSW2HMNCA_cjs.Button,
|
|
472
|
+
{
|
|
473
|
+
size: "sm",
|
|
474
|
+
variant: "ghost",
|
|
475
|
+
disabled: isDisabledDateTime(today),
|
|
476
|
+
onClick: () => {
|
|
477
|
+
setCalendarViewDate(today);
|
|
478
|
+
commit(today);
|
|
479
|
+
},
|
|
480
|
+
children: "\u73B0\u5728"
|
|
481
|
+
}
|
|
482
|
+
),
|
|
483
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "date-time-picker-footer-spacer" }),
|
|
484
|
+
allowClear && /* @__PURE__ */ jsxRuntime.jsx(
|
|
485
|
+
chunkSW2HMNCA_cjs.Button,
|
|
486
|
+
{
|
|
487
|
+
size: "sm",
|
|
488
|
+
variant: "ghost",
|
|
489
|
+
onClick: () => commit(null, true),
|
|
490
|
+
children: "\u6E05\u7A7A"
|
|
491
|
+
}
|
|
492
|
+
),
|
|
493
|
+
/* @__PURE__ */ jsxRuntime.jsx(chunkSW2HMNCA_cjs.Button, { size: "sm", variant: "primary", onClick: () => setOpen(false), children: "\u786E\u5B9A" })
|
|
494
|
+
] })
|
|
495
|
+
]
|
|
496
|
+
}
|
|
497
|
+
),
|
|
498
|
+
document.body
|
|
499
|
+
)
|
|
500
|
+
] });
|
|
501
|
+
}
|
|
502
|
+
);
|
|
503
|
+
DateTimePicker.displayName = "DateTimePicker";
|
|
504
|
+
|
|
505
|
+
exports.DateTimePicker = DateTimePicker;
|