@salt-ds/date-components 0.0.0-snapshot-20260330155807

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 (227) hide show
  1. package/CHANGELOG.md +109 -0
  2. package/README.md +63 -0
  3. package/css/salt-date-components.css +633 -0
  4. package/dist-cjs/calendar/Calendar.css.js +6 -0
  5. package/dist-cjs/calendar/Calendar.css.js.map +1 -0
  6. package/dist-cjs/calendar/Calendar.js +154 -0
  7. package/dist-cjs/calendar/Calendar.js.map +1 -0
  8. package/dist-cjs/calendar/CalendarGrid.js +85 -0
  9. package/dist-cjs/calendar/CalendarGrid.js.map +1 -0
  10. package/dist-cjs/calendar/CalendarMonthHeader.css.js +6 -0
  11. package/dist-cjs/calendar/CalendarMonthHeader.css.js.map +1 -0
  12. package/dist-cjs/calendar/CalendarMonthHeader.js +41 -0
  13. package/dist-cjs/calendar/CalendarMonthHeader.js.map +1 -0
  14. package/dist-cjs/calendar/CalendarNavigation.css.js +6 -0
  15. package/dist-cjs/calendar/CalendarNavigation.css.js.map +1 -0
  16. package/dist-cjs/calendar/CalendarNavigation.js +334 -0
  17. package/dist-cjs/calendar/CalendarNavigation.js.map +1 -0
  18. package/dist-cjs/calendar/CalendarWeekHeader.css.js +6 -0
  19. package/dist-cjs/calendar/CalendarWeekHeader.css.js.map +1 -0
  20. package/dist-cjs/calendar/CalendarWeekHeader.js +46 -0
  21. package/dist-cjs/calendar/CalendarWeekHeader.js.map +1 -0
  22. package/dist-cjs/calendar/internal/CalendarContext.js +23 -0
  23. package/dist-cjs/calendar/internal/CalendarContext.js.map +1 -0
  24. package/dist-cjs/calendar/internal/CalendarDay.css.js +6 -0
  25. package/dist-cjs/calendar/internal/CalendarDay.css.js.map +1 -0
  26. package/dist-cjs/calendar/internal/CalendarDay.js +98 -0
  27. package/dist-cjs/calendar/internal/CalendarDay.js.map +1 -0
  28. package/dist-cjs/calendar/internal/CalendarMonth.css.js +6 -0
  29. package/dist-cjs/calendar/internal/CalendarMonth.css.js.map +1 -0
  30. package/dist-cjs/calendar/internal/CalendarMonth.js +81 -0
  31. package/dist-cjs/calendar/internal/CalendarMonth.js.map +1 -0
  32. package/dist-cjs/calendar/internal/createAnnouncement.js +90 -0
  33. package/dist-cjs/calendar/internal/createAnnouncement.js.map +1 -0
  34. package/dist-cjs/calendar/internal/useFocusManagement.js +66 -0
  35. package/dist-cjs/calendar/internal/useFocusManagement.js.map +1 -0
  36. package/dist-cjs/calendar/internal/utils.js +50 -0
  37. package/dist-cjs/calendar/internal/utils.js.map +1 -0
  38. package/dist-cjs/calendar/useCalendar.js +464 -0
  39. package/dist-cjs/calendar/useCalendar.js.map +1 -0
  40. package/dist-cjs/calendar/useCalendarDay.js +84 -0
  41. package/dist-cjs/calendar/useCalendarDay.js.map +1 -0
  42. package/dist-cjs/calendar/useCalendarSelection.js +353 -0
  43. package/dist-cjs/calendar/useCalendarSelection.js.map +1 -0
  44. package/dist-cjs/calendar/useDateSelectionAnnouncer.js +52 -0
  45. package/dist-cjs/calendar/useDateSelectionAnnouncer.js.map +1 -0
  46. package/dist-cjs/date-input/DateInput.css.js +6 -0
  47. package/dist-cjs/date-input/DateInput.css.js.map +1 -0
  48. package/dist-cjs/date-input/DateInputRange.js +353 -0
  49. package/dist-cjs/date-input/DateInputRange.js.map +1 -0
  50. package/dist-cjs/date-input/DateInputSingle.js +237 -0
  51. package/dist-cjs/date-input/DateInputSingle.js.map +1 -0
  52. package/dist-cjs/date-picker/DatePicker.js +83 -0
  53. package/dist-cjs/date-picker/DatePicker.js.map +1 -0
  54. package/dist-cjs/date-picker/DatePickerActions.css.js +6 -0
  55. package/dist-cjs/date-picker/DatePickerActions.css.js.map +1 -0
  56. package/dist-cjs/date-picker/DatePickerActions.js +119 -0
  57. package/dist-cjs/date-picker/DatePickerActions.js.map +1 -0
  58. package/dist-cjs/date-picker/DatePickerContext.js +36 -0
  59. package/dist-cjs/date-picker/DatePickerContext.js.map +1 -0
  60. package/dist-cjs/date-picker/DatePickerHelperText.css.js +6 -0
  61. package/dist-cjs/date-picker/DatePickerHelperText.css.js.map +1 -0
  62. package/dist-cjs/date-picker/DatePickerHelperText.js +36 -0
  63. package/dist-cjs/date-picker/DatePickerHelperText.js.map +1 -0
  64. package/dist-cjs/date-picker/DatePickerOverlay.css.js +6 -0
  65. package/dist-cjs/date-picker/DatePickerOverlay.css.js.map +1 -0
  66. package/dist-cjs/date-picker/DatePickerOverlay.js +49 -0
  67. package/dist-cjs/date-picker/DatePickerOverlay.js.map +1 -0
  68. package/dist-cjs/date-picker/DatePickerOverlayProvider.js +164 -0
  69. package/dist-cjs/date-picker/DatePickerOverlayProvider.js.map +1 -0
  70. package/dist-cjs/date-picker/DatePickerPanel.css.js +6 -0
  71. package/dist-cjs/date-picker/DatePickerPanel.css.js.map +1 -0
  72. package/dist-cjs/date-picker/DatePickerRangeGridPanel.js +250 -0
  73. package/dist-cjs/date-picker/DatePickerRangeGridPanel.js.map +1 -0
  74. package/dist-cjs/date-picker/DatePickerRangeInput.js +206 -0
  75. package/dist-cjs/date-picker/DatePickerRangeInput.js.map +1 -0
  76. package/dist-cjs/date-picker/DatePickerRangePanel.js +365 -0
  77. package/dist-cjs/date-picker/DatePickerRangePanel.js.map +1 -0
  78. package/dist-cjs/date-picker/DatePickerSingleGridPanel.js +262 -0
  79. package/dist-cjs/date-picker/DatePickerSingleGridPanel.js.map +1 -0
  80. package/dist-cjs/date-picker/DatePickerSingleInput.js +150 -0
  81. package/dist-cjs/date-picker/DatePickerSingleInput.js.map +1 -0
  82. package/dist-cjs/date-picker/DatePickerSinglePanel.js +20 -0
  83. package/dist-cjs/date-picker/DatePickerSinglePanel.js.map +1 -0
  84. package/dist-cjs/date-picker/DatePickerTrigger.js +32 -0
  85. package/dist-cjs/date-picker/DatePickerTrigger.js.map +1 -0
  86. package/dist-cjs/date-picker/useDatePicker.js +222 -0
  87. package/dist-cjs/date-picker/useDatePicker.js.map +1 -0
  88. package/dist-cjs/date-picker/useFocusOut.js +43 -0
  89. package/dist-cjs/date-picker/useFocusOut.js.map +1 -0
  90. package/dist-cjs/date-picker/useKeyboard.js +22 -0
  91. package/dist-cjs/date-picker/useKeyboard.js.map +1 -0
  92. package/dist-cjs/index.js +64 -0
  93. package/dist-cjs/index.js.map +1 -0
  94. package/dist-cjs/localization-provider/LocalizationProvider.js +51 -0
  95. package/dist-cjs/localization-provider/LocalizationProvider.js.map +1 -0
  96. package/dist-es/calendar/Calendar.css.js +4 -0
  97. package/dist-es/calendar/Calendar.css.js.map +1 -0
  98. package/dist-es/calendar/Calendar.js +152 -0
  99. package/dist-es/calendar/Calendar.js.map +1 -0
  100. package/dist-es/calendar/CalendarGrid.js +83 -0
  101. package/dist-es/calendar/CalendarGrid.js.map +1 -0
  102. package/dist-es/calendar/CalendarMonthHeader.css.js +4 -0
  103. package/dist-es/calendar/CalendarMonthHeader.css.js.map +1 -0
  104. package/dist-es/calendar/CalendarMonthHeader.js +39 -0
  105. package/dist-es/calendar/CalendarMonthHeader.js.map +1 -0
  106. package/dist-es/calendar/CalendarNavigation.css.js +4 -0
  107. package/dist-es/calendar/CalendarNavigation.css.js.map +1 -0
  108. package/dist-es/calendar/CalendarNavigation.js +332 -0
  109. package/dist-es/calendar/CalendarNavigation.js.map +1 -0
  110. package/dist-es/calendar/CalendarWeekHeader.css.js +4 -0
  111. package/dist-es/calendar/CalendarWeekHeader.css.js.map +1 -0
  112. package/dist-es/calendar/CalendarWeekHeader.js +44 -0
  113. package/dist-es/calendar/CalendarWeekHeader.js.map +1 -0
  114. package/dist-es/calendar/internal/CalendarContext.js +20 -0
  115. package/dist-es/calendar/internal/CalendarContext.js.map +1 -0
  116. package/dist-es/calendar/internal/CalendarDay.css.js +4 -0
  117. package/dist-es/calendar/internal/CalendarDay.css.js.map +1 -0
  118. package/dist-es/calendar/internal/CalendarDay.js +96 -0
  119. package/dist-es/calendar/internal/CalendarDay.js.map +1 -0
  120. package/dist-es/calendar/internal/CalendarMonth.css.js +4 -0
  121. package/dist-es/calendar/internal/CalendarMonth.css.js.map +1 -0
  122. package/dist-es/calendar/internal/CalendarMonth.js +79 -0
  123. package/dist-es/calendar/internal/CalendarMonth.js.map +1 -0
  124. package/dist-es/calendar/internal/createAnnouncement.js +87 -0
  125. package/dist-es/calendar/internal/createAnnouncement.js.map +1 -0
  126. package/dist-es/calendar/internal/useFocusManagement.js +64 -0
  127. package/dist-es/calendar/internal/useFocusManagement.js.map +1 -0
  128. package/dist-es/calendar/internal/utils.js +44 -0
  129. package/dist-es/calendar/internal/utils.js.map +1 -0
  130. package/dist-es/calendar/useCalendar.js +462 -0
  131. package/dist-es/calendar/useCalendar.js.map +1 -0
  132. package/dist-es/calendar/useCalendarDay.js +82 -0
  133. package/dist-es/calendar/useCalendarDay.js.map +1 -0
  134. package/dist-es/calendar/useCalendarSelection.js +349 -0
  135. package/dist-es/calendar/useCalendarSelection.js.map +1 -0
  136. package/dist-es/calendar/useDateSelectionAnnouncer.js +50 -0
  137. package/dist-es/calendar/useDateSelectionAnnouncer.js.map +1 -0
  138. package/dist-es/date-input/DateInput.css.js +4 -0
  139. package/dist-es/date-input/DateInput.css.js.map +1 -0
  140. package/dist-es/date-input/DateInputRange.js +350 -0
  141. package/dist-es/date-input/DateInputRange.js.map +1 -0
  142. package/dist-es/date-input/DateInputSingle.js +235 -0
  143. package/dist-es/date-input/DateInputSingle.js.map +1 -0
  144. package/dist-es/date-picker/DatePicker.js +80 -0
  145. package/dist-es/date-picker/DatePicker.js.map +1 -0
  146. package/dist-es/date-picker/DatePickerActions.css.js +4 -0
  147. package/dist-es/date-picker/DatePickerActions.css.js.map +1 -0
  148. package/dist-es/date-picker/DatePickerActions.js +117 -0
  149. package/dist-es/date-picker/DatePickerActions.js.map +1 -0
  150. package/dist-es/date-picker/DatePickerContext.js +32 -0
  151. package/dist-es/date-picker/DatePickerContext.js.map +1 -0
  152. package/dist-es/date-picker/DatePickerHelperText.css.js +4 -0
  153. package/dist-es/date-picker/DatePickerHelperText.css.js.map +1 -0
  154. package/dist-es/date-picker/DatePickerHelperText.js +34 -0
  155. package/dist-es/date-picker/DatePickerHelperText.js.map +1 -0
  156. package/dist-es/date-picker/DatePickerOverlay.css.js +4 -0
  157. package/dist-es/date-picker/DatePickerOverlay.css.js.map +1 -0
  158. package/dist-es/date-picker/DatePickerOverlay.js +47 -0
  159. package/dist-es/date-picker/DatePickerOverlay.js.map +1 -0
  160. package/dist-es/date-picker/DatePickerOverlayProvider.js +161 -0
  161. package/dist-es/date-picker/DatePickerOverlayProvider.js.map +1 -0
  162. package/dist-es/date-picker/DatePickerPanel.css.js +4 -0
  163. package/dist-es/date-picker/DatePickerPanel.css.js.map +1 -0
  164. package/dist-es/date-picker/DatePickerRangeGridPanel.js +248 -0
  165. package/dist-es/date-picker/DatePickerRangeGridPanel.js.map +1 -0
  166. package/dist-es/date-picker/DatePickerRangeInput.js +203 -0
  167. package/dist-es/date-picker/DatePickerRangeInput.js.map +1 -0
  168. package/dist-es/date-picker/DatePickerRangePanel.js +363 -0
  169. package/dist-es/date-picker/DatePickerRangePanel.js.map +1 -0
  170. package/dist-es/date-picker/DatePickerSingleGridPanel.js +260 -0
  171. package/dist-es/date-picker/DatePickerSingleGridPanel.js.map +1 -0
  172. package/dist-es/date-picker/DatePickerSingleInput.js +148 -0
  173. package/dist-es/date-picker/DatePickerSingleInput.js.map +1 -0
  174. package/dist-es/date-picker/DatePickerSinglePanel.js +18 -0
  175. package/dist-es/date-picker/DatePickerSinglePanel.js.map +1 -0
  176. package/dist-es/date-picker/DatePickerTrigger.js +30 -0
  177. package/dist-es/date-picker/DatePickerTrigger.js.map +1 -0
  178. package/dist-es/date-picker/useDatePicker.js +220 -0
  179. package/dist-es/date-picker/useDatePicker.js.map +1 -0
  180. package/dist-es/date-picker/useFocusOut.js +41 -0
  181. package/dist-es/date-picker/useFocusOut.js.map +1 -0
  182. package/dist-es/date-picker/useKeyboard.js +20 -0
  183. package/dist-es/date-picker/useKeyboard.js.map +1 -0
  184. package/dist-es/index.js +25 -0
  185. package/dist-es/index.js.map +1 -0
  186. package/dist-es/localization-provider/LocalizationProvider.js +47 -0
  187. package/dist-es/localization-provider/LocalizationProvider.js.map +1 -0
  188. package/dist-types/calendar/Calendar.d.ts +105 -0
  189. package/dist-types/calendar/CalendarGrid.d.ts +27 -0
  190. package/dist-types/calendar/CalendarMonthHeader.d.ts +17 -0
  191. package/dist-types/calendar/CalendarNavigation.d.ts +43 -0
  192. package/dist-types/calendar/CalendarWeekHeader.d.ts +6 -0
  193. package/dist-types/calendar/index.d.ts +9 -0
  194. package/dist-types/calendar/internal/CalendarContext.d.ts +6 -0
  195. package/dist-types/calendar/internal/CalendarDay.d.ts +33 -0
  196. package/dist-types/calendar/internal/CalendarMonth.d.ts +14 -0
  197. package/dist-types/calendar/internal/createAnnouncement.d.ts +24 -0
  198. package/dist-types/calendar/internal/useFocusManagement.d.ts +9 -0
  199. package/dist-types/calendar/internal/utils.d.ts +6 -0
  200. package/dist-types/calendar/useCalendar.d.ts +335 -0
  201. package/dist-types/calendar/useCalendarDay.d.ts +67 -0
  202. package/dist-types/calendar/useCalendarSelection.d.ts +145 -0
  203. package/dist-types/calendar/useDateSelectionAnnouncer.d.ts +6 -0
  204. package/dist-types/date-input/DateInputRange.d.ts +131 -0
  205. package/dist-types/date-input/DateInputSingle.d.ts +99 -0
  206. package/dist-types/date-input/index.d.ts +2 -0
  207. package/dist-types/date-picker/DatePicker.d.ts +52 -0
  208. package/dist-types/date-picker/DatePickerActions.d.ts +79 -0
  209. package/dist-types/date-picker/DatePickerContext.d.ts +172 -0
  210. package/dist-types/date-picker/DatePickerHelperText.d.ts +4 -0
  211. package/dist-types/date-picker/DatePickerOverlay.d.ts +11 -0
  212. package/dist-types/date-picker/DatePickerOverlayProvider.d.ts +106 -0
  213. package/dist-types/date-picker/DatePickerRangeGridPanel.d.ts +14 -0
  214. package/dist-types/date-picker/DatePickerRangeInput.d.ts +17 -0
  215. package/dist-types/date-picker/DatePickerRangePanel.d.ts +83 -0
  216. package/dist-types/date-picker/DatePickerSingleGridPanel.d.ts +63 -0
  217. package/dist-types/date-picker/DatePickerSingleInput.d.ts +15 -0
  218. package/dist-types/date-picker/DatePickerSinglePanel.d.ts +8 -0
  219. package/dist-types/date-picker/DatePickerTrigger.d.ts +9 -0
  220. package/dist-types/date-picker/index.d.ts +13 -0
  221. package/dist-types/date-picker/useDatePicker.d.ts +121 -0
  222. package/dist-types/date-picker/useFocusOut.d.ts +9 -0
  223. package/dist-types/date-picker/useKeyboard.d.ts +20 -0
  224. package/dist-types/index.d.ts +4 -0
  225. package/dist-types/localization-provider/LocalizationProvider.d.ts +62 -0
  226. package/dist-types/localization-provider/index.d.ts +1 -0
  227. package/package.json +60 -0
