@mantine/schedule 9.5.1-alpha.1 → 9.5.2
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/cjs/components/WeekView/get-week-view-events/find-available-column.cjs +5 -10
- package/cjs/components/WeekView/get-week-view-events/find-available-column.cjs.map +1 -1
- package/cjs/components/WeekView/get-week-view-events/get-week-positioned-events.cjs +5 -3
- package/cjs/components/WeekView/get-week-view-events/get-week-positioned-events.cjs.map +1 -1
- package/cjs/components/YearView/YearView.cjs +2 -1
- package/cjs/components/YearView/YearView.cjs.map +1 -1
- package/cjs/components/YearView/YearViewMonth.cjs +9 -9
- package/cjs/components/YearView/YearViewMonth.cjs.map +1 -1
- package/cjs/utils/expand-recurring-events/expand-recurring-events.cjs +20 -8
- package/cjs/utils/expand-recurring-events/expand-recurring-events.cjs.map +1 -1
- package/cjs/utils/is-events-overlap/is-events-overlap.cjs +16 -4
- package/cjs/utils/is-events-overlap/is-events-overlap.cjs.map +1 -1
- package/esm/components/WeekView/get-week-view-events/find-available-column.mjs +5 -10
- package/esm/components/WeekView/get-week-view-events/find-available-column.mjs.map +1 -1
- package/esm/components/WeekView/get-week-view-events/get-week-positioned-events.mjs +5 -3
- package/esm/components/WeekView/get-week-view-events/get-week-positioned-events.mjs.map +1 -1
- package/esm/components/YearView/YearView.mjs +2 -1
- package/esm/components/YearView/YearView.mjs.map +1 -1
- package/esm/components/YearView/YearViewMonth.mjs +10 -10
- package/esm/components/YearView/YearViewMonth.mjs.map +1 -1
- package/esm/utils/expand-recurring-events/expand-recurring-events.mjs +20 -8
- package/esm/utils/expand-recurring-events/expand-recurring-events.mjs.map +1 -1
- package/esm/utils/is-events-overlap/is-events-overlap.mjs +16 -4
- package/esm/utils/is-events-overlap/is-events-overlap.mjs.map +1 -1
- package/lib/components/WeekView/get-week-view-events/find-available-column.d.ts +7 -3
- package/lib/components/YearView/YearViewMonth.d.ts +9 -2
- package/lib/components/YearView/index.d.ts +1 -0
- package/package.json +4 -4
|
@@ -1,18 +1,13 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
const require_is_all_day_event = require("../../../utils/is-all-day-event/is-all-day-event.cjs");
|
|
3
2
|
const require_is_events_overlap = require("../../../utils/is-events-overlap/is-events-overlap.cjs");
|
|
4
3
|
//#region packages/@mantine/schedule/src/components/WeekView/get-week-view-events/find-available-column.ts
|
|
5
|
-
function columnHasConflict({ columns, columnIndex, event, allDay
|
|
4
|
+
function columnHasConflict({ columns, columnIndex, event, allDay }) {
|
|
6
5
|
const columnKey = `col-${columnIndex}`;
|
|
7
6
|
if (!columns.has(columnKey)) return false;
|
|
8
|
-
return columns.get(columnKey).some((
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}));
|
|
13
|
-
const hasTimeConflict = require_is_events_overlap.isEventsOverlap(e, event);
|
|
14
|
-
if (allDay && eAllDay) return hasTimeConflict;
|
|
15
|
-
if (allDay || eAllDay) return false;
|
|
7
|
+
return columns.get(columnKey).some((columnEvent) => {
|
|
8
|
+
const hasTimeConflict = require_is_events_overlap.isEventsOverlap(columnEvent.event, event);
|
|
9
|
+
if (allDay && columnEvent.allDay) return hasTimeConflict;
|
|
10
|
+
if (allDay || columnEvent.allDay) return false;
|
|
16
11
|
return hasTimeConflict;
|
|
17
12
|
});
|
|
18
13
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"find-available-column.cjs","names":["
|
|
1
|
+
{"version":3,"file":"find-available-column.cjs","names":["isEventsOverlap"],"sources":["../../../../src/components/WeekView/get-week-view-events/find-available-column.ts"],"sourcesContent":["import { ScheduleEventData } from '../../../types';\nimport { isEventsOverlap } from '../../../utils';\n\n/** An event stored in a positioning column together with its precomputed all-day flag. */\nexport interface ColumnEvent {\n event: ScheduleEventData;\n allDay: boolean;\n}\n\ninterface FindAvailableColumnInput {\n columns: Map<string, ColumnEvent[]>;\n event: ScheduleEventData;\n allDay: boolean;\n}\n\nfunction columnHasConflict({\n columns,\n columnIndex,\n event,\n allDay,\n}: FindAvailableColumnInput & { columnIndex: number }): boolean {\n const columnKey = `col-${columnIndex}`;\n if (!columns.has(columnKey)) {\n return false;\n }\n\n const columnEvents = columns.get(columnKey)!;\n\n return columnEvents.some((columnEvent) => {\n const hasTimeConflict = isEventsOverlap(columnEvent.event, event);\n\n if (allDay && columnEvent.allDay) {\n return hasTimeConflict;\n }\n\n if (allDay || columnEvent.allDay) {\n return false;\n }\n\n return hasTimeConflict;\n });\n}\n\nexport function findAvailableColumn(input: FindAvailableColumnInput): number {\n let column = 0;\n\n while (columnHasConflict({ ...input, columnIndex: column })) {\n column++;\n }\n\n return column;\n}\n"],"mappings":";;;AAeA,SAAS,kBAAkB,EACzB,SACA,aACA,OACA,UAC8D;CAC9D,MAAM,YAAY,OAAO;CACzB,IAAI,CAAC,QAAQ,IAAI,SAAS,GACxB,OAAO;CAKT,OAFqB,QAAQ,IAAI,SAEf,CAAC,CAAC,MAAM,gBAAgB;EACxC,MAAM,kBAAkBA,0BAAAA,gBAAgB,YAAY,OAAO,KAAK;EAEhE,IAAI,UAAU,YAAY,QACxB,OAAO;EAGT,IAAI,UAAU,YAAY,QACxB,OAAO;EAGT,OAAO;CACT,CAAC;AACH;AAEA,SAAgB,oBAAoB,OAAyC;CAC3E,IAAI,SAAS;CAEb,OAAO,kBAAkB;EAAE,GAAG;EAAO,aAAa;CAAO,CAAC,GACxD;CAGF,OAAO;AACT"}
|
|
@@ -116,12 +116,14 @@ function getWeekPositionedEvents({ date, events, startTime, endTime, intervalMin
|
|
|
116
116
|
const column = require_find_available_column.findAvailableColumn({
|
|
117
117
|
columns: columnMap,
|
|
118
118
|
event,
|
|
119
|
-
allDay
|
|
120
|
-
allWeekDays: weekDays
|
|
119
|
+
allDay
|
|
121
120
|
});
|
|
122
121
|
const columnKey = `col-${column}`;
|
|
123
122
|
if (!columnMap.has(columnKey)) columnMap.set(columnKey, []);
|
|
124
|
-
columnMap.get(columnKey).push(
|
|
123
|
+
columnMap.get(columnKey).push({
|
|
124
|
+
event,
|
|
125
|
+
allDay: isActuallyAllDay
|
|
126
|
+
});
|
|
125
127
|
const verticalPosition = allDay ? {
|
|
126
128
|
top: 0,
|
|
127
129
|
height: 100
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-week-positioned-events.cjs","names":["getWeekDays","sortEvents","getEventEndDate","calculateEventDays","getHangingStatus","isAllDayEvent","getDayPosition","findAvailableColumn","calculateAllDayEventOffset","assignEventRows","calculateAllDayEventWidth"],"sources":["../../../../src/components/WeekView/get-week-view-events/get-week-positioned-events.ts"],"sourcesContent":["import dayjs from 'dayjs';\nimport {\n AnyDateValue,\n DateStringValue,\n DayOfWeek,\n ScheduleEventData,\n WeekPositionedEventData,\n} from '../../../types';\nimport { getDayPosition, getWeekDays, isAllDayEvent, sortEvents } from '../../../utils';\nimport { assignEventRows } from './assign-event-rows';\nimport { calculateAllDayEventOffset } from './calculate-all-day-event-offset';\nimport { calculateAllDayEventWidth } from './calculate-all-day-event-width';\nimport { calculateEventDays } from './calculate-event-days';\nimport { calculateRegularEventOverlaps } from './calculate-regular-event-overlaps';\nimport { findAvailableColumn } from './find-available-column';\nimport { getEventEndDate } from './get-event-end-date';\nimport { getHangingStatus } from './get-hanging-status';\n\nexport interface GetWeekPositionedEventsInput {\n /** Date (week start) at which events are positioned, used to check if events are all-day */\n date: AnyDateValue;\n\n /** List of all events that belong to the given week, extra events must be filtered out before passing to the function */\n events: ScheduleEventData[];\n\n /** Start time of the week view, used to calculate event positions */\n startTime?: string;\n\n /** End time of the week view, used to calculate event positions */\n endTime?: string;\n\n /** Number of minutes per time slot, used to align the canvas to whole slots */\n intervalMinutes?: number;\n\n /** First day of the week, 0 - Sunday, 1 - Monday, etc., used to calculate events positions */\n firstDayOfWeek?: DayOfWeek;\n\n /** Indices of weekend days, 0-6, where 0 is Sunday and 6 is Saturday */\n weekendDays?: DayOfWeek[];\n\n /** If set to false, weekend days are hidden @default true */\n withWeekendDays?: boolean;\n}\n\n/** Events grouped by week day date (YYYY-MM-DD 00:00:00) and by columns */\nexport interface GroupedWeekEvents {\n allDayEvents: WeekPositionedEventData[];\n regularEvents: Record<DateStringValue, WeekPositionedEventData[]>;\n backgroundEvents: Record<DateStringValue, WeekPositionedEventData[]>;\n}\n\nexport function getWeekPositionedEvents({\n date,\n events,\n startTime,\n endTime,\n intervalMinutes,\n firstDayOfWeek = 1,\n weekendDays = [0, 6],\n withWeekendDays = true,\n}: GetWeekPositionedEventsInput): GroupedWeekEvents {\n const weekDays = getWeekDays({ week: date, firstDayOfWeek, withWeekendDays, weekendDays });\n const visibleDaysCount = weekDays.length;\n const weekStartDate = dayjs(weekDays[0]);\n const weekEndDate = dayjs(weekDays[weekDays.length - 1]);\n\n const grouped: GroupedWeekEvents = {\n allDayEvents: [],\n regularEvents: Object.fromEntries(weekDays.map((day) => [day, []])),\n backgroundEvents: Object.fromEntries(weekDays.map((day) => [day, []])),\n };\n\n const columns = new Map<string, ScheduleEventData[]>();\n const allDayColumns = new Map<string, ScheduleEventData[]>();\n const sorted = sortEvents(events);\n\n for (const event of sorted) {\n if (event.display === 'background') {\n const eventStartDate = dayjs(event.start).startOf('day');\n const actualEndDate = getEventEndDate(event);\n const eventWeekDays = calculateEventDays({ event, weekDays, actualEndDate });\n const hanging = getHangingStatus({ eventStartDate, actualEndDate, weekDays });\n\n for (const day of eventWeekDays) {\n const visibleDayIndex = weekDays.indexOf(day);\n if (visibleDayIndex === -1) {\n continue;\n }\n\n const dayStart = dayjs(day);\n const dayEnd = dayStart.endOf('day');\n const eventStart = dayjs(event.start);\n const eventEnd = dayjs(event.end);\n\n const clippedStart = eventStart.isBefore(dayStart) ? dayStart : eventStart;\n const clippedEnd = eventEnd.isAfter(dayEnd) ? dayEnd : eventEnd;\n\n const clippedEvent = {\n ...event,\n start: clippedStart.format('YYYY-MM-DD HH:mm:ss'),\n end: clippedEnd.format('YYYY-MM-DD HH:mm:ss'),\n };\n\n const isAllDay = isAllDayEvent({ event: clippedEvent, date: day });\n const verticalPosition = isAllDay\n ? { top: 0, height: 100 }\n : getDayPosition({ event: clippedEvent, startTime, endTime, intervalMinutes });\n\n if (!isAllDay && verticalPosition.height <= 0) {\n continue;\n }\n\n const dayWeekOffset = (visibleDayIndex / visibleDaysCount) * 100;\n\n grouped.backgroundEvents[day].push({\n ...event,\n position: {\n ...verticalPosition,\n allDay: isAllDay,\n column: 0,\n width: 100,\n offset: 0,\n overlaps: 1,\n weekOffset: dayWeekOffset,\n row: 0,\n hanging,\n },\n });\n }\n\n continue;\n }\n const eventStartDate = dayjs(event.start).startOf('day');\n const actualEndDate = getEventEndDate(event);\n const eventWeekDays = calculateEventDays({ event, weekDays, actualEndDate });\n\n if (eventWeekDays.length === 0) {\n continue;\n }\n\n const isMultiday = actualEndDate.isAfter(eventStartDate);\n const hanging = getHangingStatus({ eventStartDate, actualEndDate, weekDays });\n const isActuallyAllDay = eventWeekDays.some((day) => isAllDayEvent({ event, date: day }));\n const allDay = isMultiday || isActuallyAllDay;\n\n const columnMap = allDay ? allDayColumns : columns;\n const column = findAvailableColumn({\n columns: columnMap,\n event,\n allDay,\n allWeekDays: weekDays,\n });\n\n const columnKey = `col-${column}`;\n if (!columnMap.has(columnKey)) {\n columnMap.set(columnKey, []);\n }\n columnMap.get(columnKey)!.push(event);\n\n const verticalPosition = allDay\n ? { top: 0, height: 100 }\n : getDayPosition({ event, startTime, endTime, intervalMinutes });\n\n if (allDay) {\n const offset = calculateAllDayEventOffset({\n eventStartDate,\n weekStartDate,\n weekDays,\n visibleDaysCount,\n hangingStart: hanging === 'start' || hanging === 'both',\n });\n\n grouped.allDayEvents.push({\n ...event,\n position: {\n ...verticalPosition,\n allDay,\n column,\n width: 0,\n offset,\n overlaps: 0,\n row: 0,\n hanging,\n },\n });\n } else {\n for (const day of eventWeekDays) {\n const visibleDayIndex = weekDays.indexOf(day);\n\n if (visibleDayIndex === -1) {\n continue;\n }\n\n const dayWeekOffset = (visibleDayIndex / visibleDaysCount) * 100;\n\n grouped.regularEvents[day].push({\n ...event,\n position: {\n ...verticalPosition,\n allDay,\n column,\n width: 0,\n offset: 0,\n overlaps: 0,\n weekOffset: dayWeekOffset,\n row: 0,\n hanging,\n },\n });\n }\n }\n }\n\n for (const day of weekDays) {\n calculateRegularEventOverlaps(grouped.regularEvents[day]);\n }\n\n if (grouped.allDayEvents.length > 0) {\n const eventRows = assignEventRows(grouped.allDayEvents);\n const assignedRows = new Set<number>();\n\n for (const event of grouped.allDayEvents) {\n const row = eventRows.get(event)!;\n event.position.row = row;\n assignedRows.add(row);\n }\n\n const rowCount = Math.max(...assignedRows) + 1;\n\n for (const event of grouped.allDayEvents) {\n const eventStartDate = dayjs(event.start).startOf('day');\n const actualEndDate = getEventEndDate(event);\n\n event.position.width = calculateAllDayEventWidth({\n eventStartDate,\n actualEndDate,\n weekStartDate,\n weekEndDate,\n weekDays,\n visibleDaysCount,\n });\n\n event.position.overlaps = rowCount;\n }\n }\n\n return grouped;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"get-week-positioned-events.cjs","names":["getWeekDays","sortEvents","getEventEndDate","calculateEventDays","getHangingStatus","isAllDayEvent","getDayPosition","findAvailableColumn","calculateAllDayEventOffset","assignEventRows","calculateAllDayEventWidth"],"sources":["../../../../src/components/WeekView/get-week-view-events/get-week-positioned-events.ts"],"sourcesContent":["import dayjs from 'dayjs';\nimport {\n AnyDateValue,\n DateStringValue,\n DayOfWeek,\n ScheduleEventData,\n WeekPositionedEventData,\n} from '../../../types';\nimport { getDayPosition, getWeekDays, isAllDayEvent, sortEvents } from '../../../utils';\nimport { assignEventRows } from './assign-event-rows';\nimport { calculateAllDayEventOffset } from './calculate-all-day-event-offset';\nimport { calculateAllDayEventWidth } from './calculate-all-day-event-width';\nimport { calculateEventDays } from './calculate-event-days';\nimport { calculateRegularEventOverlaps } from './calculate-regular-event-overlaps';\nimport { ColumnEvent, findAvailableColumn } from './find-available-column';\nimport { getEventEndDate } from './get-event-end-date';\nimport { getHangingStatus } from './get-hanging-status';\n\nexport interface GetWeekPositionedEventsInput {\n /** Date (week start) at which events are positioned, used to check if events are all-day */\n date: AnyDateValue;\n\n /** List of all events that belong to the given week, extra events must be filtered out before passing to the function */\n events: ScheduleEventData[];\n\n /** Start time of the week view, used to calculate event positions */\n startTime?: string;\n\n /** End time of the week view, used to calculate event positions */\n endTime?: string;\n\n /** Number of minutes per time slot, used to align the canvas to whole slots */\n intervalMinutes?: number;\n\n /** First day of the week, 0 - Sunday, 1 - Monday, etc., used to calculate events positions */\n firstDayOfWeek?: DayOfWeek;\n\n /** Indices of weekend days, 0-6, where 0 is Sunday and 6 is Saturday */\n weekendDays?: DayOfWeek[];\n\n /** If set to false, weekend days are hidden @default true */\n withWeekendDays?: boolean;\n}\n\n/** Events grouped by week day date (YYYY-MM-DD 00:00:00) and by columns */\nexport interface GroupedWeekEvents {\n allDayEvents: WeekPositionedEventData[];\n regularEvents: Record<DateStringValue, WeekPositionedEventData[]>;\n backgroundEvents: Record<DateStringValue, WeekPositionedEventData[]>;\n}\n\nexport function getWeekPositionedEvents({\n date,\n events,\n startTime,\n endTime,\n intervalMinutes,\n firstDayOfWeek = 1,\n weekendDays = [0, 6],\n withWeekendDays = true,\n}: GetWeekPositionedEventsInput): GroupedWeekEvents {\n const weekDays = getWeekDays({ week: date, firstDayOfWeek, withWeekendDays, weekendDays });\n const visibleDaysCount = weekDays.length;\n const weekStartDate = dayjs(weekDays[0]);\n const weekEndDate = dayjs(weekDays[weekDays.length - 1]);\n\n const grouped: GroupedWeekEvents = {\n allDayEvents: [],\n regularEvents: Object.fromEntries(weekDays.map((day) => [day, []])),\n backgroundEvents: Object.fromEntries(weekDays.map((day) => [day, []])),\n };\n\n const columns = new Map<string, ColumnEvent[]>();\n const allDayColumns = new Map<string, ColumnEvent[]>();\n const sorted = sortEvents(events);\n\n for (const event of sorted) {\n if (event.display === 'background') {\n const eventStartDate = dayjs(event.start).startOf('day');\n const actualEndDate = getEventEndDate(event);\n const eventWeekDays = calculateEventDays({ event, weekDays, actualEndDate });\n const hanging = getHangingStatus({ eventStartDate, actualEndDate, weekDays });\n\n for (const day of eventWeekDays) {\n const visibleDayIndex = weekDays.indexOf(day);\n if (visibleDayIndex === -1) {\n continue;\n }\n\n const dayStart = dayjs(day);\n const dayEnd = dayStart.endOf('day');\n const eventStart = dayjs(event.start);\n const eventEnd = dayjs(event.end);\n\n const clippedStart = eventStart.isBefore(dayStart) ? dayStart : eventStart;\n const clippedEnd = eventEnd.isAfter(dayEnd) ? dayEnd : eventEnd;\n\n const clippedEvent = {\n ...event,\n start: clippedStart.format('YYYY-MM-DD HH:mm:ss'),\n end: clippedEnd.format('YYYY-MM-DD HH:mm:ss'),\n };\n\n const isAllDay = isAllDayEvent({ event: clippedEvent, date: day });\n const verticalPosition = isAllDay\n ? { top: 0, height: 100 }\n : getDayPosition({ event: clippedEvent, startTime, endTime, intervalMinutes });\n\n if (!isAllDay && verticalPosition.height <= 0) {\n continue;\n }\n\n const dayWeekOffset = (visibleDayIndex / visibleDaysCount) * 100;\n\n grouped.backgroundEvents[day].push({\n ...event,\n position: {\n ...verticalPosition,\n allDay: isAllDay,\n column: 0,\n width: 100,\n offset: 0,\n overlaps: 1,\n weekOffset: dayWeekOffset,\n row: 0,\n hanging,\n },\n });\n }\n\n continue;\n }\n const eventStartDate = dayjs(event.start).startOf('day');\n const actualEndDate = getEventEndDate(event);\n const eventWeekDays = calculateEventDays({ event, weekDays, actualEndDate });\n\n if (eventWeekDays.length === 0) {\n continue;\n }\n\n const isMultiday = actualEndDate.isAfter(eventStartDate);\n const hanging = getHangingStatus({ eventStartDate, actualEndDate, weekDays });\n const isActuallyAllDay = eventWeekDays.some((day) => isAllDayEvent({ event, date: day }));\n const allDay = isMultiday || isActuallyAllDay;\n\n const columnMap = allDay ? allDayColumns : columns;\n const column = findAvailableColumn({\n columns: columnMap,\n event,\n allDay,\n });\n\n const columnKey = `col-${column}`;\n if (!columnMap.has(columnKey)) {\n columnMap.set(columnKey, []);\n }\n columnMap.get(columnKey)!.push({ event, allDay: isActuallyAllDay });\n\n const verticalPosition = allDay\n ? { top: 0, height: 100 }\n : getDayPosition({ event, startTime, endTime, intervalMinutes });\n\n if (allDay) {\n const offset = calculateAllDayEventOffset({\n eventStartDate,\n weekStartDate,\n weekDays,\n visibleDaysCount,\n hangingStart: hanging === 'start' || hanging === 'both',\n });\n\n grouped.allDayEvents.push({\n ...event,\n position: {\n ...verticalPosition,\n allDay,\n column,\n width: 0,\n offset,\n overlaps: 0,\n row: 0,\n hanging,\n },\n });\n } else {\n for (const day of eventWeekDays) {\n const visibleDayIndex = weekDays.indexOf(day);\n\n if (visibleDayIndex === -1) {\n continue;\n }\n\n const dayWeekOffset = (visibleDayIndex / visibleDaysCount) * 100;\n\n grouped.regularEvents[day].push({\n ...event,\n position: {\n ...verticalPosition,\n allDay,\n column,\n width: 0,\n offset: 0,\n overlaps: 0,\n weekOffset: dayWeekOffset,\n row: 0,\n hanging,\n },\n });\n }\n }\n }\n\n for (const day of weekDays) {\n calculateRegularEventOverlaps(grouped.regularEvents[day]);\n }\n\n if (grouped.allDayEvents.length > 0) {\n const eventRows = assignEventRows(grouped.allDayEvents);\n const assignedRows = new Set<number>();\n\n for (const event of grouped.allDayEvents) {\n const row = eventRows.get(event)!;\n event.position.row = row;\n assignedRows.add(row);\n }\n\n const rowCount = Math.max(...assignedRows) + 1;\n\n for (const event of grouped.allDayEvents) {\n const eventStartDate = dayjs(event.start).startOf('day');\n const actualEndDate = getEventEndDate(event);\n\n event.position.width = calculateAllDayEventWidth({\n eventStartDate,\n actualEndDate,\n weekStartDate,\n weekEndDate,\n weekDays,\n visibleDaysCount,\n });\n\n event.position.overlaps = rowCount;\n }\n }\n\n return grouped;\n}\n"],"mappings":"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"}
|
|
@@ -31,7 +31,7 @@ const defaultProps = {
|
|
|
31
31
|
const varsResolver = (0, _mantine_core.createVarsResolver)((_theme, { radius }) => ({ yearView: { "--year-view-radius": radius !== void 0 ? (0, _mantine_core.getRadius)(radius) : void 0 } }));
|
|
32
32
|
const YearView = (0, _mantine_core.factory)((_props) => {
|
|
33
33
|
const props = (0, _mantine_core.useProps)("YearView", defaultProps, _props);
|
|
34
|
-
const { date, onDateChange, events, monthLabelFormat, withWeekNumbers, withWeekDays, locale, firstDayOfWeek, weekdayFormat, weekendDays, withWeekendDays, onMonthClick, onDayClick, onWeekNumberClick, getDayProps, getWeekNumberProps, highlightToday, labels, withOutsideDays, withHeader, monthYearSelectProps, onViewChange, previousControlProps, nextControlProps, todayControlProps, viewSelectProps, __staticSelector, classNames, className, style, styles, unstyled, vars, attributes, radius, mode, recurrenceExpansionLimit, ...others } = props;
|
|
34
|
+
const { date, onDateChange, events, monthLabelFormat, withWeekNumbers, withWeekDays, locale, firstDayOfWeek, weekdayFormat, weekendDays, withWeekendDays, onMonthClick, onDayClick, onWeekNumberClick, getDayProps, getWeekNumberProps, highlightToday, labels, withOutsideDays, renderDay, withHeader, monthYearSelectProps, onViewChange, previousControlProps, nextControlProps, todayControlProps, viewSelectProps, __staticSelector, classNames, className, style, styles, unstyled, vars, attributes, radius, mode, recurrenceExpansionLimit, ...others } = props;
|
|
35
35
|
const ctx = (0, _mantine_dates.useDatesContext)();
|
|
36
36
|
const getStyles = (0, _mantine_core.useStyles)({
|
|
37
37
|
name: __staticSelector,
|
|
@@ -122,6 +122,7 @@ const YearView = (0, _mantine_core.factory)((_props) => {
|
|
|
122
122
|
groupedEvents,
|
|
123
123
|
mode,
|
|
124
124
|
withOutsideDays,
|
|
125
|
+
renderDay,
|
|
125
126
|
firstDayIndex: getFirstDayIndex(month),
|
|
126
127
|
__getDayRef: (weekIndex, dayIndex, node) => {
|
|
127
128
|
if (!Array.isArray(daysRef.current[currentMonthIndex])) daysRef.current[currentMonthIndex] = [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"YearView.cjs","names":["getYearViewEvents","expandRecurringEvents","getHiddenWeekendColumns","getMonthDays","getVisibleWeekDays","isSameMonth","getMonthsByQuarter","YearViewMonth","Box","ScheduleHeaderBase","toDateString","classes"],"sources":["../../../src/components/YearView/YearView.tsx"],"sourcesContent":["import dayjs from 'dayjs';\nimport { useRef } from 'react';\nimport {\n Box,\n BoxProps,\n createVarsResolver,\n DataAttributes,\n ElementProps,\n factory,\n Factory,\n getRadius,\n MantineRadius,\n StylesApiProps,\n useProps,\n useResolvedStylesApi,\n useStyles,\n} from '@mantine/core';\nimport { useDatesContext } from '@mantine/dates';\nimport { DateStringValue, ScheduleEventData, ScheduleMode, ScheduleViewLevel } from '../../types';\nimport {\n expandRecurringEvents,\n getMonthDays,\n getMonthsByQuarter,\n isSameMonth,\n toDateString,\n} from '../../utils';\nimport { MonthYearSelectProps } from '../ScheduleHeader/MonthYearSelect/MonthYearSelect';\nimport { CombinedScheduleHeaderStylesNames } from '../ScheduleHeader/ScheduleHeader';\nimport { ScheduleHeaderBase } from '../ScheduleHeader/ScheduleHeaderBase';\nimport { ViewSelectProps } from '../ScheduleHeader/ViewSelect/ViewSelect';\nimport { getHiddenWeekendColumns, getVisibleWeekDays } from './get-visible-week-days';\nimport { getYearViewEvents } from './get-year-view-events/get-year-view-events';\nimport { handleYearViewKeyDown, YearViewControlsRef } from './handle-year-view-key-down';\nimport { YearViewMonth, YearViewMonthSettings } from './YearViewMonth';\nimport classes from './YearView.module.css';\n\nexport type YearViewStylesNames =\n | 'yearView'\n | 'yearViewMonths'\n | 'yearViewMonth'\n | 'yearViewWeekday'\n | 'yearViewDay'\n | 'yearViewWeek'\n | 'yearViewWeekNumber'\n | 'yearViewWeekdays'\n | 'yearViewWeekdaysCorner'\n | 'yearViewMonthCaption'\n | 'yearViewDayIndicators'\n | 'yearViewDayIndicator'\n | CombinedScheduleHeaderStylesNames;\n\nexport type YearViewCssVariables = {\n yearView: '--year-view-radius';\n};\n\nexport interface YearViewProps\n extends YearViewMonthSettings, BoxProps, StylesApiProps<YearViewFactory>, ElementProps<'div'> {\n __staticSelector?: string;\n\n /** Date to display, Date object or date string in `YYYY-MM-DD 00:00:00` format */\n date: Date | string;\n\n /** Called with the new date value when a date is selected */\n onDateChange?: (value: DateStringValue) => void;\n\n /** Events to display, must be a stable reference */\n events?: ScheduleEventData[];\n\n /** Key of `theme.radius` or any valid CSS value to set `border-radius` @default theme.defaultRadius */\n radius?: MantineRadius;\n\n /** If set, highlights the current day @default true */\n highlightToday?: boolean;\n\n /** If set, the header is displayed @default true */\n withHeader?: boolean;\n\n /** Props passed down to `MonthYearSelect` component in the header */\n monthYearSelectProps?: Partial<MonthYearSelectProps>;\n\n /** Called when view level select button is clicked */\n onViewChange?: (view: ScheduleViewLevel) => void;\n\n /** Props passed to previous month control */\n previousControlProps?: React.ComponentProps<'button'> & DataAttributes;\n\n /** Props passed to next month control */\n nextControlProps?: React.ComponentProps<'button'> & DataAttributes;\n\n /** Props passed to today control */\n todayControlProps?: React.ComponentProps<'button'> & DataAttributes;\n\n /** Props passed to view level select */\n viewSelectProps?: Partial<ViewSelectProps> & DataAttributes;\n\n /** Interaction mode: 'default' allows all interactions, 'static' disables event interactions @default default */\n mode?: ScheduleMode;\n\n /** Max number of generated recurring instances per recurring series @default 2000 */\n recurrenceExpansionLimit?: number;\n}\n\nexport type YearViewFactory = Factory<{\n props: YearViewProps;\n ref: HTMLDivElement;\n stylesNames: YearViewStylesNames;\n vars: YearViewCssVariables;\n}>;\n\nconst defaultProps = {\n __staticSelector: 'YearView',\n monthLabelFormat: 'MMMM',\n withWeekDays: true,\n withWeekendDays: true,\n highlightToday: true,\n withHeader: true,\n withOutsideDays: true,\n mode: 'default',\n} satisfies Partial<YearViewProps>;\n\nconst varsResolver = createVarsResolver<YearViewFactory>((_theme, { radius }) => ({\n yearView: { '--year-view-radius': radius !== undefined ? getRadius(radius) : undefined },\n}));\n\nexport const YearView = factory<YearViewFactory>((_props) => {\n const props = useProps('YearView', defaultProps, _props);\n const {\n // YearView props\n date,\n onDateChange,\n events,\n\n // YearViewMonth settings\n monthLabelFormat,\n withWeekNumbers,\n withWeekDays,\n locale,\n firstDayOfWeek,\n weekdayFormat,\n weekendDays,\n withWeekendDays,\n onMonthClick,\n onDayClick,\n onWeekNumberClick,\n getDayProps,\n getWeekNumberProps,\n highlightToday,\n labels,\n withOutsideDays,\n\n // ScheduleHeader props\n withHeader,\n monthYearSelectProps,\n onViewChange,\n previousControlProps,\n nextControlProps,\n todayControlProps,\n viewSelectProps,\n\n // System props\n __staticSelector,\n classNames,\n className,\n style,\n styles,\n unstyled,\n vars,\n attributes,\n radius,\n mode,\n recurrenceExpansionLimit,\n ...others\n } = props;\n\n const ctx = useDatesContext();\n\n const getStyles = useStyles<YearViewFactory>({\n name: __staticSelector,\n classes,\n props,\n className,\n style,\n classNames,\n styles,\n unstyled,\n vars,\n varsResolver,\n attributes,\n rootSelector: 'yearView',\n });\n\n const { resolvedClassNames, resolvedStyles } = useResolvedStylesApi<YearViewFactory>({\n classNames,\n styles,\n props,\n });\n\n const stylesApiProps = {\n classNames: resolvedClassNames,\n styles: resolvedStyles,\n attributes,\n __staticSelector,\n radius,\n };\n\n const expandedEvents = expandRecurringEvents({\n events,\n rangeStart: dayjs(date).startOf('year').toDate(),\n rangeEnd: dayjs(date).endOf('year').toDate(),\n expansionLimit: recurrenceExpansionLimit,\n });\n\n const groupedEvents = getYearViewEvents({ date, events: expandedEvents });\n\n // [monthIndex][weekIndex][dayIndex]\n const daysRef = useRef<HTMLButtonElement[][][]>([]) as YearViewControlsRef;\n\n const resolvedFirstDayOfWeek = ctx.getFirstDayOfWeek(firstDayOfWeek);\n const resolvedWeekendDays = ctx.getWeekendDays(weekendDays);\n const hiddenColumns = getHiddenWeekendColumns({\n weekendDays: resolvedWeekendDays,\n firstDayOfWeek: resolvedFirstDayOfWeek,\n withWeekendDays,\n });\n const columnsCount = 7 - hiddenColumns.length;\n\n const getFirstDayIndex = (month: string): { weekIndex: number; dayIndex: number } | undefined => {\n const weeks = getMonthDays({\n month: dayjs(month).format('YYYY-MM-DD'),\n firstDayOfWeek: resolvedFirstDayOfWeek,\n consistentWeeks: true,\n });\n\n for (let weekIndex = 0; weekIndex < weeks.length; weekIndex++) {\n const week = getVisibleWeekDays({\n week: weeks[weekIndex],\n weekendDays: resolvedWeekendDays,\n withWeekendDays,\n });\n\n for (let dayIndex = 0; dayIndex < week.length; dayIndex++) {\n const dayDate = week[dayIndex];\n if (isSameMonth(dayDate, month)) {\n return { weekIndex, dayIndex };\n }\n }\n }\n\n return undefined;\n };\n\n let globalMonthIndex = 0;\n const months = getMonthsByQuarter(dayjs(date).format('YYYY-MM-DD'))\n .flat()\n .map((month) => {\n const currentMonthIndex = globalMonthIndex;\n globalMonthIndex++;\n\n return (\n <YearViewMonth\n key={month}\n month={month}\n getStyles={getStyles}\n monthLabelFormat={monthLabelFormat}\n withWeekNumbers={withWeekNumbers}\n withWeekDays={withWeekDays}\n locale={locale}\n firstDayOfWeek={firstDayOfWeek}\n weekdayFormat={\n weekdayFormat ||\n ((date) => dayjs(date).locale(ctx.getLocale(locale)).format('dd').slice(0, 1))\n }\n weekendDays={weekendDays}\n withWeekendDays={withWeekendDays}\n getDayProps={getDayProps}\n getWeekNumberProps={getWeekNumberProps}\n onMonthClick={onMonthClick}\n onDayClick={onDayClick}\n onWeekNumberClick={onWeekNumberClick}\n highlightToday={highlightToday}\n groupedEvents={groupedEvents}\n mode={mode}\n withOutsideDays={withOutsideDays}\n firstDayIndex={getFirstDayIndex(month)}\n __getDayRef={(weekIndex, dayIndex, node) => {\n if (!Array.isArray(daysRef.current[currentMonthIndex])) {\n daysRef.current[currentMonthIndex] = [];\n }\n if (!Array.isArray(daysRef.current[currentMonthIndex][weekIndex])) {\n daysRef.current[currentMonthIndex][weekIndex] = [];\n }\n daysRef.current[currentMonthIndex][weekIndex][dayIndex] = node;\n }}\n __onDayKeyDown={(event, payload) => {\n handleYearViewKeyDown({\n controlsRef: daysRef,\n monthIndex: currentMonthIndex,\n weekIndex: payload.weekIndex,\n dayIndex: payload.dayIndex,\n event,\n });\n }}\n />\n );\n });\n\n return (\n <Box\n {...getStyles('yearView')}\n mod={{ static: mode === 'static', 'without-weekend-days': hiddenColumns.length > 0 }}\n __vars={hiddenColumns.length > 0 ? { '--year-view-columns': `${columnsCount}` } : undefined}\n {...others}\n >\n {withHeader && (\n <ScheduleHeaderBase\n view=\"year\"\n navigationHandlers={{\n previous: () => toDateString(dayjs(date).subtract(1, 'year').startOf('year')),\n next: () => toDateString(dayjs(date).add(1, 'year').startOf('year')),\n today: () => toDateString(dayjs()),\n }}\n control={{\n monthYearSelect: {\n locale,\n withMonths: false,\n yearValue: dayjs(date).get('year'),\n monthValue: dayjs(date).get('month'),\n onYearChange: (year) =>\n onDateChange?.(toDateString(dayjs(date).set('year', year).startOf('year'))),\n ...monthYearSelectProps,\n },\n }}\n labels={labels}\n onDateChange={onDateChange}\n onViewChange={onViewChange}\n previousControlProps={previousControlProps}\n nextControlProps={nextControlProps}\n todayControlProps={todayControlProps}\n viewSelectProps={viewSelectProps}\n stylesApiProps={stylesApiProps}\n />\n )}\n\n <div {...getStyles('yearViewMonths')}>{months}</div>\n </Box>\n );\n});\n\nYearView.displayName = '@mantine/schedule/YearView';\nYearView.classes = classes;\nYearView.varsResolver = varsResolver;\n\nexport namespace YearView {\n export type Props = YearViewProps;\n export type Factory = YearViewFactory;\n export type StylesNames = YearViewStylesNames;\n export type CssVariables = YearViewCssVariables;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"YearView.cjs","names":["getYearViewEvents","expandRecurringEvents","getHiddenWeekendColumns","getMonthDays","getVisibleWeekDays","isSameMonth","getMonthsByQuarter","YearViewMonth","Box","ScheduleHeaderBase","toDateString","classes"],"sources":["../../../src/components/YearView/YearView.tsx"],"sourcesContent":["import dayjs from 'dayjs';\nimport { useRef } from 'react';\nimport {\n Box,\n BoxProps,\n createVarsResolver,\n DataAttributes,\n ElementProps,\n factory,\n Factory,\n getRadius,\n MantineRadius,\n StylesApiProps,\n useProps,\n useResolvedStylesApi,\n useStyles,\n} from '@mantine/core';\nimport { useDatesContext } from '@mantine/dates';\nimport { DateStringValue, ScheduleEventData, ScheduleMode, ScheduleViewLevel } from '../../types';\nimport {\n expandRecurringEvents,\n getMonthDays,\n getMonthsByQuarter,\n isSameMonth,\n toDateString,\n} from '../../utils';\nimport { MonthYearSelectProps } from '../ScheduleHeader/MonthYearSelect/MonthYearSelect';\nimport { CombinedScheduleHeaderStylesNames } from '../ScheduleHeader/ScheduleHeader';\nimport { ScheduleHeaderBase } from '../ScheduleHeader/ScheduleHeaderBase';\nimport { ViewSelectProps } from '../ScheduleHeader/ViewSelect/ViewSelect';\nimport { getHiddenWeekendColumns, getVisibleWeekDays } from './get-visible-week-days';\nimport { getYearViewEvents } from './get-year-view-events/get-year-view-events';\nimport { handleYearViewKeyDown, YearViewControlsRef } from './handle-year-view-key-down';\nimport { YearViewMonth, YearViewMonthSettings } from './YearViewMonth';\nimport classes from './YearView.module.css';\n\nexport type YearViewStylesNames =\n | 'yearView'\n | 'yearViewMonths'\n | 'yearViewMonth'\n | 'yearViewWeekday'\n | 'yearViewDay'\n | 'yearViewWeek'\n | 'yearViewWeekNumber'\n | 'yearViewWeekdays'\n | 'yearViewWeekdaysCorner'\n | 'yearViewMonthCaption'\n | 'yearViewDayIndicators'\n | 'yearViewDayIndicator'\n | CombinedScheduleHeaderStylesNames;\n\nexport type YearViewCssVariables = {\n yearView: '--year-view-radius';\n};\n\nexport interface YearViewProps\n extends YearViewMonthSettings, BoxProps, StylesApiProps<YearViewFactory>, ElementProps<'div'> {\n __staticSelector?: string;\n\n /** Date to display, Date object or date string in `YYYY-MM-DD 00:00:00` format */\n date: Date | string;\n\n /** Called with the new date value when a date is selected */\n onDateChange?: (value: DateStringValue) => void;\n\n /** Events to display, must be a stable reference */\n events?: ScheduleEventData[];\n\n /** Key of `theme.radius` or any valid CSS value to set `border-radius` @default theme.defaultRadius */\n radius?: MantineRadius;\n\n /** If set, highlights the current day @default true */\n highlightToday?: boolean;\n\n /** If set, the header is displayed @default true */\n withHeader?: boolean;\n\n /** Props passed down to `MonthYearSelect` component in the header */\n monthYearSelectProps?: Partial<MonthYearSelectProps>;\n\n /** Called when view level select button is clicked */\n onViewChange?: (view: ScheduleViewLevel) => void;\n\n /** Props passed to previous month control */\n previousControlProps?: React.ComponentProps<'button'> & DataAttributes;\n\n /** Props passed to next month control */\n nextControlProps?: React.ComponentProps<'button'> & DataAttributes;\n\n /** Props passed to today control */\n todayControlProps?: React.ComponentProps<'button'> & DataAttributes;\n\n /** Props passed to view level select */\n viewSelectProps?: Partial<ViewSelectProps> & DataAttributes;\n\n /** Interaction mode: 'default' allows all interactions, 'static' disables event interactions @default default */\n mode?: ScheduleMode;\n\n /** Max number of generated recurring instances per recurring series @default 2000 */\n recurrenceExpansionLimit?: number;\n}\n\nexport type YearViewFactory = Factory<{\n props: YearViewProps;\n ref: HTMLDivElement;\n stylesNames: YearViewStylesNames;\n vars: YearViewCssVariables;\n}>;\n\nconst defaultProps = {\n __staticSelector: 'YearView',\n monthLabelFormat: 'MMMM',\n withWeekDays: true,\n withWeekendDays: true,\n highlightToday: true,\n withHeader: true,\n withOutsideDays: true,\n mode: 'default',\n} satisfies Partial<YearViewProps>;\n\nconst varsResolver = createVarsResolver<YearViewFactory>((_theme, { radius }) => ({\n yearView: { '--year-view-radius': radius !== undefined ? getRadius(radius) : undefined },\n}));\n\nexport const YearView = factory<YearViewFactory>((_props) => {\n const props = useProps('YearView', defaultProps, _props);\n const {\n // YearView props\n date,\n onDateChange,\n events,\n\n // YearViewMonth settings\n monthLabelFormat,\n withWeekNumbers,\n withWeekDays,\n locale,\n firstDayOfWeek,\n weekdayFormat,\n weekendDays,\n withWeekendDays,\n onMonthClick,\n onDayClick,\n onWeekNumberClick,\n getDayProps,\n getWeekNumberProps,\n highlightToday,\n labels,\n withOutsideDays,\n renderDay,\n\n // ScheduleHeader props\n withHeader,\n monthYearSelectProps,\n onViewChange,\n previousControlProps,\n nextControlProps,\n todayControlProps,\n viewSelectProps,\n\n // System props\n __staticSelector,\n classNames,\n className,\n style,\n styles,\n unstyled,\n vars,\n attributes,\n radius,\n mode,\n recurrenceExpansionLimit,\n ...others\n } = props;\n\n const ctx = useDatesContext();\n\n const getStyles = useStyles<YearViewFactory>({\n name: __staticSelector,\n classes,\n props,\n className,\n style,\n classNames,\n styles,\n unstyled,\n vars,\n varsResolver,\n attributes,\n rootSelector: 'yearView',\n });\n\n const { resolvedClassNames, resolvedStyles } = useResolvedStylesApi<YearViewFactory>({\n classNames,\n styles,\n props,\n });\n\n const stylesApiProps = {\n classNames: resolvedClassNames,\n styles: resolvedStyles,\n attributes,\n __staticSelector,\n radius,\n };\n\n const expandedEvents = expandRecurringEvents({\n events,\n rangeStart: dayjs(date).startOf('year').toDate(),\n rangeEnd: dayjs(date).endOf('year').toDate(),\n expansionLimit: recurrenceExpansionLimit,\n });\n\n const groupedEvents = getYearViewEvents({ date, events: expandedEvents });\n\n // [monthIndex][weekIndex][dayIndex]\n const daysRef = useRef<HTMLButtonElement[][][]>([]) as YearViewControlsRef;\n\n const resolvedFirstDayOfWeek = ctx.getFirstDayOfWeek(firstDayOfWeek);\n const resolvedWeekendDays = ctx.getWeekendDays(weekendDays);\n const hiddenColumns = getHiddenWeekendColumns({\n weekendDays: resolvedWeekendDays,\n firstDayOfWeek: resolvedFirstDayOfWeek,\n withWeekendDays,\n });\n const columnsCount = 7 - hiddenColumns.length;\n\n const getFirstDayIndex = (month: string): { weekIndex: number; dayIndex: number } | undefined => {\n const weeks = getMonthDays({\n month: dayjs(month).format('YYYY-MM-DD'),\n firstDayOfWeek: resolvedFirstDayOfWeek,\n consistentWeeks: true,\n });\n\n for (let weekIndex = 0; weekIndex < weeks.length; weekIndex++) {\n const week = getVisibleWeekDays({\n week: weeks[weekIndex],\n weekendDays: resolvedWeekendDays,\n withWeekendDays,\n });\n\n for (let dayIndex = 0; dayIndex < week.length; dayIndex++) {\n const dayDate = week[dayIndex];\n if (isSameMonth(dayDate, month)) {\n return { weekIndex, dayIndex };\n }\n }\n }\n\n return undefined;\n };\n\n let globalMonthIndex = 0;\n const months = getMonthsByQuarter(dayjs(date).format('YYYY-MM-DD'))\n .flat()\n .map((month) => {\n const currentMonthIndex = globalMonthIndex;\n globalMonthIndex++;\n\n return (\n <YearViewMonth\n key={month}\n month={month}\n getStyles={getStyles}\n monthLabelFormat={monthLabelFormat}\n withWeekNumbers={withWeekNumbers}\n withWeekDays={withWeekDays}\n locale={locale}\n firstDayOfWeek={firstDayOfWeek}\n weekdayFormat={\n weekdayFormat ||\n ((date) => dayjs(date).locale(ctx.getLocale(locale)).format('dd').slice(0, 1))\n }\n weekendDays={weekendDays}\n withWeekendDays={withWeekendDays}\n getDayProps={getDayProps}\n getWeekNumberProps={getWeekNumberProps}\n onMonthClick={onMonthClick}\n onDayClick={onDayClick}\n onWeekNumberClick={onWeekNumberClick}\n highlightToday={highlightToday}\n groupedEvents={groupedEvents}\n mode={mode}\n withOutsideDays={withOutsideDays}\n renderDay={renderDay}\n firstDayIndex={getFirstDayIndex(month)}\n __getDayRef={(weekIndex, dayIndex, node) => {\n if (!Array.isArray(daysRef.current[currentMonthIndex])) {\n daysRef.current[currentMonthIndex] = [];\n }\n if (!Array.isArray(daysRef.current[currentMonthIndex][weekIndex])) {\n daysRef.current[currentMonthIndex][weekIndex] = [];\n }\n daysRef.current[currentMonthIndex][weekIndex][dayIndex] = node;\n }}\n __onDayKeyDown={(event, payload) => {\n handleYearViewKeyDown({\n controlsRef: daysRef,\n monthIndex: currentMonthIndex,\n weekIndex: payload.weekIndex,\n dayIndex: payload.dayIndex,\n event,\n });\n }}\n />\n );\n });\n\n return (\n <Box\n {...getStyles('yearView')}\n mod={{ static: mode === 'static', 'without-weekend-days': hiddenColumns.length > 0 }}\n __vars={hiddenColumns.length > 0 ? { '--year-view-columns': `${columnsCount}` } : undefined}\n {...others}\n >\n {withHeader && (\n <ScheduleHeaderBase\n view=\"year\"\n navigationHandlers={{\n previous: () => toDateString(dayjs(date).subtract(1, 'year').startOf('year')),\n next: () => toDateString(dayjs(date).add(1, 'year').startOf('year')),\n today: () => toDateString(dayjs()),\n }}\n control={{\n monthYearSelect: {\n locale,\n withMonths: false,\n yearValue: dayjs(date).get('year'),\n monthValue: dayjs(date).get('month'),\n onYearChange: (year) =>\n onDateChange?.(toDateString(dayjs(date).set('year', year).startOf('year'))),\n ...monthYearSelectProps,\n },\n }}\n labels={labels}\n onDateChange={onDateChange}\n onViewChange={onViewChange}\n previousControlProps={previousControlProps}\n nextControlProps={nextControlProps}\n todayControlProps={todayControlProps}\n viewSelectProps={viewSelectProps}\n stylesApiProps={stylesApiProps}\n />\n )}\n\n <div {...getStyles('yearViewMonths')}>{months}</div>\n </Box>\n );\n});\n\nYearView.displayName = '@mantine/schedule/YearView';\nYearView.classes = classes;\nYearView.varsResolver = varsResolver;\n\nexport namespace YearView {\n export type Props = YearViewProps;\n export type Factory = YearViewFactory;\n export type StylesNames = YearViewStylesNames;\n export type CssVariables = YearViewCssVariables;\n}\n"],"mappings":"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"}
|
|
@@ -13,7 +13,7 @@ let react = require("react");
|
|
|
13
13
|
let _mantine_dates = require("@mantine/dates");
|
|
14
14
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
15
15
|
//#region packages/@mantine/schedule/src/components/YearView/YearViewMonth.tsx
|
|
16
|
-
function YearViewMonth({ month, getStyles, monthLabelFormat = "MMMM", withWeekNumbers, withWeekDays, locale, firstDayOfWeek, weekdayFormat, weekendDays, withWeekendDays, getDayProps, onDayClick, onWeekNumberClick, onMonthClick, getWeekNumberProps, highlightToday, groupedEvents, mode, withOutsideDays, __getDayRef, __onDayKeyDown, firstDayIndex }) {
|
|
16
|
+
function YearViewMonth({ month, getStyles, monthLabelFormat = "MMMM", withWeekNumbers, withWeekDays, locale, firstDayOfWeek, weekdayFormat, weekendDays, withWeekendDays, getDayProps, onDayClick, onWeekNumberClick, onMonthClick, getWeekNumberProps, highlightToday, groupedEvents, mode, withOutsideDays, renderDay, __getDayRef, __onDayKeyDown, firstDayIndex }) {
|
|
17
17
|
const ctx = (0, _mantine_dates.useDatesContext)();
|
|
18
18
|
const theme = (0, _mantine_core.useMantineTheme)();
|
|
19
19
|
const today = (0, dayjs.default)();
|
|
@@ -55,10 +55,13 @@ function YearViewMonth({ month, getStyles, monthLabelFormat = "MMMM", withWeekNu
|
|
|
55
55
|
const dayEvents = groupedEvents?.[(0, dayjs.default)(date).format("YYYY-MM-DD")] || [];
|
|
56
56
|
const isFirstDayOfMonth = firstDayIndex && weekIndex === firstDayIndex.weekIndex && dayIndex === firstDayIndex.dayIndex;
|
|
57
57
|
const isInTabOrder = mode !== "static" && !outside && isFirstDayOfMonth;
|
|
58
|
-
const
|
|
59
|
-
...getStyles("
|
|
60
|
-
|
|
61
|
-
|
|
58
|
+
const dayContent = typeof renderDay === "function" ? renderDay((0, dayjs.default)(date).format("YYYY-MM-DD"), dayEvents) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, dayjs.default)(date).format("D"), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
59
|
+
...getStyles("yearViewDayIndicators"),
|
|
60
|
+
children: dayEvents.slice(0, 3).map((event) => /* @__PURE__ */ (0, react.createElement)("div", {
|
|
61
|
+
...getStyles("yearViewDayIndicator", { style: { backgroundColor: (0, _mantine_core.getThemeColor)(event.color, theme) } }),
|
|
62
|
+
key: event.id
|
|
63
|
+
}))
|
|
64
|
+
})] });
|
|
62
65
|
return /* @__PURE__ */ (0, react.createElement)(_mantine_core.UnstyledButton, {
|
|
63
66
|
"aria-label": ariaLabel,
|
|
64
67
|
...dayProps,
|
|
@@ -89,10 +92,7 @@ function YearViewMonth({ month, getStyles, monthLabelFormat = "MMMM", withWeekNu
|
|
|
89
92
|
onDayClick?.((0, dayjs.default)(date).format("YYYY-MM-DD"), event);
|
|
90
93
|
dayProps.onClick?.(event);
|
|
91
94
|
}
|
|
92
|
-
},
|
|
93
|
-
...getStyles("yearViewDayIndicators"),
|
|
94
|
-
children: indicators
|
|
95
|
-
}));
|
|
95
|
+
}, dayContent);
|
|
96
96
|
});
|
|
97
97
|
const weekNumberProps = getWeekNumberProps?.((0, dayjs.default)(week[0]).format("YYYY-MM-DD")) || {};
|
|
98
98
|
const weekNumber = require_get_week_number.getWeekNumber(week);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"YearViewMonth.cjs","names":["getHiddenWeekendColumns","getWeekdaysNames","getMonthDays","getVisibleWeekDays","isSameMonth","UnstyledButton","getWeekNumber","Box","formatDate"],"sources":["../../../src/components/YearView/YearViewMonth.tsx"],"sourcesContent":["import dayjs from 'dayjs';\nimport { Box, GetStylesApi, getThemeColor, UnstyledButton, useMantineTheme } from '@mantine/core';\nimport { useDatesContext } from '@mantine/dates';\nimport { ScheduleLabelsOverride } from '../../labels';\nimport { DateLabelFormat, DateStringValue, DayOfWeek, ScheduleMode } from '../../types';\nimport {\n formatDate,\n getMonthDays,\n getWeekdaysNames,\n getWeekNumber,\n isSameMonth,\n} from '../../utils';\nimport { getHiddenWeekendColumns, getVisibleWeekDays } from './get-visible-week-days';\nimport { GroupedEvents } from './get-year-view-events/get-year-view-events';\nimport type { YearViewFactory } from './YearView';\n\nexport interface YearViewDayKeydownPayload {\n weekIndex: number;\n dayIndex: number;\n date: string;\n}\n\nexport interface YearViewMonthSettings {\n /** `dayjs` format for month label @default 'MMMM' */\n monthLabelFormat?: DateLabelFormat;\n\n /** If set, show week numbers */\n withWeekNumbers?: boolean;\n\n /** If set, weekdays names are displayed in the first row @default true */\n withWeekDays?: boolean;\n\n /** Locale passed down to dayjs, overrides value defined on `DatesProvider` */\n locale?: string;\n\n /** Number 0-6, where 0 – Sunday and 6 – Saturday @default 0 */\n firstDayOfWeek?: DayOfWeek;\n\n /** `dayjs` format for weekdays names @default 'd' */\n weekdayFormat?: DateLabelFormat;\n\n /** Indices of weekend days, 0-6, where 0 is Sunday and 6 is Saturday. The default value is defined by `DatesProvider`. */\n weekendDays?: DayOfWeek[];\n\n /** If set, weekend days are displayed. When `false`, weekend columns are hidden and the month grid shrinks. @default true */\n withWeekendDays?: boolean;\n\n /** Props passed down to the week number button */\n getWeekNumberProps?: (weekStartDate: DateStringValue) => Record<string, any>;\n\n /** Props passed down to the day button */\n getDayProps?: (date: DateStringValue) => Record<string, any>;\n\n /** Called when day is clicked */\n onDayClick?: (date: DateStringValue, event: React.MouseEvent<HTMLButtonElement>) => void;\n\n /** Called with first day of the week when week number is clicked */\n onWeekNumberClick?: (date: DateStringValue, event: React.MouseEvent<HTMLButtonElement>) => void;\n\n /** Called with the first day of the month when month label is clicked */\n onMonthClick?: (date: DateStringValue, event: React.MouseEvent<HTMLButtonElement>) => void;\n\n /** If set, highlights the current day @default true */\n highlightToday?: boolean;\n\n /** Labels override for i18n */\n labels?: ScheduleLabelsOverride;\n\n /** Interaction mode: 'default' allows all interactions, 'static' disables event interactions */\n mode?: ScheduleMode;\n\n /** If true, days from adjacent months are displayed @default true */\n withOutsideDays?: boolean;\n}\n\nexport interface YearViewMonthProps extends YearViewMonthSettings {\n /** Month to display, Date object or date string in `YYYY-MM-DD` format */\n month: Date | string;\n\n /** `useStyles` return value of `YearView` */\n getStyles: GetStylesApi<YearViewFactory>;\n\n /** Events grouped by date */\n groupedEvents?: GroupedEvents;\n\n /** Assigns ref of every day based on its position in the month, used for keyboard navigation */\n __getDayRef?: (weekIndex: number, dayIndex: number, node: HTMLButtonElement) => void;\n\n /** Called when any keydown event is registered on day, used for keyboard navigation */\n __onDayKeyDown?: (\n event: React.KeyboardEvent<HTMLButtonElement>,\n payload: YearViewDayKeydownPayload\n ) => void;\n\n /** Index of the first day of the month in the grid (for determining which day should be in tab order) */\n firstDayIndex?: { weekIndex: number; dayIndex: number };\n}\n\nexport function YearViewMonth({\n month,\n getStyles,\n monthLabelFormat = 'MMMM',\n withWeekNumbers,\n withWeekDays,\n locale,\n firstDayOfWeek,\n weekdayFormat,\n weekendDays,\n withWeekendDays,\n getDayProps,\n onDayClick,\n onWeekNumberClick,\n onMonthClick,\n getWeekNumberProps,\n highlightToday,\n groupedEvents,\n mode,\n withOutsideDays,\n __getDayRef,\n __onDayKeyDown,\n firstDayIndex,\n}: YearViewMonthProps) {\n const ctx = useDatesContext();\n const theme = useMantineTheme();\n const today = dayjs();\n\n const resolvedFirstDayOfWeek = ctx.getFirstDayOfWeek(firstDayOfWeek);\n const resolvedWeekendDays = ctx.getWeekendDays(weekendDays);\n const hiddenColumns = new Set(\n getHiddenWeekendColumns({\n weekendDays: resolvedWeekendDays,\n firstDayOfWeek: resolvedFirstDayOfWeek,\n withWeekendDays,\n })\n );\n\n const weekdays = withWeekDays\n ? getWeekdaysNames({\n locale: ctx.getLocale(locale),\n format: weekdayFormat,\n firstDayOfWeek: resolvedFirstDayOfWeek,\n })\n .filter((_, index) => !hiddenColumns.has(index))\n .map((day, index) => (\n <div {...getStyles('yearViewWeekday')} key={index}>\n {day}\n </div>\n ))\n : null;\n\n const weeks = getMonthDays({\n month: dayjs(month).format('YYYY-MM-DD'),\n firstDayOfWeek: resolvedFirstDayOfWeek,\n consistentWeeks: true,\n }).map((week, weekIndex) => {\n const visibleDays = getVisibleWeekDays({\n week,\n weekendDays: resolvedWeekendDays,\n withWeekendDays,\n });\n\n const days = visibleDays.map((date, dayIndex) => {\n const outside = !isSameMonth(date, month);\n\n if (outside && !withOutsideDays) {\n return <div {...getStyles('yearViewDay')} data-day-placeholder key={date} />;\n }\n\n const weekend = resolvedWeekendDays.includes(dayjs(date).day() as DayOfWeek);\n const ariaLabel = dayjs(date)\n .locale(locale || ctx.locale)\n .format('MMMM D, YYYY');\n\n const dayProps = getDayProps?.(dayjs(date).format('YYYY-MM-DD')) || {};\n const isToday = dayjs(date).isSame(today, 'day') && highlightToday;\n const dayEvents = groupedEvents?.[dayjs(date).format('YYYY-MM-DD')] || [];\n\n // Determine if this day should be in the tab order\n // Only the first day of the month (not outside) should be focusable via tab\n const isFirstDayOfMonth =\n firstDayIndex &&\n weekIndex === firstDayIndex.weekIndex &&\n dayIndex === firstDayIndex.dayIndex;\n const isInTabOrder = mode !== 'static' && !outside && isFirstDayOfMonth;\n\n const indicators = dayEvents.slice(0, 3).map((event) => (\n <div\n {...getStyles('yearViewDayIndicator', {\n style: { backgroundColor: getThemeColor(event.color, theme) },\n })}\n key={event.id}\n />\n ));\n\n return (\n <UnstyledButton\n aria-label={ariaLabel}\n {...dayProps}\n {...getStyles('yearViewDay', { className: dayProps.className, style: dayProps.style })}\n key={date}\n mod={[{ outside, weekend, today: isToday, static: mode === 'static' }, dayProps.mod]}\n tabIndex={isInTabOrder ? 0 : -1}\n ref={(node) => {\n if (node) {\n __getDayRef?.(weekIndex, dayIndex, node);\n }\n }}\n onKeyDown={(event) => {\n dayProps.onKeyDown?.(event);\n __onDayKeyDown?.(event, { weekIndex, dayIndex, date });\n }}\n onClick={\n mode === 'static'\n ? undefined\n : (event) => {\n onDayClick?.(dayjs(date).format('YYYY-MM-DD'), event);\n dayProps.onClick?.(event);\n }\n }\n >\n {dayjs(date).format('D')}\n\n <div {...getStyles('yearViewDayIndicators')}>{indicators}</div>\n </UnstyledButton>\n );\n });\n\n const weekNumberProps = getWeekNumberProps?.(dayjs(week[0]).format('YYYY-MM-DD')) || {};\n const weekNumber = getWeekNumber(week);\n\n return (\n <div {...getStyles('yearViewWeek')} key={weekIndex}>\n {withWeekNumbers && (\n <UnstyledButton\n key={weekNumber}\n aria-label={`Week ${weekNumber}`}\n title={`Week ${weekNumber}`}\n {...weekNumberProps}\n onClick={\n mode === 'static'\n ? undefined\n : (event) => {\n onWeekNumberClick?.(dayjs(week[0]).format('YYYY-MM-DD'), event);\n weekNumberProps.onClick?.(event);\n }\n }\n mod={{ static: mode === 'static' }}\n tabIndex={mode === 'static' ? -1 : 0}\n {...getStyles('yearViewWeekNumber', {\n className: weekNumberProps.className,\n style: weekNumberProps.style,\n })}\n >\n {weekNumber}\n </UnstyledButton>\n )}\n\n {days}\n </div>\n );\n });\n\n return (\n <Box\n mod={[\n {\n 'with-week-numbers': withWeekNumbers,\n 'with-weekdays': withWeekDays,\n static: mode === 'static',\n },\n ]}\n {...getStyles('yearViewMonth')}\n >\n <UnstyledButton\n onClick={\n mode === 'static'\n ? undefined\n : (event) => onMonthClick?.(dayjs(month).startOf('month').format('YYYY-MM-DD'), event)\n }\n mod={{ static: mode === 'static' }}\n tabIndex={mode === 'static' ? -1 : 0}\n {...getStyles('yearViewMonthCaption')}\n >\n {formatDate({ locale: ctx.getLocale(locale), date: month, format: monthLabelFormat })}\n </UnstyledButton>\n\n {weekdays && (\n <div {...getStyles('yearViewWeekdays')}>\n {withWeekNumbers && <div {...getStyles('yearViewWeekdaysCorner')} />}\n {weekdays}\n </div>\n )}\n\n {weeks}\n </Box>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"YearViewMonth.cjs","names":["getHiddenWeekendColumns","getWeekdaysNames","getMonthDays","getVisibleWeekDays","isSameMonth","UnstyledButton","getWeekNumber","Box","formatDate"],"sources":["../../../src/components/YearView/YearViewMonth.tsx"],"sourcesContent":["import dayjs from 'dayjs';\nimport { Box, GetStylesApi, getThemeColor, UnstyledButton, useMantineTheme } from '@mantine/core';\nimport { useDatesContext } from '@mantine/dates';\nimport { ScheduleLabelsOverride } from '../../labels';\nimport {\n DateLabelFormat,\n DateStringValue,\n DayOfWeek,\n ScheduleEventData,\n ScheduleMode,\n} from '../../types';\nimport {\n formatDate,\n getMonthDays,\n getWeekdaysNames,\n getWeekNumber,\n isSameMonth,\n} from '../../utils';\nimport { getHiddenWeekendColumns, getVisibleWeekDays } from './get-visible-week-days';\nimport { GroupedEvents } from './get-year-view-events/get-year-view-events';\nimport type { YearViewFactory } from './YearView';\n\nexport type YearViewRenderDay = (\n date: DateStringValue,\n events: ScheduleEventData[]\n) => React.ReactNode;\n\nexport interface YearViewDayKeydownPayload {\n weekIndex: number;\n dayIndex: number;\n date: string;\n}\n\nexport interface YearViewMonthSettings {\n /** `dayjs` format for month label @default 'MMMM' */\n monthLabelFormat?: DateLabelFormat;\n\n /** If set, show week numbers */\n withWeekNumbers?: boolean;\n\n /** If set, weekdays names are displayed in the first row @default true */\n withWeekDays?: boolean;\n\n /** Locale passed down to dayjs, overrides value defined on `DatesProvider` */\n locale?: string;\n\n /** Number 0-6, where 0 – Sunday and 6 – Saturday @default 0 */\n firstDayOfWeek?: DayOfWeek;\n\n /** `dayjs` format for weekdays names @default 'd' */\n weekdayFormat?: DateLabelFormat;\n\n /** Indices of weekend days, 0-6, where 0 is Sunday and 6 is Saturday. The default value is defined by `DatesProvider`. */\n weekendDays?: DayOfWeek[];\n\n /** If set, weekend days are displayed. When `false`, weekend columns are hidden and the month grid shrinks. @default true */\n withWeekendDays?: boolean;\n\n /** Props passed down to the week number button */\n getWeekNumberProps?: (weekStartDate: DateStringValue) => Record<string, any>;\n\n /** Props passed down to the day button */\n getDayProps?: (date: DateStringValue) => Record<string, any>;\n\n /** Called when day is clicked */\n onDayClick?: (date: DateStringValue, event: React.MouseEvent<HTMLButtonElement>) => void;\n\n /** Called with first day of the week when week number is clicked */\n onWeekNumberClick?: (date: DateStringValue, event: React.MouseEvent<HTMLButtonElement>) => void;\n\n /** Called with the first day of the month when month label is clicked */\n onMonthClick?: (date: DateStringValue, event: React.MouseEvent<HTMLButtonElement>) => void;\n\n /** If set, highlights the current day @default true */\n highlightToday?: boolean;\n\n /** Labels override for i18n */\n labels?: ScheduleLabelsOverride;\n\n /** Interaction mode: 'default' allows all interactions, 'static' disables event interactions */\n mode?: ScheduleMode;\n\n /** If true, days from adjacent months are displayed @default true */\n withOutsideDays?: boolean;\n\n /**\n * A function to replace the entire content of a day cell, called with the day date\n * and the events grouped on that day – the same list that is used to render the default\n * indicators. When set, default event indicators are not rendered.\n */\n renderDay?: YearViewRenderDay;\n}\n\nexport interface YearViewMonthProps extends YearViewMonthSettings {\n /** Month to display, Date object or date string in `YYYY-MM-DD` format */\n month: Date | string;\n\n /** `useStyles` return value of `YearView` */\n getStyles: GetStylesApi<YearViewFactory>;\n\n /** Events grouped by date */\n groupedEvents?: GroupedEvents;\n\n /** Assigns ref of every day based on its position in the month, used for keyboard navigation */\n __getDayRef?: (weekIndex: number, dayIndex: number, node: HTMLButtonElement) => void;\n\n /** Called when any keydown event is registered on day, used for keyboard navigation */\n __onDayKeyDown?: (\n event: React.KeyboardEvent<HTMLButtonElement>,\n payload: YearViewDayKeydownPayload\n ) => void;\n\n /** Index of the first day of the month in the grid (for determining which day should be in tab order) */\n firstDayIndex?: { weekIndex: number; dayIndex: number };\n}\n\nexport function YearViewMonth({\n month,\n getStyles,\n monthLabelFormat = 'MMMM',\n withWeekNumbers,\n withWeekDays,\n locale,\n firstDayOfWeek,\n weekdayFormat,\n weekendDays,\n withWeekendDays,\n getDayProps,\n onDayClick,\n onWeekNumberClick,\n onMonthClick,\n getWeekNumberProps,\n highlightToday,\n groupedEvents,\n mode,\n withOutsideDays,\n renderDay,\n __getDayRef,\n __onDayKeyDown,\n firstDayIndex,\n}: YearViewMonthProps) {\n const ctx = useDatesContext();\n const theme = useMantineTheme();\n const today = dayjs();\n\n const resolvedFirstDayOfWeek = ctx.getFirstDayOfWeek(firstDayOfWeek);\n const resolvedWeekendDays = ctx.getWeekendDays(weekendDays);\n const hiddenColumns = new Set(\n getHiddenWeekendColumns({\n weekendDays: resolvedWeekendDays,\n firstDayOfWeek: resolvedFirstDayOfWeek,\n withWeekendDays,\n })\n );\n\n const weekdays = withWeekDays\n ? getWeekdaysNames({\n locale: ctx.getLocale(locale),\n format: weekdayFormat,\n firstDayOfWeek: resolvedFirstDayOfWeek,\n })\n .filter((_, index) => !hiddenColumns.has(index))\n .map((day, index) => (\n <div {...getStyles('yearViewWeekday')} key={index}>\n {day}\n </div>\n ))\n : null;\n\n const weeks = getMonthDays({\n month: dayjs(month).format('YYYY-MM-DD'),\n firstDayOfWeek: resolvedFirstDayOfWeek,\n consistentWeeks: true,\n }).map((week, weekIndex) => {\n const visibleDays = getVisibleWeekDays({\n week,\n weekendDays: resolvedWeekendDays,\n withWeekendDays,\n });\n\n const days = visibleDays.map((date, dayIndex) => {\n const outside = !isSameMonth(date, month);\n\n if (outside && !withOutsideDays) {\n return <div {...getStyles('yearViewDay')} data-day-placeholder key={date} />;\n }\n\n const weekend = resolvedWeekendDays.includes(dayjs(date).day() as DayOfWeek);\n const ariaLabel = dayjs(date)\n .locale(locale || ctx.locale)\n .format('MMMM D, YYYY');\n\n const dayProps = getDayProps?.(dayjs(date).format('YYYY-MM-DD')) || {};\n const isToday = dayjs(date).isSame(today, 'day') && highlightToday;\n const dayEvents = groupedEvents?.[dayjs(date).format('YYYY-MM-DD')] || [];\n\n // Determine if this day should be in the tab order\n // Only the first day of the month (not outside) should be focusable via tab\n const isFirstDayOfMonth =\n firstDayIndex &&\n weekIndex === firstDayIndex.weekIndex &&\n dayIndex === firstDayIndex.dayIndex;\n const isInTabOrder = mode !== 'static' && !outside && isFirstDayOfMonth;\n\n const dayContent =\n typeof renderDay === 'function' ? (\n renderDay(dayjs(date).format('YYYY-MM-DD'), dayEvents)\n ) : (\n <>\n {dayjs(date).format('D')}\n\n <div {...getStyles('yearViewDayIndicators')}>\n {dayEvents.slice(0, 3).map((event) => (\n <div\n {...getStyles('yearViewDayIndicator', {\n style: { backgroundColor: getThemeColor(event.color, theme) },\n })}\n key={event.id}\n />\n ))}\n </div>\n </>\n );\n\n return (\n <UnstyledButton\n aria-label={ariaLabel}\n {...dayProps}\n {...getStyles('yearViewDay', { className: dayProps.className, style: dayProps.style })}\n key={date}\n mod={[{ outside, weekend, today: isToday, static: mode === 'static' }, dayProps.mod]}\n tabIndex={isInTabOrder ? 0 : -1}\n ref={(node) => {\n if (node) {\n __getDayRef?.(weekIndex, dayIndex, node);\n }\n }}\n onKeyDown={(event) => {\n dayProps.onKeyDown?.(event);\n __onDayKeyDown?.(event, { weekIndex, dayIndex, date });\n }}\n onClick={\n mode === 'static'\n ? undefined\n : (event) => {\n onDayClick?.(dayjs(date).format('YYYY-MM-DD'), event);\n dayProps.onClick?.(event);\n }\n }\n >\n {dayContent}\n </UnstyledButton>\n );\n });\n\n const weekNumberProps = getWeekNumberProps?.(dayjs(week[0]).format('YYYY-MM-DD')) || {};\n const weekNumber = getWeekNumber(week);\n\n return (\n <div {...getStyles('yearViewWeek')} key={weekIndex}>\n {withWeekNumbers && (\n <UnstyledButton\n key={weekNumber}\n aria-label={`Week ${weekNumber}`}\n title={`Week ${weekNumber}`}\n {...weekNumberProps}\n onClick={\n mode === 'static'\n ? undefined\n : (event) => {\n onWeekNumberClick?.(dayjs(week[0]).format('YYYY-MM-DD'), event);\n weekNumberProps.onClick?.(event);\n }\n }\n mod={{ static: mode === 'static' }}\n tabIndex={mode === 'static' ? -1 : 0}\n {...getStyles('yearViewWeekNumber', {\n className: weekNumberProps.className,\n style: weekNumberProps.style,\n })}\n >\n {weekNumber}\n </UnstyledButton>\n )}\n\n {days}\n </div>\n );\n });\n\n return (\n <Box\n mod={[\n {\n 'with-week-numbers': withWeekNumbers,\n 'with-weekdays': withWeekDays,\n static: mode === 'static',\n },\n ]}\n {...getStyles('yearViewMonth')}\n >\n <UnstyledButton\n onClick={\n mode === 'static'\n ? undefined\n : (event) => onMonthClick?.(dayjs(month).startOf('month').format('YYYY-MM-DD'), event)\n }\n mod={{ static: mode === 'static' }}\n tabIndex={mode === 'static' ? -1 : 0}\n {...getStyles('yearViewMonthCaption')}\n >\n {formatDate({ locale: ctx.getLocale(locale), date: month, format: monthLabelFormat })}\n </UnstyledButton>\n\n {weekdays && (\n <div {...getStyles('yearViewWeekdays')}>\n {withWeekNumbers && <div {...getStyles('yearViewWeekdaysCorner')} />}\n {weekdays}\n </div>\n )}\n\n {weeks}\n </Box>\n );\n}\n"],"mappings":"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"}
|
|
@@ -18,6 +18,18 @@ function getExdateSet(recurrence) {
|
|
|
18
18
|
const values = recurrence.exdate.map((value) => (0, dayjs.default)(value)).filter((value) => value.isValid()).map((value) => value.format("YYYY-MM-DD HH:mm:ss"));
|
|
19
19
|
return new Set(values);
|
|
20
20
|
}
|
|
21
|
+
function toWallClockDate(value) {
|
|
22
|
+
return new Date(Date.UTC(value.year(), value.month(), value.date(), value.hour(), value.minute(), value.second(), value.millisecond()));
|
|
23
|
+
}
|
|
24
|
+
function fromWallClockDate(value) {
|
|
25
|
+
const result = new Date(2e3, 0, 1, 12);
|
|
26
|
+
result.setFullYear(value.getUTCFullYear(), value.getUTCMonth(), value.getUTCDate());
|
|
27
|
+
result.setHours(value.getUTCHours(), value.getUTCMinutes(), value.getUTCSeconds(), value.getUTCMilliseconds());
|
|
28
|
+
return (0, dayjs.default)(result);
|
|
29
|
+
}
|
|
30
|
+
function getWallClockDurationMs(start, end) {
|
|
31
|
+
return toWallClockDate(end).getTime() - toWallClockDate(start).getTime();
|
|
32
|
+
}
|
|
21
33
|
function getRRuleString(rule) {
|
|
22
34
|
const normalized = rule.trim();
|
|
23
35
|
if (!normalized.includes("\n")) return normalized.startsWith("RRULE:") ? normalized.replace(/^RRULE:/, "") : normalized;
|
|
@@ -29,10 +41,10 @@ function getOccurrenceStartsInRange(event, rangeStart, rangeEnd, expansionLimit,
|
|
|
29
41
|
if (!dtstart.isValid() || !event.recurrence) return [];
|
|
30
42
|
try {
|
|
31
43
|
const options = RRule.parseString(getRRuleString(event.recurrence.rrule));
|
|
32
|
-
options.dtstart = dtstart
|
|
44
|
+
options.dtstart = toWallClockDate(dtstart);
|
|
33
45
|
const rule = new RRule(options);
|
|
34
|
-
const searchStart = rangeStart.
|
|
35
|
-
return rule.between(searchStart, rangeEnd
|
|
46
|
+
const searchStart = new Date(toWallClockDate(rangeStart).getTime() - Math.max(0, durationMs));
|
|
47
|
+
return rule.between(searchStart, toWallClockDate(rangeEnd), true).slice(0, expansionLimit);
|
|
36
48
|
} catch {
|
|
37
49
|
return [];
|
|
38
50
|
}
|
|
@@ -43,8 +55,7 @@ function isEventInRange(event, rangeStart, rangeEnd) {
|
|
|
43
55
|
if (!start.isValid() || !end.isValid()) return false;
|
|
44
56
|
return overlapsRange(start, end, rangeStart, rangeEnd);
|
|
45
57
|
}
|
|
46
|
-
function createGeneratedInstance(event, occurrenceStart,
|
|
47
|
-
const occurrenceEnd = occurrenceStart.add(durationMs, "millisecond");
|
|
58
|
+
function createGeneratedInstance(event, occurrenceStart, occurrenceEnd) {
|
|
48
59
|
const recurrenceId = occurrenceStart.format("YYYY-MM-DD HH:mm:ss");
|
|
49
60
|
const { recurrence, ...eventWithoutRecurrence } = event;
|
|
50
61
|
return {
|
|
@@ -90,11 +101,12 @@ function expandRecurringEvents({ events, rangeStart, rangeEnd, expansionLimit =
|
|
|
90
101
|
const eventStart = (0, dayjs.default)(event.recurrence?.dtstart || event.start);
|
|
91
102
|
const eventEnd = (0, dayjs.default)(event.end);
|
|
92
103
|
if (!eventStart.isValid() || !eventEnd.isValid()) continue;
|
|
93
|
-
const durationMs =
|
|
104
|
+
const durationMs = getWallClockDurationMs((0, dayjs.default)(event.start), eventEnd);
|
|
94
105
|
if (durationMs < 0) continue;
|
|
95
106
|
const exdate = getExdateSet(event.recurrence);
|
|
96
107
|
const starts = getOccurrenceStartsInRange(event, start, end, expansionLimit, durationMs);
|
|
97
|
-
for (const
|
|
108
|
+
for (const wallClockStart of starts) {
|
|
109
|
+
const occurrenceStart = fromWallClockDate(wallClockStart);
|
|
98
110
|
const recurrenceId = occurrenceStart.format("YYYY-MM-DD HH:mm:ss");
|
|
99
111
|
if (exdate.has(recurrenceId)) continue;
|
|
100
112
|
const overrideKey = getRecurrenceKey(event.id, recurrenceId);
|
|
@@ -106,7 +118,7 @@ function expandRecurringEvents({ events, rangeStart, rangeEnd, expansionLimit =
|
|
|
106
118
|
}
|
|
107
119
|
continue;
|
|
108
120
|
}
|
|
109
|
-
const generated = createGeneratedInstance(event, occurrenceStart, durationMs);
|
|
121
|
+
const generated = createGeneratedInstance(event, occurrenceStart, fromWallClockDate(new Date(wallClockStart.getTime() + durationMs)));
|
|
110
122
|
if (overlapsRange((0, dayjs.default)(generated.start), (0, dayjs.default)(generated.end), start, end)) output.push(require_validate_event.validateEvent(generated));
|
|
111
123
|
}
|
|
112
124
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"expand-recurring-events.cjs","names":["rruleAll","validateEvent"],"sources":["../../../src/utils/expand-recurring-events/expand-recurring-events.ts"],"sourcesContent":["import dayjs from 'dayjs';\nimport * as rruleAll from 'rrule';\n\nconst RRule = (\n 'default' in rruleAll ? (rruleAll as any).default.RRule : rruleAll.RRule\n) as typeof rruleAll.RRule;\nimport { DateTimeStringValue, ScheduleEventData, ScheduleRecurrenceData } from '../../types';\nimport { validateEvent } from '../validate-event/validate-event';\n\ninterface ExpandRecurringEventsInput {\n events: ScheduleEventData[] | undefined;\n rangeStart: Date | string;\n rangeEnd: Date | string;\n expansionLimit?: number;\n}\n\nfunction getRecurrenceKey(recurringEventId: string | number, recurrenceId: DateTimeStringValue) {\n return `${recurringEventId}::${recurrenceId}`;\n}\n\nfunction overlapsRange(\n eventStart: dayjs.Dayjs,\n eventEnd: dayjs.Dayjs,\n rangeStart: dayjs.Dayjs,\n rangeEnd: dayjs.Dayjs\n) {\n return (\n (eventEnd.isAfter(rangeStart) || eventEnd.isSame(rangeStart)) &&\n (eventStart.isBefore(rangeEnd) || eventStart.isSame(rangeEnd))\n );\n}\n\nfunction getExdateSet(recurrence: ScheduleRecurrenceData | undefined) {\n if (!recurrence?.exdate) {\n return new Set<string>();\n }\n\n const values = recurrence.exdate\n .map((value) => dayjs(value))\n .filter((value) => value.isValid())\n .map((value) => value.format('YYYY-MM-DD HH:mm:ss'));\n\n return new Set(values);\n}\n\nfunction getRRuleString(rule: string) {\n const normalized = rule.trim();\n if (!normalized.includes('\\n')) {\n return normalized.startsWith('RRULE:') ? normalized.replace(/^RRULE:/, '') : normalized;\n }\n\n const rruleLine = normalized\n .split('\\n')\n .map((line) => line.trim())\n .find((line) => line.startsWith('RRULE:'));\n\n return rruleLine ? rruleLine.replace(/^RRULE:/, '') : normalized;\n}\n\nfunction getOccurrenceStartsInRange(\n event: ScheduleEventData,\n rangeStart: dayjs.Dayjs,\n rangeEnd: dayjs.Dayjs,\n expansionLimit: number,\n durationMs: number\n) {\n const dtstart = dayjs(event.recurrence?.dtstart || event.start);\n if (!dtstart.isValid() || !event.recurrence) {\n return [];\n }\n\n try {\n const options = RRule.parseString(getRRuleString(event.recurrence.rrule));\n options.dtstart = dtstart.toDate();\n const rule = new RRule(options);\n\n const searchStart = rangeStart.subtract(Math.max(0, durationMs), 'millisecond').toDate();\n const results = rule.between(searchStart, rangeEnd.toDate(), true);\n return results.slice(0, expansionLimit).map((value) => dayjs(value));\n } catch {\n return [];\n }\n}\n\nfunction isEventInRange(event: ScheduleEventData, rangeStart: dayjs.Dayjs, rangeEnd: dayjs.Dayjs) {\n const start = dayjs(event.start);\n const end = dayjs(event.end);\n\n if (!start.isValid() || !end.isValid()) {\n return false;\n }\n\n return overlapsRange(start, end, rangeStart, rangeEnd);\n}\n\nfunction createGeneratedInstance(\n event: ScheduleEventData,\n occurrenceStart: dayjs.Dayjs,\n durationMs: number\n): ScheduleEventData {\n const occurrenceEnd = occurrenceStart.add(durationMs, 'millisecond');\n const recurrenceId = occurrenceStart.format('YYYY-MM-DD HH:mm:ss');\n const { recurrence, ...eventWithoutRecurrence } = event;\n\n return {\n ...eventWithoutRecurrence,\n id: `${event.id}::${recurrenceId}`,\n start: occurrenceStart.format('YYYY-MM-DD HH:mm:ss'),\n end: occurrenceEnd.format('YYYY-MM-DD HH:mm:ss'),\n recurringEventId: event.id,\n recurrenceId,\n recurringInstance: {\n isRecurringInstance: true,\n recurringEventId: event.id,\n recurrenceId,\n originalStart: occurrenceStart.format('YYYY-MM-DD HH:mm:ss'),\n originalEnd: occurrenceEnd.format('YYYY-MM-DD HH:mm:ss'),\n },\n };\n}\n\nconst DEFAULT_EXPANSION_LIMIT = 2000;\n\nexport function expandRecurringEvents({\n events,\n rangeStart,\n rangeEnd,\n expansionLimit = DEFAULT_EXPANSION_LIMIT,\n}: ExpandRecurringEventsInput): ScheduleEventData[] {\n if (!events || events.length === 0) {\n return [];\n }\n\n const start = dayjs(rangeStart);\n const end = dayjs(rangeEnd);\n\n if (!start.isValid() || !end.isValid()) {\n return [];\n }\n\n const regularEvents: ScheduleEventData[] = [];\n const recurringEvents: ScheduleEventData[] = [];\n const overrides = new Map<string, ScheduleEventData>();\n\n for (const event of events) {\n if (event.recurringEventId && event.recurrenceId) {\n overrides.set(getRecurrenceKey(event.recurringEventId, event.recurrenceId), event);\n continue;\n }\n\n if (event.recurrence?.rrule) {\n recurringEvents.push(event);\n continue;\n }\n\n regularEvents.push(event);\n }\n\n const output: ScheduleEventData[] = [];\n const consumedOverrideIds = new Set<string | number>();\n\n for (const event of regularEvents) {\n if (isEventInRange(event, start, end)) {\n output.push(validateEvent(event));\n }\n }\n\n for (const event of recurringEvents) {\n const eventStart = dayjs(event.recurrence?.dtstart || event.start);\n const eventEnd = dayjs(event.end);\n\n if (!eventStart.isValid() || !eventEnd.isValid()) {\n continue;\n }\n\n const durationMs = eventEnd.diff(dayjs(event.start), 'millisecond');\n if (durationMs < 0) {\n continue;\n }\n\n const exdate = getExdateSet(event.recurrence);\n const starts = getOccurrenceStartsInRange(event, start, end, expansionLimit, durationMs);\n\n for (const occurrenceStart of starts) {\n const recurrenceId = occurrenceStart.format('YYYY-MM-DD HH:mm:ss');\n if (exdate.has(recurrenceId)) {\n continue;\n }\n\n const overrideKey = getRecurrenceKey(event.id, recurrenceId);\n const override = overrides.get(overrideKey);\n if (override) {\n if (isEventInRange(override, start, end)) {\n output.push(validateEvent(override));\n consumedOverrideIds.add(override.id);\n }\n continue;\n }\n\n const generated = createGeneratedInstance(event, occurrenceStart, durationMs);\n if (overlapsRange(dayjs(generated.start), dayjs(generated.end), start, end)) {\n output.push(validateEvent(generated));\n }\n }\n }\n\n for (const override of overrides.values()) {\n if (consumedOverrideIds.has(override.id)) {\n continue;\n }\n if (isEventInRange(override, start, end)) {\n output.push(validateEvent(override));\n }\n }\n\n return output;\n}\n\nexport { DEFAULT_EXPANSION_LIMIT };\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"expand-recurring-events.cjs","names":["rruleAll","validateEvent"],"sources":["../../../src/utils/expand-recurring-events/expand-recurring-events.ts"],"sourcesContent":["import dayjs from 'dayjs';\nimport * as rruleAll from 'rrule';\n\nconst RRule = (\n 'default' in rruleAll ? (rruleAll as any).default.RRule : rruleAll.RRule\n) as typeof rruleAll.RRule;\nimport { DateTimeStringValue, ScheduleEventData, ScheduleRecurrenceData } from '../../types';\nimport { validateEvent } from '../validate-event/validate-event';\n\ninterface ExpandRecurringEventsInput {\n events: ScheduleEventData[] | undefined;\n rangeStart: Date | string;\n rangeEnd: Date | string;\n expansionLimit?: number;\n}\n\nfunction getRecurrenceKey(recurringEventId: string | number, recurrenceId: DateTimeStringValue) {\n return `${recurringEventId}::${recurrenceId}`;\n}\n\nfunction overlapsRange(\n eventStart: dayjs.Dayjs,\n eventEnd: dayjs.Dayjs,\n rangeStart: dayjs.Dayjs,\n rangeEnd: dayjs.Dayjs\n) {\n return (\n (eventEnd.isAfter(rangeStart) || eventEnd.isSame(rangeStart)) &&\n (eventStart.isBefore(rangeEnd) || eventStart.isSame(rangeEnd))\n );\n}\n\nfunction getExdateSet(recurrence: ScheduleRecurrenceData | undefined) {\n if (!recurrence?.exdate) {\n return new Set<string>();\n }\n\n const values = recurrence.exdate\n .map((value) => dayjs(value))\n .filter((value) => value.isValid())\n .map((value) => value.format('YYYY-MM-DD HH:mm:ss'));\n\n return new Set(values);\n}\n\nfunction toWallClockDate(value: dayjs.Dayjs) {\n return new Date(\n Date.UTC(\n value.year(),\n value.month(),\n value.date(),\n value.hour(),\n value.minute(),\n value.second(),\n value.millisecond()\n )\n );\n}\n\nfunction fromWallClockDate(value: Date) {\n const result = new Date(2000, 0, 1, 12);\n result.setFullYear(value.getUTCFullYear(), value.getUTCMonth(), value.getUTCDate());\n result.setHours(\n value.getUTCHours(),\n value.getUTCMinutes(),\n value.getUTCSeconds(),\n value.getUTCMilliseconds()\n );\n\n return dayjs(result);\n}\n\nfunction getWallClockDurationMs(start: dayjs.Dayjs, end: dayjs.Dayjs) {\n return toWallClockDate(end).getTime() - toWallClockDate(start).getTime();\n}\n\nfunction getRRuleString(rule: string) {\n const normalized = rule.trim();\n if (!normalized.includes('\\n')) {\n return normalized.startsWith('RRULE:') ? normalized.replace(/^RRULE:/, '') : normalized;\n }\n\n const rruleLine = normalized\n .split('\\n')\n .map((line) => line.trim())\n .find((line) => line.startsWith('RRULE:'));\n\n return rruleLine ? rruleLine.replace(/^RRULE:/, '') : normalized;\n}\n\nfunction getOccurrenceStartsInRange(\n event: ScheduleEventData,\n rangeStart: dayjs.Dayjs,\n rangeEnd: dayjs.Dayjs,\n expansionLimit: number,\n durationMs: number\n) {\n const dtstart = dayjs(event.recurrence?.dtstart || event.start);\n if (!dtstart.isValid() || !event.recurrence) {\n return [];\n }\n\n try {\n const options = RRule.parseString(getRRuleString(event.recurrence.rrule));\n options.dtstart = toWallClockDate(dtstart);\n const rule = new RRule(options);\n\n const searchStart = new Date(toWallClockDate(rangeStart).getTime() - Math.max(0, durationMs));\n const results = rule.between(searchStart, toWallClockDate(rangeEnd), true);\n return results.slice(0, expansionLimit);\n } catch {\n return [];\n }\n}\n\nfunction isEventInRange(event: ScheduleEventData, rangeStart: dayjs.Dayjs, rangeEnd: dayjs.Dayjs) {\n const start = dayjs(event.start);\n const end = dayjs(event.end);\n\n if (!start.isValid() || !end.isValid()) {\n return false;\n }\n\n return overlapsRange(start, end, rangeStart, rangeEnd);\n}\n\nfunction createGeneratedInstance(\n event: ScheduleEventData,\n occurrenceStart: dayjs.Dayjs,\n occurrenceEnd: dayjs.Dayjs\n): ScheduleEventData {\n const recurrenceId = occurrenceStart.format('YYYY-MM-DD HH:mm:ss');\n const { recurrence, ...eventWithoutRecurrence } = event;\n\n return {\n ...eventWithoutRecurrence,\n id: `${event.id}::${recurrenceId}`,\n start: occurrenceStart.format('YYYY-MM-DD HH:mm:ss'),\n end: occurrenceEnd.format('YYYY-MM-DD HH:mm:ss'),\n recurringEventId: event.id,\n recurrenceId,\n recurringInstance: {\n isRecurringInstance: true,\n recurringEventId: event.id,\n recurrenceId,\n originalStart: occurrenceStart.format('YYYY-MM-DD HH:mm:ss'),\n originalEnd: occurrenceEnd.format('YYYY-MM-DD HH:mm:ss'),\n },\n };\n}\n\nconst DEFAULT_EXPANSION_LIMIT = 2000;\n\nexport function expandRecurringEvents({\n events,\n rangeStart,\n rangeEnd,\n expansionLimit = DEFAULT_EXPANSION_LIMIT,\n}: ExpandRecurringEventsInput): ScheduleEventData[] {\n if (!events || events.length === 0) {\n return [];\n }\n\n const start = dayjs(rangeStart);\n const end = dayjs(rangeEnd);\n\n if (!start.isValid() || !end.isValid()) {\n return [];\n }\n\n const regularEvents: ScheduleEventData[] = [];\n const recurringEvents: ScheduleEventData[] = [];\n const overrides = new Map<string, ScheduleEventData>();\n\n for (const event of events) {\n if (event.recurringEventId && event.recurrenceId) {\n overrides.set(getRecurrenceKey(event.recurringEventId, event.recurrenceId), event);\n continue;\n }\n\n if (event.recurrence?.rrule) {\n recurringEvents.push(event);\n continue;\n }\n\n regularEvents.push(event);\n }\n\n const output: ScheduleEventData[] = [];\n const consumedOverrideIds = new Set<string | number>();\n\n for (const event of regularEvents) {\n if (isEventInRange(event, start, end)) {\n output.push(validateEvent(event));\n }\n }\n\n for (const event of recurringEvents) {\n const eventStart = dayjs(event.recurrence?.dtstart || event.start);\n const eventEnd = dayjs(event.end);\n\n if (!eventStart.isValid() || !eventEnd.isValid()) {\n continue;\n }\n\n const durationMs = getWallClockDurationMs(dayjs(event.start), eventEnd);\n if (durationMs < 0) {\n continue;\n }\n\n const exdate = getExdateSet(event.recurrence);\n const starts = getOccurrenceStartsInRange(event, start, end, expansionLimit, durationMs);\n\n for (const wallClockStart of starts) {\n const occurrenceStart = fromWallClockDate(wallClockStart);\n const recurrenceId = occurrenceStart.format('YYYY-MM-DD HH:mm:ss');\n if (exdate.has(recurrenceId)) {\n continue;\n }\n\n const overrideKey = getRecurrenceKey(event.id, recurrenceId);\n const override = overrides.get(overrideKey);\n if (override) {\n if (isEventInRange(override, start, end)) {\n output.push(validateEvent(override));\n consumedOverrideIds.add(override.id);\n }\n continue;\n }\n\n const occurrenceEnd = fromWallClockDate(new Date(wallClockStart.getTime() + durationMs));\n const generated = createGeneratedInstance(event, occurrenceStart, occurrenceEnd);\n if (overlapsRange(dayjs(generated.start), dayjs(generated.end), start, end)) {\n output.push(validateEvent(generated));\n }\n }\n }\n\n for (const override of overrides.values()) {\n if (consumedOverrideIds.has(override.id)) {\n continue;\n }\n if (isEventInRange(override, start, end)) {\n output.push(validateEvent(override));\n }\n }\n\n return output;\n}\n\nexport { DEFAULT_EXPANSION_LIMIT };\n"],"mappings":"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"}
|
|
@@ -3,12 +3,24 @@ const require_runtime = require("../../_virtual/_rolldown/runtime.cjs");
|
|
|
3
3
|
let dayjs = require("dayjs");
|
|
4
4
|
dayjs = require_runtime.__toESM(dayjs);
|
|
5
5
|
//#region packages/@mantine/schedule/src/utils/is-events-overlap/is-events-overlap.ts
|
|
6
|
+
const timestampsCache = /* @__PURE__ */ new WeakMap();
|
|
7
|
+
function getTimestamps(event) {
|
|
8
|
+
const cached = timestampsCache.get(event);
|
|
9
|
+
if (cached && cached.start === event.start && cached.end === event.end) return cached;
|
|
10
|
+
const timestamps = {
|
|
11
|
+
start: event.start,
|
|
12
|
+
end: event.end,
|
|
13
|
+
startTimestamp: (0, dayjs.default)(event.start).valueOf(),
|
|
14
|
+
endTimestamp: (0, dayjs.default)(event.end).valueOf()
|
|
15
|
+
};
|
|
16
|
+
timestampsCache.set(event, timestamps);
|
|
17
|
+
return timestamps;
|
|
18
|
+
}
|
|
6
19
|
/** Returns true if two events overlap in time */
|
|
7
20
|
function isEventsOverlap(event1, event2) {
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
return start1 < (0, dayjs.default)(event2.end).valueOf() && start2 < end1;
|
|
21
|
+
const first = getTimestamps(event1);
|
|
22
|
+
const second = getTimestamps(event2);
|
|
23
|
+
return first.startTimestamp < second.endTimestamp && second.startTimestamp < first.endTimestamp;
|
|
12
24
|
}
|
|
13
25
|
//#endregion
|
|
14
26
|
exports.isEventsOverlap = isEventsOverlap;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"is-events-overlap.cjs","names":[],"sources":["../../../src/utils/is-events-overlap/is-events-overlap.ts"],"sourcesContent":["import dayjs from 'dayjs';\nimport { ScheduleEventData } from '../../types';\n\
|
|
1
|
+
{"version":3,"file":"is-events-overlap.cjs","names":[],"sources":["../../../src/utils/is-events-overlap/is-events-overlap.ts"],"sourcesContent":["import dayjs from 'dayjs';\nimport { ScheduleEventData } from '../../types';\n\ninterface CachedTimestamps {\n start: ScheduleEventData['start'];\n end: ScheduleEventData['end'];\n startTimestamp: number;\n endTimestamp: number;\n}\n\nconst timestampsCache = new WeakMap<ScheduleEventData, CachedTimestamps>();\n\nfunction getTimestamps(event: ScheduleEventData): CachedTimestamps {\n const cached = timestampsCache.get(event);\n\n if (cached && cached.start === event.start && cached.end === event.end) {\n return cached;\n }\n\n const timestamps: CachedTimestamps = {\n start: event.start,\n end: event.end,\n startTimestamp: dayjs(event.start).valueOf(),\n endTimestamp: dayjs(event.end).valueOf(),\n };\n\n timestampsCache.set(event, timestamps);\n\n return timestamps;\n}\n\n/** Returns true if two events overlap in time */\nexport function isEventsOverlap(event1: ScheduleEventData, event2: ScheduleEventData) {\n const first = getTimestamps(event1);\n const second = getTimestamps(event2);\n return first.startTimestamp < second.endTimestamp && second.startTimestamp < first.endTimestamp;\n}\n"],"mappings":";;;;;AAUA,MAAM,kCAAkB,IAAI,QAA6C;AAEzE,SAAS,cAAc,OAA4C;CACjE,MAAM,SAAS,gBAAgB,IAAI,KAAK;CAExC,IAAI,UAAU,OAAO,UAAU,MAAM,SAAS,OAAO,QAAQ,MAAM,KACjE,OAAO;CAGT,MAAM,aAA+B;EACnC,OAAO,MAAM;EACb,KAAK,MAAM;EACX,iBAAA,GAAA,MAAA,QAAA,CAAsB,MAAM,KAAK,CAAC,CAAC,QAAQ;EAC3C,eAAA,GAAA,MAAA,QAAA,CAAoB,MAAM,GAAG,CAAC,CAAC,QAAQ;CACzC;CAEA,gBAAgB,IAAI,OAAO,UAAU;CAErC,OAAO;AACT;;AAGA,SAAgB,gBAAgB,QAA2B,QAA2B;CACpF,MAAM,QAAQ,cAAc,MAAM;CAClC,MAAM,SAAS,cAAc,MAAM;CACnC,OAAO,MAAM,iBAAiB,OAAO,gBAAgB,OAAO,iBAAiB,MAAM;AACrF"}
|
|
@@ -1,18 +1,13 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { isAllDayEvent } from "../../../utils/is-all-day-event/is-all-day-event.mjs";
|
|
3
2
|
import { isEventsOverlap } from "../../../utils/is-events-overlap/is-events-overlap.mjs";
|
|
4
3
|
//#region packages/@mantine/schedule/src/components/WeekView/get-week-view-events/find-available-column.ts
|
|
5
|
-
function columnHasConflict({ columns, columnIndex, event, allDay
|
|
4
|
+
function columnHasConflict({ columns, columnIndex, event, allDay }) {
|
|
6
5
|
const columnKey = `col-${columnIndex}`;
|
|
7
6
|
if (!columns.has(columnKey)) return false;
|
|
8
|
-
return columns.get(columnKey).some((
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}));
|
|
13
|
-
const hasTimeConflict = isEventsOverlap(e, event);
|
|
14
|
-
if (allDay && eAllDay) return hasTimeConflict;
|
|
15
|
-
if (allDay || eAllDay) return false;
|
|
7
|
+
return columns.get(columnKey).some((columnEvent) => {
|
|
8
|
+
const hasTimeConflict = isEventsOverlap(columnEvent.event, event);
|
|
9
|
+
if (allDay && columnEvent.allDay) return hasTimeConflict;
|
|
10
|
+
if (allDay || columnEvent.allDay) return false;
|
|
16
11
|
return hasTimeConflict;
|
|
17
12
|
});
|
|
18
13
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"find-available-column.mjs","names":[],"sources":["../../../../src/components/WeekView/get-week-view-events/find-available-column.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"find-available-column.mjs","names":[],"sources":["../../../../src/components/WeekView/get-week-view-events/find-available-column.ts"],"sourcesContent":["import { ScheduleEventData } from '../../../types';\nimport { isEventsOverlap } from '../../../utils';\n\n/** An event stored in a positioning column together with its precomputed all-day flag. */\nexport interface ColumnEvent {\n event: ScheduleEventData;\n allDay: boolean;\n}\n\ninterface FindAvailableColumnInput {\n columns: Map<string, ColumnEvent[]>;\n event: ScheduleEventData;\n allDay: boolean;\n}\n\nfunction columnHasConflict({\n columns,\n columnIndex,\n event,\n allDay,\n}: FindAvailableColumnInput & { columnIndex: number }): boolean {\n const columnKey = `col-${columnIndex}`;\n if (!columns.has(columnKey)) {\n return false;\n }\n\n const columnEvents = columns.get(columnKey)!;\n\n return columnEvents.some((columnEvent) => {\n const hasTimeConflict = isEventsOverlap(columnEvent.event, event);\n\n if (allDay && columnEvent.allDay) {\n return hasTimeConflict;\n }\n\n if (allDay || columnEvent.allDay) {\n return false;\n }\n\n return hasTimeConflict;\n });\n}\n\nexport function findAvailableColumn(input: FindAvailableColumnInput): number {\n let column = 0;\n\n while (columnHasConflict({ ...input, columnIndex: column })) {\n column++;\n }\n\n return column;\n}\n"],"mappings":";;;AAeA,SAAS,kBAAkB,EACzB,SACA,aACA,OACA,UAC8D;CAC9D,MAAM,YAAY,OAAO;CACzB,IAAI,CAAC,QAAQ,IAAI,SAAS,GACxB,OAAO;CAKT,OAFqB,QAAQ,IAAI,SAEf,CAAC,CAAC,MAAM,gBAAgB;EACxC,MAAM,kBAAkB,gBAAgB,YAAY,OAAO,KAAK;EAEhE,IAAI,UAAU,YAAY,QACxB,OAAO;EAGT,IAAI,UAAU,YAAY,QACxB,OAAO;EAGT,OAAO;CACT,CAAC;AACH;AAEA,SAAgB,oBAAoB,OAAyC;CAC3E,IAAI,SAAS;CAEb,OAAO,kBAAkB;EAAE,GAAG;EAAO,aAAa;CAAO,CAAC,GACxD;CAGF,OAAO;AACT"}
|
|
@@ -114,12 +114,14 @@ function getWeekPositionedEvents({ date, events, startTime, endTime, intervalMin
|
|
|
114
114
|
const column = findAvailableColumn({
|
|
115
115
|
columns: columnMap,
|
|
116
116
|
event,
|
|
117
|
-
allDay
|
|
118
|
-
allWeekDays: weekDays
|
|
117
|
+
allDay
|
|
119
118
|
});
|
|
120
119
|
const columnKey = `col-${column}`;
|
|
121
120
|
if (!columnMap.has(columnKey)) columnMap.set(columnKey, []);
|
|
122
|
-
columnMap.get(columnKey).push(
|
|
121
|
+
columnMap.get(columnKey).push({
|
|
122
|
+
event,
|
|
123
|
+
allDay: isActuallyAllDay
|
|
124
|
+
});
|
|
123
125
|
const verticalPosition = allDay ? {
|
|
124
126
|
top: 0,
|
|
125
127
|
height: 100
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-week-positioned-events.mjs","names":[],"sources":["../../../../src/components/WeekView/get-week-view-events/get-week-positioned-events.ts"],"sourcesContent":["import dayjs from 'dayjs';\nimport {\n AnyDateValue,\n DateStringValue,\n DayOfWeek,\n ScheduleEventData,\n WeekPositionedEventData,\n} from '../../../types';\nimport { getDayPosition, getWeekDays, isAllDayEvent, sortEvents } from '../../../utils';\nimport { assignEventRows } from './assign-event-rows';\nimport { calculateAllDayEventOffset } from './calculate-all-day-event-offset';\nimport { calculateAllDayEventWidth } from './calculate-all-day-event-width';\nimport { calculateEventDays } from './calculate-event-days';\nimport { calculateRegularEventOverlaps } from './calculate-regular-event-overlaps';\nimport { findAvailableColumn } from './find-available-column';\nimport { getEventEndDate } from './get-event-end-date';\nimport { getHangingStatus } from './get-hanging-status';\n\nexport interface GetWeekPositionedEventsInput {\n /** Date (week start) at which events are positioned, used to check if events are all-day */\n date: AnyDateValue;\n\n /** List of all events that belong to the given week, extra events must be filtered out before passing to the function */\n events: ScheduleEventData[];\n\n /** Start time of the week view, used to calculate event positions */\n startTime?: string;\n\n /** End time of the week view, used to calculate event positions */\n endTime?: string;\n\n /** Number of minutes per time slot, used to align the canvas to whole slots */\n intervalMinutes?: number;\n\n /** First day of the week, 0 - Sunday, 1 - Monday, etc., used to calculate events positions */\n firstDayOfWeek?: DayOfWeek;\n\n /** Indices of weekend days, 0-6, where 0 is Sunday and 6 is Saturday */\n weekendDays?: DayOfWeek[];\n\n /** If set to false, weekend days are hidden @default true */\n withWeekendDays?: boolean;\n}\n\n/** Events grouped by week day date (YYYY-MM-DD 00:00:00) and by columns */\nexport interface GroupedWeekEvents {\n allDayEvents: WeekPositionedEventData[];\n regularEvents: Record<DateStringValue, WeekPositionedEventData[]>;\n backgroundEvents: Record<DateStringValue, WeekPositionedEventData[]>;\n}\n\nexport function getWeekPositionedEvents({\n date,\n events,\n startTime,\n endTime,\n intervalMinutes,\n firstDayOfWeek = 1,\n weekendDays = [0, 6],\n withWeekendDays = true,\n}: GetWeekPositionedEventsInput): GroupedWeekEvents {\n const weekDays = getWeekDays({ week: date, firstDayOfWeek, withWeekendDays, weekendDays });\n const visibleDaysCount = weekDays.length;\n const weekStartDate = dayjs(weekDays[0]);\n const weekEndDate = dayjs(weekDays[weekDays.length - 1]);\n\n const grouped: GroupedWeekEvents = {\n allDayEvents: [],\n regularEvents: Object.fromEntries(weekDays.map((day) => [day, []])),\n backgroundEvents: Object.fromEntries(weekDays.map((day) => [day, []])),\n };\n\n const columns = new Map<string, ScheduleEventData[]>();\n const allDayColumns = new Map<string, ScheduleEventData[]>();\n const sorted = sortEvents(events);\n\n for (const event of sorted) {\n if (event.display === 'background') {\n const eventStartDate = dayjs(event.start).startOf('day');\n const actualEndDate = getEventEndDate(event);\n const eventWeekDays = calculateEventDays({ event, weekDays, actualEndDate });\n const hanging = getHangingStatus({ eventStartDate, actualEndDate, weekDays });\n\n for (const day of eventWeekDays) {\n const visibleDayIndex = weekDays.indexOf(day);\n if (visibleDayIndex === -1) {\n continue;\n }\n\n const dayStart = dayjs(day);\n const dayEnd = dayStart.endOf('day');\n const eventStart = dayjs(event.start);\n const eventEnd = dayjs(event.end);\n\n const clippedStart = eventStart.isBefore(dayStart) ? dayStart : eventStart;\n const clippedEnd = eventEnd.isAfter(dayEnd) ? dayEnd : eventEnd;\n\n const clippedEvent = {\n ...event,\n start: clippedStart.format('YYYY-MM-DD HH:mm:ss'),\n end: clippedEnd.format('YYYY-MM-DD HH:mm:ss'),\n };\n\n const isAllDay = isAllDayEvent({ event: clippedEvent, date: day });\n const verticalPosition = isAllDay\n ? { top: 0, height: 100 }\n : getDayPosition({ event: clippedEvent, startTime, endTime, intervalMinutes });\n\n if (!isAllDay && verticalPosition.height <= 0) {\n continue;\n }\n\n const dayWeekOffset = (visibleDayIndex / visibleDaysCount) * 100;\n\n grouped.backgroundEvents[day].push({\n ...event,\n position: {\n ...verticalPosition,\n allDay: isAllDay,\n column: 0,\n width: 100,\n offset: 0,\n overlaps: 1,\n weekOffset: dayWeekOffset,\n row: 0,\n hanging,\n },\n });\n }\n\n continue;\n }\n const eventStartDate = dayjs(event.start).startOf('day');\n const actualEndDate = getEventEndDate(event);\n const eventWeekDays = calculateEventDays({ event, weekDays, actualEndDate });\n\n if (eventWeekDays.length === 0) {\n continue;\n }\n\n const isMultiday = actualEndDate.isAfter(eventStartDate);\n const hanging = getHangingStatus({ eventStartDate, actualEndDate, weekDays });\n const isActuallyAllDay = eventWeekDays.some((day) => isAllDayEvent({ event, date: day }));\n const allDay = isMultiday || isActuallyAllDay;\n\n const columnMap = allDay ? allDayColumns : columns;\n const column = findAvailableColumn({\n columns: columnMap,\n event,\n allDay,\n allWeekDays: weekDays,\n });\n\n const columnKey = `col-${column}`;\n if (!columnMap.has(columnKey)) {\n columnMap.set(columnKey, []);\n }\n columnMap.get(columnKey)!.push(event);\n\n const verticalPosition = allDay\n ? { top: 0, height: 100 }\n : getDayPosition({ event, startTime, endTime, intervalMinutes });\n\n if (allDay) {\n const offset = calculateAllDayEventOffset({\n eventStartDate,\n weekStartDate,\n weekDays,\n visibleDaysCount,\n hangingStart: hanging === 'start' || hanging === 'both',\n });\n\n grouped.allDayEvents.push({\n ...event,\n position: {\n ...verticalPosition,\n allDay,\n column,\n width: 0,\n offset,\n overlaps: 0,\n row: 0,\n hanging,\n },\n });\n } else {\n for (const day of eventWeekDays) {\n const visibleDayIndex = weekDays.indexOf(day);\n\n if (visibleDayIndex === -1) {\n continue;\n }\n\n const dayWeekOffset = (visibleDayIndex / visibleDaysCount) * 100;\n\n grouped.regularEvents[day].push({\n ...event,\n position: {\n ...verticalPosition,\n allDay,\n column,\n width: 0,\n offset: 0,\n overlaps: 0,\n weekOffset: dayWeekOffset,\n row: 0,\n hanging,\n },\n });\n }\n }\n }\n\n for (const day of weekDays) {\n calculateRegularEventOverlaps(grouped.regularEvents[day]);\n }\n\n if (grouped.allDayEvents.length > 0) {\n const eventRows = assignEventRows(grouped.allDayEvents);\n const assignedRows = new Set<number>();\n\n for (const event of grouped.allDayEvents) {\n const row = eventRows.get(event)!;\n event.position.row = row;\n assignedRows.add(row);\n }\n\n const rowCount = Math.max(...assignedRows) + 1;\n\n for (const event of grouped.allDayEvents) {\n const eventStartDate = dayjs(event.start).startOf('day');\n const actualEndDate = getEventEndDate(event);\n\n event.position.width = calculateAllDayEventWidth({\n eventStartDate,\n actualEndDate,\n weekStartDate,\n weekEndDate,\n weekDays,\n visibleDaysCount,\n });\n\n event.position.overlaps = rowCount;\n }\n }\n\n return grouped;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"get-week-positioned-events.mjs","names":[],"sources":["../../../../src/components/WeekView/get-week-view-events/get-week-positioned-events.ts"],"sourcesContent":["import dayjs from 'dayjs';\nimport {\n AnyDateValue,\n DateStringValue,\n DayOfWeek,\n ScheduleEventData,\n WeekPositionedEventData,\n} from '../../../types';\nimport { getDayPosition, getWeekDays, isAllDayEvent, sortEvents } from '../../../utils';\nimport { assignEventRows } from './assign-event-rows';\nimport { calculateAllDayEventOffset } from './calculate-all-day-event-offset';\nimport { calculateAllDayEventWidth } from './calculate-all-day-event-width';\nimport { calculateEventDays } from './calculate-event-days';\nimport { calculateRegularEventOverlaps } from './calculate-regular-event-overlaps';\nimport { ColumnEvent, findAvailableColumn } from './find-available-column';\nimport { getEventEndDate } from './get-event-end-date';\nimport { getHangingStatus } from './get-hanging-status';\n\nexport interface GetWeekPositionedEventsInput {\n /** Date (week start) at which events are positioned, used to check if events are all-day */\n date: AnyDateValue;\n\n /** List of all events that belong to the given week, extra events must be filtered out before passing to the function */\n events: ScheduleEventData[];\n\n /** Start time of the week view, used to calculate event positions */\n startTime?: string;\n\n /** End time of the week view, used to calculate event positions */\n endTime?: string;\n\n /** Number of minutes per time slot, used to align the canvas to whole slots */\n intervalMinutes?: number;\n\n /** First day of the week, 0 - Sunday, 1 - Monday, etc., used to calculate events positions */\n firstDayOfWeek?: DayOfWeek;\n\n /** Indices of weekend days, 0-6, where 0 is Sunday and 6 is Saturday */\n weekendDays?: DayOfWeek[];\n\n /** If set to false, weekend days are hidden @default true */\n withWeekendDays?: boolean;\n}\n\n/** Events grouped by week day date (YYYY-MM-DD 00:00:00) and by columns */\nexport interface GroupedWeekEvents {\n allDayEvents: WeekPositionedEventData[];\n regularEvents: Record<DateStringValue, WeekPositionedEventData[]>;\n backgroundEvents: Record<DateStringValue, WeekPositionedEventData[]>;\n}\n\nexport function getWeekPositionedEvents({\n date,\n events,\n startTime,\n endTime,\n intervalMinutes,\n firstDayOfWeek = 1,\n weekendDays = [0, 6],\n withWeekendDays = true,\n}: GetWeekPositionedEventsInput): GroupedWeekEvents {\n const weekDays = getWeekDays({ week: date, firstDayOfWeek, withWeekendDays, weekendDays });\n const visibleDaysCount = weekDays.length;\n const weekStartDate = dayjs(weekDays[0]);\n const weekEndDate = dayjs(weekDays[weekDays.length - 1]);\n\n const grouped: GroupedWeekEvents = {\n allDayEvents: [],\n regularEvents: Object.fromEntries(weekDays.map((day) => [day, []])),\n backgroundEvents: Object.fromEntries(weekDays.map((day) => [day, []])),\n };\n\n const columns = new Map<string, ColumnEvent[]>();\n const allDayColumns = new Map<string, ColumnEvent[]>();\n const sorted = sortEvents(events);\n\n for (const event of sorted) {\n if (event.display === 'background') {\n const eventStartDate = dayjs(event.start).startOf('day');\n const actualEndDate = getEventEndDate(event);\n const eventWeekDays = calculateEventDays({ event, weekDays, actualEndDate });\n const hanging = getHangingStatus({ eventStartDate, actualEndDate, weekDays });\n\n for (const day of eventWeekDays) {\n const visibleDayIndex = weekDays.indexOf(day);\n if (visibleDayIndex === -1) {\n continue;\n }\n\n const dayStart = dayjs(day);\n const dayEnd = dayStart.endOf('day');\n const eventStart = dayjs(event.start);\n const eventEnd = dayjs(event.end);\n\n const clippedStart = eventStart.isBefore(dayStart) ? dayStart : eventStart;\n const clippedEnd = eventEnd.isAfter(dayEnd) ? dayEnd : eventEnd;\n\n const clippedEvent = {\n ...event,\n start: clippedStart.format('YYYY-MM-DD HH:mm:ss'),\n end: clippedEnd.format('YYYY-MM-DD HH:mm:ss'),\n };\n\n const isAllDay = isAllDayEvent({ event: clippedEvent, date: day });\n const verticalPosition = isAllDay\n ? { top: 0, height: 100 }\n : getDayPosition({ event: clippedEvent, startTime, endTime, intervalMinutes });\n\n if (!isAllDay && verticalPosition.height <= 0) {\n continue;\n }\n\n const dayWeekOffset = (visibleDayIndex / visibleDaysCount) * 100;\n\n grouped.backgroundEvents[day].push({\n ...event,\n position: {\n ...verticalPosition,\n allDay: isAllDay,\n column: 0,\n width: 100,\n offset: 0,\n overlaps: 1,\n weekOffset: dayWeekOffset,\n row: 0,\n hanging,\n },\n });\n }\n\n continue;\n }\n const eventStartDate = dayjs(event.start).startOf('day');\n const actualEndDate = getEventEndDate(event);\n const eventWeekDays = calculateEventDays({ event, weekDays, actualEndDate });\n\n if (eventWeekDays.length === 0) {\n continue;\n }\n\n const isMultiday = actualEndDate.isAfter(eventStartDate);\n const hanging = getHangingStatus({ eventStartDate, actualEndDate, weekDays });\n const isActuallyAllDay = eventWeekDays.some((day) => isAllDayEvent({ event, date: day }));\n const allDay = isMultiday || isActuallyAllDay;\n\n const columnMap = allDay ? allDayColumns : columns;\n const column = findAvailableColumn({\n columns: columnMap,\n event,\n allDay,\n });\n\n const columnKey = `col-${column}`;\n if (!columnMap.has(columnKey)) {\n columnMap.set(columnKey, []);\n }\n columnMap.get(columnKey)!.push({ event, allDay: isActuallyAllDay });\n\n const verticalPosition = allDay\n ? { top: 0, height: 100 }\n : getDayPosition({ event, startTime, endTime, intervalMinutes });\n\n if (allDay) {\n const offset = calculateAllDayEventOffset({\n eventStartDate,\n weekStartDate,\n weekDays,\n visibleDaysCount,\n hangingStart: hanging === 'start' || hanging === 'both',\n });\n\n grouped.allDayEvents.push({\n ...event,\n position: {\n ...verticalPosition,\n allDay,\n column,\n width: 0,\n offset,\n overlaps: 0,\n row: 0,\n hanging,\n },\n });\n } else {\n for (const day of eventWeekDays) {\n const visibleDayIndex = weekDays.indexOf(day);\n\n if (visibleDayIndex === -1) {\n continue;\n }\n\n const dayWeekOffset = (visibleDayIndex / visibleDaysCount) * 100;\n\n grouped.regularEvents[day].push({\n ...event,\n position: {\n ...verticalPosition,\n allDay,\n column,\n width: 0,\n offset: 0,\n overlaps: 0,\n weekOffset: dayWeekOffset,\n row: 0,\n hanging,\n },\n });\n }\n }\n }\n\n for (const day of weekDays) {\n calculateRegularEventOverlaps(grouped.regularEvents[day]);\n }\n\n if (grouped.allDayEvents.length > 0) {\n const eventRows = assignEventRows(grouped.allDayEvents);\n const assignedRows = new Set<number>();\n\n for (const event of grouped.allDayEvents) {\n const row = eventRows.get(event)!;\n event.position.row = row;\n assignedRows.add(row);\n }\n\n const rowCount = Math.max(...assignedRows) + 1;\n\n for (const event of grouped.allDayEvents) {\n const eventStartDate = dayjs(event.start).startOf('day');\n const actualEndDate = getEventEndDate(event);\n\n event.position.width = calculateAllDayEventWidth({\n eventStartDate,\n actualEndDate,\n weekStartDate,\n weekEndDate,\n weekDays,\n visibleDaysCount,\n });\n\n event.position.overlaps = rowCount;\n }\n }\n\n return grouped;\n}\n"],"mappings":"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"}
|
|
@@ -29,7 +29,7 @@ const defaultProps = {
|
|
|
29
29
|
const varsResolver = createVarsResolver((_theme, { radius }) => ({ yearView: { "--year-view-radius": radius !== void 0 ? getRadius(radius) : void 0 } }));
|
|
30
30
|
const YearView = factory((_props) => {
|
|
31
31
|
const props = useProps("YearView", defaultProps, _props);
|
|
32
|
-
const { date, onDateChange, events, monthLabelFormat, withWeekNumbers, withWeekDays, locale, firstDayOfWeek, weekdayFormat, weekendDays, withWeekendDays, onMonthClick, onDayClick, onWeekNumberClick, getDayProps, getWeekNumberProps, highlightToday, labels, withOutsideDays, withHeader, monthYearSelectProps, onViewChange, previousControlProps, nextControlProps, todayControlProps, viewSelectProps, __staticSelector, classNames, className, style, styles, unstyled, vars, attributes, radius, mode, recurrenceExpansionLimit, ...others } = props;
|
|
32
|
+
const { date, onDateChange, events, monthLabelFormat, withWeekNumbers, withWeekDays, locale, firstDayOfWeek, weekdayFormat, weekendDays, withWeekendDays, onMonthClick, onDayClick, onWeekNumberClick, getDayProps, getWeekNumberProps, highlightToday, labels, withOutsideDays, renderDay, withHeader, monthYearSelectProps, onViewChange, previousControlProps, nextControlProps, todayControlProps, viewSelectProps, __staticSelector, classNames, className, style, styles, unstyled, vars, attributes, radius, mode, recurrenceExpansionLimit, ...others } = props;
|
|
33
33
|
const ctx = useDatesContext();
|
|
34
34
|
const getStyles = useStyles({
|
|
35
35
|
name: __staticSelector,
|
|
@@ -120,6 +120,7 @@ const YearView = factory((_props) => {
|
|
|
120
120
|
groupedEvents,
|
|
121
121
|
mode,
|
|
122
122
|
withOutsideDays,
|
|
123
|
+
renderDay,
|
|
123
124
|
firstDayIndex: getFirstDayIndex(month),
|
|
124
125
|
__getDayRef: (weekIndex, dayIndex, node) => {
|
|
125
126
|
if (!Array.isArray(daysRef.current[currentMonthIndex])) daysRef.current[currentMonthIndex] = [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"YearView.mjs","names":["classes"],"sources":["../../../src/components/YearView/YearView.tsx"],"sourcesContent":["import dayjs from 'dayjs';\nimport { useRef } from 'react';\nimport {\n Box,\n BoxProps,\n createVarsResolver,\n DataAttributes,\n ElementProps,\n factory,\n Factory,\n getRadius,\n MantineRadius,\n StylesApiProps,\n useProps,\n useResolvedStylesApi,\n useStyles,\n} from '@mantine/core';\nimport { useDatesContext } from '@mantine/dates';\nimport { DateStringValue, ScheduleEventData, ScheduleMode, ScheduleViewLevel } from '../../types';\nimport {\n expandRecurringEvents,\n getMonthDays,\n getMonthsByQuarter,\n isSameMonth,\n toDateString,\n} from '../../utils';\nimport { MonthYearSelectProps } from '../ScheduleHeader/MonthYearSelect/MonthYearSelect';\nimport { CombinedScheduleHeaderStylesNames } from '../ScheduleHeader/ScheduleHeader';\nimport { ScheduleHeaderBase } from '../ScheduleHeader/ScheduleHeaderBase';\nimport { ViewSelectProps } from '../ScheduleHeader/ViewSelect/ViewSelect';\nimport { getHiddenWeekendColumns, getVisibleWeekDays } from './get-visible-week-days';\nimport { getYearViewEvents } from './get-year-view-events/get-year-view-events';\nimport { handleYearViewKeyDown, YearViewControlsRef } from './handle-year-view-key-down';\nimport { YearViewMonth, YearViewMonthSettings } from './YearViewMonth';\nimport classes from './YearView.module.css';\n\nexport type YearViewStylesNames =\n | 'yearView'\n | 'yearViewMonths'\n | 'yearViewMonth'\n | 'yearViewWeekday'\n | 'yearViewDay'\n | 'yearViewWeek'\n | 'yearViewWeekNumber'\n | 'yearViewWeekdays'\n | 'yearViewWeekdaysCorner'\n | 'yearViewMonthCaption'\n | 'yearViewDayIndicators'\n | 'yearViewDayIndicator'\n | CombinedScheduleHeaderStylesNames;\n\nexport type YearViewCssVariables = {\n yearView: '--year-view-radius';\n};\n\nexport interface YearViewProps\n extends YearViewMonthSettings, BoxProps, StylesApiProps<YearViewFactory>, ElementProps<'div'> {\n __staticSelector?: string;\n\n /** Date to display, Date object or date string in `YYYY-MM-DD 00:00:00` format */\n date: Date | string;\n\n /** Called with the new date value when a date is selected */\n onDateChange?: (value: DateStringValue) => void;\n\n /** Events to display, must be a stable reference */\n events?: ScheduleEventData[];\n\n /** Key of `theme.radius` or any valid CSS value to set `border-radius` @default theme.defaultRadius */\n radius?: MantineRadius;\n\n /** If set, highlights the current day @default true */\n highlightToday?: boolean;\n\n /** If set, the header is displayed @default true */\n withHeader?: boolean;\n\n /** Props passed down to `MonthYearSelect` component in the header */\n monthYearSelectProps?: Partial<MonthYearSelectProps>;\n\n /** Called when view level select button is clicked */\n onViewChange?: (view: ScheduleViewLevel) => void;\n\n /** Props passed to previous month control */\n previousControlProps?: React.ComponentProps<'button'> & DataAttributes;\n\n /** Props passed to next month control */\n nextControlProps?: React.ComponentProps<'button'> & DataAttributes;\n\n /** Props passed to today control */\n todayControlProps?: React.ComponentProps<'button'> & DataAttributes;\n\n /** Props passed to view level select */\n viewSelectProps?: Partial<ViewSelectProps> & DataAttributes;\n\n /** Interaction mode: 'default' allows all interactions, 'static' disables event interactions @default default */\n mode?: ScheduleMode;\n\n /** Max number of generated recurring instances per recurring series @default 2000 */\n recurrenceExpansionLimit?: number;\n}\n\nexport type YearViewFactory = Factory<{\n props: YearViewProps;\n ref: HTMLDivElement;\n stylesNames: YearViewStylesNames;\n vars: YearViewCssVariables;\n}>;\n\nconst defaultProps = {\n __staticSelector: 'YearView',\n monthLabelFormat: 'MMMM',\n withWeekDays: true,\n withWeekendDays: true,\n highlightToday: true,\n withHeader: true,\n withOutsideDays: true,\n mode: 'default',\n} satisfies Partial<YearViewProps>;\n\nconst varsResolver = createVarsResolver<YearViewFactory>((_theme, { radius }) => ({\n yearView: { '--year-view-radius': radius !== undefined ? getRadius(radius) : undefined },\n}));\n\nexport const YearView = factory<YearViewFactory>((_props) => {\n const props = useProps('YearView', defaultProps, _props);\n const {\n // YearView props\n date,\n onDateChange,\n events,\n\n // YearViewMonth settings\n monthLabelFormat,\n withWeekNumbers,\n withWeekDays,\n locale,\n firstDayOfWeek,\n weekdayFormat,\n weekendDays,\n withWeekendDays,\n onMonthClick,\n onDayClick,\n onWeekNumberClick,\n getDayProps,\n getWeekNumberProps,\n highlightToday,\n labels,\n withOutsideDays,\n\n // ScheduleHeader props\n withHeader,\n monthYearSelectProps,\n onViewChange,\n previousControlProps,\n nextControlProps,\n todayControlProps,\n viewSelectProps,\n\n // System props\n __staticSelector,\n classNames,\n className,\n style,\n styles,\n unstyled,\n vars,\n attributes,\n radius,\n mode,\n recurrenceExpansionLimit,\n ...others\n } = props;\n\n const ctx = useDatesContext();\n\n const getStyles = useStyles<YearViewFactory>({\n name: __staticSelector,\n classes,\n props,\n className,\n style,\n classNames,\n styles,\n unstyled,\n vars,\n varsResolver,\n attributes,\n rootSelector: 'yearView',\n });\n\n const { resolvedClassNames, resolvedStyles } = useResolvedStylesApi<YearViewFactory>({\n classNames,\n styles,\n props,\n });\n\n const stylesApiProps = {\n classNames: resolvedClassNames,\n styles: resolvedStyles,\n attributes,\n __staticSelector,\n radius,\n };\n\n const expandedEvents = expandRecurringEvents({\n events,\n rangeStart: dayjs(date).startOf('year').toDate(),\n rangeEnd: dayjs(date).endOf('year').toDate(),\n expansionLimit: recurrenceExpansionLimit,\n });\n\n const groupedEvents = getYearViewEvents({ date, events: expandedEvents });\n\n // [monthIndex][weekIndex][dayIndex]\n const daysRef = useRef<HTMLButtonElement[][][]>([]) as YearViewControlsRef;\n\n const resolvedFirstDayOfWeek = ctx.getFirstDayOfWeek(firstDayOfWeek);\n const resolvedWeekendDays = ctx.getWeekendDays(weekendDays);\n const hiddenColumns = getHiddenWeekendColumns({\n weekendDays: resolvedWeekendDays,\n firstDayOfWeek: resolvedFirstDayOfWeek,\n withWeekendDays,\n });\n const columnsCount = 7 - hiddenColumns.length;\n\n const getFirstDayIndex = (month: string): { weekIndex: number; dayIndex: number } | undefined => {\n const weeks = getMonthDays({\n month: dayjs(month).format('YYYY-MM-DD'),\n firstDayOfWeek: resolvedFirstDayOfWeek,\n consistentWeeks: true,\n });\n\n for (let weekIndex = 0; weekIndex < weeks.length; weekIndex++) {\n const week = getVisibleWeekDays({\n week: weeks[weekIndex],\n weekendDays: resolvedWeekendDays,\n withWeekendDays,\n });\n\n for (let dayIndex = 0; dayIndex < week.length; dayIndex++) {\n const dayDate = week[dayIndex];\n if (isSameMonth(dayDate, month)) {\n return { weekIndex, dayIndex };\n }\n }\n }\n\n return undefined;\n };\n\n let globalMonthIndex = 0;\n const months = getMonthsByQuarter(dayjs(date).format('YYYY-MM-DD'))\n .flat()\n .map((month) => {\n const currentMonthIndex = globalMonthIndex;\n globalMonthIndex++;\n\n return (\n <YearViewMonth\n key={month}\n month={month}\n getStyles={getStyles}\n monthLabelFormat={monthLabelFormat}\n withWeekNumbers={withWeekNumbers}\n withWeekDays={withWeekDays}\n locale={locale}\n firstDayOfWeek={firstDayOfWeek}\n weekdayFormat={\n weekdayFormat ||\n ((date) => dayjs(date).locale(ctx.getLocale(locale)).format('dd').slice(0, 1))\n }\n weekendDays={weekendDays}\n withWeekendDays={withWeekendDays}\n getDayProps={getDayProps}\n getWeekNumberProps={getWeekNumberProps}\n onMonthClick={onMonthClick}\n onDayClick={onDayClick}\n onWeekNumberClick={onWeekNumberClick}\n highlightToday={highlightToday}\n groupedEvents={groupedEvents}\n mode={mode}\n withOutsideDays={withOutsideDays}\n firstDayIndex={getFirstDayIndex(month)}\n __getDayRef={(weekIndex, dayIndex, node) => {\n if (!Array.isArray(daysRef.current[currentMonthIndex])) {\n daysRef.current[currentMonthIndex] = [];\n }\n if (!Array.isArray(daysRef.current[currentMonthIndex][weekIndex])) {\n daysRef.current[currentMonthIndex][weekIndex] = [];\n }\n daysRef.current[currentMonthIndex][weekIndex][dayIndex] = node;\n }}\n __onDayKeyDown={(event, payload) => {\n handleYearViewKeyDown({\n controlsRef: daysRef,\n monthIndex: currentMonthIndex,\n weekIndex: payload.weekIndex,\n dayIndex: payload.dayIndex,\n event,\n });\n }}\n />\n );\n });\n\n return (\n <Box\n {...getStyles('yearView')}\n mod={{ static: mode === 'static', 'without-weekend-days': hiddenColumns.length > 0 }}\n __vars={hiddenColumns.length > 0 ? { '--year-view-columns': `${columnsCount}` } : undefined}\n {...others}\n >\n {withHeader && (\n <ScheduleHeaderBase\n view=\"year\"\n navigationHandlers={{\n previous: () => toDateString(dayjs(date).subtract(1, 'year').startOf('year')),\n next: () => toDateString(dayjs(date).add(1, 'year').startOf('year')),\n today: () => toDateString(dayjs()),\n }}\n control={{\n monthYearSelect: {\n locale,\n withMonths: false,\n yearValue: dayjs(date).get('year'),\n monthValue: dayjs(date).get('month'),\n onYearChange: (year) =>\n onDateChange?.(toDateString(dayjs(date).set('year', year).startOf('year'))),\n ...monthYearSelectProps,\n },\n }}\n labels={labels}\n onDateChange={onDateChange}\n onViewChange={onViewChange}\n previousControlProps={previousControlProps}\n nextControlProps={nextControlProps}\n todayControlProps={todayControlProps}\n viewSelectProps={viewSelectProps}\n stylesApiProps={stylesApiProps}\n />\n )}\n\n <div {...getStyles('yearViewMonths')}>{months}</div>\n </Box>\n );\n});\n\nYearView.displayName = '@mantine/schedule/YearView';\nYearView.classes = classes;\nYearView.varsResolver = varsResolver;\n\nexport namespace YearView {\n export type Props = YearViewProps;\n export type Factory = YearViewFactory;\n export type StylesNames = YearViewStylesNames;\n export type CssVariables = YearViewCssVariables;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"YearView.mjs","names":["classes"],"sources":["../../../src/components/YearView/YearView.tsx"],"sourcesContent":["import dayjs from 'dayjs';\nimport { useRef } from 'react';\nimport {\n Box,\n BoxProps,\n createVarsResolver,\n DataAttributes,\n ElementProps,\n factory,\n Factory,\n getRadius,\n MantineRadius,\n StylesApiProps,\n useProps,\n useResolvedStylesApi,\n useStyles,\n} from '@mantine/core';\nimport { useDatesContext } from '@mantine/dates';\nimport { DateStringValue, ScheduleEventData, ScheduleMode, ScheduleViewLevel } from '../../types';\nimport {\n expandRecurringEvents,\n getMonthDays,\n getMonthsByQuarter,\n isSameMonth,\n toDateString,\n} from '../../utils';\nimport { MonthYearSelectProps } from '../ScheduleHeader/MonthYearSelect/MonthYearSelect';\nimport { CombinedScheduleHeaderStylesNames } from '../ScheduleHeader/ScheduleHeader';\nimport { ScheduleHeaderBase } from '../ScheduleHeader/ScheduleHeaderBase';\nimport { ViewSelectProps } from '../ScheduleHeader/ViewSelect/ViewSelect';\nimport { getHiddenWeekendColumns, getVisibleWeekDays } from './get-visible-week-days';\nimport { getYearViewEvents } from './get-year-view-events/get-year-view-events';\nimport { handleYearViewKeyDown, YearViewControlsRef } from './handle-year-view-key-down';\nimport { YearViewMonth, YearViewMonthSettings } from './YearViewMonth';\nimport classes from './YearView.module.css';\n\nexport type YearViewStylesNames =\n | 'yearView'\n | 'yearViewMonths'\n | 'yearViewMonth'\n | 'yearViewWeekday'\n | 'yearViewDay'\n | 'yearViewWeek'\n | 'yearViewWeekNumber'\n | 'yearViewWeekdays'\n | 'yearViewWeekdaysCorner'\n | 'yearViewMonthCaption'\n | 'yearViewDayIndicators'\n | 'yearViewDayIndicator'\n | CombinedScheduleHeaderStylesNames;\n\nexport type YearViewCssVariables = {\n yearView: '--year-view-radius';\n};\n\nexport interface YearViewProps\n extends YearViewMonthSettings, BoxProps, StylesApiProps<YearViewFactory>, ElementProps<'div'> {\n __staticSelector?: string;\n\n /** Date to display, Date object or date string in `YYYY-MM-DD 00:00:00` format */\n date: Date | string;\n\n /** Called with the new date value when a date is selected */\n onDateChange?: (value: DateStringValue) => void;\n\n /** Events to display, must be a stable reference */\n events?: ScheduleEventData[];\n\n /** Key of `theme.radius` or any valid CSS value to set `border-radius` @default theme.defaultRadius */\n radius?: MantineRadius;\n\n /** If set, highlights the current day @default true */\n highlightToday?: boolean;\n\n /** If set, the header is displayed @default true */\n withHeader?: boolean;\n\n /** Props passed down to `MonthYearSelect` component in the header */\n monthYearSelectProps?: Partial<MonthYearSelectProps>;\n\n /** Called when view level select button is clicked */\n onViewChange?: (view: ScheduleViewLevel) => void;\n\n /** Props passed to previous month control */\n previousControlProps?: React.ComponentProps<'button'> & DataAttributes;\n\n /** Props passed to next month control */\n nextControlProps?: React.ComponentProps<'button'> & DataAttributes;\n\n /** Props passed to today control */\n todayControlProps?: React.ComponentProps<'button'> & DataAttributes;\n\n /** Props passed to view level select */\n viewSelectProps?: Partial<ViewSelectProps> & DataAttributes;\n\n /** Interaction mode: 'default' allows all interactions, 'static' disables event interactions @default default */\n mode?: ScheduleMode;\n\n /** Max number of generated recurring instances per recurring series @default 2000 */\n recurrenceExpansionLimit?: number;\n}\n\nexport type YearViewFactory = Factory<{\n props: YearViewProps;\n ref: HTMLDivElement;\n stylesNames: YearViewStylesNames;\n vars: YearViewCssVariables;\n}>;\n\nconst defaultProps = {\n __staticSelector: 'YearView',\n monthLabelFormat: 'MMMM',\n withWeekDays: true,\n withWeekendDays: true,\n highlightToday: true,\n withHeader: true,\n withOutsideDays: true,\n mode: 'default',\n} satisfies Partial<YearViewProps>;\n\nconst varsResolver = createVarsResolver<YearViewFactory>((_theme, { radius }) => ({\n yearView: { '--year-view-radius': radius !== undefined ? getRadius(radius) : undefined },\n}));\n\nexport const YearView = factory<YearViewFactory>((_props) => {\n const props = useProps('YearView', defaultProps, _props);\n const {\n // YearView props\n date,\n onDateChange,\n events,\n\n // YearViewMonth settings\n monthLabelFormat,\n withWeekNumbers,\n withWeekDays,\n locale,\n firstDayOfWeek,\n weekdayFormat,\n weekendDays,\n withWeekendDays,\n onMonthClick,\n onDayClick,\n onWeekNumberClick,\n getDayProps,\n getWeekNumberProps,\n highlightToday,\n labels,\n withOutsideDays,\n renderDay,\n\n // ScheduleHeader props\n withHeader,\n monthYearSelectProps,\n onViewChange,\n previousControlProps,\n nextControlProps,\n todayControlProps,\n viewSelectProps,\n\n // System props\n __staticSelector,\n classNames,\n className,\n style,\n styles,\n unstyled,\n vars,\n attributes,\n radius,\n mode,\n recurrenceExpansionLimit,\n ...others\n } = props;\n\n const ctx = useDatesContext();\n\n const getStyles = useStyles<YearViewFactory>({\n name: __staticSelector,\n classes,\n props,\n className,\n style,\n classNames,\n styles,\n unstyled,\n vars,\n varsResolver,\n attributes,\n rootSelector: 'yearView',\n });\n\n const { resolvedClassNames, resolvedStyles } = useResolvedStylesApi<YearViewFactory>({\n classNames,\n styles,\n props,\n });\n\n const stylesApiProps = {\n classNames: resolvedClassNames,\n styles: resolvedStyles,\n attributes,\n __staticSelector,\n radius,\n };\n\n const expandedEvents = expandRecurringEvents({\n events,\n rangeStart: dayjs(date).startOf('year').toDate(),\n rangeEnd: dayjs(date).endOf('year').toDate(),\n expansionLimit: recurrenceExpansionLimit,\n });\n\n const groupedEvents = getYearViewEvents({ date, events: expandedEvents });\n\n // [monthIndex][weekIndex][dayIndex]\n const daysRef = useRef<HTMLButtonElement[][][]>([]) as YearViewControlsRef;\n\n const resolvedFirstDayOfWeek = ctx.getFirstDayOfWeek(firstDayOfWeek);\n const resolvedWeekendDays = ctx.getWeekendDays(weekendDays);\n const hiddenColumns = getHiddenWeekendColumns({\n weekendDays: resolvedWeekendDays,\n firstDayOfWeek: resolvedFirstDayOfWeek,\n withWeekendDays,\n });\n const columnsCount = 7 - hiddenColumns.length;\n\n const getFirstDayIndex = (month: string): { weekIndex: number; dayIndex: number } | undefined => {\n const weeks = getMonthDays({\n month: dayjs(month).format('YYYY-MM-DD'),\n firstDayOfWeek: resolvedFirstDayOfWeek,\n consistentWeeks: true,\n });\n\n for (let weekIndex = 0; weekIndex < weeks.length; weekIndex++) {\n const week = getVisibleWeekDays({\n week: weeks[weekIndex],\n weekendDays: resolvedWeekendDays,\n withWeekendDays,\n });\n\n for (let dayIndex = 0; dayIndex < week.length; dayIndex++) {\n const dayDate = week[dayIndex];\n if (isSameMonth(dayDate, month)) {\n return { weekIndex, dayIndex };\n }\n }\n }\n\n return undefined;\n };\n\n let globalMonthIndex = 0;\n const months = getMonthsByQuarter(dayjs(date).format('YYYY-MM-DD'))\n .flat()\n .map((month) => {\n const currentMonthIndex = globalMonthIndex;\n globalMonthIndex++;\n\n return (\n <YearViewMonth\n key={month}\n month={month}\n getStyles={getStyles}\n monthLabelFormat={monthLabelFormat}\n withWeekNumbers={withWeekNumbers}\n withWeekDays={withWeekDays}\n locale={locale}\n firstDayOfWeek={firstDayOfWeek}\n weekdayFormat={\n weekdayFormat ||\n ((date) => dayjs(date).locale(ctx.getLocale(locale)).format('dd').slice(0, 1))\n }\n weekendDays={weekendDays}\n withWeekendDays={withWeekendDays}\n getDayProps={getDayProps}\n getWeekNumberProps={getWeekNumberProps}\n onMonthClick={onMonthClick}\n onDayClick={onDayClick}\n onWeekNumberClick={onWeekNumberClick}\n highlightToday={highlightToday}\n groupedEvents={groupedEvents}\n mode={mode}\n withOutsideDays={withOutsideDays}\n renderDay={renderDay}\n firstDayIndex={getFirstDayIndex(month)}\n __getDayRef={(weekIndex, dayIndex, node) => {\n if (!Array.isArray(daysRef.current[currentMonthIndex])) {\n daysRef.current[currentMonthIndex] = [];\n }\n if (!Array.isArray(daysRef.current[currentMonthIndex][weekIndex])) {\n daysRef.current[currentMonthIndex][weekIndex] = [];\n }\n daysRef.current[currentMonthIndex][weekIndex][dayIndex] = node;\n }}\n __onDayKeyDown={(event, payload) => {\n handleYearViewKeyDown({\n controlsRef: daysRef,\n monthIndex: currentMonthIndex,\n weekIndex: payload.weekIndex,\n dayIndex: payload.dayIndex,\n event,\n });\n }}\n />\n );\n });\n\n return (\n <Box\n {...getStyles('yearView')}\n mod={{ static: mode === 'static', 'without-weekend-days': hiddenColumns.length > 0 }}\n __vars={hiddenColumns.length > 0 ? { '--year-view-columns': `${columnsCount}` } : undefined}\n {...others}\n >\n {withHeader && (\n <ScheduleHeaderBase\n view=\"year\"\n navigationHandlers={{\n previous: () => toDateString(dayjs(date).subtract(1, 'year').startOf('year')),\n next: () => toDateString(dayjs(date).add(1, 'year').startOf('year')),\n today: () => toDateString(dayjs()),\n }}\n control={{\n monthYearSelect: {\n locale,\n withMonths: false,\n yearValue: dayjs(date).get('year'),\n monthValue: dayjs(date).get('month'),\n onYearChange: (year) =>\n onDateChange?.(toDateString(dayjs(date).set('year', year).startOf('year'))),\n ...monthYearSelectProps,\n },\n }}\n labels={labels}\n onDateChange={onDateChange}\n onViewChange={onViewChange}\n previousControlProps={previousControlProps}\n nextControlProps={nextControlProps}\n todayControlProps={todayControlProps}\n viewSelectProps={viewSelectProps}\n stylesApiProps={stylesApiProps}\n />\n )}\n\n <div {...getStyles('yearViewMonths')}>{months}</div>\n </Box>\n );\n});\n\nYearView.displayName = '@mantine/schedule/YearView';\nYearView.classes = classes;\nYearView.varsResolver = varsResolver;\n\nexport namespace YearView {\n export type Props = YearViewProps;\n export type Factory = YearViewFactory;\n export type StylesNames = YearViewStylesNames;\n export type CssVariables = YearViewCssVariables;\n}\n"],"mappings":"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"}
|
|
@@ -9,9 +9,9 @@ import dayjs from "dayjs";
|
|
|
9
9
|
import { Box, UnstyledButton, getThemeColor, useMantineTheme } from "@mantine/core";
|
|
10
10
|
import { createElement } from "react";
|
|
11
11
|
import { useDatesContext } from "@mantine/dates";
|
|
12
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
12
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
13
13
|
//#region packages/@mantine/schedule/src/components/YearView/YearViewMonth.tsx
|
|
14
|
-
function YearViewMonth({ month, getStyles, monthLabelFormat = "MMMM", withWeekNumbers, withWeekDays, locale, firstDayOfWeek, weekdayFormat, weekendDays, withWeekendDays, getDayProps, onDayClick, onWeekNumberClick, onMonthClick, getWeekNumberProps, highlightToday, groupedEvents, mode, withOutsideDays, __getDayRef, __onDayKeyDown, firstDayIndex }) {
|
|
14
|
+
function YearViewMonth({ month, getStyles, monthLabelFormat = "MMMM", withWeekNumbers, withWeekDays, locale, firstDayOfWeek, weekdayFormat, weekendDays, withWeekendDays, getDayProps, onDayClick, onWeekNumberClick, onMonthClick, getWeekNumberProps, highlightToday, groupedEvents, mode, withOutsideDays, renderDay, __getDayRef, __onDayKeyDown, firstDayIndex }) {
|
|
15
15
|
const ctx = useDatesContext();
|
|
16
16
|
const theme = useMantineTheme();
|
|
17
17
|
const today = dayjs();
|
|
@@ -53,10 +53,13 @@ function YearViewMonth({ month, getStyles, monthLabelFormat = "MMMM", withWeekNu
|
|
|
53
53
|
const dayEvents = groupedEvents?.[dayjs(date).format("YYYY-MM-DD")] || [];
|
|
54
54
|
const isFirstDayOfMonth = firstDayIndex && weekIndex === firstDayIndex.weekIndex && dayIndex === firstDayIndex.dayIndex;
|
|
55
55
|
const isInTabOrder = mode !== "static" && !outside && isFirstDayOfMonth;
|
|
56
|
-
const
|
|
57
|
-
...getStyles("
|
|
58
|
-
|
|
59
|
-
|
|
56
|
+
const dayContent = typeof renderDay === "function" ? renderDay(dayjs(date).format("YYYY-MM-DD"), dayEvents) : /* @__PURE__ */ jsxs(Fragment, { children: [dayjs(date).format("D"), /* @__PURE__ */ jsx("div", {
|
|
57
|
+
...getStyles("yearViewDayIndicators"),
|
|
58
|
+
children: dayEvents.slice(0, 3).map((event) => /* @__PURE__ */ createElement("div", {
|
|
59
|
+
...getStyles("yearViewDayIndicator", { style: { backgroundColor: getThemeColor(event.color, theme) } }),
|
|
60
|
+
key: event.id
|
|
61
|
+
}))
|
|
62
|
+
})] });
|
|
60
63
|
return /* @__PURE__ */ createElement(UnstyledButton, {
|
|
61
64
|
"aria-label": ariaLabel,
|
|
62
65
|
...dayProps,
|
|
@@ -87,10 +90,7 @@ function YearViewMonth({ month, getStyles, monthLabelFormat = "MMMM", withWeekNu
|
|
|
87
90
|
onDayClick?.(dayjs(date).format("YYYY-MM-DD"), event);
|
|
88
91
|
dayProps.onClick?.(event);
|
|
89
92
|
}
|
|
90
|
-
},
|
|
91
|
-
...getStyles("yearViewDayIndicators"),
|
|
92
|
-
children: indicators
|
|
93
|
-
}));
|
|
93
|
+
}, dayContent);
|
|
94
94
|
});
|
|
95
95
|
const weekNumberProps = getWeekNumberProps?.(dayjs(week[0]).format("YYYY-MM-DD")) || {};
|
|
96
96
|
const weekNumber = getWeekNumber(week);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"YearViewMonth.mjs","names":[],"sources":["../../../src/components/YearView/YearViewMonth.tsx"],"sourcesContent":["import dayjs from 'dayjs';\nimport { Box, GetStylesApi, getThemeColor, UnstyledButton, useMantineTheme } from '@mantine/core';\nimport { useDatesContext } from '@mantine/dates';\nimport { ScheduleLabelsOverride } from '../../labels';\nimport { DateLabelFormat, DateStringValue, DayOfWeek, ScheduleMode } from '../../types';\nimport {\n formatDate,\n getMonthDays,\n getWeekdaysNames,\n getWeekNumber,\n isSameMonth,\n} from '../../utils';\nimport { getHiddenWeekendColumns, getVisibleWeekDays } from './get-visible-week-days';\nimport { GroupedEvents } from './get-year-view-events/get-year-view-events';\nimport type { YearViewFactory } from './YearView';\n\nexport interface YearViewDayKeydownPayload {\n weekIndex: number;\n dayIndex: number;\n date: string;\n}\n\nexport interface YearViewMonthSettings {\n /** `dayjs` format for month label @default 'MMMM' */\n monthLabelFormat?: DateLabelFormat;\n\n /** If set, show week numbers */\n withWeekNumbers?: boolean;\n\n /** If set, weekdays names are displayed in the first row @default true */\n withWeekDays?: boolean;\n\n /** Locale passed down to dayjs, overrides value defined on `DatesProvider` */\n locale?: string;\n\n /** Number 0-6, where 0 – Sunday and 6 – Saturday @default 0 */\n firstDayOfWeek?: DayOfWeek;\n\n /** `dayjs` format for weekdays names @default 'd' */\n weekdayFormat?: DateLabelFormat;\n\n /** Indices of weekend days, 0-6, where 0 is Sunday and 6 is Saturday. The default value is defined by `DatesProvider`. */\n weekendDays?: DayOfWeek[];\n\n /** If set, weekend days are displayed. When `false`, weekend columns are hidden and the month grid shrinks. @default true */\n withWeekendDays?: boolean;\n\n /** Props passed down to the week number button */\n getWeekNumberProps?: (weekStartDate: DateStringValue) => Record<string, any>;\n\n /** Props passed down to the day button */\n getDayProps?: (date: DateStringValue) => Record<string, any>;\n\n /** Called when day is clicked */\n onDayClick?: (date: DateStringValue, event: React.MouseEvent<HTMLButtonElement>) => void;\n\n /** Called with first day of the week when week number is clicked */\n onWeekNumberClick?: (date: DateStringValue, event: React.MouseEvent<HTMLButtonElement>) => void;\n\n /** Called with the first day of the month when month label is clicked */\n onMonthClick?: (date: DateStringValue, event: React.MouseEvent<HTMLButtonElement>) => void;\n\n /** If set, highlights the current day @default true */\n highlightToday?: boolean;\n\n /** Labels override for i18n */\n labels?: ScheduleLabelsOverride;\n\n /** Interaction mode: 'default' allows all interactions, 'static' disables event interactions */\n mode?: ScheduleMode;\n\n /** If true, days from adjacent months are displayed @default true */\n withOutsideDays?: boolean;\n}\n\nexport interface YearViewMonthProps extends YearViewMonthSettings {\n /** Month to display, Date object or date string in `YYYY-MM-DD` format */\n month: Date | string;\n\n /** `useStyles` return value of `YearView` */\n getStyles: GetStylesApi<YearViewFactory>;\n\n /** Events grouped by date */\n groupedEvents?: GroupedEvents;\n\n /** Assigns ref of every day based on its position in the month, used for keyboard navigation */\n __getDayRef?: (weekIndex: number, dayIndex: number, node: HTMLButtonElement) => void;\n\n /** Called when any keydown event is registered on day, used for keyboard navigation */\n __onDayKeyDown?: (\n event: React.KeyboardEvent<HTMLButtonElement>,\n payload: YearViewDayKeydownPayload\n ) => void;\n\n /** Index of the first day of the month in the grid (for determining which day should be in tab order) */\n firstDayIndex?: { weekIndex: number; dayIndex: number };\n}\n\nexport function YearViewMonth({\n month,\n getStyles,\n monthLabelFormat = 'MMMM',\n withWeekNumbers,\n withWeekDays,\n locale,\n firstDayOfWeek,\n weekdayFormat,\n weekendDays,\n withWeekendDays,\n getDayProps,\n onDayClick,\n onWeekNumberClick,\n onMonthClick,\n getWeekNumberProps,\n highlightToday,\n groupedEvents,\n mode,\n withOutsideDays,\n __getDayRef,\n __onDayKeyDown,\n firstDayIndex,\n}: YearViewMonthProps) {\n const ctx = useDatesContext();\n const theme = useMantineTheme();\n const today = dayjs();\n\n const resolvedFirstDayOfWeek = ctx.getFirstDayOfWeek(firstDayOfWeek);\n const resolvedWeekendDays = ctx.getWeekendDays(weekendDays);\n const hiddenColumns = new Set(\n getHiddenWeekendColumns({\n weekendDays: resolvedWeekendDays,\n firstDayOfWeek: resolvedFirstDayOfWeek,\n withWeekendDays,\n })\n );\n\n const weekdays = withWeekDays\n ? getWeekdaysNames({\n locale: ctx.getLocale(locale),\n format: weekdayFormat,\n firstDayOfWeek: resolvedFirstDayOfWeek,\n })\n .filter((_, index) => !hiddenColumns.has(index))\n .map((day, index) => (\n <div {...getStyles('yearViewWeekday')} key={index}>\n {day}\n </div>\n ))\n : null;\n\n const weeks = getMonthDays({\n month: dayjs(month).format('YYYY-MM-DD'),\n firstDayOfWeek: resolvedFirstDayOfWeek,\n consistentWeeks: true,\n }).map((week, weekIndex) => {\n const visibleDays = getVisibleWeekDays({\n week,\n weekendDays: resolvedWeekendDays,\n withWeekendDays,\n });\n\n const days = visibleDays.map((date, dayIndex) => {\n const outside = !isSameMonth(date, month);\n\n if (outside && !withOutsideDays) {\n return <div {...getStyles('yearViewDay')} data-day-placeholder key={date} />;\n }\n\n const weekend = resolvedWeekendDays.includes(dayjs(date).day() as DayOfWeek);\n const ariaLabel = dayjs(date)\n .locale(locale || ctx.locale)\n .format('MMMM D, YYYY');\n\n const dayProps = getDayProps?.(dayjs(date).format('YYYY-MM-DD')) || {};\n const isToday = dayjs(date).isSame(today, 'day') && highlightToday;\n const dayEvents = groupedEvents?.[dayjs(date).format('YYYY-MM-DD')] || [];\n\n // Determine if this day should be in the tab order\n // Only the first day of the month (not outside) should be focusable via tab\n const isFirstDayOfMonth =\n firstDayIndex &&\n weekIndex === firstDayIndex.weekIndex &&\n dayIndex === firstDayIndex.dayIndex;\n const isInTabOrder = mode !== 'static' && !outside && isFirstDayOfMonth;\n\n const indicators = dayEvents.slice(0, 3).map((event) => (\n <div\n {...getStyles('yearViewDayIndicator', {\n style: { backgroundColor: getThemeColor(event.color, theme) },\n })}\n key={event.id}\n />\n ));\n\n return (\n <UnstyledButton\n aria-label={ariaLabel}\n {...dayProps}\n {...getStyles('yearViewDay', { className: dayProps.className, style: dayProps.style })}\n key={date}\n mod={[{ outside, weekend, today: isToday, static: mode === 'static' }, dayProps.mod]}\n tabIndex={isInTabOrder ? 0 : -1}\n ref={(node) => {\n if (node) {\n __getDayRef?.(weekIndex, dayIndex, node);\n }\n }}\n onKeyDown={(event) => {\n dayProps.onKeyDown?.(event);\n __onDayKeyDown?.(event, { weekIndex, dayIndex, date });\n }}\n onClick={\n mode === 'static'\n ? undefined\n : (event) => {\n onDayClick?.(dayjs(date).format('YYYY-MM-DD'), event);\n dayProps.onClick?.(event);\n }\n }\n >\n {dayjs(date).format('D')}\n\n <div {...getStyles('yearViewDayIndicators')}>{indicators}</div>\n </UnstyledButton>\n );\n });\n\n const weekNumberProps = getWeekNumberProps?.(dayjs(week[0]).format('YYYY-MM-DD')) || {};\n const weekNumber = getWeekNumber(week);\n\n return (\n <div {...getStyles('yearViewWeek')} key={weekIndex}>\n {withWeekNumbers && (\n <UnstyledButton\n key={weekNumber}\n aria-label={`Week ${weekNumber}`}\n title={`Week ${weekNumber}`}\n {...weekNumberProps}\n onClick={\n mode === 'static'\n ? undefined\n : (event) => {\n onWeekNumberClick?.(dayjs(week[0]).format('YYYY-MM-DD'), event);\n weekNumberProps.onClick?.(event);\n }\n }\n mod={{ static: mode === 'static' }}\n tabIndex={mode === 'static' ? -1 : 0}\n {...getStyles('yearViewWeekNumber', {\n className: weekNumberProps.className,\n style: weekNumberProps.style,\n })}\n >\n {weekNumber}\n </UnstyledButton>\n )}\n\n {days}\n </div>\n );\n });\n\n return (\n <Box\n mod={[\n {\n 'with-week-numbers': withWeekNumbers,\n 'with-weekdays': withWeekDays,\n static: mode === 'static',\n },\n ]}\n {...getStyles('yearViewMonth')}\n >\n <UnstyledButton\n onClick={\n mode === 'static'\n ? undefined\n : (event) => onMonthClick?.(dayjs(month).startOf('month').format('YYYY-MM-DD'), event)\n }\n mod={{ static: mode === 'static' }}\n tabIndex={mode === 'static' ? -1 : 0}\n {...getStyles('yearViewMonthCaption')}\n >\n {formatDate({ locale: ctx.getLocale(locale), date: month, format: monthLabelFormat })}\n </UnstyledButton>\n\n {weekdays && (\n <div {...getStyles('yearViewWeekdays')}>\n {withWeekNumbers && <div {...getStyles('yearViewWeekdaysCorner')} />}\n {weekdays}\n </div>\n )}\n\n {weeks}\n </Box>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"YearViewMonth.mjs","names":[],"sources":["../../../src/components/YearView/YearViewMonth.tsx"],"sourcesContent":["import dayjs from 'dayjs';\nimport { Box, GetStylesApi, getThemeColor, UnstyledButton, useMantineTheme } from '@mantine/core';\nimport { useDatesContext } from '@mantine/dates';\nimport { ScheduleLabelsOverride } from '../../labels';\nimport {\n DateLabelFormat,\n DateStringValue,\n DayOfWeek,\n ScheduleEventData,\n ScheduleMode,\n} from '../../types';\nimport {\n formatDate,\n getMonthDays,\n getWeekdaysNames,\n getWeekNumber,\n isSameMonth,\n} from '../../utils';\nimport { getHiddenWeekendColumns, getVisibleWeekDays } from './get-visible-week-days';\nimport { GroupedEvents } from './get-year-view-events/get-year-view-events';\nimport type { YearViewFactory } from './YearView';\n\nexport type YearViewRenderDay = (\n date: DateStringValue,\n events: ScheduleEventData[]\n) => React.ReactNode;\n\nexport interface YearViewDayKeydownPayload {\n weekIndex: number;\n dayIndex: number;\n date: string;\n}\n\nexport interface YearViewMonthSettings {\n /** `dayjs` format for month label @default 'MMMM' */\n monthLabelFormat?: DateLabelFormat;\n\n /** If set, show week numbers */\n withWeekNumbers?: boolean;\n\n /** If set, weekdays names are displayed in the first row @default true */\n withWeekDays?: boolean;\n\n /** Locale passed down to dayjs, overrides value defined on `DatesProvider` */\n locale?: string;\n\n /** Number 0-6, where 0 – Sunday and 6 – Saturday @default 0 */\n firstDayOfWeek?: DayOfWeek;\n\n /** `dayjs` format for weekdays names @default 'd' */\n weekdayFormat?: DateLabelFormat;\n\n /** Indices of weekend days, 0-6, where 0 is Sunday and 6 is Saturday. The default value is defined by `DatesProvider`. */\n weekendDays?: DayOfWeek[];\n\n /** If set, weekend days are displayed. When `false`, weekend columns are hidden and the month grid shrinks. @default true */\n withWeekendDays?: boolean;\n\n /** Props passed down to the week number button */\n getWeekNumberProps?: (weekStartDate: DateStringValue) => Record<string, any>;\n\n /** Props passed down to the day button */\n getDayProps?: (date: DateStringValue) => Record<string, any>;\n\n /** Called when day is clicked */\n onDayClick?: (date: DateStringValue, event: React.MouseEvent<HTMLButtonElement>) => void;\n\n /** Called with first day of the week when week number is clicked */\n onWeekNumberClick?: (date: DateStringValue, event: React.MouseEvent<HTMLButtonElement>) => void;\n\n /** Called with the first day of the month when month label is clicked */\n onMonthClick?: (date: DateStringValue, event: React.MouseEvent<HTMLButtonElement>) => void;\n\n /** If set, highlights the current day @default true */\n highlightToday?: boolean;\n\n /** Labels override for i18n */\n labels?: ScheduleLabelsOverride;\n\n /** Interaction mode: 'default' allows all interactions, 'static' disables event interactions */\n mode?: ScheduleMode;\n\n /** If true, days from adjacent months are displayed @default true */\n withOutsideDays?: boolean;\n\n /**\n * A function to replace the entire content of a day cell, called with the day date\n * and the events grouped on that day – the same list that is used to render the default\n * indicators. When set, default event indicators are not rendered.\n */\n renderDay?: YearViewRenderDay;\n}\n\nexport interface YearViewMonthProps extends YearViewMonthSettings {\n /** Month to display, Date object or date string in `YYYY-MM-DD` format */\n month: Date | string;\n\n /** `useStyles` return value of `YearView` */\n getStyles: GetStylesApi<YearViewFactory>;\n\n /** Events grouped by date */\n groupedEvents?: GroupedEvents;\n\n /** Assigns ref of every day based on its position in the month, used for keyboard navigation */\n __getDayRef?: (weekIndex: number, dayIndex: number, node: HTMLButtonElement) => void;\n\n /** Called when any keydown event is registered on day, used for keyboard navigation */\n __onDayKeyDown?: (\n event: React.KeyboardEvent<HTMLButtonElement>,\n payload: YearViewDayKeydownPayload\n ) => void;\n\n /** Index of the first day of the month in the grid (for determining which day should be in tab order) */\n firstDayIndex?: { weekIndex: number; dayIndex: number };\n}\n\nexport function YearViewMonth({\n month,\n getStyles,\n monthLabelFormat = 'MMMM',\n withWeekNumbers,\n withWeekDays,\n locale,\n firstDayOfWeek,\n weekdayFormat,\n weekendDays,\n withWeekendDays,\n getDayProps,\n onDayClick,\n onWeekNumberClick,\n onMonthClick,\n getWeekNumberProps,\n highlightToday,\n groupedEvents,\n mode,\n withOutsideDays,\n renderDay,\n __getDayRef,\n __onDayKeyDown,\n firstDayIndex,\n}: YearViewMonthProps) {\n const ctx = useDatesContext();\n const theme = useMantineTheme();\n const today = dayjs();\n\n const resolvedFirstDayOfWeek = ctx.getFirstDayOfWeek(firstDayOfWeek);\n const resolvedWeekendDays = ctx.getWeekendDays(weekendDays);\n const hiddenColumns = new Set(\n getHiddenWeekendColumns({\n weekendDays: resolvedWeekendDays,\n firstDayOfWeek: resolvedFirstDayOfWeek,\n withWeekendDays,\n })\n );\n\n const weekdays = withWeekDays\n ? getWeekdaysNames({\n locale: ctx.getLocale(locale),\n format: weekdayFormat,\n firstDayOfWeek: resolvedFirstDayOfWeek,\n })\n .filter((_, index) => !hiddenColumns.has(index))\n .map((day, index) => (\n <div {...getStyles('yearViewWeekday')} key={index}>\n {day}\n </div>\n ))\n : null;\n\n const weeks = getMonthDays({\n month: dayjs(month).format('YYYY-MM-DD'),\n firstDayOfWeek: resolvedFirstDayOfWeek,\n consistentWeeks: true,\n }).map((week, weekIndex) => {\n const visibleDays = getVisibleWeekDays({\n week,\n weekendDays: resolvedWeekendDays,\n withWeekendDays,\n });\n\n const days = visibleDays.map((date, dayIndex) => {\n const outside = !isSameMonth(date, month);\n\n if (outside && !withOutsideDays) {\n return <div {...getStyles('yearViewDay')} data-day-placeholder key={date} />;\n }\n\n const weekend = resolvedWeekendDays.includes(dayjs(date).day() as DayOfWeek);\n const ariaLabel = dayjs(date)\n .locale(locale || ctx.locale)\n .format('MMMM D, YYYY');\n\n const dayProps = getDayProps?.(dayjs(date).format('YYYY-MM-DD')) || {};\n const isToday = dayjs(date).isSame(today, 'day') && highlightToday;\n const dayEvents = groupedEvents?.[dayjs(date).format('YYYY-MM-DD')] || [];\n\n // Determine if this day should be in the tab order\n // Only the first day of the month (not outside) should be focusable via tab\n const isFirstDayOfMonth =\n firstDayIndex &&\n weekIndex === firstDayIndex.weekIndex &&\n dayIndex === firstDayIndex.dayIndex;\n const isInTabOrder = mode !== 'static' && !outside && isFirstDayOfMonth;\n\n const dayContent =\n typeof renderDay === 'function' ? (\n renderDay(dayjs(date).format('YYYY-MM-DD'), dayEvents)\n ) : (\n <>\n {dayjs(date).format('D')}\n\n <div {...getStyles('yearViewDayIndicators')}>\n {dayEvents.slice(0, 3).map((event) => (\n <div\n {...getStyles('yearViewDayIndicator', {\n style: { backgroundColor: getThemeColor(event.color, theme) },\n })}\n key={event.id}\n />\n ))}\n </div>\n </>\n );\n\n return (\n <UnstyledButton\n aria-label={ariaLabel}\n {...dayProps}\n {...getStyles('yearViewDay', { className: dayProps.className, style: dayProps.style })}\n key={date}\n mod={[{ outside, weekend, today: isToday, static: mode === 'static' }, dayProps.mod]}\n tabIndex={isInTabOrder ? 0 : -1}\n ref={(node) => {\n if (node) {\n __getDayRef?.(weekIndex, dayIndex, node);\n }\n }}\n onKeyDown={(event) => {\n dayProps.onKeyDown?.(event);\n __onDayKeyDown?.(event, { weekIndex, dayIndex, date });\n }}\n onClick={\n mode === 'static'\n ? undefined\n : (event) => {\n onDayClick?.(dayjs(date).format('YYYY-MM-DD'), event);\n dayProps.onClick?.(event);\n }\n }\n >\n {dayContent}\n </UnstyledButton>\n );\n });\n\n const weekNumberProps = getWeekNumberProps?.(dayjs(week[0]).format('YYYY-MM-DD')) || {};\n const weekNumber = getWeekNumber(week);\n\n return (\n <div {...getStyles('yearViewWeek')} key={weekIndex}>\n {withWeekNumbers && (\n <UnstyledButton\n key={weekNumber}\n aria-label={`Week ${weekNumber}`}\n title={`Week ${weekNumber}`}\n {...weekNumberProps}\n onClick={\n mode === 'static'\n ? undefined\n : (event) => {\n onWeekNumberClick?.(dayjs(week[0]).format('YYYY-MM-DD'), event);\n weekNumberProps.onClick?.(event);\n }\n }\n mod={{ static: mode === 'static' }}\n tabIndex={mode === 'static' ? -1 : 0}\n {...getStyles('yearViewWeekNumber', {\n className: weekNumberProps.className,\n style: weekNumberProps.style,\n })}\n >\n {weekNumber}\n </UnstyledButton>\n )}\n\n {days}\n </div>\n );\n });\n\n return (\n <Box\n mod={[\n {\n 'with-week-numbers': withWeekNumbers,\n 'with-weekdays': withWeekDays,\n static: mode === 'static',\n },\n ]}\n {...getStyles('yearViewMonth')}\n >\n <UnstyledButton\n onClick={\n mode === 'static'\n ? undefined\n : (event) => onMonthClick?.(dayjs(month).startOf('month').format('YYYY-MM-DD'), event)\n }\n mod={{ static: mode === 'static' }}\n tabIndex={mode === 'static' ? -1 : 0}\n {...getStyles('yearViewMonthCaption')}\n >\n {formatDate({ locale: ctx.getLocale(locale), date: month, format: monthLabelFormat })}\n </UnstyledButton>\n\n {weekdays && (\n <div {...getStyles('yearViewWeekdays')}>\n {withWeekNumbers && <div {...getStyles('yearViewWeekdaysCorner')} />}\n {weekdays}\n </div>\n )}\n\n {weeks}\n </Box>\n );\n}\n"],"mappings":"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"}
|
|
@@ -15,6 +15,18 @@ function getExdateSet(recurrence) {
|
|
|
15
15
|
const values = recurrence.exdate.map((value) => dayjs(value)).filter((value) => value.isValid()).map((value) => value.format("YYYY-MM-DD HH:mm:ss"));
|
|
16
16
|
return new Set(values);
|
|
17
17
|
}
|
|
18
|
+
function toWallClockDate(value) {
|
|
19
|
+
return new Date(Date.UTC(value.year(), value.month(), value.date(), value.hour(), value.minute(), value.second(), value.millisecond()));
|
|
20
|
+
}
|
|
21
|
+
function fromWallClockDate(value) {
|
|
22
|
+
const result = new Date(2e3, 0, 1, 12);
|
|
23
|
+
result.setFullYear(value.getUTCFullYear(), value.getUTCMonth(), value.getUTCDate());
|
|
24
|
+
result.setHours(value.getUTCHours(), value.getUTCMinutes(), value.getUTCSeconds(), value.getUTCMilliseconds());
|
|
25
|
+
return dayjs(result);
|
|
26
|
+
}
|
|
27
|
+
function getWallClockDurationMs(start, end) {
|
|
28
|
+
return toWallClockDate(end).getTime() - toWallClockDate(start).getTime();
|
|
29
|
+
}
|
|
18
30
|
function getRRuleString(rule) {
|
|
19
31
|
const normalized = rule.trim();
|
|
20
32
|
if (!normalized.includes("\n")) return normalized.startsWith("RRULE:") ? normalized.replace(/^RRULE:/, "") : normalized;
|
|
@@ -26,10 +38,10 @@ function getOccurrenceStartsInRange(event, rangeStart, rangeEnd, expansionLimit,
|
|
|
26
38
|
if (!dtstart.isValid() || !event.recurrence) return [];
|
|
27
39
|
try {
|
|
28
40
|
const options = RRule.parseString(getRRuleString(event.recurrence.rrule));
|
|
29
|
-
options.dtstart = dtstart
|
|
41
|
+
options.dtstart = toWallClockDate(dtstart);
|
|
30
42
|
const rule = new RRule(options);
|
|
31
|
-
const searchStart = rangeStart.
|
|
32
|
-
return rule.between(searchStart, rangeEnd
|
|
43
|
+
const searchStart = new Date(toWallClockDate(rangeStart).getTime() - Math.max(0, durationMs));
|
|
44
|
+
return rule.between(searchStart, toWallClockDate(rangeEnd), true).slice(0, expansionLimit);
|
|
33
45
|
} catch {
|
|
34
46
|
return [];
|
|
35
47
|
}
|
|
@@ -40,8 +52,7 @@ function isEventInRange(event, rangeStart, rangeEnd) {
|
|
|
40
52
|
if (!start.isValid() || !end.isValid()) return false;
|
|
41
53
|
return overlapsRange(start, end, rangeStart, rangeEnd);
|
|
42
54
|
}
|
|
43
|
-
function createGeneratedInstance(event, occurrenceStart,
|
|
44
|
-
const occurrenceEnd = occurrenceStart.add(durationMs, "millisecond");
|
|
55
|
+
function createGeneratedInstance(event, occurrenceStart, occurrenceEnd) {
|
|
45
56
|
const recurrenceId = occurrenceStart.format("YYYY-MM-DD HH:mm:ss");
|
|
46
57
|
const { recurrence, ...eventWithoutRecurrence } = event;
|
|
47
58
|
return {
|
|
@@ -87,11 +98,12 @@ function expandRecurringEvents({ events, rangeStart, rangeEnd, expansionLimit =
|
|
|
87
98
|
const eventStart = dayjs(event.recurrence?.dtstart || event.start);
|
|
88
99
|
const eventEnd = dayjs(event.end);
|
|
89
100
|
if (!eventStart.isValid() || !eventEnd.isValid()) continue;
|
|
90
|
-
const durationMs =
|
|
101
|
+
const durationMs = getWallClockDurationMs(dayjs(event.start), eventEnd);
|
|
91
102
|
if (durationMs < 0) continue;
|
|
92
103
|
const exdate = getExdateSet(event.recurrence);
|
|
93
104
|
const starts = getOccurrenceStartsInRange(event, start, end, expansionLimit, durationMs);
|
|
94
|
-
for (const
|
|
105
|
+
for (const wallClockStart of starts) {
|
|
106
|
+
const occurrenceStart = fromWallClockDate(wallClockStart);
|
|
95
107
|
const recurrenceId = occurrenceStart.format("YYYY-MM-DD HH:mm:ss");
|
|
96
108
|
if (exdate.has(recurrenceId)) continue;
|
|
97
109
|
const overrideKey = getRecurrenceKey(event.id, recurrenceId);
|
|
@@ -103,7 +115,7 @@ function expandRecurringEvents({ events, rangeStart, rangeEnd, expansionLimit =
|
|
|
103
115
|
}
|
|
104
116
|
continue;
|
|
105
117
|
}
|
|
106
|
-
const generated = createGeneratedInstance(event, occurrenceStart, durationMs);
|
|
118
|
+
const generated = createGeneratedInstance(event, occurrenceStart, fromWallClockDate(new Date(wallClockStart.getTime() + durationMs)));
|
|
107
119
|
if (overlapsRange(dayjs(generated.start), dayjs(generated.end), start, end)) output.push(validateEvent(generated));
|
|
108
120
|
}
|
|
109
121
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"expand-recurring-events.mjs","names":[],"sources":["../../../src/utils/expand-recurring-events/expand-recurring-events.ts"],"sourcesContent":["import dayjs from 'dayjs';\nimport * as rruleAll from 'rrule';\n\nconst RRule = (\n 'default' in rruleAll ? (rruleAll as any).default.RRule : rruleAll.RRule\n) as typeof rruleAll.RRule;\nimport { DateTimeStringValue, ScheduleEventData, ScheduleRecurrenceData } from '../../types';\nimport { validateEvent } from '../validate-event/validate-event';\n\ninterface ExpandRecurringEventsInput {\n events: ScheduleEventData[] | undefined;\n rangeStart: Date | string;\n rangeEnd: Date | string;\n expansionLimit?: number;\n}\n\nfunction getRecurrenceKey(recurringEventId: string | number, recurrenceId: DateTimeStringValue) {\n return `${recurringEventId}::${recurrenceId}`;\n}\n\nfunction overlapsRange(\n eventStart: dayjs.Dayjs,\n eventEnd: dayjs.Dayjs,\n rangeStart: dayjs.Dayjs,\n rangeEnd: dayjs.Dayjs\n) {\n return (\n (eventEnd.isAfter(rangeStart) || eventEnd.isSame(rangeStart)) &&\n (eventStart.isBefore(rangeEnd) || eventStart.isSame(rangeEnd))\n );\n}\n\nfunction getExdateSet(recurrence: ScheduleRecurrenceData | undefined) {\n if (!recurrence?.exdate) {\n return new Set<string>();\n }\n\n const values = recurrence.exdate\n .map((value) => dayjs(value))\n .filter((value) => value.isValid())\n .map((value) => value.format('YYYY-MM-DD HH:mm:ss'));\n\n return new Set(values);\n}\n\nfunction getRRuleString(rule: string) {\n const normalized = rule.trim();\n if (!normalized.includes('\\n')) {\n return normalized.startsWith('RRULE:') ? normalized.replace(/^RRULE:/, '') : normalized;\n }\n\n const rruleLine = normalized\n .split('\\n')\n .map((line) => line.trim())\n .find((line) => line.startsWith('RRULE:'));\n\n return rruleLine ? rruleLine.replace(/^RRULE:/, '') : normalized;\n}\n\nfunction getOccurrenceStartsInRange(\n event: ScheduleEventData,\n rangeStart: dayjs.Dayjs,\n rangeEnd: dayjs.Dayjs,\n expansionLimit: number,\n durationMs: number\n) {\n const dtstart = dayjs(event.recurrence?.dtstart || event.start);\n if (!dtstart.isValid() || !event.recurrence) {\n return [];\n }\n\n try {\n const options = RRule.parseString(getRRuleString(event.recurrence.rrule));\n options.dtstart = dtstart.toDate();\n const rule = new RRule(options);\n\n const searchStart = rangeStart.subtract(Math.max(0, durationMs), 'millisecond').toDate();\n const results = rule.between(searchStart, rangeEnd.toDate(), true);\n return results.slice(0, expansionLimit).map((value) => dayjs(value));\n } catch {\n return [];\n }\n}\n\nfunction isEventInRange(event: ScheduleEventData, rangeStart: dayjs.Dayjs, rangeEnd: dayjs.Dayjs) {\n const start = dayjs(event.start);\n const end = dayjs(event.end);\n\n if (!start.isValid() || !end.isValid()) {\n return false;\n }\n\n return overlapsRange(start, end, rangeStart, rangeEnd);\n}\n\nfunction createGeneratedInstance(\n event: ScheduleEventData,\n occurrenceStart: dayjs.Dayjs,\n durationMs: number\n): ScheduleEventData {\n const occurrenceEnd = occurrenceStart.add(durationMs, 'millisecond');\n const recurrenceId = occurrenceStart.format('YYYY-MM-DD HH:mm:ss');\n const { recurrence, ...eventWithoutRecurrence } = event;\n\n return {\n ...eventWithoutRecurrence,\n id: `${event.id}::${recurrenceId}`,\n start: occurrenceStart.format('YYYY-MM-DD HH:mm:ss'),\n end: occurrenceEnd.format('YYYY-MM-DD HH:mm:ss'),\n recurringEventId: event.id,\n recurrenceId,\n recurringInstance: {\n isRecurringInstance: true,\n recurringEventId: event.id,\n recurrenceId,\n originalStart: occurrenceStart.format('YYYY-MM-DD HH:mm:ss'),\n originalEnd: occurrenceEnd.format('YYYY-MM-DD HH:mm:ss'),\n },\n };\n}\n\nconst DEFAULT_EXPANSION_LIMIT = 2000;\n\nexport function expandRecurringEvents({\n events,\n rangeStart,\n rangeEnd,\n expansionLimit = DEFAULT_EXPANSION_LIMIT,\n}: ExpandRecurringEventsInput): ScheduleEventData[] {\n if (!events || events.length === 0) {\n return [];\n }\n\n const start = dayjs(rangeStart);\n const end = dayjs(rangeEnd);\n\n if (!start.isValid() || !end.isValid()) {\n return [];\n }\n\n const regularEvents: ScheduleEventData[] = [];\n const recurringEvents: ScheduleEventData[] = [];\n const overrides = new Map<string, ScheduleEventData>();\n\n for (const event of events) {\n if (event.recurringEventId && event.recurrenceId) {\n overrides.set(getRecurrenceKey(event.recurringEventId, event.recurrenceId), event);\n continue;\n }\n\n if (event.recurrence?.rrule) {\n recurringEvents.push(event);\n continue;\n }\n\n regularEvents.push(event);\n }\n\n const output: ScheduleEventData[] = [];\n const consumedOverrideIds = new Set<string | number>();\n\n for (const event of regularEvents) {\n if (isEventInRange(event, start, end)) {\n output.push(validateEvent(event));\n }\n }\n\n for (const event of recurringEvents) {\n const eventStart = dayjs(event.recurrence?.dtstart || event.start);\n const eventEnd = dayjs(event.end);\n\n if (!eventStart.isValid() || !eventEnd.isValid()) {\n continue;\n }\n\n const durationMs = eventEnd.diff(dayjs(event.start), 'millisecond');\n if (durationMs < 0) {\n continue;\n }\n\n const exdate = getExdateSet(event.recurrence);\n const starts = getOccurrenceStartsInRange(event, start, end, expansionLimit, durationMs);\n\n for (const occurrenceStart of starts) {\n const recurrenceId = occurrenceStart.format('YYYY-MM-DD HH:mm:ss');\n if (exdate.has(recurrenceId)) {\n continue;\n }\n\n const overrideKey = getRecurrenceKey(event.id, recurrenceId);\n const override = overrides.get(overrideKey);\n if (override) {\n if (isEventInRange(override, start, end)) {\n output.push(validateEvent(override));\n consumedOverrideIds.add(override.id);\n }\n continue;\n }\n\n const generated = createGeneratedInstance(event, occurrenceStart, durationMs);\n if (overlapsRange(dayjs(generated.start), dayjs(generated.end), start, end)) {\n output.push(validateEvent(generated));\n }\n }\n }\n\n for (const override of overrides.values()) {\n if (consumedOverrideIds.has(override.id)) {\n continue;\n }\n if (isEventInRange(override, start, end)) {\n output.push(validateEvent(override));\n }\n }\n\n return output;\n}\n\nexport { DEFAULT_EXPANSION_LIMIT };\n"],"mappings":";;;;;AAGA,MAAM,QACJ,aAAa,WAAY,SAAiB,QAAQ,QAAQ,SAAS;AAYrE,SAAS,iBAAiB,kBAAmC,cAAmC;CAC9F,OAAO,GAAG,iBAAiB,IAAI;AACjC;AAEA,SAAS,cACP,YACA,UACA,YACA,UACA;CACA,QACG,SAAS,QAAQ,UAAU,KAAK,SAAS,OAAO,UAAU,OAC1D,WAAW,SAAS,QAAQ,KAAK,WAAW,OAAO,QAAQ;AAEhE;AAEA,SAAS,aAAa,YAAgD;CACpE,IAAI,CAAC,YAAY,QACf,uBAAO,IAAI,IAAY;CAGzB,MAAM,SAAS,WAAW,OACvB,KAAK,UAAU,MAAM,KAAK,CAAC,CAAC,CAC5B,QAAQ,UAAU,MAAM,QAAQ,CAAC,CAAC,CAClC,KAAK,UAAU,MAAM,OAAO,qBAAqB,CAAC;CAErD,OAAO,IAAI,IAAI,MAAM;AACvB;AAEA,SAAS,eAAe,MAAc;CACpC,MAAM,aAAa,KAAK,KAAK;CAC7B,IAAI,CAAC,WAAW,SAAS,IAAI,GAC3B,OAAO,WAAW,WAAW,QAAQ,IAAI,WAAW,QAAQ,WAAW,EAAE,IAAI;CAG/E,MAAM,YAAY,WACf,MAAM,IAAI,CAAC,CACX,KAAK,SAAS,KAAK,KAAK,CAAC,CAAC,CAC1B,MAAM,SAAS,KAAK,WAAW,QAAQ,CAAC;CAE3C,OAAO,YAAY,UAAU,QAAQ,WAAW,EAAE,IAAI;AACxD;AAEA,SAAS,2BACP,OACA,YACA,UACA,gBACA,YACA;CACA,MAAM,UAAU,MAAM,MAAM,YAAY,WAAW,MAAM,KAAK;CAC9D,IAAI,CAAC,QAAQ,QAAQ,KAAK,CAAC,MAAM,YAC/B,OAAO,CAAC;CAGV,IAAI;EACF,MAAM,UAAU,MAAM,YAAY,eAAe,MAAM,WAAW,KAAK,CAAC;EACxE,QAAQ,UAAU,QAAQ,OAAO;EACjC,MAAM,OAAO,IAAI,MAAM,OAAO;EAE9B,MAAM,cAAc,WAAW,SAAS,KAAK,IAAI,GAAG,UAAU,GAAG,aAAa,CAAC,CAAC,OAAO;EAEvF,OADgB,KAAK,QAAQ,aAAa,SAAS,OAAO,GAAG,IAChD,CAAC,CAAC,MAAM,GAAG,cAAc,CAAC,CAAC,KAAK,UAAU,MAAM,KAAK,CAAC;CACrE,QAAQ;EACN,OAAO,CAAC;CACV;AACF;AAEA,SAAS,eAAe,OAA0B,YAAyB,UAAuB;CAChG,MAAM,QAAQ,MAAM,MAAM,KAAK;CAC/B,MAAM,MAAM,MAAM,MAAM,GAAG;CAE3B,IAAI,CAAC,MAAM,QAAQ,KAAK,CAAC,IAAI,QAAQ,GACnC,OAAO;CAGT,OAAO,cAAc,OAAO,KAAK,YAAY,QAAQ;AACvD;AAEA,SAAS,wBACP,OACA,iBACA,YACmB;CACnB,MAAM,gBAAgB,gBAAgB,IAAI,YAAY,aAAa;CACnE,MAAM,eAAe,gBAAgB,OAAO,qBAAqB;CACjE,MAAM,EAAE,YAAY,GAAG,2BAA2B;CAElD,OAAO;EACL,GAAG;EACH,IAAI,GAAG,MAAM,GAAG,IAAI;EACpB,OAAO,gBAAgB,OAAO,qBAAqB;EACnD,KAAK,cAAc,OAAO,qBAAqB;EAC/C,kBAAkB,MAAM;EACxB;EACA,mBAAmB;GACjB,qBAAqB;GACrB,kBAAkB,MAAM;GACxB;GACA,eAAe,gBAAgB,OAAO,qBAAqB;GAC3D,aAAa,cAAc,OAAO,qBAAqB;EACzD;CACF;AACF;AAEA,MAAM,0BAA0B;AAEhC,SAAgB,sBAAsB,EACpC,QACA,YACA,UACA,iBAAiB,2BACiC;CAClD,IAAI,CAAC,UAAU,OAAO,WAAW,GAC/B,OAAO,CAAC;CAGV,MAAM,QAAQ,MAAM,UAAU;CAC9B,MAAM,MAAM,MAAM,QAAQ;CAE1B,IAAI,CAAC,MAAM,QAAQ,KAAK,CAAC,IAAI,QAAQ,GACnC,OAAO,CAAC;CAGV,MAAM,gBAAqC,CAAC;CAC5C,MAAM,kBAAuC,CAAC;CAC9C,MAAM,4BAAY,IAAI,IAA+B;CAErD,KAAK,MAAM,SAAS,QAAQ;EAC1B,IAAI,MAAM,oBAAoB,MAAM,cAAc;GAChD,UAAU,IAAI,iBAAiB,MAAM,kBAAkB,MAAM,YAAY,GAAG,KAAK;GACjF;EACF;EAEA,IAAI,MAAM,YAAY,OAAO;GAC3B,gBAAgB,KAAK,KAAK;GAC1B;EACF;EAEA,cAAc,KAAK,KAAK;CAC1B;CAEA,MAAM,SAA8B,CAAC;CACrC,MAAM,sCAAsB,IAAI,IAAqB;CAErD,KAAK,MAAM,SAAS,eAClB,IAAI,eAAe,OAAO,OAAO,GAAG,GAClC,OAAO,KAAK,cAAc,KAAK,CAAC;CAIpC,KAAK,MAAM,SAAS,iBAAiB;EACnC,MAAM,aAAa,MAAM,MAAM,YAAY,WAAW,MAAM,KAAK;EACjE,MAAM,WAAW,MAAM,MAAM,GAAG;EAEhC,IAAI,CAAC,WAAW,QAAQ,KAAK,CAAC,SAAS,QAAQ,GAC7C;EAGF,MAAM,aAAa,SAAS,KAAK,MAAM,MAAM,KAAK,GAAG,aAAa;EAClE,IAAI,aAAa,GACf;EAGF,MAAM,SAAS,aAAa,MAAM,UAAU;EAC5C,MAAM,SAAS,2BAA2B,OAAO,OAAO,KAAK,gBAAgB,UAAU;EAEvF,KAAK,MAAM,mBAAmB,QAAQ;GACpC,MAAM,eAAe,gBAAgB,OAAO,qBAAqB;GACjE,IAAI,OAAO,IAAI,YAAY,GACzB;GAGF,MAAM,cAAc,iBAAiB,MAAM,IAAI,YAAY;GAC3D,MAAM,WAAW,UAAU,IAAI,WAAW;GAC1C,IAAI,UAAU;IACZ,IAAI,eAAe,UAAU,OAAO,GAAG,GAAG;KACxC,OAAO,KAAK,cAAc,QAAQ,CAAC;KACnC,oBAAoB,IAAI,SAAS,EAAE;IACrC;IACA;GACF;GAEA,MAAM,YAAY,wBAAwB,OAAO,iBAAiB,UAAU;GAC5E,IAAI,cAAc,MAAM,UAAU,KAAK,GAAG,MAAM,UAAU,GAAG,GAAG,OAAO,GAAG,GACxE,OAAO,KAAK,cAAc,SAAS,CAAC;EAExC;CACF;CAEA,KAAK,MAAM,YAAY,UAAU,OAAO,GAAG;EACzC,IAAI,oBAAoB,IAAI,SAAS,EAAE,GACrC;EAEF,IAAI,eAAe,UAAU,OAAO,GAAG,GACrC,OAAO,KAAK,cAAc,QAAQ,CAAC;CAEvC;CAEA,OAAO;AACT"}
|
|
1
|
+
{"version":3,"file":"expand-recurring-events.mjs","names":[],"sources":["../../../src/utils/expand-recurring-events/expand-recurring-events.ts"],"sourcesContent":["import dayjs from 'dayjs';\nimport * as rruleAll from 'rrule';\n\nconst RRule = (\n 'default' in rruleAll ? (rruleAll as any).default.RRule : rruleAll.RRule\n) as typeof rruleAll.RRule;\nimport { DateTimeStringValue, ScheduleEventData, ScheduleRecurrenceData } from '../../types';\nimport { validateEvent } from '../validate-event/validate-event';\n\ninterface ExpandRecurringEventsInput {\n events: ScheduleEventData[] | undefined;\n rangeStart: Date | string;\n rangeEnd: Date | string;\n expansionLimit?: number;\n}\n\nfunction getRecurrenceKey(recurringEventId: string | number, recurrenceId: DateTimeStringValue) {\n return `${recurringEventId}::${recurrenceId}`;\n}\n\nfunction overlapsRange(\n eventStart: dayjs.Dayjs,\n eventEnd: dayjs.Dayjs,\n rangeStart: dayjs.Dayjs,\n rangeEnd: dayjs.Dayjs\n) {\n return (\n (eventEnd.isAfter(rangeStart) || eventEnd.isSame(rangeStart)) &&\n (eventStart.isBefore(rangeEnd) || eventStart.isSame(rangeEnd))\n );\n}\n\nfunction getExdateSet(recurrence: ScheduleRecurrenceData | undefined) {\n if (!recurrence?.exdate) {\n return new Set<string>();\n }\n\n const values = recurrence.exdate\n .map((value) => dayjs(value))\n .filter((value) => value.isValid())\n .map((value) => value.format('YYYY-MM-DD HH:mm:ss'));\n\n return new Set(values);\n}\n\nfunction toWallClockDate(value: dayjs.Dayjs) {\n return new Date(\n Date.UTC(\n value.year(),\n value.month(),\n value.date(),\n value.hour(),\n value.minute(),\n value.second(),\n value.millisecond()\n )\n );\n}\n\nfunction fromWallClockDate(value: Date) {\n const result = new Date(2000, 0, 1, 12);\n result.setFullYear(value.getUTCFullYear(), value.getUTCMonth(), value.getUTCDate());\n result.setHours(\n value.getUTCHours(),\n value.getUTCMinutes(),\n value.getUTCSeconds(),\n value.getUTCMilliseconds()\n );\n\n return dayjs(result);\n}\n\nfunction getWallClockDurationMs(start: dayjs.Dayjs, end: dayjs.Dayjs) {\n return toWallClockDate(end).getTime() - toWallClockDate(start).getTime();\n}\n\nfunction getRRuleString(rule: string) {\n const normalized = rule.trim();\n if (!normalized.includes('\\n')) {\n return normalized.startsWith('RRULE:') ? normalized.replace(/^RRULE:/, '') : normalized;\n }\n\n const rruleLine = normalized\n .split('\\n')\n .map((line) => line.trim())\n .find((line) => line.startsWith('RRULE:'));\n\n return rruleLine ? rruleLine.replace(/^RRULE:/, '') : normalized;\n}\n\nfunction getOccurrenceStartsInRange(\n event: ScheduleEventData,\n rangeStart: dayjs.Dayjs,\n rangeEnd: dayjs.Dayjs,\n expansionLimit: number,\n durationMs: number\n) {\n const dtstart = dayjs(event.recurrence?.dtstart || event.start);\n if (!dtstart.isValid() || !event.recurrence) {\n return [];\n }\n\n try {\n const options = RRule.parseString(getRRuleString(event.recurrence.rrule));\n options.dtstart = toWallClockDate(dtstart);\n const rule = new RRule(options);\n\n const searchStart = new Date(toWallClockDate(rangeStart).getTime() - Math.max(0, durationMs));\n const results = rule.between(searchStart, toWallClockDate(rangeEnd), true);\n return results.slice(0, expansionLimit);\n } catch {\n return [];\n }\n}\n\nfunction isEventInRange(event: ScheduleEventData, rangeStart: dayjs.Dayjs, rangeEnd: dayjs.Dayjs) {\n const start = dayjs(event.start);\n const end = dayjs(event.end);\n\n if (!start.isValid() || !end.isValid()) {\n return false;\n }\n\n return overlapsRange(start, end, rangeStart, rangeEnd);\n}\n\nfunction createGeneratedInstance(\n event: ScheduleEventData,\n occurrenceStart: dayjs.Dayjs,\n occurrenceEnd: dayjs.Dayjs\n): ScheduleEventData {\n const recurrenceId = occurrenceStart.format('YYYY-MM-DD HH:mm:ss');\n const { recurrence, ...eventWithoutRecurrence } = event;\n\n return {\n ...eventWithoutRecurrence,\n id: `${event.id}::${recurrenceId}`,\n start: occurrenceStart.format('YYYY-MM-DD HH:mm:ss'),\n end: occurrenceEnd.format('YYYY-MM-DD HH:mm:ss'),\n recurringEventId: event.id,\n recurrenceId,\n recurringInstance: {\n isRecurringInstance: true,\n recurringEventId: event.id,\n recurrenceId,\n originalStart: occurrenceStart.format('YYYY-MM-DD HH:mm:ss'),\n originalEnd: occurrenceEnd.format('YYYY-MM-DD HH:mm:ss'),\n },\n };\n}\n\nconst DEFAULT_EXPANSION_LIMIT = 2000;\n\nexport function expandRecurringEvents({\n events,\n rangeStart,\n rangeEnd,\n expansionLimit = DEFAULT_EXPANSION_LIMIT,\n}: ExpandRecurringEventsInput): ScheduleEventData[] {\n if (!events || events.length === 0) {\n return [];\n }\n\n const start = dayjs(rangeStart);\n const end = dayjs(rangeEnd);\n\n if (!start.isValid() || !end.isValid()) {\n return [];\n }\n\n const regularEvents: ScheduleEventData[] = [];\n const recurringEvents: ScheduleEventData[] = [];\n const overrides = new Map<string, ScheduleEventData>();\n\n for (const event of events) {\n if (event.recurringEventId && event.recurrenceId) {\n overrides.set(getRecurrenceKey(event.recurringEventId, event.recurrenceId), event);\n continue;\n }\n\n if (event.recurrence?.rrule) {\n recurringEvents.push(event);\n continue;\n }\n\n regularEvents.push(event);\n }\n\n const output: ScheduleEventData[] = [];\n const consumedOverrideIds = new Set<string | number>();\n\n for (const event of regularEvents) {\n if (isEventInRange(event, start, end)) {\n output.push(validateEvent(event));\n }\n }\n\n for (const event of recurringEvents) {\n const eventStart = dayjs(event.recurrence?.dtstart || event.start);\n const eventEnd = dayjs(event.end);\n\n if (!eventStart.isValid() || !eventEnd.isValid()) {\n continue;\n }\n\n const durationMs = getWallClockDurationMs(dayjs(event.start), eventEnd);\n if (durationMs < 0) {\n continue;\n }\n\n const exdate = getExdateSet(event.recurrence);\n const starts = getOccurrenceStartsInRange(event, start, end, expansionLimit, durationMs);\n\n for (const wallClockStart of starts) {\n const occurrenceStart = fromWallClockDate(wallClockStart);\n const recurrenceId = occurrenceStart.format('YYYY-MM-DD HH:mm:ss');\n if (exdate.has(recurrenceId)) {\n continue;\n }\n\n const overrideKey = getRecurrenceKey(event.id, recurrenceId);\n const override = overrides.get(overrideKey);\n if (override) {\n if (isEventInRange(override, start, end)) {\n output.push(validateEvent(override));\n consumedOverrideIds.add(override.id);\n }\n continue;\n }\n\n const occurrenceEnd = fromWallClockDate(new Date(wallClockStart.getTime() + durationMs));\n const generated = createGeneratedInstance(event, occurrenceStart, occurrenceEnd);\n if (overlapsRange(dayjs(generated.start), dayjs(generated.end), start, end)) {\n output.push(validateEvent(generated));\n }\n }\n }\n\n for (const override of overrides.values()) {\n if (consumedOverrideIds.has(override.id)) {\n continue;\n }\n if (isEventInRange(override, start, end)) {\n output.push(validateEvent(override));\n }\n }\n\n return output;\n}\n\nexport { DEFAULT_EXPANSION_LIMIT };\n"],"mappings":"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"}
|
|
@@ -1,12 +1,24 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import dayjs from "dayjs";
|
|
3
3
|
//#region packages/@mantine/schedule/src/utils/is-events-overlap/is-events-overlap.ts
|
|
4
|
+
const timestampsCache = /* @__PURE__ */ new WeakMap();
|
|
5
|
+
function getTimestamps(event) {
|
|
6
|
+
const cached = timestampsCache.get(event);
|
|
7
|
+
if (cached && cached.start === event.start && cached.end === event.end) return cached;
|
|
8
|
+
const timestamps = {
|
|
9
|
+
start: event.start,
|
|
10
|
+
end: event.end,
|
|
11
|
+
startTimestamp: dayjs(event.start).valueOf(),
|
|
12
|
+
endTimestamp: dayjs(event.end).valueOf()
|
|
13
|
+
};
|
|
14
|
+
timestampsCache.set(event, timestamps);
|
|
15
|
+
return timestamps;
|
|
16
|
+
}
|
|
4
17
|
/** Returns true if two events overlap in time */
|
|
5
18
|
function isEventsOverlap(event1, event2) {
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
return start1 < dayjs(event2.end).valueOf() && start2 < end1;
|
|
19
|
+
const first = getTimestamps(event1);
|
|
20
|
+
const second = getTimestamps(event2);
|
|
21
|
+
return first.startTimestamp < second.endTimestamp && second.startTimestamp < first.endTimestamp;
|
|
10
22
|
}
|
|
11
23
|
//#endregion
|
|
12
24
|
export { isEventsOverlap };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"is-events-overlap.mjs","names":[],"sources":["../../../src/utils/is-events-overlap/is-events-overlap.ts"],"sourcesContent":["import dayjs from 'dayjs';\nimport { ScheduleEventData } from '../../types';\n\
|
|
1
|
+
{"version":3,"file":"is-events-overlap.mjs","names":[],"sources":["../../../src/utils/is-events-overlap/is-events-overlap.ts"],"sourcesContent":["import dayjs from 'dayjs';\nimport { ScheduleEventData } from '../../types';\n\ninterface CachedTimestamps {\n start: ScheduleEventData['start'];\n end: ScheduleEventData['end'];\n startTimestamp: number;\n endTimestamp: number;\n}\n\nconst timestampsCache = new WeakMap<ScheduleEventData, CachedTimestamps>();\n\nfunction getTimestamps(event: ScheduleEventData): CachedTimestamps {\n const cached = timestampsCache.get(event);\n\n if (cached && cached.start === event.start && cached.end === event.end) {\n return cached;\n }\n\n const timestamps: CachedTimestamps = {\n start: event.start,\n end: event.end,\n startTimestamp: dayjs(event.start).valueOf(),\n endTimestamp: dayjs(event.end).valueOf(),\n };\n\n timestampsCache.set(event, timestamps);\n\n return timestamps;\n}\n\n/** Returns true if two events overlap in time */\nexport function isEventsOverlap(event1: ScheduleEventData, event2: ScheduleEventData) {\n const first = getTimestamps(event1);\n const second = getTimestamps(event2);\n return first.startTimestamp < second.endTimestamp && second.startTimestamp < first.endTimestamp;\n}\n"],"mappings":";;;AAUA,MAAM,kCAAkB,IAAI,QAA6C;AAEzE,SAAS,cAAc,OAA4C;CACjE,MAAM,SAAS,gBAAgB,IAAI,KAAK;CAExC,IAAI,UAAU,OAAO,UAAU,MAAM,SAAS,OAAO,QAAQ,MAAM,KACjE,OAAO;CAGT,MAAM,aAA+B;EACnC,OAAO,MAAM;EACb,KAAK,MAAM;EACX,gBAAgB,MAAM,MAAM,KAAK,CAAC,CAAC,QAAQ;EAC3C,cAAc,MAAM,MAAM,GAAG,CAAC,CAAC,QAAQ;CACzC;CAEA,gBAAgB,IAAI,OAAO,UAAU;CAErC,OAAO;AACT;;AAGA,SAAgB,gBAAgB,QAA2B,QAA2B;CACpF,MAAM,QAAQ,cAAc,MAAM;CAClC,MAAM,SAAS,cAAc,MAAM;CACnC,OAAO,MAAM,iBAAiB,OAAO,gBAAgB,OAAO,iBAAiB,MAAM;AACrF"}
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ScheduleEventData } from '../../../types';
|
|
2
|
+
/** An event stored in a positioning column together with its precomputed all-day flag. */
|
|
3
|
+
export interface ColumnEvent {
|
|
4
|
+
event: ScheduleEventData;
|
|
5
|
+
allDay: boolean;
|
|
6
|
+
}
|
|
2
7
|
interface FindAvailableColumnInput {
|
|
3
|
-
columns: Map<string,
|
|
8
|
+
columns: Map<string, ColumnEvent[]>;
|
|
4
9
|
event: ScheduleEventData;
|
|
5
10
|
allDay: boolean;
|
|
6
|
-
allWeekDays: DateStringValue[];
|
|
7
11
|
}
|
|
8
12
|
export declare function findAvailableColumn(input: FindAvailableColumnInput): number;
|
|
9
13
|
export {};
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { GetStylesApi } from '@mantine/core';
|
|
2
2
|
import { ScheduleLabelsOverride } from '../../labels';
|
|
3
|
-
import { DateLabelFormat, DateStringValue, DayOfWeek, ScheduleMode } from '../../types';
|
|
3
|
+
import { DateLabelFormat, DateStringValue, DayOfWeek, ScheduleEventData, ScheduleMode } from '../../types';
|
|
4
4
|
import { GroupedEvents } from './get-year-view-events/get-year-view-events';
|
|
5
5
|
import type { YearViewFactory } from './YearView';
|
|
6
|
+
export type YearViewRenderDay = (date: DateStringValue, events: ScheduleEventData[]) => React.ReactNode;
|
|
6
7
|
export interface YearViewDayKeydownPayload {
|
|
7
8
|
weekIndex: number;
|
|
8
9
|
dayIndex: number;
|
|
@@ -43,6 +44,12 @@ export interface YearViewMonthSettings {
|
|
|
43
44
|
mode?: ScheduleMode;
|
|
44
45
|
/** If true, days from adjacent months are displayed @default true */
|
|
45
46
|
withOutsideDays?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* A function to replace the entire content of a day cell, called with the day date
|
|
49
|
+
* and the events grouped on that day – the same list that is used to render the default
|
|
50
|
+
* indicators. When set, default event indicators are not rendered.
|
|
51
|
+
*/
|
|
52
|
+
renderDay?: YearViewRenderDay;
|
|
46
53
|
}
|
|
47
54
|
export interface YearViewMonthProps extends YearViewMonthSettings {
|
|
48
55
|
/** Month to display, Date object or date string in `YYYY-MM-DD` format */
|
|
@@ -61,4 +68,4 @@ export interface YearViewMonthProps extends YearViewMonthSettings {
|
|
|
61
68
|
dayIndex: number;
|
|
62
69
|
};
|
|
63
70
|
}
|
|
64
|
-
export declare function YearViewMonth({ month, getStyles, monthLabelFormat, withWeekNumbers, withWeekDays, locale, firstDayOfWeek, weekdayFormat, weekendDays, withWeekendDays, getDayProps, onDayClick, onWeekNumberClick, onMonthClick, getWeekNumberProps, highlightToday, groupedEvents, mode, withOutsideDays, __getDayRef, __onDayKeyDown, firstDayIndex, }: YearViewMonthProps): import("react/jsx-runtime").JSX.Element;
|
|
71
|
+
export declare function YearViewMonth({ month, getStyles, monthLabelFormat, withWeekNumbers, withWeekDays, locale, firstDayOfWeek, weekdayFormat, weekendDays, withWeekendDays, getDayProps, onDayClick, onWeekNumberClick, onMonthClick, getWeekNumberProps, highlightToday, groupedEvents, mode, withOutsideDays, renderDay, __getDayRef, __onDayKeyDown, firstDayIndex, }: YearViewMonthProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import type { YearViewCssVariables, YearViewFactory, YearViewProps, YearViewStylesNames } from './YearView';
|
|
2
2
|
export { YearView } from './YearView';
|
|
3
3
|
export type { YearViewProps, YearViewFactory, YearViewStylesNames, YearViewCssVariables };
|
|
4
|
+
export type { YearViewRenderDay } from './YearViewMonth';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mantine/schedule",
|
|
3
|
-
"version": "9.5.
|
|
3
|
+
"version": "9.5.2",
|
|
4
4
|
"description": "Schedule Mantine component",
|
|
5
5
|
"homepage": "https://mantine.dev/",
|
|
6
6
|
"license": "MIT",
|
|
@@ -35,9 +35,9 @@
|
|
|
35
35
|
"directory": "packages/@mantine/schedule"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
|
-
"@mantine/core": "9.5.
|
|
39
|
-
"@mantine/dates": "9.5.
|
|
40
|
-
"@mantine/hooks": "9.5.
|
|
38
|
+
"@mantine/core": "9.5.2",
|
|
39
|
+
"@mantine/dates": "9.5.2",
|
|
40
|
+
"@mantine/hooks": "9.5.2",
|
|
41
41
|
"react": "^19.2.0",
|
|
42
42
|
"react-dom": "^19.2.0"
|
|
43
43
|
},
|