calendarkit-pro 1.2.0 → 1.3.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.
- package/README.md +24 -3
- package/dist/index.d.mts +12 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +1424 -1014
- package/dist/index.mjs +1381 -953
- package/package.json +29 -6
- package/dist/index.js.map +0 -1
- package/dist/index.mjs.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,46 +1,64 @@
|
|
|
1
|
-
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __export = (target, all) => {
|
|
10
|
+
for (var name in all)
|
|
11
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
12
|
+
};
|
|
13
|
+
var __copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
+
for (let key of __getOwnPropNames(from))
|
|
16
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
17
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
18
|
+
}
|
|
19
|
+
return to;
|
|
20
|
+
};
|
|
21
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
22
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
23
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
24
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
25
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
26
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
27
|
+
mod
|
|
28
|
+
));
|
|
29
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
2
30
|
|
|
3
|
-
|
|
4
|
-
var
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
var
|
|
11
|
-
var
|
|
12
|
-
var
|
|
13
|
-
var
|
|
14
|
-
var rrule = require('rrule');
|
|
31
|
+
// src/index.tsx
|
|
32
|
+
var index_exports = {};
|
|
33
|
+
__export(index_exports, {
|
|
34
|
+
Scheduler: () => Scheduler,
|
|
35
|
+
cn: () => cn
|
|
36
|
+
});
|
|
37
|
+
module.exports = __toCommonJS(index_exports);
|
|
38
|
+
var import_react20 = __toESM(require("react"));
|
|
39
|
+
var import_core3 = require("@dnd-kit/core");
|
|
40
|
+
var import_modifiers = require("@dnd-kit/modifiers");
|
|
41
|
+
var import_framer_motion4 = require("framer-motion");
|
|
15
42
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
if (e) {
|
|
20
|
-
Object.keys(e).forEach(function (k) {
|
|
21
|
-
if (k !== 'default') {
|
|
22
|
-
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
23
|
-
Object.defineProperty(n, k, d.get ? d : {
|
|
24
|
-
enumerable: true,
|
|
25
|
-
get: function () { return e[k]; }
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
n.default = e;
|
|
31
|
-
return Object.freeze(n);
|
|
32
|
-
}
|
|
43
|
+
// src/components/CalendarHeader.tsx
|
|
44
|
+
var import_react = __toESM(require("react"));
|
|
45
|
+
var import_date_fns = require("date-fns");
|
|
33
46
|
|
|
34
|
-
|
|
47
|
+
// src/components/ui/button.tsx
|
|
48
|
+
var React = __toESM(require("react"));
|
|
49
|
+
var import_class_variance_authority = require("class-variance-authority");
|
|
35
50
|
|
|
51
|
+
// src/utils.ts
|
|
52
|
+
var import_clsx = require("clsx");
|
|
53
|
+
var import_tailwind_merge = require("tailwind-merge");
|
|
36
54
|
function cn(...inputs) {
|
|
37
|
-
return
|
|
55
|
+
return (0, import_tailwind_merge.twMerge)((0, import_clsx.clsx)(inputs));
|
|
38
56
|
}
|
|
39
57
|
var isEventDragDisabled = (event) => event?.draggable === false;
|
|
40
58
|
var isEventResizeDisabled = (event) => event?.resizable === false || event?.resizable === void 0 && isEventDragDisabled(event);
|
|
41
59
|
|
|
42
60
|
// src/components/ui/button.tsx
|
|
43
|
-
var buttonVariants =
|
|
61
|
+
var buttonVariants = (0, import_class_variance_authority.cva)(
|
|
44
62
|
"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
|
|
45
63
|
{
|
|
46
64
|
variants: {
|
|
@@ -65,10 +83,10 @@ var buttonVariants = classVarianceAuthority.cva(
|
|
|
65
83
|
}
|
|
66
84
|
}
|
|
67
85
|
);
|
|
68
|
-
var Button =
|
|
69
|
-
({ className, variant, size,
|
|
86
|
+
var Button = React.forwardRef(
|
|
87
|
+
({ className, variant, size, ...props }, ref) => {
|
|
70
88
|
const Comp = "button";
|
|
71
|
-
return /* @__PURE__ */
|
|
89
|
+
return /* @__PURE__ */ React.createElement(
|
|
72
90
|
Comp,
|
|
73
91
|
{
|
|
74
92
|
className: cn(buttonVariants({ variant, size, className })),
|
|
@@ -79,6 +97,9 @@ var Button = React15__namespace.forwardRef(
|
|
|
79
97
|
}
|
|
80
98
|
);
|
|
81
99
|
Button.displayName = "Button";
|
|
100
|
+
|
|
101
|
+
// src/components/CalendarHeader.tsx
|
|
102
|
+
var import_lucide_react = require("lucide-react");
|
|
82
103
|
var CalendarHeader = ({
|
|
83
104
|
currentDate,
|
|
84
105
|
onPrev,
|
|
@@ -96,12 +117,12 @@ var CalendarHeader = ({
|
|
|
96
117
|
locale
|
|
97
118
|
}) => {
|
|
98
119
|
const viewConfig = [
|
|
99
|
-
{ key: "month", icon:
|
|
100
|
-
{ key: "week", icon:
|
|
101
|
-
{ key: "day", icon:
|
|
102
|
-
{ key: "agenda", icon:
|
|
120
|
+
{ key: "month", icon: import_lucide_react.CalendarDays },
|
|
121
|
+
{ key: "week", icon: import_lucide_react.CalendarRange },
|
|
122
|
+
{ key: "day", icon: import_lucide_react.Calendar },
|
|
123
|
+
{ key: "agenda", icon: import_lucide_react.ListTodo }
|
|
103
124
|
];
|
|
104
|
-
return /* @__PURE__ */
|
|
125
|
+
return /* @__PURE__ */ import_react.default.createElement("div", { className: "flex flex-col md:flex-row items-center justify-between px-3 md:px-5 py-3 border-b-[0px] border-border/50 bg-gradient-to-r from-background via-background to-muted/20 gap-3 md:gap-0 min-h-[64px]" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "flex items-center gap-2 w-full md:w-auto justify-between md:justify-start" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "flex items-center gap-2 md:gap-3" }, /* @__PURE__ */ import_react.default.createElement(
|
|
105
126
|
Button,
|
|
106
127
|
{
|
|
107
128
|
variant: "ghost",
|
|
@@ -109,8 +130,8 @@ var CalendarHeader = ({
|
|
|
109
130
|
className: "text-muted-foreground hover:text-foreground hover:bg-accent/80 rounded-xl h-10 w-10 hidden md:inline-flex transition-all duration-200",
|
|
110
131
|
onClick: onMenuClick
|
|
111
132
|
},
|
|
112
|
-
/* @__PURE__ */
|
|
113
|
-
), /* @__PURE__ */
|
|
133
|
+
/* @__PURE__ */ import_react.default.createElement(import_lucide_react.Menu, { className: "h-5 w-5" })
|
|
134
|
+
), /* @__PURE__ */ import_react.default.createElement(
|
|
114
135
|
Button,
|
|
115
136
|
{
|
|
116
137
|
variant: "outline",
|
|
@@ -118,7 +139,7 @@ var CalendarHeader = ({
|
|
|
118
139
|
className: "h-9 px-5 rounded-xl text-sm font-medium hidden sm:inline-flex border-[0.5px] border-border/60 hover:border-primary/40 hover:bg-primary/5 hover:text-primary transition-all duration-200"
|
|
119
140
|
},
|
|
120
141
|
translations.today
|
|
121
|
-
), /* @__PURE__ */
|
|
142
|
+
), /* @__PURE__ */ import_react.default.createElement("div", { className: "flex items-center bg-muted/40 rounded-xl p-0.5" }, /* @__PURE__ */ import_react.default.createElement(
|
|
122
143
|
Button,
|
|
123
144
|
{
|
|
124
145
|
variant: "ghost",
|
|
@@ -126,8 +147,8 @@ var CalendarHeader = ({
|
|
|
126
147
|
onClick: onPrev,
|
|
127
148
|
className: "rounded-lg h-8 w-8 hover:bg-background/80 transition-all duration-200"
|
|
128
149
|
},
|
|
129
|
-
/* @__PURE__ */
|
|
130
|
-
), /* @__PURE__ */
|
|
150
|
+
/* @__PURE__ */ import_react.default.createElement(import_lucide_react.ChevronLeft, { className: "h-4 w-4 text-muted-foreground" })
|
|
151
|
+
), /* @__PURE__ */ import_react.default.createElement(
|
|
131
152
|
Button,
|
|
132
153
|
{
|
|
133
154
|
variant: "ghost",
|
|
@@ -135,8 +156,8 @@ var CalendarHeader = ({
|
|
|
135
156
|
onClick: onNext,
|
|
136
157
|
className: "rounded-lg h-8 w-8 hover:bg-background/80 transition-all duration-200"
|
|
137
158
|
},
|
|
138
|
-
/* @__PURE__ */
|
|
139
|
-
)), /* @__PURE__ */
|
|
159
|
+
/* @__PURE__ */ import_react.default.createElement(import_lucide_react.ChevronRight, { className: "h-4 w-4 text-muted-foreground" })
|
|
160
|
+
)), /* @__PURE__ */ import_react.default.createElement("div", { className: "ml-2 md:ml-4" }, /* @__PURE__ */ import_react.default.createElement("h2", { className: "text-lg md:text-xl font-semibold text-foreground whitespace-nowrap capitalize tracking-tight" }, (0, import_date_fns.format)(currentDate, "MMMM yyyy", { locale }))))), /* @__PURE__ */ import_react.default.createElement("div", { className: "flex items-center gap-2 md:gap-3 w-full md:w-auto justify-end" }, onLanguageChange && language && /* @__PURE__ */ import_react.default.createElement(
|
|
140
161
|
Button,
|
|
141
162
|
{
|
|
142
163
|
variant: "ghost",
|
|
@@ -145,7 +166,7 @@ var CalendarHeader = ({
|
|
|
145
166
|
className: "h-9 px-3 rounded-xl text-xs font-semibold text-muted-foreground hover:text-foreground hover:bg-accent/80 transition-all duration-200 uppercase tracking-wider"
|
|
146
167
|
},
|
|
147
168
|
language
|
|
148
|
-
), onThemeToggle && /* @__PURE__ */
|
|
169
|
+
), onThemeToggle && /* @__PURE__ */ import_react.default.createElement(
|
|
149
170
|
Button,
|
|
150
171
|
{
|
|
151
172
|
variant: "ghost",
|
|
@@ -153,8 +174,8 @@ var CalendarHeader = ({
|
|
|
153
174
|
className: "rounded-xl h-9 w-9 hover:bg-accent/80 transition-all duration-200",
|
|
154
175
|
onClick: onThemeToggle
|
|
155
176
|
},
|
|
156
|
-
isDarkMode ? /* @__PURE__ */
|
|
157
|
-
), !hideViewSwitcher && /* @__PURE__ */
|
|
177
|
+
isDarkMode ? /* @__PURE__ */ import_react.default.createElement(import_lucide_react.Sun, { className: "h-4 w-4 text-amber-500" }) : /* @__PURE__ */ import_react.default.createElement(import_lucide_react.Moon, { className: "h-4 w-4 text-muted-foreground" })
|
|
178
|
+
), !hideViewSwitcher && /* @__PURE__ */ import_react.default.createElement("div", { className: "flex items-center bg-muted/50 backdrop-blur-sm rounded-xl p-1" }, viewConfig.map(({ key, icon: Icon }) => /* @__PURE__ */ import_react.default.createElement(
|
|
158
179
|
Button,
|
|
159
180
|
{
|
|
160
181
|
key,
|
|
@@ -166,24 +187,40 @@ var CalendarHeader = ({
|
|
|
166
187
|
view === key ? "bg-background shadow-sm text-foreground font-medium border-[0.5px] border-border/50" : "text-muted-foreground hover:text-foreground hover:bg-background/50"
|
|
167
188
|
)
|
|
168
189
|
},
|
|
169
|
-
/* @__PURE__ */
|
|
170
|
-
/* @__PURE__ */
|
|
190
|
+
/* @__PURE__ */ import_react.default.createElement(Icon, { className: "h-3.5 w-3.5" }),
|
|
191
|
+
/* @__PURE__ */ import_react.default.createElement("span", { className: "hidden sm:inline" }, translations[key])
|
|
171
192
|
)))));
|
|
172
193
|
};
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
194
|
+
|
|
195
|
+
// src/components/Sidebar.tsx
|
|
196
|
+
var import_react3 = __toESM(require("react"));
|
|
197
|
+
var import_lucide_react3 = require("lucide-react");
|
|
198
|
+
|
|
199
|
+
// src/components/MiniCalendar.tsx
|
|
200
|
+
var import_react2 = __toESM(require("react"));
|
|
201
|
+
var import_date_fns3 = require("date-fns");
|
|
202
|
+
|
|
203
|
+
// src/core/week.ts
|
|
204
|
+
var import_date_fns2 = require("date-fns");
|
|
205
|
+
function resolveWeekStartsOn(locale, fallback) {
|
|
206
|
+
return locale?.options?.weekStartsOn ?? fallback;
|
|
207
|
+
}
|
|
208
|
+
function getWeekDays(date, weekStartsOn) {
|
|
209
|
+
return (0, import_date_fns2.eachDayOfInterval)({
|
|
210
|
+
start: (0, import_date_fns2.startOfWeek)(date, { weekStartsOn }),
|
|
211
|
+
end: (0, import_date_fns2.endOfWeek)(date, { weekStartsOn })
|
|
181
212
|
});
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
return
|
|
186
|
-
}
|
|
213
|
+
}
|
|
214
|
+
function getMonthGrid(date, weekStartsOn) {
|
|
215
|
+
const monthStart = (0, import_date_fns2.startOfMonth)(date);
|
|
216
|
+
return (0, import_date_fns2.eachDayOfInterval)({
|
|
217
|
+
start: (0, import_date_fns2.startOfWeek)(monthStart, { weekStartsOn }),
|
|
218
|
+
end: (0, import_date_fns2.endOfWeek)((0, import_date_fns2.endOfMonth)(monthStart), { weekStartsOn })
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// src/components/MiniCalendar.tsx
|
|
223
|
+
var import_lucide_react2 = require("lucide-react");
|
|
187
224
|
var MiniCalendar = ({
|
|
188
225
|
currentDate,
|
|
189
226
|
onDateChange,
|
|
@@ -191,12 +228,12 @@ var MiniCalendar = ({
|
|
|
191
228
|
className,
|
|
192
229
|
locale
|
|
193
230
|
}) => {
|
|
194
|
-
const [viewDate, setViewDate] =
|
|
195
|
-
|
|
231
|
+
const [viewDate, setViewDate] = import_react2.default.useState(currentDate);
|
|
232
|
+
import_react2.default.useEffect(() => {
|
|
196
233
|
setViewDate(currentDate);
|
|
197
234
|
}, [currentDate]);
|
|
198
|
-
const weekStartsOn = locale
|
|
199
|
-
const days =
|
|
235
|
+
const weekStartsOn = resolveWeekStartsOn(locale, 0);
|
|
236
|
+
const days = import_react2.default.useMemo(
|
|
200
237
|
() => getMonthGrid(viewDate, weekStartsOn),
|
|
201
238
|
[viewDate, weekStartsOn]
|
|
202
239
|
);
|
|
@@ -205,13 +242,13 @@ var MiniCalendar = ({
|
|
|
205
242
|
return locale.localize.day(dayIndex, { width: "narrow" });
|
|
206
243
|
}) : ["S", "M", "T", "W", "T", "F", "S"];
|
|
207
244
|
const handlePrev = () => {
|
|
208
|
-
const newDate =
|
|
245
|
+
const newDate = (0, import_date_fns3.subMonths)(viewDate, 1);
|
|
209
246
|
setViewDate(newDate);
|
|
210
247
|
onDateChange(newDate);
|
|
211
248
|
if (onViewChange) onViewChange("month");
|
|
212
249
|
};
|
|
213
250
|
const handleNext = () => {
|
|
214
|
-
const newDate =
|
|
251
|
+
const newDate = (0, import_date_fns3.addMonths)(viewDate, 1);
|
|
215
252
|
setViewDate(newDate);
|
|
216
253
|
onDateChange(newDate);
|
|
217
254
|
if (onViewChange) onViewChange("month");
|
|
@@ -220,7 +257,7 @@ var MiniCalendar = ({
|
|
|
220
257
|
onDateChange(day);
|
|
221
258
|
if (onViewChange) onViewChange("day");
|
|
222
259
|
};
|
|
223
|
-
return /* @__PURE__ */
|
|
260
|
+
return /* @__PURE__ */ import_react2.default.createElement("div", { className: cn("px-4 w-[260px]", className) }, /* @__PURE__ */ import_react2.default.createElement("div", { className: "flex items-center justify-between mb-4" }, /* @__PURE__ */ import_react2.default.createElement("span", { className: "text-sm font-semibold text-foreground capitalize" }, (0, import_date_fns3.format)(viewDate, "MMMM yyyy", { locale })), /* @__PURE__ */ import_react2.default.createElement("div", { className: "flex items-center bg-muted/40 rounded-lg p-0.5" }, /* @__PURE__ */ import_react2.default.createElement(
|
|
224
261
|
Button,
|
|
225
262
|
{
|
|
226
263
|
variant: "ghost",
|
|
@@ -229,8 +266,8 @@ var MiniCalendar = ({
|
|
|
229
266
|
onClick: handlePrev,
|
|
230
267
|
"aria-label": "Previous month"
|
|
231
268
|
},
|
|
232
|
-
/* @__PURE__ */
|
|
233
|
-
), /* @__PURE__ */
|
|
269
|
+
/* @__PURE__ */ import_react2.default.createElement(import_lucide_react2.ChevronLeft, { className: "h-4 w-4" })
|
|
270
|
+
), /* @__PURE__ */ import_react2.default.createElement(
|
|
234
271
|
Button,
|
|
235
272
|
{
|
|
236
273
|
variant: "ghost",
|
|
@@ -239,12 +276,12 @@ var MiniCalendar = ({
|
|
|
239
276
|
onClick: handleNext,
|
|
240
277
|
"aria-label": "Next month"
|
|
241
278
|
},
|
|
242
|
-
/* @__PURE__ */
|
|
243
|
-
))), /* @__PURE__ */
|
|
244
|
-
const isSelected =
|
|
245
|
-
const isCurrentMonth =
|
|
246
|
-
const isTodayDate =
|
|
247
|
-
return /* @__PURE__ */
|
|
279
|
+
/* @__PURE__ */ import_react2.default.createElement(import_lucide_react2.ChevronRight, { className: "h-4 w-4" })
|
|
280
|
+
))), /* @__PURE__ */ import_react2.default.createElement("div", { className: "grid grid-cols-7 gap-y-2 text-center mb-2" }, weekDays.map((day, i) => /* @__PURE__ */ import_react2.default.createElement("div", { key: `${day}-${i}`, className: "text-[10px] text-muted-foreground/70 font-semibold uppercase" }, day))), /* @__PURE__ */ import_react2.default.createElement("div", { className: "grid grid-cols-7 gap-y-1 text-center" }, days.map((day) => {
|
|
281
|
+
const isSelected = (0, import_date_fns3.isSameDay)(day, currentDate);
|
|
282
|
+
const isCurrentMonth = (0, import_date_fns3.isSameMonth)(day, viewDate);
|
|
283
|
+
const isTodayDate = (0, import_date_fns3.isToday)(day);
|
|
284
|
+
return /* @__PURE__ */ import_react2.default.createElement(
|
|
248
285
|
"button",
|
|
249
286
|
{
|
|
250
287
|
key: day.toISOString(),
|
|
@@ -257,10 +294,202 @@ var MiniCalendar = ({
|
|
|
257
294
|
!isSelected && isTodayDate && "bg-primary/10 text-primary ring-1 ring-primary/30"
|
|
258
295
|
)
|
|
259
296
|
},
|
|
260
|
-
|
|
297
|
+
(0, import_date_fns3.format)(day, "d")
|
|
261
298
|
);
|
|
262
299
|
})));
|
|
263
300
|
};
|
|
301
|
+
|
|
302
|
+
// src/components/Sidebar.tsx
|
|
303
|
+
var import_date_fns_tz = require("date-fns-tz");
|
|
304
|
+
var import_date_fns5 = require("date-fns");
|
|
305
|
+
|
|
306
|
+
// src/core/format.ts
|
|
307
|
+
var import_date_fns4 = require("date-fns");
|
|
308
|
+
|
|
309
|
+
// src/locales/index.ts
|
|
310
|
+
var en = {
|
|
311
|
+
today: "Today",
|
|
312
|
+
month: "Month",
|
|
313
|
+
week: "Week",
|
|
314
|
+
day: "Day",
|
|
315
|
+
agenda: "Agenda",
|
|
316
|
+
resource: "Resources",
|
|
317
|
+
createEvent: "Create Event",
|
|
318
|
+
editEvent: "Edit Event",
|
|
319
|
+
delete: "Delete",
|
|
320
|
+
save: "Save",
|
|
321
|
+
cancel: "Cancel",
|
|
322
|
+
title: "Add title",
|
|
323
|
+
start: "Start",
|
|
324
|
+
end: "End",
|
|
325
|
+
allDay: "All Day",
|
|
326
|
+
description: "Description",
|
|
327
|
+
repeat: "Repeat",
|
|
328
|
+
noRepeat: "Does not repeat",
|
|
329
|
+
selectCalendar: "Select Calendar",
|
|
330
|
+
selectType: "Select Type",
|
|
331
|
+
daily: "Daily",
|
|
332
|
+
weekly: "Weekly",
|
|
333
|
+
monthly: "Monthly",
|
|
334
|
+
yearly: "Yearly",
|
|
335
|
+
search: "Search events...",
|
|
336
|
+
allTypes: "All Types",
|
|
337
|
+
timezone: "Time zone",
|
|
338
|
+
localTime: "Local Time",
|
|
339
|
+
create: "Create",
|
|
340
|
+
calendars: "Calendars",
|
|
341
|
+
event: "Event",
|
|
342
|
+
task: "Task",
|
|
343
|
+
appointmentSchedule: "Appointment schedule",
|
|
344
|
+
new: "New",
|
|
345
|
+
dateAndTime: "Date & Time",
|
|
346
|
+
whosJoining: "Who's joining?",
|
|
347
|
+
suggestedTimes: "Suggested times for guests",
|
|
348
|
+
viewSuggestions: "View suggestions",
|
|
349
|
+
whereWillItBe: "Where will it be?",
|
|
350
|
+
location: "Enter address",
|
|
351
|
+
descriptionAndAttachments: "Description",
|
|
352
|
+
dragAndDrop: "Drag & drop files or",
|
|
353
|
+
guests: "Guests",
|
|
354
|
+
addGuests: "Add guests",
|
|
355
|
+
addAttachment: "Upload files",
|
|
356
|
+
moreOptions: "More options",
|
|
357
|
+
doesNotRepeat: "Does not repeat",
|
|
358
|
+
locationHelpText: 'Enter a physical address (e.g. "123 Main St") to generate the map.',
|
|
359
|
+
notes: "Notes...",
|
|
360
|
+
guestCount: "guest",
|
|
361
|
+
guestsCount: "guests",
|
|
362
|
+
repeatFor: "Repeat for",
|
|
363
|
+
times: "times",
|
|
364
|
+
until: "Until",
|
|
365
|
+
endRepeat: "End repeat",
|
|
366
|
+
never: "Never",
|
|
367
|
+
afterOccurrences: "After occurrences",
|
|
368
|
+
onDate: "On date",
|
|
369
|
+
tomorrow: "Tomorrow",
|
|
370
|
+
edit: "Edit",
|
|
371
|
+
duplicate: "Duplicate",
|
|
372
|
+
eventSingular: "event",
|
|
373
|
+
eventPlural: "events",
|
|
374
|
+
allCaughtUp: "All caught up!",
|
|
375
|
+
noEventsScheduled: "No events scheduled",
|
|
376
|
+
noUpcoming: "Your schedule is clear",
|
|
377
|
+
noUpcomingHint: "No upcoming events to show. Create a new event to start planning."
|
|
378
|
+
};
|
|
379
|
+
var fr = {
|
|
380
|
+
today: "Aujourd'hui",
|
|
381
|
+
month: "Mois",
|
|
382
|
+
week: "Semaine",
|
|
383
|
+
day: "Jour",
|
|
384
|
+
agenda: "Agenda",
|
|
385
|
+
resource: "Ressources",
|
|
386
|
+
createEvent: "Cr\xE9er un \xE9v\xE9nement",
|
|
387
|
+
editEvent: "Modifier l'\xE9v\xE9nement",
|
|
388
|
+
delete: "Supprimer",
|
|
389
|
+
save: "Enregistrer",
|
|
390
|
+
cancel: "Annuler",
|
|
391
|
+
title: "Ajouter un titre",
|
|
392
|
+
start: "D\xE9but",
|
|
393
|
+
end: "Fin",
|
|
394
|
+
allDay: "Toute la journ\xE9e",
|
|
395
|
+
description: "Description",
|
|
396
|
+
repeat: "R\xE9p\xE9ter",
|
|
397
|
+
noRepeat: "Ne se r\xE9p\xE8te pas",
|
|
398
|
+
selectCalendar: "S\xE9lectionner un calendrier",
|
|
399
|
+
selectType: "S\xE9lectionner un type",
|
|
400
|
+
daily: "Quotidien",
|
|
401
|
+
weekly: "Hebdomadaire",
|
|
402
|
+
monthly: "Mensuel",
|
|
403
|
+
yearly: "Annuel",
|
|
404
|
+
search: "Rechercher...",
|
|
405
|
+
allTypes: "Tous les types",
|
|
406
|
+
timezone: "Fuseau horaire",
|
|
407
|
+
localTime: "Heure locale",
|
|
408
|
+
create: "Cr\xE9er",
|
|
409
|
+
calendars: "Calendriers",
|
|
410
|
+
event: "\xC9v\xE9nement",
|
|
411
|
+
task: "T\xE2che",
|
|
412
|
+
appointmentSchedule: "Planning de rendez-vous",
|
|
413
|
+
new: "Nouveau",
|
|
414
|
+
dateAndTime: "Date et heure",
|
|
415
|
+
whosJoining: "Qui participe ?",
|
|
416
|
+
suggestedTimes: "Horaires sugg\xE9r\xE9s",
|
|
417
|
+
viewSuggestions: "Voir les suggestions",
|
|
418
|
+
whereWillItBe: "O\xF9 aura lieu ?",
|
|
419
|
+
location: "Entrer une adresse",
|
|
420
|
+
descriptionAndAttachments: "Description",
|
|
421
|
+
dragAndDrop: "Glisser-d\xE9poser des fichiers ou",
|
|
422
|
+
guests: "Invit\xE9s",
|
|
423
|
+
addGuests: "Ajouter des invit\xE9s",
|
|
424
|
+
addAttachment: "T\xE9l\xE9charger des fichiers",
|
|
425
|
+
moreOptions: "Plus d'options",
|
|
426
|
+
doesNotRepeat: "Ne se r\xE9p\xE8te pas",
|
|
427
|
+
locationHelpText: 'Entrez une adresse physique (ex: "123 Rue Principale") pour g\xE9n\xE9rer la carte.',
|
|
428
|
+
notes: "Notes...",
|
|
429
|
+
guestCount: "invit\xE9",
|
|
430
|
+
guestsCount: "invit\xE9s",
|
|
431
|
+
repeatFor: "R\xE9p\xE9ter pendant",
|
|
432
|
+
times: "fois",
|
|
433
|
+
until: "Jusqu'au",
|
|
434
|
+
endRepeat: "Fin de r\xE9p\xE9tition",
|
|
435
|
+
never: "Jamais",
|
|
436
|
+
afterOccurrences: "Apr\xE8s occurrences",
|
|
437
|
+
onDate: "\xC0 la date",
|
|
438
|
+
tomorrow: "Demain",
|
|
439
|
+
edit: "Modifier",
|
|
440
|
+
duplicate: "Dupliquer",
|
|
441
|
+
eventSingular: "\xE9v\xE9nement",
|
|
442
|
+
eventPlural: "\xE9v\xE9nements",
|
|
443
|
+
allCaughtUp: "Tout est \xE0 jour !",
|
|
444
|
+
noEventsScheduled: "Aucun \xE9v\xE9nement pr\xE9vu",
|
|
445
|
+
noUpcoming: "Votre planning est libre",
|
|
446
|
+
noUpcomingHint: "Aucun \xE9v\xE9nement \xE0 venir. Cr\xE9ez un nouvel \xE9v\xE9nement pour commencer \xE0 planifier."
|
|
447
|
+
};
|
|
448
|
+
|
|
449
|
+
// src/core/format.ts
|
|
450
|
+
var clockCache = /* @__PURE__ */ new WeakMap();
|
|
451
|
+
function uses24HourClock(locale) {
|
|
452
|
+
if (!locale) return false;
|
|
453
|
+
let is24 = clockCache.get(locale);
|
|
454
|
+
if (is24 === void 0) {
|
|
455
|
+
is24 = !/[ap]\.?m/i.test((0, import_date_fns4.format)(new Date(2e3, 0, 1, 13, 0), "p", { locale }));
|
|
456
|
+
clockCache.set(locale, is24);
|
|
457
|
+
}
|
|
458
|
+
return is24;
|
|
459
|
+
}
|
|
460
|
+
var H24 = { hour: "H:mm", time: "H:mm", compact: "H:mm" };
|
|
461
|
+
var H12 = { hour: "h a", time: "h:mm a", compact: "h:mm" };
|
|
462
|
+
function timeFormats(locale) {
|
|
463
|
+
return uses24HourClock(locale) ? H24 : H12;
|
|
464
|
+
}
|
|
465
|
+
var MAX_FORMATTERS = 50;
|
|
466
|
+
var formatters = /* @__PURE__ */ new Map();
|
|
467
|
+
function getDateTimeFormat(locale, timeZone, options) {
|
|
468
|
+
const key = `${locale}|${timeZone ?? ""}|${JSON.stringify(options)}`;
|
|
469
|
+
let formatter = formatters.get(key);
|
|
470
|
+
if (formatter) {
|
|
471
|
+
formatters.delete(key);
|
|
472
|
+
} else {
|
|
473
|
+
formatter = new Intl.DateTimeFormat(locale, { ...options, timeZone });
|
|
474
|
+
if (formatters.size >= MAX_FORMATTERS) {
|
|
475
|
+
formatters.delete(formatters.keys().next().value);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
formatters.set(key, formatter);
|
|
479
|
+
return formatter;
|
|
480
|
+
}
|
|
481
|
+
function timeZoneAbbreviation(date, timeZone) {
|
|
482
|
+
try {
|
|
483
|
+
return getDateTimeFormat("en-US", timeZone, { timeZoneName: "short" }).formatToParts(date).find((part) => part.type === "timeZoneName")?.value ?? "";
|
|
484
|
+
} catch {
|
|
485
|
+
return "";
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
function resolveTranslations(language, overrides) {
|
|
489
|
+
return { ...language === "fr" ? fr : en, ...overrides };
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
// src/components/Sidebar.tsx
|
|
264
493
|
var Sidebar = ({
|
|
265
494
|
currentDate,
|
|
266
495
|
onDateChange,
|
|
@@ -275,11 +504,11 @@ var Sidebar = ({
|
|
|
275
504
|
translations,
|
|
276
505
|
locale
|
|
277
506
|
}) => {
|
|
278
|
-
const [calendarsOpen, setCalendarsOpen] =
|
|
279
|
-
const [timezoneOpen, setTimezoneOpen] =
|
|
280
|
-
const [now, setNow] =
|
|
281
|
-
const [hasMounted, setHasMounted] =
|
|
282
|
-
|
|
507
|
+
const [calendarsOpen, setCalendarsOpen] = (0, import_react3.useState)(true);
|
|
508
|
+
const [timezoneOpen, setTimezoneOpen] = (0, import_react3.useState)(false);
|
|
509
|
+
const [now, setNow] = (0, import_react3.useState)(null);
|
|
510
|
+
const [hasMounted, setHasMounted] = (0, import_react3.useState)(false);
|
|
511
|
+
(0, import_react3.useEffect)(() => {
|
|
283
512
|
setHasMounted(true);
|
|
284
513
|
setNow(/* @__PURE__ */ new Date());
|
|
285
514
|
const timer = setInterval(() => setNow(/* @__PURE__ */ new Date()), 6e4);
|
|
@@ -291,14 +520,7 @@ var Sidebar = ({
|
|
|
291
520
|
{ id: "3", label: "Tasks", color: "#6366f1", active: true }
|
|
292
521
|
];
|
|
293
522
|
const displayCalendars = calendars || defaultCalendars;
|
|
294
|
-
const getAcronym = (tz) =>
|
|
295
|
-
if (!tz || !now) return "LOC";
|
|
296
|
-
try {
|
|
297
|
-
return new Intl.DateTimeFormat("en-US", { timeZone: tz, timeZoneName: "short" }).formatToParts(now).find((part) => part.type === "timeZoneName")?.value || "";
|
|
298
|
-
} catch (e) {
|
|
299
|
-
return "";
|
|
300
|
-
}
|
|
301
|
-
};
|
|
523
|
+
const getAcronym = (tz) => !tz || !now ? "LOC" : timeZoneAbbreviation(now, tz);
|
|
302
524
|
const timezones = [
|
|
303
525
|
{ value: "", label: translations?.localTime || "Local Time", acronym: "LOC" },
|
|
304
526
|
{ value: "UTC", label: "UTC", acronym: "UTC" },
|
|
@@ -316,56 +538,53 @@ var Sidebar = ({
|
|
|
316
538
|
];
|
|
317
539
|
const formatTzLabel = (tz, showTime = true) => {
|
|
318
540
|
if (!hasMounted || !now || !showTime) {
|
|
319
|
-
return /* @__PURE__ */
|
|
541
|
+
return /* @__PURE__ */ import_react3.default.createElement("span", null, tz.label);
|
|
320
542
|
}
|
|
321
543
|
let time = "";
|
|
322
544
|
let acronym = tz.acronym;
|
|
323
545
|
try {
|
|
324
546
|
if (!tz.value) {
|
|
325
|
-
time =
|
|
326
|
-
|
|
327
|
-
acronym = new Intl.DateTimeFormat("en-US", { timeZoneName: "short" }).formatToParts(now).find((part) => part.type === "timeZoneName")?.value || "LOC";
|
|
328
|
-
} catch (e) {
|
|
329
|
-
}
|
|
547
|
+
time = (0, import_date_fns5.format)(now, "HH:mm");
|
|
548
|
+
acronym = timeZoneAbbreviation(now) || "LOC";
|
|
330
549
|
} else {
|
|
331
|
-
const zDate =
|
|
332
|
-
time =
|
|
550
|
+
const zDate = (0, import_date_fns_tz.toZonedTime)(now, tz.value);
|
|
551
|
+
time = (0, import_date_fns5.format)(zDate, "HH:mm");
|
|
333
552
|
const dynAcronym = getAcronym(tz.value);
|
|
334
553
|
if (dynAcronym && !dynAcronym.includes("GMT") && !dynAcronym.includes("Time")) {
|
|
335
554
|
acronym = dynAcronym;
|
|
336
555
|
}
|
|
337
556
|
}
|
|
338
|
-
} catch
|
|
339
|
-
return /* @__PURE__ */
|
|
557
|
+
} catch {
|
|
558
|
+
return /* @__PURE__ */ import_react3.default.createElement("span", null, tz.label);
|
|
340
559
|
}
|
|
341
|
-
return /* @__PURE__ */
|
|
560
|
+
return /* @__PURE__ */ import_react3.default.createElement("div", { className: "flex justify-between w-full" }, /* @__PURE__ */ import_react3.default.createElement("span", null, tz.label), /* @__PURE__ */ import_react3.default.createElement("span", { className: "text-muted-foreground ml-2 tabular-nums" }, time, " ", /* @__PURE__ */ import_react3.default.createElement("span", { className: "text-xs opacity-75" }, "(", acronym, ")")));
|
|
342
561
|
};
|
|
343
562
|
const selectedTzObj = timezones.find((t) => t.value === (timezone || ""));
|
|
344
563
|
const selectedTimezoneLabel = selectedTzObj ? formatTzLabel(selectedTzObj) : translations?.localTime || "Local Time";
|
|
345
|
-
return /* @__PURE__ */
|
|
564
|
+
return /* @__PURE__ */ import_react3.default.createElement("div", { className: cn("flex flex-col w-[260px] overflow-x-hidden h-full bg-gradient-to-b scrollbar-hide from-background via-background to-muted/10 pt-4 pb-4 overflow-y-auto hidden lg:flex", className) }, !readOnly && /* @__PURE__ */ import_react3.default.createElement("div", { className: "px-4 mb-6" }, /* @__PURE__ */ import_react3.default.createElement(
|
|
346
565
|
Button,
|
|
347
566
|
{
|
|
348
567
|
className: "w-full rounded-2xl shadow-lg bg-primary text-primary-foreground hover:bg-primary/90 h-12 gap-3 justify-center transition-all duration-300 hover:shadow-xl hover:shadow-primary/20 hover:scale-[1.02] active:scale-[0.98] font-semibold",
|
|
349
568
|
onClick: onEventCreate
|
|
350
569
|
},
|
|
351
|
-
/* @__PURE__ */
|
|
352
|
-
/* @__PURE__ */
|
|
353
|
-
)), /* @__PURE__ */
|
|
570
|
+
/* @__PURE__ */ import_react3.default.createElement(import_lucide_react3.Plus, { className: "w-5 h-5" }),
|
|
571
|
+
/* @__PURE__ */ import_react3.default.createElement("span", { className: "text-sm" }, translations?.create || "Create")
|
|
572
|
+
)), /* @__PURE__ */ import_react3.default.createElement(MiniCalendar, { currentDate, onDateChange, onViewChange, locale }), /* @__PURE__ */ import_react3.default.createElement("div", { className: "flex-1 px-4 space-y-5 mt-5" }, /* @__PURE__ */ import_react3.default.createElement("div", { className: "bg-muted/20 rounded-2xl p-3 border-[0px] border-border/30" }, /* @__PURE__ */ import_react3.default.createElement(
|
|
354
573
|
"div",
|
|
355
574
|
{
|
|
356
575
|
className: "flex items-center justify-between cursor-pointer hover:bg-accent/50 p-2 -m-1 rounded-xl mb-2 transition-all duration-200",
|
|
357
576
|
onClick: () => setCalendarsOpen(!calendarsOpen)
|
|
358
577
|
},
|
|
359
|
-
/* @__PURE__ */
|
|
360
|
-
/* @__PURE__ */
|
|
361
|
-
), calendarsOpen && /* @__PURE__ */
|
|
578
|
+
/* @__PURE__ */ import_react3.default.createElement("span", { className: "text-sm font-semibold text-foreground" }, translations?.calendars || "Calendars"),
|
|
579
|
+
/* @__PURE__ */ import_react3.default.createElement(import_lucide_react3.ChevronDown, { className: cn("w-4 h-4 text-muted-foreground transition-transform duration-200", calendarsOpen && "rotate-180") })
|
|
580
|
+
), calendarsOpen && /* @__PURE__ */ import_react3.default.createElement("div", { className: "space-y-1" }, displayCalendars.map((cal) => /* @__PURE__ */ import_react3.default.createElement(
|
|
362
581
|
"div",
|
|
363
582
|
{
|
|
364
583
|
key: cal.id,
|
|
365
584
|
className: "flex items-center gap-3 py-2 px-2 hover:bg-accent/60 rounded-xl cursor-pointer group transition-all duration-200",
|
|
366
585
|
onClick: () => onCalendarToggle?.(cal.id, !(cal.active ?? true))
|
|
367
586
|
},
|
|
368
|
-
/* @__PURE__ */
|
|
587
|
+
/* @__PURE__ */ import_react3.default.createElement("div", { className: "relative flex items-center justify-center" }, /* @__PURE__ */ import_react3.default.createElement(
|
|
369
588
|
"input",
|
|
370
589
|
{
|
|
371
590
|
type: "checkbox",
|
|
@@ -378,7 +597,7 @@ var Sidebar = ({
|
|
|
378
597
|
style: { "--primary-color": cal.color },
|
|
379
598
|
"data-cal-id": cal.id
|
|
380
599
|
}
|
|
381
|
-
), /* @__PURE__ */
|
|
600
|
+
), /* @__PURE__ */ import_react3.default.createElement("div", { className: "absolute inset-0 flex items-center justify-center pointer-events-none opacity-0 peer-checked:opacity-100 transition-opacity" }, /* @__PURE__ */ import_react3.default.createElement("svg", { className: "w-3.5 h-3.5 text-white", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 3 }, /* @__PURE__ */ import_react3.default.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M5 13l4 4L19 7" }))), /* @__PURE__ */ import_react3.default.createElement("style", null, `
|
|
382
601
|
input[type="checkbox"][data-cal-id="${cal.id}"]:checked {
|
|
383
602
|
background-color: ${cal.color} !important;
|
|
384
603
|
border-color: ${cal.color} !important;
|
|
@@ -387,23 +606,23 @@ var Sidebar = ({
|
|
|
387
606
|
--tw-ring-color: ${cal.color}40 !important;
|
|
388
607
|
}
|
|
389
608
|
`)),
|
|
390
|
-
/* @__PURE__ */
|
|
391
|
-
/* @__PURE__ */
|
|
609
|
+
/* @__PURE__ */ import_react3.default.createElement("div", { className: "flex items-center gap-2 flex-1 min-w-0" }, /* @__PURE__ */ import_react3.default.createElement("span", { className: "text-sm text-foreground/90 truncate font-medium" }, cal.label)),
|
|
610
|
+
/* @__PURE__ */ import_react3.default.createElement(
|
|
392
611
|
"div",
|
|
393
612
|
{
|
|
394
613
|
className: "w-2 h-2 rounded-full opacity-60 group-hover:opacity-100 transition-opacity",
|
|
395
614
|
style: { backgroundColor: cal.color }
|
|
396
615
|
}
|
|
397
616
|
)
|
|
398
|
-
))))), /* @__PURE__ */
|
|
617
|
+
))))), /* @__PURE__ */ import_react3.default.createElement("div", { className: "mt-auto px-4 pt-5" }, /* @__PURE__ */ import_react3.default.createElement("div", { className: "bg-muted/20 rounded-2xl p-3" }, /* @__PURE__ */ import_react3.default.createElement("div", { className: "flex items-center gap-2 mb-3" }, /* @__PURE__ */ import_react3.default.createElement("div", { className: "p-1.5 bg-primary/10 rounded-lg" }, /* @__PURE__ */ import_react3.default.createElement(import_lucide_react3.Globe, { className: "w-4 h-4 text-primary" })), /* @__PURE__ */ import_react3.default.createElement("span", { className: "text-sm font-semibold text-foreground" }, translations?.timezone || "Timezone")), /* @__PURE__ */ import_react3.default.createElement("div", { className: "relative" }, /* @__PURE__ */ import_react3.default.createElement(
|
|
399
618
|
"button",
|
|
400
619
|
{
|
|
401
620
|
onClick: () => setTimezoneOpen(!timezoneOpen),
|
|
402
621
|
className: "w-full flex items-center justify-between bg-blue-200/40 hover:bg-blue-200/80 rounded-xl py-2.5 pl-4 pr-3 text-sm text-foreground focus:outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary/50 transition-all duration-200 text-left"
|
|
403
622
|
},
|
|
404
|
-
/* @__PURE__ */
|
|
405
|
-
/* @__PURE__ */
|
|
406
|
-
), timezoneOpen && /* @__PURE__ */
|
|
623
|
+
/* @__PURE__ */ import_react3.default.createElement("div", { className: "flex-1 truncate mr-2 font-medium" }, selectedTimezoneLabel),
|
|
624
|
+
/* @__PURE__ */ import_react3.default.createElement(import_lucide_react3.ChevronDown, { className: cn("w-4 h-4 text-muted-foreground transition-transform duration-200", timezoneOpen && "rotate-180") })
|
|
625
|
+
), timezoneOpen && /* @__PURE__ */ import_react3.default.createElement(import_react3.default.Fragment, null, /* @__PURE__ */ import_react3.default.createElement("div", { className: "fixed inset-0 z-40", onClick: () => setTimezoneOpen(false) }), /* @__PURE__ */ import_react3.default.createElement("div", { className: "absolute bottom-full left-0 w-full mb-2 bg-background rounded-xl shadow-2xl z-50 max-h-[260px] overflow-y-auto p-1.5 animate-in fade-in zoom-in-95 duration-200 backdrop-blur-none" }, timezones.map((tz) => /* @__PURE__ */ import_react3.default.createElement(
|
|
407
626
|
"div",
|
|
408
627
|
{
|
|
409
628
|
key: tz.value,
|
|
@@ -419,26 +638,202 @@ var Sidebar = ({
|
|
|
419
638
|
formatTzLabel(tz)
|
|
420
639
|
))))))));
|
|
421
640
|
};
|
|
422
|
-
|
|
641
|
+
|
|
642
|
+
// src/views/MonthView.tsx
|
|
643
|
+
var import_react6 = __toESM(require("react"));
|
|
644
|
+
var import_date_fns8 = require("date-fns");
|
|
645
|
+
|
|
646
|
+
// src/core/events.ts
|
|
647
|
+
var import_date_fns7 = require("date-fns");
|
|
648
|
+
|
|
649
|
+
// src/core/timezone.ts
|
|
650
|
+
var import_date_fns6 = require("date-fns");
|
|
651
|
+
var import_date_fns_tz2 = require("date-fns-tz");
|
|
652
|
+
|
|
653
|
+
// src/core/warn.ts
|
|
654
|
+
var warned = /* @__PURE__ */ new Set();
|
|
655
|
+
function isProductionBuild() {
|
|
656
|
+
try {
|
|
657
|
+
return process.env.NODE_ENV === "production";
|
|
658
|
+
} catch {
|
|
659
|
+
return false;
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
function warnOnce(key, message) {
|
|
663
|
+
if (isProductionBuild() || warned.has(key)) return;
|
|
664
|
+
warned.add(key);
|
|
665
|
+
console.warn(`[calendarkit-pro] ${message}`);
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
// src/core/timezone.ts
|
|
669
|
+
var validity = /* @__PURE__ */ new Map();
|
|
670
|
+
function resolveTimeZone(tz) {
|
|
671
|
+
if (!tz) return void 0;
|
|
672
|
+
let valid = validity.get(tz);
|
|
673
|
+
if (valid === void 0) {
|
|
674
|
+
try {
|
|
675
|
+
new Intl.DateTimeFormat("en-US", { timeZone: tz });
|
|
676
|
+
valid = true;
|
|
677
|
+
} catch {
|
|
678
|
+
valid = false;
|
|
679
|
+
}
|
|
680
|
+
validity.set(tz, valid);
|
|
681
|
+
}
|
|
682
|
+
if (!valid) {
|
|
683
|
+
warnOnce(`invalid-timezone:${tz}`, `Unknown timezone "${tz}", falling back to local time.`);
|
|
684
|
+
return void 0;
|
|
685
|
+
}
|
|
686
|
+
return tz;
|
|
687
|
+
}
|
|
688
|
+
function toDisplay(date, tz) {
|
|
689
|
+
const zone = resolveTimeZone(tz);
|
|
690
|
+
return zone ? (0, import_date_fns_tz2.toZonedTime)(date, zone) : date;
|
|
691
|
+
}
|
|
692
|
+
function fromDisplay(wall, tz) {
|
|
693
|
+
const zone = resolveTimeZone(tz);
|
|
694
|
+
return zone ? (0, import_date_fns_tz2.fromZonedTime)(wall, zone) : new Date(wall);
|
|
695
|
+
}
|
|
696
|
+
function minutesSinceDisplayMidnight(date, tz) {
|
|
697
|
+
const wall = toDisplay(date, tz);
|
|
698
|
+
return wall.getHours() * 60 + wall.getMinutes();
|
|
699
|
+
}
|
|
700
|
+
function isSameDisplayDay(date, day, tz) {
|
|
701
|
+
return (0, import_date_fns6.isSameDay)(toDisplay(date, tz), day);
|
|
702
|
+
}
|
|
703
|
+
function displayToday(tz, now = /* @__PURE__ */ new Date()) {
|
|
704
|
+
return (0, import_date_fns6.startOfDay)(toDisplay(now, tz));
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
// src/core/events.ts
|
|
708
|
+
var toDate = (value) => value === void 0 || value === null ? void 0 : value instanceof Date ? value : new Date(value);
|
|
709
|
+
var isValidDate = (date) => !!date && !Number.isNaN(date.getTime());
|
|
710
|
+
var normalizedEvent = /* @__PURE__ */ new WeakMap();
|
|
711
|
+
var normalizedList = /* @__PURE__ */ new WeakMap();
|
|
712
|
+
function normalizeEvent(event) {
|
|
713
|
+
const cached = normalizedEvent.get(event);
|
|
714
|
+
if (cached !== void 0) return cached;
|
|
715
|
+
const start = toDate(event.start);
|
|
716
|
+
const end = toDate(event.end);
|
|
717
|
+
let result = null;
|
|
718
|
+
if (!isValidDate(start) || !isValidDate(end)) {
|
|
719
|
+
warnOnce(`invalid-date:${event.id}`, `Event "${event.id}" has an invalid start or end date and was skipped.`);
|
|
720
|
+
} else if (end.getTime() < start.getTime()) {
|
|
721
|
+
warnOnce(`end-before-start:${event.id}`, `Event "${event.id}" ends before it starts and was skipped.`);
|
|
722
|
+
} else {
|
|
723
|
+
const needsCopy = start !== event.start || end !== event.end || needsRecurrenceCopy(event);
|
|
724
|
+
result = needsCopy ? {
|
|
725
|
+
...event,
|
|
726
|
+
start,
|
|
727
|
+
end,
|
|
728
|
+
recurrence: event.recurrence && {
|
|
729
|
+
...event.recurrence,
|
|
730
|
+
until: toDate(event.recurrence.until),
|
|
731
|
+
exdates: event.recurrence.exdates?.map((d) => toDate(d))
|
|
732
|
+
}
|
|
733
|
+
} : event;
|
|
734
|
+
}
|
|
735
|
+
normalizedEvent.set(event, result);
|
|
736
|
+
return result;
|
|
737
|
+
}
|
|
738
|
+
function needsRecurrenceCopy(event) {
|
|
739
|
+
const r = event.recurrence;
|
|
740
|
+
if (!r) return false;
|
|
741
|
+
return r.until !== void 0 && !(r.until instanceof Date) || !!r.exdates?.some((d) => !(d instanceof Date));
|
|
742
|
+
}
|
|
743
|
+
function normalizeEvents(events) {
|
|
744
|
+
const cached = normalizedList.get(events);
|
|
745
|
+
if (cached) return cached;
|
|
746
|
+
const seen = /* @__PURE__ */ new Set();
|
|
747
|
+
const result = [];
|
|
748
|
+
for (const event of events) {
|
|
749
|
+
const normalized = normalizeEvent(event);
|
|
750
|
+
if (!normalized) continue;
|
|
751
|
+
if (seen.has(normalized.id)) {
|
|
752
|
+
warnOnce(`duplicate-id:${normalized.id}`, `Duplicate event id "${normalized.id}": ids must be unique.`);
|
|
753
|
+
}
|
|
754
|
+
seen.add(normalized.id);
|
|
755
|
+
result.push(normalized);
|
|
756
|
+
}
|
|
757
|
+
normalizedList.set(events, result);
|
|
758
|
+
return result;
|
|
759
|
+
}
|
|
760
|
+
var dayKey = (wall) => (0, import_date_fns7.format)(wall, "yyyy-MM-dd");
|
|
761
|
+
function memoByZone(cache, events, tz, compute) {
|
|
762
|
+
let byZone = cache.get(events);
|
|
763
|
+
if (!byZone) {
|
|
764
|
+
byZone = /* @__PURE__ */ new Map();
|
|
765
|
+
cache.set(events, byZone);
|
|
766
|
+
}
|
|
767
|
+
const key = tz ?? "";
|
|
768
|
+
let value = byZone.get(key);
|
|
769
|
+
if (value === void 0) {
|
|
770
|
+
value = compute();
|
|
771
|
+
byZone.set(key, value);
|
|
772
|
+
}
|
|
773
|
+
return value;
|
|
774
|
+
}
|
|
775
|
+
var startDayCache = /* @__PURE__ */ new WeakMap();
|
|
776
|
+
function eventsByStartDay(events, tz) {
|
|
777
|
+
return memoByZone(startDayCache, events, tz, () => {
|
|
778
|
+
const map = /* @__PURE__ */ new Map();
|
|
779
|
+
for (const event of events) {
|
|
780
|
+
const key = dayKey(toDisplay(event.start, tz));
|
|
781
|
+
const bucket = map.get(key);
|
|
782
|
+
if (bucket) bucket.push(event);
|
|
783
|
+
else map.set(key, [event]);
|
|
784
|
+
}
|
|
785
|
+
return map;
|
|
786
|
+
});
|
|
787
|
+
}
|
|
788
|
+
var segmentCache = /* @__PURE__ */ new WeakMap();
|
|
789
|
+
function segmentsByDisplayDay(events, tz, range) {
|
|
790
|
+
const cacheKey = range ? `${tz ?? ""}|${range.start.getTime()}|${range.end.getTime()}` : tz;
|
|
791
|
+
return memoByZone(segmentCache, events, cacheKey, () => {
|
|
792
|
+
const map = /* @__PURE__ */ new Map();
|
|
793
|
+
for (const event of events) {
|
|
794
|
+
const wallStart = toDisplay(event.start, tz);
|
|
795
|
+
const rawEnd = toDisplay(event.end, tz);
|
|
796
|
+
const wallEnd = rawEnd < wallStart ? wallStart : rawEnd;
|
|
797
|
+
if (range && (wallEnd < range.start || wallStart >= range.end)) continue;
|
|
798
|
+
let day = (0, import_date_fns7.startOfDay)(range && wallStart < range.start ? range.start : wallStart);
|
|
799
|
+
const stop = range && wallEnd > range.end ? range.end : wallEnd;
|
|
800
|
+
do {
|
|
801
|
+
const next = (0, import_date_fns7.addDays)(day, 1);
|
|
802
|
+
const start = wallStart > day ? wallStart : day;
|
|
803
|
+
const end = wallEnd < next ? wallEnd : next;
|
|
804
|
+
if (end > start || wallStart.getTime() === wallEnd.getTime()) {
|
|
805
|
+
const key = dayKey(day);
|
|
806
|
+
const bucket = map.get(key);
|
|
807
|
+
const segment = { event, start, end };
|
|
808
|
+
if (bucket) bucket.push(segment);
|
|
809
|
+
else map.set(key, [segment]);
|
|
810
|
+
}
|
|
811
|
+
day = next;
|
|
812
|
+
} while (day < stop);
|
|
813
|
+
}
|
|
814
|
+
return map;
|
|
815
|
+
});
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
// src/components/dnd/DraggableEvent.tsx
|
|
819
|
+
var import_react4 = __toESM(require("react"));
|
|
820
|
+
var import_core = require("@dnd-kit/core");
|
|
821
|
+
var import_utilities = require("@dnd-kit/utilities");
|
|
822
|
+
var DraggableEventImpl = ({ event, dragId, grabOffsetMs, children, className, style: propStyle, ...props }) => {
|
|
423
823
|
const dragDisabled = isEventDragDisabled(event);
|
|
424
|
-
const { attributes, listeners, setNodeRef, transform, isDragging } =
|
|
425
|
-
id: event.id,
|
|
426
|
-
data: { event },
|
|
824
|
+
const { attributes, listeners, setNodeRef, transform, isDragging } = (0, import_core.useDraggable)({
|
|
825
|
+
id: dragId ?? event.id,
|
|
826
|
+
data: { event, grabOffsetMs },
|
|
427
827
|
disabled: dragDisabled
|
|
428
828
|
});
|
|
429
829
|
const style = {
|
|
430
830
|
...propStyle,
|
|
431
|
-
transform:
|
|
831
|
+
transform: import_utilities.CSS.Translate.toString(transform),
|
|
432
832
|
zIndex: isDragging ? 100 : propStyle?.zIndex,
|
|
433
|
-
//
|
|
434
|
-
// so that the DragOverlay (the "ghost") is the only thing the user focuses on.
|
|
435
|
-
// If we set opacity: 0, it disappears. If 0.1, it's a faint placeholder.
|
|
436
|
-
// The user asked for "Make the entire dragged item transparent".
|
|
437
|
-
// Usually this means the original item should be faded out while the drag overlay is moving.
|
|
833
|
+
// Hide the original while dragging: the DragOverlay ghost is what the user follows.
|
|
438
834
|
opacity: isDragging ? 0 : propStyle?.opacity
|
|
439
|
-
// Hiding original element completely
|
|
440
835
|
};
|
|
441
|
-
return /* @__PURE__ */
|
|
836
|
+
return /* @__PURE__ */ import_react4.default.createElement(
|
|
442
837
|
"div",
|
|
443
838
|
{
|
|
444
839
|
ref: setNodeRef,
|
|
@@ -451,32 +846,59 @@ var DraggableEvent = ({ event, children, className, style: propStyle, ...props }
|
|
|
451
846
|
children
|
|
452
847
|
);
|
|
453
848
|
};
|
|
454
|
-
var
|
|
455
|
-
|
|
849
|
+
var DraggableEvent = import_react4.default.memo(DraggableEventImpl);
|
|
850
|
+
|
|
851
|
+
// src/components/dnd/DroppableCell.tsx
|
|
852
|
+
var import_react5 = __toESM(require("react"));
|
|
853
|
+
var import_core2 = require("@dnd-kit/core");
|
|
854
|
+
var QUARTER_HOVER = [
|
|
855
|
+
"hover:bg-blue-50/50 dark:hover:bg-blue-900/10",
|
|
856
|
+
"hover:bg-blue-50/80 dark:hover:bg-blue-900/20",
|
|
857
|
+
"hover:bg-blue-100/50 dark:hover:bg-blue-900/30",
|
|
858
|
+
"hover:bg-blue-100/80 dark:hover:bg-blue-900/40"
|
|
859
|
+
];
|
|
860
|
+
var QUARTER_ACTIVE = [
|
|
861
|
+
"bg-blue-50/50 dark:bg-blue-900/10 ring-2 ring-primary ring-inset",
|
|
862
|
+
"bg-blue-50/80 dark:bg-blue-900/20 ring-2 ring-primary ring-inset",
|
|
863
|
+
"bg-blue-100/50 dark:bg-blue-900/30 ring-2 ring-primary ring-inset",
|
|
864
|
+
"bg-blue-100/80 dark:bg-blue-900/40 ring-2 ring-primary ring-inset"
|
|
865
|
+
];
|
|
866
|
+
var quarterOf = (date) => Math.min(3, Math.floor(date.getMinutes() / 15));
|
|
867
|
+
var DroppableCellImpl = ({ id, date, resourceId, children, className, style, onClick, onSlotClick }) => {
|
|
868
|
+
const { isOver, setNodeRef } = (0, import_core2.useDroppable)({
|
|
456
869
|
id,
|
|
457
870
|
data: { date, resourceId }
|
|
458
871
|
});
|
|
459
|
-
const
|
|
460
|
-
|
|
461
|
-
const activeQuarterClass = minutes === 0 ? "bg-blue-50/50 dark:bg-blue-900/10 ring-2 ring-primary ring-inset" : minutes === 15 ? "bg-blue-50/80 dark:bg-blue-900/20 ring-2 ring-primary ring-inset" : minutes === 30 ? "bg-blue-100/50 dark:bg-blue-900/30 ring-2 ring-primary ring-inset" : "bg-blue-100/80 dark:bg-blue-900/40 ring-2 ring-primary ring-inset";
|
|
462
|
-
return /* @__PURE__ */ React15__namespace.default.createElement(
|
|
872
|
+
const quarter = quarterOf(date);
|
|
873
|
+
return /* @__PURE__ */ import_react5.default.createElement(
|
|
463
874
|
"div",
|
|
464
875
|
{
|
|
465
876
|
ref: setNodeRef,
|
|
466
877
|
className: cn(
|
|
467
878
|
className,
|
|
468
|
-
|
|
469
|
-
isOver &&
|
|
879
|
+
QUARTER_HOVER[quarter],
|
|
880
|
+
isOver && QUARTER_ACTIVE[quarter],
|
|
881
|
+
onSlotClick && "cursor-pointer"
|
|
470
882
|
),
|
|
471
883
|
style,
|
|
472
|
-
onClick
|
|
884
|
+
onClick: onSlotClick ? () => onSlotClick(date, resourceId) : onClick
|
|
473
885
|
},
|
|
474
886
|
children
|
|
475
887
|
);
|
|
476
888
|
};
|
|
889
|
+
var shallowEqualStyle = (a, b) => {
|
|
890
|
+
if (a === b) return true;
|
|
891
|
+
if (!a || !b) return false;
|
|
892
|
+
const keys = Object.keys(a);
|
|
893
|
+
return keys.length === Object.keys(b).length && keys.every((key) => a[key] === b[key]);
|
|
894
|
+
};
|
|
895
|
+
var DroppableCell = import_react5.default.memo(
|
|
896
|
+
DroppableCellImpl,
|
|
897
|
+
(prev, next) => prev.id === next.id && prev.date.getTime() === next.date.getTime() && prev.resourceId === next.resourceId && prev.children === next.children && prev.className === next.className && prev.onClick === next.onClick && prev.onSlotClick === next.onSlotClick && shallowEqualStyle(prev.style, next.style)
|
|
898
|
+
);
|
|
477
899
|
|
|
478
900
|
// src/views/MonthView.tsx
|
|
479
|
-
var EventItem =
|
|
901
|
+
var EventItem = import_react6.default.memo(({ event, onEventClick }) => /* @__PURE__ */ import_react6.default.createElement(DraggableEvent, { event }, /* @__PURE__ */ import_react6.default.createElement(
|
|
480
902
|
"div",
|
|
481
903
|
{
|
|
482
904
|
className: cn(
|
|
@@ -494,7 +916,7 @@ var EventItem = React15__namespace.default.memo(({ event, onEventClick }) => /*
|
|
|
494
916
|
onEventClick?.(event);
|
|
495
917
|
}
|
|
496
918
|
},
|
|
497
|
-
/* @__PURE__ */
|
|
919
|
+
/* @__PURE__ */ import_react6.default.createElement("span", { className: "font-medium" }, event.title)
|
|
498
920
|
)));
|
|
499
921
|
EventItem.displayName = "EventItem";
|
|
500
922
|
var MonthView = ({
|
|
@@ -505,44 +927,24 @@ var MonthView = ({
|
|
|
505
927
|
timezone,
|
|
506
928
|
locale
|
|
507
929
|
}) => {
|
|
508
|
-
const weekStartsOn = locale
|
|
509
|
-
const days =
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
);
|
|
513
|
-
|
|
514
|
-
const start = dateFns.startOfWeek(currentDate, { weekStartsOn });
|
|
515
|
-
const end = dateFns.endOfWeek(currentDate, { weekStartsOn });
|
|
516
|
-
return dateFns.eachDayOfInterval({ start, end });
|
|
517
|
-
}, [currentDate, weekStartsOn]);
|
|
518
|
-
const getZonedDate = React15.useCallback((date) => {
|
|
519
|
-
return timezone ? dateFnsTz.toZonedTime(date, timezone) : date;
|
|
520
|
-
}, [timezone]);
|
|
521
|
-
const eventsByDay = React15.useMemo(() => {
|
|
522
|
-
const map = /* @__PURE__ */ new Map();
|
|
523
|
-
events.forEach((event) => {
|
|
524
|
-
const zonedStart = getZonedDate(event.start);
|
|
525
|
-
const key = dateFns.format(zonedStart, "yyyy-MM-dd");
|
|
526
|
-
if (!map.has(key)) {
|
|
527
|
-
map.set(key, []);
|
|
528
|
-
}
|
|
529
|
-
map.get(key).push(event);
|
|
530
|
-
});
|
|
531
|
-
return map;
|
|
532
|
-
}, [events, getZonedDate]);
|
|
533
|
-
return /* @__PURE__ */ React15__namespace.default.createElement("div", { className: "flex flex-col h-full bg-background border-[0.5px] scrollbar-hide border-border/50 rounded-2xl overflow-hidden min-w-[800px] md:min-w-0 shadow-sm" }, /* @__PURE__ */ React15__namespace.default.createElement("div", { className: "overflow-y-auto flex-1 relative" }, /* @__PURE__ */ React15__namespace.default.createElement("div", { className: "grid grid-cols-7 border-b-[0.5px] border-border/50 bg-gradient-to-r from-muted/30 via-muted/40 to-muted/30 sticky top-0 z-20 backdrop-blur-sm" }, weekDays.map((day) => /* @__PURE__ */ React15__namespace.default.createElement(
|
|
930
|
+
const weekStartsOn = resolveWeekStartsOn(locale, 1);
|
|
931
|
+
const days = (0, import_react6.useMemo)(() => getMonthGrid(currentDate, weekStartsOn), [currentDate, weekStartsOn]);
|
|
932
|
+
const weekDays = (0, import_react6.useMemo)(() => getWeekDays(currentDate, weekStartsOn), [currentDate, weekStartsOn]);
|
|
933
|
+
const eventsByDay = eventsByStartDay(events, timezone);
|
|
934
|
+
const today = displayToday(timezone);
|
|
935
|
+
return /* @__PURE__ */ import_react6.default.createElement("div", { className: "flex flex-col h-full bg-background border-[0.5px] scrollbar-hide border-border/50 rounded-2xl overflow-hidden min-w-[800px] md:min-w-0 shadow-sm" }, /* @__PURE__ */ import_react6.default.createElement("div", { className: "overflow-y-auto flex-1 relative" }, /* @__PURE__ */ import_react6.default.createElement("div", { className: "grid grid-cols-7 border-b-[0.5px] border-border/50 bg-gradient-to-r from-muted/30 via-muted/40 to-muted/30 sticky top-0 z-20 backdrop-blur-sm" }, weekDays.map((day) => /* @__PURE__ */ import_react6.default.createElement(
|
|
534
936
|
"div",
|
|
535
937
|
{
|
|
536
938
|
key: day.toISOString(),
|
|
537
939
|
className: "py-3 text-center text-xs font-semibold text-muted-foreground border-r-[0.5px] border-border/30 last:border-r-0 uppercase tracking-wider"
|
|
538
940
|
},
|
|
539
|
-
|
|
540
|
-
))), /* @__PURE__ */
|
|
541
|
-
const
|
|
542
|
-
const dayEvents = eventsByDay.get(
|
|
543
|
-
const isCurrentMonth =
|
|
941
|
+
(0, import_date_fns8.format)(day, "EEE", { locale })
|
|
942
|
+
))), /* @__PURE__ */ import_react6.default.createElement("div", { className: "grid grid-cols-7", style: { gridAutoRows: "130px" } }, days.map((day) => {
|
|
943
|
+
const dayKey2 = (0, import_date_fns8.format)(day, "yyyy-MM-dd");
|
|
944
|
+
const dayEvents = eventsByDay.get(dayKey2) || [];
|
|
945
|
+
const isCurrentMonth = (0, import_date_fns8.isSameMonth)(day, currentDate);
|
|
544
946
|
const cellId = day.toISOString();
|
|
545
|
-
return /* @__PURE__ */
|
|
947
|
+
return /* @__PURE__ */ import_react6.default.createElement(
|
|
546
948
|
DroppableCell,
|
|
547
949
|
{
|
|
548
950
|
key: cellId,
|
|
@@ -551,18 +953,87 @@ var MonthView = ({
|
|
|
551
953
|
className: cn(
|
|
552
954
|
"h-[130px] p-2 border-b-[0.5px] border-r-[0.5px] border-border/30 last:border-r-0 relative transition-all duration-200 hover:bg-accent/5 flex flex-col gap-1.5 overflow-hidden group",
|
|
553
955
|
!isCurrentMonth && "bg-muted/5 text-muted-foreground/60",
|
|
554
|
-
|
|
956
|
+
(0, import_date_fns8.isSameDay)(day, today) && "bg-primary/5 ring-1 ring-inset ring-primary/20"
|
|
555
957
|
),
|
|
556
958
|
onClick: () => onDateClick?.(day)
|
|
557
959
|
},
|
|
558
|
-
/* @__PURE__ */
|
|
960
|
+
/* @__PURE__ */ import_react6.default.createElement("div", { className: "flex justify-between items-start" }, /* @__PURE__ */ import_react6.default.createElement("div", { className: cn(
|
|
559
961
|
"text-sm font-semibold w-7 h-7 flex items-center justify-center rounded-full transition-all duration-200",
|
|
560
|
-
|
|
561
|
-
) },
|
|
562
|
-
/* @__PURE__ */
|
|
962
|
+
(0, import_date_fns8.isSameDay)(day, today) ? "bg-primary text-primary-foreground shadow-md shadow-primary/30" : "group-hover:bg-accent"
|
|
963
|
+
) }, (0, import_date_fns8.format)(day, "d", { locale })), dayEvents.length > 0 && /* @__PURE__ */ import_react6.default.createElement("div", { className: "text-[10px] font-medium text-muted-foreground/60 bg-muted/50 px-1.5 py-0.5 rounded-full" }, dayEvents.length)),
|
|
964
|
+
/* @__PURE__ */ import_react6.default.createElement("div", { className: "flex-1 flex flex-col gap-1 scrollbar-hide overflow-y-auto overflow-x-hidden" }, dayEvents.slice(0, 4).map((event) => /* @__PURE__ */ import_react6.default.createElement(EventItem, { key: `${event.id}-${dayKey2}`, event, onEventClick })), dayEvents.length > 4 && /* @__PURE__ */ import_react6.default.createElement("div", { className: "text-[10px] text-primary font-semibold text-center py-1 px-2 rounded-md bg-primary/5 hover:bg-primary/10 cursor-pointer transition-colors" }, "+", dayEvents.length - 4, " more"))
|
|
563
965
|
);
|
|
564
966
|
}))));
|
|
565
967
|
};
|
|
968
|
+
|
|
969
|
+
// src/views/WeekView.tsx
|
|
970
|
+
var import_react8 = __toESM(require("react"));
|
|
971
|
+
var import_date_fns9 = require("date-fns");
|
|
972
|
+
|
|
973
|
+
// src/core/layout.ts
|
|
974
|
+
var layoutCache = /* @__PURE__ */ new WeakMap();
|
|
975
|
+
function layoutDayEvents(segments) {
|
|
976
|
+
const cached = layoutCache.get(segments);
|
|
977
|
+
if (cached) return cached;
|
|
978
|
+
const sorted = [...segments].sort(
|
|
979
|
+
(a, b) => a.start.getTime() - b.start.getTime() || b.end.getTime() - a.end.getTime() || (a.event.id < b.event.id ? -1 : a.event.id > b.event.id ? 1 : 0)
|
|
980
|
+
);
|
|
981
|
+
const result = [];
|
|
982
|
+
let cluster = [];
|
|
983
|
+
let columnEnds = [];
|
|
984
|
+
let clusterEnd = -Infinity;
|
|
985
|
+
const closeCluster = () => {
|
|
986
|
+
for (const placed of cluster) placed.columns = columnEnds.length;
|
|
987
|
+
cluster = [];
|
|
988
|
+
columnEnds = [];
|
|
989
|
+
};
|
|
990
|
+
for (const segment of sorted) {
|
|
991
|
+
const start = segment.start.getTime();
|
|
992
|
+
const end = Math.max(segment.end.getTime(), start + 1);
|
|
993
|
+
if (start >= clusterEnd) closeCluster();
|
|
994
|
+
let column = columnEnds.findIndex((columnEnd) => columnEnd <= start);
|
|
995
|
+
if (column === -1) {
|
|
996
|
+
column = columnEnds.length;
|
|
997
|
+
columnEnds.push(end);
|
|
998
|
+
} else {
|
|
999
|
+
columnEnds[column] = end;
|
|
1000
|
+
}
|
|
1001
|
+
const placed = { ...segment, column, columns: 1 };
|
|
1002
|
+
cluster.push(placed);
|
|
1003
|
+
result.push(placed);
|
|
1004
|
+
clusterEnd = Math.max(clusterEnd, end);
|
|
1005
|
+
}
|
|
1006
|
+
closeCluster();
|
|
1007
|
+
layoutCache.set(segments, result);
|
|
1008
|
+
return result;
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
// src/components/dnd/ResizableEvent.tsx
|
|
1012
|
+
var import_react7 = __toESM(require("react"));
|
|
1013
|
+
|
|
1014
|
+
// src/core/dnd.ts
|
|
1015
|
+
function computeDrop({ event, overDate, overResourceId, grabOffsetMs = 0, view, tz }) {
|
|
1016
|
+
let wallStart;
|
|
1017
|
+
if (view === "month") {
|
|
1018
|
+
const original = toDisplay(event.start, tz);
|
|
1019
|
+
wallStart = new Date(overDate);
|
|
1020
|
+
wallStart.setHours(original.getHours(), original.getMinutes(), original.getSeconds(), original.getMilliseconds());
|
|
1021
|
+
} else {
|
|
1022
|
+
wallStart = new Date(overDate.getTime() - grabOffsetMs);
|
|
1023
|
+
wallStart.setSeconds(0, 0);
|
|
1024
|
+
}
|
|
1025
|
+
const start = fromDisplay(wallStart, tz);
|
|
1026
|
+
const end = new Date(start.getTime() + (event.end.getTime() - event.start.getTime()));
|
|
1027
|
+
const resourceId = overResourceId ?? event.resourceId;
|
|
1028
|
+
if (start.getTime() === event.start.getTime() && resourceId === event.resourceId) return null;
|
|
1029
|
+
return { start, end, resourceId };
|
|
1030
|
+
}
|
|
1031
|
+
function computeResizeEnd(event, deltaMinutes, minDuration = 15) {
|
|
1032
|
+
const minEnd = event.start.getTime() + minDuration * 6e4;
|
|
1033
|
+
return new Date(Math.max(event.end.getTime() + deltaMinutes * 6e4, minEnd));
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
// src/components/dnd/ResizableEvent.tsx
|
|
566
1037
|
var ResizableEvent = ({
|
|
567
1038
|
event,
|
|
568
1039
|
hourHeight,
|
|
@@ -574,13 +1045,13 @@ var ResizableEvent = ({
|
|
|
574
1045
|
readonly
|
|
575
1046
|
}) => {
|
|
576
1047
|
const resizeLocked = readonly || isEventResizeDisabled(event);
|
|
577
|
-
const [isResizing, setIsResizing] =
|
|
578
|
-
const [resizeHeight, setResizeHeight] =
|
|
579
|
-
const containerRef =
|
|
580
|
-
const startYRef =
|
|
581
|
-
const startHeightRef =
|
|
582
|
-
const resizeHeightRef =
|
|
583
|
-
const handleResizeStart =
|
|
1048
|
+
const [isResizing, setIsResizing] = (0, import_react7.useState)(false);
|
|
1049
|
+
const [resizeHeight, setResizeHeight] = (0, import_react7.useState)(null);
|
|
1050
|
+
const containerRef = (0, import_react7.useRef)(null);
|
|
1051
|
+
const startYRef = (0, import_react7.useRef)(0);
|
|
1052
|
+
const startHeightRef = (0, import_react7.useRef)(0);
|
|
1053
|
+
const resizeHeightRef = (0, import_react7.useRef)(null);
|
|
1054
|
+
const handleResizeStart = (0, import_react7.useCallback)((e) => {
|
|
584
1055
|
e.preventDefault();
|
|
585
1056
|
e.stopPropagation();
|
|
586
1057
|
const clientY = "touches" in e ? e.touches[0].clientY : e.clientY;
|
|
@@ -604,14 +1075,8 @@ var ResizableEvent = ({
|
|
|
604
1075
|
setIsResizing(false);
|
|
605
1076
|
const finalHeight = resizeHeightRef.current;
|
|
606
1077
|
if (finalHeight !== null && containerRef.current && onResize) {
|
|
607
|
-
const
|
|
608
|
-
|
|
609
|
-
const minutesDiff = heightDiff / hourHeight * 60;
|
|
610
|
-
const newEnd = new Date(event.end);
|
|
611
|
-
newEnd.setMinutes(newEnd.getMinutes() + minutesDiff);
|
|
612
|
-
if (newEnd > event.start) {
|
|
613
|
-
onResize(event, newEnd);
|
|
614
|
-
}
|
|
1078
|
+
const minutesDiff = (finalHeight - startHeightRef.current) / hourHeight * 60;
|
|
1079
|
+
onResize(event, computeResizeEnd(event, minutesDiff, minDuration));
|
|
615
1080
|
}
|
|
616
1081
|
resizeHeightRef.current = null;
|
|
617
1082
|
setResizeHeight(null);
|
|
@@ -625,10 +1090,10 @@ var ResizableEvent = ({
|
|
|
625
1090
|
document.addEventListener("touchmove", handleMove, { passive: false });
|
|
626
1091
|
document.addEventListener("touchend", handleEnd);
|
|
627
1092
|
}, [event, hourHeight, minDuration, onResize]);
|
|
628
|
-
const handlePointerDown =
|
|
1093
|
+
const handlePointerDown = (0, import_react7.useCallback)((e) => {
|
|
629
1094
|
e.stopPropagation();
|
|
630
1095
|
}, []);
|
|
631
|
-
return /* @__PURE__ */
|
|
1096
|
+
return /* @__PURE__ */ import_react7.default.createElement(
|
|
632
1097
|
"div",
|
|
633
1098
|
{
|
|
634
1099
|
ref: containerRef,
|
|
@@ -639,7 +1104,7 @@ var ResizableEvent = ({
|
|
|
639
1104
|
}
|
|
640
1105
|
},
|
|
641
1106
|
children,
|
|
642
|
-
/* @__PURE__ */
|
|
1107
|
+
/* @__PURE__ */ import_react7.default.createElement(
|
|
643
1108
|
"div",
|
|
644
1109
|
{
|
|
645
1110
|
className: cn(
|
|
@@ -652,17 +1117,26 @@ var ResizableEvent = ({
|
|
|
652
1117
|
onMouseDown: resizeLocked ? void 0 : handleResizeStart,
|
|
653
1118
|
onTouchStart: resizeLocked ? void 0 : handleResizeStart
|
|
654
1119
|
},
|
|
655
|
-
/* @__PURE__ */
|
|
1120
|
+
/* @__PURE__ */ import_react7.default.createElement("div", { className: cn(
|
|
656
1121
|
"w-8 h-1 rounded-full transition-all",
|
|
657
1122
|
isResizing ? "bg-primary" : "bg-muted-foreground/30 group-hover:bg-primary/50"
|
|
658
1123
|
) })
|
|
659
1124
|
),
|
|
660
|
-
isResizing && /* @__PURE__ */
|
|
1125
|
+
isResizing && /* @__PURE__ */ import_react7.default.createElement("div", { className: "absolute inset-0 border-2 border-primary border-dashed rounded-md pointer-events-none bg-primary/5" })
|
|
661
1126
|
);
|
|
662
1127
|
};
|
|
663
1128
|
|
|
664
1129
|
// src/views/WeekView.tsx
|
|
665
|
-
var
|
|
1130
|
+
var HOUR_HEIGHT = 60;
|
|
1131
|
+
var HOURS = Array.from({ length: 24 }, (_, i) => i);
|
|
1132
|
+
var QUARTERS = [0, 15, 30, 45];
|
|
1133
|
+
var NO_SEGMENTS = [];
|
|
1134
|
+
var slotDate = (day, hour, minute) => {
|
|
1135
|
+
const date = new Date(day);
|
|
1136
|
+
date.setHours(hour, minute, 0, 0);
|
|
1137
|
+
return date;
|
|
1138
|
+
};
|
|
1139
|
+
var WeekViewImpl = ({
|
|
666
1140
|
currentDate,
|
|
667
1141
|
events,
|
|
668
1142
|
onEventClick,
|
|
@@ -672,151 +1146,110 @@ var WeekView = ({
|
|
|
672
1146
|
locale,
|
|
673
1147
|
readonly
|
|
674
1148
|
}) => {
|
|
675
|
-
const
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
const
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
1149
|
+
const weekDays = import_react8.default.useMemo(
|
|
1150
|
+
() => getWeekDays(currentDate, resolveWeekStartsOn(locale, 1)),
|
|
1151
|
+
[currentDate, locale]
|
|
1152
|
+
);
|
|
1153
|
+
const visibleRange = import_react8.default.useMemo(
|
|
1154
|
+
() => ({ start: weekDays[0], end: (0, import_date_fns9.addDays)(weekDays[weekDays.length - 1], 1) }),
|
|
1155
|
+
[weekDays]
|
|
1156
|
+
);
|
|
1157
|
+
const scrollContainerRef = import_react8.default.useRef(null);
|
|
1158
|
+
const [now, setNow] = import_react8.default.useState(() => /* @__PURE__ */ new Date());
|
|
1159
|
+
import_react8.default.useEffect(() => {
|
|
684
1160
|
const interval = setInterval(() => setNow(/* @__PURE__ */ new Date()), 6e4);
|
|
685
1161
|
return () => clearInterval(interval);
|
|
686
1162
|
}, []);
|
|
687
|
-
|
|
1163
|
+
import_react8.default.useEffect(() => {
|
|
688
1164
|
if (scrollContainerRef.current) {
|
|
689
|
-
const
|
|
690
|
-
|
|
691
|
-
const offsetHour = 4;
|
|
692
|
-
return (currentHour - offsetHour) * hourHeight;
|
|
693
|
-
};
|
|
694
|
-
scrollContainerRef.current.scrollTop = scrollToActualTime();
|
|
1165
|
+
const offsetHour = 4;
|
|
1166
|
+
scrollContainerRef.current.scrollTop = (toDisplay(/* @__PURE__ */ new Date(), timezone).getHours() - offsetHour) * HOUR_HEIGHT;
|
|
695
1167
|
}
|
|
696
|
-
}, []);
|
|
697
|
-
const
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
const
|
|
701
|
-
const
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
displayTime = dateFns.format(date, "HH:mm");
|
|
707
|
-
try {
|
|
708
|
-
acronym = new Intl.DateTimeFormat("en-US", { timeZoneName: "short" }).formatToParts(date).find((part) => part.type === "timeZoneName")?.value || "";
|
|
709
|
-
} catch (e) {
|
|
710
|
-
acronym = "LOC";
|
|
711
|
-
}
|
|
712
|
-
} else {
|
|
713
|
-
try {
|
|
714
|
-
const zDate = dateFnsTz.toZonedTime(date, tz);
|
|
715
|
-
displayTime = dateFns.format(zDate, "HH:mm");
|
|
716
|
-
acronym = new Intl.DateTimeFormat("en-US", { timeZone: tz, timeZoneName: "short" }).formatToParts(date).find((part) => part.type === "timeZoneName")?.value || "";
|
|
717
|
-
} catch (e) {
|
|
718
|
-
displayTime = dateFns.format(date, "HH:mm");
|
|
719
|
-
acronym = tz;
|
|
720
|
-
}
|
|
721
|
-
}
|
|
722
|
-
return /* @__PURE__ */ React15__namespace.default.createElement("div", { className: "flex flex-col items-center justify-center leading-tight" }, /* @__PURE__ */ React15__namespace.default.createElement("span", null, displayTime), /* @__PURE__ */ React15__namespace.default.createElement("span", { className: "text-[10px] opacity-75" }, "(", acronym, ")"));
|
|
723
|
-
};
|
|
724
|
-
const is24h = uses24HourClock(locale);
|
|
725
|
-
const timeFormat = is24h ? "H:mm" : "h a";
|
|
726
|
-
const eventTimeFormat = is24h ? "H:mm" : "h:mm a";
|
|
727
|
-
const nowFormat = is24h ? "H:mm" : "h:mm";
|
|
728
|
-
return /* @__PURE__ */ React15__namespace.default.createElement("div", { className: "flex flex-col h-full bg-background border-[0.5px] border-border/50 rounded-2xl overflow-hidden min-w-[800px] md:min-w-0 shadow-sm" }, /* @__PURE__ */ React15__namespace.default.createElement(
|
|
1168
|
+
}, [timezone]);
|
|
1169
|
+
const segmentsByDay = segmentsByDisplayDay(events, timezone, visibleRange);
|
|
1170
|
+
const today = displayToday(timezone, now);
|
|
1171
|
+
const zonedNow = toDisplay(now, timezone);
|
|
1172
|
+
const nowTop = minutesSinceDisplayMidnight(now, timezone) / 60 * HOUR_HEIGHT;
|
|
1173
|
+
const showsToday = weekDays.some((day) => (0, import_date_fns9.isSameDay)(day, today));
|
|
1174
|
+
const zone = resolveTimeZone(timezone);
|
|
1175
|
+
const zoneLabel = timeZoneAbbreviation(now, zone) || zone || "LOC";
|
|
1176
|
+
const formats = timeFormats(locale);
|
|
1177
|
+
return /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex flex-col h-full bg-background border-[0.5px] border-border/50 rounded-2xl overflow-hidden min-w-[800px] md:min-w-0 shadow-sm" }, /* @__PURE__ */ import_react8.default.createElement(
|
|
729
1178
|
"div",
|
|
730
1179
|
{
|
|
731
1180
|
ref: scrollContainerRef,
|
|
732
1181
|
className: "flex-1 overflow-y-auto scrollbar-hide relative bg-background scroll-smooth"
|
|
733
1182
|
},
|
|
734
|
-
/* @__PURE__ */
|
|
1183
|
+
/* @__PURE__ */ import_react8.default.createElement("div", { className: "flex border-b-[0.5px] border-border/50 bg-gradient-to-r from-muted/20 via-background to-muted/20 z-20 sticky top-0 backdrop-blur-sm" }, /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex-none p-3 text-center text-xs font-semibold text-muted-foreground w-16 flex items-center justify-center border-r-[0.5px] border-border/30 bg-muted/10" }, /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex flex-col items-center justify-center leading-tight" }, /* @__PURE__ */ import_react8.default.createElement("span", null, (0, import_date_fns9.format)(zonedNow, "HH:mm")), /* @__PURE__ */ import_react8.default.createElement("span", { className: "text-[10px] opacity-75" }, "(", zoneLabel, ")"))), /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex-1 grid grid-cols-7" }, weekDays.map((day, index) => /* @__PURE__ */ import_react8.default.createElement("div", { key: day.toISOString(), className: cn("py-3 px-2 text-center", index > 0 && "border-l-[0.5px] border-border/30") }, /* @__PURE__ */ import_react8.default.createElement("div", { className: "text-[10px] font-semibold text-muted-foreground uppercase tracking-wider mb-1.5" }, (0, import_date_fns9.format)(day, "EEE", { locale })), /* @__PURE__ */ import_react8.default.createElement("div", { className: cn(
|
|
735
1184
|
"w-9 h-9 flex items-center justify-center rounded-xl mx-auto text-sm font-semibold transition-all duration-200",
|
|
736
|
-
|
|
737
|
-
) },
|
|
738
|
-
/* @__PURE__ */
|
|
1185
|
+
(0, import_date_fns9.isSameDay)(day, today) ? "bg-primary text-primary-foreground shadow-lg shadow-primary/30 scale-110" : "text-foreground hover:bg-accent/80"
|
|
1186
|
+
) }, (0, import_date_fns9.format)(day, "d", { locale })))))),
|
|
1187
|
+
/* @__PURE__ */ import_react8.default.createElement(
|
|
739
1188
|
"div",
|
|
740
1189
|
{
|
|
741
1190
|
className: "flex min-w-full relative",
|
|
742
|
-
style: { height:
|
|
1191
|
+
style: { height: HOURS.length * HOUR_HEIGHT }
|
|
743
1192
|
},
|
|
744
|
-
/* @__PURE__ */
|
|
1193
|
+
/* @__PURE__ */ import_react8.default.createElement("div", { className: "flex-none w-16 border-r-[0.5px] border-border/30 relative bg-muted/5" }, HOURS.map((hour) => /* @__PURE__ */ import_react8.default.createElement(
|
|
745
1194
|
"div",
|
|
746
1195
|
{
|
|
747
1196
|
key: hour,
|
|
748
1197
|
className: "relative w-full text-[11px] text-muted-foreground/80 text-right pr-3 font-medium tabular-nums box-border",
|
|
749
|
-
style: { height:
|
|
1198
|
+
style: { height: HOUR_HEIGHT }
|
|
750
1199
|
},
|
|
751
|
-
/* @__PURE__ */
|
|
752
|
-
))
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
}
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
1200
|
+
/* @__PURE__ */ import_react8.default.createElement("span", { className: "block -translate-y-1/2" }, hour !== 0 && (0, import_date_fns9.format)(slotDate(currentDate, hour, 0), formats.hour, { locale }))
|
|
1201
|
+
)), showsToday && /* @__PURE__ */ import_react8.default.createElement(
|
|
1202
|
+
"div",
|
|
1203
|
+
{
|
|
1204
|
+
className: "absolute left-0 w-full pointer-events-none z-30 flex justify-end pr-2",
|
|
1205
|
+
style: { top: `${nowTop}px` }
|
|
1206
|
+
},
|
|
1207
|
+
/* @__PURE__ */ import_react8.default.createElement("span", { className: "text-[10px] font-bold text-primary-foreground bg-primary px-1.5 py-0.5 rounded-md shadow-md -translate-y-1/2 backdrop-blur-none" }, (0, import_date_fns9.format)(zonedNow, formats.compact, { locale }))
|
|
1208
|
+
)),
|
|
1209
|
+
/* @__PURE__ */ import_react8.default.createElement("div", { className: "flex-1 grid grid-cols-7 relative" }, weekDays.map((day, dayIndex) => {
|
|
1210
|
+
const dayKey2 = (0, import_date_fns9.format)(day, "yyyy-MM-dd");
|
|
1211
|
+
const positioned = layoutDayEvents(segmentsByDay.get(dayKey2) ?? NO_SEGMENTS);
|
|
1212
|
+
return /* @__PURE__ */ import_react8.default.createElement("div", { key: dayKey2, className: cn("relative h-full", dayIndex > 0 && "border-l-[0.5px] border-border/30") }, HOURS.map((hour) => /* @__PURE__ */ import_react8.default.createElement(
|
|
1213
|
+
"div",
|
|
1214
|
+
{
|
|
1215
|
+
key: hour,
|
|
1216
|
+
className: "w-full border-b-[0.5px] border-dashed border-border/20 box-border relative hover:bg-accent/5 transition-colors",
|
|
1217
|
+
style: { height: HOUR_HEIGHT }
|
|
1218
|
+
},
|
|
1219
|
+
QUARTERS.map((minute) => {
|
|
1220
|
+
const cellDate = slotDate(day, hour, minute);
|
|
1221
|
+
return /* @__PURE__ */ import_react8.default.createElement(
|
|
1222
|
+
DroppableCell,
|
|
1223
|
+
{
|
|
1224
|
+
key: minute,
|
|
1225
|
+
id: cellDate.toISOString(),
|
|
1226
|
+
date: cellDate,
|
|
1227
|
+
className: "w-full absolute left-0 right-0 z-0 transition-colors",
|
|
1228
|
+
style: {
|
|
1229
|
+
height: "25%",
|
|
1230
|
+
top: `${minute / 60 * 100}%`
|
|
781
1231
|
},
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
);
|
|
792
|
-
|
|
793
|
-
const
|
|
794
|
-
|
|
795
|
-
const s1 = getZonedDate(event.start).getTime();
|
|
796
|
-
const e1 = getZonedDate(event.end).getTime();
|
|
797
|
-
const s2 = getZonedDate(e.start).getTime();
|
|
798
|
-
const e2 = getZonedDate(e.end).getTime();
|
|
799
|
-
return s1 < e2 && e1 > s2;
|
|
800
|
-
});
|
|
801
|
-
const group = [event, ...overlappingEvents].sort(
|
|
802
|
-
(a, b) => getZonedDate(a.start).getTime() - getZonedDate(b.start).getTime() || (a.id > b.id ? 1 : -1)
|
|
803
|
-
// stable sort
|
|
804
|
-
);
|
|
805
|
-
const index = group.findIndex((e) => e.id === event.id);
|
|
806
|
-
const count = group.length;
|
|
807
|
-
const widthPercent = 100 / count;
|
|
808
|
-
const leftPercent = index * widthPercent;
|
|
809
|
-
const zonedEventStart = getZonedDate(event.start);
|
|
810
|
-
const zonedEventEnd = getZonedDate(event.end);
|
|
811
|
-
const startMinutes = zonedEventStart.getHours() * 60 + zonedEventStart.getMinutes();
|
|
812
|
-
const durationMinutes = dateFns.differenceInMinutes(zonedEventEnd, zonedEventStart);
|
|
813
|
-
const top = startMinutes / 60 * hourHeight;
|
|
814
|
-
const height = durationMinutes / 60 * hourHeight;
|
|
1232
|
+
onSlotClick: onTimeSlotClick
|
|
1233
|
+
}
|
|
1234
|
+
);
|
|
1235
|
+
})
|
|
1236
|
+
)), positioned.map(({ event, start, end, column, columns }) => {
|
|
1237
|
+
const widthPercent = 100 / columns;
|
|
1238
|
+
const leftPercent = column * widthPercent;
|
|
1239
|
+
const zonedEventStart = toDisplay(event.start, timezone);
|
|
1240
|
+
const zonedEventEnd = toDisplay(event.end, timezone);
|
|
1241
|
+
const startMinutes = start.getHours() * 60 + start.getMinutes();
|
|
1242
|
+
const durationMinutes = (0, import_date_fns9.differenceInMinutes)(end, start);
|
|
1243
|
+
const top = startMinutes / 60 * HOUR_HEIGHT;
|
|
1244
|
+
const height = durationMinutes / 60 * HOUR_HEIGHT;
|
|
815
1245
|
const isShortEvent = durationMinutes < 60;
|
|
816
|
-
|
|
1246
|
+
const isLastSegment = end.getTime() === zonedEventEnd.getTime();
|
|
1247
|
+
return /* @__PURE__ */ import_react8.default.createElement(
|
|
817
1248
|
DraggableEvent,
|
|
818
1249
|
{
|
|
819
|
-
key: `${event.id}-${
|
|
1250
|
+
key: `${event.id}-${dayKey2}`,
|
|
1251
|
+
dragId: `${event.id}@${dayKey2}`,
|
|
1252
|
+
grabOffsetMs: start.getTime() - zonedEventStart.getTime(),
|
|
820
1253
|
event,
|
|
821
1254
|
className: `absolute z-10 transition-all ${readonly ? "cursor-default" : ""}`,
|
|
822
1255
|
style: {
|
|
@@ -825,20 +1258,20 @@ var WeekView = ({
|
|
|
825
1258
|
left: `${leftPercent}%`,
|
|
826
1259
|
width: `${widthPercent}%`,
|
|
827
1260
|
// Add minimal spacing between overlapping events
|
|
828
|
-
paddingRight:
|
|
1261
|
+
paddingRight: columns > 1 ? "2px" : "0"
|
|
829
1262
|
}
|
|
830
1263
|
},
|
|
831
|
-
/* @__PURE__ */
|
|
1264
|
+
/* @__PURE__ */ import_react8.default.createElement(
|
|
832
1265
|
ResizableEvent,
|
|
833
1266
|
{
|
|
834
|
-
readonly,
|
|
1267
|
+
readonly: readonly || !isLastSegment,
|
|
835
1268
|
event,
|
|
836
|
-
hourHeight,
|
|
1269
|
+
hourHeight: HOUR_HEIGHT,
|
|
837
1270
|
onResize: onEventResize,
|
|
838
1271
|
className: "h-full",
|
|
839
1272
|
style: { height: "100%" }
|
|
840
1273
|
},
|
|
841
|
-
/* @__PURE__ */
|
|
1274
|
+
/* @__PURE__ */ import_react8.default.createElement(
|
|
842
1275
|
"div",
|
|
843
1276
|
{
|
|
844
1277
|
className: cn(
|
|
@@ -848,7 +1281,7 @@ var WeekView = ({
|
|
|
848
1281
|
!event.color && "border-primary/20 bg-primary/10",
|
|
849
1282
|
isShortEvent ? "px-1 flex items-center justify-center" : "p-2",
|
|
850
1283
|
// Add active border for overlapped events to distinguish them
|
|
851
|
-
|
|
1284
|
+
columns > 1 && "border-l-4 border-l-primary/50"
|
|
852
1285
|
),
|
|
853
1286
|
style: {
|
|
854
1287
|
height: "100%",
|
|
@@ -861,41 +1294,43 @@ var WeekView = ({
|
|
|
861
1294
|
e.stopPropagation();
|
|
862
1295
|
onEventClick?.(event);
|
|
863
1296
|
},
|
|
864
|
-
title:
|
|
1297
|
+
title: columns > 1 ? `${event.title} (${column + 1}/${columns})` : void 0
|
|
865
1298
|
},
|
|
866
|
-
/* @__PURE__ */
|
|
1299
|
+
/* @__PURE__ */ import_react8.default.createElement("div", { className: "flex flex-col h-full overflow-hidden w-full" }, /* @__PURE__ */ import_react8.default.createElement("div", { className: cn(
|
|
867
1300
|
"font-semibold truncate text-foreground/90 leading-tight",
|
|
868
1301
|
isShortEvent ? "text-xs text-center" : "text-xs"
|
|
869
|
-
) }, event.title), !isShortEvent && /* @__PURE__ */
|
|
1302
|
+
) }, event.title), !isShortEvent && /* @__PURE__ */ import_react8.default.createElement(import_react8.default.Fragment, null, /* @__PURE__ */ import_react8.default.createElement("div", { className: "text-[10px] text-muted-foreground truncate mt-0.5 font-medium leading-tight" }, (0, import_date_fns9.format)(zonedEventStart, formats.time, { locale }), " - ", (0, import_date_fns9.format)(zonedEventEnd, formats.time, { locale })), event.description && height > 50 && /* @__PURE__ */ import_react8.default.createElement("div", { className: "text-[10px] text-muted-foreground/80 truncate mt-1 leading-tight opacity-80" }, event.description)), columns > 1 && !isShortEvent && /* @__PURE__ */ import_react8.default.createElement("div", { className: "absolute top-1 right-1 bg-background/80 backdrop-blur-sm rounded-full w-4 h-4 flex items-center justify-center text-[9px] font-bold text-muted-foreground border border-border shadow-sm" }, columns))
|
|
870
1303
|
)
|
|
871
1304
|
)
|
|
872
1305
|
);
|
|
873
|
-
}),
|
|
1306
|
+
}), (0, import_date_fns9.isSameDay)(day, today) && /* @__PURE__ */ import_react8.default.createElement(
|
|
874
1307
|
"div",
|
|
875
1308
|
{
|
|
876
1309
|
className: "absolute left-0 right-0 z-20 pointer-events-none flex items-center",
|
|
877
|
-
style: {
|
|
878
|
-
top: `${(zonedNow.getHours() * 60 + zonedNow.getMinutes()) / 60 * hourHeight}px`
|
|
879
|
-
}
|
|
1310
|
+
style: { top: `${nowTop}px` }
|
|
880
1311
|
},
|
|
881
|
-
/* @__PURE__ */
|
|
882
|
-
/* @__PURE__ */
|
|
1312
|
+
/* @__PURE__ */ import_react8.default.createElement("div", { className: "h-[2px] w-full bg-gradient-to-r from-primary via-primary to-primary/50" }),
|
|
1313
|
+
/* @__PURE__ */ import_react8.default.createElement("div", { className: "absolute -left-1.5 w-3 h-3 bg-primary rounded-full shadow-lg shadow-primary/40 ring-2 ring-background animate-pulse" })
|
|
883
1314
|
));
|
|
884
1315
|
}))
|
|
885
|
-
),
|
|
886
|
-
/* @__PURE__ */ React15__namespace.default.createElement(
|
|
887
|
-
"div",
|
|
888
|
-
{
|
|
889
|
-
className: "absolute left-0 w-16 pointer-events-none z-30 flex justify-end pr-2",
|
|
890
|
-
style: {
|
|
891
|
-
top: `${(zonedNow.getHours() * 60 + zonedNow.getMinutes()) / 60 * hourHeight + 80}px`
|
|
892
|
-
}
|
|
893
|
-
},
|
|
894
|
-
/* @__PURE__ */ React15__namespace.default.createElement("span", { className: "text-[10px] font-bold text-primary-foreground bg-primary px-1.5 py-0.5 rounded-md shadow-md -translate-y-1/2 backdrop-blur-none" }, dateFns.format(zonedNow, nowFormat, { locale }))
|
|
895
1316
|
)
|
|
896
1317
|
));
|
|
897
1318
|
};
|
|
898
|
-
var
|
|
1319
|
+
var WeekView = import_react8.default.memo(WeekViewImpl);
|
|
1320
|
+
|
|
1321
|
+
// src/views/DayView.tsx
|
|
1322
|
+
var import_react9 = __toESM(require("react"));
|
|
1323
|
+
var import_date_fns10 = require("date-fns");
|
|
1324
|
+
var HOUR_HEIGHT2 = 80;
|
|
1325
|
+
var HOURS2 = Array.from({ length: 24 }, (_, i) => i);
|
|
1326
|
+
var QUARTERS2 = [0, 15, 30, 45];
|
|
1327
|
+
var NO_SEGMENTS2 = [];
|
|
1328
|
+
var slotDate2 = (day, hour, minute) => {
|
|
1329
|
+
const date = new Date(day);
|
|
1330
|
+
date.setHours(hour, minute, 0, 0);
|
|
1331
|
+
return date;
|
|
1332
|
+
};
|
|
1333
|
+
var DayViewImpl = ({
|
|
899
1334
|
currentDate,
|
|
900
1335
|
events,
|
|
901
1336
|
onEventClick,
|
|
@@ -905,114 +1340,84 @@ var DayView = ({
|
|
|
905
1340
|
locale,
|
|
906
1341
|
readonly
|
|
907
1342
|
}) => {
|
|
908
|
-
const
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
1343
|
+
const visibleRange = import_react9.default.useMemo(() => {
|
|
1344
|
+
const start = (0, import_date_fns10.startOfDay)(currentDate);
|
|
1345
|
+
return { start, end: (0, import_date_fns10.addDays)(start, 1) };
|
|
1346
|
+
}, [currentDate]);
|
|
1347
|
+
const scrollContainerRef = import_react9.default.useRef(null);
|
|
1348
|
+
const [now, setNow] = import_react9.default.useState(() => /* @__PURE__ */ new Date());
|
|
1349
|
+
import_react9.default.useEffect(() => {
|
|
913
1350
|
const interval = setInterval(() => setNow(/* @__PURE__ */ new Date()), 6e4);
|
|
914
1351
|
return () => clearInterval(interval);
|
|
915
1352
|
}, []);
|
|
916
|
-
|
|
1353
|
+
import_react9.default.useEffect(() => {
|
|
917
1354
|
if (scrollContainerRef.current) {
|
|
918
|
-
const
|
|
919
|
-
|
|
920
|
-
const offsetHour = 3;
|
|
921
|
-
return (currentHour - offsetHour) * hourHeight;
|
|
922
|
-
};
|
|
923
|
-
scrollContainerRef.current.scrollTop = scrollToActualTime();
|
|
1355
|
+
const offsetHour = 3;
|
|
1356
|
+
scrollContainerRef.current.scrollTop = (toDisplay(/* @__PURE__ */ new Date(), timezone).getHours() - offsetHour) * HOUR_HEIGHT2;
|
|
924
1357
|
}
|
|
925
|
-
}, []);
|
|
926
|
-
const
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
const zonedNow =
|
|
930
|
-
const
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
});
|
|
934
|
-
const is24h = uses24HourClock(locale);
|
|
935
|
-
const timeFormat = is24h ? "H:mm" : "h a";
|
|
936
|
-
const eventTimeFormat = is24h ? "H:mm" : "h:mm a";
|
|
937
|
-
const nowFormat = is24h ? "H:mm" : "h:mm a";
|
|
938
|
-
return /* @__PURE__ */ React15__namespace.default.createElement("div", { className: "flex flex-col h-full bg-background border-[0.5px] border-border/50 rounded-2xl overflow-hidden shadow-sm" }, /* @__PURE__ */ React15__namespace.default.createElement("div", { className: "px-6 py-4 border-b-[0.5px] border-border/50 bg-gradient-to-r from-muted/20 via-background to-muted/20 text-center shrink-0" }, /* @__PURE__ */ React15__namespace.default.createElement("div", { className: "flex items-center justify-center gap-3" }, /* @__PURE__ */ React15__namespace.default.createElement("h2", { className: "text-xl font-semibold capitalize text-foreground" }, dateFns.format(currentDate, "EEEE, MMMM d, yyyy", { locale })), dateFns.isToday(currentDate) && /* @__PURE__ */ React15__namespace.default.createElement("span", { className: "text-xs font-semibold bg-primary text-primary-foreground px-3 py-1 rounded-full shadow-md shadow-primary/20" }, "Today"))), /* @__PURE__ */ React15__namespace.default.createElement("div", { ref: scrollContainerRef, className: "flex-1 overflow-y-auto relative" }, /* @__PURE__ */ React15__namespace.default.createElement("div", { className: "flex relative", style: { height: hours.length * hourHeight } }, /* @__PURE__ */ React15__namespace.default.createElement("div", { className: "w-20 bg-muted/5 border-r-[0.5px] border-border/30 relative" }, hours.map((hour) => /* @__PURE__ */ React15__namespace.default.createElement(
|
|
1358
|
+
}, [timezone]);
|
|
1359
|
+
const dayKey2 = (0, import_date_fns10.format)(currentDate, "yyyy-MM-dd");
|
|
1360
|
+
const positioned = layoutDayEvents(segmentsByDisplayDay(events, timezone, visibleRange).get(dayKey2) ?? NO_SEGMENTS2);
|
|
1361
|
+
const isToday2 = (0, import_date_fns10.isSameDay)(currentDate, displayToday(timezone, now));
|
|
1362
|
+
const zonedNow = toDisplay(now, timezone);
|
|
1363
|
+
const nowTop = minutesSinceDisplayMidnight(now, timezone) / 60 * HOUR_HEIGHT2;
|
|
1364
|
+
const formats = timeFormats(locale);
|
|
1365
|
+
return /* @__PURE__ */ import_react9.default.createElement("div", { className: "flex flex-col h-full bg-background border-[0.5px] border-border/50 rounded-2xl overflow-hidden shadow-sm" }, /* @__PURE__ */ import_react9.default.createElement("div", { className: "px-6 py-4 border-b-[0.5px] border-border/50 bg-gradient-to-r from-muted/20 via-background to-muted/20 text-center shrink-0" }, /* @__PURE__ */ import_react9.default.createElement("div", { className: "flex items-center justify-center gap-3" }, /* @__PURE__ */ import_react9.default.createElement("h2", { className: "text-xl font-semibold capitalize text-foreground" }, (0, import_date_fns10.format)(currentDate, "EEEE, MMMM d, yyyy", { locale })), isToday2 && /* @__PURE__ */ import_react9.default.createElement("span", { className: "text-xs font-semibold bg-primary text-primary-foreground px-3 py-1 rounded-full shadow-md shadow-primary/20" }, "Today"))), /* @__PURE__ */ import_react9.default.createElement("div", { ref: scrollContainerRef, className: "flex-1 overflow-y-auto relative" }, /* @__PURE__ */ import_react9.default.createElement("div", { className: "flex relative", style: { height: HOURS2.length * HOUR_HEIGHT2 } }, /* @__PURE__ */ import_react9.default.createElement("div", { className: "w-20 bg-muted/5 border-r-[0.5px] border-border/30 relative" }, HOURS2.map((hour) => /* @__PURE__ */ import_react9.default.createElement(
|
|
939
1366
|
"div",
|
|
940
1367
|
{
|
|
941
1368
|
key: hour,
|
|
942
1369
|
className: "relative w-full",
|
|
943
|
-
style: { height:
|
|
1370
|
+
style: { height: HOUR_HEIGHT2 }
|
|
944
1371
|
},
|
|
945
|
-
hour !== 0 && /* @__PURE__ */
|
|
946
|
-
)),
|
|
1372
|
+
hour !== 0 && /* @__PURE__ */ import_react9.default.createElement("span", { className: "absolute w-full text-center -top-3 left-1/2 -translate-x-1/2 text-[11px] text-muted-foreground/80 font-medium tabular-nums bg-background px-1.5 py-0.5 rounded-md" }, (0, import_date_fns10.format)(slotDate2(currentDate, hour, 0), formats.hour, { locale }))
|
|
1373
|
+
)), isToday2 && /* @__PURE__ */ import_react9.default.createElement(
|
|
947
1374
|
"div",
|
|
948
1375
|
{
|
|
949
1376
|
className: "absolute left-0 w-full pointer-events-none z-30 flex justify-end pr-2",
|
|
950
|
-
style: {
|
|
951
|
-
top: `${(zonedNow.getHours() * 60 + zonedNow.getMinutes()) / 60 * hourHeight}px`
|
|
952
|
-
}
|
|
1377
|
+
style: { top: `${nowTop}px` }
|
|
953
1378
|
},
|
|
954
|
-
/* @__PURE__ */
|
|
955
|
-
)), /* @__PURE__ */
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
style: {
|
|
975
|
-
height: "25%",
|
|
976
|
-
top: `${minute / 60 * 100}%`
|
|
977
|
-
}
|
|
1379
|
+
/* @__PURE__ */ import_react9.default.createElement("span", { className: "text-[10px] font-bold text-white bg-primary px-2 py-1 rounded-lg shadow-md shadow-primary/30 -translate-y-1/2" }, (0, import_date_fns10.format)(zonedNow, formats.time, { locale }))
|
|
1380
|
+
)), /* @__PURE__ */ import_react9.default.createElement("div", { className: "flex-1 relative" }, HOURS2.map((hour) => /* @__PURE__ */ import_react9.default.createElement(
|
|
1381
|
+
"div",
|
|
1382
|
+
{
|
|
1383
|
+
key: hour,
|
|
1384
|
+
className: "border-b-[0.5px] border-dashed border-border/20 box-border relative hover:bg-accent/5 transition-colors",
|
|
1385
|
+
style: { height: HOUR_HEIGHT2 }
|
|
1386
|
+
},
|
|
1387
|
+
QUARTERS2.map((minute) => {
|
|
1388
|
+
const cellDate = slotDate2(currentDate, hour, minute);
|
|
1389
|
+
return /* @__PURE__ */ import_react9.default.createElement(
|
|
1390
|
+
DroppableCell,
|
|
1391
|
+
{
|
|
1392
|
+
key: minute,
|
|
1393
|
+
id: cellDate.toISOString(),
|
|
1394
|
+
date: cellDate,
|
|
1395
|
+
className: "w-full absolute left-0 right-0 z-0 transition-colors",
|
|
1396
|
+
style: {
|
|
1397
|
+
height: "25%",
|
|
1398
|
+
top: `${minute / 60 * 100}%`
|
|
978
1399
|
},
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
);
|
|
989
|
-
|
|
990
|
-
const
|
|
991
|
-
|
|
992
|
-
const s1 = getZonedDate(event.start).getTime();
|
|
993
|
-
const e1 = getZonedDate(event.end).getTime();
|
|
994
|
-
const s2 = getZonedDate(e.start).getTime();
|
|
995
|
-
const e2 = getZonedDate(e.end).getTime();
|
|
996
|
-
return s1 < e2 && e1 > s2;
|
|
997
|
-
});
|
|
998
|
-
const group = [event, ...overlappingEvents].sort(
|
|
999
|
-
(a, b) => getZonedDate(a.start).getTime() - getZonedDate(b.start).getTime() || (a.id > b.id ? 1 : -1)
|
|
1000
|
-
);
|
|
1001
|
-
const index = group.findIndex((e) => e.id === event.id);
|
|
1002
|
-
const count = group.length;
|
|
1003
|
-
const widthPercent = 100 / count;
|
|
1004
|
-
const leftPercent = index * widthPercent;
|
|
1005
|
-
const zonedStart = getZonedDate(event.start);
|
|
1006
|
-
const zonedEnd = getZonedDate(event.end);
|
|
1007
|
-
const startMinutes = zonedStart.getHours() * 60 + zonedStart.getMinutes();
|
|
1008
|
-
const durationMinutes = dateFns.differenceInMinutes(zonedEnd, zonedStart);
|
|
1009
|
-
const top = startMinutes / 60 * hourHeight;
|
|
1010
|
-
const height = durationMinutes / 60 * hourHeight;
|
|
1400
|
+
onSlotClick: onTimeSlotClick
|
|
1401
|
+
}
|
|
1402
|
+
);
|
|
1403
|
+
})
|
|
1404
|
+
)), positioned.map(({ event, start, end, column, columns }) => {
|
|
1405
|
+
const widthPercent = 100 / columns;
|
|
1406
|
+
const leftPercent = column * widthPercent;
|
|
1407
|
+
const zonedStart = toDisplay(event.start, timezone);
|
|
1408
|
+
const zonedEnd = toDisplay(event.end, timezone);
|
|
1409
|
+
const startMinutes = start.getHours() * 60 + start.getMinutes();
|
|
1410
|
+
const durationMinutes = (0, import_date_fns10.differenceInMinutes)(end, start);
|
|
1411
|
+
const top = startMinutes / 60 * HOUR_HEIGHT2;
|
|
1412
|
+
const height = durationMinutes / 60 * HOUR_HEIGHT2;
|
|
1011
1413
|
const isShortEvent = durationMinutes < 45;
|
|
1012
|
-
|
|
1414
|
+
const isLastSegment = end.getTime() === zonedEnd.getTime();
|
|
1415
|
+
return /* @__PURE__ */ import_react9.default.createElement(
|
|
1013
1416
|
DraggableEvent,
|
|
1014
1417
|
{
|
|
1015
|
-
key: `${event.id}-${
|
|
1418
|
+
key: `${event.id}-${dayKey2}`,
|
|
1419
|
+
dragId: `${event.id}@${dayKey2}`,
|
|
1420
|
+
grabOffsetMs: start.getTime() - zonedStart.getTime(),
|
|
1016
1421
|
event,
|
|
1017
1422
|
className: `absolute z-10 transition-all ${readonly ? "cursor-default" : ""}`,
|
|
1018
1423
|
style: {
|
|
@@ -1020,20 +1425,20 @@ var DayView = ({
|
|
|
1020
1425
|
height: `${Math.max(height, 28)}px`,
|
|
1021
1426
|
left: `calc(${leftPercent}% + 4px)`,
|
|
1022
1427
|
width: `calc(${widthPercent}% - 8px)`,
|
|
1023
|
-
paddingRight:
|
|
1428
|
+
paddingRight: columns > 1 ? "2px" : "0"
|
|
1024
1429
|
}
|
|
1025
1430
|
},
|
|
1026
|
-
/* @__PURE__ */
|
|
1431
|
+
/* @__PURE__ */ import_react9.default.createElement(
|
|
1027
1432
|
ResizableEvent,
|
|
1028
1433
|
{
|
|
1029
|
-
readonly,
|
|
1434
|
+
readonly: readonly || !isLastSegment,
|
|
1030
1435
|
event,
|
|
1031
|
-
hourHeight,
|
|
1436
|
+
hourHeight: HOUR_HEIGHT2,
|
|
1032
1437
|
onResize: onEventResize,
|
|
1033
1438
|
className: "h-full",
|
|
1034
1439
|
style: { height: "100%" }
|
|
1035
1440
|
},
|
|
1036
|
-
/* @__PURE__ */
|
|
1441
|
+
/* @__PURE__ */ import_react9.default.createElement(
|
|
1037
1442
|
"div",
|
|
1038
1443
|
{
|
|
1039
1444
|
className: cn(
|
|
@@ -1042,61 +1447,72 @@ var DayView = ({
|
|
|
1042
1447
|
readonly || isEventDragDisabled(event) ? "cursor-default" : "cursor-grab active:cursor-grabbing",
|
|
1043
1448
|
!event.color && "bg-primary/10 border-primary/20",
|
|
1044
1449
|
isShortEvent ? "px-2 flex items-center" : "px-3 py-2",
|
|
1045
|
-
|
|
1450
|
+
columns > 1 && "border-l-4"
|
|
1046
1451
|
),
|
|
1047
1452
|
style: {
|
|
1048
1453
|
backgroundColor: event.color ? `${event.color}15` : void 0,
|
|
1049
1454
|
borderColor: event.color ? `${event.color}30` : void 0,
|
|
1050
1455
|
borderLeftColor: event.color || "var(--primary)",
|
|
1051
|
-
borderLeftWidth:
|
|
1456
|
+
borderLeftWidth: columns > 1 ? "4px" : "3px"
|
|
1052
1457
|
},
|
|
1053
1458
|
onClick: (e) => {
|
|
1054
1459
|
e.stopPropagation();
|
|
1055
1460
|
onEventClick?.(event);
|
|
1056
1461
|
},
|
|
1057
|
-
title:
|
|
1462
|
+
title: columns > 1 ? `${event.title} (${column + 1}/${columns})` : void 0
|
|
1058
1463
|
},
|
|
1059
|
-
/* @__PURE__ */
|
|
1464
|
+
/* @__PURE__ */ import_react9.default.createElement("div", { className: "flex flex-col h-full overflow-hidden w-full" }, /* @__PURE__ */ import_react9.default.createElement("div", { className: cn(
|
|
1060
1465
|
"font-semibold truncate leading-tight",
|
|
1061
1466
|
isShortEvent ? "text-xs" : "text-sm",
|
|
1062
1467
|
event.color ? "text-foreground" : "text-foreground/90"
|
|
1063
|
-
) }, event.title), !isShortEvent && /* @__PURE__ */
|
|
1468
|
+
) }, event.title), !isShortEvent && /* @__PURE__ */ import_react9.default.createElement(import_react9.default.Fragment, null, /* @__PURE__ */ import_react9.default.createElement("div", { className: "text-xs text-muted-foreground mt-0.5 font-medium" }, (0, import_date_fns10.format)(zonedStart, formats.time, { locale }), " - ", (0, import_date_fns10.format)(zonedEnd, formats.time, { locale })), event.description && height > 60 && /* @__PURE__ */ import_react9.default.createElement("div", { className: "text-xs text-muted-foreground/80 mt-1 line-clamp-2" }, event.description)), columns > 1 && !isShortEvent && /* @__PURE__ */ import_react9.default.createElement("div", { className: "absolute top-1.5 right-1.5 bg-background/90 backdrop-blur-sm rounded-full w-5 h-5 flex items-center justify-center text-[10px] font-bold text-muted-foreground border border-border shadow-sm" }, columns))
|
|
1064
1469
|
)
|
|
1065
1470
|
)
|
|
1066
1471
|
);
|
|
1067
|
-
}),
|
|
1472
|
+
}), isToday2 && /* @__PURE__ */ import_react9.default.createElement(
|
|
1068
1473
|
"div",
|
|
1069
1474
|
{
|
|
1070
1475
|
className: "absolute left-0 right-0 z-20 pointer-events-none flex items-center",
|
|
1071
|
-
style: {
|
|
1072
|
-
top: `${(zonedNow.getHours() * 60 + zonedNow.getMinutes()) / 60 * hourHeight}px`
|
|
1073
|
-
}
|
|
1476
|
+
style: { top: `${nowTop}px` }
|
|
1074
1477
|
},
|
|
1075
|
-
/* @__PURE__ */
|
|
1076
|
-
/* @__PURE__ */
|
|
1478
|
+
/* @__PURE__ */ import_react9.default.createElement("div", { className: "h-[2px] w-full bg-gradient-to-r from-primary via-primary to-primary/50" }),
|
|
1479
|
+
/* @__PURE__ */ import_react9.default.createElement("div", { className: "absolute -left-1.5 w-3 h-3 bg-primary rounded-full shadow-lg shadow-primary/40 ring-2 ring-background animate-pulse" })
|
|
1077
1480
|
)))));
|
|
1078
1481
|
};
|
|
1079
|
-
var
|
|
1482
|
+
var DayView = import_react9.default.memo(DayViewImpl);
|
|
1483
|
+
|
|
1484
|
+
// src/views/AgendaView.tsx
|
|
1485
|
+
var import_react11 = __toESM(require("react"));
|
|
1486
|
+
var import_date_fns11 = require("date-fns");
|
|
1487
|
+
|
|
1488
|
+
// src/components/EmptyState.tsx
|
|
1489
|
+
var import_react10 = __toESM(require("react"));
|
|
1490
|
+
var import_lucide_react4 = require("lucide-react");
|
|
1491
|
+
var AgendaEmptyState = ({ onCreateEvent, translations }) => /* @__PURE__ */ import_react10.default.createElement("div", { className: "flex flex-col items-center justify-center h-full min-h-[400px] py-12" }, /* @__PURE__ */ import_react10.default.createElement("div", { className: "relative mb-8" }, /* @__PURE__ */ import_react10.default.createElement("div", { className: "p-8 bg-gradient-to-br from-green-50 to-blue-50 dark:from-green-900/10 dark:to-blue-900/10 rounded-3xl border border-border/30" }, /* @__PURE__ */ import_react10.default.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ import_react10.default.createElement("div", { className: "w-12 h-12 rounded-2xl bg-green-100 dark:bg-green-900/30 flex items-center justify-center" }, /* @__PURE__ */ import_react10.default.createElement("svg", { className: "w-6 h-6 text-green-600 dark:text-green-400", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2 }, /* @__PURE__ */ import_react10.default.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M5 13l4 4L19 7" }))), /* @__PURE__ */ import_react10.default.createElement("div", { className: "text-left" }, /* @__PURE__ */ import_react10.default.createElement("div", { className: "font-medium text-foreground" }, translations?.allCaughtUp || "All caught up!"), /* @__PURE__ */ import_react10.default.createElement("div", { className: "text-sm text-muted-foreground" }, translations?.noEventsScheduled || "No events scheduled"))))), /* @__PURE__ */ import_react10.default.createElement("div", { className: "text-center max-w-sm" }, /* @__PURE__ */ import_react10.default.createElement("h3", { className: "text-lg font-semibold text-foreground mb-2" }, translations?.noUpcoming || "Your schedule is clear"), /* @__PURE__ */ import_react10.default.createElement("p", { className: "text-sm text-muted-foreground mb-6" }, translations?.noUpcomingHint || "No upcoming events to show. Create a new event to start planning."), onCreateEvent && /* @__PURE__ */ import_react10.default.createElement(
|
|
1080
1492
|
"button",
|
|
1081
1493
|
{
|
|
1082
1494
|
onClick: onCreateEvent,
|
|
1083
1495
|
className: "inline-flex items-center gap-2 px-5 py-2.5 bg-primary text-primary-foreground rounded-xl font-medium text-sm shadow-lg shadow-primary/20 hover:shadow-xl hover:shadow-primary/30 hover:scale-105 active:scale-95 transition-all duration-200"
|
|
1084
1496
|
},
|
|
1085
|
-
/* @__PURE__ */
|
|
1497
|
+
/* @__PURE__ */ import_react10.default.createElement(import_lucide_react4.Plus, { className: "w-4 h-4" }),
|
|
1086
1498
|
translations?.createEvent || "Create Event"
|
|
1087
1499
|
)));
|
|
1500
|
+
|
|
1501
|
+
// src/views/AgendaView.tsx
|
|
1502
|
+
var import_framer_motion = require("framer-motion");
|
|
1503
|
+
var import_lucide_react5 = require("lucide-react");
|
|
1088
1504
|
var formatDuration = (start, end) => {
|
|
1089
|
-
const minutes =
|
|
1505
|
+
const minutes = (0, import_date_fns11.differenceInMinutes)(end, start);
|
|
1090
1506
|
if (minutes < 60) return `${minutes}m`;
|
|
1091
1507
|
const hours = Math.floor(minutes / 60);
|
|
1092
1508
|
const remainingMinutes = minutes % 60;
|
|
1093
1509
|
if (remainingMinutes === 0) return `${hours}h`;
|
|
1094
1510
|
return `${hours}h ${remainingMinutes}m`;
|
|
1095
1511
|
};
|
|
1096
|
-
var getDateLabel = (date, locale, translations) => {
|
|
1097
|
-
if (
|
|
1098
|
-
if (
|
|
1099
|
-
return
|
|
1512
|
+
var getDateLabel = (date, today, locale, translations) => {
|
|
1513
|
+
if ((0, import_date_fns11.isSameDay)(date, today)) return translations?.today || "Today";
|
|
1514
|
+
if ((0, import_date_fns11.isSameDay)(date, (0, import_date_fns11.addDays)(today, 1))) return translations?.tomorrow || "Tomorrow";
|
|
1515
|
+
return (0, import_date_fns11.format)(date, "EEEE", { locale });
|
|
1100
1516
|
};
|
|
1101
1517
|
var AgendaView = ({
|
|
1102
1518
|
currentDate,
|
|
@@ -1104,24 +1520,24 @@ var AgendaView = ({
|
|
|
1104
1520
|
onEventClick,
|
|
1105
1521
|
onCreateEvent,
|
|
1106
1522
|
locale,
|
|
1107
|
-
translations
|
|
1523
|
+
translations,
|
|
1524
|
+
timezone
|
|
1108
1525
|
}) => {
|
|
1109
1526
|
const is24h = uses24HourClock(locale);
|
|
1110
|
-
const
|
|
1111
|
-
const
|
|
1112
|
-
const groupedEvents =
|
|
1113
|
-
const
|
|
1527
|
+
const { time: timePattern, compact: compactTimePattern } = timeFormats(locale);
|
|
1528
|
+
const today = displayToday(timezone);
|
|
1529
|
+
const groupedEvents = (0, import_react11.useMemo)(() => {
|
|
1530
|
+
const byDay = eventsByStartDay(events, timezone);
|
|
1114
1531
|
const groups = [];
|
|
1115
|
-
const sortedEvents = [...events].sort((a, b) => a.start.getTime() - b.start.getTime());
|
|
1116
1532
|
for (let i = 0; i < 30; i++) {
|
|
1117
|
-
const day =
|
|
1118
|
-
const dayEvents =
|
|
1119
|
-
if (dayEvents
|
|
1120
|
-
groups.push({ date: day, events: dayEvents });
|
|
1533
|
+
const day = (0, import_date_fns11.addDays)((0, import_date_fns11.startOfDay)(currentDate), i);
|
|
1534
|
+
const dayEvents = byDay.get((0, import_date_fns11.format)(day, "yyyy-MM-dd"));
|
|
1535
|
+
if (dayEvents?.length) {
|
|
1536
|
+
groups.push({ date: day, events: [...dayEvents].sort((a, b) => a.start.getTime() - b.start.getTime()) });
|
|
1121
1537
|
}
|
|
1122
1538
|
}
|
|
1123
1539
|
return groups;
|
|
1124
|
-
}, [currentDate, events]);
|
|
1540
|
+
}, [currentDate, events, timezone]);
|
|
1125
1541
|
const container = {
|
|
1126
1542
|
hidden: { opacity: 0 },
|
|
1127
1543
|
show: {
|
|
@@ -1135,30 +1551,30 @@ var AgendaView = ({
|
|
|
1135
1551
|
hidden: { opacity: 0, x: -20 },
|
|
1136
1552
|
show: { opacity: 1, x: 0 }
|
|
1137
1553
|
};
|
|
1138
|
-
return /* @__PURE__ */
|
|
1139
|
-
|
|
1554
|
+
return /* @__PURE__ */ import_react11.default.createElement("div", { className: "flex flex-col h-full bg-background overflow-y-auto" }, groupedEvents.length === 0 ? /* @__PURE__ */ import_react11.default.createElement(AgendaEmptyState, { onCreateEvent, translations }) : /* @__PURE__ */ import_react11.default.createElement(
|
|
1555
|
+
import_framer_motion.motion.div,
|
|
1140
1556
|
{
|
|
1141
1557
|
className: "max-w-3xl mx-auto w-full pb-10 px-4 md:px-6",
|
|
1142
1558
|
variants: container,
|
|
1143
1559
|
initial: "hidden",
|
|
1144
1560
|
animate: "show"
|
|
1145
1561
|
},
|
|
1146
|
-
groupedEvents.map((group
|
|
1147
|
-
|
|
1562
|
+
groupedEvents.map((group) => /* @__PURE__ */ import_react11.default.createElement(
|
|
1563
|
+
import_framer_motion.motion.div,
|
|
1148
1564
|
{
|
|
1149
1565
|
key: group.date.toISOString(),
|
|
1150
1566
|
className: "relative",
|
|
1151
1567
|
variants: item
|
|
1152
1568
|
},
|
|
1153
|
-
/* @__PURE__ */
|
|
1569
|
+
/* @__PURE__ */ import_react11.default.createElement("div", { className: "sticky top-0 bg-background/95 backdrop-blur-md py-4 z-10 border-b border-border/50" }, /* @__PURE__ */ import_react11.default.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ import_react11.default.createElement("div", { className: cn(
|
|
1154
1570
|
"flex flex-col items-center justify-center w-16 h-16 rounded-2xl transition-all",
|
|
1155
|
-
|
|
1156
|
-
) }, /* @__PURE__ */
|
|
1571
|
+
(0, import_date_fns11.isSameDay)(group.date, today) ? "bg-primary text-primary-foreground shadow-lg shadow-primary/30" : "bg-muted/50 text-foreground"
|
|
1572
|
+
) }, /* @__PURE__ */ import_react11.default.createElement("span", { className: "text-2xl font-bold leading-none" }, (0, import_date_fns11.format)(group.date, "d")), /* @__PURE__ */ import_react11.default.createElement("span", { className: "text-xs font-medium uppercase tracking-wide opacity-80" }, (0, import_date_fns11.format)(group.date, "MMM", { locale }))), /* @__PURE__ */ import_react11.default.createElement("div", { className: "flex flex-col" }, /* @__PURE__ */ import_react11.default.createElement("span", { className: cn(
|
|
1157
1573
|
"text-lg font-semibold",
|
|
1158
|
-
|
|
1159
|
-
) }, getDateLabel(group.date, locale, translations)), /* @__PURE__ */
|
|
1160
|
-
/* @__PURE__ */
|
|
1161
|
-
|
|
1574
|
+
(0, import_date_fns11.isSameDay)(group.date, today) && "text-primary"
|
|
1575
|
+
) }, getDateLabel(group.date, today, locale, translations)), /* @__PURE__ */ import_react11.default.createElement("span", { className: "text-sm text-muted-foreground" }, group.events.length, " ", group.events.length !== 1 ? translations?.eventPlural || "events" : translations?.eventSingular || "event")))),
|
|
1576
|
+
/* @__PURE__ */ import_react11.default.createElement("div", { className: "py-4 space-y-3" }, group.events.map((event) => /* @__PURE__ */ import_react11.default.createElement(
|
|
1577
|
+
import_framer_motion.motion.div,
|
|
1162
1578
|
{
|
|
1163
1579
|
key: event.id,
|
|
1164
1580
|
onClick: () => onEventClick?.(event),
|
|
@@ -1171,44 +1587,49 @@ var AgendaView = ({
|
|
|
1171
1587
|
whileHover: { scale: 1.01, y: -2 },
|
|
1172
1588
|
transition: { duration: 0.2 }
|
|
1173
1589
|
},
|
|
1174
|
-
/* @__PURE__ */
|
|
1590
|
+
/* @__PURE__ */ import_react11.default.createElement(
|
|
1175
1591
|
"div",
|
|
1176
1592
|
{
|
|
1177
1593
|
className: "absolute left-0 top-3 bottom-3 w-1 rounded-full",
|
|
1178
1594
|
style: { backgroundColor: event.color || "var(--primary)" }
|
|
1179
1595
|
}
|
|
1180
1596
|
),
|
|
1181
|
-
/* @__PURE__ */
|
|
1182
|
-
/* @__PURE__ */
|
|
1597
|
+
/* @__PURE__ */ import_react11.default.createElement("div", { className: "flex flex-col items-center min-w-[70px] pl-2" }, event.allDay ? /* @__PURE__ */ import_react11.default.createElement("div", { className: "flex flex-col items-center" }, /* @__PURE__ */ import_react11.default.createElement("span", { className: "text-xs font-semibold text-muted-foreground bg-muted/80 px-2.5 py-1 rounded-full" }, translations?.allDay || "All Day")) : /* @__PURE__ */ import_react11.default.createElement("div", { className: "flex flex-col items-center" }, /* @__PURE__ */ import_react11.default.createElement("span", { className: "text-base font-semibold text-foreground" }, (0, import_date_fns11.format)(toDisplay(event.start, timezone), compactTimePattern, { locale })), !is24h && /* @__PURE__ */ import_react11.default.createElement("span", { className: "text-xs text-muted-foreground uppercase" }, (0, import_date_fns11.format)(toDisplay(event.start, timezone), "a")), /* @__PURE__ */ import_react11.default.createElement("div", { className: "w-px h-3 bg-border my-1" }), /* @__PURE__ */ import_react11.default.createElement("span", { className: "text-xs text-muted-foreground/70 font-medium" }, formatDuration(event.start, event.end)))),
|
|
1598
|
+
/* @__PURE__ */ import_react11.default.createElement("div", { className: "flex-1 min-w-0 space-y-2" }, /* @__PURE__ */ import_react11.default.createElement("div", { className: "flex items-start justify-between gap-2" }, /* @__PURE__ */ import_react11.default.createElement("h4", { className: "text-base font-semibold text-foreground group-hover:text-primary transition-colors line-clamp-1" }, event.title), /* @__PURE__ */ import_react11.default.createElement(
|
|
1183
1599
|
"div",
|
|
1184
1600
|
{
|
|
1185
1601
|
className: "w-3 h-3 rounded-full shrink-0 mt-1.5",
|
|
1186
1602
|
style: { backgroundColor: event.color || "var(--primary)" }
|
|
1187
1603
|
}
|
|
1188
|
-
)), event.description && /* @__PURE__ */
|
|
1189
|
-
/* @__PURE__ */
|
|
1604
|
+
)), event.description && /* @__PURE__ */ import_react11.default.createElement("p", { className: "text-sm text-muted-foreground line-clamp-2 leading-relaxed" }, event.description), /* @__PURE__ */ import_react11.default.createElement("div", { className: "flex flex-wrap items-center gap-3 pt-1" }, !event.allDay && /* @__PURE__ */ import_react11.default.createElement("div", { className: "flex items-center gap-1.5 text-xs text-muted-foreground" }, /* @__PURE__ */ import_react11.default.createElement(import_lucide_react5.Clock, { className: "w-3.5 h-3.5" }), /* @__PURE__ */ import_react11.default.createElement("span", null, (0, import_date_fns11.format)(toDisplay(event.start, timezone), timePattern, { locale }), " - ", (0, import_date_fns11.format)(toDisplay(event.end, timezone), timePattern, { locale }))), event.guests && event.guests.length > 0 && /* @__PURE__ */ import_react11.default.createElement("div", { className: "flex items-center gap-1.5 text-xs text-muted-foreground" }, /* @__PURE__ */ import_react11.default.createElement(import_lucide_react5.Users, { className: "w-3.5 h-3.5" }), /* @__PURE__ */ import_react11.default.createElement("span", null, event.guests.length, " ", event.guests.length !== 1 ? translations?.guestsCount || "guests" : translations?.guestCount || "guest")), event.attachments && event.attachments.length > 0 && /* @__PURE__ */ import_react11.default.createElement("div", { className: "flex items-center gap-1.5 text-xs text-muted-foreground" }, /* @__PURE__ */ import_react11.default.createElement(import_lucide_react5.Paperclip, { className: "w-3.5 h-3.5" }), /* @__PURE__ */ import_react11.default.createElement("span", null, event.attachments.length)), event.reminders && event.reminders.length > 0 && /* @__PURE__ */ import_react11.default.createElement("div", { className: "flex items-center gap-1.5 text-xs text-muted-foreground" }, /* @__PURE__ */ import_react11.default.createElement(import_lucide_react5.Bell, { className: "w-3.5 h-3.5" }), /* @__PURE__ */ import_react11.default.createElement("span", null, event.reminders.length)))),
|
|
1605
|
+
/* @__PURE__ */ import_react11.default.createElement("div", { className: "absolute right-4 top-1/2 -translate-y-1/2 opacity-0 group-hover:opacity-100 transition-opacity" }, /* @__PURE__ */ import_react11.default.createElement("svg", { className: "w-5 h-5 text-muted-foreground", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2" }, /* @__PURE__ */ import_react11.default.createElement("path", { d: "M9 18l6-6-6-6" })))
|
|
1190
1606
|
)))
|
|
1191
1607
|
))
|
|
1192
1608
|
));
|
|
1193
1609
|
};
|
|
1610
|
+
|
|
1611
|
+
// src/views/ResourceView.tsx
|
|
1612
|
+
var import_react12 = __toESM(require("react"));
|
|
1613
|
+
var import_date_fns12 = require("date-fns");
|
|
1194
1614
|
var ResourceView = ({
|
|
1195
1615
|
currentDate,
|
|
1196
1616
|
events,
|
|
1197
1617
|
resources,
|
|
1198
1618
|
onEventClick,
|
|
1199
1619
|
onTimeSlotClick,
|
|
1200
|
-
locale
|
|
1620
|
+
locale,
|
|
1621
|
+
timezone
|
|
1201
1622
|
}) => {
|
|
1202
|
-
const containerRef =
|
|
1623
|
+
const containerRef = (0, import_react12.useRef)(null);
|
|
1203
1624
|
const hours = Array.from({ length: 24 }, (_, i) => i);
|
|
1204
1625
|
const hourWidth = 100;
|
|
1205
|
-
const timeFormat =
|
|
1626
|
+
const timeFormat = timeFormats(locale).hour;
|
|
1206
1627
|
const getEventStyle = (event) => {
|
|
1207
|
-
const start =
|
|
1208
|
-
const end =
|
|
1209
|
-
const dayStart =
|
|
1210
|
-
const startMinutes =
|
|
1211
|
-
const durationMinutes =
|
|
1628
|
+
const start = toDisplay(event.start, timezone);
|
|
1629
|
+
const end = toDisplay(event.end, timezone);
|
|
1630
|
+
const dayStart = (0, import_date_fns12.startOfDay)(currentDate);
|
|
1631
|
+
const startMinutes = (0, import_date_fns12.differenceInMinutes)(start, dayStart);
|
|
1632
|
+
const durationMinutes = (0, import_date_fns12.differenceInMinutes)(end, start);
|
|
1212
1633
|
const left = startMinutes / 60 * hourWidth;
|
|
1213
1634
|
const width = durationMinutes / 60 * hourWidth;
|
|
1214
1635
|
return {
|
|
@@ -1217,19 +1638,19 @@ var ResourceView = ({
|
|
|
1217
1638
|
// Min width for visibility
|
|
1218
1639
|
};
|
|
1219
1640
|
};
|
|
1220
|
-
return /* @__PURE__ */
|
|
1641
|
+
return /* @__PURE__ */ import_react12.default.createElement("div", { className: "flex flex-col h-full bg-background overflow-hidden" }, /* @__PURE__ */ import_react12.default.createElement("div", { className: "flex border-b border-border bg-muted/20" }, /* @__PURE__ */ import_react12.default.createElement("div", { className: "w-48 shrink-0 border-r border-border p-4 font-semibold text-sm bg-background sticky left-0 z-20" }, "Resources"), /* @__PURE__ */ import_react12.default.createElement("div", { className: "flex overflow-hidden" }, /* @__PURE__ */ import_react12.default.createElement("div", { className: "flex relative", style: { width: hours.length * hourWidth } }, hours.map((hour) => /* @__PURE__ */ import_react12.default.createElement(
|
|
1221
1642
|
"div",
|
|
1222
1643
|
{
|
|
1223
1644
|
key: hour,
|
|
1224
1645
|
className: "border-r border-border/50 text-xs text-muted-foreground p-2 font-medium shrink-0",
|
|
1225
1646
|
style: { width: hourWidth }
|
|
1226
1647
|
},
|
|
1227
|
-
|
|
1228
|
-
))))), /* @__PURE__ */
|
|
1648
|
+
(0, import_date_fns12.format)((/* @__PURE__ */ new Date()).setHours(hour, 0, 0, 0), timeFormat, { locale })
|
|
1649
|
+
))))), /* @__PURE__ */ import_react12.default.createElement("div", { className: "flex-1 overflow-auto relative", ref: containerRef }, /* @__PURE__ */ import_react12.default.createElement("div", { className: "min-w-fit" }, resources.map((resource) => {
|
|
1229
1650
|
const resourceEvents = events.filter(
|
|
1230
|
-
(e) => e.resourceId === resource.id &&
|
|
1651
|
+
(e) => e.resourceId === resource.id && isSameDisplayDay(e.start, currentDate, timezone)
|
|
1231
1652
|
);
|
|
1232
|
-
return /* @__PURE__ */
|
|
1653
|
+
return /* @__PURE__ */ import_react12.default.createElement("div", { key: resource.id, className: "flex border-b border-border min-h-[100px]" }, /* @__PURE__ */ import_react12.default.createElement("div", { className: "w-48 shrink-0 border-r border-border p-4 bg-background sticky left-0 z-10 flex items-center gap-3" }, resource.avatar ? /* @__PURE__ */ import_react12.default.createElement("img", { src: resource.avatar, alt: resource.label, className: "w-8 h-8 rounded-full object-cover" }) : /* @__PURE__ */ import_react12.default.createElement("div", { className: "w-8 h-8 rounded-full bg-primary/10 flex items-center justify-center text-xs font-bold text-primary" }, resource.label.substring(0, 2).toUpperCase()), /* @__PURE__ */ import_react12.default.createElement("div", { className: "flex flex-col" }, /* @__PURE__ */ import_react12.default.createElement("span", { className: "text-sm font-medium" }, resource.label), /* @__PURE__ */ import_react12.default.createElement("span", { className: "text-xs text-muted-foreground" }, "ID: ", resource.id))), /* @__PURE__ */ import_react12.default.createElement("div", { className: "relative flex", style: { width: hours.length * hourWidth } }, hours.map((hour) => /* @__PURE__ */ import_react12.default.createElement(
|
|
1233
1654
|
"div",
|
|
1234
1655
|
{
|
|
1235
1656
|
key: hour,
|
|
@@ -1237,24 +1658,22 @@ var ResourceView = ({
|
|
|
1237
1658
|
style: { width: hourWidth }
|
|
1238
1659
|
},
|
|
1239
1660
|
[0, 15, 30, 45].map((minute) => {
|
|
1240
|
-
const
|
|
1241
|
-
|
|
1242
|
-
const slotId = `${resource.id}-${
|
|
1243
|
-
return /* @__PURE__ */
|
|
1661
|
+
const slotDate3 = new Date(currentDate);
|
|
1662
|
+
slotDate3.setHours(hour, minute, 0, 0);
|
|
1663
|
+
const slotId = `${resource.id}-${slotDate3.toISOString()}`;
|
|
1664
|
+
return /* @__PURE__ */ import_react12.default.createElement(
|
|
1244
1665
|
DroppableCell,
|
|
1245
1666
|
{
|
|
1246
1667
|
key: minute,
|
|
1247
1668
|
id: slotId,
|
|
1248
|
-
date:
|
|
1669
|
+
date: slotDate3,
|
|
1249
1670
|
resourceId: resource.id,
|
|
1250
1671
|
className: "h-full flex-1 border-r border-border/10 last:border-border/30 hover:bg-accent/10 transition-colors",
|
|
1251
|
-
|
|
1252
|
-
onTimeSlotClick?.(slotDate, resource.id);
|
|
1253
|
-
}
|
|
1672
|
+
onSlotClick: onTimeSlotClick
|
|
1254
1673
|
}
|
|
1255
1674
|
);
|
|
1256
1675
|
})
|
|
1257
|
-
)), resourceEvents.map((event) => /* @__PURE__ */
|
|
1676
|
+
)), resourceEvents.map((event) => /* @__PURE__ */ import_react12.default.createElement(
|
|
1258
1677
|
DraggableEvent,
|
|
1259
1678
|
{
|
|
1260
1679
|
key: event.id,
|
|
@@ -1271,10 +1690,17 @@ var ResourceView = ({
|
|
|
1271
1690
|
color: "#fff"
|
|
1272
1691
|
}
|
|
1273
1692
|
},
|
|
1274
|
-
/* @__PURE__ */
|
|
1693
|
+
/* @__PURE__ */ import_react12.default.createElement("div", { className: "truncate" }, event.title)
|
|
1275
1694
|
))));
|
|
1276
1695
|
}))));
|
|
1277
1696
|
};
|
|
1697
|
+
|
|
1698
|
+
// src/components/EventModal.tsx
|
|
1699
|
+
var import_react14 = __toESM(require("react"));
|
|
1700
|
+
|
|
1701
|
+
// src/components/ui/Modal.tsx
|
|
1702
|
+
var import_react13 = __toESM(require("react"));
|
|
1703
|
+
var import_lucide_react6 = require("lucide-react");
|
|
1278
1704
|
var Modal = ({
|
|
1279
1705
|
isOpen,
|
|
1280
1706
|
onClose,
|
|
@@ -1283,8 +1709,8 @@ var Modal = ({
|
|
|
1283
1709
|
className,
|
|
1284
1710
|
hideHeader = false
|
|
1285
1711
|
}) => {
|
|
1286
|
-
const overlayRef =
|
|
1287
|
-
|
|
1712
|
+
const overlayRef = (0, import_react13.useRef)(null);
|
|
1713
|
+
(0, import_react13.useEffect)(() => {
|
|
1288
1714
|
const handleEscape = (e) => {
|
|
1289
1715
|
if (e.key === "Escape") {
|
|
1290
1716
|
onClose();
|
|
@@ -1298,14 +1724,14 @@ var Modal = ({
|
|
|
1298
1724
|
};
|
|
1299
1725
|
}, [isOpen, onClose]);
|
|
1300
1726
|
if (!isOpen) return null;
|
|
1301
|
-
return /* @__PURE__ */
|
|
1727
|
+
return /* @__PURE__ */ import_react13.default.createElement("div", { className: "absolute inset-0 z-50 flex items-center justify-center p-4 bg-black/40 backdrop-blur-md animate-in fade-in duration-300" }, /* @__PURE__ */ import_react13.default.createElement(
|
|
1302
1728
|
"div",
|
|
1303
1729
|
{
|
|
1304
1730
|
ref: overlayRef,
|
|
1305
1731
|
className: "absolute inset-0",
|
|
1306
1732
|
onClick: onClose
|
|
1307
1733
|
}
|
|
1308
|
-
), /* @__PURE__ */
|
|
1734
|
+
), /* @__PURE__ */ import_react13.default.createElement(
|
|
1309
1735
|
"div",
|
|
1310
1736
|
{
|
|
1311
1737
|
className: cn(
|
|
@@ -1313,7 +1739,7 @@ var Modal = ({
|
|
|
1313
1739
|
className
|
|
1314
1740
|
)
|
|
1315
1741
|
},
|
|
1316
|
-
!hideHeader && /* @__PURE__ */
|
|
1742
|
+
!hideHeader && /* @__PURE__ */ import_react13.default.createElement("div", { className: "flex items-center justify-between px-6 py-4 border-b border-border/50 shrink-0 bg-gradient-to-r from-muted/20 to-background" }, /* @__PURE__ */ import_react13.default.createElement("h3", { className: "text-lg font-semibold text-foreground" }, title), /* @__PURE__ */ import_react13.default.createElement(
|
|
1317
1743
|
Button,
|
|
1318
1744
|
{
|
|
1319
1745
|
variant: "ghost",
|
|
@@ -1321,12 +1747,17 @@ var Modal = ({
|
|
|
1321
1747
|
onClick: onClose,
|
|
1322
1748
|
className: "h-9 w-9 p-0 rounded-xl hover:bg-accent/80 transition-all duration-200"
|
|
1323
1749
|
},
|
|
1324
|
-
/* @__PURE__ */
|
|
1325
|
-
/* @__PURE__ */
|
|
1750
|
+
/* @__PURE__ */ import_react13.default.createElement(import_lucide_react6.X, { className: "h-4 w-4" }),
|
|
1751
|
+
/* @__PURE__ */ import_react13.default.createElement("span", { className: "sr-only" }, "Close")
|
|
1326
1752
|
)),
|
|
1327
|
-
/* @__PURE__ */
|
|
1753
|
+
/* @__PURE__ */ import_react13.default.createElement("div", { className: cn("overflow-y-auto flex-1", !hideHeader && "p-6") }, children)
|
|
1328
1754
|
));
|
|
1329
1755
|
};
|
|
1756
|
+
|
|
1757
|
+
// src/components/EventModal.tsx
|
|
1758
|
+
var import_date_fns13 = require("date-fns");
|
|
1759
|
+
var import_framer_motion2 = require("framer-motion");
|
|
1760
|
+
var import_lucide_react7 = require("lucide-react");
|
|
1330
1761
|
var REMINDER_OPTIONS = [
|
|
1331
1762
|
{ value: 0, label: "At time of event" },
|
|
1332
1763
|
{ value: 5, label: "5 minutes before" },
|
|
@@ -1368,13 +1799,10 @@ var EventModal = ({
|
|
|
1368
1799
|
initialDate,
|
|
1369
1800
|
onSave,
|
|
1370
1801
|
onDelete,
|
|
1371
|
-
calendars
|
|
1372
|
-
eventTypes,
|
|
1373
|
-
translations
|
|
1802
|
+
calendars
|
|
1374
1803
|
}) => {
|
|
1375
|
-
const [mode, setMode] =
|
|
1376
|
-
const [
|
|
1377
|
-
const [formData, setFormData] = React15.useState({
|
|
1804
|
+
const [mode, setMode] = (0, import_react14.useState)("create");
|
|
1805
|
+
const [formData, setFormData] = (0, import_react14.useState)({
|
|
1378
1806
|
title: "",
|
|
1379
1807
|
description: "",
|
|
1380
1808
|
location: "",
|
|
@@ -1388,10 +1816,10 @@ var EventModal = ({
|
|
|
1388
1816
|
attachments: [],
|
|
1389
1817
|
reminders: [{ id: "1", type: "notification", time: 30, label: "30 minutes before" }]
|
|
1390
1818
|
});
|
|
1391
|
-
const [isCalendarDropdownOpen, setIsCalendarDropdownOpen] =
|
|
1392
|
-
const [isColorPickerOpen, setIsColorPickerOpen] =
|
|
1393
|
-
const [isReminderDropdownOpen, setIsReminderDropdownOpen] =
|
|
1394
|
-
const [isGuestsDropdownOpen, setIsGuestsDropdownOpen] =
|
|
1819
|
+
const [isCalendarDropdownOpen, setIsCalendarDropdownOpen] = (0, import_react14.useState)(false);
|
|
1820
|
+
const [isColorPickerOpen, setIsColorPickerOpen] = (0, import_react14.useState)(false);
|
|
1821
|
+
const [isReminderDropdownOpen, setIsReminderDropdownOpen] = (0, import_react14.useState)(false);
|
|
1822
|
+
const [isGuestsDropdownOpen, setIsGuestsDropdownOpen] = (0, import_react14.useState)(false);
|
|
1395
1823
|
const fakeGuests = [
|
|
1396
1824
|
"alice@example.com",
|
|
1397
1825
|
"bob@example.com",
|
|
@@ -1399,9 +1827,8 @@ var EventModal = ({
|
|
|
1399
1827
|
"diana@example.com",
|
|
1400
1828
|
"evan@example.com"
|
|
1401
1829
|
];
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
React15.useEffect(() => {
|
|
1830
|
+
const [selectedGuests, setSelectedGuests] = (0, import_react14.useState)([]);
|
|
1831
|
+
(0, import_react14.useEffect)(() => {
|
|
1405
1832
|
if (isOpen) {
|
|
1406
1833
|
if (event) {
|
|
1407
1834
|
setMode("view");
|
|
@@ -1431,7 +1858,6 @@ var EventModal = ({
|
|
|
1431
1858
|
reminders: [{ id: "1", type: "notification", time: 30, label: "30 minutes before" }]
|
|
1432
1859
|
});
|
|
1433
1860
|
setSelectedGuests([]);
|
|
1434
|
-
setActiveTab("details");
|
|
1435
1861
|
}
|
|
1436
1862
|
}
|
|
1437
1863
|
}, [isOpen, event, initialDate, calendars]);
|
|
@@ -1466,7 +1892,7 @@ var EventModal = ({
|
|
|
1466
1892
|
};
|
|
1467
1893
|
const formatDateForInput = (date) => {
|
|
1468
1894
|
if (!date) return "";
|
|
1469
|
-
return
|
|
1895
|
+
return (0, import_date_fns13.format)(date, "yyyy-MM-dd'T'HH:mm");
|
|
1470
1896
|
};
|
|
1471
1897
|
const handleDateChange = (field, value) => {
|
|
1472
1898
|
const date = new Date(value);
|
|
@@ -1516,14 +1942,14 @@ var EventModal = ({
|
|
|
1516
1942
|
};
|
|
1517
1943
|
const getDurationText = () => {
|
|
1518
1944
|
if (!formData.start || !formData.end) return "";
|
|
1519
|
-
const mins =
|
|
1945
|
+
const mins = (0, import_date_fns13.differenceInMinutes)(formData.end, formData.start);
|
|
1520
1946
|
if (mins < 60) return `${mins} min`;
|
|
1521
1947
|
const hours = Math.floor(mins / 60);
|
|
1522
1948
|
const remainingMins = mins % 60;
|
|
1523
1949
|
if (remainingMins === 0) return `${hours} hr`;
|
|
1524
1950
|
return `${hours} hr ${remainingMins} min`;
|
|
1525
1951
|
};
|
|
1526
|
-
const renderViewMode = () => /* @__PURE__ */
|
|
1952
|
+
const renderViewMode = () => /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex flex-col bg-background overflow-hidden w-full max-h-[90vh]" }, /* @__PURE__ */ import_react14.default.createElement(
|
|
1527
1953
|
"div",
|
|
1528
1954
|
{
|
|
1529
1955
|
className: "relative px-6 pt-6 pb-8",
|
|
@@ -1531,65 +1957,65 @@ var EventModal = ({
|
|
|
1531
1957
|
background: `linear-gradient(135deg, ${event?.color || "#3b82f6"}15 0%, transparent 100%)`
|
|
1532
1958
|
}
|
|
1533
1959
|
},
|
|
1534
|
-
/* @__PURE__ */
|
|
1960
|
+
/* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center justify-between mb-6" }, /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react14.default.createElement(
|
|
1535
1961
|
"div",
|
|
1536
1962
|
{
|
|
1537
1963
|
className: "w-3 h-3 rounded-full",
|
|
1538
1964
|
style: { backgroundColor: event?.color || "#3b82f6" }
|
|
1539
1965
|
}
|
|
1540
|
-
), /* @__PURE__ */
|
|
1966
|
+
), /* @__PURE__ */ import_react14.default.createElement("span", { className: "text-xs font-medium text-muted-foreground uppercase tracking-wider" }, calendars?.find((c) => c.id === event?.calendarId)?.label || "Event")), /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center gap-1" }, /* @__PURE__ */ import_react14.default.createElement(
|
|
1541
1967
|
"button",
|
|
1542
1968
|
{
|
|
1543
1969
|
onClick: () => setMode("edit"),
|
|
1544
1970
|
className: "p-2 hover:bg-background/80 rounded-lg transition-all text-muted-foreground hover:text-foreground",
|
|
1545
1971
|
title: "Edit"
|
|
1546
1972
|
},
|
|
1547
|
-
/* @__PURE__ */
|
|
1548
|
-
), /* @__PURE__ */
|
|
1973
|
+
/* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.Edit2, { className: "w-4 h-4" })
|
|
1974
|
+
), /* @__PURE__ */ import_react14.default.createElement(
|
|
1549
1975
|
"button",
|
|
1550
1976
|
{
|
|
1551
1977
|
onClick: handleDelete,
|
|
1552
1978
|
className: "p-2 hover:bg-destructive/10 rounded-lg transition-all text-muted-foreground hover:text-destructive",
|
|
1553
1979
|
title: "Delete"
|
|
1554
1980
|
},
|
|
1555
|
-
/* @__PURE__ */
|
|
1556
|
-
), /* @__PURE__ */
|
|
1981
|
+
/* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.Trash2, { className: "w-4 h-4" })
|
|
1982
|
+
), /* @__PURE__ */ import_react14.default.createElement(
|
|
1557
1983
|
"button",
|
|
1558
1984
|
{
|
|
1559
1985
|
onClick: onClose,
|
|
1560
1986
|
className: "p-2 hover:bg-background/80 rounded-lg transition-all text-muted-foreground hover:text-foreground",
|
|
1561
1987
|
title: "Close"
|
|
1562
1988
|
},
|
|
1563
|
-
/* @__PURE__ */
|
|
1989
|
+
/* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.X, { className: "w-4 h-4" })
|
|
1564
1990
|
))),
|
|
1565
|
-
/* @__PURE__ */
|
|
1566
|
-
/* @__PURE__ */
|
|
1567
|
-
), /* @__PURE__ */
|
|
1568
|
-
|
|
1991
|
+
/* @__PURE__ */ import_react14.default.createElement("h1", { className: "text-2xl font-bold text-foreground mb-3 leading-tight" }, event?.title || "(No title)"),
|
|
1992
|
+
/* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center gap-3 text-sm" }, /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center gap-2 px-3 py-1.5 bg-background/60 backdrop-blur-sm rounded-lg border border-border/30" }, /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.Calendar, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ import_react14.default.createElement("span", { className: "font-medium" }, event?.start && (0, import_date_fns13.format)(new Date(event.start), "EEE, MMM d"))), /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center gap-2 px-3 py-1.5 bg-background/60 backdrop-blur-sm rounded-lg border border-border/30" }, /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.Clock, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ import_react14.default.createElement("span", { className: "font-medium" }, event?.start && (0, import_date_fns13.format)(new Date(event.start), "h:mm a"), " \u2013 ", event?.end && (0, import_date_fns13.format)(new Date(event.end), "h:mm a"))))
|
|
1993
|
+
), /* @__PURE__ */ import_react14.default.createElement("div", { className: "px-6 pb-6 space-y-4 overflow-y-auto flex-1" }, event?.location && /* @__PURE__ */ import_react14.default.createElement(
|
|
1994
|
+
import_framer_motion2.motion.div,
|
|
1569
1995
|
{
|
|
1570
1996
|
initial: { opacity: 0, y: 10 },
|
|
1571
1997
|
animate: { opacity: 1, y: 0 },
|
|
1572
1998
|
className: "flex items-start gap-3 p-4 rounded-2xl bg-muted/30 border border-border/30 group hover:bg-muted/50 transition-all cursor-pointer"
|
|
1573
1999
|
},
|
|
1574
|
-
/* @__PURE__ */
|
|
1575
|
-
/* @__PURE__ */
|
|
1576
|
-
/* @__PURE__ */
|
|
1577
|
-
), event?.guests && event.guests.length > 0 && /* @__PURE__ */
|
|
1578
|
-
|
|
2000
|
+
/* @__PURE__ */ import_react14.default.createElement("div", { className: "p-2 bg-primary/10 rounded-xl" }, /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.MapPin, { className: "w-5 h-5 text-primary" })),
|
|
2001
|
+
/* @__PURE__ */ import_react14.default.createElement("div", { className: "flex-1" }, /* @__PURE__ */ import_react14.default.createElement("p", { className: "text-sm font-medium text-foreground" }, event.location), /* @__PURE__ */ import_react14.default.createElement("p", { className: "text-xs text-muted-foreground mt-0.5" }, "Click to open in maps")),
|
|
2002
|
+
/* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.ExternalLink, { className: "w-4 h-4 text-muted-foreground opacity-0 group-hover:opacity-100 transition-opacity" })
|
|
2003
|
+
), event?.guests && event.guests.length > 0 && /* @__PURE__ */ import_react14.default.createElement(
|
|
2004
|
+
import_framer_motion2.motion.div,
|
|
1579
2005
|
{
|
|
1580
2006
|
initial: { opacity: 0, y: 10 },
|
|
1581
2007
|
animate: { opacity: 1, y: 0 },
|
|
1582
2008
|
transition: { delay: 0.05 },
|
|
1583
2009
|
className: "space-y-3"
|
|
1584
2010
|
},
|
|
1585
|
-
/* @__PURE__ */
|
|
1586
|
-
/* @__PURE__ */
|
|
2011
|
+
/* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.Users, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ import_react14.default.createElement("span", { className: "text-sm font-medium text-foreground" }, event.guests.length, " ", event.guests.length > 1 ? "Guests" : "Guest"))),
|
|
2012
|
+
/* @__PURE__ */ import_react14.default.createElement("div", { className: "flex flex-wrap gap-2" }, event.guests.map((email, index) => /* @__PURE__ */ import_react14.default.createElement(
|
|
1587
2013
|
"div",
|
|
1588
2014
|
{
|
|
1589
2015
|
key: index,
|
|
1590
2016
|
className: "flex items-center gap-2 px-3 py-2 rounded-xl bg-muted/30 border border-border/30 hover:bg-muted/50 transition-all cursor-pointer group"
|
|
1591
2017
|
},
|
|
1592
|
-
/* @__PURE__ */
|
|
2018
|
+
/* @__PURE__ */ import_react14.default.createElement(
|
|
1593
2019
|
"div",
|
|
1594
2020
|
{
|
|
1595
2021
|
className: "w-8 h-8 rounded-full flex items-center justify-center text-sm font-semibold text-white",
|
|
@@ -1597,18 +2023,18 @@ var EventModal = ({
|
|
|
1597
2023
|
},
|
|
1598
2024
|
email[0].toUpperCase()
|
|
1599
2025
|
),
|
|
1600
|
-
/* @__PURE__ */
|
|
2026
|
+
/* @__PURE__ */ import_react14.default.createElement("div", { className: "flex-1 min-w-0" }, /* @__PURE__ */ import_react14.default.createElement("p", { className: "text-sm font-medium text-foreground" }, email.split("@")[0]), /* @__PURE__ */ import_react14.default.createElement("p", { className: "text-xs text-muted-foreground truncate" }, email))
|
|
1601
2027
|
)))
|
|
1602
|
-
), event?.reminders && event.reminders.length > 0 && /* @__PURE__ */
|
|
1603
|
-
|
|
2028
|
+
), event?.reminders && event.reminders.length > 0 && /* @__PURE__ */ import_react14.default.createElement(
|
|
2029
|
+
import_framer_motion2.motion.div,
|
|
1604
2030
|
{
|
|
1605
2031
|
initial: { opacity: 0, y: 10 },
|
|
1606
2032
|
animate: { opacity: 1, y: 0 },
|
|
1607
2033
|
transition: { delay: 0.1 },
|
|
1608
2034
|
className: "flex items-center gap-3"
|
|
1609
2035
|
},
|
|
1610
|
-
/* @__PURE__ */
|
|
1611
|
-
/* @__PURE__ */
|
|
2036
|
+
/* @__PURE__ */ import_react14.default.createElement("div", { className: "p-2 bg-amber-500/10 rounded-xl" }, /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.Bell, { className: "w-4 h-4 text-amber-500" })),
|
|
2037
|
+
/* @__PURE__ */ import_react14.default.createElement("div", { className: "flex flex-wrap gap-2" }, event.reminders.map((reminder) => /* @__PURE__ */ import_react14.default.createElement(
|
|
1612
2038
|
"span",
|
|
1613
2039
|
{
|
|
1614
2040
|
key: reminder.id,
|
|
@@ -1616,45 +2042,45 @@ var EventModal = ({
|
|
|
1616
2042
|
},
|
|
1617
2043
|
reminder.label || `${reminder.time} min before`
|
|
1618
2044
|
)))
|
|
1619
|
-
), event?.description && /* @__PURE__ */
|
|
1620
|
-
|
|
2045
|
+
), event?.description && /* @__PURE__ */ import_react14.default.createElement(
|
|
2046
|
+
import_framer_motion2.motion.div,
|
|
1621
2047
|
{
|
|
1622
2048
|
initial: { opacity: 0, y: 10 },
|
|
1623
2049
|
animate: { opacity: 1, y: 0 },
|
|
1624
2050
|
transition: { delay: 0.15 },
|
|
1625
2051
|
className: "space-y-2"
|
|
1626
2052
|
},
|
|
1627
|
-
/* @__PURE__ */
|
|
1628
|
-
/* @__PURE__ */
|
|
1629
|
-
), event?.attachments && event.attachments.length > 0 && /* @__PURE__ */
|
|
1630
|
-
|
|
2053
|
+
/* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.AlignLeft, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ import_react14.default.createElement("span", { className: "text-sm font-medium text-foreground" }, "Notes")),
|
|
2054
|
+
/* @__PURE__ */ import_react14.default.createElement("div", { className: "text-sm text-foreground/80 whitespace-pre-wrap leading-relaxed pl-6 p-3 rounded-xl bg-muted/20 border border-border/30" }, event.description)
|
|
2055
|
+
), event?.attachments && event.attachments.length > 0 && /* @__PURE__ */ import_react14.default.createElement(
|
|
2056
|
+
import_framer_motion2.motion.div,
|
|
1631
2057
|
{
|
|
1632
2058
|
initial: { opacity: 0, y: 10 },
|
|
1633
2059
|
animate: { opacity: 1, y: 0 },
|
|
1634
2060
|
transition: { delay: 0.2 },
|
|
1635
2061
|
className: "space-y-2"
|
|
1636
2062
|
},
|
|
1637
|
-
/* @__PURE__ */
|
|
1638
|
-
/* @__PURE__ */
|
|
2063
|
+
/* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.Paperclip, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ import_react14.default.createElement("span", { className: "text-sm font-medium text-foreground" }, "Attachments")),
|
|
2064
|
+
/* @__PURE__ */ import_react14.default.createElement("div", { className: "grid gap-2" }, event.attachments.map((att) => /* @__PURE__ */ import_react14.default.createElement(
|
|
1639
2065
|
"div",
|
|
1640
2066
|
{
|
|
1641
2067
|
key: att.id,
|
|
1642
2068
|
onClick: () => handleDownload(att),
|
|
1643
2069
|
className: "flex items-center gap-3 p-3 rounded-xl border border-border/30 bg-muted/20 hover:bg-muted/40 transition-all cursor-pointer group"
|
|
1644
2070
|
},
|
|
1645
|
-
/* @__PURE__ */
|
|
1646
|
-
/* @__PURE__ */
|
|
1647
|
-
/* @__PURE__ */
|
|
2071
|
+
/* @__PURE__ */ import_react14.default.createElement("div", { className: "p-2 bg-primary/10 rounded-lg" }, /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.File, { className: "w-4 h-4 text-primary" })),
|
|
2072
|
+
/* @__PURE__ */ import_react14.default.createElement("div", { className: "flex-1 min-w-0" }, /* @__PURE__ */ import_react14.default.createElement("p", { className: "text-sm font-medium text-foreground truncate" }, att.name), /* @__PURE__ */ import_react14.default.createElement("p", { className: "text-xs text-muted-foreground" }, att.size)),
|
|
2073
|
+
/* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.Download, { className: "w-4 h-4 text-muted-foreground opacity-0 group-hover:opacity-100 transition-opacity" })
|
|
1648
2074
|
)))
|
|
1649
2075
|
)));
|
|
1650
|
-
const renderEditMode = () => /* @__PURE__ */
|
|
2076
|
+
const renderEditMode = () => /* @__PURE__ */ import_react14.default.createElement("form", { onSubmit: handleSubmit, className: "flex flex-col bg-background overflow-hidden w-full max-h-[85vh]" }, /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center justify-between px-5 py-4 border-b border-border/50 shrink-0" }, /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center gap-3" }, /* @__PURE__ */ import_react14.default.createElement(
|
|
1651
2077
|
"button",
|
|
1652
2078
|
{
|
|
1653
2079
|
type: "button",
|
|
1654
2080
|
onClick: () => setIsColorPickerOpen(!isColorPickerOpen),
|
|
1655
2081
|
className: "relative p-1"
|
|
1656
2082
|
},
|
|
1657
|
-
/* @__PURE__ */
|
|
2083
|
+
/* @__PURE__ */ import_react14.default.createElement(
|
|
1658
2084
|
"div",
|
|
1659
2085
|
{
|
|
1660
2086
|
className: "w-5 h-5 rounded-full cursor-pointer hover:scale-110 transition-transform",
|
|
@@ -1664,7 +2090,7 @@ var EventModal = ({
|
|
|
1664
2090
|
}
|
|
1665
2091
|
}
|
|
1666
2092
|
),
|
|
1667
|
-
isColorPickerOpen && /* @__PURE__ */
|
|
2093
|
+
isColorPickerOpen && /* @__PURE__ */ import_react14.default.createElement("div", { className: "absolute top-full left-0 mt-2 p-2 bg-background border border-border rounded-xl shadow-xl z-50 flex flex-wrap gap-1.5 w-[180px]" }, COLOR_PALETTE.map((color) => /* @__PURE__ */ import_react14.default.createElement(
|
|
1668
2094
|
"button",
|
|
1669
2095
|
{
|
|
1670
2096
|
key: color,
|
|
@@ -1680,15 +2106,15 @@ var EventModal = ({
|
|
|
1680
2106
|
style: { backgroundColor: color, color }
|
|
1681
2107
|
}
|
|
1682
2108
|
)))
|
|
1683
|
-
), /* @__PURE__ */
|
|
2109
|
+
), /* @__PURE__ */ import_react14.default.createElement("h2", { className: "text-lg font-semibold text-foreground" }, mode === "edit" ? "Edit Event" : "New Event")), /* @__PURE__ */ import_react14.default.createElement(
|
|
1684
2110
|
"button",
|
|
1685
2111
|
{
|
|
1686
2112
|
type: "button",
|
|
1687
2113
|
onClick: onClose,
|
|
1688
2114
|
className: "p-2 hover:bg-accent rounded-xl transition-all text-muted-foreground hover:text-foreground"
|
|
1689
2115
|
},
|
|
1690
|
-
/* @__PURE__ */
|
|
1691
|
-
)), /* @__PURE__ */
|
|
2116
|
+
/* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.X, { className: "w-4 h-4" })
|
|
2117
|
+
)), /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex-1 overflow-y-auto" }, /* @__PURE__ */ import_react14.default.createElement("div", { className: "px-5 py-4 space-y-5" }, /* @__PURE__ */ import_react14.default.createElement("div", null, /* @__PURE__ */ import_react14.default.createElement(
|
|
1692
2118
|
"input",
|
|
1693
2119
|
{
|
|
1694
2120
|
type: "text",
|
|
@@ -1699,7 +2125,7 @@ var EventModal = ({
|
|
|
1699
2125
|
onChange: (e) => setFormData({ ...formData, title: e.target.value }),
|
|
1700
2126
|
placeholder: "Add title"
|
|
1701
2127
|
}
|
|
1702
|
-
)), /* @__PURE__ */
|
|
2128
|
+
)), /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center gap-3 p-4 rounded-2xl bg-muted/20 border border-border/30" }, /* @__PURE__ */ import_react14.default.createElement("div", { className: "p-2 bg-primary/10 rounded-xl shrink-0" }, /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.Clock, { className: "w-5 h-5 text-primary" })), /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex-1 grid grid-cols-2 gap-3" }, /* @__PURE__ */ import_react14.default.createElement("div", null, /* @__PURE__ */ import_react14.default.createElement("label", { className: "text-[10px] font-semibold text-muted-foreground uppercase tracking-wider mb-1 block" }, "Start"), /* @__PURE__ */ import_react14.default.createElement(
|
|
1703
2129
|
"input",
|
|
1704
2130
|
{
|
|
1705
2131
|
type: "datetime-local",
|
|
@@ -1707,7 +2133,7 @@ var EventModal = ({
|
|
|
1707
2133
|
value: formatDateForInput(formData.start),
|
|
1708
2134
|
onChange: (e) => handleDateChange("start", e.target.value)
|
|
1709
2135
|
}
|
|
1710
|
-
)), /* @__PURE__ */
|
|
2136
|
+
)), /* @__PURE__ */ import_react14.default.createElement("div", null, /* @__PURE__ */ import_react14.default.createElement("label", { className: "text-[10px] font-semibold text-muted-foreground uppercase tracking-wider mb-1 block" }, "End"), /* @__PURE__ */ import_react14.default.createElement(
|
|
1711
2137
|
"input",
|
|
1712
2138
|
{
|
|
1713
2139
|
type: "datetime-local",
|
|
@@ -1715,16 +2141,16 @@ var EventModal = ({
|
|
|
1715
2141
|
value: formatDateForInput(formData.end),
|
|
1716
2142
|
onChange: (e) => handleDateChange("end", e.target.value)
|
|
1717
2143
|
}
|
|
1718
|
-
)))), getDurationText() && /* @__PURE__ */
|
|
2144
|
+
)))), getDurationText() && /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex justify-center" }, /* @__PURE__ */ import_react14.default.createElement("span", { className: "text-xs font-medium px-3 py-1 rounded-full bg-primary/10 text-primary" }, getDurationText())), /* @__PURE__ */ import_react14.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.Bell, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ import_react14.default.createElement("span", { className: "text-sm font-medium text-foreground" }, "Reminders")), /* @__PURE__ */ import_react14.default.createElement("div", { className: "relative" }, /* @__PURE__ */ import_react14.default.createElement(
|
|
1719
2145
|
"button",
|
|
1720
2146
|
{
|
|
1721
2147
|
type: "button",
|
|
1722
2148
|
onClick: () => setIsReminderDropdownOpen(!isReminderDropdownOpen),
|
|
1723
2149
|
className: "flex items-center gap-1 text-xs font-medium text-primary hover:text-primary/80 transition-colors"
|
|
1724
2150
|
},
|
|
1725
|
-
/* @__PURE__ */
|
|
2151
|
+
/* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.Plus, { className: "w-3.5 h-3.5" }),
|
|
1726
2152
|
"Add"
|
|
1727
|
-
), isReminderDropdownOpen && /* @__PURE__ */
|
|
2153
|
+
), isReminderDropdownOpen && /* @__PURE__ */ import_react14.default.createElement(import_react14.default.Fragment, null, /* @__PURE__ */ import_react14.default.createElement("div", { className: "fixed inset-0 z-40", onClick: () => setIsReminderDropdownOpen(false) }), /* @__PURE__ */ import_react14.default.createElement("div", { className: "absolute right-0 top-full mt-1 w-48 bg-background border border-border rounded-xl shadow-xl z-50 py-1 max-h-60 overflow-y-auto" }, REMINDER_OPTIONS.map((option) => /* @__PURE__ */ import_react14.default.createElement(
|
|
1728
2154
|
"button",
|
|
1729
2155
|
{
|
|
1730
2156
|
key: option.value,
|
|
@@ -1733,58 +2159,58 @@ var EventModal = ({
|
|
|
1733
2159
|
className: "w-full px-3 py-2 text-left text-sm hover:bg-accent transition-colors"
|
|
1734
2160
|
},
|
|
1735
2161
|
option.label
|
|
1736
|
-
)))))), formData.reminders && formData.reminders.length > 0 && /* @__PURE__ */
|
|
2162
|
+
)))))), formData.reminders && formData.reminders.length > 0 && /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex flex-wrap gap-2" }, formData.reminders.map((reminder) => /* @__PURE__ */ import_react14.default.createElement(
|
|
1737
2163
|
"div",
|
|
1738
2164
|
{
|
|
1739
2165
|
key: reminder.id,
|
|
1740
2166
|
className: "flex items-center gap-2 px-3 py-1.5 rounded-full bg-amber-500/10 border border-amber-500/20"
|
|
1741
2167
|
},
|
|
1742
|
-
/* @__PURE__ */
|
|
1743
|
-
/* @__PURE__ */
|
|
1744
|
-
/* @__PURE__ */
|
|
2168
|
+
/* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.BellRing, { className: "w-3.5 h-3.5 text-amber-500" }),
|
|
2169
|
+
/* @__PURE__ */ import_react14.default.createElement("span", { className: "text-xs font-medium text-amber-600 dark:text-amber-400" }, reminder.label),
|
|
2170
|
+
/* @__PURE__ */ import_react14.default.createElement(
|
|
1745
2171
|
"button",
|
|
1746
2172
|
{
|
|
1747
2173
|
type: "button",
|
|
1748
2174
|
onClick: () => removeReminder(reminder.id),
|
|
1749
2175
|
className: "p-0.5 hover:bg-amber-500/20 rounded-full transition-colors"
|
|
1750
2176
|
},
|
|
1751
|
-
/* @__PURE__ */
|
|
2177
|
+
/* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.X, { className: "w-3 h-3 text-amber-500" })
|
|
1752
2178
|
)
|
|
1753
|
-
)))), /* @__PURE__ */
|
|
2179
|
+
)))), /* @__PURE__ */ import_react14.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.Users, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ import_react14.default.createElement("span", { className: "text-sm font-medium text-foreground" }, "Guests")), /* @__PURE__ */ import_react14.default.createElement("div", { className: "relative" }, /* @__PURE__ */ import_react14.default.createElement(
|
|
1754
2180
|
"button",
|
|
1755
2181
|
{
|
|
1756
2182
|
type: "button",
|
|
1757
2183
|
onClick: () => setIsGuestsDropdownOpen(!isGuestsDropdownOpen),
|
|
1758
2184
|
className: "w-full flex items-center justify-between px-4 py-3 bg-muted/20 border border-border/30 rounded-xl text-sm text-left hover:bg-muted/30 transition-all"
|
|
1759
2185
|
},
|
|
1760
|
-
/* @__PURE__ */
|
|
1761
|
-
/* @__PURE__ */
|
|
1762
|
-
), isGuestsDropdownOpen && /* @__PURE__ */
|
|
2186
|
+
/* @__PURE__ */ import_react14.default.createElement("span", { className: selectedGuests.length > 0 ? "text-foreground font-medium" : "text-muted-foreground" }, selectedGuests.length > 0 ? `${selectedGuests.length} guest${selectedGuests.length > 1 ? "s" : ""} added` : "Add guests"),
|
|
2187
|
+
/* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.ChevronDown, { className: cn("w-4 h-4 text-muted-foreground transition-transform", isGuestsDropdownOpen && "rotate-180") })
|
|
2188
|
+
), isGuestsDropdownOpen && /* @__PURE__ */ import_react14.default.createElement(import_react14.default.Fragment, null, /* @__PURE__ */ import_react14.default.createElement("div", { className: "fixed inset-0 z-40", onClick: () => setIsGuestsDropdownOpen(false) }), /* @__PURE__ */ import_react14.default.createElement("div", { className: "absolute z-50 w-full mt-2 bg-background border border-border rounded-xl shadow-xl max-h-48 overflow-y-auto" }, fakeGuests.map((email) => /* @__PURE__ */ import_react14.default.createElement(
|
|
1763
2189
|
"div",
|
|
1764
2190
|
{
|
|
1765
2191
|
key: email,
|
|
1766
2192
|
className: "px-4 py-3 hover:bg-accent cursor-pointer flex items-center gap-3 transition-colors",
|
|
1767
2193
|
onClick: () => toggleGuest(email)
|
|
1768
2194
|
},
|
|
1769
|
-
/* @__PURE__ */
|
|
2195
|
+
/* @__PURE__ */ import_react14.default.createElement("div", { className: cn(
|
|
1770
2196
|
"w-5 h-5 rounded-md border-2 flex items-center justify-center transition-all",
|
|
1771
2197
|
selectedGuests.includes(email) ? "bg-primary border-primary" : "border-border"
|
|
1772
|
-
) }, selectedGuests.includes(email) && /* @__PURE__ */
|
|
1773
|
-
/* @__PURE__ */
|
|
2198
|
+
) }, selectedGuests.includes(email) && /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.Check, { className: "w-3 h-3 text-primary-foreground" })),
|
|
2199
|
+
/* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react14.default.createElement(
|
|
1774
2200
|
"div",
|
|
1775
2201
|
{
|
|
1776
2202
|
className: "w-7 h-7 rounded-full flex items-center justify-center text-xs font-semibold text-white",
|
|
1777
2203
|
style: { backgroundColor: `hsl(${fakeGuests.indexOf(email) * 60}, 70%, 50%)` }
|
|
1778
2204
|
},
|
|
1779
2205
|
email[0].toUpperCase()
|
|
1780
|
-
), /* @__PURE__ */
|
|
1781
|
-
))))), selectedGuests.length > 0 && /* @__PURE__ */
|
|
2206
|
+
), /* @__PURE__ */ import_react14.default.createElement("span", { className: "text-sm" }, email))
|
|
2207
|
+
))))), selectedGuests.length > 0 && /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex flex-wrap gap-2 mt-2" }, selectedGuests.map((email) => /* @__PURE__ */ import_react14.default.createElement(
|
|
1782
2208
|
"div",
|
|
1783
2209
|
{
|
|
1784
2210
|
key: email,
|
|
1785
2211
|
className: "flex items-center gap-2 pl-1 pr-2 py-1 bg-muted/30 border border-border/30 rounded-full"
|
|
1786
2212
|
},
|
|
1787
|
-
/* @__PURE__ */
|
|
2213
|
+
/* @__PURE__ */ import_react14.default.createElement(
|
|
1788
2214
|
"div",
|
|
1789
2215
|
{
|
|
1790
2216
|
className: "w-6 h-6 rounded-full flex items-center justify-center text-xs font-semibold text-white",
|
|
@@ -1792,17 +2218,17 @@ var EventModal = ({
|
|
|
1792
2218
|
},
|
|
1793
2219
|
email[0].toUpperCase()
|
|
1794
2220
|
),
|
|
1795
|
-
/* @__PURE__ */
|
|
1796
|
-
/* @__PURE__ */
|
|
2221
|
+
/* @__PURE__ */ import_react14.default.createElement("span", { className: "text-xs font-medium text-foreground" }, email.split("@")[0]),
|
|
2222
|
+
/* @__PURE__ */ import_react14.default.createElement(
|
|
1797
2223
|
"button",
|
|
1798
2224
|
{
|
|
1799
2225
|
type: "button",
|
|
1800
2226
|
onClick: () => toggleGuest(email),
|
|
1801
2227
|
className: "p-0.5 hover:bg-destructive/10 rounded-full transition-colors"
|
|
1802
2228
|
},
|
|
1803
|
-
/* @__PURE__ */
|
|
2229
|
+
/* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.X, { className: "w-3 h-3 text-muted-foreground" })
|
|
1804
2230
|
)
|
|
1805
|
-
)))), /* @__PURE__ */
|
|
2231
|
+
)))), /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center gap-3 p-3 rounded-xl bg-muted/20 border border-border/30" }, /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.MapPin, { className: "w-5 h-5 text-muted-foreground shrink-0" }), /* @__PURE__ */ import_react14.default.createElement(
|
|
1806
2232
|
"input",
|
|
1807
2233
|
{
|
|
1808
2234
|
type: "text",
|
|
@@ -1811,7 +2237,7 @@ var EventModal = ({
|
|
|
1811
2237
|
value: formData.location || "",
|
|
1812
2238
|
onChange: (e) => setFormData({ ...formData, location: e.target.value })
|
|
1813
2239
|
}
|
|
1814
|
-
)), /* @__PURE__ */
|
|
2240
|
+
)), /* @__PURE__ */ import_react14.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.AlignLeft, { className: "w-4 h-4 text-muted-foreground" }), /* @__PURE__ */ import_react14.default.createElement("span", { className: "text-sm font-medium text-foreground" }, "Notes")), /* @__PURE__ */ import_react14.default.createElement(
|
|
1815
2241
|
"textarea",
|
|
1816
2242
|
{
|
|
1817
2243
|
className: "w-full bg-muted/20 border border-border/30 rounded-xl px-4 py-3 text-sm min-h-[100px] resize-none text-foreground placeholder-muted-foreground focus:border-primary focus:ring-2 focus:ring-primary/20 transition-all",
|
|
@@ -1819,7 +2245,7 @@ var EventModal = ({
|
|
|
1819
2245
|
value: formData.description || "",
|
|
1820
2246
|
onChange: (e) => setFormData({ ...formData, description: e.target.value })
|
|
1821
2247
|
}
|
|
1822
|
-
)), /* @__PURE__ */
|
|
2248
|
+
)), /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center gap-3 p-3 rounded-xl bg-muted/20 border border-border/30" }, /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.Repeat, { className: "w-5 h-5 text-muted-foreground shrink-0" }), /* @__PURE__ */ import_react14.default.createElement(
|
|
1823
2249
|
"select",
|
|
1824
2250
|
{
|
|
1825
2251
|
className: "flex-1 bg-transparent text-sm text-foreground focus:outline-none cursor-pointer",
|
|
@@ -1838,28 +2264,28 @@ var EventModal = ({
|
|
|
1838
2264
|
}
|
|
1839
2265
|
}
|
|
1840
2266
|
},
|
|
1841
|
-
/* @__PURE__ */
|
|
1842
|
-
/* @__PURE__ */
|
|
1843
|
-
/* @__PURE__ */
|
|
1844
|
-
/* @__PURE__ */
|
|
1845
|
-
/* @__PURE__ */
|
|
1846
|
-
)), /* @__PURE__ */
|
|
2267
|
+
/* @__PURE__ */ import_react14.default.createElement("option", { value: "" }, "Does not repeat"),
|
|
2268
|
+
/* @__PURE__ */ import_react14.default.createElement("option", { value: "DAILY" }, "Daily"),
|
|
2269
|
+
/* @__PURE__ */ import_react14.default.createElement("option", { value: "WEEKLY" }, "Weekly"),
|
|
2270
|
+
/* @__PURE__ */ import_react14.default.createElement("option", { value: "MONTHLY" }, "Monthly"),
|
|
2271
|
+
/* @__PURE__ */ import_react14.default.createElement("option", { value: "YEARLY" }, "Yearly")
|
|
2272
|
+
)), /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center justify-between p-3 rounded-xl bg-muted/20 border border-border/30" }, /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.Tag, { className: "w-5 h-5 text-muted-foreground" }), /* @__PURE__ */ import_react14.default.createElement("span", { className: "text-sm text-foreground" }, "Calendar")), /* @__PURE__ */ import_react14.default.createElement("div", { className: "relative" }, /* @__PURE__ */ import_react14.default.createElement(
|
|
1847
2273
|
"button",
|
|
1848
2274
|
{
|
|
1849
2275
|
type: "button",
|
|
1850
2276
|
onClick: () => setIsCalendarDropdownOpen(!isCalendarDropdownOpen),
|
|
1851
2277
|
className: "flex items-center gap-2 px-3 py-1.5 bg-background border border-border/50 rounded-lg text-sm hover:bg-accent/50 transition-all"
|
|
1852
2278
|
},
|
|
1853
|
-
/* @__PURE__ */
|
|
2279
|
+
/* @__PURE__ */ import_react14.default.createElement(
|
|
1854
2280
|
"div",
|
|
1855
2281
|
{
|
|
1856
2282
|
className: "w-3 h-3 rounded-full",
|
|
1857
2283
|
style: { backgroundColor: calendars?.find((c) => c.id === formData.calendarId)?.color || "#3b82f6" }
|
|
1858
2284
|
}
|
|
1859
2285
|
),
|
|
1860
|
-
/* @__PURE__ */
|
|
1861
|
-
/* @__PURE__ */
|
|
1862
|
-
), isCalendarDropdownOpen && /* @__PURE__ */
|
|
2286
|
+
/* @__PURE__ */ import_react14.default.createElement("span", { className: "font-medium" }, calendars?.find((c) => c.id === formData.calendarId)?.label || "Select"),
|
|
2287
|
+
/* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.ChevronDown, { className: "w-3.5 h-3.5 text-muted-foreground" })
|
|
2288
|
+
), isCalendarDropdownOpen && /* @__PURE__ */ import_react14.default.createElement(import_react14.default.Fragment, null, /* @__PURE__ */ import_react14.default.createElement("div", { className: "fixed inset-0 z-40", onClick: () => setIsCalendarDropdownOpen(false) }), /* @__PURE__ */ import_react14.default.createElement("div", { className: "absolute right-0 bottom-full mb-2 w-48 bg-background border border-border rounded-xl shadow-xl z-50 py-1" }, calendars?.map((cal) => /* @__PURE__ */ import_react14.default.createElement(
|
|
1863
2289
|
"button",
|
|
1864
2290
|
{
|
|
1865
2291
|
key: cal.id,
|
|
@@ -1874,19 +2300,19 @@ var EventModal = ({
|
|
|
1874
2300
|
setIsCalendarDropdownOpen(false);
|
|
1875
2301
|
}
|
|
1876
2302
|
},
|
|
1877
|
-
/* @__PURE__ */
|
|
1878
|
-
/* @__PURE__ */
|
|
1879
|
-
formData.calendarId === cal.id && /* @__PURE__ */
|
|
1880
|
-
)))))))), /* @__PURE__ */
|
|
2303
|
+
/* @__PURE__ */ import_react14.default.createElement("div", { className: "w-3 h-3 rounded-full", style: { backgroundColor: cal.color } }),
|
|
2304
|
+
/* @__PURE__ */ import_react14.default.createElement("span", { className: "flex-1 text-sm" }, cal.label),
|
|
2305
|
+
formData.calendarId === cal.id && /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.Check, { className: "w-4 h-4 text-primary" })
|
|
2306
|
+
)))))))), /* @__PURE__ */ import_react14.default.createElement("div", { className: "px-5 py-4 border-t border-border/50 flex items-center justify-between bg-muted/10 shrink-0" }, mode === "edit" && /* @__PURE__ */ import_react14.default.createElement(
|
|
1881
2307
|
"button",
|
|
1882
2308
|
{
|
|
1883
2309
|
type: "button",
|
|
1884
2310
|
onClick: handleDelete,
|
|
1885
2311
|
className: "flex items-center gap-2 px-4 py-2 text-destructive hover:bg-destructive/10 rounded-xl transition-all text-sm font-medium"
|
|
1886
2312
|
},
|
|
1887
|
-
/* @__PURE__ */
|
|
2313
|
+
/* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.Trash2, { className: "w-4 h-4" }),
|
|
1888
2314
|
"Delete"
|
|
1889
|
-
), mode === "create" && /* @__PURE__ */
|
|
2315
|
+
), mode === "create" && /* @__PURE__ */ import_react14.default.createElement("div", null), /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react14.default.createElement(
|
|
1890
2316
|
"button",
|
|
1891
2317
|
{
|
|
1892
2318
|
type: "button",
|
|
@@ -1894,7 +2320,7 @@ var EventModal = ({
|
|
|
1894
2320
|
className: "px-4 py-2.5 text-muted-foreground hover:text-foreground font-medium text-sm rounded-xl transition-all hover:bg-accent"
|
|
1895
2321
|
},
|
|
1896
2322
|
"Cancel"
|
|
1897
|
-
), /* @__PURE__ */
|
|
2323
|
+
), /* @__PURE__ */ import_react14.default.createElement(
|
|
1898
2324
|
"button",
|
|
1899
2325
|
{
|
|
1900
2326
|
type: "submit",
|
|
@@ -1902,8 +2328,8 @@ var EventModal = ({
|
|
|
1902
2328
|
},
|
|
1903
2329
|
mode === "edit" ? "Save Changes" : "Create Event"
|
|
1904
2330
|
))));
|
|
1905
|
-
return /* @__PURE__ */
|
|
1906
|
-
|
|
2331
|
+
return /* @__PURE__ */ import_react14.default.createElement(Modal, { isOpen, onClose, hideHeader: true, className: "p-0 overflow-hidden max-w-lg rounded-2xl shadow-2xl" }, /* @__PURE__ */ import_react14.default.createElement(import_framer_motion2.AnimatePresence, { mode: "wait" }, mode === "view" && event ? /* @__PURE__ */ import_react14.default.createElement(
|
|
2332
|
+
import_framer_motion2.motion.div,
|
|
1907
2333
|
{
|
|
1908
2334
|
key: "view",
|
|
1909
2335
|
initial: { opacity: 0 },
|
|
@@ -1912,8 +2338,8 @@ var EventModal = ({
|
|
|
1912
2338
|
transition: { duration: 0.15 }
|
|
1913
2339
|
},
|
|
1914
2340
|
renderViewMode()
|
|
1915
|
-
) : /* @__PURE__ */
|
|
1916
|
-
|
|
2341
|
+
) : /* @__PURE__ */ import_react14.default.createElement(
|
|
2342
|
+
import_framer_motion2.motion.div,
|
|
1917
2343
|
{
|
|
1918
2344
|
key: "edit",
|
|
1919
2345
|
initial: { opacity: 0 },
|
|
@@ -1924,9 +2350,12 @@ var EventModal = ({
|
|
|
1924
2350
|
renderEditMode()
|
|
1925
2351
|
)));
|
|
1926
2352
|
};
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
var
|
|
2353
|
+
|
|
2354
|
+
// src/components/Skeleton.tsx
|
|
2355
|
+
var import_react15 = __toESM(require("react"));
|
|
2356
|
+
var Skeleton = ({ className, style }) => /* @__PURE__ */ import_react15.default.createElement("div", { className: cn("animate-pulse bg-muted/40 rounded", className), style });
|
|
2357
|
+
var MonthViewSkeleton = () => /* @__PURE__ */ import_react15.default.createElement("div", { className: "h-full bg-background border border-border/50 rounded-2xl overflow-hidden" }, /* @__PURE__ */ import_react15.default.createElement("div", { className: "grid grid-cols-7 border-b border-border/50 bg-muted/10" }, Array.from({ length: 7 }).map((_, i) => /* @__PURE__ */ import_react15.default.createElement("div", { key: i, className: "py-3 px-2 text-center border-r border-border/30 last:border-r-0" }, /* @__PURE__ */ import_react15.default.createElement(Skeleton, { className: "h-4 w-8 mx-auto" })))), /* @__PURE__ */ import_react15.default.createElement("div", { className: "grid grid-cols-7 flex-1" }, Array.from({ length: 35 }).map((_, i) => /* @__PURE__ */ import_react15.default.createElement("div", { key: i, className: "min-h-[120px] border-r border-b border-border/30 p-2" }, /* @__PURE__ */ import_react15.default.createElement(Skeleton, { className: "h-4 w-6 mb-2" }), /* @__PURE__ */ import_react15.default.createElement("div", { className: "space-y-1" }, Math.random() > 0.5 && /* @__PURE__ */ import_react15.default.createElement(Skeleton, { className: "h-5 w-full rounded-md" }), Math.random() > 0.7 && /* @__PURE__ */ import_react15.default.createElement(Skeleton, { className: "h-5 w-3/4 rounded-md" }))))));
|
|
2358
|
+
var WeekViewSkeleton = () => /* @__PURE__ */ import_react15.default.createElement("div", { className: "h-full bg-background border border-border/50 rounded-2xl overflow-hidden" }, /* @__PURE__ */ import_react15.default.createElement("div", { className: "flex border-b border-border/50 bg-muted/10" }, /* @__PURE__ */ import_react15.default.createElement("div", { className: "w-16 p-3 border-r border-border/30" }, /* @__PURE__ */ import_react15.default.createElement(Skeleton, { className: "h-8 w-10 mx-auto" })), /* @__PURE__ */ import_react15.default.createElement("div", { className: "flex-1 grid grid-cols-7" }, Array.from({ length: 7 }).map((_, i) => /* @__PURE__ */ import_react15.default.createElement("div", { key: i, className: "py-3 px-2 text-center border-r border-border/30 last:border-r-0" }, /* @__PURE__ */ import_react15.default.createElement(Skeleton, { className: "h-3 w-8 mx-auto mb-1" }), /* @__PURE__ */ import_react15.default.createElement(Skeleton, { className: "h-8 w-8 mx-auto rounded-xl" }))))), /* @__PURE__ */ import_react15.default.createElement("div", { className: "flex flex-1", style: { height: "600px" } }, /* @__PURE__ */ import_react15.default.createElement("div", { className: "w-16 border-r border-border/30" }, Array.from({ length: 10 }).map((_, i) => /* @__PURE__ */ import_react15.default.createElement("div", { key: i, className: "h-[60px] relative" }, /* @__PURE__ */ import_react15.default.createElement(Skeleton, { className: "h-4 w-10 absolute right-2 -translate-y-1/2" })))), /* @__PURE__ */ import_react15.default.createElement("div", { className: "flex-1 grid grid-cols-7 relative" }, Array.from({ length: 7 }).map((_, colIdx) => /* @__PURE__ */ import_react15.default.createElement("div", { key: colIdx, className: "relative border-r border-border/30 last:border-r-0" }, Array.from({ length: 10 }).map((_2, rowIdx) => /* @__PURE__ */ import_react15.default.createElement("div", { key: rowIdx, className: "h-[60px] border-b border-dashed border-border/20" })), Math.random() > 0.3 && /* @__PURE__ */ import_react15.default.createElement(
|
|
1930
2359
|
Skeleton,
|
|
1931
2360
|
{
|
|
1932
2361
|
className: "absolute rounded-md",
|
|
@@ -1938,20 +2367,25 @@ var WeekViewSkeleton = () => /* @__PURE__ */ React15__namespace.default.createEl
|
|
|
1938
2367
|
}
|
|
1939
2368
|
}
|
|
1940
2369
|
))))));
|
|
1941
|
-
var DayViewSkeleton = () => /* @__PURE__ */
|
|
2370
|
+
var DayViewSkeleton = () => /* @__PURE__ */ import_react15.default.createElement("div", { className: "h-full bg-background border border-border/50 rounded-2xl overflow-hidden" }, /* @__PURE__ */ import_react15.default.createElement("div", { className: "px-6 py-4 border-b border-border/50 bg-muted/10 text-center" }, /* @__PURE__ */ import_react15.default.createElement(Skeleton, { className: "h-7 w-64 mx-auto" })), /* @__PURE__ */ import_react15.default.createElement("div", { className: "flex flex-1", style: { height: "600px" } }, /* @__PURE__ */ import_react15.default.createElement("div", { className: "w-20 border-r border-border/30 bg-muted/5" }, Array.from({ length: 10 }).map((_, i) => /* @__PURE__ */ import_react15.default.createElement("div", { key: i, className: "h-[80px] relative" }, /* @__PURE__ */ import_react15.default.createElement(Skeleton, { className: "h-4 w-12 absolute left-1/2 -translate-x-1/2 -translate-y-1/2" })))), /* @__PURE__ */ import_react15.default.createElement("div", { className: "flex-1 relative" }, Array.from({ length: 10 }).map((_, i) => /* @__PURE__ */ import_react15.default.createElement("div", { key: i, className: "h-[80px] border-b border-dashed border-border/20" })), /* @__PURE__ */ import_react15.default.createElement(
|
|
1942
2371
|
Skeleton,
|
|
1943
2372
|
{
|
|
1944
2373
|
className: "absolute rounded-lg left-4 right-4",
|
|
1945
2374
|
style: { top: "160px", height: "120px" }
|
|
1946
2375
|
}
|
|
1947
|
-
), /* @__PURE__ */
|
|
2376
|
+
), /* @__PURE__ */ import_react15.default.createElement(
|
|
1948
2377
|
Skeleton,
|
|
1949
2378
|
{
|
|
1950
2379
|
className: "absolute rounded-lg left-4 right-4",
|
|
1951
2380
|
style: { top: "400px", height: "80px" }
|
|
1952
2381
|
}
|
|
1953
2382
|
))));
|
|
1954
|
-
var AgendaViewSkeleton = () => /* @__PURE__ */
|
|
2383
|
+
var AgendaViewSkeleton = () => /* @__PURE__ */ import_react15.default.createElement("div", { className: "h-full bg-background border border-border/50 rounded-2xl overflow-hidden p-6" }, /* @__PURE__ */ import_react15.default.createElement("div", { className: "space-y-6" }, Array.from({ length: 4 }).map((_, dayIdx) => /* @__PURE__ */ import_react15.default.createElement("div", { key: dayIdx }, /* @__PURE__ */ import_react15.default.createElement(Skeleton, { className: "h-5 w-40 mb-4" }), /* @__PURE__ */ import_react15.default.createElement("div", { className: "space-y-3" }, Array.from({ length: 2 + Math.floor(Math.random() * 3) }).map((_2, eventIdx) => /* @__PURE__ */ import_react15.default.createElement("div", { key: eventIdx, className: "flex items-center gap-4 p-3 rounded-xl bg-muted/10" }, /* @__PURE__ */ import_react15.default.createElement(Skeleton, { className: "h-10 w-10 rounded-lg" }), /* @__PURE__ */ import_react15.default.createElement("div", { className: "flex-1 space-y-2" }, /* @__PURE__ */ import_react15.default.createElement(Skeleton, { className: "h-4 w-3/4" }), /* @__PURE__ */ import_react15.default.createElement(Skeleton, { className: "h-3 w-1/2" })))))))));
|
|
2384
|
+
|
|
2385
|
+
// src/components/ContextMenu.tsx
|
|
2386
|
+
var import_react16 = __toESM(require("react"));
|
|
2387
|
+
var import_lucide_react8 = require("lucide-react");
|
|
2388
|
+
var import_framer_motion3 = require("framer-motion");
|
|
1955
2389
|
var EventContextMenu = ({
|
|
1956
2390
|
event,
|
|
1957
2391
|
position,
|
|
@@ -1962,8 +2396,8 @@ var EventContextMenu = ({
|
|
|
1962
2396
|
customActions = [],
|
|
1963
2397
|
translations
|
|
1964
2398
|
}) => {
|
|
1965
|
-
const menuRef =
|
|
1966
|
-
|
|
2399
|
+
const menuRef = (0, import_react16.useRef)(null);
|
|
2400
|
+
(0, import_react16.useEffect)(() => {
|
|
1967
2401
|
const handleKeyDown = (e) => {
|
|
1968
2402
|
if (e.key === "Escape") {
|
|
1969
2403
|
onClose();
|
|
@@ -1974,7 +2408,7 @@ var EventContextMenu = ({
|
|
|
1974
2408
|
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
1975
2409
|
}
|
|
1976
2410
|
}, [position, onClose]);
|
|
1977
|
-
|
|
2411
|
+
(0, import_react16.useEffect)(() => {
|
|
1978
2412
|
const handleClickOutside = (e) => {
|
|
1979
2413
|
if (menuRef.current && !menuRef.current.contains(e.target)) {
|
|
1980
2414
|
onClose();
|
|
@@ -1992,7 +2426,7 @@ var EventContextMenu = ({
|
|
|
1992
2426
|
...onEdit ? [{
|
|
1993
2427
|
id: "edit",
|
|
1994
2428
|
label: translations?.edit || "Edit",
|
|
1995
|
-
icon: /* @__PURE__ */
|
|
2429
|
+
icon: /* @__PURE__ */ import_react16.default.createElement(import_lucide_react8.Edit3, { className: "w-4 h-4" }),
|
|
1996
2430
|
onClick: () => {
|
|
1997
2431
|
onEdit(event);
|
|
1998
2432
|
onClose();
|
|
@@ -2001,7 +2435,7 @@ var EventContextMenu = ({
|
|
|
2001
2435
|
...onDuplicate ? [{
|
|
2002
2436
|
id: "duplicate",
|
|
2003
2437
|
label: translations?.duplicate || "Duplicate",
|
|
2004
|
-
icon: /* @__PURE__ */
|
|
2438
|
+
icon: /* @__PURE__ */ import_react16.default.createElement(import_lucide_react8.Copy, { className: "w-4 h-4" }),
|
|
2005
2439
|
onClick: () => {
|
|
2006
2440
|
onDuplicate(event);
|
|
2007
2441
|
onClose();
|
|
@@ -2011,7 +2445,7 @@ var EventContextMenu = ({
|
|
|
2011
2445
|
...onDelete ? [{
|
|
2012
2446
|
id: "delete",
|
|
2013
2447
|
label: translations?.delete || "Delete",
|
|
2014
|
-
icon: /* @__PURE__ */
|
|
2448
|
+
icon: /* @__PURE__ */ import_react16.default.createElement(import_lucide_react8.Trash2, { className: "w-4 h-4" }),
|
|
2015
2449
|
onClick: () => {
|
|
2016
2450
|
onDelete(event.id);
|
|
2017
2451
|
onClose();
|
|
@@ -2023,8 +2457,8 @@ var EventContextMenu = ({
|
|
|
2023
2457
|
x: Math.min(position.x, window.innerWidth - 200),
|
|
2024
2458
|
y: Math.min(position.y, window.innerHeight - (actions.length * 44 + 80))
|
|
2025
2459
|
};
|
|
2026
|
-
return /* @__PURE__ */
|
|
2027
|
-
|
|
2460
|
+
return /* @__PURE__ */ import_react16.default.createElement(import_framer_motion3.AnimatePresence, null, /* @__PURE__ */ import_react16.default.createElement(
|
|
2461
|
+
import_framer_motion3.motion.div,
|
|
2028
2462
|
{
|
|
2029
2463
|
ref: menuRef,
|
|
2030
2464
|
initial: { opacity: 0, scale: 0.95, y: -5 },
|
|
@@ -2037,14 +2471,14 @@ var EventContextMenu = ({
|
|
|
2037
2471
|
top: adjustedPosition.y
|
|
2038
2472
|
}
|
|
2039
2473
|
},
|
|
2040
|
-
/* @__PURE__ */
|
|
2474
|
+
/* @__PURE__ */ import_react16.default.createElement("div", { className: "px-3 py-2 border-b-[0.5px] border-border bg-muted/30" }, /* @__PURE__ */ import_react16.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react16.default.createElement(
|
|
2041
2475
|
"div",
|
|
2042
2476
|
{
|
|
2043
2477
|
className: "w-2.5 h-2.5 rounded-full shrink-0",
|
|
2044
2478
|
style: { backgroundColor: event.color || "var(--primary)" }
|
|
2045
2479
|
}
|
|
2046
|
-
), /* @__PURE__ */
|
|
2047
|
-
/* @__PURE__ */
|
|
2480
|
+
), /* @__PURE__ */ import_react16.default.createElement("span", { className: "text-sm font-medium truncate text-foreground" }, event.title))),
|
|
2481
|
+
/* @__PURE__ */ import_react16.default.createElement("div", { className: "py-1" }, actions.map((action, index) => /* @__PURE__ */ import_react16.default.createElement(import_react16.default.Fragment, { key: action.id }, index > 0 && action.variant === "danger" && /* @__PURE__ */ import_react16.default.createElement("div", { className: "h-px bg-border my-1" }), /* @__PURE__ */ import_react16.default.createElement(
|
|
2048
2482
|
"button",
|
|
2049
2483
|
{
|
|
2050
2484
|
onClick: action.onClick,
|
|
@@ -2056,13 +2490,13 @@ var EventContextMenu = ({
|
|
|
2056
2490
|
)
|
|
2057
2491
|
},
|
|
2058
2492
|
action.icon,
|
|
2059
|
-
/* @__PURE__ */
|
|
2493
|
+
/* @__PURE__ */ import_react16.default.createElement("span", null, action.label)
|
|
2060
2494
|
))))
|
|
2061
2495
|
));
|
|
2062
2496
|
};
|
|
2063
2497
|
var useEventContextMenu = () => {
|
|
2064
|
-
const [contextMenu, setContextMenu] =
|
|
2065
|
-
const openContextMenu =
|
|
2498
|
+
const [contextMenu, setContextMenu] = (0, import_react16.useState)({ event: null, position: null });
|
|
2499
|
+
const openContextMenu = (0, import_react16.useCallback)((event, e) => {
|
|
2066
2500
|
e.preventDefault();
|
|
2067
2501
|
e.stopPropagation();
|
|
2068
2502
|
setContextMenu({
|
|
@@ -2070,7 +2504,7 @@ var useEventContextMenu = () => {
|
|
|
2070
2504
|
position: { x: e.clientX, y: e.clientY }
|
|
2071
2505
|
});
|
|
2072
2506
|
}, []);
|
|
2073
|
-
const closeContextMenu =
|
|
2507
|
+
const closeContextMenu = (0, import_react16.useCallback)(() => {
|
|
2074
2508
|
setContextMenu({ event: null, position: null });
|
|
2075
2509
|
}, []);
|
|
2076
2510
|
return {
|
|
@@ -2081,146 +2515,6 @@ var useEventContextMenu = () => {
|
|
|
2081
2515
|
};
|
|
2082
2516
|
};
|
|
2083
2517
|
|
|
2084
|
-
// src/locales/index.ts
|
|
2085
|
-
var en = {
|
|
2086
|
-
today: "Today",
|
|
2087
|
-
month: "Month",
|
|
2088
|
-
week: "Week",
|
|
2089
|
-
day: "Day",
|
|
2090
|
-
agenda: "Agenda",
|
|
2091
|
-
resource: "Resources",
|
|
2092
|
-
createEvent: "Create Event",
|
|
2093
|
-
editEvent: "Edit Event",
|
|
2094
|
-
delete: "Delete",
|
|
2095
|
-
save: "Save",
|
|
2096
|
-
cancel: "Cancel",
|
|
2097
|
-
title: "Add title",
|
|
2098
|
-
start: "Start",
|
|
2099
|
-
end: "End",
|
|
2100
|
-
allDay: "All Day",
|
|
2101
|
-
description: "Description",
|
|
2102
|
-
repeat: "Repeat",
|
|
2103
|
-
noRepeat: "Does not repeat",
|
|
2104
|
-
selectCalendar: "Select Calendar",
|
|
2105
|
-
selectType: "Select Type",
|
|
2106
|
-
daily: "Daily",
|
|
2107
|
-
weekly: "Weekly",
|
|
2108
|
-
monthly: "Monthly",
|
|
2109
|
-
yearly: "Yearly",
|
|
2110
|
-
search: "Search events...",
|
|
2111
|
-
allTypes: "All Types",
|
|
2112
|
-
timezone: "Time zone",
|
|
2113
|
-
localTime: "Local Time",
|
|
2114
|
-
create: "Create",
|
|
2115
|
-
calendars: "Calendars",
|
|
2116
|
-
event: "Event",
|
|
2117
|
-
task: "Task",
|
|
2118
|
-
appointmentSchedule: "Appointment schedule",
|
|
2119
|
-
new: "New",
|
|
2120
|
-
dateAndTime: "Date & Time",
|
|
2121
|
-
whosJoining: "Who's joining?",
|
|
2122
|
-
suggestedTimes: "Suggested times for guests",
|
|
2123
|
-
viewSuggestions: "View suggestions",
|
|
2124
|
-
whereWillItBe: "Where will it be?",
|
|
2125
|
-
location: "Enter address",
|
|
2126
|
-
descriptionAndAttachments: "Description",
|
|
2127
|
-
dragAndDrop: "Drag & drop files or",
|
|
2128
|
-
guests: "Guests",
|
|
2129
|
-
addGuests: "Add guests",
|
|
2130
|
-
addAttachment: "Upload files",
|
|
2131
|
-
moreOptions: "More options",
|
|
2132
|
-
doesNotRepeat: "Does not repeat",
|
|
2133
|
-
locationHelpText: 'Enter a physical address (e.g. "123 Main St") to generate the map.',
|
|
2134
|
-
notes: "Notes...",
|
|
2135
|
-
guestCount: "guest",
|
|
2136
|
-
guestsCount: "guests",
|
|
2137
|
-
repeatFor: "Repeat for",
|
|
2138
|
-
times: "times",
|
|
2139
|
-
until: "Until",
|
|
2140
|
-
endRepeat: "End repeat",
|
|
2141
|
-
never: "Never",
|
|
2142
|
-
afterOccurrences: "After occurrences",
|
|
2143
|
-
onDate: "On date",
|
|
2144
|
-
tomorrow: "Tomorrow",
|
|
2145
|
-
edit: "Edit",
|
|
2146
|
-
duplicate: "Duplicate",
|
|
2147
|
-
eventSingular: "event",
|
|
2148
|
-
eventPlural: "events",
|
|
2149
|
-
allCaughtUp: "All caught up!",
|
|
2150
|
-
noEventsScheduled: "No events scheduled",
|
|
2151
|
-
noUpcoming: "Your schedule is clear",
|
|
2152
|
-
noUpcomingHint: "No upcoming events to show. Create a new event to start planning."
|
|
2153
|
-
};
|
|
2154
|
-
var fr = {
|
|
2155
|
-
today: "Aujourd'hui",
|
|
2156
|
-
month: "Mois",
|
|
2157
|
-
week: "Semaine",
|
|
2158
|
-
day: "Jour",
|
|
2159
|
-
agenda: "Agenda",
|
|
2160
|
-
resource: "Ressources",
|
|
2161
|
-
createEvent: "Cr\xE9er un \xE9v\xE9nement",
|
|
2162
|
-
editEvent: "Modifier l'\xE9v\xE9nement",
|
|
2163
|
-
delete: "Supprimer",
|
|
2164
|
-
save: "Enregistrer",
|
|
2165
|
-
cancel: "Annuler",
|
|
2166
|
-
title: "Ajouter un titre",
|
|
2167
|
-
start: "D\xE9but",
|
|
2168
|
-
end: "Fin",
|
|
2169
|
-
allDay: "Toute la journ\xE9e",
|
|
2170
|
-
description: "Description",
|
|
2171
|
-
repeat: "R\xE9p\xE9ter",
|
|
2172
|
-
noRepeat: "Ne se r\xE9p\xE8te pas",
|
|
2173
|
-
selectCalendar: "S\xE9lectionner un calendrier",
|
|
2174
|
-
selectType: "S\xE9lectionner un type",
|
|
2175
|
-
daily: "Quotidien",
|
|
2176
|
-
weekly: "Hebdomadaire",
|
|
2177
|
-
monthly: "Mensuel",
|
|
2178
|
-
yearly: "Annuel",
|
|
2179
|
-
search: "Rechercher...",
|
|
2180
|
-
allTypes: "Tous les types",
|
|
2181
|
-
timezone: "Fuseau horaire",
|
|
2182
|
-
localTime: "Heure locale",
|
|
2183
|
-
create: "Cr\xE9er",
|
|
2184
|
-
calendars: "Calendriers",
|
|
2185
|
-
event: "\xC9v\xE9nement",
|
|
2186
|
-
task: "T\xE2che",
|
|
2187
|
-
appointmentSchedule: "Planning de rendez-vous",
|
|
2188
|
-
new: "Nouveau",
|
|
2189
|
-
dateAndTime: "Date et heure",
|
|
2190
|
-
whosJoining: "Qui participe ?",
|
|
2191
|
-
suggestedTimes: "Horaires sugg\xE9r\xE9s",
|
|
2192
|
-
viewSuggestions: "Voir les suggestions",
|
|
2193
|
-
whereWillItBe: "O\xF9 aura lieu ?",
|
|
2194
|
-
location: "Entrer une adresse",
|
|
2195
|
-
descriptionAndAttachments: "Description",
|
|
2196
|
-
dragAndDrop: "Glisser-d\xE9poser des fichiers ou",
|
|
2197
|
-
guests: "Invit\xE9s",
|
|
2198
|
-
addGuests: "Ajouter des invit\xE9s",
|
|
2199
|
-
addAttachment: "T\xE9l\xE9charger des fichiers",
|
|
2200
|
-
moreOptions: "Plus d'options",
|
|
2201
|
-
doesNotRepeat: "Ne se r\xE9p\xE8te pas",
|
|
2202
|
-
locationHelpText: 'Entrez une adresse physique (ex: "123 Rue Principale") pour g\xE9n\xE9rer la carte.',
|
|
2203
|
-
notes: "Notes...",
|
|
2204
|
-
guestCount: "invit\xE9",
|
|
2205
|
-
guestsCount: "invit\xE9s",
|
|
2206
|
-
repeatFor: "R\xE9p\xE9ter pendant",
|
|
2207
|
-
times: "fois",
|
|
2208
|
-
until: "Jusqu'au",
|
|
2209
|
-
endRepeat: "Fin de r\xE9p\xE9tition",
|
|
2210
|
-
never: "Jamais",
|
|
2211
|
-
afterOccurrences: "Apr\xE8s occurrences",
|
|
2212
|
-
onDate: "\xC0 la date",
|
|
2213
|
-
tomorrow: "Demain",
|
|
2214
|
-
edit: "Modifier",
|
|
2215
|
-
duplicate: "Dupliquer",
|
|
2216
|
-
eventSingular: "\xE9v\xE9nement",
|
|
2217
|
-
eventPlural: "\xE9v\xE9nements",
|
|
2218
|
-
allCaughtUp: "Tout est \xE0 jour !",
|
|
2219
|
-
noEventsScheduled: "Aucun \xE9v\xE9nement pr\xE9vu",
|
|
2220
|
-
noUpcoming: "Votre planning est libre",
|
|
2221
|
-
noUpcomingHint: "Aucun \xE9v\xE9nement \xE0 venir. Cr\xE9ez un nouvel \xE9v\xE9nement pour commencer \xE0 planifier."
|
|
2222
|
-
};
|
|
2223
|
-
|
|
2224
2518
|
// src/lib/theme.ts
|
|
2225
2519
|
function colorToHsl(color) {
|
|
2226
2520
|
let r = 0, g = 0, b = 0;
|
|
@@ -2246,7 +2540,7 @@ function colorToHsl(color) {
|
|
|
2246
2540
|
const min = Math.min(r, g, b);
|
|
2247
2541
|
let h = 0;
|
|
2248
2542
|
let s = 0;
|
|
2249
|
-
|
|
2543
|
+
const l = (max + min) / 2;
|
|
2250
2544
|
if (max !== min) {
|
|
2251
2545
|
const d = max - min;
|
|
2252
2546
|
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
@@ -2299,6 +2593,151 @@ function getThemeStyles(theme) {
|
|
|
2299
2593
|
}
|
|
2300
2594
|
return styles;
|
|
2301
2595
|
}
|
|
2596
|
+
|
|
2597
|
+
// src/hooks/useCalendarLogic.ts
|
|
2598
|
+
var import_react18 = require("react");
|
|
2599
|
+
var import_date_fns15 = require("date-fns");
|
|
2600
|
+
|
|
2601
|
+
// src/core/recurrence.ts
|
|
2602
|
+
var import_date_fns14 = require("date-fns");
|
|
2603
|
+
var import_rrule = require("rrule");
|
|
2604
|
+
var WEEKDAYS = [import_rrule.RRule.MO, import_rrule.RRule.TU, import_rrule.RRule.WE, import_rrule.RRule.TH, import_rrule.RRule.FR, import_rrule.RRule.SA, import_rrule.RRule.SU];
|
|
2605
|
+
var toFloating = (instant, tz) => {
|
|
2606
|
+
const w = toDisplay(instant, tz);
|
|
2607
|
+
return new Date(Date.UTC(w.getFullYear(), w.getMonth(), w.getDate(), w.getHours(), w.getMinutes(), w.getSeconds(), w.getMilliseconds()));
|
|
2608
|
+
};
|
|
2609
|
+
var fromFloating = (floating, tz) => fromDisplay(
|
|
2610
|
+
new Date(
|
|
2611
|
+
floating.getUTCFullYear(),
|
|
2612
|
+
floating.getUTCMonth(),
|
|
2613
|
+
floating.getUTCDate(),
|
|
2614
|
+
floating.getUTCHours(),
|
|
2615
|
+
floating.getUTCMinutes(),
|
|
2616
|
+
floating.getUTCSeconds(),
|
|
2617
|
+
floating.getUTCMilliseconds()
|
|
2618
|
+
),
|
|
2619
|
+
tz
|
|
2620
|
+
);
|
|
2621
|
+
var minuteKey = (date) => Math.floor(date.getTime() / 6e4);
|
|
2622
|
+
var FREQUENCIES = { DAILY: import_rrule.RRule.DAILY, WEEKLY: import_rrule.RRule.WEEKLY, MONTHLY: import_rrule.RRule.MONTHLY, YEARLY: import_rrule.RRule.YEARLY };
|
|
2623
|
+
function buildRule(event, tz) {
|
|
2624
|
+
const r = event.recurrence;
|
|
2625
|
+
const freq = FREQUENCIES[r.freq];
|
|
2626
|
+
if (freq === void 0) throw new Error(`unsupported frequency "${r.freq}"`);
|
|
2627
|
+
return new import_rrule.RRule({
|
|
2628
|
+
freq,
|
|
2629
|
+
interval: r.interval || 1,
|
|
2630
|
+
dtstart: toFloating(event.start, tz),
|
|
2631
|
+
until: r.until ? toFloating(r.until, tz) : void 0,
|
|
2632
|
+
count: r.count,
|
|
2633
|
+
byweekday: r.byweekday?.length ? r.byweekday.map((d) => WEEKDAYS[d]) : void 0
|
|
2634
|
+
});
|
|
2635
|
+
}
|
|
2636
|
+
function occurrencesInMonth(event, monthStart, tz) {
|
|
2637
|
+
const rule = buildRule(event, tz);
|
|
2638
|
+
const excluded = new Set((event.recurrence.exdates ?? []).map(minuteKey));
|
|
2639
|
+
const duration = event.end.getTime() - event.start.getTime();
|
|
2640
|
+
const from = toFloating(monthStart, tz);
|
|
2641
|
+
const to = toFloating((0, import_date_fns14.addMonths)(monthStart, 1), tz);
|
|
2642
|
+
const result = [];
|
|
2643
|
+
for (const floating of rule.between(from, to, true)) {
|
|
2644
|
+
if (floating.getTime() === to.getTime()) continue;
|
|
2645
|
+
const start = fromFloating(floating, tz);
|
|
2646
|
+
if (excluded.has(minuteKey(start))) continue;
|
|
2647
|
+
result.push({
|
|
2648
|
+
...event,
|
|
2649
|
+
id: `${event.id}-${start.getTime()}`,
|
|
2650
|
+
originalEventId: event.id,
|
|
2651
|
+
occurrenceStart: start,
|
|
2652
|
+
start,
|
|
2653
|
+
end: new Date(start.getTime() + duration)
|
|
2654
|
+
});
|
|
2655
|
+
}
|
|
2656
|
+
return result;
|
|
2657
|
+
}
|
|
2658
|
+
var MAX_MONTHS_PER_EVENT = 12;
|
|
2659
|
+
var occurrenceCache = /* @__PURE__ */ new WeakMap();
|
|
2660
|
+
function cachedMonth(event, monthStart, tz) {
|
|
2661
|
+
let months = occurrenceCache.get(event);
|
|
2662
|
+
if (!months) {
|
|
2663
|
+
months = /* @__PURE__ */ new Map();
|
|
2664
|
+
occurrenceCache.set(event, months);
|
|
2665
|
+
}
|
|
2666
|
+
const key = `${monthStart.getFullYear()}-${monthStart.getMonth()}|${tz ?? ""}`;
|
|
2667
|
+
let occurrences = months.get(key);
|
|
2668
|
+
if (occurrences) {
|
|
2669
|
+
months.delete(key);
|
|
2670
|
+
} else {
|
|
2671
|
+
occurrences = occurrencesInMonth(event, monthStart, tz);
|
|
2672
|
+
if (months.size >= MAX_MONTHS_PER_EVENT) months.delete(months.keys().next().value);
|
|
2673
|
+
}
|
|
2674
|
+
months.set(key, occurrences);
|
|
2675
|
+
return occurrences;
|
|
2676
|
+
}
|
|
2677
|
+
function expandRecurrences(events, range, anchorTz) {
|
|
2678
|
+
const result = [];
|
|
2679
|
+
const firstMonth = (0, import_date_fns14.startOfMonth)(toDisplay(range.start, anchorTz));
|
|
2680
|
+
const lastMonth = (0, import_date_fns14.startOfMonth)(toDisplay(range.end, anchorTz));
|
|
2681
|
+
for (const event of events) {
|
|
2682
|
+
if (!event.recurrence) {
|
|
2683
|
+
result.push(event);
|
|
2684
|
+
continue;
|
|
2685
|
+
}
|
|
2686
|
+
try {
|
|
2687
|
+
for (let month = firstMonth; month <= lastMonth; month = (0, import_date_fns14.addMonths)(month, 1)) {
|
|
2688
|
+
for (const occurrence of cachedMonth(event, fromDisplay(month, anchorTz), anchorTz)) {
|
|
2689
|
+
if (occurrence.end >= range.start && occurrence.start <= range.end) result.push(occurrence);
|
|
2690
|
+
}
|
|
2691
|
+
}
|
|
2692
|
+
} catch (error) {
|
|
2693
|
+
warnOnce(`invalid-recurrence:${event.id}`, `Event "${event.id}" has an invalid recurrence rule: ${String(error)}`);
|
|
2694
|
+
result.push(event);
|
|
2695
|
+
}
|
|
2696
|
+
}
|
|
2697
|
+
return result;
|
|
2698
|
+
}
|
|
2699
|
+
function stripOccurrenceFields(event) {
|
|
2700
|
+
const { originalEventId: _originalEventId, occurrenceStart: _occurrenceStart, ...rest } = event;
|
|
2701
|
+
return rest;
|
|
2702
|
+
}
|
|
2703
|
+
var shiftFloating = (instant, deltaMs, tz) => fromFloating(new Date(toFloating(instant, tz).getTime() + deltaMs), tz);
|
|
2704
|
+
var DAY_MS = 24 * 60 * 60 * 1e3;
|
|
2705
|
+
var floatingDay = (floating) => Math.floor(floating.getTime() / DAY_MS);
|
|
2706
|
+
function shiftSeries(master, occurrence, newStart, newEnd, anchorTz) {
|
|
2707
|
+
const fromFloat = toFloating(occurrence.start, anchorTz);
|
|
2708
|
+
const toFloat = toFloating(newStart, anchorTz);
|
|
2709
|
+
const deltaMs = toFloat.getTime() - fromFloat.getTime();
|
|
2710
|
+
const dayDelta = floatingDay(toFloat) - floatingDay(fromFloat);
|
|
2711
|
+
const start = shiftFloating(master.start, deltaMs, anchorTz);
|
|
2712
|
+
const end = new Date(start.getTime() + (newEnd.getTime() - newStart.getTime()));
|
|
2713
|
+
const recurrence = master.recurrence && {
|
|
2714
|
+
...master.recurrence,
|
|
2715
|
+
byweekday: master.recurrence.byweekday && dayDelta % 7 !== 0 ? master.recurrence.byweekday.map((d) => ((d + dayDelta) % 7 + 7) % 7) : master.recurrence.byweekday,
|
|
2716
|
+
exdates: master.recurrence.exdates?.map((d) => shiftFloating(d, deltaMs, anchorTz))
|
|
2717
|
+
};
|
|
2718
|
+
return stripOccurrenceFields({ ...master, start, end, recurrence });
|
|
2719
|
+
}
|
|
2720
|
+
function excludeOccurrence(master, occurrenceStart) {
|
|
2721
|
+
const recurrence = master.recurrence ?? { freq: "DAILY" };
|
|
2722
|
+
return { ...master, recurrence: { ...recurrence, exdates: [...recurrence.exdates ?? [], occurrenceStart] } };
|
|
2723
|
+
}
|
|
2724
|
+
|
|
2725
|
+
// src/hooks/useStableCallback.ts
|
|
2726
|
+
var import_react17 = require("react");
|
|
2727
|
+
function useStableCallback(fn) {
|
|
2728
|
+
const ref = (0, import_react17.useRef)(fn);
|
|
2729
|
+
ref.current = fn;
|
|
2730
|
+
return (0, import_react17.useCallback)((...args) => ref.current(...args), []);
|
|
2731
|
+
}
|
|
2732
|
+
|
|
2733
|
+
// src/hooks/useCalendarLogic.ts
|
|
2734
|
+
function expansionRange(monthStart) {
|
|
2735
|
+
return {
|
|
2736
|
+
start: (0, import_date_fns15.startOfWeek)((0, import_date_fns15.startOfMonth)((0, import_date_fns15.subMonths)(monthStart, 1))),
|
|
2737
|
+
end: (0, import_date_fns15.addDays)((0, import_date_fns15.endOfMonth)((0, import_date_fns15.addMonths)(monthStart, 1)), 37)
|
|
2738
|
+
};
|
|
2739
|
+
}
|
|
2740
|
+
var DAY_MS2 = 24 * 60 * 60 * 1e3;
|
|
2302
2741
|
var useCalendarLogic = ({
|
|
2303
2742
|
events,
|
|
2304
2743
|
view: controlledView,
|
|
@@ -2309,211 +2748,192 @@ var useCalendarLogic = ({
|
|
|
2309
2748
|
onEventUpdate,
|
|
2310
2749
|
onEventCreate,
|
|
2311
2750
|
onEventDelete,
|
|
2751
|
+
onEventDrop,
|
|
2752
|
+
onEventResize,
|
|
2753
|
+
onOccurrenceDelete,
|
|
2312
2754
|
readOnly,
|
|
2313
2755
|
timezone
|
|
2314
2756
|
}) => {
|
|
2315
|
-
const [internalView, setInternalView] =
|
|
2316
|
-
const [internalDate, setInternalDate] =
|
|
2317
|
-
const [isSidebarOpen, setIsSidebarOpen] =
|
|
2318
|
-
const [isModalOpen, setIsModalOpen] =
|
|
2319
|
-
const [selectedEvent, setSelectedEvent] =
|
|
2320
|
-
const [modalInitialDate, setModalInitialDate] =
|
|
2757
|
+
const [internalView, setInternalView] = (0, import_react18.useState)("week");
|
|
2758
|
+
const [internalDate, setInternalDate] = (0, import_react18.useState)(() => /* @__PURE__ */ new Date());
|
|
2759
|
+
const [isSidebarOpen, setIsSidebarOpen] = (0, import_react18.useState)(true);
|
|
2760
|
+
const [isModalOpen, setIsModalOpen] = (0, import_react18.useState)(false);
|
|
2761
|
+
const [selectedEvent, setSelectedEvent] = (0, import_react18.useState)(null);
|
|
2762
|
+
const [modalInitialDate, setModalInitialDate] = (0, import_react18.useState)(void 0);
|
|
2763
|
+
const [modalInitialResourceId, setModalInitialResourceId] = (0, import_react18.useState)(void 0);
|
|
2321
2764
|
const view = controlledView ?? internalView;
|
|
2322
2765
|
const currentDate = controlledDate ?? internalDate;
|
|
2323
|
-
const
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
interval: event.recurrence.interval || 1,
|
|
2333
|
-
dtstart: new Date(event.start),
|
|
2334
|
-
until: event.recurrence.until ? new Date(event.recurrence.until) : void 0,
|
|
2335
|
-
count: event.recurrence.count
|
|
2336
|
-
});
|
|
2337
|
-
const dates = rule.between(rangeStart, rangeEnd);
|
|
2338
|
-
dates.forEach((date) => {
|
|
2339
|
-
const duration = dateFns.differenceInMilliseconds(new Date(event.end), new Date(event.start));
|
|
2340
|
-
allEvents.push({
|
|
2341
|
-
...event,
|
|
2342
|
-
id: `${event.id}-${date.getTime()}`,
|
|
2343
|
-
// Unique ID for each instance
|
|
2344
|
-
originalEventId: event.id,
|
|
2345
|
-
// Reference to original
|
|
2346
|
-
start: date,
|
|
2347
|
-
end: new Date(date.getTime() + duration)
|
|
2348
|
-
});
|
|
2349
|
-
});
|
|
2350
|
-
} catch (e) {
|
|
2351
|
-
console.error("Error parsing recurrence rule", e);
|
|
2352
|
-
allEvents.push(event);
|
|
2353
|
-
}
|
|
2354
|
-
} else {
|
|
2355
|
-
allEvents.push(event);
|
|
2356
|
-
}
|
|
2357
|
-
});
|
|
2358
|
-
return allEvents;
|
|
2359
|
-
}, [events, currentDate]);
|
|
2360
|
-
const handleViewChange = (newView) => {
|
|
2766
|
+
const normalizedEvents = (0, import_react18.useMemo)(() => normalizeEvents(events), [events]);
|
|
2767
|
+
const monthKey = (0, import_date_fns15.format)(currentDate, "yyyy-MM");
|
|
2768
|
+
const range = (0, import_react18.useMemo)(() => expansionRange(/* @__PURE__ */ new Date(`${monthKey}-01T00:00:00`)), [monthKey]);
|
|
2769
|
+
const expandedEvents = (0, import_react18.useMemo)(
|
|
2770
|
+
() => expandRecurrences(normalizedEvents, range, timezone),
|
|
2771
|
+
[normalizedEvents, range, timezone]
|
|
2772
|
+
);
|
|
2773
|
+
const masterOf = (occurrence) => normalizedEvents.find((e) => e.id === occurrence.originalEventId);
|
|
2774
|
+
const handleViewChange = useStableCallback((newView) => {
|
|
2361
2775
|
if (controlledOnViewChange) {
|
|
2362
2776
|
controlledOnViewChange(newView);
|
|
2363
2777
|
} else {
|
|
2364
2778
|
setInternalView(newView);
|
|
2365
2779
|
}
|
|
2366
|
-
};
|
|
2367
|
-
const handleDateChange = (newDate) => {
|
|
2780
|
+
});
|
|
2781
|
+
const handleDateChange = useStableCallback((newDate) => {
|
|
2368
2782
|
if (controlledOnDateChange) {
|
|
2369
2783
|
controlledOnDateChange(newDate);
|
|
2370
2784
|
} else {
|
|
2371
2785
|
setInternalDate(newDate);
|
|
2372
2786
|
}
|
|
2373
|
-
};
|
|
2374
|
-
const handlePrev = () => {
|
|
2787
|
+
});
|
|
2788
|
+
const handlePrev = useStableCallback(() => {
|
|
2375
2789
|
switch (view) {
|
|
2376
2790
|
case "month":
|
|
2377
|
-
handleDateChange(
|
|
2791
|
+
handleDateChange((0, import_date_fns15.subMonths)(currentDate, 1));
|
|
2378
2792
|
break;
|
|
2379
2793
|
case "week":
|
|
2380
|
-
handleDateChange(
|
|
2794
|
+
handleDateChange((0, import_date_fns15.subWeeks)(currentDate, 1));
|
|
2381
2795
|
break;
|
|
2382
2796
|
case "day":
|
|
2383
2797
|
case "resource":
|
|
2384
|
-
handleDateChange(
|
|
2798
|
+
handleDateChange((0, import_date_fns15.subDays)(currentDate, 1));
|
|
2385
2799
|
break;
|
|
2386
2800
|
case "agenda":
|
|
2387
|
-
handleDateChange(
|
|
2801
|
+
handleDateChange((0, import_date_fns15.subDays)(currentDate, 7));
|
|
2388
2802
|
break;
|
|
2389
2803
|
}
|
|
2390
|
-
};
|
|
2391
|
-
const handleNext = () => {
|
|
2804
|
+
});
|
|
2805
|
+
const handleNext = useStableCallback(() => {
|
|
2392
2806
|
switch (view) {
|
|
2393
2807
|
case "month":
|
|
2394
|
-
handleDateChange(
|
|
2808
|
+
handleDateChange((0, import_date_fns15.addMonths)(currentDate, 1));
|
|
2395
2809
|
break;
|
|
2396
2810
|
case "week":
|
|
2397
|
-
handleDateChange(
|
|
2811
|
+
handleDateChange((0, import_date_fns15.addWeeks)(currentDate, 1));
|
|
2398
2812
|
break;
|
|
2399
2813
|
case "day":
|
|
2400
2814
|
case "resource":
|
|
2401
|
-
handleDateChange(
|
|
2815
|
+
handleDateChange((0, import_date_fns15.addDays)(currentDate, 1));
|
|
2402
2816
|
break;
|
|
2403
2817
|
case "agenda":
|
|
2404
|
-
handleDateChange(
|
|
2818
|
+
handleDateChange((0, import_date_fns15.addDays)(currentDate, 7));
|
|
2405
2819
|
break;
|
|
2406
2820
|
}
|
|
2407
|
-
};
|
|
2408
|
-
const handleToday = () => {
|
|
2821
|
+
});
|
|
2822
|
+
const handleToday = useStableCallback(() => {
|
|
2409
2823
|
handleDateChange(/* @__PURE__ */ new Date());
|
|
2410
|
-
};
|
|
2411
|
-
const handleDateClick = (date) => {
|
|
2824
|
+
});
|
|
2825
|
+
const handleDateClick = useStableCallback((date) => {
|
|
2412
2826
|
handleDateChange(date);
|
|
2413
2827
|
handleViewChange("day");
|
|
2414
|
-
};
|
|
2415
|
-
const handleTimeSlotClick = (date) => {
|
|
2828
|
+
});
|
|
2829
|
+
const handleTimeSlotClick = useStableCallback((date, resourceId) => {
|
|
2416
2830
|
if (readOnly) return;
|
|
2417
2831
|
setSelectedEvent(null);
|
|
2418
2832
|
setModalInitialDate(date);
|
|
2833
|
+
setModalInitialResourceId(resourceId);
|
|
2419
2834
|
setIsModalOpen(true);
|
|
2420
|
-
};
|
|
2421
|
-
const handleEventClickInternal = (event) => {
|
|
2422
|
-
|
|
2423
|
-
onEventClick(event);
|
|
2424
|
-
}
|
|
2835
|
+
});
|
|
2836
|
+
const handleEventClickInternal = useStableCallback((event) => {
|
|
2837
|
+
onEventClick?.(event);
|
|
2425
2838
|
if (!readOnly) {
|
|
2426
2839
|
setSelectedEvent(event);
|
|
2427
2840
|
setModalInitialDate(void 0);
|
|
2841
|
+
setModalInitialResourceId(void 0);
|
|
2428
2842
|
setIsModalOpen(true);
|
|
2429
2843
|
}
|
|
2430
|
-
};
|
|
2431
|
-
const handleCreateEvent = () => {
|
|
2844
|
+
});
|
|
2845
|
+
const handleCreateEvent = useStableCallback(() => {
|
|
2432
2846
|
if (readOnly) return;
|
|
2433
2847
|
setSelectedEvent(null);
|
|
2434
2848
|
setModalInitialDate(/* @__PURE__ */ new Date());
|
|
2849
|
+
setModalInitialResourceId(void 0);
|
|
2435
2850
|
setIsModalOpen(true);
|
|
2436
|
-
};
|
|
2437
|
-
const handleModalSave = (eventData) => {
|
|
2438
|
-
let effectiveEventId = selectedEvent?.id;
|
|
2851
|
+
});
|
|
2852
|
+
const handleModalSave = useStableCallback((eventData) => {
|
|
2439
2853
|
if (selectedEvent?.originalEventId) {
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
}
|
|
2854
|
+
const master = masterOf(selectedEvent);
|
|
2855
|
+
if (!master) return;
|
|
2856
|
+
const edited = {
|
|
2857
|
+
...master,
|
|
2858
|
+
...stripOccurrenceFields(eventData),
|
|
2859
|
+
id: master.id,
|
|
2860
|
+
start: master.start,
|
|
2861
|
+
end: master.end
|
|
2862
|
+
};
|
|
2863
|
+
onEventUpdate?.(
|
|
2864
|
+
shiftSeries(edited, selectedEvent, eventData.start ?? selectedEvent.start, eventData.end ?? selectedEvent.end, timezone)
|
|
2865
|
+
);
|
|
2866
|
+
} else if (selectedEvent) {
|
|
2867
|
+
onEventUpdate?.({ ...eventData, id: selectedEvent.id });
|
|
2449
2868
|
} else {
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
}
|
|
2454
|
-
};
|
|
2455
|
-
const handleModalDelete = (eventId) => {
|
|
2456
|
-
let effectiveEventId = eventId;
|
|
2457
|
-
if (selectedEvent?.originalEventId && selectedEvent.id === eventId) {
|
|
2458
|
-
effectiveEventId = selectedEvent.originalEventId;
|
|
2869
|
+
onEventCreate?.(
|
|
2870
|
+
modalInitialResourceId && eventData.resourceId === void 0 ? { ...eventData, resourceId: modalInitialResourceId } : eventData
|
|
2871
|
+
);
|
|
2459
2872
|
}
|
|
2460
|
-
|
|
2461
|
-
|
|
2873
|
+
});
|
|
2874
|
+
const handleEventDelete = useStableCallback((event) => {
|
|
2875
|
+
if (!event.originalEventId) {
|
|
2876
|
+
onEventDelete?.(event.id);
|
|
2877
|
+
return;
|
|
2462
2878
|
}
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
if (!over) return;
|
|
2467
|
-
const activeEvent = active.data.current?.event;
|
|
2468
|
-
const overDate = over.data.current?.date;
|
|
2469
|
-
if (!activeEvent || !overDate) return;
|
|
2470
|
-
const originalStart = new Date(activeEvent.start);
|
|
2471
|
-
const originalEnd = new Date(activeEvent.end);
|
|
2472
|
-
const duration = dateFns.differenceInMilliseconds(originalEnd, originalStart);
|
|
2473
|
-
let newStart;
|
|
2474
|
-
if (view === "month") {
|
|
2475
|
-
if (timezone) {
|
|
2476
|
-
const zonedOriginal = dateFnsTz.toZonedTime(originalStart, timezone);
|
|
2477
|
-
const zonedNew = new Date(overDate);
|
|
2478
|
-
zonedNew.setHours(zonedOriginal.getHours());
|
|
2479
|
-
zonedNew.setMinutes(zonedOriginal.getMinutes());
|
|
2480
|
-
zonedNew.setSeconds(zonedOriginal.getSeconds());
|
|
2481
|
-
zonedNew.setMilliseconds(zonedOriginal.getMilliseconds());
|
|
2482
|
-
newStart = dateFnsTz.fromZonedTime(zonedNew, timezone);
|
|
2483
|
-
} else {
|
|
2484
|
-
newStart = new Date(overDate);
|
|
2485
|
-
newStart.setHours(originalStart.getHours());
|
|
2486
|
-
newStart.setMinutes(originalStart.getMinutes());
|
|
2487
|
-
newStart.setSeconds(originalStart.getSeconds());
|
|
2488
|
-
newStart.setMilliseconds(originalStart.getMilliseconds());
|
|
2489
|
-
}
|
|
2879
|
+
const master = masterOf(event);
|
|
2880
|
+
if (onOccurrenceDelete && master) {
|
|
2881
|
+
onOccurrenceDelete(event, excludeOccurrence(master, event.occurrenceStart ?? event.start));
|
|
2490
2882
|
} else {
|
|
2491
|
-
|
|
2492
|
-
newStart = dateFnsTz.fromZonedTime(overDate, timezone);
|
|
2493
|
-
} else {
|
|
2494
|
-
newStart = new Date(overDate);
|
|
2495
|
-
}
|
|
2496
|
-
newStart.setSeconds(0);
|
|
2497
|
-
newStart.setMilliseconds(0);
|
|
2498
|
-
}
|
|
2499
|
-
const newEnd = new Date(newStart.getTime() + duration);
|
|
2500
|
-
let newResourceId = activeEvent.resourceId;
|
|
2501
|
-
const overResourceId = over.data.current?.resourceId;
|
|
2502
|
-
if (overResourceId) {
|
|
2503
|
-
newResourceId = overResourceId;
|
|
2504
|
-
}
|
|
2505
|
-
if (newStart.getTime() === originalStart.getTime() && newEnd.getTime() === originalEnd.getTime() && newResourceId === activeEvent.resourceId) {
|
|
2506
|
-
return;
|
|
2883
|
+
onEventDelete?.(event.originalEventId);
|
|
2507
2884
|
}
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
});
|
|
2885
|
+
});
|
|
2886
|
+
const handleModalDelete = useStableCallback((eventId) => {
|
|
2887
|
+
if (selectedEvent && selectedEvent.id === eventId) {
|
|
2888
|
+
handleEventDelete(selectedEvent);
|
|
2889
|
+
} else {
|
|
2890
|
+
onEventDelete?.(eventId);
|
|
2515
2891
|
}
|
|
2892
|
+
});
|
|
2893
|
+
const handleEventDuplicate = useStableCallback((event) => {
|
|
2894
|
+
const { recurrence: _recurrence, ...copy } = stripOccurrenceFields(event);
|
|
2895
|
+
onEventCreate?.({
|
|
2896
|
+
...copy,
|
|
2897
|
+
id: `${event.originalEventId ?? event.id}-copy-${Date.now()}`,
|
|
2898
|
+
title: `${event.title} (Copy)`,
|
|
2899
|
+
start: new Date(event.start.getTime() + DAY_MS2),
|
|
2900
|
+
end: new Date(event.end.getTime() + DAY_MS2)
|
|
2901
|
+
});
|
|
2902
|
+
});
|
|
2903
|
+
const applyChange = (event, start, end) => {
|
|
2904
|
+
if (!event.originalEventId) return { original: event, updated: { ...event, start, end } };
|
|
2905
|
+
const master = masterOf(event);
|
|
2906
|
+
if (!master) return null;
|
|
2907
|
+
return { original: master, updated: shiftSeries(master, event, start, end, timezone) };
|
|
2516
2908
|
};
|
|
2909
|
+
const handleDragEnd = useStableCallback((dragEvent) => {
|
|
2910
|
+
const { active, over } = dragEvent;
|
|
2911
|
+
if (!over) return;
|
|
2912
|
+
const dragged = active.data.current?.event;
|
|
2913
|
+
const overDate = over.data.current?.date;
|
|
2914
|
+
if (!dragged || !overDate) return;
|
|
2915
|
+
const drop = computeDrop({
|
|
2916
|
+
event: dragged,
|
|
2917
|
+
overDate,
|
|
2918
|
+
overResourceId: over.data.current?.resourceId,
|
|
2919
|
+
grabOffsetMs: active.data.current?.grabOffsetMs,
|
|
2920
|
+
view,
|
|
2921
|
+
tz: timezone
|
|
2922
|
+
});
|
|
2923
|
+
if (!drop) return;
|
|
2924
|
+
const change = applyChange(dragged, drop.start, drop.end);
|
|
2925
|
+
if (!change) return;
|
|
2926
|
+
const updated = { ...change.updated, resourceId: drop.resourceId };
|
|
2927
|
+
onEventDrop?.(change.original, updated.start, updated.end);
|
|
2928
|
+
onEventUpdate?.(updated);
|
|
2929
|
+
});
|
|
2930
|
+
const handleEventResize = useStableCallback((event, newEnd) => {
|
|
2931
|
+
if (readOnly) return;
|
|
2932
|
+
const change = applyChange(event, event.start, newEnd);
|
|
2933
|
+
if (!change) return;
|
|
2934
|
+
onEventResize?.(change.original, change.updated.start, change.updated.end);
|
|
2935
|
+
onEventUpdate?.(change.updated);
|
|
2936
|
+
});
|
|
2517
2937
|
return {
|
|
2518
2938
|
view,
|
|
2519
2939
|
currentDate,
|
|
@@ -2535,9 +2955,18 @@ var useCalendarLogic = ({
|
|
|
2535
2955
|
handleCreateEvent,
|
|
2536
2956
|
handleModalSave,
|
|
2537
2957
|
handleModalDelete,
|
|
2958
|
+
handleEventDelete,
|
|
2959
|
+
handleEventDuplicate,
|
|
2960
|
+
handleEventResize,
|
|
2538
2961
|
handleDragEnd
|
|
2539
2962
|
};
|
|
2540
2963
|
};
|
|
2964
|
+
|
|
2965
|
+
// src/index.tsx
|
|
2966
|
+
var import_date_fns16 = require("date-fns");
|
|
2967
|
+
|
|
2968
|
+
// src/hooks/useSwipeGesture.ts
|
|
2969
|
+
var import_react19 = require("react");
|
|
2541
2970
|
var useSwipeGesture = (options) => {
|
|
2542
2971
|
const {
|
|
2543
2972
|
onSwipeLeft,
|
|
@@ -2549,9 +2978,9 @@ var useSwipeGesture = (options) => {
|
|
|
2549
2978
|
allowedTime = 500,
|
|
2550
2979
|
enabled = true
|
|
2551
2980
|
} = options;
|
|
2552
|
-
const touchInfoRef =
|
|
2553
|
-
const elementRef =
|
|
2554
|
-
const handleTouchStart =
|
|
2981
|
+
const touchInfoRef = (0, import_react19.useRef)(null);
|
|
2982
|
+
const elementRef = (0, import_react19.useRef)(null);
|
|
2983
|
+
const handleTouchStart = (0, import_react19.useCallback)((e) => {
|
|
2555
2984
|
if (!enabled) return;
|
|
2556
2985
|
const touch = e.touches[0];
|
|
2557
2986
|
touchInfoRef.current = {
|
|
@@ -2560,7 +2989,7 @@ var useSwipeGesture = (options) => {
|
|
|
2560
2989
|
startTime: Date.now()
|
|
2561
2990
|
};
|
|
2562
2991
|
}, [enabled]);
|
|
2563
|
-
const handleTouchEnd =
|
|
2992
|
+
const handleTouchEnd = (0, import_react19.useCallback)((e) => {
|
|
2564
2993
|
if (!enabled || !touchInfoRef.current) return;
|
|
2565
2994
|
const touch = e.changedTouches[0];
|
|
2566
2995
|
const { startX, startY, startTime } = touchInfoRef.current;
|
|
@@ -2584,7 +3013,7 @@ var useSwipeGesture = (options) => {
|
|
|
2584
3013
|
}
|
|
2585
3014
|
touchInfoRef.current = null;
|
|
2586
3015
|
}, [enabled, threshold, restraint, allowedTime, onSwipeLeft, onSwipeRight, onSwipeUp, onSwipeDown]);
|
|
2587
|
-
|
|
3016
|
+
(0, import_react19.useEffect)(() => {
|
|
2588
3017
|
const element = elementRef.current;
|
|
2589
3018
|
if (!element) return;
|
|
2590
3019
|
element.addEventListener("touchstart", handleTouchStart, { passive: true });
|
|
@@ -2618,7 +3047,9 @@ var Scheduler = ({
|
|
|
2618
3047
|
onEventCreate,
|
|
2619
3048
|
onEventUpdate,
|
|
2620
3049
|
onEventDelete,
|
|
3050
|
+
onEventDrop,
|
|
2621
3051
|
onEventResize,
|
|
3052
|
+
onOccurrenceDelete,
|
|
2622
3053
|
timezone,
|
|
2623
3054
|
onTimezoneChange,
|
|
2624
3055
|
className,
|
|
@@ -2640,7 +3071,7 @@ var Scheduler = ({
|
|
|
2640
3071
|
locale
|
|
2641
3072
|
// Date-fns locale
|
|
2642
3073
|
}) => {
|
|
2643
|
-
const [activeDragEvent, setActiveDragEvent] =
|
|
3074
|
+
const [activeDragEvent, setActiveDragEvent] = (0, import_react20.useState)(null);
|
|
2644
3075
|
const {
|
|
2645
3076
|
contextMenuEvent,
|
|
2646
3077
|
contextMenuPosition,
|
|
@@ -2666,9 +3097,11 @@ var Scheduler = ({
|
|
|
2666
3097
|
handleCreateEvent,
|
|
2667
3098
|
handleModalSave,
|
|
2668
3099
|
handleModalDelete,
|
|
3100
|
+
handleEventDelete,
|
|
3101
|
+
handleEventDuplicate,
|
|
3102
|
+
handleEventResize,
|
|
2669
3103
|
handleDragEnd,
|
|
2670
3104
|
expandedEvents
|
|
2671
|
-
// New export
|
|
2672
3105
|
} = useCalendarLogic({
|
|
2673
3106
|
events,
|
|
2674
3107
|
view: controlledView,
|
|
@@ -2679,71 +3112,57 @@ var Scheduler = ({
|
|
|
2679
3112
|
onEventUpdate,
|
|
2680
3113
|
onEventCreate,
|
|
2681
3114
|
onEventDelete,
|
|
3115
|
+
onEventDrop,
|
|
3116
|
+
onEventResize,
|
|
3117
|
+
onOccurrenceDelete,
|
|
2682
3118
|
readOnly,
|
|
2683
3119
|
timezone
|
|
2684
3120
|
});
|
|
2685
|
-
const sensors =
|
|
2686
|
-
|
|
3121
|
+
const sensors = (0, import_core3.useSensors)(
|
|
3122
|
+
(0, import_core3.useSensor)(import_core3.PointerSensor, {
|
|
2687
3123
|
activationConstraint: {
|
|
2688
3124
|
distance: 8
|
|
2689
3125
|
}
|
|
2690
3126
|
})
|
|
2691
3127
|
);
|
|
2692
3128
|
const gridSize = 15;
|
|
2693
|
-
const snapToGrid =
|
|
2694
|
-
const modifiers
|
|
3129
|
+
const snapToGrid = (0, import_modifiers.createSnapModifier)(gridSize);
|
|
3130
|
+
const modifiers = [snapToGrid, import_modifiers.restrictToWindowEdges];
|
|
2695
3131
|
const dndSensors = readOnly ? [] : sensors;
|
|
2696
|
-
const
|
|
2697
|
-
if (readOnly) return;
|
|
2698
|
-
if (onEventResize) {
|
|
2699
|
-
onEventResize(event, event.start, newEnd);
|
|
2700
|
-
}
|
|
2701
|
-
if (onEventUpdate) {
|
|
2702
|
-
onEventUpdate({
|
|
2703
|
-
...event,
|
|
2704
|
-
end: newEnd
|
|
2705
|
-
});
|
|
2706
|
-
}
|
|
2707
|
-
};
|
|
2708
|
-
const id = React15.useId();
|
|
3132
|
+
const id = (0, import_react20.useId)();
|
|
2709
3133
|
const swipeRef = useViewSwipe(handlePrev, handleNext, true);
|
|
2710
|
-
const
|
|
2711
|
-
const
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
};
|
|
2715
|
-
const overlayTimeFormat = uses24HourClock(locale) ? "H:mm" : "h:mm a";
|
|
2716
|
-
const handleDragStart = (event) => {
|
|
2717
|
-
const { active } = event;
|
|
2718
|
-
const draggedEvent = expandedEvents.find((e) => e.id === active.id);
|
|
3134
|
+
const t = (0, import_react20.useMemo)(() => resolveTranslations(language, translations), [language, translations]);
|
|
3135
|
+
const overlayTimeFormat = timeFormats(locale).time;
|
|
3136
|
+
const handleDragStart = (0, import_react20.useCallback)((event) => {
|
|
3137
|
+
const draggedEvent = event.active.data.current?.event;
|
|
2719
3138
|
if (draggedEvent) {
|
|
2720
3139
|
setActiveDragEvent(draggedEvent);
|
|
2721
3140
|
}
|
|
2722
|
-
};
|
|
2723
|
-
const onDragEndWrapper = (event) => {
|
|
3141
|
+
}, []);
|
|
3142
|
+
const onDragEndWrapper = (0, import_react20.useCallback)((event) => {
|
|
2724
3143
|
setActiveDragEvent(null);
|
|
2725
3144
|
handleDragEnd(event);
|
|
2726
|
-
};
|
|
3145
|
+
}, [handleDragEnd]);
|
|
2727
3146
|
const getDragHeight = () => {
|
|
2728
3147
|
if (!activeDragEvent) return void 0;
|
|
2729
3148
|
if (view === "resource") {
|
|
2730
3149
|
return 80;
|
|
2731
3150
|
}
|
|
2732
3151
|
if (view !== "week" && view !== "day") return void 0;
|
|
2733
|
-
const duration =
|
|
3152
|
+
const duration = (0, import_date_fns16.differenceInMinutes)(activeDragEvent.end, activeDragEvent.start);
|
|
2734
3153
|
const hourHeight = view === "day" ? 80 : 60;
|
|
2735
3154
|
return duration / 60 * hourHeight;
|
|
2736
3155
|
};
|
|
2737
3156
|
const getDragWidth = () => {
|
|
2738
3157
|
if (view === "month") return "100%";
|
|
2739
3158
|
if (view === "resource" && activeDragEvent) {
|
|
2740
|
-
const duration =
|
|
3159
|
+
const duration = (0, import_date_fns16.differenceInMinutes)(activeDragEvent.end, activeDragEvent.start);
|
|
2741
3160
|
const width = duration / 60 * 100;
|
|
2742
3161
|
return `${Math.max(width, 4)}px`;
|
|
2743
3162
|
}
|
|
2744
3163
|
return "150px";
|
|
2745
3164
|
};
|
|
2746
|
-
const filteredEvents =
|
|
3165
|
+
const filteredEvents = (0, import_react20.useMemo)(() => {
|
|
2747
3166
|
if (!calendars) return expandedEvents;
|
|
2748
3167
|
const activeCalendarIds = calendars.filter((c) => c.active !== false).map((c) => c.id);
|
|
2749
3168
|
return expandedEvents.filter((e) => {
|
|
@@ -2751,22 +3170,22 @@ var Scheduler = ({
|
|
|
2751
3170
|
return activeCalendarIds.includes(e.calendarId);
|
|
2752
3171
|
});
|
|
2753
3172
|
}, [expandedEvents, calendars]);
|
|
2754
|
-
return /* @__PURE__ */
|
|
2755
|
-
|
|
3173
|
+
return /* @__PURE__ */ import_react20.default.createElement(
|
|
3174
|
+
import_core3.DndContext,
|
|
2756
3175
|
{
|
|
2757
3176
|
id,
|
|
2758
3177
|
sensors: dndSensors,
|
|
2759
3178
|
onDragStart: handleDragStart,
|
|
2760
3179
|
onDragEnd: onDragEndWrapper,
|
|
2761
|
-
modifiers
|
|
3180
|
+
modifiers
|
|
2762
3181
|
},
|
|
2763
|
-
/* @__PURE__ */
|
|
3182
|
+
/* @__PURE__ */ import_react20.default.createElement(
|
|
2764
3183
|
"div",
|
|
2765
3184
|
{
|
|
2766
3185
|
className: cn("flex flex-col h-full bg-background text-foreground relative", className),
|
|
2767
3186
|
style: getThemeStyles(theme)
|
|
2768
3187
|
},
|
|
2769
|
-
/* @__PURE__ */
|
|
3188
|
+
/* @__PURE__ */ import_react20.default.createElement(
|
|
2770
3189
|
CalendarHeader,
|
|
2771
3190
|
{
|
|
2772
3191
|
currentDate,
|
|
@@ -2785,8 +3204,8 @@ var Scheduler = ({
|
|
|
2785
3204
|
locale
|
|
2786
3205
|
}
|
|
2787
3206
|
),
|
|
2788
|
-
/* @__PURE__ */
|
|
2789
|
-
|
|
3207
|
+
/* @__PURE__ */ import_react20.default.createElement("div", { className: "flex flex-1 overflow-hidden" }, /* @__PURE__ */ import_react20.default.createElement(
|
|
3208
|
+
import_framer_motion4.motion.div,
|
|
2790
3209
|
{
|
|
2791
3210
|
className: cn(
|
|
2792
3211
|
"hidden md:block overflow-hidden"
|
|
@@ -2801,7 +3220,7 @@ var Scheduler = ({
|
|
|
2801
3220
|
ease: [0.4, 0, 0.2, 1]
|
|
2802
3221
|
}
|
|
2803
3222
|
},
|
|
2804
|
-
/* @__PURE__ */
|
|
3223
|
+
/* @__PURE__ */ import_react20.default.createElement(
|
|
2805
3224
|
Sidebar,
|
|
2806
3225
|
{
|
|
2807
3226
|
currentDate,
|
|
@@ -2818,8 +3237,8 @@ var Scheduler = ({
|
|
|
2818
3237
|
locale
|
|
2819
3238
|
}
|
|
2820
3239
|
)
|
|
2821
|
-
), /* @__PURE__ */
|
|
2822
|
-
|
|
3240
|
+
), /* @__PURE__ */ import_react20.default.createElement("div", { className: "flex-1 flex flex-col overflow-hidden relative" }, isLoading ? /* @__PURE__ */ import_react20.default.createElement("div", { className: "flex-1 overflow-auto p-0 md:p-4" }, /* @__PURE__ */ import_react20.default.createElement("div", { className: "h-full min-w-full" }, view === "month" && /* @__PURE__ */ import_react20.default.createElement(MonthViewSkeleton, null), view === "week" && /* @__PURE__ */ import_react20.default.createElement(WeekViewSkeleton, null), view === "day" && /* @__PURE__ */ import_react20.default.createElement(DayViewSkeleton, null), view === "agenda" && /* @__PURE__ */ import_react20.default.createElement(AgendaViewSkeleton, null), view === "resource" && /* @__PURE__ */ import_react20.default.createElement(WeekViewSkeleton, null))) : /* @__PURE__ */ import_react20.default.createElement("div", { ref: swipeRef, className: "flex-1 overflow-auto p-0 md:p-4 touch-pan-y" }, /* @__PURE__ */ import_react20.default.createElement("div", { className: "h-full min-w-full" }, /* @__PURE__ */ import_react20.default.createElement(import_framer_motion4.AnimatePresence, { mode: "wait", initial: false }, /* @__PURE__ */ import_react20.default.createElement(
|
|
3241
|
+
import_framer_motion4.motion.div,
|
|
2823
3242
|
{
|
|
2824
3243
|
key: `${view}-${currentDate.toISOString()}-${timezone || "local"}`,
|
|
2825
3244
|
initial: { opacity: 0, scale: 0.98, y: 15 },
|
|
@@ -2843,7 +3262,7 @@ var Scheduler = ({
|
|
|
2843
3262
|
},
|
|
2844
3263
|
className: "h-full"
|
|
2845
3264
|
},
|
|
2846
|
-
view === "month" && /* @__PURE__ */
|
|
3265
|
+
view === "month" && /* @__PURE__ */ import_react20.default.createElement(
|
|
2847
3266
|
MonthView,
|
|
2848
3267
|
{
|
|
2849
3268
|
currentDate,
|
|
@@ -2854,7 +3273,7 @@ var Scheduler = ({
|
|
|
2854
3273
|
locale
|
|
2855
3274
|
}
|
|
2856
3275
|
),
|
|
2857
|
-
view === "week" && /* @__PURE__ */
|
|
3276
|
+
view === "week" && /* @__PURE__ */ import_react20.default.createElement(
|
|
2858
3277
|
WeekView,
|
|
2859
3278
|
{
|
|
2860
3279
|
currentDate,
|
|
@@ -2867,7 +3286,7 @@ var Scheduler = ({
|
|
|
2867
3286
|
readonly: readOnly
|
|
2868
3287
|
}
|
|
2869
3288
|
),
|
|
2870
|
-
view === "day" && /* @__PURE__ */
|
|
3289
|
+
view === "day" && /* @__PURE__ */ import_react20.default.createElement(
|
|
2871
3290
|
DayView,
|
|
2872
3291
|
{
|
|
2873
3292
|
currentDate,
|
|
@@ -2880,7 +3299,7 @@ var Scheduler = ({
|
|
|
2880
3299
|
readonly: readOnly
|
|
2881
3300
|
}
|
|
2882
3301
|
),
|
|
2883
|
-
view === "agenda" && /* @__PURE__ */
|
|
3302
|
+
view === "agenda" && /* @__PURE__ */ import_react20.default.createElement(
|
|
2884
3303
|
AgendaView,
|
|
2885
3304
|
{
|
|
2886
3305
|
currentDate,
|
|
@@ -2888,30 +3307,29 @@ var Scheduler = ({
|
|
|
2888
3307
|
onEventClick: handleEventClickInternal,
|
|
2889
3308
|
onCreateEvent: handleCreateEvent,
|
|
2890
3309
|
locale,
|
|
2891
|
-
translations: t
|
|
3310
|
+
translations: t,
|
|
3311
|
+
timezone
|
|
2892
3312
|
}
|
|
2893
3313
|
),
|
|
2894
|
-
view === "resource" && resources && /* @__PURE__ */
|
|
3314
|
+
view === "resource" && resources && /* @__PURE__ */ import_react20.default.createElement(
|
|
2895
3315
|
ResourceView,
|
|
2896
3316
|
{
|
|
2897
3317
|
currentDate,
|
|
2898
3318
|
events: filteredEvents,
|
|
2899
3319
|
resources,
|
|
2900
3320
|
onEventClick: handleEventClickInternal,
|
|
2901
|
-
onTimeSlotClick:
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
},
|
|
2905
|
-
locale
|
|
3321
|
+
onTimeSlotClick: handleTimeSlotClick,
|
|
3322
|
+
locale,
|
|
3323
|
+
timezone
|
|
2906
3324
|
}
|
|
2907
3325
|
)
|
|
2908
|
-
)))), /* @__PURE__ */
|
|
3326
|
+
)))), /* @__PURE__ */ import_react20.default.createElement("div", { className: "md:hidden absolute bottom-6 right-6 z-50" }, /* @__PURE__ */ import_react20.default.createElement(
|
|
2909
3327
|
"button",
|
|
2910
3328
|
{
|
|
2911
3329
|
onClick: handleCreateEvent,
|
|
2912
3330
|
className: "w-14 h-14 bg-blue-600 rounded-full shadow-lg flex items-center justify-center text-white active:scale-90 transition-transform"
|
|
2913
3331
|
},
|
|
2914
|
-
/* @__PURE__ */
|
|
3332
|
+
/* @__PURE__ */ import_react20.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }, /* @__PURE__ */ import_react20.default.createElement("path", { d: "M5 12h14" }), /* @__PURE__ */ import_react20.default.createElement("path", { d: "M12 5v14" }))
|
|
2915
3333
|
)))),
|
|
2916
3334
|
renderEventForm ? renderEventForm({
|
|
2917
3335
|
isOpen: isModalOpen,
|
|
@@ -2920,7 +3338,7 @@ var Scheduler = ({
|
|
|
2920
3338
|
initialDate: modalInitialDate,
|
|
2921
3339
|
onSave: handleModalSave,
|
|
2922
3340
|
onDelete: handleModalDelete
|
|
2923
|
-
}) : /* @__PURE__ */
|
|
3341
|
+
}) : /* @__PURE__ */ import_react20.default.createElement(
|
|
2924
3342
|
EventModal,
|
|
2925
3343
|
{
|
|
2926
3344
|
isOpen: isModalOpen,
|
|
@@ -2934,7 +3352,7 @@ var Scheduler = ({
|
|
|
2934
3352
|
translations: t
|
|
2935
3353
|
}
|
|
2936
3354
|
),
|
|
2937
|
-
/* @__PURE__ */
|
|
3355
|
+
/* @__PURE__ */ import_react20.default.createElement(
|
|
2938
3356
|
EventContextMenu,
|
|
2939
3357
|
{
|
|
2940
3358
|
event: contextMenuEvent,
|
|
@@ -2944,20 +3362,12 @@ var Scheduler = ({
|
|
|
2944
3362
|
handleEventClickInternal(event);
|
|
2945
3363
|
closeContextMenu();
|
|
2946
3364
|
},
|
|
2947
|
-
onDelete: (
|
|
2948
|
-
|
|
3365
|
+
onDelete: () => {
|
|
3366
|
+
if (contextMenuEvent) handleEventDelete(contextMenuEvent);
|
|
2949
3367
|
closeContextMenu();
|
|
2950
3368
|
},
|
|
2951
3369
|
onDuplicate: (event) => {
|
|
2952
|
-
|
|
2953
|
-
...event,
|
|
2954
|
-
id: `${event.id}-copy-${Date.now()}`,
|
|
2955
|
-
title: `${event.title} (Copy)`,
|
|
2956
|
-
start: new Date(event.start.getTime() + 24 * 60 * 60 * 1e3),
|
|
2957
|
-
// +1 day
|
|
2958
|
-
end: new Date(event.end.getTime() + 24 * 60 * 60 * 1e3)
|
|
2959
|
-
};
|
|
2960
|
-
onEventCreate?.(duplicatedEvent);
|
|
3370
|
+
handleEventDuplicate(event);
|
|
2961
3371
|
closeContextMenu();
|
|
2962
3372
|
},
|
|
2963
3373
|
translations: {
|
|
@@ -2967,7 +3377,7 @@ var Scheduler = ({
|
|
|
2967
3377
|
}
|
|
2968
3378
|
}
|
|
2969
3379
|
),
|
|
2970
|
-
/* @__PURE__ */
|
|
3380
|
+
/* @__PURE__ */ import_react20.default.createElement(import_core3.DragOverlay, { dropAnimation: null }, activeDragEvent ? /* @__PURE__ */ import_react20.default.createElement(
|
|
2971
3381
|
"div",
|
|
2972
3382
|
{
|
|
2973
3383
|
className: cn(
|
|
@@ -2985,19 +3395,19 @@ var Scheduler = ({
|
|
|
2985
3395
|
transform: "rotate(-2deg) scale(1.02)"
|
|
2986
3396
|
}
|
|
2987
3397
|
},
|
|
2988
|
-
/* @__PURE__ */
|
|
3398
|
+
/* @__PURE__ */ import_react20.default.createElement("div", { className: "p-2.5 h-full flex flex-col" }, /* @__PURE__ */ import_react20.default.createElement(
|
|
2989
3399
|
"div",
|
|
2990
3400
|
{
|
|
2991
3401
|
className: "absolute left-0 top-0 bottom-0 w-1 rounded-l-lg",
|
|
2992
3402
|
style: { backgroundColor: activeDragEvent.color || "var(--primary)" }
|
|
2993
3403
|
}
|
|
2994
|
-
), /* @__PURE__ */
|
|
3404
|
+
), /* @__PURE__ */ import_react20.default.createElement("div", { className: "pl-2" }, /* @__PURE__ */ import_react20.default.createElement("div", { className: "font-semibold truncate text-sm" }, activeDragEvent.title), (view === "week" || view === "day") && getDragHeight() && getDragHeight() > 40 && /* @__PURE__ */ import_react20.default.createElement("div", { className: "text-xs opacity-80 mt-0.5 flex items-center gap-1" }, /* @__PURE__ */ import_react20.default.createElement("svg", { className: "w-3 h-3", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2" }, /* @__PURE__ */ import_react20.default.createElement("circle", { cx: "12", cy: "12", r: "10" }), /* @__PURE__ */ import_react20.default.createElement("path", { d: "M12 6v6l4 2" })), (0, import_date_fns16.format)(activeDragEvent.start, overlayTimeFormat, { locale }), " - ", (0, import_date_fns16.format)(activeDragEvent.end, overlayTimeFormat, { locale }))), /* @__PURE__ */ import_react20.default.createElement("div", { className: "absolute bottom-1.5 right-1.5 opacity-60" }, /* @__PURE__ */ import_react20.default.createElement("svg", { className: "w-4 h-4", viewBox: "0 0 24 24", fill: "currentColor" }, /* @__PURE__ */ import_react20.default.createElement("circle", { cx: "9", cy: "5", r: "1.5" }), /* @__PURE__ */ import_react20.default.createElement("circle", { cx: "15", cy: "5", r: "1.5" }), /* @__PURE__ */ import_react20.default.createElement("circle", { cx: "9", cy: "12", r: "1.5" }), /* @__PURE__ */ import_react20.default.createElement("circle", { cx: "15", cy: "12", r: "1.5" }), /* @__PURE__ */ import_react20.default.createElement("circle", { cx: "9", cy: "19", r: "1.5" }), /* @__PURE__ */ import_react20.default.createElement("circle", { cx: "15", cy: "19", r: "1.5" }))))
|
|
2995
3405
|
) : null)
|
|
2996
3406
|
)
|
|
2997
3407
|
);
|
|
2998
3408
|
};
|
|
2999
|
-
|
|
3000
|
-
exports
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3409
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
3410
|
+
0 && (module.exports = {
|
|
3411
|
+
Scheduler,
|
|
3412
|
+
cn
|
|
3413
|
+
});
|