dishui 0.0.67 → 0.0.68

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 (32) hide show
  1. package/dist/calendar.js +5 -0
  2. package/dist/components/Demo/index.js +76 -80
  3. package/dist/components/Demo/index.js.map +1 -1
  4. package/dist/components/pro/Calendar/Calendar.js +576 -0
  5. package/dist/components/pro/Calendar/Calendar.js.map +1 -0
  6. package/dist/components/pro/Calendar/hooks/useCalendarDrag.js +104 -0
  7. package/dist/components/pro/Calendar/hooks/useCalendarDrag.js.map +1 -0
  8. package/dist/components/pro/Calendar/hooks/useCalendarState.js +187 -0
  9. package/dist/components/pro/Calendar/hooks/useCalendarState.js.map +1 -0
  10. package/dist/components/pro/Calendar/utils.js +193 -0
  11. package/dist/components/pro/Calendar/utils.js.map +1 -0
  12. package/dist/components/pro/Gantt/Gantt.js +868 -0
  13. package/dist/components/pro/Gantt/Gantt.js.map +1 -0
  14. package/dist/components/pro/Gantt/hooks/useGanttDrag.js +99 -0
  15. package/dist/components/pro/Gantt/hooks/useGanttDrag.js.map +1 -0
  16. package/dist/components/pro/Gantt/hooks/useGanttState.js +95 -0
  17. package/dist/components/pro/Gantt/hooks/useGanttState.js.map +1 -0
  18. package/dist/components/pro/Gantt/utils.js +236 -0
  19. package/dist/components/pro/Gantt/utils.js.map +1 -0
  20. package/dist/dishui.css +1 -1
  21. package/dist/gantt.js +5 -0
  22. package/dist/hooks/useCopyToClipboard.d.ts +2 -1
  23. package/dist/hooks/useCopyToClipboard.js +17 -9
  24. package/dist/hooks/useCopyToClipboard.js.map +1 -1
  25. package/dist/index.d.ts +4 -0
  26. package/dist/index.js +9 -1
  27. package/dist/utils/i18n.js +40 -0
  28. package/dist/utils/i18n.js.map +1 -1
  29. package/package.json +12 -1
  30. package/dist/pages/components/Gantt/index.d.ts +0 -3
  31. package/dist/pages/components/Gantt/index.en.d.ts +0 -3
  32. package/dist/pages/components/Gantt/index.zh.d.ts +0 -3