@@ -0,0 +1,462 @@
1
+ import { useBreakpoint, resolveResponsiveValue, useControlled } from '@salt-ds/core';
2
+ import { useCallback, useMemo, useEffect } from 'react';
3
+ import { useLocalization } from '../localization-provider/LocalizationProvider.js';
4
+ import { createSingleSelectionAnnouncement, createRangeSelectionAnnouncement } from './internal/createAnnouncement.js';
5
+ import { generateDatesForMonth } from './internal/utils.js';
6
+ import { useCalendarSelection, isDateRangeSelection } from './useCalendarSelection.js';
7
+ import { useDateSelectionAnnouncer } from './useDateSelectionAnnouncer.js';
8
+
9
+ const defaultIsDayUnselectable = () => false;
10
+ const defaultIsDayHighlighted = () => false;
11
+ function useCalendar(props) {
12
+ const {
13
+ dateAdapter,
14
+ defaultDates: { minDate: defaultMinDate, maxDate: defaultMaxDate }
15
+ } = useLocalization();
16
+ const {
17
+ createAnnouncement,
18
+ timezone,
19
+ defaultSelectedDate,
20
+ defaultVisibleMonth = dateAdapter.today(timezone),
21
+ hideOutOfRangeDates,
22
+ hoveredDate: hoveredDateProp,
23
+ focusedDate: focusedDateProp,
24
+ focusedDateRef,
25
+ isDayHighlighted = defaultIsDayHighlighted,
26
+ isDayUnselectable = defaultIsDayUnselectable,
27
+ multiselect,
28
+ maxDate = defaultMaxDate,
29
+ minDate = defaultMinDate,
30
+ numberOfVisibleMonths = 1,
31
+ onHoveredDateChange,
32
+ onSelectionChange,
33
+ onVisibleMonthChange,
34
+ onFocusedDateChange,
35
+ select,
36
+ selectedDate: selectedDateProp,
37
+ selectionVariant,
38
+ visibleMonth: visibleMonthProp,
39
+ startDateOffset,
40
+ endDateOffset
41
+ } = props;
42
+ const { matchedBreakpoints } = useBreakpoint();
43
+ const responsiveNumberOfVisibleMonths = resolveResponsiveValue(numberOfVisibleMonths, matchedBreakpoints) ?? 1;
44
+ const [hoveredDate, setHoveredDateState] = useControlled({
45
+ controlled: hoveredDateProp,
46
+ default: void 0,
47
+ name: "Calendar",
48
+ state: "hoveredDate"
49
+ });
50
+ const setHoveredDate = useCallback(
51
+ (event, date) => {
52
+ setHoveredDateState(date);
53
+ onHoveredDateChange == null ? void 0 : onHoveredDateChange(event, date);
54
+ },
55
+ [onHoveredDateChange]
56
+ );
57
+ const [visibleMonth, setVisibleMonthState] = useControlled({
58
+ controlled: useMemo(
59
+ () => visibleMonthProp ? dateAdapter.startOf(visibleMonthProp, "month") : void 0,
60
+ [visibleMonthProp, dateAdapter]
61
+ ),
62
+ // biome-ignore lint/correctness/useExhaustiveDependencies: just on mount
63
+ default: useMemo(
64
+ () => dateAdapter.startOf(defaultVisibleMonth, "month"),
65
+ []
66
+ ),
67
+ name: "Calendar",
68
+ state: "visibleMonth"
69
+ });
70
+ const isOutsideAllowedDates = useCallback(
71
+ (date) => {
72
+ if (dateAdapter.compare(date, minDate) < 0) {
73
+ return -1;
74
+ }
75
+ if (dateAdapter.compare(date, maxDate) > 0) {
76
+ return 1;
77
+ }
78
+ return 0;
79
+ },
80
+ [dateAdapter, maxDate, minDate]
81
+ );
82
+ const isOutsideAllowedMonths = useCallback(
83
+ (date) => {
84
+ const startOfMonth = dateAdapter.startOf(date, "month");
85
+ const endOfMonth = dateAdapter.endOf(date, "month");
86
+ return dateAdapter.compare(endOfMonth, minDate) < 0 || dateAdapter.compare(startOfMonth, maxDate) > 0;
87
+ },
88
+ [dateAdapter, minDate, maxDate]
89
+ );
90
+ const isOutsideAllowedYears = useCallback(
91
+ (date) => {
92
+ const startOfYear = dateAdapter.startOf(date, "year");
93
+ const endOfYear = dateAdapter.endOf(date, "year");
94
+ return dateAdapter.compare(endOfYear, minDate) < 0 || dateAdapter.compare(startOfYear, maxDate) > 0;
95
+ },
96
+ [dateAdapter, minDate, maxDate]
97
+ );
98
+ const isDaySelectable = useCallback(
99
+ (date) => !(date && (isDayUnselectable(date) || isOutsideAllowedDates(date) !== 0)),
100
+ [isDayUnselectable, isOutsideAllowedDates]
101
+ );
102
+ const isDayVisible = useCallback(
103
+ (date) => {
104
+ if (!date) {
105
+ return false;
106
+ }
107
+ const startInsideDays = dateAdapter.startOf(visibleMonth, "month");
108
+ if (dateAdapter.compare(date, startInsideDays) < 0) return false;
109
+ const endVisibleMonth = dateAdapter.add(visibleMonth, {
110
+ months: responsiveNumberOfVisibleMonths - 1
111
+ });
112
+ const endInsideDays = dateAdapter.endOf(endVisibleMonth, "month");
113
+ return !(dateAdapter.compare(date, endInsideDays) > 0);
114
+ },
115
+ [dateAdapter, responsiveNumberOfVisibleMonths, visibleMonth]
116
+ );
117
+ const selectionManager = useCalendarSelection({
118
+ defaultSelectedDate,
119
+ selectedDate: selectedDateProp,
120
+ isDaySelectable,
121
+ isOutsideAllowedDates,
122
+ multiselect,
123
+ onSelectionChange,
124
+ select,
125
+ selectionVariant,
126
+ startDateOffset,
127
+ endDateOffset
128
+ });
129
+ const {
130
+ state: { selectedDate },
131
+ helpers: {
132
+ isSelected,
133
+ isSameDay,
134
+ setSelectedDate,
135
+ isSelectedStart,
136
+ isSelectedSpan,
137
+ isSelectedEnd
138
+ }
139
+ } = selectionManager;
140
+ const isHovered = useCallback(
141
+ (date) => {
142
+ return !!hoveredDate && dateAdapter.isSame(date, hoveredDate, "day");
143
+ },
144
+ [dateAdapter, hoveredDate]
145
+ );
146
+ const isHoveredStart = useCallback(
147
+ (date) => {
148
+ if (selectionVariant === "range" && hoveredDate && dateAdapter.isSame(date, hoveredDate, "day")) {
149
+ const dateRanges = Array.isArray(selectedDate) ? selectedDate : [selectedDate];
150
+ const allDatesPopulated = dateRanges.every(
151
+ (range) => (range == null ? void 0 : range.startDate) && (range == null ? void 0 : range.endDate)
152
+ );
153
+ const startDateMatches = dateRanges.some(
154
+ (range) => (range == null ? void 0 : range.startDate) && dateAdapter.isSame(date, range.startDate, "day")
155
+ );
156
+ const firstIncompleteRange = dateRanges.find(
157
+ (range) => (range == null ? void 0 : range.startDate) && !(range == null ? void 0 : range.endDate)
158
+ );
159
+ const newDateRangeRequired = (firstIncompleteRange == null ? void 0 : firstIncompleteRange.startDate) && dateAdapter.compare(date, firstIncompleteRange.startDate) < 0;
160
+ return allDatesPopulated || startDateMatches || newDateRangeRequired;
161
+ }
162
+ if (selectionVariant === "offset" && hoveredDate) {
163
+ const startDate = startDateOffset ? startDateOffset(hoveredDate) : hoveredDate;
164
+ return dateAdapter.isSame(date, startDate, "day") && (!isDaySelectable || isDaySelectable(date));
165
+ }
166
+ return false;
167
+ },
168
+ [
169
+ dateAdapter,
170
+ selectionVariant,
171
+ selectedDate,
172
+ hoveredDate,
173
+ isDaySelectable,
174
+ startDateOffset
175
+ ]
176
+ );
177
+ const getDefaultFocusedDate = () => {
178
+ if (selectedDate && (selectionVariant === "range" || selectionVariant === "offset")) {
179
+ const getFocusableDate = (result, selection) => {
180
+ if ((selection == null ? void 0 : selection.startDate) && isDayVisible(selection.startDate)) {
181
+ return [...result, selection.startDate];
182
+ }
183
+ if ((selection == null ? void 0 : selection.endDate) && isDayVisible(selection.endDate)) {
184
+ return [...result, selection.endDate];
185
+ }
186
+ return result;
187
+ };
188
+ let focusableSelectedDates;
189
+ if (!multiselect) {
190
+ focusableSelectedDates = [selectedDate];
191
+ } else {
192
+ focusableSelectedDates = selectedDate;
193
+ }
194
+ const selectionInMonth = focusableSelectedDates.reduce(getFocusableDate, []).sort((a, b) => dateAdapter.compare(a, b));
195
+ if (selectionInMonth.length > 0) {
196
+ return selectionInMonth[0];
197
+ }
198
+ } else if (selectedDate && selectionVariant === "single") {
199
+ const focusableSelectedDate = multiselect ? selectedDate == null ? void 0 : selectedDate[0] : selectedDate;
200
+ if (focusableSelectedDate && isDayVisible(focusableSelectedDate)) {
201
+ return focusableSelectedDate;
202
+ }
203
+ }
204
+ if ((isDaySelectable == null ? void 0 : isDaySelectable(dateAdapter.today(timezone))) && isDayVisible(dateAdapter.today(timezone))) {
205
+ return dateAdapter.today(timezone);
206
+ }
207
+ const firstSelectableDate = generateDatesForMonth(
208
+ dateAdapter,
209
+ visibleMonth
210
+ ).find((visibleDay) => visibleDay && (isDaySelectable == null ? void 0 : isDaySelectable(visibleDay)));
211
+ if (firstSelectableDate) {
212
+ return firstSelectableDate;
213
+ }
214
+ return null;
215
+ };
216
+ const [focusedDate, setFocusedDateState] = useControlled({
217
+ controlled: focusedDateProp,
218
+ // biome-ignore lint/correctness/useExhaustiveDependencies: initial value only
219
+ default: useMemo(() => getDefaultFocusedDate(), []),
220
+ name: "Calendar",
221
+ state: "focusedDate"
222
+ });
223
+ const focusableDate = useMemo(() => {
224
+ const dates = [];
225
+ if (Array.isArray(selectedDate)) {
226
+ for (const selection of selectedDate) {
227
+ if (isDateRangeSelection(selection)) {
228
+ if (selection.startDate && isDayVisible(selection.startDate)) {
229
+ dates.push(selection.startDate);
230
+ } else if (selection.endDate && isDayVisible(selection.endDate)) {
231
+ dates.push(selection.endDate);
232
+ }
233
+ } else if (isDayVisible(selection)) {
234
+ dates.push(selection);
235
+ }
236
+ }
237
+ } else if (selectedDate) {
238
+ if (isDateRangeSelection(selectedDate)) {
239
+ if (selectedDate.startDate && isDayVisible(selectedDate.startDate)) {
240
+ dates.push(selectedDate.startDate);
241
+ } else if (selectedDate.endDate && isDayVisible(selectedDate.endDate)) {
242
+ dates.push(selectedDate.endDate);
243
+ }
244
+ } else if (isDayVisible(selectedDate)) {
245
+ dates.push(selectedDate);
246
+ }
247
+ }
248
+ if (focusedDate && visibleMonth && dateAdapter.isSame(focusedDate, visibleMonth, "month")) {
249
+ dates.push(focusedDate);
250
+ return dates[0];
251
+ }
252
+ if (dates.length === 0 && isDaySelectable(dateAdapter.today(timezone)) && isDayVisible(dateAdapter.today(timezone))) {
253
+ dates.push(dateAdapter.today(timezone));
254
+ }
255
+ if (dates.length === 0 || !dates.some(isDayVisible)) {
256
+ const firstSelectableDate = generateDatesForMonth(
257
+ dateAdapter,
258
+ visibleMonth
259
+ ).find((visibleDay) => visibleDay && isDaySelectable(visibleDay));
260
+ if (firstSelectableDate) {
261
+ dates.push(firstSelectableDate);
262
+ }
263
+ }
264
+ return dates.length ? dates[0] : null;
265
+ }, [
266
+ dateAdapter,
267
+ focusedDate,
268
+ isDaySelectable,
269
+ isDayVisible,
270
+ selectedDate,
271
+ timezone,
272
+ visibleMonth
273
+ ]);
274
+ const isHoveredSpan = useCallback(
275
+ (date) => {
276
+ if (selectionVariant === "range") {
277
+ const dateRanges = Array.isArray(selectedDate) ? selectedDate : [selectedDate];
278
+ return dateRanges.some((range) => {
279
+ if (isDateRangeSelection(range) && dateAdapter.isValid(range.startDate) && !dateAdapter.isValid(range.endDate) && isOutsideAllowedDates(range.startDate) === 0 && hoveredDate) {
280
+ const isForwardRange = dateAdapter.compare(hoveredDate, range.startDate) > 0 && dateAdapter.compare(date, range.startDate) > 0 && dateAdapter.compare(date, hoveredDate) < 0;
281
+ const isValidDayHovered = !isDaySelectable || isDaySelectable(hoveredDate);
282
+ return isForwardRange && isValidDayHovered;
283
+ }
284
+ return false;
285
+ });
286
+ }
287
+ if (selectionVariant === "offset" && hoveredDate) {
288
+ const startDate = startDateOffset ? startDateOffset(hoveredDate) : hoveredDate;
289
+ const endDate = endDateOffset ? endDateOffset(hoveredDate) : hoveredDate;
290
+ return dateAdapter.compare(date, startDate) > 0 && dateAdapter.compare(date, endDate) < 0 && (!isDaySelectable || isDaySelectable(date));
291
+ }
292
+ return false;
293
+ },
294
+ [
295
+ dateAdapter,
296
+ endDateOffset,
297
+ isOutsideAllowedDates,
298
+ selectionVariant,
299
+ selectedDate,
300
+ hoveredDate,
301
+ isDaySelectable,
302
+ startDateOffset
303
+ ]
304
+ );
305
+ const isHoveredEnd = useCallback(
306
+ (date) => {
307
+ if (selectionVariant === "range" && hoveredDate && dateAdapter.isSame(date, hoveredDate, "day")) {
308
+ const dateRanges = Array.isArray(selectedDate) ? selectedDate : [selectedDate];
309
+ const isIncompleteRange = dateRanges.some(
310
+ (range) => (range == null ? void 0 : range.startDate) && !(range == null ? void 0 : range.endDate) && hoveredDate && dateAdapter.compare(hoveredDate, range.startDate) >= 0
311
+ );
312
+ const endDateMatches = dateRanges.some(
313
+ (range) => (range == null ? void 0 : range.endDate) && dateAdapter.isSame(range.endDate, date, "day")
314
+ );
315
+ return endDateMatches || isIncompleteRange;
316
+ }
317
+ if (selectionVariant === "offset" && hoveredDate) {
318
+ const endDate = endDateOffset ? endDateOffset(hoveredDate) : hoveredDate;
319
+ return dateAdapter.isSame(date, endDate, "day") && (!isDaySelectable || isDaySelectable(date));
320
+ }
321
+ return false;
322
+ },
323
+ [
324
+ dateAdapter,
325
+ selectionVariant,
326
+ selectedDate,
327
+ hoveredDate,
328
+ endDateOffset,
329
+ isDaySelectable
330
+ ]
331
+ );
332
+ const defaultCreateAnnouncement = selectionVariant === "single" ? createSingleSelectionAnnouncement : createRangeSelectionAnnouncement;
333
+ const { announce } = useDateSelectionAnnouncer(
334
+ createAnnouncement === void 0 ? defaultCreateAnnouncement : createAnnouncement,
335
+ dateAdapter
336
+ );
337
+ const setFocusedDate = useCallback(
338
+ (event, date) => {
339
+ if (focusedDateRef && (event == null ? void 0 : event.target) instanceof HTMLElement) {
340
+ focusedDateRef.current = event.target;
341
+ }
342
+ const exceededRangeLimit = date ? isOutsideAllowedDates(date) : 0;
343
+ if (date && (focusedDate && dateAdapter.isSame(date, focusedDate, "day") || exceededRangeLimit !== 0)) {
344
+ if (exceededRangeLimit !== 0) {
345
+ announce(
346
+ exceededRangeLimit < 0 ? "minFocusableDateExceeded" : "maxFocusableDateExceeded"
347
+ );
348
+ }
349
+ return;
350
+ }
351
+ setFocusedDateState(date);
352
+ onFocusedDateChange == null ? void 0 : onFocusedDateChange(event, date);
353
+ },
354
+ [
355
+ announce,
356
+ dateAdapter,
357
+ focusedDate,
358
+ focusedDateRef,
359
+ isOutsideAllowedDates,
360
+ onFocusedDateChange
361
+ ]
362
+ );
363
+ useEffect(() => {
364
+ const shouldTransition = focusedDate && !focusedDateProp !== void 0 && !isDayVisible(focusedDate) && isOutsideAllowedDates(focusedDate) === 0;
365
+ if (shouldTransition) {
366
+ setVisibleMonth(null, dateAdapter.startOf(focusedDate, "month"));
367
+ }
368
+ }, [dateAdapter, focusedDateProp, isOutsideAllowedDates, focusedDate]);
369
+ const setVisibleMonth = useCallback(
370
+ (event, newVisibleMonth) => {
371
+ setVisibleMonthState(newVisibleMonth);
372
+ announce("visibleMonthChanged", {
373
+ startVisibleMonth: newVisibleMonth,
374
+ endVisibleMonth: dateAdapter.add(newVisibleMonth, {
375
+ months: responsiveNumberOfVisibleMonths - 1
376
+ })
377
+ });
378
+ onVisibleMonthChange == null ? void 0 : onVisibleMonthChange(event, newVisibleMonth);
379
+ },
380
+ [
381
+ announce,
382
+ dateAdapter,
383
+ onVisibleMonthChange,
384
+ responsiveNumberOfVisibleMonths
385
+ ]
386
+ );
387
+ return useMemo(
388
+ () => ({
389
+ state: {
390
+ visibleMonth,
391
+ timezone,
392
+ multiselect,
393
+ minDate,
394
+ maxDate,
395
+ numberOfVisibleMonths: responsiveNumberOfVisibleMonths,
396
+ selectionVariant,
397
+ hideOutOfRangeDates,
398
+ focusedDate,
399
+ focusableDate,
400
+ focusedDateRef
401
+ },
402
+ helpers: {
403
+ setVisibleMonth,
404
+ isDayUnselectable,
405
+ isDayHighlighted,
406
+ isDayVisible,
407
+ isHovered,
408
+ isHoveredStart,
409
+ isHoveredSpan,
410
+ isHoveredEnd,
411
+ isOutsideAllowedDates,
412
+ isOutsideAllowedMonths,
413
+ isOutsideAllowedYears,
414
+ setFocusedDate,
415
+ setHoveredDate,
416
+ isDaySelectable,
417
+ isSelected,
418
+ isSameDay,
419
+ setSelectedDate,
420
+ isSelectedStart,
421
+ isSelectedSpan,
422
+ isSelectedEnd
423
+ }
424
+ }),
425
+ [
426
+ visibleMonth,
427
+ timezone,
428
+ multiselect,
429
+ minDate,
430
+ maxDate,
431
+ responsiveNumberOfVisibleMonths,
432
+ selectionVariant,
433
+ hideOutOfRangeDates,
434
+ focusedDate,
435
+ focusedDateRef,
436
+ focusableDate,
437
+ setVisibleMonth,
438
+ isDayUnselectable,
439
+ isDayHighlighted,
440
+ isDayVisible,
441
+ isHovered,
442
+ isHoveredStart,
443
+ isHoveredSpan,
444
+ isHoveredEnd,
445
+ isOutsideAllowedDates,
446
+ isOutsideAllowedMonths,
447
+ isOutsideAllowedYears,
448
+ setFocusedDate,
449
+ setHoveredDate,
450
+ isDaySelectable,
451
+ isSelected,
452
+ isSameDay,
453
+ setSelectedDate,
454
+ isSelectedStart,
455
+ isSelectedSpan,
456
+ isSelectedEnd
457
+ ]
458
+ );
459
+ }
460
+
461
+ export { useCalendar };
462
+ //# sourceMappingURL=useCalendar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useCalendar.js","sources":["../src/calendar/useCalendar.ts"],"sourcesContent":["import {\n type ResponsiveProp,\n resolveResponsiveValue,\n useBreakpoint,\n useControlled,\n} from \"@salt-ds/core\";\nimport type { DateFrameworkType, Timezone } from \"@salt-ds/date-adapters\";\nimport { type SyntheticEvent, useCallback, useEffect, useMemo } from \"react\";\nimport { useLocalization } from \"../localization-provider\";\nimport {\n createRangeSelectionAnnouncement,\n createSingleSelectionAnnouncement,\n} from \"./internal/createAnnouncement\";\nimport { generateDatesForMonth } from \"./internal/utils\";\nimport {\n type DateRangeSelection,\n isDateRangeSelection,\n type SingleDateSelection,\n type UseCalendarSelectionMultiselectOffsetProps,\n type UseCalendarSelectionMultiselectRangeProps,\n type UseCalendarSelectionMultiselectSingleProps,\n type UseCalendarSelectionOffsetProps,\n type UseCalendarSelectionProps,\n type UseCalendarSelectionRangeProps,\n type UseCalendarSelectionSingleProps,\n useCalendarSelection,\n} from \"./useCalendarSelection\";\nimport {\n type CreateAnnouncement,\n useDateSelectionAnnouncer,\n} from \"./useDateSelectionAnnouncer\";\n\n/**\n * Base properties for the UseCalendar hook.\n */\ninterface UseCalendarBaseProps {\n /**\n * Factory method for date selection live announcements or null to silence announcements\n */\n createAnnouncement?: CreateAnnouncement | null;\n /**\n * The default visible month.\n */\n defaultVisibleMonth?: DateFrameworkType;\n /**\n * The currently focused date in the calendar, or null if no date is focused.\n */\n focusedDate?: DateFrameworkType | null;\n /**\n * The currently hovered date.\n */\n hoveredDate?: DateFrameworkType | null;\n /**\n * Function to determine if a day is visible.\n * @param date - The date to check.\n * @returns `true` if the day is visible, otherwise `false`.\n */\n isDayVisible?: (date: DateFrameworkType) => boolean;\n /**\n * Ref to attach to the focused element, enabling focus to be controlled.\n */\n focusedDateRef?: React.MutableRefObject<HTMLElement | null>;\n /**\n * Callback fired when the focused date changes.\n * @param event - The synthetic event, if user event triggered focus or null.\n * @param date - The new focused date.\n */\n onFocusedDateChange?: (\n event: SyntheticEvent | null,\n date: DateFrameworkType | null,\n ) => void;\n /**\n * Callback fired when the hovered date changes.\n * @param event - The synthetic event.\n * @param hoveredDate - The new hovered date.\n */\n onHoveredDateChange?: (\n event: SyntheticEvent,\n hoveredDate: DateFrameworkType | null,\n ) => void;\n /**\n * Callback fired when the visible month changes.\n * @param event - The synthetic event or null if triggered by code.\n * @param visibleMonth - The new visible month.\n */\n onVisibleMonthChange?: (\n event: SyntheticEvent | null,\n visibleMonth: DateFrameworkType,\n ) => void;\n /**\n * Function to determine if a day is unselectable.\n * @param date - The date to check.\n * @returns A string reason if the day is unselectable, otherwise `false` or `undefined`.\n */\n isDayUnselectable?: (date: DateFrameworkType) => string | false | undefined;\n /**\n * Function to determine if a day is highlighted.\n * @param date - The date to check.\n * @returns A string reason if the day is highlighted, otherwise `false` or `undefined`.\n */\n isDayHighlighted?: (date: DateFrameworkType) => string | false | undefined;\n /**\n * If `true`, hides dates that are out of the selectable range.\n */\n hideOutOfRangeDates?: boolean;\n /**\n * The minimum selectable date.\n */\n minDate?: DateFrameworkType;\n /**\n * The maximum selectable date.\n */\n maxDate?: DateFrameworkType;\n /**\n * Number of visible months, maximum 12, defaults to 1.\n */\n numberOfVisibleMonths?: ResponsiveProp<\n 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12\n >;\n /**\n * Specifies the timezone behavior:\n * - If undefined, the timezone will be derived from the passed date, or from `defaultSelectedDate`/`selectedDate`.\n * - If set to \"default\", the default timezone of the date library will be used.\n * - If set to \"system\", the local system's timezone will be applied.\n * - If set to \"UTC\", the time will be returned in UTC.\n * - If set to a valid IANA timezone identifier, the time will be returned for that specific timezone.\n */\n timezone?: Timezone;\n /**\n * The currently visible month.\n */\n visibleMonth?: DateFrameworkType;\n}\n\n/**\n * UseCalendar hook props for a single date selection.\n */\nexport interface UseCalendarSingleProps\n extends UseCalendarSelectionSingleProps,\n UseCalendarBaseProps {}\n\n/**\n * UseCalendar hook props for a multi-select, single date selection.\n */\nexport interface UseCalendarMultiselectSingleProps\n extends UseCalendarSelectionMultiselectSingleProps,\n Omit<UseCalendarBaseProps, \"multiselect\"> {}\n\n/**\n * UseCalendar hook props for a date range selection.\n */\nexport interface UseCalendarRangeProps\n extends UseCalendarSelectionRangeProps,\n UseCalendarBaseProps {}\n\n/**\n * UseCalendar hook props for a multi-select, date range selection.\n */\nexport interface UseCalendarMultiselectRangeProps\n extends UseCalendarSelectionMultiselectRangeProps,\n Omit<UseCalendarBaseProps, \"multiselect\"> {}\n\n/**\n * UseCalendar hook props for an offset date selection.\n */\nexport interface UseCalendarOffsetProps\n extends UseCalendarSelectionOffsetProps,\n UseCalendarBaseProps {}\n\n/**\n * UseCalendar hook props for a multi-select, offset selection.\n */\nexport interface UseCalendarMultiselectOffsetProps\n extends UseCalendarSelectionMultiselectOffsetProps,\n Omit<UseCalendarBaseProps, \"multiselect\"> {}\n\n/**\n * UseCalendar hook props, wth the selection variant determining the return type of the date selection\n */\nexport type UseCalendarProps =\n | UseCalendarSingleProps\n | UseCalendarMultiselectSingleProps\n | UseCalendarRangeProps\n | UseCalendarMultiselectRangeProps\n | UseCalendarOffsetProps\n | UseCalendarMultiselectOffsetProps;\n\n/**\n * Default function to determine if a day is unselectable.\n * @returns `false` indicating the day is selectable.\n */\nconst defaultIsDayUnselectable = (): string | false => false;\n\n/**\n * Default function to determine if a day is highlighted.\n * @returns `false` indicating the day is not highlighted.\n */\nconst defaultIsDayHighlighted = (): string | false => false;\n\n/**\n * Represents the return type of the useCalendar hook.\n */\nexport interface UseCalendarReturn {\n /**\n * The state of the calendar.\n */\n state: {\n /**\n * The currently visible month in the calendar.\n */\n visibleMonth: DateFrameworkType;\n\n /**\n * The currently focused date in the calendar, or null if no date is focused.\n */\n focusedDate: DateFrameworkType | null;\n\n /**\n * Focusable dates based on current state\n */\n focusableDate: DateFrameworkType | null;\n\n /**\n * Ref to attach to the focused element,enabling focus to be controlled.\n */\n focusedDateRef?: React.MutableRefObject<HTMLButtonElement | null>;\n\n /**\n * Multi-select variant of the calendar, indicating if multiple date selections are allowed.\n */\n multiselect: boolean;\n /**\n * The minimum selectable date in the calendar.\n */\n minDate: DateFrameworkType;\n\n /**\n * The maximum selectable date in the calendar.\n */\n maxDate: DateFrameworkType;\n\n /**\n * The selection variant of the calendar, indicating the type of selection allowed.\n */\n selectionVariant: \"single\" | \"range\" | \"offset\";\n\n /**\n * Whether to hide dates that are out of the selectable range.\n */\n hideOutOfRangeDates?: boolean;\n\n /**\n * Number of visible months\n */\n numberOfVisibleMonths: number;\n /**\n * Specifies the timezone behavior:\n * - If undefined, the timezone will be derived from the passed date, or from `defaultSelectedDate`/`selectedDate`.\n * - If set to \"default\", the default timezone of the date library will be used.\n * - If set to \"system\", the local system's timezone will be applied.\n * - If set to \"UTC\", the time will be returned in UTC.\n * - If set to a valid IANA timezone identifier, the time will be returned for that specific timezone.\n */\n timezone?: Timezone;\n };\n\n /**\n * Helper functions for interacting with the calendar.\n */\n helpers: {\n /**\n * Sets the visible month in the calendar.\n *\n * @param event - The synthetic event or null if triggered by code.\n * @param newVisibleMonth - The new visible month to set.\n */\n setVisibleMonth: (\n event: SyntheticEvent | null,\n newVisibleMonth: DateFrameworkType,\n ) => void;\n\n /**\n * Sets the focused date in the calendar.\n *\n * @param event - The synthetic event or null if triggered by code.\n * @param date - The new date to focus.\n */\n setFocusedDate: (\n event: SyntheticEvent | null,\n date: DateFrameworkType | null,\n ) => void;\n\n /**\n * Determines if a day is unselectable.\n *\n * @param date - The date to check.\n * @returns A string reason if the day is unselectable, otherwise `false` or `undefined`.\n */\n isDayUnselectable: (date: DateFrameworkType) => string | false | undefined;\n\n /**\n * Determines if a day is highlighted.\n *\n * @param date - The date to check.\n * @returns A string reason if the day is highlighted, otherwise `false` or `undefined`.\n */\n isDayHighlighted: (date: DateFrameworkType) => string | false | undefined;\n\n /**\n * Determines if a day is visible in the calendar.\n *\n * @param date - The date to check.\n * @returns `true` if the day is visible, otherwise `false`.\n */\n isDayVisible: (date: DateFrameworkType) => boolean;\n\n /**\n * Determines if a date is outside the allowed date range.\n *\n * @param date - The date to check.\n * * @returns -1 if before the allowed range, 0 if inside, 1 if after.\n */\n isOutsideAllowedDates: (date: DateFrameworkType) => -1 | 0 | 1;\n\n /**\n * Determines if a month is outside the allowed range.\n *\n * @param date - The date to check.\n * @returns `true` if the month is outside the allowed range, otherwise `false`.\n */\n isOutsideAllowedMonths: (date: DateFrameworkType) => boolean;\n\n /**\n * Determines if a year is outside the allowed range.\n *\n * @param date - The date to check.\n * @returns `true` if the year is outside the allowed range, otherwise `false`.\n */\n isOutsideAllowedYears: (date: DateFrameworkType) => boolean;\n\n /**\n * Determines if the date range is on the same day\n *\n * @param date - The range to check.\n * @returns `true` if the range start and end date are the same\n */\n isSameDay: (date: DateFrameworkType) => boolean;\n\n /**\n * Sets the selected date in the calendar.\n *\n * @param event - The event triggering the change.\n * @param newSelectedDate - The new date to select.\n */\n setSelectedDate: (\n event:\n | React.KeyboardEvent<HTMLButtonElement>\n | React.MouseEvent<HTMLButtonElement, MouseEvent>,\n newSelectedDate: DateFrameworkType,\n ) => void;\n\n /**\n * Determines if a date is selected.\n *\n * @param date - The date to check.\n * @returns `true` if the date is selected, otherwise `false`.\n */\n isSelected: (date: DateFrameworkType) => boolean;\n\n /**\n * Determines if a date is hovered.\n *\n * @param date - The date to check.\n * @returns `true` if the date is hovered, otherwise `false`.\n */\n isHovered: (date: DateFrameworkType) => boolean;\n\n /**\n * Sets the hovered date in the calendar.\n *\n * @param event - The event triggering the change.\n * @param newHoveredDate - The new date to hover.\n */\n setHoveredDate: (\n event: SyntheticEvent,\n newHoveredDate: DateFrameworkType | null,\n ) => void;\n\n /**\n * Determines if a date is part of a selected span.\n *\n * @param date - The date to check.\n * @returns `true` if the date is part of a selected span, otherwise `false`.\n */\n isSelectedSpan: (date: DateFrameworkType) => boolean;\n\n /**\n * Determines if a date is the start of a selected range.\n *\n * @param date - The date to check.\n * @returns `true` if the date is the start of a selected range, otherwise `false`.\n */\n isSelectedStart: (date: DateFrameworkType) => boolean;\n\n /**\n * Determines if a date is the end of a selected range.\n *\n * @param date - The date to check.\n * @returns `true` if the date is the end of a selected range, otherwise `false`.\n */\n isSelectedEnd: (date: DateFrameworkType) => boolean;\n\n /**\n * Determines if the hovered and a new date range would be created, if selected.\n *\n * @param date - The date to check.\n * @returns `true` if the date is the start of a hovered offset, otherwise `false`.\n */\n isHoveredStart: (date: DateFrameworkType) => boolean;\n\n /**\n * Determines if a date is part of a hovered range.\n *\n * @param date - The date to check.\n * @returns `true` if the date is part of a hovered offset, otherwise `false`.\n */\n isHoveredSpan: (date: DateFrameworkType) => boolean;\n\n /**\n * Determines if the hovered and a date range would be completed, if selected.\n *\n * @param date - The date to check.\n * @returns `true` if the date is the end of a hovered offset, otherwise `false`.\n */\n isHoveredEnd: (date: DateFrameworkType) => boolean;\n\n /**\n * Determines if a day is selectable.\n *\n * @param date - The date to check.\n * @returns `true` if the day is selectable, otherwise `false`.\n */\n isDaySelectable: (date: DateFrameworkType) => boolean;\n };\n}\n\nexport function useCalendar(props: UseCalendarProps): UseCalendarReturn {\n const {\n dateAdapter,\n defaultDates: { minDate: defaultMinDate, maxDate: defaultMaxDate },\n } = useLocalization<DateFrameworkType>();\n const {\n createAnnouncement,\n timezone,\n defaultSelectedDate,\n defaultVisibleMonth = dateAdapter.today(timezone),\n hideOutOfRangeDates,\n hoveredDate: hoveredDateProp,\n focusedDate: focusedDateProp,\n focusedDateRef,\n isDayHighlighted = defaultIsDayHighlighted,\n isDayUnselectable = defaultIsDayUnselectable,\n multiselect,\n maxDate = defaultMaxDate,\n minDate = defaultMinDate,\n numberOfVisibleMonths = 1,\n onHoveredDateChange,\n onSelectionChange,\n onVisibleMonthChange,\n onFocusedDateChange,\n select,\n selectedDate: selectedDateProp,\n selectionVariant,\n visibleMonth: visibleMonthProp,\n startDateOffset,\n endDateOffset,\n } = props;\n const { matchedBreakpoints } = useBreakpoint();\n\n const responsiveNumberOfVisibleMonths =\n resolveResponsiveValue(numberOfVisibleMonths, matchedBreakpoints) ?? 1;\n\n const [hoveredDate, setHoveredDateState] = useControlled({\n controlled: hoveredDateProp,\n default: undefined,\n name: \"Calendar\",\n state: \"hoveredDate\",\n });\n\n const setHoveredDate = useCallback(\n (event: SyntheticEvent, date: DateFrameworkType | null) => {\n setHoveredDateState(date);\n onHoveredDateChange?.(event, date);\n },\n [onHoveredDateChange],\n );\n\n const [visibleMonth, setVisibleMonthState] = useControlled({\n controlled: useMemo(\n () =>\n visibleMonthProp\n ? dateAdapter.startOf(visibleMonthProp, \"month\")\n : undefined,\n [visibleMonthProp, dateAdapter],\n ),\n // biome-ignore lint/correctness/useExhaustiveDependencies: just on mount\n default: useMemo(\n () => dateAdapter.startOf(defaultVisibleMonth, \"month\"),\n [],\n ),\n name: \"Calendar\",\n state: \"visibleMonth\",\n });\n\n const isOutsideAllowedDates = useCallback(\n (date: DateFrameworkType): -1 | 0 | 1 => {\n if (dateAdapter.compare(date, minDate) < 0) {\n return -1;\n }\n if (dateAdapter.compare(date, maxDate) > 0) {\n return 1;\n }\n return 0;\n },\n [dateAdapter, maxDate, minDate],\n );\n\n const isOutsideAllowedMonths = useCallback(\n (date: DateFrameworkType) => {\n const startOfMonth = dateAdapter.startOf(date, \"month\");\n const endOfMonth = dateAdapter.endOf(date, \"month\");\n return (\n dateAdapter.compare(endOfMonth, minDate) < 0 ||\n dateAdapter.compare(startOfMonth, maxDate) > 0\n );\n },\n [dateAdapter, minDate, maxDate],\n );\n\n const isOutsideAllowedYears = useCallback(\n (date: DateFrameworkType) => {\n const startOfYear = dateAdapter.startOf(date, \"year\");\n const endOfYear = dateAdapter.endOf(date, \"year\");\n return (\n dateAdapter.compare(endOfYear, minDate) < 0 ||\n dateAdapter.compare(startOfYear, maxDate) > 0\n );\n },\n [dateAdapter, minDate, maxDate],\n );\n\n const isDaySelectable = useCallback(\n (date?: DateFrameworkType) =>\n !(date && (isDayUnselectable(date) || isOutsideAllowedDates(date) !== 0)),\n [isDayUnselectable, isOutsideAllowedDates],\n );\n\n const isDayVisible = useCallback(\n (date?: DateFrameworkType | null) => {\n if (!date) {\n return false;\n }\n const startInsideDays = dateAdapter.startOf(visibleMonth, \"month\");\n if (dateAdapter.compare(date, startInsideDays) < 0) return false;\n\n const endVisibleMonth = dateAdapter.add(visibleMonth, {\n months: responsiveNumberOfVisibleMonths - 1,\n });\n const endInsideDays = dateAdapter.endOf(endVisibleMonth, \"month\");\n\n return !(dateAdapter.compare(date, endInsideDays) > 0);\n },\n [dateAdapter, responsiveNumberOfVisibleMonths, visibleMonth],\n );\n\n const selectionManager = useCalendarSelection({\n defaultSelectedDate,\n selectedDate: selectedDateProp,\n isDaySelectable,\n isOutsideAllowedDates,\n multiselect,\n onSelectionChange,\n select,\n selectionVariant,\n startDateOffset,\n endDateOffset,\n } as UseCalendarSelectionProps);\n\n const {\n state: { selectedDate },\n helpers: {\n isSelected,\n isSameDay,\n setSelectedDate,\n isSelectedStart,\n isSelectedSpan,\n isSelectedEnd,\n },\n } = selectionManager;\n\n const isHovered = useCallback(\n (date: DateFrameworkType) => {\n return !!hoveredDate && dateAdapter.isSame(date, hoveredDate, \"day\");\n },\n [dateAdapter, hoveredDate],\n );\n\n const isHoveredStart = useCallback(\n (date: DateFrameworkType) => {\n if (\n selectionVariant === \"range\" &&\n hoveredDate &&\n dateAdapter.isSame(date, hoveredDate, \"day\")\n ) {\n const dateRanges = (\n Array.isArray(selectedDate) ? selectedDate : [selectedDate]\n ) as DateRangeSelection[];\n const allDatesPopulated = dateRanges.every(\n (range) => range?.startDate && range?.endDate,\n );\n const startDateMatches = dateRanges.some(\n (range) =>\n range?.startDate &&\n dateAdapter.isSame(date, range.startDate, \"day\"),\n );\n const firstIncompleteRange = dateRanges.find(\n (range) => range?.startDate && !range?.endDate,\n );\n const newDateRangeRequired =\n firstIncompleteRange?.startDate &&\n dateAdapter.compare(date, firstIncompleteRange.startDate) < 0;\n return allDatesPopulated || startDateMatches || newDateRangeRequired;\n }\n if (selectionVariant === \"offset\" && hoveredDate) {\n const startDate = startDateOffset\n ? startDateOffset(hoveredDate)\n : hoveredDate;\n return (\n dateAdapter.isSame(date, startDate, \"day\") &&\n (!isDaySelectable || isDaySelectable(date))\n );\n }\n return false;\n },\n [\n dateAdapter,\n selectionVariant,\n selectedDate,\n hoveredDate,\n isDaySelectable,\n startDateOffset,\n ],\n );\n\n const getDefaultFocusedDate = () => {\n if (\n selectedDate &&\n (selectionVariant === \"range\" || selectionVariant === \"offset\")\n ) {\n const getFocusableDate = (\n result: DateFrameworkType[],\n selection: DateRangeSelection,\n ) => {\n if (selection?.startDate && isDayVisible(selection.startDate)) {\n return [...result, selection.startDate];\n }\n if (selection?.endDate && isDayVisible(selection.endDate)) {\n return [...result, selection.endDate];\n }\n return result;\n };\n let focusableSelectedDates: DateRangeSelection | DateRangeSelection[];\n if (!multiselect) {\n focusableSelectedDates = [selectedDate as DateRangeSelection];\n } else {\n focusableSelectedDates = selectedDate as DateRangeSelection[];\n }\n const selectionInMonth = focusableSelectedDates\n .reduce(getFocusableDate, [])\n .sort((a, b) => dateAdapter.compare(a, b));\n if (selectionInMonth.length > 0) {\n return selectionInMonth[0];\n }\n } else if (selectedDate && selectionVariant === \"single\") {\n const focusableSelectedDate = multiselect\n ? (selectedDate as SingleDateSelection[])?.[0]\n : (selectedDate as SingleDateSelection);\n if (focusableSelectedDate && isDayVisible(focusableSelectedDate)) {\n return focusableSelectedDate;\n }\n }\n\n // Defaults\n if (\n isDaySelectable?.(dateAdapter.today(timezone)) &&\n isDayVisible(dateAdapter.today(timezone))\n ) {\n return dateAdapter.today(timezone);\n }\n const firstSelectableDate = generateDatesForMonth(\n dateAdapter,\n visibleMonth,\n ).find((visibleDay) => visibleDay && isDaySelectable?.(visibleDay));\n if (firstSelectableDate) {\n return firstSelectableDate;\n }\n return null;\n };\n\n const [focusedDate, setFocusedDateState] = useControlled({\n controlled: focusedDateProp,\n // biome-ignore lint/correctness/useExhaustiveDependencies: initial value only\n default: useMemo(() => getDefaultFocusedDate(), []),\n name: \"Calendar\",\n state: \"focusedDate\",\n });\n\n const focusableDate = useMemo(() => {\n const dates: DateFrameworkType[] = [];\n\n if (Array.isArray(selectedDate)) {\n for (const selection of selectedDate) {\n if (isDateRangeSelection(selection)) {\n if (selection.startDate && isDayVisible(selection.startDate)) {\n dates.push(selection.startDate);\n } else if (selection.endDate && isDayVisible(selection.endDate)) {\n dates.push(selection.endDate);\n }\n } else if (isDayVisible(selection as DateFrameworkType)) {\n dates.push(selection as DateFrameworkType);\n }\n }\n } else if (selectedDate) {\n if (isDateRangeSelection(selectedDate)) {\n if (selectedDate.startDate && isDayVisible(selectedDate.startDate)) {\n dates.push(selectedDate.startDate);\n } else if (selectedDate.endDate && isDayVisible(selectedDate.endDate)) {\n dates.push(selectedDate.endDate);\n }\n } else if (isDayVisible(selectedDate)) {\n dates.push(selectedDate);\n }\n }\n\n if (\n focusedDate &&\n visibleMonth &&\n dateAdapter.isSame(focusedDate, visibleMonth, \"month\")\n ) {\n dates.push(focusedDate);\n return dates[0];\n }\n\n // Defaults\n if (\n dates.length === 0 &&\n isDaySelectable(dateAdapter.today(timezone)) &&\n isDayVisible(dateAdapter.today(timezone))\n ) {\n dates.push(dateAdapter.today(timezone));\n }\n if (dates.length === 0 || !dates.some(isDayVisible)) {\n const firstSelectableDate = generateDatesForMonth(\n dateAdapter,\n visibleMonth,\n ).find((visibleDay) => visibleDay && isDaySelectable(visibleDay));\n if (firstSelectableDate) {\n dates.push(firstSelectableDate);\n }\n }\n\n return dates.length ? dates[0] : null;\n }, [\n dateAdapter,\n focusedDate,\n isDaySelectable,\n isDayVisible,\n selectedDate,\n timezone,\n visibleMonth,\n ]);\n\n const isHoveredSpan = useCallback(\n (date: DateFrameworkType) => {\n if (selectionVariant === \"range\") {\n const dateRanges = Array.isArray(selectedDate)\n ? selectedDate\n : [selectedDate];\n return dateRanges.some((range) => {\n if (\n isDateRangeSelection(range) &&\n dateAdapter.isValid(range.startDate) &&\n !dateAdapter.isValid(range.endDate) &&\n isOutsideAllowedDates(range.startDate) === 0 &&\n hoveredDate\n ) {\n const isForwardRange =\n dateAdapter.compare(hoveredDate, range.startDate) > 0 &&\n dateAdapter.compare(date, range.startDate) > 0 &&\n dateAdapter.compare(date, hoveredDate) < 0;\n\n const isValidDayHovered =\n !isDaySelectable || isDaySelectable(hoveredDate);\n return isForwardRange && isValidDayHovered;\n }\n return false;\n });\n }\n if (selectionVariant === \"offset\" && hoveredDate) {\n const startDate = startDateOffset\n ? startDateOffset(hoveredDate)\n : hoveredDate;\n const endDate = endDateOffset\n ? endDateOffset(hoveredDate)\n : hoveredDate;\n return (\n dateAdapter.compare(date, startDate) > 0 &&\n dateAdapter.compare(date, endDate) < 0 &&\n (!isDaySelectable || isDaySelectable(date))\n );\n }\n return false;\n },\n [\n dateAdapter,\n endDateOffset,\n isOutsideAllowedDates,\n selectionVariant,\n selectedDate,\n hoveredDate,\n isDaySelectable,\n startDateOffset,\n ],\n );\n\n const isHoveredEnd = useCallback(\n (date: DateFrameworkType) => {\n if (\n selectionVariant === \"range\" &&\n hoveredDate &&\n dateAdapter.isSame(date, hoveredDate, \"day\")\n ) {\n const dateRanges = (\n Array.isArray(selectedDate) ? selectedDate : [selectedDate]\n ) as DateRangeSelection[];\n const isIncompleteRange = dateRanges.some(\n (range) =>\n range?.startDate &&\n !range?.endDate &&\n hoveredDate &&\n dateAdapter.compare(hoveredDate, range.startDate) >= 0,\n );\n const endDateMatches = dateRanges.some(\n (range) =>\n range?.endDate && dateAdapter.isSame(range.endDate, date, \"day\"),\n );\n return endDateMatches || isIncompleteRange;\n }\n if (selectionVariant === \"offset\" && hoveredDate) {\n const endDate = endDateOffset\n ? endDateOffset(hoveredDate)\n : hoveredDate;\n return (\n dateAdapter.isSame(date, endDate, \"day\") &&\n (!isDaySelectable || isDaySelectable(date))\n );\n }\n return false;\n },\n [\n dateAdapter,\n selectionVariant,\n selectedDate,\n hoveredDate,\n endDateOffset,\n isDaySelectable,\n ],\n );\n\n const defaultCreateAnnouncement =\n selectionVariant === \"single\"\n ? createSingleSelectionAnnouncement\n : createRangeSelectionAnnouncement;\n const { announce } = useDateSelectionAnnouncer(\n createAnnouncement === undefined\n ? defaultCreateAnnouncement\n : createAnnouncement,\n dateAdapter,\n );\n\n const setFocusedDate = useCallback(\n (event: SyntheticEvent | null, date: DateFrameworkType | null) => {\n if (focusedDateRef && event?.target instanceof HTMLElement) {\n focusedDateRef.current = event.target;\n }\n const exceededRangeLimit = date ? isOutsideAllowedDates(date) : 0;\n if (\n date &&\n ((focusedDate && dateAdapter.isSame(date, focusedDate, \"day\")) ||\n exceededRangeLimit !== 0)\n ) {\n if (exceededRangeLimit !== 0) {\n announce(\n exceededRangeLimit < 0\n ? \"minFocusableDateExceeded\"\n : \"maxFocusableDateExceeded\",\n );\n }\n return;\n }\n setFocusedDateState(date);\n onFocusedDateChange?.(event, date);\n },\n [\n announce,\n dateAdapter,\n focusedDate,\n focusedDateRef,\n isOutsideAllowedDates,\n onFocusedDateChange,\n ],\n );\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: isDayVisible ignored (due to dependency on visibleMonth)\n useEffect(() => {\n const shouldTransition =\n focusedDate &&\n !focusedDateProp !== undefined &&\n !isDayVisible(focusedDate) &&\n isOutsideAllowedDates(focusedDate) === 0;\n\n if (shouldTransition) {\n setVisibleMonth(null, dateAdapter.startOf(focusedDate, \"month\"));\n }\n }, [dateAdapter, focusedDateProp, isOutsideAllowedDates, focusedDate]);\n\n const setVisibleMonth = useCallback(\n (event: SyntheticEvent | null, newVisibleMonth: DateFrameworkType) => {\n setVisibleMonthState(newVisibleMonth);\n announce(\"visibleMonthChanged\", {\n startVisibleMonth: newVisibleMonth,\n endVisibleMonth: dateAdapter.add(newVisibleMonth, {\n months: responsiveNumberOfVisibleMonths - 1,\n }),\n });\n onVisibleMonthChange?.(event, newVisibleMonth);\n },\n [\n announce,\n dateAdapter,\n onVisibleMonthChange,\n responsiveNumberOfVisibleMonths,\n ],\n );\n\n return useMemo(\n () =>\n ({\n state: {\n visibleMonth,\n timezone,\n multiselect,\n minDate,\n maxDate,\n numberOfVisibleMonths: responsiveNumberOfVisibleMonths,\n selectionVariant,\n hideOutOfRangeDates,\n focusedDate,\n focusableDate,\n focusedDateRef,\n },\n helpers: {\n setVisibleMonth,\n isDayUnselectable,\n isDayHighlighted,\n isDayVisible,\n isHovered,\n isHoveredStart,\n isHoveredSpan,\n isHoveredEnd,\n isOutsideAllowedDates,\n isOutsideAllowedMonths,\n isOutsideAllowedYears,\n setFocusedDate,\n setHoveredDate,\n isDaySelectable,\n isSelected,\n isSameDay,\n setSelectedDate,\n isSelectedStart,\n isSelectedSpan,\n isSelectedEnd,\n },\n }) as UseCalendarReturn,\n [\n visibleMonth,\n timezone,\n multiselect,\n minDate,\n maxDate,\n responsiveNumberOfVisibleMonths,\n selectionVariant,\n hideOutOfRangeDates,\n focusedDate,\n focusedDateRef,\n focusableDate,\n setVisibleMonth,\n isDayUnselectable,\n isDayHighlighted,\n isDayVisible,\n isHovered,\n isHoveredStart,\n isHoveredSpan,\n isHoveredEnd,\n isOutsideAllowedDates,\n isOutsideAllowedMonths,\n isOutsideAllowedYears,\n setFocusedDate,\n setHoveredDate,\n isDaySelectable,\n isSelected,\n isSameDay,\n setSelectedDate,\n isSelectedStart,\n isSelectedSpan,\n isSelectedEnd,\n ],\n );\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,82 @@
1
+ import { useLocalization } from '../localization-provider/LocalizationProvider.js';
2
+ import { useCalendarContext } from './internal/CalendarContext.js';
3
+ import { useFocusManagement } from './internal/useFocusManagement.js';
4
+ import { useCalendarSelectionDay } from './useCalendarSelection.js';
5
+
6
+ function useCalendarDay(props) {
7
+ const { date, month } = props;
8
+ const { dateAdapter } = useLocalization();
9
+ const state = useCalendarContext();
10
+ const {
11
+ state: {
12
+ focusedDate,
13
+ focusedDateRef,
14
+ hideOutOfRangeDates,
15
+ timezone,
16
+ focusableDate
17
+ },
18
+ helpers: {
19
+ setHoveredDate,
20
+ isDayUnselectable,
21
+ isDayHighlighted,
22
+ isOutsideAllowedMonths,
23
+ isOutsideAllowedDates
24
+ }
25
+ } = state;
26
+ const selectionManager = useCalendarSelectionDay({ date });
27
+ const focusManager = useFocusManagement({ date });
28
+ const handleClick = (event) => {
29
+ selectionManager.handleClick(event);
30
+ focusManager.handleClick(event);
31
+ };
32
+ const handleKeyDown = (event) => {
33
+ focusManager.handleKeyDown(event);
34
+ selectionManager.handleKeyDown(event);
35
+ };
36
+ const handleFocus = (event) => {
37
+ focusManager.handleFocus(event);
38
+ setHoveredDate(event, date);
39
+ };
40
+ const handleMouseMove = (event) => {
41
+ setHoveredDate(event, date);
42
+ };
43
+ const eventHandlers = {
44
+ onClick: handleClick,
45
+ onKeyDown: handleKeyDown,
46
+ onFocus: handleFocus,
47
+ onMouseMove: handleMouseMove
48
+ };
49
+ const focused = focusedDate && dateAdapter.isSame(date, focusedDate, "day");
50
+ const tabIndex = focusableDate && dateAdapter.isSame(date, focusableDate, "day") ? 0 : -1;
51
+ const today = dateAdapter.isSame(dateAdapter.today(timezone), date, "day");
52
+ const unselectableReason = isDayUnselectable(date);
53
+ const highlightedReason = isDayHighlighted(date);
54
+ const outOfRange = !dateAdapter.isSame(date, month, "month");
55
+ const unselectable = Boolean(unselectableReason) || !!isOutsideAllowedMonths(date) || !!isOutsideAllowedDates(date);
56
+ const highlighted = Boolean(highlightedReason);
57
+ const hidden = hideOutOfRangeDates ? outOfRange : false;
58
+ return {
59
+ status: {
60
+ outOfRange,
61
+ today,
62
+ unselectable,
63
+ focused,
64
+ hidden,
65
+ highlighted,
66
+ ...selectionManager.status
67
+ },
68
+ dayProps: {
69
+ tabIndex,
70
+ "aria-current": today ? "date" : void 0,
71
+ "aria-hidden": hidden ? "true" : void 0,
72
+ ...eventHandlers,
73
+ ...selectionManager.dayProps
74
+ },
75
+ focusedDateRef: focused ? focusedDateRef : null,
76
+ unselectableReason,
77
+ highlightedReason
78
+ };
79
+ }
80
+
81
+ export { useCalendarDay };
82
+ //# sourceMappingURL=useCalendarDay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useCalendarDay.js","sources":["../src/calendar/useCalendarDay.ts"],"sourcesContent":["import type { DateFrameworkType } from \"@salt-ds/date-adapters\";\nimport type {\n ComponentPropsWithoutRef,\n FocusEventHandler,\n KeyboardEventHandler,\n MouseEventHandler,\n} from \"react\";\nimport { useLocalization } from \"../localization-provider\";\nimport { useCalendarContext } from \"./internal/CalendarContext\";\nimport { useFocusManagement } from \"./internal/useFocusManagement\";\nimport { useCalendarSelectionDay } from \"./useCalendarSelection\";\n\n/**\n * Interface representing the status of a day in the Calendar.\n */\nexport interface DayStatus {\n /**\n * If `true`, the day is selectable but outside of current month.\n */\n outOfRange?: boolean;\n /**\n * If `true`, the day is selected.\n */\n selected?: boolean;\n /**\n * If `true`, the day is selected.\n */\n selectedStart?: boolean;\n /**\n * If `true`, the day is selected.\n */\n selectedSpan?: boolean;\n /**\n * If `true`, the day is selected.\n */\n selectedEnd?: boolean;\n /**\n * If `true`, the day is today.\n */\n today?: boolean;\n /**\n * If set, the day is unselectable with a reason.\n */\n unselectable?: string | false;\n /**\n * If set, the day is highlighted with a reason.\n */\n highlighted?: string | false;\n /**\n * If `true`, the day is focused.\n */\n focused?: boolean;\n /**\n * If `true`, the day is hidden.\n */\n hidden?: boolean;\n}\n\n/**\n * UseCalendar hook props to return a calendar day's status\n */\nexport interface useCalendarDayProps {\n /**\n * The date of the calendar day.\n */\n date: DateFrameworkType;\n /**\n * The month of the calendar day.\n */\n month: DateFrameworkType;\n}\n\nexport function useCalendarDay(props: useCalendarDayProps) {\n const { date, month } = props;\n const { dateAdapter } = useLocalization<DateFrameworkType>();\n const state = useCalendarContext();\n const {\n state: {\n focusedDate,\n focusedDateRef,\n hideOutOfRangeDates,\n timezone,\n focusableDate,\n },\n helpers: {\n setHoveredDate,\n isDayUnselectable,\n isDayHighlighted,\n isOutsideAllowedMonths,\n isOutsideAllowedDates,\n },\n } = state;\n const selectionManager = useCalendarSelectionDay({ date });\n const focusManager = useFocusManagement({ date });\n\n const handleClick: MouseEventHandler<HTMLButtonElement> = (event) => {\n selectionManager.handleClick(event);\n focusManager.handleClick(event);\n };\n\n const handleKeyDown: KeyboardEventHandler<HTMLButtonElement> = (event) => {\n focusManager.handleKeyDown(event);\n selectionManager.handleKeyDown(event);\n };\n\n const handleFocus: FocusEventHandler<HTMLButtonElement> = (event) => {\n focusManager.handleFocus(event);\n setHoveredDate(event, date);\n };\n\n const handleMouseMove: MouseEventHandler<HTMLButtonElement> = (event) => {\n setHoveredDate(event, date);\n };\n\n const eventHandlers = {\n onClick: handleClick,\n onKeyDown: handleKeyDown,\n onFocus: handleFocus,\n onMouseMove: handleMouseMove,\n };\n\n const focused = focusedDate && dateAdapter.isSame(date, focusedDate, \"day\");\n const tabIndex =\n focusableDate && dateAdapter.isSame(date, focusableDate, \"day\") ? 0 : -1;\n const today = dateAdapter.isSame(dateAdapter.today(timezone), date, \"day\");\n\n const unselectableReason = isDayUnselectable(date);\n const highlightedReason = isDayHighlighted(date);\n\n const outOfRange = !dateAdapter.isSame(date, month, \"month\");\n const unselectable =\n Boolean(unselectableReason) ||\n !!isOutsideAllowedMonths(date) ||\n !!isOutsideAllowedDates(date);\n const highlighted = Boolean(highlightedReason);\n const hidden = hideOutOfRangeDates ? outOfRange : false;\n\n return {\n status: {\n outOfRange,\n today,\n unselectable,\n focused,\n hidden,\n highlighted,\n ...selectionManager.status,\n } as DayStatus,\n dayProps: {\n tabIndex,\n \"aria-current\": today ? \"date\" : undefined,\n \"aria-hidden\": hidden ? \"true\" : undefined,\n ...eventHandlers,\n ...selectionManager.dayProps,\n } as ComponentPropsWithoutRef<\"button\">,\n focusedDateRef: focused ? focusedDateRef : null,\n unselectableReason,\n highlightedReason,\n };\n}\n"],"names":[],"mappings":"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"}