@mantine/schedule 9.7.2 → 9.7.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/cjs/components/DayView/DayView.cjs +45 -29
  2. package/cjs/components/DayView/DayView.cjs.map +1 -1
  3. package/cjs/components/DayView/DayView.module.cjs.map +1 -1
  4. package/cjs/components/MobileMonthView/MobileMonthView.cjs +54 -22
  5. package/cjs/components/MobileMonthView/MobileMonthView.cjs.map +1 -1
  6. package/cjs/components/MobileMonthView/MobileMonthView.module.cjs.map +1 -1
  7. package/cjs/components/MobileMonthView/get-mobile-month-view-weeks.cjs +32 -0
  8. package/cjs/components/MobileMonthView/get-mobile-month-view-weeks.cjs.map +1 -0
  9. package/cjs/components/ResourcesDayView/ResourcesDayView.cjs +15 -7
  10. package/cjs/components/ResourcesDayView/ResourcesDayView.cjs.map +1 -1
  11. package/cjs/components/ResourcesDayView/ResourcesDayView.module.cjs.map +1 -1
  12. package/cjs/components/ResourcesDayView/ResourcesDayViewColumn.cjs +11 -6
  13. package/cjs/components/ResourcesDayView/ResourcesDayViewColumn.cjs.map +1 -1
  14. package/cjs/components/ResourcesWeekView/ResourcesWeekView.cjs +15 -7
  15. package/cjs/components/ResourcesWeekView/ResourcesWeekView.cjs.map +1 -1
  16. package/cjs/components/ResourcesWeekView/ResourcesWeekView.module.cjs.map +1 -1
  17. package/cjs/components/ResourcesWeekView/ResourcesWeekViewRow.cjs +11 -6
  18. package/cjs/components/ResourcesWeekView/ResourcesWeekViewRow.cjs.map +1 -1
  19. package/cjs/components/Schedule/Schedule.cjs +2 -0
  20. package/cjs/components/Schedule/Schedule.cjs.map +1 -1
  21. package/cjs/components/WeekView/WeekView.cjs +29 -19
  22. package/cjs/components/WeekView/WeekView.cjs.map +1 -1
  23. package/cjs/components/WeekView/WeekView.module.cjs.map +1 -1
  24. package/cjs/components/WeekView/WeekViewDay.cjs +13 -7
  25. package/cjs/components/WeekView/WeekViewDay.cjs.map +1 -1
  26. package/cjs/components/YearView/YearView.cjs +1 -1
  27. package/cjs/components/YearView/YearView.cjs.map +1 -1
  28. package/cjs/components/YearView/YearViewMonth.cjs +1 -1
  29. package/cjs/components/YearView/YearViewMonth.cjs.map +1 -1
  30. package/cjs/index.cjs +10 -0
  31. package/cjs/utils/add-minutes-to-time/add-minutes-to-time.cjs +17 -0
  32. package/cjs/utils/add-minutes-to-time/add-minutes-to-time.cjs.map +1 -0
  33. package/cjs/utils/clamp-slot-label-interval/clamp-slot-label-interval.cjs +22 -0
  34. package/cjs/utils/clamp-slot-label-interval/clamp-slot-label-interval.cjs.map +1 -0
  35. package/cjs/utils/get-business-hours-mod/get-business-hours-mod.cjs +74 -17
  36. package/cjs/utils/get-business-hours-mod/get-business-hours-mod.cjs.map +1 -1
  37. package/cjs/utils/get-day-time-intervals/get-day-time-intervals.cjs +7 -2
  38. package/cjs/utils/get-day-time-intervals/get-day-time-intervals.cjs.map +1 -1
  39. package/cjs/utils/get-slot-label-groups/get-slot-label-groups.cjs +26 -0
  40. package/cjs/utils/get-slot-label-groups/get-slot-label-groups.cjs.map +1 -0
  41. package/cjs/{components/YearView → utils/get-visible-week-days}/get-visible-week-days.cjs +1 -1
  42. package/cjs/utils/get-visible-week-days/get-visible-week-days.cjs.map +1 -0
  43. package/esm/components/DayView/DayView.mjs +46 -30
  44. package/esm/components/DayView/DayView.mjs.map +1 -1
  45. package/esm/components/DayView/DayView.module.mjs.map +1 -1
  46. package/esm/components/MobileMonthView/MobileMonthView.mjs +54 -22
  47. package/esm/components/MobileMonthView/MobileMonthView.mjs.map +1 -1
  48. package/esm/components/MobileMonthView/MobileMonthView.module.mjs.map +1 -1
  49. package/esm/components/MobileMonthView/get-mobile-month-view-weeks.mjs +30 -0
  50. package/esm/components/MobileMonthView/get-mobile-month-view-weeks.mjs.map +1 -0
  51. package/esm/components/ResourcesDayView/ResourcesDayView.mjs +16 -8
  52. package/esm/components/ResourcesDayView/ResourcesDayView.mjs.map +1 -1
  53. package/esm/components/ResourcesDayView/ResourcesDayView.module.mjs.map +1 -1
  54. package/esm/components/ResourcesDayView/ResourcesDayViewColumn.mjs +12 -7
  55. package/esm/components/ResourcesDayView/ResourcesDayViewColumn.mjs.map +1 -1
  56. package/esm/components/ResourcesWeekView/ResourcesWeekView.mjs +16 -8
  57. package/esm/components/ResourcesWeekView/ResourcesWeekView.mjs.map +1 -1
  58. package/esm/components/ResourcesWeekView/ResourcesWeekView.module.mjs.map +1 -1
  59. package/esm/components/ResourcesWeekView/ResourcesWeekViewRow.mjs +12 -7
  60. package/esm/components/ResourcesWeekView/ResourcesWeekViewRow.mjs.map +1 -1
  61. package/esm/components/Schedule/Schedule.mjs +2 -0
  62. package/esm/components/Schedule/Schedule.mjs.map +1 -1
  63. package/esm/components/WeekView/WeekView.mjs +30 -20
  64. package/esm/components/WeekView/WeekView.mjs.map +1 -1
  65. package/esm/components/WeekView/WeekView.module.mjs.map +1 -1
  66. package/esm/components/WeekView/WeekViewDay.mjs +14 -8
  67. package/esm/components/WeekView/WeekViewDay.mjs.map +1 -1
  68. package/esm/components/YearView/YearView.mjs +1 -1
  69. package/esm/components/YearView/YearView.mjs.map +1 -1
  70. package/esm/components/YearView/YearViewMonth.mjs +1 -1
  71. package/esm/components/YearView/YearViewMonth.mjs.map +1 -1
  72. package/esm/index.mjs +6 -2
  73. package/esm/utils/add-minutes-to-time/add-minutes-to-time.mjs +17 -0
  74. package/esm/utils/add-minutes-to-time/add-minutes-to-time.mjs.map +1 -0
  75. package/esm/utils/clamp-slot-label-interval/clamp-slot-label-interval.mjs +22 -0
  76. package/esm/utils/clamp-slot-label-interval/clamp-slot-label-interval.mjs.map +1 -0
  77. package/esm/utils/get-business-hours-mod/get-business-hours-mod.mjs +74 -18
  78. package/esm/utils/get-business-hours-mod/get-business-hours-mod.mjs.map +1 -1
  79. package/esm/utils/get-day-time-intervals/get-day-time-intervals.mjs +7 -2
  80. package/esm/utils/get-day-time-intervals/get-day-time-intervals.mjs.map +1 -1
  81. package/esm/utils/get-slot-label-groups/get-slot-label-groups.mjs +26 -0
  82. package/esm/utils/get-slot-label-groups/get-slot-label-groups.mjs.map +1 -0
  83. package/esm/{components/YearView → utils/get-visible-week-days}/get-visible-week-days.mjs +1 -1
  84. package/esm/utils/get-visible-week-days/get-visible-week-days.mjs.map +1 -0
  85. package/lib/components/DayView/DayView.d.ts +3 -1
  86. package/lib/components/MobileMonthView/MobileMonthView.d.ts +2 -0
  87. package/lib/components/MobileMonthView/get-mobile-month-view-weeks.d.ts +11 -0
  88. package/lib/components/ResourcesDayView/ResourcesDayView.d.ts +1 -1
  89. package/lib/components/ResourcesDayView/ResourcesDayViewColumn.d.ts +2 -1
  90. package/lib/components/ResourcesWeekView/ResourcesWeekView.d.ts +1 -1
  91. package/lib/components/ResourcesWeekView/ResourcesWeekViewRow.d.ts +2 -1
  92. package/lib/components/Schedule/Schedule.d.ts +1 -1
  93. package/lib/components/WeekView/WeekView.d.ts +3 -1
  94. package/lib/utils/add-minutes-to-time/add-minutes-to-time.d.ts +1 -0
  95. package/lib/utils/clamp-slot-label-interval/clamp-slot-label-interval.d.ts +9 -0
  96. package/lib/utils/get-business-hours-mod/get-business-hours-mod.d.ts +24 -5
  97. package/lib/utils/get-day-time-intervals/get-day-time-intervals.d.ts +5 -1
  98. package/lib/utils/get-slot-label-groups/get-slot-label-groups.d.ts +15 -0
  99. package/lib/utils/index.d.ts +7 -2
  100. package/package.json +4 -4
  101. package/styles.css +175 -6
  102. package/styles.layer.css +175 -6
  103. package/cjs/components/YearView/get-visible-week-days.cjs.map +0 -1
  104. package/esm/components/YearView/get-visible-week-days.mjs.map +0 -1
  105. /package/lib/{components/YearView → utils/get-visible-week-days}/get-visible-week-days.d.ts +0 -0
@@ -1,7 +1,8 @@
1
1
  "use client";
2
2
  import { getLabel } from "../../labels.mjs";
3
3
  import { clampIntervalMinutes } from "../../utils/clamp-interval-minutes/clamp-interval-minutes.mjs";
4
- import { getBusinessHoursMod } from "../../utils/get-business-hours-mod/get-business-hours-mod.mjs";
4
+ import { getBusinessHoursState } from "../../utils/get-business-hours-mod/get-business-hours-mod.mjs";
5
+ import { addMinutesToTime } from "../../utils/add-minutes-to-time/add-minutes-to-time.mjs";
5
6
  import dayjs from "dayjs";
6
7
  import { Box, UnstyledButton } from "@mantine/core";
7
8
  import { useDatesContext } from "@mantine/dates";
