@sia.soul/sia-react-ui 0.1.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.
Files changed (46) hide show
  1. package/README.md +37 -0
  2. package/THIRD_PARTY_NOTICES.md +12 -0
  3. package/dist/Select-CJJ5LQap.d.cts +44 -0
  4. package/dist/Select-CJJ5LQap.d.ts +44 -0
  5. package/dist/chart.cjs +7523 -0
  6. package/dist/chart.css +1036 -0
  7. package/dist/chart.d.cts +2061 -0
  8. package/dist/chart.d.ts +2061 -0
  9. package/dist/chart.js +120 -0
  10. package/dist/chunk-34TTF4Y7.js +812 -0
  11. package/dist/chunk-6VXOLMKZ.js +381 -0
  12. package/dist/chunk-DZ45HRVP.js +583 -0
  13. package/dist/chunk-I342FGQY.js +7344 -0
  14. package/dist/chunk-JKZGAZMB.js +318 -0
  15. package/dist/chunk-MBS2HXLZ.js +59 -0
  16. package/dist/chunk-NZAT2RUM.js +60 -0
  17. package/dist/chunk-OMA75YLM.js +298 -0
  18. package/dist/chunk-ULEGTKXR.js +2138 -0
  19. package/dist/chunk-YCVXUMGP.js +945 -0
  20. package/dist/core-BeiAQiDY.d.ts +1076 -0
  21. package/dist/core-DRICIs2n.d.cts +1076 -0
  22. package/dist/core.cjs +3353 -0
  23. package/dist/core.css +8734 -0
  24. package/dist/core.d.cts +3 -0
  25. package/dist/core.d.ts +3 -0
  26. package/dist/core.js +45 -0
  27. package/dist/index.cjs +19658 -0
  28. package/dist/index.css +9762 -0
  29. package/dist/index.d.cts +1222 -0
  30. package/dist/index.d.ts +1222 -0
  31. package/dist/index.js +6843 -0
  32. package/dist/markdown-editor.cjs +417 -0
  33. package/dist/markdown-editor.d.cts +28 -0
  34. package/dist/markdown-editor.d.ts +28 -0
  35. package/dist/markdown-editor.js +6 -0
  36. package/dist/rich-text-editor.cjs +1853 -0
  37. package/dist/rich-text-editor.d.cts +27 -0
  38. package/dist/rich-text-editor.d.ts +27 -0
  39. package/dist/rich-text-editor.js +11 -0
  40. package/dist/select-date-range-BDWdo7qt.d.ts +84 -0
  41. package/dist/select-date-range-DWik3ADr.d.cts +84 -0
  42. package/dist/select-date-range.cjs +2074 -0
  43. package/dist/select-date-range.d.cts +3 -0
  44. package/dist/select-date-range.d.ts +3 -0
  45. package/dist/select-date-range.js +8 -0
  46. package/package.json +129 -0