@@ -0,0 +1,104 @@
1
+ import { minutesToTime as e, timeToMinutes as t } from "../utils.js";
2
+ import { useCallback as n, useRef as r, useState as i } from "react";
3
+ //#region src/components/pro/Calendar/hooks/useCalendarDrag.ts
4
+ function a(a) {
5
+ let { readOnly: o = !1, onEntryDrop: s, onEntryUpdate: c } = a, [l, u] = i(null), [d, f] = i(null), p = r(null), m = n((e, n) => {
6
+ if (o) {
7
+ e.preventDefault();
8
+ return;
9
+ }
10
+ let r = {
11
+ entry: n,
12
+ fromDate: n.date,
13
+ fromTime: n.startTime,
14
+ isResize: !1,
15
+ startY: e.clientY,
16
+ originalDuration: n.startTime && n.endTime ? t(n.endTime) - t(n.startTime) : 60
17
+ };
18
+ if (u(r), p.current = r, e.dataTransfer.setData("text/plain", n.id), e.dataTransfer.effectAllowed = "move", e.currentTarget instanceof HTMLElement) {
19
+ let t = e.currentTarget.getBoundingClientRect();
20
+ e.dataTransfer.setDragImage(e.currentTarget, e.clientX - t.left, e.clientY - t.top);
21
+ }
22
+ }, [o]), h = n((e, n) => {
23
+ if (o) {
24
+ e.preventDefault();
25
+ return;
26
+ }
27
+ e.stopPropagation();
28
+ let r = {
29
+ entry: n,
30
+ fromDate: n.date,
31
+ fromTime: n.startTime,
32
+ isResize: !0,
33
+ startY: e.clientY,
34
+ originalDuration: n.startTime && n.endTime ? t(n.endTime) - t(n.startTime) : 60
35
+ };
36
+ u(r), p.current = r, e.dataTransfer.setData("text/plain", n.id), e.dataTransfer.effectAllowed = "move";
37
+ let i = new Image();
38
+ i.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7", e.dataTransfer.setDragImage(i, 0, 0);
39
+ }, [o]), g = n((e, t, n) => {
40
+ e.preventDefault(), e.dataTransfer.dropEffect = "move", f({
41
+ date: t,
42
+ time: n
43
+ });
44
+ }, []), _ = n((e) => {
45
+ let t = e.relatedTarget;
46
+ (!t || !e.currentTarget.contains(t)) && f(null);
47
+ }, []), v = n((n, r, i) => {
48
+ n.preventDefault();
49
+ let a = p.current;
50
+ if (a) {
51
+ if (a.isResize) {
52
+ if (i && a.entry.startTime) {
53
+ let n = t(a.entry.startTime), o = t(i), l = Math.max(o + 30, n + 30), u = Math.min(l, 1440), d = {
54
+ ...a.entry,
55
+ endTime: e(u)
56
+ };
57
+ c?.(d), s?.({
58
+ entry: a.entry,
59
+ fromDate: a.fromDate,
60
+ toDate: r,
61
+ fromTime: a.entry.endTime,
62
+ toTime: e(u)
63
+ });
64
+ }
65
+ } else {
66
+ let n = {
67
+ entry: a.entry,
68
+ fromDate: a.fromDate,
69
+ toDate: r,
70
+ fromTime: a.fromTime,
71
+ toTime: i
72
+ }, o = {
73
+ ...a.entry,
74
+ date: r
75
+ };
76
+ if (i && a.entry.startTime) {
77
+ let n = a.originalDuration, r = t(i), s = Math.min(r + n, 1440);
78
+ o.startTime = i, o.endTime = e(s);
79
+ } else i && a.entry.allDay && (o.startTime = i, o.endTime = e(Math.min(t(i) + 60, 1440)), o.allDay = !1);
80
+ c?.(o), s?.(n);
81
+ }
82
+ u(null), f(null), p.current = null;
83
+ }
84
+ }, [s, c]), y = n(() => {
85
+ u(null), f(null), p.current = null;
86
+ }, []);
87
+ return {
88
+ isDragging: l !== null,
89
+ draggingEntryId: l?.entry.id ?? null,
90
+ dragState: l,
91
+ dropTarget: d,
92
+ isDropTarget: n((e, t) => !(!d || d.date !== e || t !== void 0 && d.time !== t), [d]),
93
+ handleDragStart: m,
94
+ handleResizeStart: h,
95
+ handleDragOver: g,
96
+ handleDragLeave: _,
97
+ handleDrop: v,
98
+ handleDragEnd: y
99
+ };
100
+ }
101
+ //#endregion
102
+ export { a as useCalendarDrag };
103
+
104
+ //# sourceMappingURL=useCalendarDrag.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useCalendarDrag.js","names":[],"sources":["../../../../../src/components/pro/Calendar/hooks/useCalendarDrag.ts"],"sourcesContent":["/**\n * useCalendarDrag - Drag-and-drop interaction hook for Calendar entries.\n *\n * Uses the native HTML5 Drag and Drop API to support:\n * - Moving entries between date cells (month view)\n * - Moving entries between time slots (week/day view)\n * - Resizing entry duration in time-based views\n */\n\nimport { useState, useCallback, useRef } from \"react\";\nimport type { CalendarEntry, CalendarDragEvent } from \"../types\";\nimport { timeToMinutes, minutesToTime } from \"../utils\";\n\n// ─── Types ────────────────────────────────────────────────────────\n\nexport interface DragState {\n /** The entry being dragged */\n entry: CalendarEntry;\n /** The original date of the entry */\n fromDate: string;\n /** The original start time (if time-based) */\n fromTime?: string;\n /** Whether we're resizing (bottom edge) vs moving */\n isResize: boolean;\n /** Initial mouse Y when drag started (for resize calculations) */\n startY: number;\n /** Original entry duration in minutes (for resize) */\n originalDuration: number;\n}\n\nexport interface DropTarget {\n /** Target date (YYYY-MM-DD) */\n date: string;\n /** Target time slot (HH:mm) — only in week/day view */\n time?: string;\n}\n\nexport interface UseCalendarDragOptions {\n readOnly?: boolean;\n onEntryDrop?: (event: CalendarDragEvent) => void;\n onEntryUpdate?: (entry: CalendarEntry) => void;\n}\n\n// ─── Hook ─────────────────────────────────────────────────────────\n\nexport function useCalendarDrag(options: UseCalendarDragOptions) {\n const { readOnly = false, onEntryDrop, onEntryUpdate } = options;\n\n const [dragState, setDragState] = useState<DragState | null>(null);\n const [dropTarget, setDropTarget] = useState<DropTarget | null>(null);\n const dragRef = useRef<DragState | null>(null);\n\n // ─── Drag Start ─────────────────────────────────────────────────\n\n const handleDragStart = useCallback(\n (e: React.DragEvent, entry: CalendarEntry) => {\n if (readOnly) {\n e.preventDefault();\n return;\n }\n\n const state: DragState = {\n entry,\n fromDate: entry.date,\n fromTime: entry.startTime,\n isResize: false,\n startY: e.clientY,\n originalDuration:\n entry.startTime && entry.endTime\n ? timeToMinutes(entry.endTime) - timeToMinutes(entry.startTime)\n : 60,\n };\n\n setDragState(state);\n dragRef.current = state;\n\n // Set drag data for the native API\n e.dataTransfer.setData(\"text/plain\", entry.id);\n e.dataTransfer.effectAllowed = \"move\";\n\n // Set a custom drag image (optional: use the element itself)\n if (e.currentTarget instanceof HTMLElement) {\n const rect = e.currentTarget.getBoundingClientRect();\n e.dataTransfer.setDragImage(\n e.currentTarget,\n e.clientX - rect.left,\n e.clientY - rect.top,\n );\n }\n },\n [readOnly],\n );\n\n // ─── Resize Start ───────────────────────────────────────────────\n\n const handleResizeStart = useCallback(\n (e: React.DragEvent, entry: CalendarEntry) => {\n if (readOnly) {\n e.preventDefault();\n return;\n }\n\n e.stopPropagation();\n\n const state: DragState = {\n entry,\n fromDate: entry.date,\n fromTime: entry.startTime,\n isResize: true,\n startY: e.clientY,\n originalDuration:\n entry.startTime && entry.endTime\n ? timeToMinutes(entry.endTime) - timeToMinutes(entry.startTime)\n : 60,\n };\n\n setDragState(state);\n dragRef.current = state;\n\n e.dataTransfer.setData(\"text/plain\", entry.id);\n e.dataTransfer.effectAllowed = \"move\";\n\n // Use a tiny transparent image for resize to show native cursor\n const img = new Image();\n img.src =\n \"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\";\n e.dataTransfer.setDragImage(img, 0, 0);\n },\n [readOnly],\n );\n\n // ─── Drag Over (drop target) ────────────────────────────────────\n\n const handleDragOver = useCallback(\n (e: React.DragEvent, date: string, time?: string) => {\n e.preventDefault();\n e.dataTransfer.dropEffect = \"move\";\n setDropTarget({ date, time });\n },\n [],\n );\n\n // ─── Drag Leave ─────────────────────────────────────────────────\n\n const handleDragLeave = useCallback((e: React.DragEvent) => {\n // Only clear if leaving the actual target (not entering a child)\n const relatedTarget = e.relatedTarget as HTMLElement | null;\n if (!relatedTarget || !e.currentTarget.contains(relatedTarget)) {\n setDropTarget(null);\n }\n }, []);\n\n // ─── Drop ───────────────────────────────────────────────────────\n\n const handleDrop = useCallback(\n (e: React.DragEvent, date: string, time?: string) => {\n e.preventDefault();\n const state = dragRef.current;\n if (!state) return;\n\n if (state.isResize) {\n // Handle resize: compute new end time based on drop position\n // The drop time IS the new end time (snapped to slot)\n if (time && state.entry.startTime) {\n const startMinutes = timeToMinutes(state.entry.startTime);\n const dropMinutes = timeToMinutes(time);\n // Ensure minimum 30-minute duration\n const endMinutes = Math.max(dropMinutes + 30, startMinutes + 30);\n const clampedEnd = Math.min(endMinutes, 24 * 60);\n\n const updatedEntry: CalendarEntry = {\n ...state.entry,\n endTime: minutesToTime(clampedEnd),\n };\n\n onEntryUpdate?.(updatedEntry);\n onEntryDrop?.({\n entry: state.entry,\n fromDate: state.fromDate,\n toDate: date,\n fromTime: state.entry.endTime,\n toTime: minutesToTime(clampedEnd),\n });\n }\n } else {\n // Handle move\n const dragEvent: CalendarDragEvent = {\n entry: state.entry,\n fromDate: state.fromDate,\n toDate: date,\n fromTime: state.fromTime,\n toTime: time,\n };\n\n // Compute the updated entry\n const updatedEntry: CalendarEntry = {\n ...state.entry,\n date,\n };\n\n // If we have time info, update start/end times\n if (time && state.entry.startTime) {\n const duration = state.originalDuration;\n const newStartMinutes = timeToMinutes(time);\n const newEndMinutes = Math.min(newStartMinutes + duration, 24 * 60);\n updatedEntry.startTime = time;\n updatedEntry.endTime = minutesToTime(newEndMinutes);\n } else if (time && state.entry.allDay) {\n // Moving an all-day event into a time slot\n updatedEntry.startTime = time;\n updatedEntry.endTime = minutesToTime(\n Math.min(timeToMinutes(time) + 60, 24 * 60),\n );\n updatedEntry.allDay = false;\n }\n\n onEntryUpdate?.(updatedEntry);\n onEntryDrop?.(dragEvent);\n }\n\n // Clear state\n setDragState(null);\n setDropTarget(null);\n dragRef.current = null;\n },\n [onEntryDrop, onEntryUpdate],\n );\n\n // ─── Drag End (cleanup) ─────────────────────────────────────────\n\n const handleDragEnd = useCallback(() => {\n setDragState(null);\n setDropTarget(null);\n dragRef.current = null;\n }, []);\n\n // ─── Computed State ─────────────────────────────────────────────\n\n const isDragging = dragState !== null;\n const draggingEntryId = dragState?.entry.id ?? null;\n\n const isDropTarget = useCallback(\n (date: string, time?: string): boolean => {\n if (!dropTarget) return false;\n if (dropTarget.date !== date) return false;\n if (time !== undefined && dropTarget.time !== time) return false;\n return true;\n },\n [dropTarget],\n );\n\n return {\n isDragging,\n draggingEntryId,\n dragState,\n dropTarget,\n isDropTarget,\n handleDragStart,\n handleResizeStart,\n handleDragOver,\n handleDragLeave,\n handleDrop,\n handleDragEnd,\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,187 @@
1
+ import { DEFAULT_COLOR_OPTIONS as e, LABELS_EN as t, LABELS_ZH as n, addDays as r, formatDate as i, generateId as a, getMonthDates as o, getWeekDates as s, parseDate as c, todayStr as l } from "../utils.js";
2
+ import { useCallback as u, useMemo as d, useRef as f, useState as p } from "react";
3
+ //#region src/components/pro/Calendar/hooks/useCalendarState.ts
4
+ function m(m) {
5
+ let { entries: h, holidays: g, defaultView: _ = "month", defaultDate: v, locale: y = "en", labels: b, colorOptions: x = e, readOnly: S = !1, onEntryAdd: C, onEntryUpdate: w, onEntryDelete: T, onViewChange: E } = m, D = d(() => ({
6
+ ...y === "zh" ? n : t,
7
+ ...b
8
+ }), [y, b]), [O, k] = p(() => v || l()), A = d(() => c(O) || /* @__PURE__ */ new Date(), [O]), [j, M] = p(_), N = u((e) => {
9
+ M(e), E?.(e);
10
+ }, [E]), P = h !== void 0 && (C !== void 0 || w !== void 0 || T !== void 0), [F, I] = p(() => h || []), L = f(h);
11
+ P && h !== L.current && (L.current = h);
12
+ let R = P ? h : F, z = u(() => {
13
+ k(l());
14
+ }, []), B = u((e) => {
15
+ k(e);
16
+ }, []), V = u(() => {
17
+ let e = c(O);
18
+ if (e) switch (j) {
19
+ case "month": {
20
+ let t = new Date(e.getFullYear(), e.getMonth() + 1, 1);
21
+ k(i(t));
22
+ break;
23
+ }
24
+ case "week": {
25
+ let t = r(e, 7);
26
+ k(i(t));
27
+ break;
28
+ }
29
+ case "day": {
30
+ let t = r(e, 1);
31
+ k(i(t));
32
+ break;
33
+ }
34
+ }
35
+ }, [O, j]), H = u(() => {
36
+ let e = c(O);
37
+ if (e) switch (j) {
38
+ case "month": {
39
+ let t = new Date(e.getFullYear(), e.getMonth() - 1, 1);
40
+ k(i(t));
41
+ break;
42
+ }
43
+ case "week": {
44
+ let t = r(e, -7);
45
+ k(i(t));
46
+ break;
47
+ }
48
+ case "day": {
49
+ let t = r(e, -1);
50
+ k(i(t));
51
+ break;
52
+ }
53
+ }
54
+ }, [O, j]), U = d(() => {
55
+ let e = A, t = D.monthNames[e.getMonth()], n = e.getFullYear();
56
+ switch (j) {
57
+ case "month": return `${t} ${n}`;
58
+ case "week": {
59
+ let t = s(e), r = t[0], i = t[6];
60
+ return r.getMonth() === i.getMonth() ? `${D.monthNames[r.getMonth()]} ${r.getDate()} - ${i.getDate()}, ${n}` : `${D.monthNames[r.getMonth()]} ${r.getDate()} - ${D.monthNames[i.getMonth()]} ${i.getDate()}, ${n}`;
61
+ }
62
+ case "day": return `${t} ${e.getDate()}, ${n}`;
63
+ }
64
+ }, [
65
+ A,
66
+ j,
67
+ D
68
+ ]), W = d(() => {
69
+ let e = A;
70
+ return o(e.getFullYear(), e.getMonth() + 1);
71
+ }, [A]), G = d(() => s(A), [A]), K = u((e) => {
72
+ let t = {
73
+ ...e,
74
+ id: e.id || a()
75
+ };
76
+ return P || I((e) => [...e, t]), C?.(t), t;
77
+ }, [P, C]), q = u((e) => {
78
+ P || I((t) => t.map((t) => t.id === e.id ? e : t)), w?.(e);
79
+ }, [P, w]), J = u((e) => {
80
+ P || I((t) => t.filter((t) => t.id !== e)), T?.(e);
81
+ }, [P, T]), [Y, X] = p({
82
+ open: !1,
83
+ mode: "add",
84
+ entry: {}
85
+ }), Z = u((e, t) => {
86
+ S || X({
87
+ open: !0,
88
+ mode: "add",
89
+ entry: {
90
+ date: e || O,
91
+ startTime: t || void 0,
92
+ endTime: t ? (() => {
93
+ let [e, n] = t.split(":").map(Number), r = e * 60 + n + 60, i = Math.min(Math.floor(r / 60), 23), a = r % 60;
94
+ return `${String(i).padStart(2, "0")}:${String(a).padStart(2, "0")}`;
95
+ })() : void 0,
96
+ allDay: !t,
97
+ color: x[0]
98
+ }
99
+ });
100
+ }, [
101
+ S,
102
+ O,
103
+ x
104
+ ]), Q = u((e) => {
105
+ S || X({
106
+ open: !0,
107
+ mode: "edit",
108
+ entry: { ...e }
109
+ });
110
+ }, [S]), $ = u(() => {
111
+ X((e) => ({
112
+ ...e,
113
+ open: !1
114
+ }));
115
+ }, []), ee = u((e) => {
116
+ if (Y.mode === "add") {
117
+ let t = K({
118
+ title: e.title || "",
119
+ date: e.date || O,
120
+ startTime: e.allDay ? void 0 : e.startTime,
121
+ endTime: e.allDay ? void 0 : e.endTime,
122
+ color: e.color || x[0],
123
+ description: e.description,
124
+ allDay: e.allDay ?? !0
125
+ });
126
+ return $(), t;
127
+ }
128
+ {
129
+ let t = {
130
+ ...Y.entry,
131
+ ...e,
132
+ id: Y.entry.id,
133
+ startTime: e.allDay ? void 0 : e.startTime,
134
+ endTime: e.allDay ? void 0 : e.endTime
135
+ };
136
+ return q(t), $(), t;
137
+ }
138
+ }, [
139
+ Y,
140
+ K,
141
+ q,
142
+ $,
143
+ O,
144
+ x
145
+ ]), te = u(() => {
146
+ Y.entry.id && J(Y.entry.id), $();
147
+ }, [
148
+ Y.entry.id,
149
+ J,
150
+ $
151
+ ]);
152
+ return {
153
+ currentDate: O,
154
+ currentDateObj: A,
155
+ viewMode: j,
156
+ entries: R,
157
+ labels: D,
158
+ colorOptions: x,
159
+ holidays: g,
160
+ readOnly: S,
161
+ goToToday: z,
162
+ goToDate: B,
163
+ goNext: V,
164
+ goPrev: H,
165
+ title: U,
166
+ setViewMode: N,
167
+ monthDates: W,
168
+ weekDates: G,
169
+ addEntry: K,
170
+ updateEntry: q,
171
+ deleteEntry: J,
172
+ getEntriesForDate: u((e) => R.filter((t) => t.date === e).sort((e, t) => {
173
+ let n = e.allDay || !e.startTime, r = t.allDay || !t.startTime;
174
+ return n && !r ? -1 : !n && r ? 1 : n && r ? 0 : (e.startTime || "").localeCompare(t.startTime || "");
175
+ }), [R]),
176
+ modalState: Y,
177
+ openAddModal: Z,
178
+ openEditModal: Q,
179
+ closeModal: $,
180
+ saveModal: ee,
181
+ deleteModalEntry: te
182
+ };
183
+ }
184
+ //#endregion
185
+ export { m as useCalendarState };
186
+
187
+ //# sourceMappingURL=useCalendarState.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useCalendarState.js","names":[],"sources":["../../../../../src/components/pro/Calendar/hooks/useCalendarState.ts"],"sourcesContent":["/**\n * useCalendarState - Core state management hook for the Calendar component.\n *\n * Manages current date, view mode, entries CRUD, navigation,\n * and modal state for add/edit entry forms.\n */\n\nimport { useState, useCallback, useMemo, useRef } from \"react\";\nimport type {\n CalendarViewMode,\n CalendarEntry,\n CalendarLabels,\n HolidayCalendar,\n} from \"../types\";\nimport {\n formatDate,\n todayStr,\n parseDate,\n addDays,\n generateId,\n getMonthDates,\n getWeekDates,\n LABELS_EN,\n LABELS_ZH,\n DEFAULT_COLOR_OPTIONS,\n} from \"../utils\";\n\n// ─── Options ──────────────────────────────────────────────────────\n\nexport interface UseCalendarStateOptions {\n entries?: CalendarEntry[];\n holidays?: HolidayCalendar;\n defaultView?: CalendarViewMode;\n defaultDate?: string;\n locale?: \"zh\" | \"en\";\n labels?: CalendarLabels;\n colorOptions?: string[];\n readOnly?: boolean;\n onEntryAdd?: (entry: CalendarEntry) => void;\n onEntryUpdate?: (entry: CalendarEntry) => void;\n onEntryDelete?: (entryId: string) => void;\n onViewChange?: (view: CalendarViewMode) => void;\n}\n\n// ─── Modal State ──────────────────────────────────────────────────\n\nexport interface EntryModalState {\n open: boolean;\n mode: \"add\" | \"edit\";\n entry: Partial<CalendarEntry>;\n}\n\n// ─── Hook ─────────────────────────────────────────────────────────\n\nexport function useCalendarState(options: UseCalendarStateOptions) {\n const {\n entries: externalEntries,\n holidays,\n defaultView = \"month\",\n defaultDate,\n locale = \"en\",\n labels: userLabels,\n colorOptions = DEFAULT_COLOR_OPTIONS,\n readOnly = false,\n onEntryAdd,\n onEntryUpdate,\n onEntryDelete,\n onViewChange,\n } = options;\n\n // ─── Labels ───────────────────────────────────────────────────\n\n const labels: Required<CalendarLabels> = useMemo(() => {\n const base = locale === \"zh\" ? LABELS_ZH : LABELS_EN;\n return { ...base, ...userLabels } as Required<CalendarLabels>;\n }, [locale, userLabels]);\n\n // ─── Current Date ─────────────────────────────────────────────\n\n const [currentDate, setCurrentDate] = useState<string>(() => {\n if (defaultDate) return defaultDate;\n return todayStr();\n });\n\n const currentDateObj = useMemo(() => {\n const d = parseDate(currentDate);\n return d || new Date();\n }, [currentDate]);\n\n // ─── View Mode ────────────────────────────────────────────────\n\n const [viewMode, setViewModeRaw] = useState<CalendarViewMode>(defaultView);\n\n const setViewMode = useCallback(\n (view: CalendarViewMode) => {\n setViewModeRaw(view);\n onViewChange?.(view);\n },\n [onViewChange],\n );\n\n // ─── Internal Entries ─────────────────────────────────────────\n\n // Controlled mode: external entries + at least one CRUD callback provided.\n // Otherwise entries prop is treated as initial value, managed internally.\n const isControlled =\n externalEntries !== undefined &&\n (onEntryAdd !== undefined ||\n onEntryUpdate !== undefined ||\n onEntryDelete !== undefined);\n\n const [internalEntries, setInternalEntries] = useState<CalendarEntry[]>(\n () => externalEntries || [],\n );\n\n // Sync internal state when external entries change in controlled mode\n // so the component always reflects the parent's truth.\n const prevExternalRef = useRef(externalEntries);\n if (isControlled && externalEntries !== prevExternalRef.current) {\n prevExternalRef.current = externalEntries;\n // will be picked up on next render via `entries` below\n }\n\n const entries = isControlled ? externalEntries! : internalEntries;\n\n // ─── Navigation ───────────────────────────────────────────────\n\n const goToToday = useCallback(() => {\n setCurrentDate(todayStr());\n }, []);\n\n const goToDate = useCallback((date: string) => {\n setCurrentDate(date);\n }, []);\n\n const goNext = useCallback(() => {\n const d = parseDate(currentDate);\n if (!d) return;\n\n switch (viewMode) {\n case \"month\": {\n const next = new Date(d.getFullYear(), d.getMonth() + 1, 1);\n setCurrentDate(formatDate(next));\n break;\n }\n case \"week\": {\n const next = addDays(d, 7);\n setCurrentDate(formatDate(next));\n break;\n }\n case \"day\": {\n const next = addDays(d, 1);\n setCurrentDate(formatDate(next));\n break;\n }\n }\n }, [currentDate, viewMode]);\n\n const goPrev = useCallback(() => {\n const d = parseDate(currentDate);\n if (!d) return;\n\n switch (viewMode) {\n case \"month\": {\n const prev = new Date(d.getFullYear(), d.getMonth() - 1, 1);\n setCurrentDate(formatDate(prev));\n break;\n }\n case \"week\": {\n const prev = addDays(d, -7);\n setCurrentDate(formatDate(prev));\n break;\n }\n case \"day\": {\n const prev = addDays(d, -1);\n setCurrentDate(formatDate(prev));\n break;\n }\n }\n }, [currentDate, viewMode]);\n\n // ─── Title Display ────────────────────────────────────────────\n\n const title = useMemo(() => {\n const d = currentDateObj;\n const monthName = labels.monthNames![d.getMonth()];\n const year = d.getFullYear();\n\n switch (viewMode) {\n case \"month\":\n return `${monthName} ${year}`;\n case \"week\": {\n const weekDates = getWeekDates(d);\n const start = weekDates[0];\n const end = weekDates[6];\n if (start.getMonth() === end.getMonth()) {\n return `${labels.monthNames![start.getMonth()]} ${start.getDate()} - ${end.getDate()}, ${year}`;\n }\n return `${labels.monthNames![start.getMonth()]} ${start.getDate()} - ${labels.monthNames![end.getMonth()]} ${end.getDate()}, ${year}`;\n }\n case \"day\":\n return `${monthName} ${d.getDate()}, ${year}`;\n }\n }, [currentDateObj, viewMode, labels]);\n\n // ─── Grid Dates ───────────────────────────────────────────────\n\n const monthDates = useMemo(() => {\n const d = currentDateObj;\n return getMonthDates(d.getFullYear(), d.getMonth() + 1);\n }, [currentDateObj]);\n\n const weekDates = useMemo(() => {\n return getWeekDates(currentDateObj);\n }, [currentDateObj]);\n\n // ─── Entry CRUD ───────────────────────────────────────────────\n\n const addEntry = useCallback(\n (entry: Omit<CalendarEntry, \"id\"> & { id?: string }) => {\n const newEntry = {\n ...entry,\n id: entry.id || generateId(),\n } as CalendarEntry;\n\n if (!isControlled) {\n setInternalEntries((prev) => [...prev, newEntry]);\n }\n onEntryAdd?.(newEntry);\n return newEntry;\n },\n [isControlled, onEntryAdd],\n );\n\n const updateEntry = useCallback(\n (entry: CalendarEntry) => {\n if (!isControlled) {\n setInternalEntries((prev) =>\n prev.map((e) => (e.id === entry.id ? entry : e)),\n );\n }\n onEntryUpdate?.(entry);\n },\n [isControlled, onEntryUpdate],\n );\n\n const deleteEntry = useCallback(\n (entryId: string) => {\n if (!isControlled) {\n setInternalEntries((prev) => prev.filter((e) => e.id !== entryId));\n }\n onEntryDelete?.(entryId);\n },\n [isControlled, onEntryDelete],\n );\n\n // ─── Entry Modal State ────────────────────────────────────────\n\n const [modalState, setModalState] = useState<EntryModalState>({\n open: false,\n mode: \"add\",\n entry: {},\n });\n\n const openAddModal = useCallback(\n (date?: string, startTime?: string) => {\n if (readOnly) return;\n setModalState({\n open: true,\n mode: \"add\",\n entry: {\n date: date || currentDate,\n startTime: startTime || undefined,\n endTime: startTime\n ? (() => {\n const [h, m] = startTime.split(\":\").map(Number);\n const endM = h * 60 + m + 60; // 1 hour later\n const eh = Math.min(Math.floor(endM / 60), 23);\n const em = endM % 60;\n return `${String(eh).padStart(2, \"0\")}:${String(em).padStart(2, \"0\")}`;\n })()\n : undefined,\n allDay: !startTime,\n color: colorOptions[0],\n },\n });\n },\n [readOnly, currentDate, colorOptions],\n );\n\n const openEditModal = useCallback(\n (entry: CalendarEntry) => {\n if (readOnly) return;\n setModalState({\n open: true,\n mode: \"edit\",\n entry: { ...entry },\n });\n },\n [readOnly],\n );\n\n const closeModal = useCallback(() => {\n setModalState((prev) => ({ ...prev, open: false }));\n }, []);\n\n const saveModal = useCallback(\n (entryData: Partial<CalendarEntry>) => {\n if (modalState.mode === \"add\") {\n const newEntry = addEntry({\n title: entryData.title || \"\",\n date: entryData.date || currentDate,\n startTime: entryData.allDay ? undefined : entryData.startTime,\n endTime: entryData.allDay ? undefined : entryData.endTime,\n color: entryData.color || colorOptions[0],\n description: entryData.description,\n allDay: entryData.allDay ?? true,\n });\n closeModal();\n return newEntry;\n } else {\n const updated: CalendarEntry = {\n ...(modalState.entry as CalendarEntry),\n ...entryData,\n id: modalState.entry.id!,\n startTime: entryData.allDay ? undefined : entryData.startTime,\n endTime: entryData.allDay ? undefined : entryData.endTime,\n };\n updateEntry(updated);\n closeModal();\n return updated;\n }\n },\n [modalState, addEntry, updateEntry, closeModal, currentDate, colorOptions],\n );\n\n const deleteModalEntry = useCallback(() => {\n if (modalState.entry.id) {\n deleteEntry(modalState.entry.id);\n }\n closeModal();\n }, [modalState.entry.id, deleteEntry, closeModal]);\n\n // ─── Helpers ──────────────────────────────────────────────────\n\n /** Get entries for a specific date (YYYY-MM-DD), sorted by time */\n const getEntriesForDate = useCallback(\n (date: string): CalendarEntry[] => {\n return entries\n .filter((e) => e.date === date)\n .sort((a, b) => {\n // All-day events come first\n const aAllDay = a.allDay || !a.startTime;\n const bAllDay = b.allDay || !b.startTime;\n if (aAllDay && !bAllDay) return -1;\n if (!aAllDay && bAllDay) return 1;\n // Both all-day: keep original order\n if (aAllDay && bAllDay) return 0;\n // Both timed: sort by startTime ascending\n return (a.startTime || \"\").localeCompare(b.startTime || \"\");\n });\n },\n [entries],\n );\n\n return {\n // State\n currentDate,\n currentDateObj,\n viewMode,\n entries,\n labels,\n colorOptions,\n holidays,\n readOnly,\n\n // Navigation\n goToToday,\n goToDate,\n goNext,\n goPrev,\n title,\n\n // View mode\n setViewMode,\n\n // Grid data\n monthDates,\n weekDates,\n\n // Entry CRUD\n addEntry,\n updateEntry,\n deleteEntry,\n getEntriesForDate,\n\n // Modal\n modalState,\n openAddModal,\n openEditModal,\n closeModal,\n saveModal,\n deleteModalEntry,\n };\n}\n"],"mappings":";;;AAsDA,SAAgB,EAAiB,GAAkC;CACjE,IAAM,EACJ,SAAS,GACT,aACA,iBAAc,SACd,gBACA,YAAS,MACT,QAAQ,GACR,kBAAe,GACf,cAAW,IACX,eACA,kBACA,kBACA,oBACE,GAIE,IAAmC,SAEhC;EAAE,GADI,MAAW,OAAO,IAAY;EACzB,GAAG;CAAW,IAC/B,CAAC,GAAQ,CAAU,CAAC,GAIjB,CAAC,GAAa,KAAkB,QAChC,KACG,EAAS,CACjB,GAEK,IAAiB,QACX,EAAU,CACb,qBAAK,IAAI,KAAK,GACpB,CAAC,CAAW,CAAC,GAIV,CAAC,GAAU,KAAkB,EAA2B,CAAW,GAEnE,IAAc,GACjB,MAA2B;EAE1B,AADA,EAAe,CAAI,GACnB,IAAe,CAAI;CACrB,GACA,CAAC,CAAY,CACf,GAMM,IACJ,MAAoB,KAAA,MACnB,MAAe,KAAA,KACd,MAAkB,KAAA,KAClB,MAAkB,KAAA,IAEhB,CAAC,GAAiB,KAAsB,QACtC,KAAmB,CAAC,CAC5B,GAIM,IAAkB,EAAO,CAAe;CAC9C,AAAI,KAAgB,MAAoB,EAAgB,YACtD,EAAgB,UAAU;CAI5B,IAAM,IAAU,IAAe,IAAmB,GAI5C,IAAY,QAAkB;EAClC,EAAe,EAAS,CAAC;CAC3B,GAAG,CAAC,CAAC,GAEC,IAAW,GAAa,MAAiB;EAC7C,EAAe,CAAI;CACrB,GAAG,CAAC,CAAC,GAEC,IAAS,QAAkB;EAC/B,IAAM,IAAI,EAAU,CAAW;EAC1B,OAEL,QAAQ,GAAR;GACE,KAAK,SAAS;IACZ,IAAM,IAAO,IAAI,KAAK,EAAE,YAAY,GAAG,EAAE,SAAS,IAAI,GAAG,CAAC;IAC1D,EAAe,EAAW,CAAI,CAAC;IAC/B;GACF;GACA,KAAK,QAAQ;IACX,IAAM,IAAO,EAAQ,GAAG,CAAC;IACzB,EAAe,EAAW,CAAI,CAAC;IAC/B;GACF;GACA,KAAK,OAAO;IACV,IAAM,IAAO,EAAQ,GAAG,CAAC;IACzB,EAAe,EAAW,CAAI,CAAC;IAC/B;GACF;EACF;CACF,GAAG,CAAC,GAAa,CAAQ,CAAC,GAEpB,IAAS,QAAkB;EAC/B,IAAM,IAAI,EAAU,CAAW;EAC1B,OAEL,QAAQ,GAAR;GACE,KAAK,SAAS;IACZ,IAAM,IAAO,IAAI,KAAK,EAAE,YAAY,GAAG,EAAE,SAAS,IAAI,GAAG,CAAC;IAC1D,EAAe,EAAW,CAAI,CAAC;IAC/B;GACF;GACA,KAAK,QAAQ;IACX,IAAM,IAAO,EAAQ,GAAG,EAAE;IAC1B,EAAe,EAAW,CAAI,CAAC;IAC/B;GACF;GACA,KAAK,OAAO;IACV,IAAM,IAAO,EAAQ,GAAG,EAAE;IAC1B,EAAe,EAAW,CAAI,CAAC;IAC/B;GACF;EACF;CACF,GAAG,CAAC,GAAa,CAAQ,CAAC,GAIpB,IAAQ,QAAc;EAC1B,IAAM,IAAI,GACJ,IAAY,EAAO,WAAY,EAAE,SAAS,IAC1C,IAAO,EAAE,YAAY;EAE3B,QAAQ,GAAR;GACE,KAAK,SACH,OAAO,GAAG,EAAU,GAAG;GACzB,KAAK,QAAQ;IACX,IAAM,IAAY,EAAa,CAAC,GAC1B,IAAQ,EAAU,IAClB,IAAM,EAAU;IAItB,OAHI,EAAM,SAAS,MAAM,EAAI,SAAS,IAC7B,GAAG,EAAO,WAAY,EAAM,SAAS,GAAG,GAAG,EAAM,QAAQ,EAAE,KAAK,EAAI,QAAQ,EAAE,IAAI,MAEpF,GAAG,EAAO,WAAY,EAAM,SAAS,GAAG,GAAG,EAAM,QAAQ,EAAE,KAAK,EAAO,WAAY,EAAI,SAAS,GAAG,GAAG,EAAI,QAAQ,EAAE,IAAI;GACjI;GACA,KAAK,OACH,OAAO,GAAG,EAAU,GAAG,EAAE,QAAQ,EAAE,IAAI;EAC3C;CACF,GAAG;EAAC;EAAgB;EAAU;CAAM,CAAC,GAI/B,IAAa,QAAc;EAC/B,IAAM,IAAI;EACV,OAAO,EAAc,EAAE,YAAY,GAAG,EAAE,SAAS,IAAI,CAAC;CACxD,GAAG,CAAC,CAAc,CAAC,GAEb,IAAY,QACT,EAAa,CAAc,GACjC,CAAC,CAAc,CAAC,GAIb,IAAW,GACd,MAAuD;EACtD,IAAM,IAAW;GACf,GAAG;GACH,IAAI,EAAM,MAAM,EAAW;EAC7B;EAMA,OAJK,KACH,GAAoB,MAAS,CAAC,GAAG,GAAM,CAAQ,CAAC,GAElD,IAAa,CAAQ,GACd;CACT,GACA,CAAC,GAAc,CAAU,CAC3B,GAEM,IAAc,GACjB,MAAyB;EAMxB,AALK,KACH,GAAoB,MAClB,EAAK,KAAK,MAAO,EAAE,OAAO,EAAM,KAAK,IAAQ,CAAE,CACjD,GAEF,IAAgB,CAAK;CACvB,GACA,CAAC,GAAc,CAAa,CAC9B,GAEM,IAAc,GACjB,MAAoB;EAInB,AAHK,KACH,GAAoB,MAAS,EAAK,QAAQ,MAAM,EAAE,OAAO,CAAO,CAAC,GAEnE,IAAgB,CAAO;CACzB,GACA,CAAC,GAAc,CAAa,CAC9B,GAIM,CAAC,GAAY,KAAiB,EAA0B;EAC5D,MAAM;EACN,MAAM;EACN,OAAO,CAAC;CACV,CAAC,GAEK,IAAe,GAClB,GAAe,MAAuB;EACjC,KACJ,EAAc;GACZ,MAAM;GACN,MAAM;GACN,OAAO;IACL,MAAM,KAAQ;IACd,WAAW,KAAa,KAAA;IACxB,SAAS,WACE;KACL,IAAM,CAAC,GAAG,KAAK,EAAU,MAAM,GAAG,CAAC,CAAC,IAAI,MAAM,GACxC,IAAO,IAAI,KAAK,IAAI,IACpB,IAAK,KAAK,IAAI,KAAK,MAAM,IAAO,EAAE,GAAG,EAAE,GACvC,IAAK,IAAO;KAClB,OAAO,GAAG,OAAO,CAAE,CAAC,CAAC,SAAS,GAAG,GAAG,EAAE,GAAG,OAAO,CAAE,CAAC,CAAC,SAAS,GAAG,GAAG;IACrE,EAAA,CAAG,IACH,KAAA;IACJ,QAAQ,CAAC;IACT,OAAO,EAAa;GACtB;EACF,CAAC;CACH,GACA;EAAC;EAAU;EAAa;CAAY,CACtC,GAEM,IAAgB,GACnB,MAAyB;EACpB,KACJ,EAAc;GACZ,MAAM;GACN,MAAM;GACN,OAAO,EAAE,GAAG,EAAM;EACpB,CAAC;CACH,GACA,CAAC,CAAQ,CACX,GAEM,IAAa,QAAkB;EACnC,GAAe,OAAU;GAAE,GAAG;GAAM,MAAM;EAAM,EAAE;CACpD,GAAG,CAAC,CAAC,GAEC,KAAY,GACf,MAAsC;EACrC,IAAI,EAAW,SAAS,OAAO;GAC7B,IAAM,IAAW,EAAS;IACxB,OAAO,EAAU,SAAS;IAC1B,MAAM,EAAU,QAAQ;IACxB,WAAW,EAAU,SAAS,KAAA,IAAY,EAAU;IACpD,SAAS,EAAU,SAAS,KAAA,IAAY,EAAU;IAClD,OAAO,EAAU,SAAS,EAAa;IACvC,aAAa,EAAU;IACvB,QAAQ,EAAU,UAAU;GAC9B,CAAC;GAED,OADA,EAAW,GACJ;EACT;EAAO;GACL,IAAM,IAAyB;IAC7B,GAAI,EAAW;IACf,GAAG;IACH,IAAI,EAAW,MAAM;IACrB,WAAW,EAAU,SAAS,KAAA,IAAY,EAAU;IACpD,SAAS,EAAU,SAAS,KAAA,IAAY,EAAU;GACpD;GAGA,OAFA,EAAY,CAAO,GACnB,EAAW,GACJ;EACT;CACF,GACA;EAAC;EAAY;EAAU;EAAa;EAAY;EAAa;CAAY,CAC3E,GAEM,KAAmB,QAAkB;EAIzC,AAHI,EAAW,MAAM,MACnB,EAAY,EAAW,MAAM,EAAE,GAEjC,EAAW;CACb,GAAG;EAAC,EAAW,MAAM;EAAI;EAAa;CAAU,CAAC;CAwBjD,OAAO;EAEL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAGA;EACA;EACA;EACA;EACA;EAGA;EAGA;EACA;EAGA;EACA;EACA;EACA,mBAhDwB,GACvB,MACQ,EACJ,QAAQ,MAAM,EAAE,SAAS,CAAI,CAAC,CAC9B,MAAM,GAAG,MAAM;GAEd,IAAM,IAAU,EAAE,UAAU,CAAC,EAAE,WACzB,IAAU,EAAE,UAAU,CAAC,EAAE;GAM/B,OALI,KAAW,CAAC,IAAgB,KAC5B,CAAC,KAAW,IAAgB,IAE5B,KAAW,IAAgB,KAEvB,EAAE,aAAa,GAAA,CAAI,cAAc,EAAE,aAAa,EAAE;EAC5D,CAAC,GAEL,CAAC,CAAO,CAgCR;EAGA;EACA;EACA;EACA;EACA;EACA;CACF;AACF"}
@@ -0,0 +1,193 @@
1
+ //#region src/components/pro/Calendar/utils.ts
2
+ var e = {
3
+ today: "Today",
4
+ month: "Month",
5
+ week: "Week",
6
+ day: "Day",
7
+ addEntry: "Add",
8
+ deleteEntry: "Delete",
9
+ editEntry: "Edit",
10
+ allDay: "All day",
11
+ noEntries: "No entries",
12
+ confirmDelete: "Are you sure you want to delete this entry?",
13
+ cancel: "Cancel",
14
+ save: "Save",
15
+ title: "Title",
16
+ date: "Date",
17
+ startTime: "Start time",
18
+ endTime: "End time",
19
+ description: "Description",
20
+ color: "Color",
21
+ weekDays: [
22
+ "Sun",
23
+ "Mon",
24
+ "Tue",
25
+ "Wed",
26
+ "Thu",
27
+ "Fri",
28
+ "Sat"
29
+ ],
30
+ monthNames: [
31
+ "January",
32
+ "February",
33
+ "March",
34
+ "April",
35
+ "May",
36
+ "June",
37
+ "July",
38
+ "August",
39
+ "September",
40
+ "October",
41
+ "November",
42
+ "December"
43
+ ]
44
+ }, t = {
45
+ today: "今天",
46
+ month: "月",
47
+ week: "周",
48
+ day: "日",
49
+ addEntry: "添加",
50
+ deleteEntry: "删除",
51
+ editEntry: "编辑",
52
+ allDay: "全天",
53
+ noEntries: "暂无日程",
54
+ confirmDelete: "确定要删除此日程吗?",
55
+ cancel: "取消",
56
+ save: "保存",
57
+ title: "标题",
58
+ date: "日期",
59
+ startTime: "开始时间",
60
+ endTime: "结束时间",
61
+ description: "描述",
62
+ color: "颜色",
63
+ weekDays: [
64
+ "日",
65
+ "一",
66
+ "二",
67
+ "三",
68
+ "四",
69
+ "五",
70
+ "六"
71
+ ],
72
+ monthNames: [
73
+ "一月",
74
+ "二月",
75
+ "三月",
76
+ "四月",
77
+ "五月",
78
+ "六月",
79
+ "七月",
80
+ "八月",
81
+ "九月",
82
+ "十月",
83
+ "十一月",
84
+ "十二月"
85
+ ]
86
+ }, n = [
87
+ "#3b82f6",
88
+ "#ef4444",
89
+ "#22c55e",
90
+ "#f59e0b",
91
+ "#8b5cf6",
92
+ "#ec4899",
93
+ "#06b6d4",
94
+ "#f97316"
95
+ ];
96
+ function r(e) {
97
+ if (!e) return null;
98
+ if (/^\d{4}-\d{2}-\d{2}$/.test(e)) {
99
+ let [t, n, r] = e.split("-").map(Number), i = new Date(t, n - 1, r);
100
+ return isNaN(i.getTime()) ? null : i;
101
+ }
102
+ return null;
103
+ }
104
+ function i(e) {
105
+ return `${e.getFullYear()}-${String(e.getMonth() + 1).padStart(2, "0")}-${String(e.getDate()).padStart(2, "0")}`;
106
+ }
107
+ function a() {
108
+ return i(/* @__PURE__ */ new Date());
109
+ }
110
+ function o(e) {
111
+ let t = /* @__PURE__ */ new Date();
112
+ return e.getFullYear() === t.getFullYear() && e.getMonth() === t.getMonth() && e.getDate() === t.getDate();
113
+ }
114
+ function s(e, t) {
115
+ return e.getFullYear() === t.getFullYear() && e.getMonth() === t.getMonth() && e.getDate() === t.getDate();
116
+ }
117
+ function c(e) {
118
+ let t = e.getDay();
119
+ return t === 0 || t === 6;
120
+ }
121
+ function l(e, t) {
122
+ return new Date(e, t, 0).getDate();
123
+ }
124
+ function u(e, t) {
125
+ return new Date(e, t - 1, 1).getDay();
126
+ }
127
+ function d(e, t) {
128
+ if (t) return t.entries.find((t) => t.date === e);
129
+ }
130
+ function f(e, t) {
131
+ if (!t) return !1;
132
+ let n = t.entries.find((t) => t.date === e);
133
+ return !!n && !n.isWorkday;
134
+ }
135
+ function p(e, t) {
136
+ if (!t) return c(e);
137
+ let n = i(e), r = t.entries.find((e) => e.date === n);
138
+ return r ? !r.isWorkday : t.weekendsOff !== !1 && c(e);
139
+ }
140
+ function m(e, t) {
141
+ let n = [], r = u(e, t), i = l(e, t), a = t === 1 ? 12 : t - 1, o = t === 1 ? e - 1 : e, s = l(o, a);
142
+ for (let e = r - 1; e >= 0; e--) n.push(new Date(o, a - 1, s - e));
143
+ for (let r = 1; r <= i; r++) n.push(new Date(e, t - 1, r));
144
+ let c = t === 12 ? 1 : t + 1, d = t === 12 ? e + 1 : e, f = 1;
145
+ for (; n.length < 42;) n.push(new Date(d, c - 1, f)), f++;
146
+ return n;
147
+ }
148
+ function h(e) {
149
+ let t = [], n = e.getDay(), r = new Date(e);
150
+ r.setDate(r.getDate() - n), r.setHours(0, 0, 0, 0);
151
+ for (let e = 0; e < 7; e++) {
152
+ let n = new Date(r);
153
+ n.setDate(n.getDate() + e), t.push(n);
154
+ }
155
+ return t;
156
+ }
157
+ function g(e) {
158
+ let t = Math.floor(e / 60), n = e % 60;
159
+ return `${String(t).padStart(2, "0")}:${String(n).padStart(2, "0")}`;
160
+ }
161
+ function _(e) {
162
+ if (!e) return 0;
163
+ let t = e.split(":");
164
+ if (t.length < 2) return 0;
165
+ let n = parseInt(t[0], 10), r = parseInt(t[1], 10);
166
+ return isNaN(n) || isNaN(r) ? 0 : n * 60 + r;
167
+ }
168
+ function v(e) {
169
+ return e;
170
+ }
171
+ function y(e) {
172
+ return e && /^\d{2}:\d{2}$/.test(e) ? e : "";
173
+ }
174
+ function b() {
175
+ let e = [];
176
+ for (let t = 0; t < 24; t++) e.push(`${String(t).padStart(2, "0")}:00`), e.push(`${String(t).padStart(2, "0")}:30`);
177
+ return e;
178
+ }
179
+ var x = b(), S = 28, C = x.length * 28;
180
+ function w(e, t) {
181
+ let n = new Date(e);
182
+ return n.setDate(n.getDate() + t), n;
183
+ }
184
+ function T() {
185
+ return `cal-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
186
+ }
187
+ function E(e, t, n) {
188
+ return Math.min(Math.max(e, t), n);
189
+ }
190
+ //#endregion
191
+ export { n as DEFAULT_COLOR_OPTIONS, e as LABELS_EN, t as LABELS_ZH, S as SLOT_HEIGHT, C as TIME_GRID_HEIGHT, x as TIME_SLOTS, w as addDays, E as clamp, i as formatDate, v as formatTime, T as generateId, b as generateTimeSlots, l as getDaysInMonth, u as getFirstDayOfMonth, d as getHolidayEntry, m as getMonthDates, h as getWeekDates, f as isHoliday, p as isNonWorkingDay, s as isSameDay, o as isToday, c as isWeekend, g as minutesToTime, r as parseDate, y as parseTime, _ as timeToMinutes, a as todayStr };
192
+
193
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","names":[],"sources":["../../../../src/components/pro/Calendar/utils.ts"],"sourcesContent":["/**\n * DishUI Calendar Component - Utility Functions\n *\n * Core date/time helpers, grid generation, and holiday resolution.\n */\n\nimport type { HolidayCalendar, HolidayEntry, CalendarLabels } from \"./types\";\n\n// ─── Default Labels ───────────────────────────────────────────────\n\nexport const LABELS_EN: Required<CalendarLabels> = {\n today: \"Today\",\n month: \"Month\",\n week: \"Week\",\n day: \"Day\",\n addEntry: \"Add\",\n deleteEntry: \"Delete\",\n editEntry: \"Edit\",\n allDay: \"All day\",\n noEntries: \"No entries\",\n confirmDelete: \"Are you sure you want to delete this entry?\",\n cancel: \"Cancel\",\n save: \"Save\",\n title: \"Title\",\n date: \"Date\",\n startTime: \"Start time\",\n endTime: \"End time\",\n description: \"Description\",\n color: \"Color\",\n weekDays: [\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"],\n monthNames: [\n \"January\",\n \"February\",\n \"March\",\n \"April\",\n \"May\",\n \"June\",\n \"July\",\n \"August\",\n \"September\",\n \"October\",\n \"November\",\n \"December\",\n ],\n};\n\nexport const LABELS_ZH: Required<CalendarLabels> = {\n today: \"今天\",\n month: \"月\",\n week: \"周\",\n day: \"日\",\n addEntry: \"添加\",\n deleteEntry: \"删除\",\n editEntry: \"编辑\",\n allDay: \"全天\",\n noEntries: \"暂无日程\",\n confirmDelete: \"确定要删除此日程吗?\",\n cancel: \"取消\",\n save: \"保存\",\n title: \"标题\",\n date: \"日期\",\n startTime: \"开始时间\",\n endTime: \"结束时间\",\n description: \"描述\",\n color: \"颜色\",\n weekDays: [\"日\", \"一\", \"二\", \"三\", \"四\", \"五\", \"六\"],\n monthNames: [\n \"一月\",\n \"二月\",\n \"三月\",\n \"四月\",\n \"五月\",\n \"六月\",\n \"七月\",\n \"八月\",\n \"九月\",\n \"十月\",\n \"十一月\",\n \"十二月\",\n ],\n};\n\n/** Default entry color palette */\nexport const DEFAULT_COLOR_OPTIONS = [\n \"#3b82f6\", // blue\n \"#ef4444\", // red\n \"#22c55e\", // green\n \"#f59e0b\", // amber\n \"#8b5cf6\", // violet\n \"#ec4899\", // pink\n \"#06b6d4\", // cyan\n \"#f97316\", // orange\n];\n\n// ─── Date Parsing & Formatting ────────────────────────────────────\n\n/**\n * Parse a YYYY-MM-DD string into a local Date at midnight.\n * Returns null for invalid strings.\n */\nexport function parseDate(value: string | undefined | null): Date | null {\n if (!value) return null;\n if (/^\\d{4}-\\d{2}-\\d{2}$/.test(value)) {\n const [y, m, d] = value.split(\"-\").map(Number);\n const date = new Date(y, m - 1, d);\n return isNaN(date.getTime()) ? null : date;\n }\n return null;\n}\n\n/**\n * Format a Date to YYYY-MM-DD string (local timezone).\n */\nexport function formatDate(date: Date): string {\n const y = date.getFullYear();\n const m = String(date.getMonth() + 1).padStart(2, \"0\");\n const d = String(date.getDate()).padStart(2, \"0\");\n return `${y}-${m}-${d}`;\n}\n\n/**\n * Get today's date as a YYYY-MM-DD string.\n */\nexport function todayStr(): string {\n return formatDate(new Date());\n}\n\n// ─── Date Query Helpers ───────────────────────────────────────────\n\n/** Check if a Date is today */\nexport function isToday(date: Date): boolean {\n const now = new Date();\n return (\n date.getFullYear() === now.getFullYear() &&\n date.getMonth() === now.getMonth() &&\n date.getDate() === now.getDate()\n );\n}\n\n/** Check if two Dates represent the same calendar day */\nexport function isSameDay(a: Date, b: Date): boolean {\n return (\n a.getFullYear() === b.getFullYear() &&\n a.getMonth() === b.getMonth() &&\n a.getDate() === b.getDate()\n );\n}\n\n/** Check if a Date falls on Saturday or Sunday */\nexport function isWeekend(date: Date): boolean {\n const d = date.getDay();\n return d === 0 || d === 6;\n}\n\n/** Get the number of days in a given month (1-indexed month) */\nexport function getDaysInMonth(year: number, month: number): number {\n return new Date(year, month, 0).getDate();\n}\n\n/** Get the day-of-week (0 = Sun) of the 1st of a given month */\nexport function getFirstDayOfMonth(year: number, month: number): number {\n return new Date(year, month - 1, 1).getDay();\n}\n\n// ─── Holiday Helpers ──────────────────────────────────────────────\n\n/**\n * Find a holiday entry for a given date string.\n */\nexport function getHolidayEntry(\n dateStr: string,\n holidays?: HolidayCalendar,\n): HolidayEntry | undefined {\n if (!holidays) return undefined;\n return holidays.entries.find((e) => e.date === dateStr);\n}\n\n/**\n * Check if a date is a holiday (non-working day from the holiday calendar).\n * Returns true for declared holidays (not compensatory workdays).\n */\nexport function isHoliday(dateStr: string, holidays?: HolidayCalendar): boolean {\n if (!holidays) return false;\n const entry = holidays.entries.find((e) => e.date === dateStr);\n return !!entry && !entry.isWorkday;\n}\n\n/**\n * Check if a date is a non-working day considering the full holiday calendar.\n * Priority: holiday entries > weekend check.\n */\nexport function isNonWorkingDay(\n date: Date,\n holidays?: HolidayCalendar,\n): boolean {\n if (!holidays) return isWeekend(date);\n\n const dateStr = formatDate(date);\n const entry = holidays.entries.find((e) => e.date === dateStr);\n\n if (entry) {\n return !entry.isWorkday;\n }\n\n if (holidays.weekendsOff !== false) {\n return isWeekend(date);\n }\n\n return false;\n}\n\n// ─── Calendar Grid Generation ─────────────────────────────────────\n\n/**\n * Generate a 42-cell (6 rows × 7 columns) grid for a month view.\n * Each cell is a Date object. Includes leading/trailing days from\n * the previous/next month to fill the grid.\n */\nexport function getMonthDates(year: number, month: number): Date[] {\n const dates: Date[] = [];\n const firstDay = getFirstDayOfMonth(year, month);\n const daysInMonth = getDaysInMonth(year, month);\n\n // Previous month trailing days\n const prevMonth = month === 1 ? 12 : month - 1;\n const prevYear = month === 1 ? year - 1 : year;\n const daysInPrevMonth = getDaysInMonth(prevYear, prevMonth);\n\n for (let i = firstDay - 1; i >= 0; i--) {\n dates.push(new Date(prevYear, prevMonth - 1, daysInPrevMonth - i));\n }\n\n // Current month days\n for (let d = 1; d <= daysInMonth; d++) {\n dates.push(new Date(year, month - 1, d));\n }\n\n // Next month leading days (fill to 42 cells)\n const nextMonth = month === 12 ? 1 : month + 1;\n const nextYear = month === 12 ? year + 1 : year;\n let nextDay = 1;\n while (dates.length < 42) {\n dates.push(new Date(nextYear, nextMonth - 1, nextDay));\n nextDay++;\n }\n\n return dates;\n}\n\n/**\n * Generate the 7 dates for a week containing the given date.\n * Week starts on Sunday.\n */\nexport function getWeekDates(date: Date): Date[] {\n const dates: Date[] = [];\n const dayOfWeek = date.getDay(); // 0 = Sun\n const start = new Date(date);\n start.setDate(start.getDate() - dayOfWeek);\n start.setHours(0, 0, 0, 0);\n\n for (let i = 0; i < 7; i++) {\n const d = new Date(start);\n d.setDate(d.getDate() + i);\n dates.push(d);\n }\n\n return dates;\n}\n\n// ─── Time Utilities ───────────────────────────────────────────────\n\n/**\n * Format minutes since midnight to HH:mm string.\n */\nexport function minutesToTime(minutes: number): string {\n const h = Math.floor(minutes / 60);\n const m = minutes % 60;\n return `${String(h).padStart(2, \"0\")}:${String(m).padStart(2, \"0\")}`;\n}\n\n/**\n * Parse an HH:mm string to minutes since midnight.\n * Returns 0 for invalid input.\n */\nexport function timeToMinutes(time: string | undefined): number {\n if (!time) return 0;\n const parts = time.split(\":\");\n if (parts.length < 2) return 0;\n const h = parseInt(parts[0], 10);\n const m = parseInt(parts[1], 10);\n if (isNaN(h) || isNaN(m)) return 0;\n return h * 60 + m;\n}\n\n/**\n * Format an HH:mm string for display (identity for now, but could localize).\n */\nexport function formatTime(time: string): string {\n return time;\n}\n\n/**\n * Parse an HH:mm string — validates format, returns the string or empty.\n */\nexport function parseTime(time: string | undefined): string {\n if (!time) return \"\";\n if (/^\\d{2}:\\d{2}$/.test(time)) return time;\n return \"\";\n}\n\n/**\n * Generate an array of time slot labels from 00:00 to 23:30 (30-minute intervals).\n * Returns 48 items.\n */\nexport function generateTimeSlots(): string[] {\n const slots: string[] = [];\n for (let h = 0; h < 24; h++) {\n slots.push(`${String(h).padStart(2, \"0\")}:00`);\n slots.push(`${String(h).padStart(2, \"0\")}:30`);\n }\n return slots;\n}\n\n/** Cached time slots — always 48 items (00:00 through 23:30) */\nexport const TIME_SLOTS = generateTimeSlots();\n\n/** Height of each 30-minute time slot in pixels */\nexport const SLOT_HEIGHT = 28;\n\n/** Total height of the time grid (48 slots × SLOT_HEIGHT) */\nexport const TIME_GRID_HEIGHT = TIME_SLOTS.length * SLOT_HEIGHT;\n\n// ─── Misc Helpers ─────────────────────────────────────────────────\n\n/** Add N days to a date (returns new Date) */\nexport function addDays(date: Date, days: number): Date {\n const result = new Date(date);\n result.setDate(result.getDate() + days);\n return result;\n}\n\n/** Generate a simple unique ID */\nexport function generateId(): string {\n return `cal-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n}\n\n/**\n * Clamp a number between min and max.\n */\nexport function clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n"],"mappings":"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"}