@gobrand/calendar-core 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +706 -0
- package/dist/index.d.cts +245 -0
- package/dist/index.d.ts +245 -0
- package/dist/index.js +651 -0
- package/package.json +61 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,706 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
buildDay: () => buildDay,
|
|
24
|
+
buildMonth: () => buildMonth,
|
|
25
|
+
buildWeek: () => buildWeek,
|
|
26
|
+
convertToTimezone: () => convertToTimezone,
|
|
27
|
+
createCalendar: () => createCalendar,
|
|
28
|
+
createCalendarAccessor: () => createCalendarAccessor,
|
|
29
|
+
createCalendarViews: () => createCalendarViews,
|
|
30
|
+
createZonedDateTime: () => createZonedDateTime,
|
|
31
|
+
formatTime: () => formatTime,
|
|
32
|
+
functionalUpdate: () => functionalUpdate,
|
|
33
|
+
getCurrentTimeZone: () => getCurrentTimeZone,
|
|
34
|
+
getDayDateRange: () => getDayDateRange,
|
|
35
|
+
getDayRange: () => getDayRange,
|
|
36
|
+
getEventPosition: () => getEventPosition,
|
|
37
|
+
getMonthDateRange: () => getMonthDateRange,
|
|
38
|
+
getMonthName: () => getMonthName,
|
|
39
|
+
getMonthRange: () => getMonthRange,
|
|
40
|
+
getTimeSlotHeight: () => getTimeSlotHeight,
|
|
41
|
+
getTimezoneOffset: () => getTimezoneOffset,
|
|
42
|
+
getWeekDateRange: () => getWeekDateRange,
|
|
43
|
+
getWeekRange: () => getWeekRange,
|
|
44
|
+
getWeekdays: () => getWeekdays,
|
|
45
|
+
goToToday: () => goToToday,
|
|
46
|
+
nextDay: () => nextDay,
|
|
47
|
+
nextMonth: () => nextMonth,
|
|
48
|
+
nextWeek: () => nextWeek,
|
|
49
|
+
previousDay: () => previousDay,
|
|
50
|
+
previousMonth: () => previousMonth,
|
|
51
|
+
previousWeek: () => previousWeek
|
|
52
|
+
});
|
|
53
|
+
module.exports = __toCommonJS(index_exports);
|
|
54
|
+
|
|
55
|
+
// src/utils.ts
|
|
56
|
+
var import_polyfill = require("@js-temporal/polyfill");
|
|
57
|
+
function functionalUpdate(updater, input) {
|
|
58
|
+
return typeof updater === "function" ? updater(input) : updater;
|
|
59
|
+
}
|
|
60
|
+
function createCalendarAccessor(accessor) {
|
|
61
|
+
return accessor;
|
|
62
|
+
}
|
|
63
|
+
function nextMonth(month) {
|
|
64
|
+
return month.add({ months: 1 });
|
|
65
|
+
}
|
|
66
|
+
function previousMonth(month) {
|
|
67
|
+
return month.subtract({ months: 1 });
|
|
68
|
+
}
|
|
69
|
+
function nextWeek(date) {
|
|
70
|
+
return date.add({ weeks: 1 });
|
|
71
|
+
}
|
|
72
|
+
function previousWeek(date) {
|
|
73
|
+
return date.subtract({ weeks: 1 });
|
|
74
|
+
}
|
|
75
|
+
function nextDay(date) {
|
|
76
|
+
return date.add({ days: 1 });
|
|
77
|
+
}
|
|
78
|
+
function previousDay(date) {
|
|
79
|
+
return date.subtract({ days: 1 });
|
|
80
|
+
}
|
|
81
|
+
function goToToday() {
|
|
82
|
+
const today = import_polyfill.Temporal.Now.plainDateISO();
|
|
83
|
+
return { year: today.year, month: today.month };
|
|
84
|
+
}
|
|
85
|
+
function getWeekdays(weekStartsOn = 1, locale = "en-US", format = "short") {
|
|
86
|
+
const referenceDate = import_polyfill.Temporal.PlainDate.from("2023-01-02");
|
|
87
|
+
const days = [];
|
|
88
|
+
for (let i = 0; i < 7; i++) {
|
|
89
|
+
const offset = (weekStartsOn - 1 + i + 7) % 7;
|
|
90
|
+
const date = referenceDate.add({ days: offset });
|
|
91
|
+
days.push(date.toLocaleString(locale, { weekday: format }));
|
|
92
|
+
}
|
|
93
|
+
return days;
|
|
94
|
+
}
|
|
95
|
+
function getMonthName(month, locale = "en-US") {
|
|
96
|
+
return month.toPlainDate({ day: 1 }).toLocaleString(locale, { month: "long" });
|
|
97
|
+
}
|
|
98
|
+
function formatTime(time, locale = "en-US") {
|
|
99
|
+
const date = import_polyfill.Temporal.PlainDate.from("2023-01-01");
|
|
100
|
+
const dateTime = date.toPlainDateTime(time);
|
|
101
|
+
return dateTime.toLocaleString(locale, { hour: "numeric", minute: "2-digit" });
|
|
102
|
+
}
|
|
103
|
+
function getTimeSlotHeight(slotDuration, hourHeight) {
|
|
104
|
+
return slotDuration / 60 * hourHeight;
|
|
105
|
+
}
|
|
106
|
+
function getEventPosition(eventStart, eventEnd, dayStart, hourHeight) {
|
|
107
|
+
const startTime = eventStart.toPlainTime();
|
|
108
|
+
const endTime = eventEnd.toPlainTime();
|
|
109
|
+
const startMinutes = startTime.hour * 60 + startTime.minute;
|
|
110
|
+
const endMinutes = endTime.hour * 60 + endTime.minute;
|
|
111
|
+
const dayStartMinutes = dayStart * 60;
|
|
112
|
+
const top = (startMinutes - dayStartMinutes) / 60 * hourHeight;
|
|
113
|
+
const height = (endMinutes - startMinutes) / 60 * hourHeight;
|
|
114
|
+
return { top, height };
|
|
115
|
+
}
|
|
116
|
+
function convertToTimezone(dateTime, timeZone) {
|
|
117
|
+
return dateTime.withTimeZone(timeZone);
|
|
118
|
+
}
|
|
119
|
+
function getTimezoneOffset(dateTime) {
|
|
120
|
+
return dateTime.offsetNanoseconds / 36e11 >= 0 ? `+${Math.floor(dateTime.offsetNanoseconds / 36e11)}` : `${Math.floor(dateTime.offsetNanoseconds / 36e11)}`;
|
|
121
|
+
}
|
|
122
|
+
function createZonedDateTime(date, time, timeZone) {
|
|
123
|
+
return date.toZonedDateTime({ timeZone, plainTime: time });
|
|
124
|
+
}
|
|
125
|
+
function getCurrentTimeZone() {
|
|
126
|
+
return import_polyfill.Temporal.Now.timeZoneId();
|
|
127
|
+
}
|
|
128
|
+
function getMonthRange(timeZone = getCurrentTimeZone(), weekStartsOn = 1) {
|
|
129
|
+
const today = import_polyfill.Temporal.Now.zonedDateTimeISO(timeZone).toPlainDate();
|
|
130
|
+
const firstOfMonth = today.with({ day: 1 });
|
|
131
|
+
const lastOfMonth = today.with({ day: today.daysInMonth });
|
|
132
|
+
const startDayOfWeek = firstOfMonth.dayOfWeek;
|
|
133
|
+
const daysToSubtract = (startDayOfWeek - weekStartsOn + 7) % 7;
|
|
134
|
+
const start = firstOfMonth.subtract({ days: daysToSubtract });
|
|
135
|
+
const endDayOfWeek = lastOfMonth.dayOfWeek;
|
|
136
|
+
const daysToAdd = (weekStartsOn + 6 - endDayOfWeek) % 7;
|
|
137
|
+
const end = lastOfMonth.add({ days: daysToAdd });
|
|
138
|
+
return { start, end };
|
|
139
|
+
}
|
|
140
|
+
function getWeekRange(timeZone = getCurrentTimeZone(), weekStartsOn = 1) {
|
|
141
|
+
const today = import_polyfill.Temporal.Now.zonedDateTimeISO(timeZone).toPlainDate();
|
|
142
|
+
const dayOfWeek = today.dayOfWeek;
|
|
143
|
+
const daysToSubtract = (dayOfWeek - weekStartsOn + 7) % 7;
|
|
144
|
+
const start = today.subtract({ days: daysToSubtract });
|
|
145
|
+
const end = start.add({ days: 6 });
|
|
146
|
+
return { start, end };
|
|
147
|
+
}
|
|
148
|
+
function getDayRange(timeZone = getCurrentTimeZone()) {
|
|
149
|
+
const today = import_polyfill.Temporal.Now.zonedDateTimeISO(timeZone).toPlainDate();
|
|
150
|
+
return { start: today, end: today };
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// src/utils/buildMonth.ts
|
|
154
|
+
var import_polyfill2 = require("@js-temporal/polyfill");
|
|
155
|
+
function buildMonth(year, month, options) {
|
|
156
|
+
const weekStartsOn = options?.weekStartsOn ?? 1;
|
|
157
|
+
const today = options?.today ?? import_polyfill2.Temporal.Now.plainDateISO();
|
|
158
|
+
const data = options?.data ?? [];
|
|
159
|
+
const accessor = options?.accessor;
|
|
160
|
+
const yearMonth = import_polyfill2.Temporal.PlainYearMonth.from({ year, month });
|
|
161
|
+
const firstOfMonth = yearMonth.toPlainDate({ day: 1 });
|
|
162
|
+
const lastOfMonth = yearMonth.toPlainDate({ day: yearMonth.daysInMonth });
|
|
163
|
+
const itemsByDate = /* @__PURE__ */ new Map();
|
|
164
|
+
if (accessor) {
|
|
165
|
+
for (const item of data) {
|
|
166
|
+
const date = accessor.getDate(item);
|
|
167
|
+
const key = date.toString();
|
|
168
|
+
const existing = itemsByDate.get(key) ?? [];
|
|
169
|
+
itemsByDate.set(key, [...existing, item]);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
let startDate = firstOfMonth;
|
|
173
|
+
const firstDayOfWeek = firstOfMonth.dayOfWeek;
|
|
174
|
+
const daysToSubtract = (firstDayOfWeek - weekStartsOn + 7) % 7;
|
|
175
|
+
if (daysToSubtract > 0) {
|
|
176
|
+
startDate = firstOfMonth.subtract({ days: daysToSubtract });
|
|
177
|
+
}
|
|
178
|
+
const weeks = [];
|
|
179
|
+
let currentDate = startDate;
|
|
180
|
+
while (currentDate.month !== lastOfMonth.month || currentDate.day <= lastOfMonth.day || weeks.length === 0 || weeks[weeks.length - 1].length < 7) {
|
|
181
|
+
if (weeks.length === 0 || weeks[weeks.length - 1].length === 7) {
|
|
182
|
+
weeks.push([]);
|
|
183
|
+
}
|
|
184
|
+
const dateKey = currentDate.toString();
|
|
185
|
+
weeks[weeks.length - 1].push({
|
|
186
|
+
date: currentDate,
|
|
187
|
+
isCurrentMonth: currentDate.month === month,
|
|
188
|
+
isToday: import_polyfill2.Temporal.PlainDate.compare(currentDate, today) === 0,
|
|
189
|
+
items: itemsByDate.get(dateKey) ?? []
|
|
190
|
+
});
|
|
191
|
+
currentDate = currentDate.add({ days: 1 });
|
|
192
|
+
if (weeks.length >= 6 && weeks[weeks.length - 1].length === 7) {
|
|
193
|
+
break;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return {
|
|
197
|
+
weeks,
|
|
198
|
+
month: yearMonth
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// src/utils/buildWeek.ts
|
|
203
|
+
var import_polyfill4 = require("@js-temporal/polyfill");
|
|
204
|
+
|
|
205
|
+
// src/utils/buildDay.ts
|
|
206
|
+
var import_polyfill3 = require("@js-temporal/polyfill");
|
|
207
|
+
function buildDay(date, options) {
|
|
208
|
+
const startHour = options?.startHour ?? 0;
|
|
209
|
+
const endHour = options?.endHour ?? 24;
|
|
210
|
+
const slotDuration = options?.slotDuration ?? 30;
|
|
211
|
+
const today = options?.today ?? import_polyfill3.Temporal.Now.plainDateISO();
|
|
212
|
+
const data = options?.data ?? [];
|
|
213
|
+
const accessor = options?.accessor;
|
|
214
|
+
const dayItems = [];
|
|
215
|
+
if (accessor) {
|
|
216
|
+
for (const item of data) {
|
|
217
|
+
const itemDate = accessor.getDate(item);
|
|
218
|
+
if (import_polyfill3.Temporal.PlainDate.compare(itemDate, date) === 0) {
|
|
219
|
+
dayItems.push(item);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
const timeSlots = [];
|
|
224
|
+
let currentHour = startHour;
|
|
225
|
+
let currentMinute = 0;
|
|
226
|
+
while (currentHour < endHour) {
|
|
227
|
+
const slotStart = import_polyfill3.Temporal.PlainTime.from({ hour: currentHour, minute: currentMinute });
|
|
228
|
+
let nextMinute = currentMinute + slotDuration;
|
|
229
|
+
let nextHour = currentHour;
|
|
230
|
+
if (nextMinute >= 60) {
|
|
231
|
+
nextHour += Math.floor(nextMinute / 60);
|
|
232
|
+
nextMinute = nextMinute % 60;
|
|
233
|
+
}
|
|
234
|
+
const slotItems = [];
|
|
235
|
+
if (accessor?.getStart) {
|
|
236
|
+
for (const item of dayItems) {
|
|
237
|
+
const itemStart = accessor.getStart(item);
|
|
238
|
+
const itemTime = itemStart.toPlainTime();
|
|
239
|
+
const slotEndHour = nextHour >= 24 ? 0 : nextHour;
|
|
240
|
+
const slotEndMinute = nextHour >= 24 ? 0 : nextMinute;
|
|
241
|
+
const slotEnd = import_polyfill3.Temporal.PlainTime.from({ hour: slotEndHour, minute: slotEndMinute });
|
|
242
|
+
const isAfterStart = import_polyfill3.Temporal.PlainTime.compare(itemTime, slotStart) >= 0;
|
|
243
|
+
const isBeforeEnd = nextHour >= 24 ? import_polyfill3.Temporal.PlainTime.compare(itemTime, slotEnd) > 0 : import_polyfill3.Temporal.PlainTime.compare(itemTime, slotEnd) < 0;
|
|
244
|
+
if (isAfterStart && isBeforeEnd) {
|
|
245
|
+
slotItems.push(item);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
timeSlots.push({
|
|
250
|
+
hour: currentHour,
|
|
251
|
+
minute: currentMinute,
|
|
252
|
+
time: slotStart,
|
|
253
|
+
items: slotItems
|
|
254
|
+
});
|
|
255
|
+
currentMinute += slotDuration;
|
|
256
|
+
if (currentMinute >= 60) {
|
|
257
|
+
currentHour += Math.floor(currentMinute / 60);
|
|
258
|
+
currentMinute = currentMinute % 60;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
return {
|
|
262
|
+
date,
|
|
263
|
+
isToday: import_polyfill3.Temporal.PlainDate.compare(date, today) === 0,
|
|
264
|
+
timeSlots,
|
|
265
|
+
items: dayItems
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// src/utils/buildWeek.ts
|
|
270
|
+
function buildWeek(date, options) {
|
|
271
|
+
const weekStartsOn = options?.weekStartsOn ?? 1;
|
|
272
|
+
const startHour = options?.startHour;
|
|
273
|
+
const endHour = options?.endHour;
|
|
274
|
+
const slotDuration = options?.slotDuration;
|
|
275
|
+
const today = options?.today ?? import_polyfill4.Temporal.Now.plainDateISO();
|
|
276
|
+
const data = options?.data ?? [];
|
|
277
|
+
const accessor = options?.accessor;
|
|
278
|
+
const hasTimeSlots = startHour !== void 0 && endHour !== void 0 && slotDuration !== void 0;
|
|
279
|
+
const itemsByDate = /* @__PURE__ */ new Map();
|
|
280
|
+
if (accessor) {
|
|
281
|
+
for (const item of data) {
|
|
282
|
+
const date2 = accessor.getDate(item);
|
|
283
|
+
const key = date2.toString();
|
|
284
|
+
const existing = itemsByDate.get(key) ?? [];
|
|
285
|
+
itemsByDate.set(key, [...existing, item]);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
const dayOfWeek = date.dayOfWeek;
|
|
289
|
+
const daysToSubtract = (dayOfWeek - weekStartsOn + 7) % 7;
|
|
290
|
+
const weekStart = date.subtract({ days: daysToSubtract });
|
|
291
|
+
const days = [];
|
|
292
|
+
for (let i = 0; i < 7; i++) {
|
|
293
|
+
const currentDate = weekStart.add({ days: i });
|
|
294
|
+
const dateKey = currentDate.toString();
|
|
295
|
+
let timeSlots = void 0;
|
|
296
|
+
if (hasTimeSlots) {
|
|
297
|
+
const dayView = buildDay(currentDate, {
|
|
298
|
+
startHour,
|
|
299
|
+
endHour,
|
|
300
|
+
slotDuration,
|
|
301
|
+
today,
|
|
302
|
+
data,
|
|
303
|
+
accessor
|
|
304
|
+
});
|
|
305
|
+
timeSlots = dayView.timeSlots;
|
|
306
|
+
}
|
|
307
|
+
days.push({
|
|
308
|
+
date: currentDate,
|
|
309
|
+
isToday: import_polyfill4.Temporal.PlainDate.compare(currentDate, today) === 0,
|
|
310
|
+
items: itemsByDate.get(dateKey) ?? [],
|
|
311
|
+
timeSlots
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
const weekEnd = weekStart.add({ days: 6 });
|
|
315
|
+
return {
|
|
316
|
+
days,
|
|
317
|
+
weekStart,
|
|
318
|
+
weekEnd
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// src/utils/dateRanges.ts
|
|
323
|
+
var import_polyfill5 = require("@js-temporal/polyfill");
|
|
324
|
+
function getMonthDateRange(date, timeZone, options) {
|
|
325
|
+
const weekStartsOn = options?.weekStartsOn ?? 1;
|
|
326
|
+
const bounds = options?.bounds ?? "calendar";
|
|
327
|
+
const firstOfMonth = date.with({ day: 1 });
|
|
328
|
+
const lastOfMonth = date.with({ day: date.daysInMonth });
|
|
329
|
+
let start;
|
|
330
|
+
let end;
|
|
331
|
+
if (bounds === "calendar") {
|
|
332
|
+
const startDayOfWeek = firstOfMonth.dayOfWeek;
|
|
333
|
+
const daysToSubtract = (startDayOfWeek - weekStartsOn + 7) % 7;
|
|
334
|
+
start = firstOfMonth.subtract({ days: daysToSubtract });
|
|
335
|
+
const endDayOfWeek = lastOfMonth.dayOfWeek;
|
|
336
|
+
const daysToAdd = (weekStartsOn + 6 - endDayOfWeek) % 7;
|
|
337
|
+
end = lastOfMonth.add({ days: daysToAdd });
|
|
338
|
+
} else {
|
|
339
|
+
start = firstOfMonth;
|
|
340
|
+
end = lastOfMonth;
|
|
341
|
+
}
|
|
342
|
+
const startZoned = start.toZonedDateTime({
|
|
343
|
+
timeZone,
|
|
344
|
+
plainTime: import_polyfill5.Temporal.PlainTime.from("00:00:00")
|
|
345
|
+
});
|
|
346
|
+
const endZoned = end.toZonedDateTime({
|
|
347
|
+
timeZone,
|
|
348
|
+
plainTime: import_polyfill5.Temporal.PlainTime.from("23:59:59.999")
|
|
349
|
+
});
|
|
350
|
+
return { start: startZoned, end: endZoned };
|
|
351
|
+
}
|
|
352
|
+
function getWeekDateRange(date, timeZone, options) {
|
|
353
|
+
const weekStartsOn = options?.weekStartsOn ?? 1;
|
|
354
|
+
const dayOfWeek = date.dayOfWeek;
|
|
355
|
+
const daysToSubtract = (dayOfWeek - weekStartsOn + 7) % 7;
|
|
356
|
+
const start = date.subtract({ days: daysToSubtract });
|
|
357
|
+
const end = start.add({ days: 6 });
|
|
358
|
+
const startZoned = start.toZonedDateTime({
|
|
359
|
+
timeZone,
|
|
360
|
+
plainTime: import_polyfill5.Temporal.PlainTime.from("00:00:00")
|
|
361
|
+
});
|
|
362
|
+
const endZoned = end.toZonedDateTime({
|
|
363
|
+
timeZone,
|
|
364
|
+
plainTime: import_polyfill5.Temporal.PlainTime.from("23:59:59.999")
|
|
365
|
+
});
|
|
366
|
+
return { start: startZoned, end: endZoned };
|
|
367
|
+
}
|
|
368
|
+
function getDayDateRange(date, timeZone) {
|
|
369
|
+
const startZoned = date.toZonedDateTime({
|
|
370
|
+
timeZone,
|
|
371
|
+
plainTime: import_polyfill5.Temporal.PlainTime.from("00:00:00")
|
|
372
|
+
});
|
|
373
|
+
const endZoned = date.toZonedDateTime({
|
|
374
|
+
timeZone,
|
|
375
|
+
plainTime: import_polyfill5.Temporal.PlainTime.from("23:59:59.999")
|
|
376
|
+
});
|
|
377
|
+
return { start: startZoned, end: endZoned };
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// src/core/calendar.ts
|
|
381
|
+
var import_polyfill6 = require("@js-temporal/polyfill");
|
|
382
|
+
var import_store = require("@tanstack/store");
|
|
383
|
+
function computeDateRange(view, referenceDate, timeZone, weekStartsOn = 1) {
|
|
384
|
+
let start;
|
|
385
|
+
let end;
|
|
386
|
+
if (view === "month") {
|
|
387
|
+
const firstOfMonth = referenceDate.with({ day: 1 });
|
|
388
|
+
const lastOfMonth = referenceDate.with({ day: referenceDate.daysInMonth });
|
|
389
|
+
const startDayOfWeek = firstOfMonth.dayOfWeek;
|
|
390
|
+
const daysToSubtract = (startDayOfWeek - weekStartsOn + 7) % 7;
|
|
391
|
+
start = firstOfMonth.subtract({ days: daysToSubtract });
|
|
392
|
+
const endDayOfWeek = lastOfMonth.dayOfWeek;
|
|
393
|
+
const daysToAdd = (weekStartsOn + 6 - endDayOfWeek) % 7;
|
|
394
|
+
end = lastOfMonth.add({ days: daysToAdd });
|
|
395
|
+
} else if (view === "week") {
|
|
396
|
+
const dayOfWeek = referenceDate.dayOfWeek;
|
|
397
|
+
const daysToSubtract = (dayOfWeek - weekStartsOn + 7) % 7;
|
|
398
|
+
start = referenceDate.subtract({ days: daysToSubtract });
|
|
399
|
+
end = start.add({ days: 6 });
|
|
400
|
+
} else {
|
|
401
|
+
start = referenceDate;
|
|
402
|
+
end = referenceDate;
|
|
403
|
+
}
|
|
404
|
+
const startZoned = start.toZonedDateTime({
|
|
405
|
+
timeZone,
|
|
406
|
+
plainTime: import_polyfill6.Temporal.PlainTime.from("00:00:00")
|
|
407
|
+
});
|
|
408
|
+
const endZoned = end.toZonedDateTime({
|
|
409
|
+
timeZone,
|
|
410
|
+
plainTime: import_polyfill6.Temporal.PlainTime.from("23:59:59.999")
|
|
411
|
+
});
|
|
412
|
+
return { start: startZoned, end: endZoned };
|
|
413
|
+
}
|
|
414
|
+
function createCalendar(options) {
|
|
415
|
+
const configuredViews = Object.keys(options.views);
|
|
416
|
+
const defaultView = configuredViews[0];
|
|
417
|
+
const timeZone = options.timeZone || import_polyfill6.Temporal.Now.timeZoneId();
|
|
418
|
+
const monthView = options.views.month;
|
|
419
|
+
const weekView = options.views.week;
|
|
420
|
+
const weekStartsOn = monthView?.weekStartsOn ?? weekView?.weekStartsOn ?? 1;
|
|
421
|
+
const initialReferenceDate = options.state?.referenceDate || import_polyfill6.Temporal.Now.plainDateISO();
|
|
422
|
+
const initialView = options.state?.currentView || defaultView;
|
|
423
|
+
const initialDateRange = computeDateRange(
|
|
424
|
+
initialView,
|
|
425
|
+
initialReferenceDate,
|
|
426
|
+
timeZone,
|
|
427
|
+
weekStartsOn
|
|
428
|
+
);
|
|
429
|
+
const resolvedOptions = {
|
|
430
|
+
state: {
|
|
431
|
+
referenceDate: initialReferenceDate,
|
|
432
|
+
currentView: initialView,
|
|
433
|
+
dateRange: initialDateRange
|
|
434
|
+
},
|
|
435
|
+
onStateChange: () => {
|
|
436
|
+
},
|
|
437
|
+
...options
|
|
438
|
+
};
|
|
439
|
+
let _options = resolvedOptions;
|
|
440
|
+
const store = new import_store.Store({
|
|
441
|
+
referenceDate: initialReferenceDate,
|
|
442
|
+
currentView: initialView,
|
|
443
|
+
dateRange: initialDateRange,
|
|
444
|
+
...resolvedOptions.state
|
|
445
|
+
});
|
|
446
|
+
const getMonthImpl = () => {
|
|
447
|
+
const state = store.state;
|
|
448
|
+
const { year, month } = state.referenceDate;
|
|
449
|
+
const monthView2 = _options.views.month;
|
|
450
|
+
if (!monthView2) throw new Error("Month view not configured");
|
|
451
|
+
return buildMonth(year, month, {
|
|
452
|
+
weekStartsOn: monthView2.weekStartsOn,
|
|
453
|
+
data: _options.data,
|
|
454
|
+
accessor: monthView2.accessor
|
|
455
|
+
});
|
|
456
|
+
};
|
|
457
|
+
const getWeekImpl = () => {
|
|
458
|
+
const state = store.state;
|
|
459
|
+
const weekView2 = _options.views.week;
|
|
460
|
+
if (!weekView2) throw new Error("Week view not configured");
|
|
461
|
+
return buildWeek(state.referenceDate, {
|
|
462
|
+
weekStartsOn: weekView2.weekStartsOn,
|
|
463
|
+
startHour: weekView2.startHour,
|
|
464
|
+
endHour: weekView2.endHour,
|
|
465
|
+
slotDuration: weekView2.slotDuration,
|
|
466
|
+
data: _options.data,
|
|
467
|
+
accessor: weekView2.accessor
|
|
468
|
+
});
|
|
469
|
+
};
|
|
470
|
+
const getDayImpl = () => {
|
|
471
|
+
const state = store.state;
|
|
472
|
+
const dayView = _options.views.day;
|
|
473
|
+
if (!dayView) throw new Error("Day view not configured");
|
|
474
|
+
return buildDay(state.referenceDate, {
|
|
475
|
+
startHour: dayView.startHour,
|
|
476
|
+
endHour: dayView.endHour,
|
|
477
|
+
slotDuration: dayView.slotDuration,
|
|
478
|
+
data: _options.data,
|
|
479
|
+
accessor: dayView.accessor
|
|
480
|
+
});
|
|
481
|
+
};
|
|
482
|
+
const setStateImpl = (updater) => {
|
|
483
|
+
const partialState = typeof updater === "function" ? updater(store.state) : updater;
|
|
484
|
+
const newState = {
|
|
485
|
+
...store.state,
|
|
486
|
+
...partialState
|
|
487
|
+
};
|
|
488
|
+
const currentView = newState.currentView || defaultView;
|
|
489
|
+
const dateRange = computeDateRange(
|
|
490
|
+
currentView,
|
|
491
|
+
newState.referenceDate,
|
|
492
|
+
timeZone,
|
|
493
|
+
weekStartsOn
|
|
494
|
+
);
|
|
495
|
+
const stateWithDateRange = {
|
|
496
|
+
...newState,
|
|
497
|
+
dateRange
|
|
498
|
+
};
|
|
499
|
+
store.setState(() => stateWithDateRange);
|
|
500
|
+
if (_options.onStateChange) {
|
|
501
|
+
_options.onStateChange(stateWithDateRange);
|
|
502
|
+
}
|
|
503
|
+
};
|
|
504
|
+
const nextMonthImpl = () => {
|
|
505
|
+
setStateImpl((old) => {
|
|
506
|
+
const current = import_polyfill6.Temporal.PlainYearMonth.from({
|
|
507
|
+
year: old.referenceDate.year,
|
|
508
|
+
month: old.referenceDate.month
|
|
509
|
+
});
|
|
510
|
+
const next = nextMonth(current);
|
|
511
|
+
return {
|
|
512
|
+
referenceDate: next.toPlainDate({ day: 1 })
|
|
513
|
+
};
|
|
514
|
+
});
|
|
515
|
+
};
|
|
516
|
+
const previousMonthImpl = () => {
|
|
517
|
+
setStateImpl((old) => {
|
|
518
|
+
const current = import_polyfill6.Temporal.PlainYearMonth.from({
|
|
519
|
+
year: old.referenceDate.year,
|
|
520
|
+
month: old.referenceDate.month
|
|
521
|
+
});
|
|
522
|
+
const prev = previousMonth(current);
|
|
523
|
+
return {
|
|
524
|
+
referenceDate: prev.toPlainDate({ day: 1 })
|
|
525
|
+
};
|
|
526
|
+
});
|
|
527
|
+
};
|
|
528
|
+
const nextWeekImpl = () => {
|
|
529
|
+
setStateImpl((old) => ({
|
|
530
|
+
referenceDate: nextWeek(old.referenceDate)
|
|
531
|
+
}));
|
|
532
|
+
};
|
|
533
|
+
const previousWeekImpl = () => {
|
|
534
|
+
setStateImpl((old) => ({
|
|
535
|
+
referenceDate: previousWeek(old.referenceDate)
|
|
536
|
+
}));
|
|
537
|
+
};
|
|
538
|
+
const nextDayImpl = () => {
|
|
539
|
+
setStateImpl((old) => ({
|
|
540
|
+
referenceDate: nextDay(old.referenceDate)
|
|
541
|
+
}));
|
|
542
|
+
};
|
|
543
|
+
const previousDayImpl = () => {
|
|
544
|
+
setStateImpl((old) => ({
|
|
545
|
+
referenceDate: previousDay(old.referenceDate)
|
|
546
|
+
}));
|
|
547
|
+
};
|
|
548
|
+
const calendar = {
|
|
549
|
+
getMonth: getMonthImpl,
|
|
550
|
+
getWeek: getWeekImpl,
|
|
551
|
+
getDay: getDayImpl,
|
|
552
|
+
getTitle(view, locales, options2) {
|
|
553
|
+
switch (view) {
|
|
554
|
+
case "month": {
|
|
555
|
+
const month = getMonthImpl();
|
|
556
|
+
const date = month.month.toPlainDate({ day: 1 });
|
|
557
|
+
return date.toLocaleString(locales, {
|
|
558
|
+
month: "long",
|
|
559
|
+
year: "numeric",
|
|
560
|
+
...options2
|
|
561
|
+
});
|
|
562
|
+
}
|
|
563
|
+
case "week": {
|
|
564
|
+
const week = getWeekImpl();
|
|
565
|
+
const startOptions = {
|
|
566
|
+
month: "short",
|
|
567
|
+
day: "numeric",
|
|
568
|
+
...options2
|
|
569
|
+
};
|
|
570
|
+
const endOptions = {
|
|
571
|
+
month: "short",
|
|
572
|
+
day: "numeric",
|
|
573
|
+
year: "numeric",
|
|
574
|
+
...options2
|
|
575
|
+
};
|
|
576
|
+
const start = week.weekStart.toLocaleString(locales, startOptions);
|
|
577
|
+
const end = week.weekEnd.toLocaleString(locales, endOptions);
|
|
578
|
+
return `${start} - ${end}`;
|
|
579
|
+
}
|
|
580
|
+
case "day": {
|
|
581
|
+
const day = getDayImpl();
|
|
582
|
+
return day.date.toLocaleString(locales, {
|
|
583
|
+
weekday: "long",
|
|
584
|
+
month: "long",
|
|
585
|
+
day: "numeric",
|
|
586
|
+
year: "numeric",
|
|
587
|
+
...options2
|
|
588
|
+
});
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
},
|
|
592
|
+
getState() {
|
|
593
|
+
return store.state;
|
|
594
|
+
},
|
|
595
|
+
setState: setStateImpl,
|
|
596
|
+
nextMonth: nextMonthImpl,
|
|
597
|
+
previousMonth: previousMonthImpl,
|
|
598
|
+
goToMonth(year, month) {
|
|
599
|
+
setStateImpl(() => ({
|
|
600
|
+
referenceDate: import_polyfill6.Temporal.PlainDate.from({ year, month, day: 1 })
|
|
601
|
+
}));
|
|
602
|
+
},
|
|
603
|
+
nextWeek: nextWeekImpl,
|
|
604
|
+
previousWeek: previousWeekImpl,
|
|
605
|
+
nextDay: nextDayImpl,
|
|
606
|
+
previousDay: previousDayImpl,
|
|
607
|
+
goToToday() {
|
|
608
|
+
setStateImpl(() => ({
|
|
609
|
+
referenceDate: import_polyfill6.Temporal.Now.plainDateISO()
|
|
610
|
+
}));
|
|
611
|
+
},
|
|
612
|
+
goToDate(date) {
|
|
613
|
+
setStateImpl(() => ({
|
|
614
|
+
referenceDate: date
|
|
615
|
+
}));
|
|
616
|
+
},
|
|
617
|
+
next(view) {
|
|
618
|
+
switch (view) {
|
|
619
|
+
case "month":
|
|
620
|
+
nextMonthImpl();
|
|
621
|
+
break;
|
|
622
|
+
case "week":
|
|
623
|
+
nextWeekImpl();
|
|
624
|
+
break;
|
|
625
|
+
case "day":
|
|
626
|
+
nextDayImpl();
|
|
627
|
+
break;
|
|
628
|
+
}
|
|
629
|
+
},
|
|
630
|
+
previous(view) {
|
|
631
|
+
switch (view) {
|
|
632
|
+
case "month":
|
|
633
|
+
previousMonthImpl();
|
|
634
|
+
break;
|
|
635
|
+
case "week":
|
|
636
|
+
previousWeekImpl();
|
|
637
|
+
break;
|
|
638
|
+
case "day":
|
|
639
|
+
previousDayImpl();
|
|
640
|
+
break;
|
|
641
|
+
}
|
|
642
|
+
},
|
|
643
|
+
get views() {
|
|
644
|
+
return configuredViews;
|
|
645
|
+
},
|
|
646
|
+
get currentView() {
|
|
647
|
+
return store.state.currentView || defaultView;
|
|
648
|
+
},
|
|
649
|
+
setCurrentView(view) {
|
|
650
|
+
setStateImpl((old) => ({
|
|
651
|
+
...old,
|
|
652
|
+
currentView: view
|
|
653
|
+
}));
|
|
654
|
+
},
|
|
655
|
+
get dateRange() {
|
|
656
|
+
return store.state.dateRange;
|
|
657
|
+
},
|
|
658
|
+
get options() {
|
|
659
|
+
return _options;
|
|
660
|
+
},
|
|
661
|
+
setOptions(updater) {
|
|
662
|
+
_options = functionalUpdate(updater, _options);
|
|
663
|
+
},
|
|
664
|
+
store
|
|
665
|
+
};
|
|
666
|
+
return calendar;
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
// src/createCalendarViews.ts
|
|
670
|
+
function createCalendarViews() {
|
|
671
|
+
return (views) => {
|
|
672
|
+
return views;
|
|
673
|
+
};
|
|
674
|
+
}
|
|
675
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
676
|
+
0 && (module.exports = {
|
|
677
|
+
buildDay,
|
|
678
|
+
buildMonth,
|
|
679
|
+
buildWeek,
|
|
680
|
+
convertToTimezone,
|
|
681
|
+
createCalendar,
|
|
682
|
+
createCalendarAccessor,
|
|
683
|
+
createCalendarViews,
|
|
684
|
+
createZonedDateTime,
|
|
685
|
+
formatTime,
|
|
686
|
+
functionalUpdate,
|
|
687
|
+
getCurrentTimeZone,
|
|
688
|
+
getDayDateRange,
|
|
689
|
+
getDayRange,
|
|
690
|
+
getEventPosition,
|
|
691
|
+
getMonthDateRange,
|
|
692
|
+
getMonthName,
|
|
693
|
+
getMonthRange,
|
|
694
|
+
getTimeSlotHeight,
|
|
695
|
+
getTimezoneOffset,
|
|
696
|
+
getWeekDateRange,
|
|
697
|
+
getWeekRange,
|
|
698
|
+
getWeekdays,
|
|
699
|
+
goToToday,
|
|
700
|
+
nextDay,
|
|
701
|
+
nextMonth,
|
|
702
|
+
nextWeek,
|
|
703
|
+
previousDay,
|
|
704
|
+
previousMonth,
|
|
705
|
+
previousWeek
|
|
706
|
+
});
|