@@ -0,0 +1,812 @@
1
+ import {
2
+ Select
3
+ } from "./chunk-JKZGAZMB.js";
4
+ import {
5
+ Icon,
6
+ PopupPortal,
7
+ useControllableState
8
+ } from "./chunk-YCVXUMGP.js";
9
+
10
+ // src/components/DatePicker.tsx
11
+ import { useEffect, useId, useMemo, useRef as useRef2, useState } from "react";
12
+
13
+ // src/components/DatePickerPanel.tsx
14
+ import { useLayoutEffect, useRef } from "react";
15
+ import { jsx, jsxs } from "react/jsx-runtime";
16
+ function pad(value) {
17
+ return String(value).padStart(2, "0");
18
+ }
19
+ function dateKey(date) {
20
+ return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`;
21
+ }
22
+ function parseDate(value) {
23
+ const match = value?.match(/^(\d{4})-(\d{2})-(\d{2})/);
24
+ if (!match) return null;
25
+ const date = new Date(Number(match[1]), Number(match[2]) - 1, Number(match[3]));
26
+ return Number.isNaN(date.getTime()) ? null : date;
27
+ }
28
+ function startOfMonth(value) {
29
+ return new Date(value.getFullYear(), value.getMonth(), 1);
30
+ }
31
+ function addMonths(value, amount) {
32
+ return new Date(value.getFullYear(), value.getMonth() + amount, 1);
33
+ }
34
+ function addDays(value, amount) {
35
+ return new Date(value.getFullYear(), value.getMonth(), value.getDate() + amount);
36
+ }
37
+ function daysBetween(left, right) {
38
+ const leftDate = parseDate(left);
39
+ const rightDate = parseDate(right);
40
+ if (!leftDate || !rightDate) return 0;
41
+ return Math.round((rightDate.getTime() - leftDate.getTime()) / 864e5);
42
+ }
43
+ function timePart(value, fallback = "00:00:00") {
44
+ const match = value?.match(/[T ](\d{2}):(\d{2})(?::(\d{2}))?/);
45
+ return match ? `${match[1]}:${match[2]}:${match[3] ?? "00"}` : fallback;
46
+ }
47
+ function withTime(date, time, showSecond = false) {
48
+ if (!date) return "";
49
+ const [hour = "00", minute = "00", second = "00"] = time.split(":");
50
+ return `${date} ${hour}:${minute}${showSecond ? `:${second}` : ""}`;
51
+ }
52
+ function normalizeDateValue(value, showTime) {
53
+ if (!value) return "";
54
+ const date = parseDate(value);
55
+ if (!date) return value;
56
+ const day = dateKey(date);
57
+ if (!showTime) return day;
58
+ const config = typeof showTime === "object" ? showTime : {};
59
+ return withTime(day, timePart(value, config.defaultValue ?? "00:00:00"), Boolean(config.showSecond));
60
+ }
61
+ var WEEKDAYS = ["\u4E00", "\u4E8C", "\u4E09", "\u56DB", "\u4E94", "\u516D", "\u65E5"];
62
+ function CalendarMonth({
63
+ month,
64
+ selectedDates = [],
65
+ range = ["", ""],
66
+ previewEnd,
67
+ disabledDate,
68
+ onSelect,
69
+ onHover
70
+ }) {
71
+ const first = startOfMonth(month);
72
+ const mondayIndex = (first.getDay() + 6) % 7;
73
+ const gridStart = addDays(first, -mondayIndex);
74
+ const today = dateKey(/* @__PURE__ */ new Date());
75
+ const start = range[0];
76
+ const end = range[1] || previewEnd || "";
77
+ const low = start && end ? start <= end ? start : end : "";
78
+ const high = start && end ? start <= end ? end : start : "";
79
+ return /* @__PURE__ */ jsxs("div", { className: "sia-date-panel__month", children: [
80
+ /* @__PURE__ */ jsx("div", { className: "sia-date-panel__weekdays", "aria-hidden": "true", children: WEEKDAYS.map((day) => /* @__PURE__ */ jsx("span", { children: day }, day)) }),
81
+ /* @__PURE__ */ jsx("div", { className: "sia-date-panel__days", children: Array.from({ length: 42 }, (_, index) => {
82
+ const date = addDays(gridStart, index);
83
+ const key = dateKey(date);
84
+ const outside = date.getMonth() !== month.getMonth();
85
+ const disabled = disabledDate?.(key) ?? false;
86
+ const selected = selectedDates.includes(key);
87
+ const rangeStart = Boolean(start && key === start);
88
+ const rangeEnd = Boolean(range[1] && key === range[1]);
89
+ const inRange = Boolean(low && high && key >= low && key <= high);
90
+ return /* @__PURE__ */ jsx(
91
+ "span",
92
+ {
93
+ className: `sia-date-panel__cell${outside ? " is-outside" : ""}${selected ? " is-selected" : ""}${rangeStart ? " is-range-start" : ""}${rangeEnd ? " is-range-end" : ""}${inRange ? " is-in-range" : ""}${key === today ? " is-today" : ""}`,
94
+ children: /* @__PURE__ */ jsx(
95
+ "button",
96
+ {
97
+ type: "button",
98
+ "aria-label": key,
99
+ "aria-pressed": selected || rangeStart || rangeEnd || void 0,
100
+ disabled,
101
+ onClick: () => onSelect(key),
102
+ onMouseEnter: () => onHover?.(key),
103
+ children: date.getDate()
104
+ }
105
+ )
106
+ },
107
+ key
108
+ );
109
+ }) })
110
+ ] });
111
+ }
112
+ function CalendarHeader({
113
+ month,
114
+ label,
115
+ range = false,
116
+ onPreviousYear,
117
+ onPreviousMonth,
118
+ onNextMonth,
119
+ onNextYear
120
+ }) {
121
+ return /* @__PURE__ */ jsxs("div", { className: "sia-date-panel__header", children: [
122
+ /* @__PURE__ */ jsxs("span", { className: "sia-date-panel__nav", children: [
123
+ onPreviousYear ? /* @__PURE__ */ jsxs("button", { type: "button", "aria-label": "\u4E0A\u4E00\u5E74", onClick: onPreviousYear, children: [
124
+ /* @__PURE__ */ jsx(Icon, { name: "chevron-left", size: 13 }),
125
+ /* @__PURE__ */ jsx(Icon, { name: "chevron-left", size: 13 })
126
+ ] }) : null,
127
+ onPreviousMonth ? /* @__PURE__ */ jsx("button", { type: "button", "aria-label": "\u4E0A\u4E2A\u6708", onClick: onPreviousMonth, children: /* @__PURE__ */ jsx(Icon, { name: "chevron-left", size: 15 }) }) : null
128
+ ] }),
129
+ /* @__PURE__ */ jsxs("strong", { children: [
130
+ label ? /* @__PURE__ */ jsx("small", { children: label }) : null,
131
+ /* @__PURE__ */ jsxs("span", { children: [
132
+ month.getFullYear(),
133
+ "\u5E74\xA0 ",
134
+ month.getMonth() + 1,
135
+ "\u6708"
136
+ ] })
137
+ ] }),
138
+ /* @__PURE__ */ jsxs("span", { className: "sia-date-panel__nav", children: [
139
+ onNextMonth ? /* @__PURE__ */ jsx("button", { type: "button", "aria-label": "\u4E0B\u4E2A\u6708", onClick: onNextMonth, children: /* @__PURE__ */ jsx(Icon, { name: "chevron-right", size: 15 }) }) : null,
140
+ onNextYear ? /* @__PURE__ */ jsxs("button", { type: "button", "aria-label": "\u4E0B\u4E00\u5E74", onClick: onNextYear, children: [
141
+ /* @__PURE__ */ jsx(Icon, { name: "chevron-right", size: 13 }),
142
+ /* @__PURE__ */ jsx(Icon, { name: "chevron-right", size: 13 })
143
+ ] }) : null
144
+ ] }),
145
+ range ? null : null
146
+ ] });
147
+ }
148
+ function TimePanel({
149
+ value,
150
+ showSecond = false,
151
+ ariaLabel = "\u65F6\u95F4",
152
+ disabledTime,
153
+ use12Hours = false,
154
+ onChange
155
+ }) {
156
+ const [hour = "00", minute = "00", second = "00"] = value.split(":");
157
+ const columnsRef = useRef(null);
158
+ useLayoutEffect(() => {
159
+ for (const column of columnsRef.current?.children ?? []) {
160
+ const selected = column.querySelector('[aria-selected="true"]');
161
+ const first = column.firstElementChild;
162
+ if (!selected || !first) continue;
163
+ const top = selected.offsetTop - first.offsetTop + parseFloat(getComputedStyle(column).paddingTop || "0");
164
+ const bottom = top + selected.offsetHeight;
165
+ if (top < column.scrollTop || bottom > column.scrollTop + column.clientHeight) {
166
+ column.scrollTop = Math.max(0, top - (column.clientHeight - selected.offsetHeight) / 2);
167
+ }
168
+ }
169
+ }, [hour, minute, second, showSecond, ariaLabel]);
170
+ const columns = [
171
+ { label: "\u5C0F\u65F6", value: hour, count: 24, index: 0 },
172
+ { label: "\u5206\u949F", value: minute, count: 60, index: 1 },
173
+ ...showSecond ? [{ label: "\u79D2", value: second, count: 60, index: 2 }] : []
174
+ ];
175
+ function update(index, next) {
176
+ const values = [hour, minute, second];
177
+ values[index] = next;
178
+ onChange(values.join(":"));
179
+ }
180
+ return /* @__PURE__ */ jsxs("aside", { className: "sia-date-panel__time", "aria-label": ariaLabel, children: [
181
+ /* @__PURE__ */ jsxs("strong", { children: [
182
+ use12Hours ? pad(Number(hour) % 12 || 12) : hour,
183
+ ":",
184
+ minute,
185
+ showSecond ? `:${second}` : "",
186
+ use12Hours ? Number(hour) < 12 ? " AM" : " PM" : ""
187
+ ] }),
188
+ /* @__PURE__ */ jsx("div", { ref: columnsRef, className: "sia-date-panel__time-columns", children: columns.map((column) => /* @__PURE__ */ jsx("div", { role: "listbox", "aria-label": `${ariaLabel}${column.label}`, children: Array.from({ length: column.count }, (_, index) => {
189
+ const next = pad(index);
190
+ const candidate = [hour, minute, second];
191
+ candidate[column.index] = next;
192
+ return /* @__PURE__ */ jsx("button", { type: "button", role: "option", disabled: disabledTime?.(candidate.join(":")), "aria-selected": next === column.value, className: next === column.value ? "is-selected" : "", onKeyDown: (event) => {
193
+ if (!["ArrowDown", "ArrowUp", "Home", "End"].includes(event.key)) return;
194
+ event.preventDefault();
195
+ const buttons = Array.from(event.currentTarget.parentElement.querySelectorAll("button:not(:disabled)"));
196
+ const position = buttons.indexOf(event.currentTarget);
197
+ const target = event.key === "Home" ? 0 : event.key === "End" ? buttons.length - 1 : Math.max(0, Math.min(buttons.length - 1, position + (event.key === "ArrowDown" ? 1 : -1)));
198
+ buttons[target]?.focus();
199
+ }, onClick: () => update(column.index, next), children: use12Hours && column.index === 0 ? `${pad(index % 12 || 12)} ${index < 12 ? "AM" : "PM"}` : next }, next);
200
+ }) }, column.label)) })
201
+ ] });
202
+ }
203
+ function DatePanelFooter({
204
+ showToday = true,
205
+ needConfirm = false,
206
+ disabledConfirm = false,
207
+ confirmText = "\u786E\u5B9A",
208
+ extra,
209
+ onToday,
210
+ onConfirm
211
+ }) {
212
+ return /* @__PURE__ */ jsxs("footer", { className: "sia-date-panel__footer", children: [
213
+ /* @__PURE__ */ jsxs("span", { children: [
214
+ showToday ? /* @__PURE__ */ jsx("button", { type: "button", onClick: onToday, children: "\u4ECA\u5929" }) : null,
215
+ extra
216
+ ] }),
217
+ needConfirm ? /* @__PURE__ */ jsx("button", { type: "button", className: "sia-date-panel__confirm", disabled: disabledConfirm, onClick: onConfirm, children: confirmText }) : null
218
+ ] });
219
+ }
220
+
221
+ // src/components/DatePicker.tsx
222
+ import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
223
+ function formatWeek(date) {
224
+ const target = new Date(date);
225
+ target.setHours(0, 0, 0, 0);
226
+ target.setDate(target.getDate() + 3 - (target.getDay() + 6) % 7);
227
+ const firstThursday = new Date(target.getFullYear(), 0, 4);
228
+ const week = 1 + Math.round(((target.getTime() - firstThursday.getTime()) / 864e5 - 3 + (firstThursday.getDay() + 6) % 7) / 7);
229
+ return `${target.getFullYear()}-W${String(week).padStart(2, "0")}`;
230
+ }
231
+ function formatPickerValue(day, picker) {
232
+ const date = parseDate(day);
233
+ if (!date) return day;
234
+ if (picker === "month") return day.slice(0, 7);
235
+ if (picker === "year") return day.slice(0, 4);
236
+ if (picker === "quarter") return `${day.slice(0, 4)}-Q${Math.floor(date.getMonth() / 3) + 1}`;
237
+ if (picker === "week") return formatWeek(date);
238
+ return day;
239
+ }
240
+ function dayFromValue(value) {
241
+ if (!value) return "";
242
+ if (/^\d{4}-\d{2}-\d{2}/.test(value)) return value.slice(0, 10);
243
+ if (/^\d{4}-\d{2}$/.test(value)) return `${value}-01`;
244
+ if (/^\d{4}-Q[1-4]$/.test(value)) return `${value.slice(0, 4)}-${String((Number(value.slice(-1)) - 1) * 3 + 1).padStart(2, "0")}-01`;
245
+ if (/^\d{4}$/.test(value)) return `${value}-01-01`;
246
+ return "";
247
+ }
248
+ function placeholderFor(picker, showTime, multiple) {
249
+ if (multiple) return "\u8BF7\u9009\u62E9\u591A\u4E2A\u65E5\u671F";
250
+ if (picker === "month") return "\u8BF7\u9009\u62E9\u6708\u4EFD";
251
+ if (picker === "year") return "\u8BF7\u9009\u62E9\u5E74\u4EFD";
252
+ if (picker === "quarter") return "\u8BF7\u9009\u62E9\u5B63\u5EA6";
253
+ if (picker === "week") return "\u8BF7\u9009\u62E9\u5468";
254
+ return showTime ? "\u8BF7\u9009\u62E9\u65E5\u671F\u65F6\u95F4" : "\u8BF7\u9009\u62E9\u65E5\u671F";
255
+ }
256
+ function showSecondFrom(showTime) {
257
+ return Boolean(typeof showTime === "object" && showTime.showSecond);
258
+ }
259
+ function defaultTimeFrom(showTime) {
260
+ return typeof showTime === "object" ? showTime.defaultValue ?? "00:00:00" : "00:00:00";
261
+ }
262
+ function resolvePreset(value) {
263
+ return typeof value === "function" ? value() : value;
264
+ }
265
+ function resolveRangePreset(value) {
266
+ return typeof value === "function" ? value() : value;
267
+ }
268
+ function DatePicker({
269
+ value,
270
+ defaultValue,
271
+ picker = "date",
272
+ size = "medium",
273
+ status = "default",
274
+ allowClear = true,
275
+ multiple = false,
276
+ needConfirm,
277
+ showTime = false,
278
+ showToday = true,
279
+ open,
280
+ defaultOpen = false,
281
+ suffixIcon,
282
+ minDate,
283
+ maxDate,
284
+ presets,
285
+ disabledDate,
286
+ disabled,
287
+ className = "",
288
+ onChange,
289
+ onOpenChange,
290
+ placeholder,
291
+ ...props
292
+ }) {
293
+ const id = useId();
294
+ const rootRef = useRef2(null);
295
+ const popupRef = useRef2(null);
296
+ const initialValue = defaultValue ?? (multiple ? [] : "");
297
+ const [currentValue, setCurrentValue] = useControllableState({ value, defaultValue: initialValue, onChange });
298
+ const [visible, setVisible] = useControllableState({ value: open, defaultValue: defaultOpen, onChange: onOpenChange });
299
+ const [draftValue, setDraftValue] = useState(currentValue);
300
+ const firstCurrent = Array.isArray(currentValue) ? currentValue[0] : currentValue;
301
+ const [viewMonth, setViewMonth] = useState(() => startOfMonth(parseDate(dayFromValue(firstCurrent)) ?? /* @__PURE__ */ new Date()));
302
+ const [draftTime, setDraftTime] = useState(() => timePart(firstCurrent, defaultTimeFrom(showTime)));
303
+ const resolvedNeedConfirm = needConfirm ?? Boolean(showTime);
304
+ const showSecond = showSecondFrom(showTime);
305
+ const selectedDates = useMemo(() => {
306
+ const values = Array.isArray(draftValue) ? draftValue : draftValue ? [draftValue] : [];
307
+ return values.map(dayFromValue).filter(Boolean);
308
+ }, [draftValue]);
309
+ useEffect(() => {
310
+ if (!visible) return void 0;
311
+ const close = (event) => {
312
+ const target = event.target;
313
+ if (!rootRef.current?.contains(target) && !popupRef.current?.contains(target)) setVisible(false);
314
+ };
315
+ document.addEventListener("pointerdown", close);
316
+ return () => document.removeEventListener("pointerdown", close);
317
+ }, [setVisible, visible]);
318
+ function changeOpen(next) {
319
+ if (next) {
320
+ setDraftValue(currentValue);
321
+ const current = Array.isArray(currentValue) ? currentValue[0] : currentValue;
322
+ setViewMonth(startOfMonth(parseDate(dayFromValue(current)) ?? /* @__PURE__ */ new Date()));
323
+ setDraftTime(timePart(current, defaultTimeFrom(showTime)));
324
+ }
325
+ setVisible(next);
326
+ }
327
+ function isDisabled(day) {
328
+ const minimum = minDate ?? props.min;
329
+ const maximum = maxDate ?? props.max;
330
+ if (minimum && day < String(minimum).slice(0, 10)) return true;
331
+ if (maximum && day > String(maximum).slice(0, 10)) return true;
332
+ return disabledDate?.(day, { type: "date" }) ?? false;
333
+ }
334
+ function buildValue(day) {
335
+ const picked = formatPickerValue(day, picker);
336
+ return showTime && picker === "date" ? withTime(picked, draftTime, showSecond) : picked;
337
+ }
338
+ function selectDate(day) {
339
+ if (isDisabled(day)) return;
340
+ const nextValue = buildValue(day);
341
+ if (multiple) {
342
+ const current = Array.isArray(draftValue) ? [...draftValue] : [];
343
+ const exists = current.some((item) => dayFromValue(item) === day);
344
+ const next = exists ? current.filter((item) => dayFromValue(item) !== day) : [...current, nextValue];
345
+ setDraftValue(next);
346
+ if (!resolvedNeedConfirm) setCurrentValue(next);
347
+ return;
348
+ }
349
+ setDraftValue(nextValue);
350
+ if (!resolvedNeedConfirm) {
351
+ setCurrentValue(nextValue);
352
+ changeOpen(false);
353
+ }
354
+ }
355
+ function commitDraft() {
356
+ setCurrentValue(draftValue);
357
+ changeOpen(false);
358
+ }
359
+ function clearValue(event) {
360
+ event.stopPropagation();
361
+ const empty = multiple ? [] : "";
362
+ setDraftValue(empty);
363
+ setCurrentValue(empty);
364
+ }
365
+ const display = Array.isArray(currentValue) ? currentValue.join("\u3001") : currentValue;
366
+ const triggerLabel = props["aria-label"] ?? (typeof placeholder === "string" ? placeholder : "\u65E5\u671F\u9009\u62E9\u5668");
367
+ return /* @__PURE__ */ jsxs2("span", { ref: rootRef, className: `sia-picker sia-picker--${size} sia-picker--${status}${visible ? " is-open" : ""}${disabled ? " is-disabled" : ""} ${className}`.trim(), children: [
368
+ /* @__PURE__ */ jsxs2(
369
+ "button",
370
+ {
371
+ type: "button",
372
+ id: props.id ?? id,
373
+ className: "sia-picker__trigger",
374
+ "aria-label": triggerLabel,
375
+ "aria-labelledby": props["aria-labelledby"],
376
+ "aria-haspopup": "dialog",
377
+ "aria-expanded": visible,
378
+ "aria-invalid": status === "error" || void 0,
379
+ "aria-describedby": props["aria-describedby"],
380
+ "aria-errormessage": props["aria-errormessage"],
381
+ disabled,
382
+ onClick: () => changeOpen(!visible),
383
+ onKeyDown: (event) => {
384
+ if (event.key === "ArrowDown" || event.key === "Enter" || event.key === " ") {
385
+ event.preventDefault();
386
+ changeOpen(true);
387
+ } else if (event.key === "Escape") changeOpen(false);
388
+ },
389
+ children: [
390
+ /* @__PURE__ */ jsx2("span", { className: `sia-picker__value${display ? "" : " is-placeholder"}`, children: display || placeholder || placeholderFor(picker, showTime, multiple) }),
391
+ allowClear && display && !disabled ? /* @__PURE__ */ jsx2("span", { role: "button", className: "sia-picker__clear", "aria-label": "\u6E05\u9664\u65E5\u671F", onClick: clearValue, children: /* @__PURE__ */ jsx2(Icon, { name: "circle-close", variant: "filled", size: 15 }) }) : null,
392
+ /* @__PURE__ */ jsx2("span", { className: "sia-picker__icon", "aria-hidden": "true", children: suffixIcon ?? /* @__PURE__ */ jsx2(Icon, { name: "calendar", size: 16 }) })
393
+ ]
394
+ }
395
+ ),
396
+ /* @__PURE__ */ jsxs2(PopupPortal, { ref: popupRef, anchorRef: rootRef, open: visible, className: `sia-date-panel${showTime ? " sia-date-panel--with-time" : ""}${presets?.length ? " sia-date-panel--with-presets" : ""}`, role: "dialog", "aria-label": "\u65E5\u671F\u9009\u62E9\u9762\u677F", children: [
397
+ /* @__PURE__ */ jsxs2("div", { className: "sia-date-panel__body", children: [
398
+ presets?.length ? /* @__PURE__ */ jsx2("aside", { className: "sia-date-panel__presets", children: presets.map((preset, index) => /* @__PURE__ */ jsx2("button", { type: "button", onClick: () => {
399
+ const next = resolvePreset(preset.value);
400
+ setDraftValue(next);
401
+ if (!resolvedNeedConfirm) {
402
+ setCurrentValue(next);
403
+ changeOpen(false);
404
+ }
405
+ }, children: preset.label }, index)) }) : null,
406
+ /* @__PURE__ */ jsxs2("section", { className: "sia-date-panel__calendar", children: [
407
+ /* @__PURE__ */ jsx2(
408
+ CalendarHeader,
409
+ {
410
+ month: viewMonth,
411
+ onPreviousYear: () => setViewMonth(addMonths(viewMonth, -12)),
412
+ onPreviousMonth: () => setViewMonth(addMonths(viewMonth, -1)),
413
+ onNextMonth: () => setViewMonth(addMonths(viewMonth, 1)),
414
+ onNextYear: () => setViewMonth(addMonths(viewMonth, 12))
415
+ }
416
+ ),
417
+ /* @__PURE__ */ jsx2(CalendarMonth, { month: viewMonth, selectedDates, disabledDate: isDisabled, onSelect: selectDate })
418
+ ] }),
419
+ showTime ? /* @__PURE__ */ jsx2(TimePanel, { value: draftTime, showSecond, onChange: (next) => {
420
+ setDraftTime(next);
421
+ if (typeof draftValue === "string" && draftValue) setDraftValue(withTime(dayFromValue(draftValue), next, showSecond));
422
+ } }) : null
423
+ ] }),
424
+ /* @__PURE__ */ jsx2(
425
+ DatePanelFooter,
426
+ {
427
+ showToday,
428
+ needConfirm: resolvedNeedConfirm,
429
+ disabledConfirm: Array.isArray(draftValue) ? draftValue.length === 0 : !draftValue,
430
+ onToday: () => selectDate(dateKey(/* @__PURE__ */ new Date())),
431
+ onConfirm: commitDraft
432
+ }
433
+ )
434
+ ] })
435
+ ] });
436
+ }
437
+ function DateRangePicker({
438
+ value,
439
+ defaultValue = ["", ""],
440
+ placeholder = ["\u5F00\u59CB\u65E5\u671F", "\u7ED3\u675F\u65E5\u671F"],
441
+ separator = "\u2192",
442
+ presets,
443
+ maxRangeDays,
444
+ size = "medium",
445
+ status = "default",
446
+ allowClear = true,
447
+ needConfirm,
448
+ showTime = false,
449
+ showToday = true,
450
+ open,
451
+ defaultOpen = false,
452
+ suffixIcon,
453
+ minDate,
454
+ maxDate,
455
+ disabledDate,
456
+ disabled,
457
+ className = "",
458
+ onCalendarChange,
459
+ onChange,
460
+ onOpenChange,
461
+ ...props
462
+ }) {
463
+ const id = useId();
464
+ const rootRef = useRef2(null);
465
+ const popupRef = useRef2(null);
466
+ const [currentValue, setCurrentValue] = useControllableState({ value, defaultValue, onChange });
467
+ const [visible, setVisible] = useControllableState({ value: open, defaultValue: defaultOpen, onChange: onOpenChange });
468
+ const [draftValue, setDraftValue] = useState(currentValue);
469
+ const [activeIndex, setActiveIndex] = useState(currentValue[0] && !currentValue[1] ? 1 : 0);
470
+ const [hoverDate, setHoverDate] = useState("");
471
+ const [viewMonth, setViewMonth] = useState(() => startOfMonth(parseDate(dayFromValue(currentValue[0] || currentValue[1])) ?? /* @__PURE__ */ new Date()));
472
+ const [endViewMonth, setEndViewMonth] = useState(() => startOfMonth(parseDate(dayFromValue(currentValue[1])) ?? addMonths(parseDate(dayFromValue(currentValue[0])) ?? /* @__PURE__ */ new Date(), 1)));
473
+ const [compactDateTime, setCompactDateTime] = useState(false);
474
+ const showSecond = showSecondFrom(showTime);
475
+ const defaultTime = defaultTimeFrom(showTime);
476
+ const [times, setTimes] = useState([
477
+ timePart(currentValue[0], defaultTime),
478
+ timePart(currentValue[1], defaultTime)
479
+ ]);
480
+ const resolvedNeedConfirm = needConfirm ?? Boolean(showTime);
481
+ const rangeDates = [dayFromValue(draftValue[0]), dayFromValue(draftValue[1])];
482
+ const invalidDateTimeRange = Boolean(showTime && draftValue[0] && draftValue[1] && draftValue[0] > draftValue[1]);
483
+ useEffect(() => {
484
+ if (!showTime || typeof document === "undefined") {
485
+ setCompactDateTime(false);
486
+ return void 0;
487
+ }
488
+ const updateLayout = () => {
489
+ const pairedPanelWidth = 2 * (280 + (showSecond ? 144 : 96) + 1) + 3;
490
+ setCompactDateTime(document.documentElement.clientWidth < pairedPanelWidth + 16);
491
+ };
492
+ updateLayout();
493
+ window.addEventListener("resize", updateLayout);
494
+ return () => window.removeEventListener("resize", updateLayout);
495
+ }, [showSecond, showTime]);
496
+ useEffect(() => {
497
+ if (!visible) return void 0;
498
+ const close = (event) => {
499
+ const target = event.target;
500
+ if (!rootRef.current?.contains(target) && !popupRef.current?.contains(target)) setVisible(false);
501
+ };
502
+ document.addEventListener("pointerdown", close);
503
+ return () => document.removeEventListener("pointerdown", close);
504
+ }, [setVisible, visible]);
505
+ function changeOpen(next) {
506
+ if (next) {
507
+ setDraftValue(currentValue);
508
+ setTimes([timePart(currentValue[0], defaultTime), timePart(currentValue[1], defaultTime)]);
509
+ setActiveIndex(currentValue[0] && !currentValue[1] ? 1 : 0);
510
+ const nextStartMonth = startOfMonth(parseDate(dayFromValue(currentValue[0] || currentValue[1])) ?? /* @__PURE__ */ new Date());
511
+ setViewMonth(nextStartMonth);
512
+ setEndViewMonth(startOfMonth(parseDate(dayFromValue(currentValue[1])) ?? addMonths(nextStartMonth, 1)));
513
+ }
514
+ setVisible(next);
515
+ }
516
+ function isDisabled(day, index = activeIndex, pairedDateTime = false) {
517
+ const minimum = minDate ?? props.min;
518
+ const maximum = maxDate ?? props.max;
519
+ if (minimum && day < String(minimum).slice(0, 10)) return true;
520
+ if (maximum && day > String(maximum).slice(0, 10)) return true;
521
+ const from = index === 1 ? rangeDates[0] : void 0;
522
+ if (pairedDateTime) {
523
+ const otherEndpoint = index === 0 ? rangeDates[1] : rangeDates[0];
524
+ if (index === 0 && otherEndpoint && day > otherEndpoint) return true;
525
+ if (index === 1 && otherEndpoint && day < otherEndpoint) return true;
526
+ if (otherEndpoint && maxRangeDays && Math.abs(daysBetween(otherEndpoint, day)) >= maxRangeDays) return true;
527
+ } else if (from && maxRangeDays && Math.abs(daysBetween(from, day)) >= maxRangeDays) return true;
528
+ return disabledDate?.(day, { from, type: "date" }) ?? false;
529
+ }
530
+ function buildRangeValue(day, index) {
531
+ return showTime ? withTime(day, times[index], showSecond) : day;
532
+ }
533
+ function updateDraft(next) {
534
+ setDraftValue(next);
535
+ onCalendarChange?.(next);
536
+ }
537
+ function selectDate(day) {
538
+ if (isDisabled(day)) return;
539
+ if (activeIndex === 0 || !rangeDates[0] || rangeDates[1]) {
540
+ const next = [buildRangeValue(day, 0), ""];
541
+ updateDraft(next);
542
+ setActiveIndex(1);
543
+ setHoverDate("");
544
+ return;
545
+ }
546
+ const startDay = rangeDates[0];
547
+ const ordered = day < startDay ? [buildRangeValue(day, 0), buildRangeValue(startDay, 1)] : [draftValue[0], buildRangeValue(day, 1)];
548
+ updateDraft(ordered);
549
+ setActiveIndex(0);
550
+ setHoverDate("");
551
+ if (!resolvedNeedConfirm) {
552
+ setCurrentValue(ordered);
553
+ changeOpen(false);
554
+ }
555
+ }
556
+ function selectDateTime(day, index) {
557
+ if (isDisabled(day, index, true)) return;
558
+ const nextValue = [...draftValue];
559
+ nextValue[index] = buildRangeValue(day, index);
560
+ updateDraft(nextValue);
561
+ setHoverDate("");
562
+ if (!resolvedNeedConfirm && compactDateTime && index === 0) {
563
+ setActiveIndex(1);
564
+ setEndViewMonth(startOfMonth(parseDate(day) ?? /* @__PURE__ */ new Date()));
565
+ return;
566
+ }
567
+ setActiveIndex(index);
568
+ if (!resolvedNeedConfirm && nextValue[0] && nextValue[1] && nextValue[0] <= nextValue[1]) {
569
+ setCurrentValue(nextValue);
570
+ changeOpen(false);
571
+ }
572
+ }
573
+ function changeTime(index, nextTime) {
574
+ const nextTimes = [...times];
575
+ nextTimes[index] = nextTime;
576
+ setTimes(nextTimes);
577
+ setActiveIndex(index);
578
+ if (draftValue[index]) {
579
+ const nextValue = [...draftValue];
580
+ nextValue[index] = withTime(dayFromValue(draftValue[index]), nextTime, showSecond);
581
+ updateDraft(nextValue);
582
+ }
583
+ }
584
+ function confirm() {
585
+ if (compactDateTime && showTime && activeIndex === 0) {
586
+ if (!draftValue[0]) return;
587
+ setActiveIndex(1);
588
+ setEndViewMonth(startOfMonth(parseDate(dayFromValue(draftValue[1] || draftValue[0])) ?? /* @__PURE__ */ new Date()));
589
+ setHoverDate("");
590
+ return;
591
+ }
592
+ if (!draftValue[0] || !draftValue[1] || invalidDateTimeRange) return;
593
+ setCurrentValue(draftValue);
594
+ changeOpen(false);
595
+ }
596
+ function applyPreset(preset) {
597
+ const raw = resolveRangePreset(preset.value);
598
+ const next = [
599
+ normalizeDateValue(raw[0], showTime),
600
+ normalizeDateValue(raw[1], showTime)
601
+ ];
602
+ updateDraft(next);
603
+ setTimes([timePart(next[0], defaultTime), timePart(next[1], defaultTime)]);
604
+ const nextStartMonth = startOfMonth(parseDate(dayFromValue(next[0] || next[1])) ?? /* @__PURE__ */ new Date());
605
+ setViewMonth(nextStartMonth);
606
+ setEndViewMonth(startOfMonth(parseDate(dayFromValue(next[1])) ?? addMonths(nextStartMonth, 1)));
607
+ if (!resolvedNeedConfirm) {
608
+ setCurrentValue(next);
609
+ changeOpen(false);
610
+ }
611
+ }
612
+ function clearValue(event) {
613
+ event.stopPropagation();
614
+ const empty = ["", ""];
615
+ updateDraft(empty);
616
+ setCurrentValue(empty);
617
+ setActiveIndex(0);
618
+ }
619
+ function renderDateTimeGroup(index) {
620
+ const month = index === 0 ? viewMonth : endViewMonth;
621
+ const setMonth = index === 0 ? setViewMonth : setEndViewMonth;
622
+ const endpointLabel = index === 0 ? "\u5F00\u59CB" : "\u7ED3\u675F";
623
+ return /* @__PURE__ */ jsxs2(
624
+ "div",
625
+ {
626
+ className: `sia-date-panel__range-date-time-group${activeIndex === index ? " is-active" : ""}`,
627
+ "aria-label": `${endpointLabel}\u65E5\u671F\u65F6\u95F4`,
628
+ children: [
629
+ /* @__PURE__ */ jsxs2("section", { className: "sia-date-panel__calendar", children: [
630
+ /* @__PURE__ */ jsx2(
631
+ CalendarHeader,
632
+ {
633
+ month,
634
+ label: endpointLabel,
635
+ range: true,
636
+ onPreviousYear: () => setMonth(addMonths(month, -12)),
637
+ onPreviousMonth: () => setMonth(addMonths(month, -1)),
638
+ onNextMonth: () => setMonth(addMonths(month, 1)),
639
+ onNextYear: () => setMonth(addMonths(month, 12))
640
+ }
641
+ ),
642
+ /* @__PURE__ */ jsx2(
643
+ CalendarMonth,
644
+ {
645
+ month,
646
+ range: rangeDates,
647
+ disabledDate: (day) => isDisabled(day, index, true),
648
+ onSelect: (day) => selectDateTime(day, index)
649
+ }
650
+ )
651
+ ] }),
652
+ /* @__PURE__ */ jsx2(
653
+ TimePanel,
654
+ {
655
+ value: times[index],
656
+ showSecond,
657
+ ariaLabel: `${endpointLabel}\u65F6\u95F4`,
658
+ onChange: (nextTime) => changeTime(index, nextTime)
659
+ }
660
+ )
661
+ ]
662
+ },
663
+ endpointLabel
664
+ );
665
+ }
666
+ return /* @__PURE__ */ jsxs2("span", { ref: rootRef, className: `sia-picker sia-picker-range-control sia-picker--${size} sia-picker--${status}${visible ? " is-open" : ""}${disabled ? " is-disabled" : ""} ${className}`.trim(), children: [
667
+ /* @__PURE__ */ jsxs2(
668
+ "button",
669
+ {
670
+ type: "button",
671
+ id: props.id ?? id,
672
+ className: "sia-picker__trigger",
673
+ "aria-label": props["aria-label"] ?? "\u65E5\u671F\u8303\u56F4\u9009\u62E9\u5668",
674
+ "aria-labelledby": props["aria-labelledby"],
675
+ "aria-haspopup": "dialog",
676
+ "aria-expanded": visible,
677
+ "aria-invalid": status === "error" || void 0,
678
+ "aria-describedby": props["aria-describedby"],
679
+ "aria-errormessage": props["aria-errormessage"],
680
+ disabled,
681
+ onClick: () => changeOpen(!visible),
682
+ children: [
683
+ /* @__PURE__ */ jsx2("span", { className: `sia-picker-range-control__value${currentValue[0] ? "" : " is-placeholder"}`, children: currentValue[0] || placeholder[0] }),
684
+ /* @__PURE__ */ jsx2("span", { className: "sia-picker-range-control__separator", children: separator }),
685
+ /* @__PURE__ */ jsx2("span", { className: `sia-picker-range-control__value${currentValue[1] ? "" : " is-placeholder"}`, children: currentValue[1] || placeholder[1] }),
686
+ allowClear && (currentValue[0] || currentValue[1]) && !disabled ? /* @__PURE__ */ jsx2("span", { role: "button", className: "sia-picker__clear", "aria-label": "\u6E05\u9664\u65E5\u671F\u8303\u56F4", onClick: clearValue, children: /* @__PURE__ */ jsx2(Icon, { name: "circle-close", variant: "filled", size: 15 }) }) : null,
687
+ /* @__PURE__ */ jsx2("span", { className: "sia-picker__icon", "aria-hidden": "true", children: suffixIcon ?? /* @__PURE__ */ jsx2(Icon, { name: "calendar", size: 16 }) })
688
+ ]
689
+ }
690
+ ),
691
+ /* @__PURE__ */ jsxs2(PopupPortal, { ref: popupRef, anchorRef: rootRef, open: visible, className: `sia-date-panel sia-date-panel--range${showTime ? ` sia-date-panel--with-time sia-date-panel--range-time-${compactDateTime ? "compact" : "paired"}` : ""}${presets?.length ? " sia-date-panel--with-presets" : ""}`, role: "dialog", "aria-label": "\u65E5\u671F\u8303\u56F4\u9009\u62E9\u9762\u677F", children: [
692
+ /* @__PURE__ */ jsx2("div", { className: "sia-date-panel__body", children: showTime ? /* @__PURE__ */ jsx2("div", { className: "sia-date-panel__range-date-time", children: compactDateTime ? renderDateTimeGroup(activeIndex) : /* @__PURE__ */ jsxs2(Fragment, { children: [
693
+ renderDateTimeGroup(0),
694
+ renderDateTimeGroup(1)
695
+ ] }) }) : /* @__PURE__ */ jsxs2("div", { className: "sia-date-panel__range-calendars", children: [
696
+ /* @__PURE__ */ jsxs2("section", { className: "sia-date-panel__calendar", children: [
697
+ /* @__PURE__ */ jsx2(
698
+ CalendarHeader,
699
+ {
700
+ month: viewMonth,
701
+ range: true,
702
+ onPreviousYear: () => setViewMonth(addMonths(viewMonth, -12)),
703
+ onPreviousMonth: () => setViewMonth(addMonths(viewMonth, -1))
704
+ }
705
+ ),
706
+ /* @__PURE__ */ jsx2(CalendarMonth, { month: viewMonth, range: rangeDates, previewEnd: activeIndex === 1 ? hoverDate : "", disabledDate: isDisabled, onSelect: selectDate, onHover: activeIndex === 1 ? setHoverDate : void 0 })
707
+ ] }),
708
+ /* @__PURE__ */ jsxs2("section", { className: "sia-date-panel__calendar", children: [
709
+ /* @__PURE__ */ jsx2(
710
+ CalendarHeader,
711
+ {
712
+ month: addMonths(viewMonth, 1),
713
+ range: true,
714
+ onNextMonth: () => setViewMonth(addMonths(viewMonth, 1)),
715
+ onNextYear: () => setViewMonth(addMonths(viewMonth, 12))
716
+ }
717
+ ),
718
+ /* @__PURE__ */ jsx2(CalendarMonth, { month: addMonths(viewMonth, 1), range: rangeDates, previewEnd: activeIndex === 1 ? hoverDate : "", disabledDate: isDisabled, onSelect: selectDate, onHover: activeIndex === 1 ? setHoverDate : void 0 })
719
+ ] })
720
+ ] }) }),
721
+ /* @__PURE__ */ jsx2(
722
+ DatePanelFooter,
723
+ {
724
+ showToday: showToday && !presets?.length,
725
+ needConfirm: resolvedNeedConfirm,
726
+ disabledConfirm: compactDateTime && showTime && activeIndex === 0 ? !draftValue[0] : !draftValue[0] || !draftValue[1] || invalidDateTimeRange,
727
+ confirmText: compactDateTime && showTime && activeIndex === 0 ? "\u4E0B\u4E00\u6B65" : "\u786E\u5B9A",
728
+ extra: /* @__PURE__ */ jsxs2(Fragment, { children: [
729
+ presets?.map((preset, index) => /* @__PURE__ */ jsx2("button", { type: "button", onClick: () => applyPreset(preset), children: preset.label }, index)),
730
+ compactDateTime && showTime && activeIndex === 1 ? /* @__PURE__ */ jsx2("button", { type: "button", onClick: () => {
731
+ setActiveIndex(0);
732
+ setViewMonth(startOfMonth(parseDate(dayFromValue(draftValue[0])) ?? /* @__PURE__ */ new Date()));
733
+ }, children: "\u4E0A\u4E00\u6B65" }) : null,
734
+ invalidDateTimeRange ? /* @__PURE__ */ jsx2("small", { className: "sia-date-panel__range-error", children: "\u7ED3\u675F\u65F6\u95F4\u4E0D\u80FD\u65E9\u4E8E\u5F00\u59CB\u65F6\u95F4" }) : maxRangeDays ? /* @__PURE__ */ jsxs2("small", { children: [
735
+ "\u6700\u591A\u9009\u62E9 ",
736
+ maxRangeDays,
737
+ " \u5929"
738
+ ] }) : null
739
+ ] }),
740
+ onToday: () => showTime ? selectDateTime(dateKey(/* @__PURE__ */ new Date()), activeIndex) : selectDate(dateKey(/* @__PURE__ */ new Date())),
741
+ onConfirm: confirm
742
+ }
743
+ )
744
+ ] })
745
+ ] });
746
+ }
747
+ ((DatePicker2) => {
748
+ DatePicker2.RangePicker = DateRangePicker;
749
+ })(DatePicker || (DatePicker = {}));
750
+
751
+ // src/components/SelectDateRange.tsx
752
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
753
+ function SelectDateRange({
754
+ options,
755
+ value,
756
+ defaultValue,
757
+ selectPlaceholder = "\u8BF7\u9009\u62E9\u7C7B\u578B",
758
+ selectWidth = 180,
759
+ rangePlaceholder = ["\u5F00\u59CB\u65E5\u671F", "\u7ED3\u675F\u65E5\u671F"],
760
+ selectAriaLabel = "\u9009\u62E9\u7C7B\u578B",
761
+ rangeAriaLabel = "\u65E5\u671F\u8303\u56F4",
762
+ presets,
763
+ size = "medium",
764
+ status = "default",
765
+ disabled = false,
766
+ onChange,
767
+ className = "",
768
+ style,
769
+ ...props
770
+ }) {
771
+ const initialValue = defaultValue ?? { select: options[0]?.value ?? "", range: ["", ""] };
772
+ const [currentValue, setCurrentValue] = useControllableState({ value, defaultValue: initialValue, onChange });
773
+ return /* @__PURE__ */ jsxs3("div", { className: `sia-select-date-range sia-select-date-range--${size} ${className}`.trim(), role: "group", "aria-label": `${selectAriaLabel}\u4E0E${rangeAriaLabel}`, ...props, style: { ...style, "--sia-select-date-range-select-width": typeof selectWidth === "number" ? `${selectWidth}px` : selectWidth }, children: [
774
+ /* @__PURE__ */ jsx3(
775
+ Select,
776
+ {
777
+ className: "sia-select-date-range__select",
778
+ "aria-label": selectAriaLabel,
779
+ options,
780
+ value: currentValue.select,
781
+ placeholder: selectPlaceholder,
782
+ size,
783
+ status,
784
+ disabled,
785
+ onChange: (nextSelect) => {
786
+ if (nextSelect === null || Array.isArray(nextSelect)) return;
787
+ setCurrentValue({ ...currentValue, select: nextSelect });
788
+ }
789
+ }
790
+ ),
791
+ /* @__PURE__ */ jsx3(
792
+ DatePicker.RangePicker,
793
+ {
794
+ className: "sia-select-date-range__picker",
795
+ "aria-label": rangeAriaLabel,
796
+ value: currentValue.range,
797
+ placeholder: rangePlaceholder,
798
+ presets,
799
+ size,
800
+ status,
801
+ disabled,
802
+ onChange: (nextRange) => setCurrentValue({ ...currentValue, range: nextRange })
803
+ }
804
+ )
805
+ ] });
806
+ }
807
+
808
+ export {
809
+ TimePanel,
810
+ DatePicker,
811
+ SelectDateRange
812
+ };