@@ -27,6 +28,13 @@ function WeekViewDay({ day, dayIndex, slots, intervalMinutes, getStyles, weekend
27
28
  onSlotClick?.(String(day), slot.startTime, e);
28
29
  externalOnClick?.(e);
29
30
  };
31
+ const businessHoursState = getBusinessHoursState({
32
+ time: slot.startTime,
33
+ endTime: addMinutesToTime(slot.startTime, clampIntervalMinutes(intervalMinutes)),
34
+ businessHours,
35
+ highlightBusinessHours,
36
+ dayOfWeek
37
+ });
30
38
  return /* @__PURE__ */ jsx(UnstyledButton, {
31
39
  ref: (node) => {
32
40
  if (node && slotsRef?.current) {
@@ -37,17 +45,15 @@ function WeekViewDay({ day, dayIndex, slots, intervalMinutes, getStyles, weekend
37
45
  ...getStyles("weekViewDaySlot"),
38
46
  mod: {
39
47
  "hour-start": slot.isHourStart,
40
- ...getBusinessHoursMod({
41
- time: slot.startTime,
42
- businessHours,
43
- highlightBusinessHours,
44
- dayOfWeek
45
- }),
48
+ ...businessHoursState.mod,
46
49
  "drop-target": isDropTarget,
47
50
  "drag-selected": isDragSelected,
48
51
  static: mode === "static"
49
52
  },
50
- __vars: { "--slot-size": `${clampIntervalMinutes(intervalMinutes) / 60}` },
53
+ __vars: {
54
+ "--slot-size": `${clampIntervalMinutes(intervalMinutes) / 60}`,
55
+ ...businessHoursState.vars
56
+ },
51
57
  "aria-label": `${getLabel("timeSlot", labels)} ${dayGroup} ${slot.startTime} - ${slot.endTime}`,
52
58
  tabIndex: mode === "static" ? -1 : isFirstSlot ? 0 : -1,
53
59
  "data-drag-slot-index": withDragSlotSelect && mode !== "static" ? slotIndex : void 0,
@@ -1 +1 @@
1
- {"version":3,"file":"WeekViewDay.mjs","names":[],"sources":["../../../src/components/WeekView/WeekViewDay.tsx"],"sourcesContent":["import dayjs from 'dayjs';\nimport { Box, GetStylesApi, UnstyledButton } from '@mantine/core';\nimport { useDatesContext } from '@mantine/dates';\nimport { getLabel, ScheduleLabelsOverride } from '../../labels';\nimport { DateStringValue, DateTimeStringValue, DayOfWeek, ScheduleMode } from '../../types';\nimport {\n BusinessHoursValue,\n clampIntervalMinutes,\n DayTimeInterval,\n getBusinessHoursMod,\n} from '../../utils';\nimport type { WeekViewControlsRef } from './handle-week-view-key-down';\nimport type { WeekViewFactory } from './WeekView';\n\nexport interface WeekViewDayProps {\n /** Date to display */\n day: Date | DateStringValue;\n\n /** Index of this day in the week */\n dayIndex: number;\n\n /** Slots intervals */\n slots: DayTimeInterval[];\n\n /** Number of minutes for each interval, used to calculate slot height */\n intervalMinutes: number;\n\n /** `useStyles` return value of `WeekView` */\n getStyles: GetStylesApi<WeekViewFactory>;\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 /** Events list */\n children?: React.ReactNode;\n\n /** Labels override */\n labels?: ScheduleLabelsOverride;\n\n /** If set to true, highlights business hours with white background */\n highlightBusinessHours?: boolean;\n\n /** Business hours range in `HH:mm:ss` format, or per-day record keyed by day of the week */\n businessHours?: BusinessHoursValue;\n\n /** If true, slots are drop targets for drag and drop */\n withEventsDragAndDrop?: boolean;\n\n /** Called when dragging over day slots container */\n onDaySlotsDragOver?: (e: React.DragEvent<HTMLDivElement>, day: string, dayIndex: number) => void;\n\n /** Called when dragging leaves day slots container */\n onDaySlotsDragLeave?: () => void;\n\n /** Called when dropping on day slots container */\n onDaySlotsDrop?: (e: React.DragEvent<HTMLDivElement>, day: string, dayIndex: number) => void;\n\n /** Called when slot is clicked */\n onSlotClick?: (day: string, slotTime: string, event: React.MouseEvent<HTMLButtonElement>) => void;\n\n /** Index of the slot that is currently a drop target */\n dropTargetSlotIndex?: number;\n\n /** Interaction mode: 'default' allows all interactions, 'static' disables event interactions */\n mode?: ScheduleMode;\n\n /** Ref for keyboard navigation */\n slotsRef?: WeekViewControlsRef;\n\n /** Index of the first focusable slot */\n firstSlotIndex?: { dayIndex: number; slotIndex: number };\n\n /** Keyboard event handler for slots */\n onSlotKeyDown?: (\n event: React.KeyboardEvent<HTMLButtonElement>,\n dayIndex: number,\n slotIndex: number\n ) => void;\n\n /** Called when Arrow Up is pressed on the first slot, used to navigate to all-day slot */\n onFirstSlotArrowUp?: (dayIndex: number) => void;\n\n /** If set, enables drag-to-select time slot ranges */\n withDragSlotSelect?: boolean;\n\n /** Called when pointer down on a slot for drag selection */\n onSlotPointerDown?: (\n event: React.PointerEvent<HTMLButtonElement>,\n index: number,\n group: string\n ) => void;\n\n /** Function to check if a slot is drag-selected */\n isSlotDragSelected?: (index: number, group: string) => boolean;\n\n /** Ref callback for the day slots container */\n daySlotsContainerRef?: (node: HTMLDivElement | null) => void;\n\n /** Function to get additional props for each time slot */\n getTimeSlotProps?: (data: {\n start: DateTimeStringValue;\n end: DateTimeStringValue;\n }) => Record<string, any> | undefined;\n}\n\nexport function WeekViewDay({\n day,\n dayIndex,\n slots,\n intervalMinutes,\n getStyles,\n weekendDays,\n children,\n labels,\n highlightBusinessHours,\n businessHours,\n withEventsDragAndDrop,\n onDaySlotsDragOver,\n onDaySlotsDragLeave,\n onDaySlotsDrop,\n onSlotClick,\n dropTargetSlotIndex,\n mode,\n slotsRef,\n firstSlotIndex,\n onSlotKeyDown,\n onFirstSlotArrowUp,\n withDragSlotSelect,\n onSlotPointerDown,\n isSlotDragSelected,\n daySlotsContainerRef,\n getTimeSlotProps,\n}: WeekViewDayProps) {\n const ctx = useDatesContext();\n const dayOfWeek = dayjs(day).day() as DayOfWeek;\n const weekend = ctx.getWeekendDays(weekendDays).includes(dayOfWeek);\n const today = dayjs(day).isSame(dayjs(), 'day');\n\n const dayGroup = dayjs(day).format('YYYY-MM-DD');\n\n const items = slots.map((slot, slotIndex) => {\n const isDropTarget = dropTargetSlotIndex === slotIndex;\n const isFirstSlot =\n firstSlotIndex?.dayIndex === dayIndex && firstSlotIndex?.slotIndex === slotIndex;\n const isDragSelected = isSlotDragSelected?.(slotIndex, dayGroup) || false;\n const slotStart = `${dayGroup} ${slot.startTime}` as DateTimeStringValue;\n const slotEnd = `${dayGroup} ${slot.endTime}` as DateTimeStringValue;\n const { onClick: externalOnClick, ...externalSlotProps } =\n getTimeSlotProps?.({ start: slotStart, end: slotEnd }) || {};\n\n const handleClick =\n mode === 'static'\n ? undefined\n : (e: React.MouseEvent<HTMLButtonElement>) => {\n onSlotClick?.(String(day), slot.startTime, e);\n externalOnClick?.(e);\n };\n\n return (\n <UnstyledButton\n key={slot.startTime}\n ref={(node) => {\n if (node && slotsRef?.current) {\n if (!slotsRef.current[dayIndex]) {\n slotsRef.current[dayIndex] = [];\n }\n slotsRef.current[dayIndex][slotIndex] = node;\n }\n }}\n {...getStyles('weekViewDaySlot')}\n mod={{\n 'hour-start': slot.isHourStart,\n ...getBusinessHoursMod({\n time: slot.startTime,\n businessHours,\n highlightBusinessHours,\n dayOfWeek,\n }),\n 'drop-target': isDropTarget,\n 'drag-selected': isDragSelected,\n static: mode === 'static',\n }}\n __vars={{ '--slot-size': `${clampIntervalMinutes(intervalMinutes) / 60}` }}\n aria-label={`${getLabel('timeSlot', labels)} ${dayGroup} ${slot.startTime} - ${slot.endTime}`}\n tabIndex={mode === 'static' ? -1 : isFirstSlot ? 0 : -1}\n data-drag-slot-index={withDragSlotSelect && mode !== 'static' ? slotIndex : undefined}\n data-drag-slot-group={withDragSlotSelect && mode !== 'static' ? dayGroup : undefined}\n onKeyDown={(e) => {\n if (slotIndex === 0 && e.key === 'ArrowUp' && onFirstSlotArrowUp) {\n e.preventDefault();\n onFirstSlotArrowUp(dayIndex);\n } else if (onSlotKeyDown) {\n onSlotKeyDown(e, dayIndex, slotIndex);\n }\n }}\n onPointerDown={\n withDragSlotSelect && mode !== 'static'\n ? (e) => onSlotPointerDown?.(e, slotIndex, dayGroup)\n : undefined\n }\n onClick={handleClick}\n onDragOver={\n withEventsDragAndDrop && mode !== 'static' ? (e) => e.preventDefault() : undefined\n }\n {...externalSlotProps}\n />\n );\n });\n\n return (\n <Box {...getStyles('weekViewDay')} mod={{ today, weekend }}>\n <Box\n ref={daySlotsContainerRef}\n mod={{ today }}\n {...getStyles('weekViewDaySlots')}\n onDragOver={\n withEventsDragAndDrop && mode !== 'static'\n ? (e) => onDaySlotsDragOver?.(e, String(day), dayIndex)\n : undefined\n }\n onDragLeave={withEventsDragAndDrop && mode !== 'static' ? onDaySlotsDragLeave : undefined}\n onDrop={\n withEventsDragAndDrop && mode !== 'static'\n ? (e) => onDaySlotsDrop?.(e, String(day), dayIndex)\n : undefined\n }\n >\n {children}\n {items}\n </Box>\n </Box>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"WeekViewDay.mjs","names":[],"sources":["../../../src/components/WeekView/WeekViewDay.tsx"],"sourcesContent":["import dayjs from 'dayjs';\nimport { Box, GetStylesApi, UnstyledButton } from '@mantine/core';\nimport { useDatesContext } from '@mantine/dates';\nimport { getLabel, ScheduleLabelsOverride } from '../../labels';\nimport { DateStringValue, DateTimeStringValue, DayOfWeek, ScheduleMode } from '../../types';\nimport {\n BusinessHoursValue,\n clampIntervalMinutes,\n DayTimeInterval,\n addMinutesToTime,\n getBusinessHoursState,\n} from '../../utils';\nimport type { WeekViewControlsRef } from './handle-week-view-key-down';\nimport type { WeekViewFactory } from './WeekView';\n\nexport interface WeekViewDayProps {\n /** Date to display */\n day: Date | DateStringValue;\n\n /** Index of this day in the week */\n dayIndex: number;\n\n /** Slots intervals */\n slots: DayTimeInterval[];\n\n /** Number of minutes for each interval, used to calculate slot height */\n intervalMinutes: number;\n\n /** `useStyles` return value of `WeekView` */\n getStyles: GetStylesApi<WeekViewFactory>;\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 /** Events list */\n children?: React.ReactNode;\n\n /** Labels override */\n labels?: ScheduleLabelsOverride;\n\n /** If set to true, highlights business hours with white background */\n highlightBusinessHours?: boolean;\n\n /** Business hours range in `HH:mm:ss` format, or per-day record keyed by day of the week */\n businessHours?: BusinessHoursValue;\n\n /** If true, slots are drop targets for drag and drop */\n withEventsDragAndDrop?: boolean;\n\n /** Called when dragging over day slots container */\n onDaySlotsDragOver?: (e: React.DragEvent<HTMLDivElement>, day: string, dayIndex: number) => void;\n\n /** Called when dragging leaves day slots container */\n onDaySlotsDragLeave?: () => void;\n\n /** Called when dropping on day slots container */\n onDaySlotsDrop?: (e: React.DragEvent<HTMLDivElement>, day: string, dayIndex: number) => void;\n\n /** Called when slot is clicked */\n onSlotClick?: (day: string, slotTime: string, event: React.MouseEvent<HTMLButtonElement>) => void;\n\n /** Index of the slot that is currently a drop target */\n dropTargetSlotIndex?: number;\n\n /** Interaction mode: 'default' allows all interactions, 'static' disables event interactions */\n mode?: ScheduleMode;\n\n /** Ref for keyboard navigation */\n slotsRef?: WeekViewControlsRef;\n\n /** Index of the first focusable slot */\n firstSlotIndex?: { dayIndex: number; slotIndex: number };\n\n /** Keyboard event handler for slots */\n onSlotKeyDown?: (\n event: React.KeyboardEvent<HTMLButtonElement>,\n dayIndex: number,\n slotIndex: number\n ) => void;\n\n /** Called when Arrow Up is pressed on the first slot, used to navigate to all-day slot */\n onFirstSlotArrowUp?: (dayIndex: number) => void;\n\n /** If set, enables drag-to-select time slot ranges */\n withDragSlotSelect?: boolean;\n\n /** Called when pointer down on a slot for drag selection */\n onSlotPointerDown?: (\n event: React.PointerEvent<HTMLButtonElement>,\n index: number,\n group: string\n ) => void;\n\n /** Function to check if a slot is drag-selected */\n isSlotDragSelected?: (index: number, group: string) => boolean;\n\n /** Ref callback for the day slots container */\n daySlotsContainerRef?: (node: HTMLDivElement | null) => void;\n\n /** Function to get additional props for each time slot */\n getTimeSlotProps?: (data: {\n start: DateTimeStringValue;\n end: DateTimeStringValue;\n }) => Record<string, any> | undefined;\n}\n\nexport function WeekViewDay({\n day,\n dayIndex,\n slots,\n intervalMinutes,\n getStyles,\n weekendDays,\n children,\n labels,\n highlightBusinessHours,\n businessHours,\n withEventsDragAndDrop,\n onDaySlotsDragOver,\n onDaySlotsDragLeave,\n onDaySlotsDrop,\n onSlotClick,\n dropTargetSlotIndex,\n mode,\n slotsRef,\n firstSlotIndex,\n onSlotKeyDown,\n onFirstSlotArrowUp,\n withDragSlotSelect,\n onSlotPointerDown,\n isSlotDragSelected,\n daySlotsContainerRef,\n getTimeSlotProps,\n}: WeekViewDayProps) {\n const ctx = useDatesContext();\n const dayOfWeek = dayjs(day).day() as DayOfWeek;\n const weekend = ctx.getWeekendDays(weekendDays).includes(dayOfWeek);\n const today = dayjs(day).isSame(dayjs(), 'day');\n\n const dayGroup = dayjs(day).format('YYYY-MM-DD');\n\n const items = slots.map((slot, slotIndex) => {\n const isDropTarget = dropTargetSlotIndex === slotIndex;\n const isFirstSlot =\n firstSlotIndex?.dayIndex === dayIndex && firstSlotIndex?.slotIndex === slotIndex;\n const isDragSelected = isSlotDragSelected?.(slotIndex, dayGroup) || false;\n const slotStart = `${dayGroup} ${slot.startTime}` as DateTimeStringValue;\n const slotEnd = `${dayGroup} ${slot.endTime}` as DateTimeStringValue;\n const { onClick: externalOnClick, ...externalSlotProps } =\n getTimeSlotProps?.({ start: slotStart, end: slotEnd }) || {};\n\n const handleClick =\n mode === 'static'\n ? undefined\n : (e: React.MouseEvent<HTMLButtonElement>) => {\n onSlotClick?.(String(day), slot.startTime, e);\n externalOnClick?.(e);\n };\n\n const businessHoursState = getBusinessHoursState({\n time: slot.startTime,\n endTime: addMinutesToTime(slot.startTime, clampIntervalMinutes(intervalMinutes)),\n businessHours,\n highlightBusinessHours,\n dayOfWeek,\n });\n\n return (\n <UnstyledButton\n key={slot.startTime}\n ref={(node) => {\n if (node && slotsRef?.current) {\n if (!slotsRef.current[dayIndex]) {\n slotsRef.current[dayIndex] = [];\n }\n slotsRef.current[dayIndex][slotIndex] = node;\n }\n }}\n {...getStyles('weekViewDaySlot')}\n mod={{\n 'hour-start': slot.isHourStart,\n ...businessHoursState.mod,\n 'drop-target': isDropTarget,\n 'drag-selected': isDragSelected,\n static: mode === 'static',\n }}\n __vars={{\n '--slot-size': `${clampIntervalMinutes(intervalMinutes) / 60}`,\n ...businessHoursState.vars,\n }}\n aria-label={`${getLabel('timeSlot', labels)} ${dayGroup} ${slot.startTime} - ${slot.endTime}`}\n tabIndex={mode === 'static' ? -1 : isFirstSlot ? 0 : -1}\n data-drag-slot-index={withDragSlotSelect && mode !== 'static' ? slotIndex : undefined}\n data-drag-slot-group={withDragSlotSelect && mode !== 'static' ? dayGroup : undefined}\n onKeyDown={(e) => {\n if (slotIndex === 0 && e.key === 'ArrowUp' && onFirstSlotArrowUp) {\n e.preventDefault();\n onFirstSlotArrowUp(dayIndex);\n } else if (onSlotKeyDown) {\n onSlotKeyDown(e, dayIndex, slotIndex);\n }\n }}\n onPointerDown={\n withDragSlotSelect && mode !== 'static'\n ? (e) => onSlotPointerDown?.(e, slotIndex, dayGroup)\n : undefined\n }\n onClick={handleClick}\n onDragOver={\n withEventsDragAndDrop && mode !== 'static' ? (e) => e.preventDefault() : undefined\n }\n {...externalSlotProps}\n />\n );\n });\n\n return (\n <Box {...getStyles('weekViewDay')} mod={{ today, weekend }}>\n <Box\n ref={daySlotsContainerRef}\n mod={{ today }}\n {...getStyles('weekViewDaySlots')}\n onDragOver={\n withEventsDragAndDrop && mode !== 'static'\n ? (e) => onDaySlotsDragOver?.(e, String(day), dayIndex)\n : undefined\n }\n onDragLeave={withEventsDragAndDrop && mode !== 'static' ? onDaySlotsDragLeave : undefined}\n onDrop={\n withEventsDragAndDrop && mode !== 'static'\n ? (e) => onDaySlotsDrop?.(e, String(day), dayIndex)\n : undefined\n }\n >\n {children}\n {items}\n </Box>\n </Box>\n );\n}\n"],"mappings":"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"}
@@ -4,8 +4,8 @@ import { isSameMonth } from "../../utils/is-same-month/is-same-month.mjs";
4
4
  import { getMonthsByQuarter } from "../../utils/get-months-by-quarter/get-months-by-quarter.mjs";
5
5
  import { toDateString } from "../../utils/to-date-string/to-date-string.mjs";
6
6
  import { expandRecurringEvents } from "../../utils/expand-recurring-events/expand-recurring-events.mjs";
7
+ import { getHiddenWeekendColumns, getVisibleWeekDays } from "../../utils/get-visible-week-days/get-visible-week-days.mjs";
7
8
  import { ScheduleHeaderBase } from "../ScheduleHeader/ScheduleHeaderBase.mjs";
8
- import { getHiddenWeekendColumns, getVisibleWeekDays } from "./get-visible-week-days.mjs";
9
9
  import { getYearViewEvents } from "./get-year-view-events/get-year-view-events.mjs";
10
10
  import { handleYearViewKeyDown } from "./handle-year-view-key-down.mjs";
11
11
  import { YearViewMonth } from "./YearViewMonth.mjs";
@@ -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 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":";;;;;;;;;;;;;;;;;;AA6GA,MAAM,eAAe;CACnB,kBAAkB;CAClB,kBAAkB;CAClB,cAAc;CACd,iBAAiB;CACjB,gBAAgB;CAChB,YAAY;CACZ,iBAAiB;CACjB,MAAM;AACR;AAEA,MAAM,eAAe,oBAAqC,QAAQ,EAAE,cAAc,EAChF,UAAU,EAAE,sBAAsB,WAAW,KAAA,IAAY,UAAU,MAAM,IAAI,KAAA,EAAU,EACzF,EAAE;AAEF,MAAa,WAAW,SAA0B,WAAW;CAC3D,MAAM,QAAQ,SAAS,YAAY,cAAc,MAAM;CACvD,MAAM,EAEJ,MACA,cACA,QAGA,kBACA,iBACA,cACA,QACA,gBACA,eACA,aACA,iBACA,cACA,YACA,mBACA,aACA,oBACA,gBACA,QACA,iBACA,WAGA,YACA,sBACA,cACA,sBACA,kBACA,mBACA,iBAGA,kBACA,YACA,WACA,OACA,QACA,UACA,MACA,YACA,QACA,MACA,0BACA,GAAG,WACD;CAEJ,MAAM,MAAM,gBAAgB;CAE5B,MAAM,YAAY,UAA2B;EAC3C,MAAM;EACN,SAAA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,cAAc;CAChB,CAAC;CAED,MAAM,EAAE,oBAAoB,mBAAmB,qBAAsC;EACnF;EACA;EACA;CACF,CAAC;CAED,MAAM,iBAAiB;EACrB,YAAY;EACZ,QAAQ;EACR;EACA;EACA;CACF;CAEA,MAAM,iBAAiB,sBAAsB;EAC3C;EACA,YAAY,MAAM,IAAI,CAAC,CAAC,QAAQ,MAAM,CAAC,CAAC,OAAO;EAC/C,UAAU,MAAM,IAAI,CAAC,CAAC,MAAM,MAAM,CAAC,CAAC,OAAO;EAC3C,gBAAgB;CAClB,CAAC;CAED,MAAM,gBAAgB,kBAAkB;EAAE;EAAM,QAAQ;CAAe,CAAC;CAGxE,MAAM,UAAU,OAAgC,CAAC,CAAC;CAElD,MAAM,yBAAyB,IAAI,kBAAkB,cAAc;CACnE,MAAM,sBAAsB,IAAI,eAAe,WAAW;CAC1D,MAAM,gBAAgB,wBAAwB;EAC5C,aAAa;EACb,gBAAgB;EAChB;CACF,CAAC;CACD,MAAM,eAAe,IAAI,cAAc;CAEvC,MAAM,oBAAoB,UAAuE;EAC/F,MAAM,QAAQ,aAAa;GACzB,OAAO,MAAM,KAAK,CAAC,CAAC,OAAO,YAAY;GACvC,gBAAgB;GAChB,iBAAiB;EACnB,CAAC;EAED,KAAK,IAAI,YAAY,GAAG,YAAY,MAAM,QAAQ,aAAa;GAC7D,MAAM,OAAO,mBAAmB;IAC9B,MAAM,MAAM;IACZ,aAAa;IACb;GACF,CAAC;GAED,KAAK,IAAI,WAAW,GAAG,WAAW,KAAK,QAAQ,YAAY;IACzD,MAAM,UAAU,KAAK;IACrB,IAAI,YAAY,SAAS,KAAK,GAC5B,OAAO;KAAE;KAAW;IAAS;GAEjC;EACF;CAGF;CAEA,IAAI,mBAAmB;CACvB,MAAM,SAAS,mBAAmB,MAAM,IAAI,CAAC,CAAC,OAAO,YAAY,CAAC,CAAC,CAChE,KAAK,CAAC,CACN,KAAK,UAAU;EACd,MAAM,oBAAoB;EAC1B;EAEA,OACE,oBAAC,eAAD;GAES;GACI;GACO;GACD;GACH;GACN;GACQ;GAChB,eACE,mBACE,SAAS,MAAM,IAAI,CAAC,CAAC,OAAO,IAAI,UAAU,MAAM,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC;GAEjE;GACI;GACJ;GACO;GACN;GACF;GACO;GACH;GACD;GACT;GACW;GACN;GACX,eAAe,iBAAiB,KAAK;GACrC,cAAc,WAAW,UAAU,SAAS;IAC1C,IAAI,CAAC,MAAM,QAAQ,QAAQ,QAAQ,kBAAkB,GACnD,QAAQ,QAAQ,qBAAqB,CAAC;IAExC,IAAI,CAAC,MAAM,QAAQ,QAAQ,QAAQ,kBAAkB,CAAC,UAAU,GAC9D,QAAQ,QAAQ,kBAAkB,CAAC,aAAa,CAAC;IAEnD,QAAQ,QAAQ,kBAAkB,CAAC,UAAU,CAAC,YAAY;GAC5D;GACA,iBAAiB,OAAO,YAAY;IAClC,sBAAsB;KACpB,aAAa;KACb,YAAY;KACZ,WAAW,QAAQ;KACnB,UAAU,QAAQ;KAClB;IACF,CAAC;GACH;EACD,GA3CM,KA2CN;CAEL,CAAC;CAEH,OACE,qBAAC,KAAD;EACE,GAAI,UAAU,UAAU;EACxB,KAAK;GAAE,QAAQ,SAAS;GAAU,wBAAwB,cAAc,SAAS;EAAE;EACnF,QAAQ,cAAc,SAAS,IAAI,EAAE,uBAAuB,GAAG,eAAe,IAAI,KAAA;EAClF,GAAI;EAJN,UAAA,CAMG,cACC,oBAAC,oBAAD;GACE,MAAK;GACL,oBAAoB;IAClB,gBAAgB,aAAa,MAAM,IAAI,CAAC,CAAC,SAAS,GAAG,MAAM,CAAC,CAAC,QAAQ,MAAM,CAAC;IAC5E,YAAY,aAAa,MAAM,IAAI,CAAC,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC,QAAQ,MAAM,CAAC;IACnE,aAAa,aAAa,MAAM,CAAC;GACnC;GACA,SAAS,EACP,iBAAiB;IACf;IACA,YAAY;IACZ,WAAW,MAAM,IAAI,CAAC,CAAC,IAAI,MAAM;IACjC,YAAY,MAAM,IAAI,CAAC,CAAC,IAAI,OAAO;IACnC,eAAe,SACb,eAAe,aAAa,MAAM,IAAI,CAAC,CAAC,IAAI,QAAQ,IAAI,CAAC,CAAC,QAAQ,MAAM,CAAC,CAAC;IAC5E,GAAG;GACL,EACF;GACQ;GACM;GACA;GACQ;GACJ;GACC;GACF;GACD;EACjB,CAAA,GAGH,oBAAC,OAAD;GAAK,GAAI,UAAU,gBAAgB;GAAI,UAAA;EAAY,CAAA,CAChD;;AAET,CAAC;AAED,SAAS,cAAc;AACvB,SAAS,UAAUA;AACnB,SAAS,eAAe"}
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 {\n getHiddenWeekendColumns,\n getVisibleWeekDays,\n} from '../../utils/get-visible-week-days/get-visible-week-days';\nimport { MonthYearSelectProps } from '../ScheduleHeader/MonthYearSelect/MonthYearSelect';\nimport { CombinedScheduleHeaderStylesNames } from '../ScheduleHeader/ScheduleHeader';\nimport { ScheduleHeaderBase } from '../ScheduleHeader/ScheduleHeaderBase';\nimport { ViewSelectProps } from '../ScheduleHeader/ViewSelect/ViewSelect';\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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"}
@@ -4,7 +4,7 @@ import { getWeekdaysNames } from "../../utils/get-weekdays-names/get-weekdays-na
4
4
  import { getWeekNumber } from "../../utils/get-week-number/get-week-number.mjs";
5
5
  import { getMonthDays } from "../../utils/get-month-days/get-month-days.mjs";
6
6
  import { isSameMonth } from "../../utils/is-same-month/is-same-month.mjs";
7
- import { getHiddenWeekendColumns, getVisibleWeekDays } from "./get-visible-week-days.mjs";
7
+ import { getHiddenWeekendColumns, getVisibleWeekDays } from "../../utils/get-visible-week-days/get-visible-week-days.mjs";
8
8
  import dayjs from "dayjs";
9
9
  import { Box, UnstyledButton, getThemeColor, useMantineTheme } from "@mantine/core";
10
10
  import { createElement } from "react";
@@ -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 {\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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"}
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 {\n getHiddenWeekendColumns,\n getVisibleWeekDays,\n} from '../../utils/get-visible-week-days/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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"}
package/esm/index.mjs CHANGED
@@ -10,6 +10,7 @@ import { isBeforeMaxDate } from "./utils/is-before-max-date/is-before-max-date.m
10
10
  import { isSameMonth } from "./utils/is-same-month/is-same-month.mjs";
11
11
  import { getMonthsByQuarter } from "./utils/get-months-by-quarter/get-months-by-quarter.mjs";
12
12
  import { clampIntervalMinutes } from "./utils/clamp-interval-minutes/clamp-interval-minutes.mjs";
13
+ import { clampSlotLabelInterval } from "./utils/clamp-slot-label-interval/clamp-slot-label-interval.mjs";
13
14
  import { parseTimeString } from "./utils/parse-time-string/parse-time-string.mjs";
14
15
  import { toTimeString } from "./utils/to-time-string/to-time-string.mjs";
15
16
  import { getDayTimeIntervals } from "./utils/get-day-time-intervals/get-day-time-intervals.mjs";
@@ -19,6 +20,7 @@ import { getMonthsList } from "./utils/get-months-list/get-months-list.mjs";
19
20
  import { getYearsList } from "./utils/get-years-list/get-years-list.mjs";
20
21
  import { nextWeek } from "./utils/next-week/next-week.mjs";
21
22
  import { previousWeek } from "./utils/previous-week/previous-week.mjs";
23
+ import { getSlotLabelGroups } from "./utils/get-slot-label-groups/get-slot-label-groups.mjs";
22
24
  import { getCurrentTimePosition } from "./utils/get-current-time-position/get-current-time-position.mjs";
23
25
  import { isInTimeRange } from "./utils/is-in-time-range/is-in-time-range.mjs";
24
26
  import { isAllDayEvent } from "./utils/is-all-day-event/is-all-day-event.mjs";
@@ -34,9 +36,10 @@ import { getDayPosition } from "./utils/get-day-position/get-day-position.mjs";
34
36
  import { getTimeAxisEventStyle } from "./utils/get-time-axis-event-style/get-time-axis-event-style.mjs";
35
37
  import { calculateDropTime } from "./utils/calculate-drop-time/calculate-drop-time.mjs";
36
38
  import { calculateMonthDropDate } from "./utils/calculate-month-drop-date/calculate-month-drop-date.mjs";
37
- import { getBusinessHoursMod } from "./utils/get-business-hours-mod/get-business-hours-mod.mjs";
39
+ import { getBusinessHoursMod, getBusinessHoursState } from "./utils/get-business-hours-mod/get-business-hours-mod.mjs";
38
40
  import { expandRecurringEvents } from "./utils/expand-recurring-events/expand-recurring-events.mjs";
39
41
  import { getOrderedResources } from "./utils/get-ordered-resources/get-ordered-resources.mjs";
42
+ import { addMinutesToTime } from "./utils/add-minutes-to-time/add-minutes-to-time.mjs";
40
43
  import { handleResourcesGridKeyDown } from "./utils/handle-resources-grid-key-down/handle-resources-grid-key-down.mjs";
41
44
  import { getGroupToResourceIdMap } from "./utils/get-group-to-resource-id-map/get-group-to-resource-id-map.mjs";
42
45
  import { getIndexFromDragPoint } from "./utils/get-index-from-drag-point/get-index-from-drag-point.mjs";
@@ -44,6 +47,7 @@ import { getDayRelativePercent } from "./utils/get-day-relative-percent/get-day-
44
47
  import { getOverlapClusters } from "./utils/get-overlap-clusters/get-overlap-clusters.mjs";
45
48
  import { applyCascadeLayout } from "./utils/apply-cascade-layout/apply-cascade-layout.mjs";
46
49
  import { isEventPlacementAllowed } from "./utils/is-event-placement-allowed/is-event-placement-allowed.mjs";
50
+ import { getHiddenWeekendColumns, getVisibleWeekDays } from "./utils/get-visible-week-days/get-visible-week-days.mjs";
47
51
  import { AgendaView } from "./components/AgendaView/AgendaView.mjs";
48
52
  import { CurrentTimeIndicator } from "./components/CurrentTimeIndicator/CurrentTimeIndicator.mjs";
49
53
  import { DragContext } from "./components/DragContext/DragContext.mjs";
@@ -61,4 +65,4 @@ import { ResourcesDayView } from "./components/ResourcesDayView/ResourcesDayView
61
65
  import { ResourcesWeekView } from "./components/ResourcesWeekView/ResourcesWeekView.mjs";
62
66
  import { ResourcesMonthView } from "./components/ResourcesMonthView/ResourcesMonthView.mjs";
63
67
  import { ResourcesSchedule } from "./components/ResourcesSchedule/ResourcesSchedule.mjs";
64
- export { AgendaView, CurrentTimeIndicator, DEFAULT_SCHEDULE_LABELS, DayView, DragContext, MobileMonthView, MonthView, MoreEvents, ResourcesDayView, ResourcesMonthView, ResourcesSchedule, ResourcesWeekView, Schedule, ScheduleBackgroundEvent, ScheduleEvent, ScheduleHeader, WeekView, YearView, applyCascadeLayout, calculateDropTime, calculateMonthDropDate, clampIntervalMinutes, expandRecurringEvents, formatDate, getBusinessHoursMod, getCurrentTimePosition, getDayPosition, getDayRelativePercent, getDayTimeIntervals, getEndOfWeek, getGroupToResourceIdMap, getIndexFromDragPoint, getLabel, getMonthDays, getMonthRange, getMonthsByQuarter, getMonthsList, getOrderedResources, getOverlapClusters, getStartOfWeek, getTimeAxisEventStyle, getVisibleEvents, getWeekDays, getWeekNumber, getWeekdaysNames, getYearsList, handleResourcesGridKeyDown, isAfterMinDate, isAllDayEvent, isBeforeMaxDate, isEventInTimeRange, isEventPlacementAllowed, isEventsOverlap, isInTimeRange, isMultidayEvent, isSameMonth, isWithinWeek, nextWeek, parseTimeString, previousWeek, sortEvents, toDateString, toTimeString, validateEvent };
68
+ export { AgendaView, CurrentTimeIndicator, DEFAULT_SCHEDULE_LABELS, DayView, DragContext, MobileMonthView, MonthView, MoreEvents, ResourcesDayView, ResourcesMonthView, ResourcesSchedule, ResourcesWeekView, Schedule, ScheduleBackgroundEvent, ScheduleEvent, ScheduleHeader, WeekView, YearView, addMinutesToTime, applyCascadeLayout, calculateDropTime, calculateMonthDropDate, clampIntervalMinutes, clampSlotLabelInterval, expandRecurringEvents, formatDate, getBusinessHoursMod, getBusinessHoursState, getCurrentTimePosition, getDayPosition, getDayRelativePercent, getDayTimeIntervals, getEndOfWeek, getGroupToResourceIdMap, getHiddenWeekendColumns, getIndexFromDragPoint, getLabel, getMonthDays, getMonthRange, getMonthsByQuarter, getMonthsList, getOrderedResources, getOverlapClusters, getSlotLabelGroups, getStartOfWeek, getTimeAxisEventStyle, getVisibleEvents, getVisibleWeekDays, getWeekDays, getWeekNumber, getWeekdaysNames, getYearsList, handleResourcesGridKeyDown, isAfterMinDate, isAllDayEvent, isBeforeMaxDate, isEventInTimeRange, isEventPlacementAllowed, isEventsOverlap, isInTimeRange, isMultidayEvent, isSameMonth, isWithinWeek, nextWeek, parseTimeString, previousWeek, sortEvents, toDateString, toTimeString, validateEvent };
@@ -0,0 +1,17 @@
1
+ "use client";
2
+ import { parseTimeString } from "../parse-time-string/parse-time-string.mjs";
3
+ import { toTimeString } from "../to-time-string/to-time-string.mjs";
4
+ //#region packages/@mantine/schedule/src/utils/add-minutes-to-time/add-minutes-to-time.ts
5
+ function addMinutesToTime(time, minutes) {
6
+ const parsed = parseTimeString(time);
7
+ const total = parsed.hours * 3600 + parsed.minutes * 60 + parsed.seconds + minutes * 60;
8
+ return toTimeString({
9
+ hours: Math.floor(total / 3600),
10
+ minutes: Math.floor(total % 3600 / 60),
11
+ seconds: total % 60
12
+ });
13
+ }
14
+ //#endregion
15
+ export { addMinutesToTime };
16
+
17
+ //# sourceMappingURL=add-minutes-to-time.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add-minutes-to-time.mjs","names":[],"sources":["../../../src/utils/add-minutes-to-time/add-minutes-to-time.ts"],"sourcesContent":["import { parseTimeString } from '../parse-time-string/parse-time-string';\nimport { toTimeString } from '../to-time-string/to-time-string';\n\nexport function addMinutesToTime(time: string, minutes: number) {\n const parsed = parseTimeString(time);\n const total = parsed.hours * 3600 + parsed.minutes * 60 + parsed.seconds + minutes * 60;\n\n return toTimeString({\n hours: Math.floor(total / 3600),\n minutes: Math.floor((total % 3600) / 60),\n seconds: total % 60,\n });\n}\n"],"mappings":";;;;AAGA,SAAgB,iBAAiB,MAAc,SAAiB;CAC9D,MAAM,SAAS,gBAAgB,IAAI;CACnC,MAAM,QAAQ,OAAO,QAAQ,OAAO,OAAO,UAAU,KAAK,OAAO,UAAU,UAAU;CAErF,OAAO,aAAa;EAClB,OAAO,KAAK,MAAM,QAAQ,IAAI;EAC9B,SAAS,KAAK,MAAO,QAAQ,OAAQ,EAAE;EACvC,SAAS,QAAQ;CACnB,CAAC;AACH"}
@@ -0,0 +1,22 @@
1
+ "use client";
2
+ import { clampIntervalMinutes } from "../clamp-interval-minutes/clamp-interval-minutes.mjs";
3
+ //#region packages/@mantine/schedule/src/utils/clamp-slot-label-interval/clamp-slot-label-interval.ts
4
+ /**
5
+ * Clamps slot label interval so that every label lines up with a slot boundary:
6
+ *
7
+ * - Non-positive and non-finite values fall back to `60`.
8
+ * - The value is clamped with the same rules as `intervalMinutes` (see `clampIntervalMinutes`).
9
+ * - The result is rounded up to the next multiple of the clamped `intervalMinutes` that
10
+ * satisfies the same rules and is never smaller than it. It is capped to a single day (`1440`).
11
+ */
12
+ function clampSlotLabelInterval(slotLabelInterval, intervalMinutes) {
13
+ const interval = clampIntervalMinutes(intervalMinutes);
14
+ const label = clampIntervalMinutes(Number.isFinite(slotLabelInterval) && slotLabelInterval > 0 ? slotLabelInterval : 60);
15
+ let result = Math.ceil(label / interval) * interval;
16
+ while (result < 1440 && clampIntervalMinutes(result) !== result) result += interval;
17
+ return Math.min(1440, result);
18
+ }
19
+ //#endregion
20
+ export { clampSlotLabelInterval };
21
+
22
+ //# sourceMappingURL=clamp-slot-label-interval.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clamp-slot-label-interval.mjs","names":[],"sources":["../../../src/utils/clamp-slot-label-interval/clamp-slot-label-interval.ts"],"sourcesContent":["import { clampIntervalMinutes } from '../clamp-interval-minutes/clamp-interval-minutes';\n\n/**\n * Clamps slot label interval so that every label lines up with a slot boundary:\n *\n * - Non-positive and non-finite values fall back to `60`.\n * - The value is clamped with the same rules as `intervalMinutes` (see `clampIntervalMinutes`).\n * - The result is rounded up to the next multiple of the clamped `intervalMinutes` that\n * satisfies the same rules and is never smaller than it. It is capped to a single day (`1440`).\n */\nexport function clampSlotLabelInterval(slotLabelInterval: number, intervalMinutes: number): number {\n const interval = clampIntervalMinutes(intervalMinutes);\n const label = clampIntervalMinutes(\n Number.isFinite(slotLabelInterval) && slotLabelInterval > 0 ? slotLabelInterval : 60\n );\n\n let result = Math.ceil(label / interval) * interval;\n\n while (result < 1440 && clampIntervalMinutes(result) !== result) {\n result += interval;\n }\n\n return Math.min(1440, result);\n}\n"],"mappings":";;;;;;;;;;;AAUA,SAAgB,uBAAuB,mBAA2B,iBAAiC;CACjG,MAAM,WAAW,qBAAqB,eAAe;CACrD,MAAM,QAAQ,qBACZ,OAAO,SAAS,iBAAiB,KAAK,oBAAoB,IAAI,oBAAoB,EACpF;CAEA,IAAI,SAAS,KAAK,KAAK,QAAQ,QAAQ,IAAI;CAE3C,OAAO,SAAS,QAAQ,qBAAqB,MAAM,MAAM,QACvD,UAAU;CAGZ,OAAO,KAAK,IAAI,MAAM,MAAM;AAC9B"}
@@ -1,42 +1,98 @@
1
1
  "use client";
2
+ import { parseTimeString } from "../parse-time-string/parse-time-string.mjs";
2
3
  //#region packages/@mantine/schedule/src/utils/get-business-hours-mod/get-business-hours-mod.ts
4
+ const NONE = {
5
+ "business-hours": false,
6
+ "non-business-hours": false,
7
+ "partial-business-hours": false
8
+ };
9
+ const INSIDE = {
10
+ "business-hours": true,
11
+ "non-business-hours": false,
12
+ "partial-business-hours": false
13
+ };
14
+ const OUTSIDE = {
15
+ "business-hours": false,
16
+ "non-business-hours": true,
17
+ "partial-business-hours": false
18
+ };
19
+ const PARTIAL = {
20
+ "business-hours": false,
21
+ "non-business-hours": false,
22
+ "partial-business-hours": true
23
+ };
3
24
  function isBusinessHoursRange(value) {
4
25
  return Array.isArray(value) && value.length === 2 && typeof value[0] === "string" && typeof value[1] === "string";
5
26
  }
27
+ function toSeconds(time) {
28
+ const { hours, minutes, seconds } = parseTimeString(time);
29
+ return hours * 3600 + minutes * 60 + seconds;
30
+ }
31
+ function toPercent(value) {
32
+ return `${Math.round(value * 1e4) / 100}%`;
33
+ }
6
34
  /**
7
- * Determines if a given time is within business hours and returns modifier object
8
- * @param time - Time string in HH:mm:ss format
9
- * @param businessHours - Tuple of [start, end] times in HH:mm:ss format, or per-day record keyed by day of the week
10
- * @param highlightBusinessHours - Whether to highlight business hours
11
- * @param dayOfWeek - Day of the week (0 – Sunday, 6 – Saturday), used to resolve per-day business hours
12
- * @returns Modifier object for styling business/non-business hours
35
+ * Resolves business hours state of a time interval
36
+ * @returns `mod` – modifiers for styling business/non-business/partial intervals, `vars` – CSS variables with the business hours boundaries inside a partial interval
13
37
  */
14
- function getBusinessHoursMod({ time, businessHours, highlightBusinessHours, dayOfWeek }) {
38
+ function getBusinessHoursState({ time, endTime, businessHours, highlightBusinessHours, dayOfWeek }) {
15
39
  if (!highlightBusinessHours || !businessHours) return {
16
- "business-hours": false,
17
- "non-business-hours": false
40
+ mod: NONE,
41
+ vars: void 0
18
42
  };
19
43
  let range;
20
44
  if (isBusinessHoursRange(businessHours)) range = businessHours;
21
45
  else {
22
46
  if (dayOfWeek === void 0) return {
23
- "business-hours": false,
24
- "non-business-hours": false
47
+ mod: NONE,
48
+ vars: void 0
25
49
  };
26
50
  range = businessHours[dayOfWeek] ?? null;
27
51
  }
28
52
  if (!range) return {
29
- "business-hours": false,
30
- "non-business-hours": true
53
+ mod: OUTSIDE,
54
+ vars: void 0
55
+ };
56
+ const start = toSeconds(time);
57
+ const rangeStart = toSeconds(range[0]);
58
+ const rangeEnd = toSeconds(range[1]);
59
+ const end = endTime === void 0 ? start : toSeconds(endTime);
60
+ if (end <= start) return {
61
+ mod: start >= rangeStart && start < rangeEnd ? INSIDE : OUTSIDE,
62
+ vars: void 0
63
+ };
64
+ const overlapStart = Math.max(start, rangeStart);
65
+ const overlapEnd = Math.min(end, rangeEnd);
66
+ if (overlapEnd <= overlapStart) return {
67
+ mod: OUTSIDE,
68
+ vars: void 0
31
69
  };
32
- const [start, end] = range;
33
- const isInBusinessHours = time >= start && time < end;
70
+ if (overlapStart === start && overlapEnd === end) return {
71
+ mod: INSIDE,
72
+ vars: void 0
73
+ };
74
+ const duration = end - start;
34
75
  return {
35
- "business-hours": isInBusinessHours,
36
- "non-business-hours": !isInBusinessHours
76
+ mod: PARTIAL,
77
+ vars: {
78
+ "--business-hours-from": toPercent((overlapStart - start) / duration),
79
+ "--business-hours-to": toPercent((overlapEnd - start) / duration)
80
+ }
37
81
  };
38
82
  }
83
+ /**
84
+ * Determines if a given time interval is within business hours and returns modifier object
85
+ * @param time - Start time in HH:mm:ss format
86
+ * @param endTime - End time in HH:mm:ss format, enables the partial state for intervals that contain a boundary
87
+ * @param businessHours - Tuple of [start, end] times in HH:mm:ss or HH:mm format, or per-day record keyed by day of the week
88
+ * @param highlightBusinessHours - Whether to highlight business hours
89
+ * @param dayOfWeek - Day of the week (0 – Sunday, 6 – Saturday), used to resolve per-day business hours
90
+ * @returns Modifier object for styling business/non-business hours
91
+ */
92
+ function getBusinessHoursMod(input) {
93
+ return getBusinessHoursState(input).mod;
94
+ }
39
95
  //#endregion
40
- export { getBusinessHoursMod };
96
+ export { getBusinessHoursMod, getBusinessHoursState };
41
97
 
42
98
  //# sourceMappingURL=get-business-hours-mod.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"get-business-hours-mod.mjs","names":[],"sources":["../../../src/utils/get-business-hours-mod/get-business-hours-mod.ts"],"sourcesContent":["import { DayOfWeek } from '../../types';\n\n/** Business hours range in `HH:mm:ss` format */\nexport type BusinessHoursRange = [string, string];\n\n/** Per-day business hours map keyed by day of the week (0 – Sunday, 6 – Saturday). `null` marks a day as fully outside business hours. */\nexport type BusinessHoursPerDay = Partial<Record<DayOfWeek, BusinessHoursRange | null>>;\n\n/** Business hours value – tuple applies to every day, record configures business hours per day */\nexport type BusinessHoursValue = BusinessHoursRange | BusinessHoursPerDay;\n\nexport interface GetBusinessHoursModInput {\n time: string;\n businessHours?: BusinessHoursValue;\n highlightBusinessHours?: boolean;\n dayOfWeek?: DayOfWeek;\n}\n\nexport interface BusinessHoursMod {\n 'business-hours': boolean;\n 'non-business-hours': boolean;\n}\n\nfunction isBusinessHoursRange(value: BusinessHoursValue): value is BusinessHoursRange {\n return (\n Array.isArray(value) &&\n value.length === 2 &&\n typeof value[0] === 'string' &&\n typeof value[1] === 'string'\n );\n}\n\n/**\n * Determines if a given time is within business hours and returns modifier object\n * @param time - Time string in HH:mm:ss format\n * @param businessHours - Tuple of [start, end] times in HH:mm:ss format, or per-day record keyed by day of the week\n * @param highlightBusinessHours - Whether to highlight business hours\n * @param dayOfWeek - Day of the week (0 – Sunday, 6 – Saturday), used to resolve per-day business hours\n * @returns Modifier object for styling business/non-business hours\n */\nexport function getBusinessHoursMod({\n time,\n businessHours,\n highlightBusinessHours,\n dayOfWeek,\n}: GetBusinessHoursModInput): BusinessHoursMod {\n if (!highlightBusinessHours || !businessHours) {\n return {\n 'business-hours': false,\n 'non-business-hours': false,\n };\n }\n\n let range: [string, string] | null;\n if (isBusinessHoursRange(businessHours)) {\n range = businessHours;\n } else {\n if (dayOfWeek === undefined) {\n return {\n 'business-hours': false,\n 'non-business-hours': false,\n };\n }\n range = businessHours[dayOfWeek] ?? null;\n }\n\n if (!range) {\n return {\n 'business-hours': false,\n 'non-business-hours': true,\n };\n }\n\n const [start, end] = range;\n const isInBusinessHours = time >= start && time < end;\n\n return {\n 'business-hours': isInBusinessHours,\n 'non-business-hours': !isInBusinessHours,\n };\n}\n"],"mappings":";;AAuBA,SAAS,qBAAqB,OAAwD;CACpF,OACE,MAAM,QAAQ,KAAK,KACnB,MAAM,WAAW,KACjB,OAAO,MAAM,OAAO,YACpB,OAAO,MAAM,OAAO;AAExB;;;;;;;;;AAUA,SAAgB,oBAAoB,EAClC,MACA,eACA,wBACA,aAC6C;CAC7C,IAAI,CAAC,0BAA0B,CAAC,eAC9B,OAAO;EACL,kBAAkB;EAClB,sBAAsB;CACxB;CAGF,IAAI;CACJ,IAAI,qBAAqB,aAAa,GACpC,QAAQ;MACH;EACL,IAAI,cAAc,KAAA,GAChB,OAAO;GACL,kBAAkB;GAClB,sBAAsB;EACxB;EAEF,QAAQ,cAAc,cAAc;CACtC;CAEA,IAAI,CAAC,OACH,OAAO;EACL,kBAAkB;EAClB,sBAAsB;CACxB;CAGF,MAAM,CAAC,OAAO,OAAO;CACrB,MAAM,oBAAoB,QAAQ,SAAS,OAAO;CAElD,OAAO;EACL,kBAAkB;EAClB,sBAAsB,CAAC;CACzB;AACF"}
1
+ {"version":3,"file":"get-business-hours-mod.mjs","names":[],"sources":["../../../src/utils/get-business-hours-mod/get-business-hours-mod.ts"],"sourcesContent":["import { DayOfWeek } from '../../types';\nimport { parseTimeString } from '../parse-time-string/parse-time-string';\n\n/** Business hours range in `HH:mm:ss` or `HH:mm` format */\nexport type BusinessHoursRange = [string, string];\n\n/** Per-day business hours map keyed by day of the week (0 – Sunday, 6 – Saturday). `null` marks a day as fully outside business hours. */\nexport type BusinessHoursPerDay = Partial<Record<DayOfWeek, BusinessHoursRange | null>>;\n\n/** Business hours value – tuple applies to every day, record configures business hours per day */\nexport type BusinessHoursValue = BusinessHoursRange | BusinessHoursPerDay;\n\nexport interface GetBusinessHoursModInput {\n /** Start of the interval in `HH:mm:ss` format */\n time: string;\n\n /** End of the interval in `HH:mm:ss` format. When set, intervals that contain a business hours boundary get the partial state. */\n endTime?: string;\n\n businessHours?: BusinessHoursValue;\n highlightBusinessHours?: boolean;\n dayOfWeek?: DayOfWeek;\n}\n\nexport interface BusinessHoursMod {\n 'business-hours': boolean;\n 'non-business-hours': boolean;\n 'partial-business-hours': boolean;\n}\n\n/** CSS variables applied to partial intervals, percentage of the interval where business hours start and end */\nexport type BusinessHoursVars = {\n '--business-hours-from': string;\n '--business-hours-to': string;\n};\n\nexport interface BusinessHoursState {\n mod: BusinessHoursMod;\n vars: BusinessHoursVars | undefined;\n}\n\nconst NONE: BusinessHoursMod = {\n 'business-hours': false,\n 'non-business-hours': false,\n 'partial-business-hours': false,\n};\n\nconst INSIDE: BusinessHoursMod = {\n 'business-hours': true,\n 'non-business-hours': false,\n 'partial-business-hours': false,\n};\n\nconst OUTSIDE: BusinessHoursMod = {\n 'business-hours': false,\n 'non-business-hours': true,\n 'partial-business-hours': false,\n};\n\nconst PARTIAL: BusinessHoursMod = {\n 'business-hours': false,\n 'non-business-hours': false,\n 'partial-business-hours': true,\n};\n\nfunction isBusinessHoursRange(value: BusinessHoursValue): value is BusinessHoursRange {\n return (\n Array.isArray(value) &&\n value.length === 2 &&\n typeof value[0] === 'string' &&\n typeof value[1] === 'string'\n );\n}\n\nfunction toSeconds(time: string) {\n const { hours, minutes, seconds } = parseTimeString(time);\n return hours * 3600 + minutes * 60 + seconds;\n}\n\nfunction toPercent(value: number) {\n return `${Math.round(value * 10000) / 100}%`;\n}\n\n/**\n * Resolves business hours state of a time interval\n * @returns `mod` – modifiers for styling business/non-business/partial intervals, `vars` – CSS variables with the business hours boundaries inside a partial interval\n */\nexport function getBusinessHoursState({\n time,\n endTime,\n businessHours,\n highlightBusinessHours,\n dayOfWeek,\n}: GetBusinessHoursModInput): BusinessHoursState {\n if (!highlightBusinessHours || !businessHours) {\n return { mod: NONE, vars: undefined };\n }\n\n let range: BusinessHoursRange | null;\n if (isBusinessHoursRange(businessHours)) {\n range = businessHours;\n } else {\n if (dayOfWeek === undefined) {\n return { mod: NONE, vars: undefined };\n }\n range = businessHours[dayOfWeek] ?? null;\n }\n\n if (!range) {\n return { mod: OUTSIDE, vars: undefined };\n }\n\n const start = toSeconds(time);\n const rangeStart = toSeconds(range[0]);\n const rangeEnd = toSeconds(range[1]);\n const end = endTime === undefined ? start : toSeconds(endTime);\n\n if (end <= start) {\n const isInside = start >= rangeStart && start < rangeEnd;\n return { mod: isInside ? INSIDE : OUTSIDE, vars: undefined };\n }\n\n const overlapStart = Math.max(start, rangeStart);\n const overlapEnd = Math.min(end, rangeEnd);\n\n if (overlapEnd <= overlapStart) {\n return { mod: OUTSIDE, vars: undefined };\n }\n\n if (overlapStart === start && overlapEnd === end) {\n return { mod: INSIDE, vars: undefined };\n }\n\n const duration = end - start;\n\n return {\n mod: PARTIAL,\n vars: {\n '--business-hours-from': toPercent((overlapStart - start) / duration),\n '--business-hours-to': toPercent((overlapEnd - start) / duration),\n },\n };\n}\n\n/**\n * Determines if a given time interval is within business hours and returns modifier object\n * @param time - Start time in HH:mm:ss format\n * @param endTime - End time in HH:mm:ss format, enables the partial state for intervals that contain a boundary\n * @param businessHours - Tuple of [start, end] times in HH:mm:ss or HH:mm format, or per-day record keyed by day of the week\n * @param highlightBusinessHours - Whether to highlight business hours\n * @param dayOfWeek - Day of the week (0 – Sunday, 6 – Saturday), used to resolve per-day business hours\n * @returns Modifier object for styling business/non-business hours\n */\nexport function getBusinessHoursMod(input: GetBusinessHoursModInput): BusinessHoursMod {\n return getBusinessHoursState(input).mod;\n}\n"],"mappings":";;;AAyCA,MAAM,OAAyB;CAC7B,kBAAkB;CAClB,sBAAsB;CACtB,0BAA0B;AAC5B;AAEA,MAAM,SAA2B;CAC/B,kBAAkB;CAClB,sBAAsB;CACtB,0BAA0B;AAC5B;AAEA,MAAM,UAA4B;CAChC,kBAAkB;CAClB,sBAAsB;CACtB,0BAA0B;AAC5B;AAEA,MAAM,UAA4B;CAChC,kBAAkB;CAClB,sBAAsB;CACtB,0BAA0B;AAC5B;AAEA,SAAS,qBAAqB,OAAwD;CACpF,OACE,MAAM,QAAQ,KAAK,KACnB,MAAM,WAAW,KACjB,OAAO,MAAM,OAAO,YACpB,OAAO,MAAM,OAAO;AAExB;AAEA,SAAS,UAAU,MAAc;CAC/B,MAAM,EAAE,OAAO,SAAS,YAAY,gBAAgB,IAAI;CACxD,OAAO,QAAQ,OAAO,UAAU,KAAK;AACvC;AAEA,SAAS,UAAU,OAAe;CAChC,OAAO,GAAG,KAAK,MAAM,QAAQ,GAAK,IAAI,IAAI;AAC5C;;;;;AAMA,SAAgB,sBAAsB,EACpC,MACA,SACA,eACA,wBACA,aAC+C;CAC/C,IAAI,CAAC,0BAA0B,CAAC,eAC9B,OAAO;EAAE,KAAK;EAAM,MAAM,KAAA;CAAU;CAGtC,IAAI;CACJ,IAAI,qBAAqB,aAAa,GACpC,QAAQ;MACH;EACL,IAAI,cAAc,KAAA,GAChB,OAAO;GAAE,KAAK;GAAM,MAAM,KAAA;EAAU;EAEtC,QAAQ,cAAc,cAAc;CACtC;CAEA,IAAI,CAAC,OACH,OAAO;EAAE,KAAK;EAAS,MAAM,KAAA;CAAU;CAGzC,MAAM,QAAQ,UAAU,IAAI;CAC5B,MAAM,aAAa,UAAU,MAAM,EAAE;CACrC,MAAM,WAAW,UAAU,MAAM,EAAE;CACnC,MAAM,MAAM,YAAY,KAAA,IAAY,QAAQ,UAAU,OAAO;CAE7D,IAAI,OAAO,OAET,OAAO;EAAE,KADQ,SAAS,cAAc,QAAQ,WACvB,SAAS;EAAS,MAAM,KAAA;CAAU;CAG7D,MAAM,eAAe,KAAK,IAAI,OAAO,UAAU;CAC/C,MAAM,aAAa,KAAK,IAAI,KAAK,QAAQ;CAEzC,IAAI,cAAc,cAChB,OAAO;EAAE,KAAK;EAAS,MAAM,KAAA;CAAU;CAGzC,IAAI,iBAAiB,SAAS,eAAe,KAC3C,OAAO;EAAE,KAAK;EAAQ,MAAM,KAAA;CAAU;CAGxC,MAAM,WAAW,MAAM;CAEvB,OAAO;EACL,KAAK;EACL,MAAM;GACJ,yBAAyB,WAAW,eAAe,SAAS,QAAQ;GACpE,uBAAuB,WAAW,aAAa,SAAS,QAAQ;EAClE;CACF;AACF;;;;;;;;;;AAWA,SAAgB,oBAAoB,OAAmD;CACrF,OAAO,sBAAsB,KAAK,CAAC,CAAC;AACtC"}
@@ -1,10 +1,12 @@
1
1
  "use client";
2
2
  import { clampIntervalMinutes } from "../clamp-interval-minutes/clamp-interval-minutes.mjs";
3
+ import { clampSlotLabelInterval } from "../clamp-slot-label-interval/clamp-slot-label-interval.mjs";
3
4
  import { parseTimeString } from "../parse-time-string/parse-time-string.mjs";
4
5
  import { toTimeString } from "../to-time-string/to-time-string.mjs";
5
6
  //#region packages/@mantine/schedule/src/utils/get-day-time-intervals/get-day-time-intervals.ts
6
- function getDayTimeIntervals({ startTime, endTime, intervalMinutes: _intervalMinutes = 60 }) {
7
+ function getDayTimeIntervals({ startTime, endTime, intervalMinutes: _intervalMinutes = 60, labelIntervalMinutes: _labelIntervalMinutes = 60 }) {
7
8
  const intervalMinutes = clampIntervalMinutes(_intervalMinutes);
9
+ const labelIntervalSeconds = clampSlotLabelInterval(_labelIntervalMinutes, intervalMinutes) * 60;
8
10
  const start = parseTimeString(startTime);
9
11
  const end = endTime ? parseTimeString(endTime) : {
10
12
  hours: 23,
@@ -14,6 +16,7 @@ function getDayTimeIntervals({ startTime, endTime, intervalMinutes: _intervalMin
14
16
  const startSeconds = start.hours * 3600 + start.minutes * 60 + start.seconds;
15
17
  const endSeconds = end.hours * 3600 + end.minutes * 60 + end.seconds;
16
18
  const intervalSeconds = intervalMinutes * 60;
19
+ const labelOriginSeconds = startSeconds % labelIntervalSeconds % intervalSeconds === 0 ? 0 : startSeconds;
17
20
  const intervals = [];
18
21
  let currentSeconds = startSeconds;
19
22
  while (currentSeconds < endSeconds) {
@@ -28,6 +31,7 @@ function getDayTimeIntervals({ startTime, endTime, intervalMinutes: _intervalMin
28
31
  const endSecs = intervalEndSeconds % 60;
29
32
  const durationSeconds = intervalEndSeconds - intervalStartSeconds;
30
33
  const isHourStart = startMinutes === 0 && startSecs === 0;
34
+ const isLabelStart = (intervalStartSeconds - labelOriginSeconds) % labelIntervalSeconds === 0;
31
35
  intervals.push({
32
36
  startTime: toTimeString({
33
37
  hours: startHours,
@@ -40,7 +44,8 @@ function getDayTimeIntervals({ startTime, endTime, intervalMinutes: _intervalMin
40
44
  seconds: endSecs
41
45
  }),
42
46
  duration: durationSeconds,
43
- isHourStart
47
+ isHourStart,
48
+ isLabelStart
44
49
  });
45
50
  currentSeconds = intervalEndSeconds;
46
51
  }
@@ -1 +1 @@
1
- {"version":3,"file":"get-day-time-intervals.mjs","names":[],"sources":["../../../src/utils/get-day-time-intervals/get-day-time-intervals.ts"],"sourcesContent":["import { clampIntervalMinutes } from '../clamp-interval-minutes/clamp-interval-minutes';\nimport { parseTimeString } from '../parse-time-string/parse-time-string';\nimport { toTimeString } from '../to-time-string/to-time-string';\n\nexport interface DayTimeInterval {\n /** Start time of the interval in HH:mm:ss format */\n startTime: string;\n\n /** End time of the interval in HH:mm:ss format */\n endTime: string;\n\n /** Duration of the interval in seconds */\n duration: number;\n\n /** Indicates if the interval starts at the beginning of an hour */\n isHourStart: boolean;\n}\n\nexport interface GetDayTimeIntervalsInput {\n /** Start time in HH:mm:ss format */\n startTime: string;\n\n /** End time in HH:mm:ss format, end of the day by default */\n endTime?: string;\n\n /** Interval in minutes, 60 by default */\n intervalMinutes?: number;\n}\n\nexport function getDayTimeIntervals({\n startTime,\n endTime,\n intervalMinutes: _intervalMinutes = 60,\n}: GetDayTimeIntervalsInput): DayTimeInterval[] {\n const intervalMinutes = clampIntervalMinutes(_intervalMinutes);\n\n const start = parseTimeString(startTime);\n const end = endTime ? parseTimeString(endTime) : { hours: 23, minutes: 59, seconds: 59 };\n\n const startSeconds = start.hours * 3600 + start.minutes * 60 + start.seconds;\n const endSeconds = end.hours * 3600 + end.minutes * 60 + end.seconds;\n const intervalSeconds = intervalMinutes * 60;\n\n const intervals: DayTimeInterval[] = [];\n let currentSeconds = startSeconds;\n\n while (currentSeconds < endSeconds) {\n const intervalStartSeconds = currentSeconds;\n let intervalEndSeconds = currentSeconds + intervalSeconds;\n\n if (intervalEndSeconds > endSeconds) {\n intervalEndSeconds = endSeconds;\n }\n\n const startHours = Math.floor(intervalStartSeconds / 3600);\n const startMinutes = Math.floor((intervalStartSeconds % 3600) / 60);\n const startSecs = intervalStartSeconds % 60;\n\n const endHours = Math.floor(intervalEndSeconds / 3600);\n const endMinutes = Math.floor((intervalEndSeconds % 3600) / 60);\n const endSecs = intervalEndSeconds % 60;\n\n const durationSeconds = intervalEndSeconds - intervalStartSeconds;\n const isHourStart = startMinutes === 0 && startSecs === 0;\n\n intervals.push({\n startTime: toTimeString({ hours: startHours, minutes: startMinutes, seconds: startSecs }),\n endTime: toTimeString({ hours: endHours, minutes: endMinutes, seconds: endSecs }),\n duration: durationSeconds,\n isHourStart,\n });\n\n currentSeconds = intervalEndSeconds;\n }\n\n return intervals;\n}\n"],"mappings":";;;;;AA6BA,SAAgB,oBAAoB,EAClC,WACA,SACA,iBAAiB,mBAAmB,MACU;CAC9C,MAAM,kBAAkB,qBAAqB,gBAAgB;CAE7D,MAAM,QAAQ,gBAAgB,SAAS;CACvC,MAAM,MAAM,UAAU,gBAAgB,OAAO,IAAI;EAAE,OAAO;EAAI,SAAS;EAAI,SAAS;CAAG;CAEvF,MAAM,eAAe,MAAM,QAAQ,OAAO,MAAM,UAAU,KAAK,MAAM;CACrE,MAAM,aAAa,IAAI,QAAQ,OAAO,IAAI,UAAU,KAAK,IAAI;CAC7D,MAAM,kBAAkB,kBAAkB;CAE1C,MAAM,YAA+B,CAAC;CACtC,IAAI,iBAAiB;CAErB,OAAO,iBAAiB,YAAY;EAClC,MAAM,uBAAuB;EAC7B,IAAI,qBAAqB,iBAAiB;EAE1C,IAAI,qBAAqB,YACvB,qBAAqB;EAGvB,MAAM,aAAa,KAAK,MAAM,uBAAuB,IAAI;EACzD,MAAM,eAAe,KAAK,MAAO,uBAAuB,OAAQ,EAAE;EAClE,MAAM,YAAY,uBAAuB;EAEzC,MAAM,WAAW,KAAK,MAAM,qBAAqB,IAAI;EACrD,MAAM,aAAa,KAAK,MAAO,qBAAqB,OAAQ,EAAE;EAC9D,MAAM,UAAU,qBAAqB;EAErC,MAAM,kBAAkB,qBAAqB;EAC7C,MAAM,cAAc,iBAAiB,KAAK,cAAc;EAExD,UAAU,KAAK;GACb,WAAW,aAAa;IAAE,OAAO;IAAY,SAAS;IAAc,SAAS;GAAU,CAAC;GACxF,SAAS,aAAa;IAAE,OAAO;IAAU,SAAS;IAAY,SAAS;GAAQ,CAAC;GAChF,UAAU;GACV;EACF,CAAC;EAED,iBAAiB;CACnB;CAEA,OAAO;AACT"}
1
+ {"version":3,"file":"get-day-time-intervals.mjs","names":[],"sources":["../../../src/utils/get-day-time-intervals/get-day-time-intervals.ts"],"sourcesContent":["import { clampIntervalMinutes } from '../clamp-interval-minutes/clamp-interval-minutes';\nimport { clampSlotLabelInterval } from '../clamp-slot-label-interval/clamp-slot-label-interval';\nimport { parseTimeString } from '../parse-time-string/parse-time-string';\nimport { toTimeString } from '../to-time-string/to-time-string';\n\nexport interface DayTimeInterval {\n /** Start time of the interval in HH:mm:ss format */\n startTime: string;\n\n /** End time of the interval in HH:mm:ss format */\n endTime: string;\n\n /** Duration of the interval in seconds */\n duration: number;\n\n /** Indicates if the interval starts at the beginning of an hour */\n isHourStart: boolean;\n\n /** Indicates if the interval starts at a label boundary defined by `labelIntervalMinutes`. Boundaries are aligned to the clock when the slots grid reaches them, otherwise they are counted from `startTime`. */\n isLabelStart: boolean;\n}\n\nexport interface GetDayTimeIntervalsInput {\n /** Start time in HH:mm:ss format */\n startTime: string;\n\n /** End time in HH:mm:ss format, end of the day by default */\n endTime?: string;\n\n /** Interval in minutes, 60 by default */\n intervalMinutes?: number;\n\n /** Interval between labeled slots in minutes, 60 by default */\n labelIntervalMinutes?: number;\n}\n\nexport function getDayTimeIntervals({\n startTime,\n endTime,\n intervalMinutes: _intervalMinutes = 60,\n labelIntervalMinutes: _labelIntervalMinutes = 60,\n}: GetDayTimeIntervalsInput): DayTimeInterval[] {\n const intervalMinutes = clampIntervalMinutes(_intervalMinutes);\n const labelIntervalSeconds = clampSlotLabelInterval(_labelIntervalMinutes, intervalMinutes) * 60;\n\n const start = parseTimeString(startTime);\n const end = endTime ? parseTimeString(endTime) : { hours: 23, minutes: 59, seconds: 59 };\n\n const startSeconds = start.hours * 3600 + start.minutes * 60 + start.seconds;\n const endSeconds = end.hours * 3600 + end.minutes * 60 + end.seconds;\n const intervalSeconds = intervalMinutes * 60;\n const labelOriginSeconds =\n (startSeconds % labelIntervalSeconds) % intervalSeconds === 0 ? 0 : startSeconds;\n\n const intervals: DayTimeInterval[] = [];\n let currentSeconds = startSeconds;\n\n while (currentSeconds < endSeconds) {\n const intervalStartSeconds = currentSeconds;\n let intervalEndSeconds = currentSeconds + intervalSeconds;\n\n if (intervalEndSeconds > endSeconds) {\n intervalEndSeconds = endSeconds;\n }\n\n const startHours = Math.floor(intervalStartSeconds / 3600);\n const startMinutes = Math.floor((intervalStartSeconds % 3600) / 60);\n const startSecs = intervalStartSeconds % 60;\n\n const endHours = Math.floor(intervalEndSeconds / 3600);\n const endMinutes = Math.floor((intervalEndSeconds % 3600) / 60);\n const endSecs = intervalEndSeconds % 60;\n\n const durationSeconds = intervalEndSeconds - intervalStartSeconds;\n const isHourStart = startMinutes === 0 && startSecs === 0;\n const isLabelStart = (intervalStartSeconds - labelOriginSeconds) % labelIntervalSeconds === 0;\n\n intervals.push({\n startTime: toTimeString({ hours: startHours, minutes: startMinutes, seconds: startSecs }),\n endTime: toTimeString({ hours: endHours, minutes: endMinutes, seconds: endSecs }),\n duration: durationSeconds,\n isHourStart,\n isLabelStart,\n });\n\n currentSeconds = intervalEndSeconds;\n }\n\n return intervals;\n}\n"],"mappings":";;;;;;AAoCA,SAAgB,oBAAoB,EAClC,WACA,SACA,iBAAiB,mBAAmB,IACpC,sBAAsB,wBAAwB,MACA;CAC9C,MAAM,kBAAkB,qBAAqB,gBAAgB;CAC7D,MAAM,uBAAuB,uBAAuB,uBAAuB,eAAe,IAAI;CAE9F,MAAM,QAAQ,gBAAgB,SAAS;CACvC,MAAM,MAAM,UAAU,gBAAgB,OAAO,IAAI;EAAE,OAAO;EAAI,SAAS;EAAI,SAAS;CAAG;CAEvF,MAAM,eAAe,MAAM,QAAQ,OAAO,MAAM,UAAU,KAAK,MAAM;CACrE,MAAM,aAAa,IAAI,QAAQ,OAAO,IAAI,UAAU,KAAK,IAAI;CAC7D,MAAM,kBAAkB,kBAAkB;CAC1C,MAAM,qBACH,eAAe,uBAAwB,oBAAoB,IAAI,IAAI;CAEtE,MAAM,YAA+B,CAAC;CACtC,IAAI,iBAAiB;CAErB,OAAO,iBAAiB,YAAY;EAClC,MAAM,uBAAuB;EAC7B,IAAI,qBAAqB,iBAAiB;EAE1C,IAAI,qBAAqB,YACvB,qBAAqB;EAGvB,MAAM,aAAa,KAAK,MAAM,uBAAuB,IAAI;EACzD,MAAM,eAAe,KAAK,MAAO,uBAAuB,OAAQ,EAAE;EAClE,MAAM,YAAY,uBAAuB;EAEzC,MAAM,WAAW,KAAK,MAAM,qBAAqB,IAAI;EACrD,MAAM,aAAa,KAAK,MAAO,qBAAqB,OAAQ,EAAE;EAC9D,MAAM,UAAU,qBAAqB;EAErC,MAAM,kBAAkB,qBAAqB;EAC7C,MAAM,cAAc,iBAAiB,KAAK,cAAc;EACxD,MAAM,gBAAgB,uBAAuB,sBAAsB,yBAAyB;EAE5F,UAAU,KAAK;GACb,WAAW,aAAa;IAAE,OAAO;IAAY,SAAS;IAAc,SAAS;GAAU,CAAC;GACxF,SAAS,aAAa;IAAE,OAAO;IAAU,SAAS;IAAY,SAAS;GAAQ,CAAC;GAChF,UAAU;GACV;GACA;EACF,CAAC;EAED,iBAAiB;CACnB;CAEA,OAAO;AACT"}
@@ -0,0 +1,26 @@
1
+ "use client";
2
+ //#region packages/@mantine/schedule/src/utils/get-slot-label-groups/get-slot-label-groups.ts
3
+ /** Groups consecutive time intervals by label boundaries, the first group may start before the first label */
4
+ function getSlotLabelGroups(intervals) {
5
+ const groups = [];
6
+ intervals.forEach((interval) => {
7
+ const current = groups[groups.length - 1];
8
+ if (current && !interval.isLabelStart) {
9
+ current.endTime = interval.endTime;
10
+ current.slotsCount += 1;
11
+ return;
12
+ }
13
+ groups.push({
14
+ startTime: interval.startTime,
15
+ endTime: interval.endTime,
16
+ slotsCount: 1,
17
+ isLabelStart: interval.isLabelStart,
18
+ isHourStart: interval.isHourStart
19
+ });
20
+ });
21
+ return groups;
22
+ }
23
+ //#endregion
24
+ export { getSlotLabelGroups };
25
+
26
+ //# sourceMappingURL=get-slot-label-groups.mjs.map