@mezzanine-ui/react 1.0.0-beta.3 → 1.0.0-beta.5

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 (146) hide show
  1. package/AutoComplete/AutoComplete.d.ts +23 -0
  2. package/AutoComplete/AutoComplete.js +39 -9
  3. package/Breadcrumb/Breadcrumb.js +16 -21
  4. package/Breadcrumb/BreadcrumbDropdown.d.ts +11 -0
  5. package/Breadcrumb/BreadcrumbDropdown.js +22 -0
  6. package/Breadcrumb/BreadcrumbItem.d.ts +2 -3
  7. package/Breadcrumb/BreadcrumbItem.js +13 -31
  8. package/Breadcrumb/BreadcrumbOverflowMenu.d.ts +7 -0
  9. package/Breadcrumb/BreadcrumbOverflowMenu.js +77 -0
  10. package/Breadcrumb/BreadcrumbOverflowMenuDropdown.d.ts +11 -0
  11. package/Breadcrumb/BreadcrumbOverflowMenuDropdown.js +21 -0
  12. package/Breadcrumb/BreadcrumbOverflowMenuItem.d.ts +3 -0
  13. package/Breadcrumb/BreadcrumbOverflowMenuItem.js +27 -0
  14. package/Breadcrumb/typings.d.ts +21 -39
  15. package/Calendar/Calendar.js +2 -6
  16. package/Calendar/CalendarCell.d.ts +22 -0
  17. package/Calendar/CalendarCell.js +6 -2
  18. package/Calendar/CalendarControls.js +1 -1
  19. package/Calendar/CalendarDayOfWeek.js +3 -2
  20. package/Calendar/CalendarDays.js +5 -1
  21. package/Calendar/CalendarHalfYears.js +13 -7
  22. package/Calendar/CalendarMonths.js +13 -6
  23. package/Calendar/CalendarQuarters.js +13 -7
  24. package/Calendar/CalendarWeeks.js +87 -34
  25. package/Calendar/CalendarYears.js +13 -12
  26. package/Calendar/useCalendarControlModifiers.d.ts +1 -1
  27. package/Calendar/useCalendarControlModifiers.js +12 -12
  28. package/Calendar/useCalendarControls.d.ts +4 -4
  29. package/Calendar/useCalendarControls.js +33 -19
  30. package/Calendar/useRangeCalendarControls.d.ts +8 -8
  31. package/Calendar/useRangeCalendarControls.js +42 -31
  32. package/Checkbox/index.d.ts +4 -5
  33. package/Checkbox/index.js +1 -5
  34. package/ContentHeader/ContentHeader.d.ts +160 -0
  35. package/ContentHeader/ContentHeader.js +54 -0
  36. package/ContentHeader/index.d.ts +2 -0
  37. package/ContentHeader/index.js +1 -0
  38. package/ContentHeader/utils.d.ts +23 -0
  39. package/ContentHeader/utils.js +215 -0
  40. package/DateRangePicker/useDateRangeCalendarControls.js +8 -2
  41. package/Dropdown/Dropdown.d.ts +48 -0
  42. package/Dropdown/Dropdown.js +16 -2
  43. package/Dropdown/DropdownItem.d.ts +42 -0
  44. package/Dropdown/DropdownItem.js +144 -13
  45. package/Dropdown/DropdownItemCard.d.ts +7 -2
  46. package/Dropdown/DropdownItemCard.js +12 -9
  47. package/Empty/Empty.js +2 -1
  48. package/Empty/icons/EmptyMainNotificationIcon.d.ts +4 -0
  49. package/Empty/icons/EmptyMainNotificationIcon.js +9 -0
  50. package/Empty/typings.d.ts +2 -2
  51. package/FilterArea/Filter.d.ts +32 -0
  52. package/FilterArea/Filter.js +23 -0
  53. package/FilterArea/FilterArea.d.ts +58 -0
  54. package/FilterArea/FilterArea.js +31 -0
  55. package/FilterArea/FilterLine.d.ts +11 -0
  56. package/FilterArea/FilterLine.js +13 -0
  57. package/FilterArea/index.d.ts +6 -0
  58. package/FilterArea/index.js +3 -0
  59. package/Form/useSelectValueControl.d.ts +3 -4
  60. package/Form/useSelectValueControl.js +51 -39
  61. package/Input/Input.d.ts +6 -4
  62. package/Input/Input.js +28 -10
  63. package/Input/index.d.ts +1 -1
  64. package/Modal/MediaPreviewModal.d.ts +54 -0
  65. package/Modal/MediaPreviewModal.js +158 -0
  66. package/Modal/Modal.js +1 -1
  67. package/Modal/index.d.ts +2 -0
  68. package/Modal/index.js +1 -0
  69. package/Navigation/Navigation.js +6 -5
  70. package/Navigation/NavigationOption.d.ts +6 -2
  71. package/Navigation/NavigationOption.js +19 -9
  72. package/Navigation/NavigationOverflowMenu.d.ts +6 -0
  73. package/Navigation/NavigationOverflowMenu.js +90 -0
  74. package/Navigation/NavigationOverflowMenuOption.d.ts +7 -0
  75. package/Navigation/NavigationOverflowMenuOption.js +68 -0
  76. package/Navigation/NavigationUserMenu.d.ts +4 -2
  77. package/Navigation/NavigationUserMenu.js +13 -5
  78. package/Navigation/context.d.ts +3 -2
  79. package/NotificationCenter/NotificationCenter.d.ts +1 -1
  80. package/NotificationCenter/NotificationCenter.js +34 -14
  81. package/NotificationCenter/NotificationCenterDrawer.d.ts +20 -0
  82. package/PageHeader/PageHeader.d.ts +32 -25
  83. package/PageHeader/PageHeader.js +49 -35
  84. package/Popper/Popper.js +2 -1
  85. package/ResultState/ResultState.d.ts +9 -0
  86. package/ResultState/ResultState.js +36 -4
  87. package/Scrollbar/Scrollbar.d.ts +9 -0
  88. package/Scrollbar/Scrollbar.js +79 -0
  89. package/Scrollbar/index.d.ts +2 -0
  90. package/Scrollbar/index.js +1 -0
  91. package/Scrollbar/typings.d.ts +47 -0
  92. package/Select/Select.d.ts +37 -18
  93. package/Select/Select.js +165 -51
  94. package/Select/SelectTrigger.js +5 -4
  95. package/Select/index.d.ts +8 -9
  96. package/Select/index.js +3 -3
  97. package/Select/typings.d.ts +6 -1
  98. package/Selection/Selection.js +1 -1
  99. package/Selection/SelectionGroup.d.ts +28 -0
  100. package/Table/Table.d.ts +2 -120
  101. package/Table/Table.js +148 -53
  102. package/Table/TableContext.d.ts +11 -12
  103. package/Table/components/TableActionsCell.js +12 -4
  104. package/Table/components/TableBody.js +2 -1
  105. package/Table/components/TableColGroup.d.ts +1 -4
  106. package/Table/components/TableColGroup.js +15 -16
  107. package/Table/components/TableCollectableCell.d.ts +17 -0
  108. package/Table/components/TableCollectableCell.js +54 -0
  109. package/Table/components/TableDragOrPinHandleCell.d.ts +20 -0
  110. package/Table/components/TableDragOrPinHandleCell.js +58 -0
  111. package/Table/components/TableExpandedRow.js +11 -2
  112. package/Table/components/TableHeader.js +12 -10
  113. package/Table/components/TableRow.js +38 -13
  114. package/Table/components/TableSelectionCell.js +1 -1
  115. package/Table/components/TableToggleableCell.d.ts +16 -0
  116. package/Table/components/TableToggleableCell.js +51 -0
  117. package/Table/components/index.d.ts +4 -1
  118. package/Table/components/index.js +3 -0
  119. package/Table/hooks/typings.d.ts +18 -4
  120. package/Table/hooks/useTableExpansion.d.ts +2 -2
  121. package/Table/hooks/useTableExpansion.js +5 -5
  122. package/Table/hooks/useTableFixedOffsets.d.ts +6 -2
  123. package/Table/hooks/useTableFixedOffsets.js +58 -24
  124. package/Table/hooks/useTableScroll.d.ts +9 -3
  125. package/Table/hooks/useTableScroll.js +34 -7
  126. package/Table/hooks/useTableVirtualization.d.ts +2 -1
  127. package/Table/hooks/useTableVirtualization.js +2 -8
  128. package/Table/index.d.ts +4 -3
  129. package/Table/index.js +3 -0
  130. package/Table/typings.d.ts +172 -0
  131. package/Transition/Slide.d.ts +9 -2
  132. package/Transition/Slide.js +7 -4
  133. package/Tree/TreeNode.js +1 -1
  134. package/index.d.ts +4 -2
  135. package/index.js +6 -3
  136. package/package.json +6 -4
  137. package/Navigation/CollapsedMenu.d.ts +0 -6
  138. package/Navigation/CollapsedMenu.js +0 -16
  139. package/PageToolbar/PageToolbar.d.ts +0 -110
  140. package/PageToolbar/PageToolbar.js +0 -23
  141. package/PageToolbar/index.d.ts +0 -2
  142. package/PageToolbar/index.js +0 -1
  143. package/PageToolbar/utils.d.ts +0 -23
  144. package/PageToolbar/utils.js +0 -157
  145. package/Table/components/TableDragHandleCell.d.ts +0 -11
  146. package/Table/components/TableDragHandleCell.js +0 -44
@@ -1,3 +1,4 @@
1
+ import { CalendarMode } from '@mezzanine-ui/core/calendar';
1
2
  import { NativeElementPropsWithoutKeyAndRef } from '../utils/jsx-types';
2
3
  export interface CalendarCellProps extends NativeElementPropsWithoutKeyAndRef<'div'> {
3
4
  /**
@@ -8,6 +9,11 @@ export interface CalendarCellProps extends NativeElementPropsWithoutKeyAndRef<'d
8
9
  * Apply disabled styles if true.
9
10
  */
10
11
  disabled?: boolean;
12
+ /**
13
+ * Calendar mode for applying mode specific styles.
14
+ * @default 'day'
15
+ */
16
+ mode?: CalendarMode;
11
17
  /**
12
18
  * Apply today styles if true.
13
19
  */
@@ -16,6 +22,22 @@ export interface CalendarCellProps extends NativeElementPropsWithoutKeyAndRef<'d
16
22
  * The role attribute for accessibility
17
23
  */
18
24
  role?: string;
25
+ /**
26
+ * Apply range start styles if true.
27
+ */
28
+ isRangeStart?: boolean;
29
+ /**
30
+ * Apply range end styles if true.
31
+ */
32
+ isRangeEnd?: boolean;
33
+ /**
34
+ * Apply weekend styles if true.
35
+ */
36
+ isWeekend?: boolean;
37
+ /**
38
+ * Apply annotation styles if true.
39
+ */
40
+ withAnnotation?: boolean;
19
41
  }
20
42
  /**
21
43
  * The react component for `mezzanine` calendar cell.
@@ -7,11 +7,15 @@ import cx from 'clsx';
7
7
  * You may use it to compose your own calendar.
8
8
  */
9
9
  function CalendarCell(props) {
10
- const { active, children, className, disabled, today, role, ...restCalendarCellProps } = props;
11
- return (jsx("div", { role: role, className: cx(calendarClasses.cell, {
10
+ const { active, children, className, disabled, mode = 'day', today, role, isRangeStart, isRangeEnd, isWeekend, withAnnotation, ...restCalendarCellProps } = props;
11
+ return (jsx("div", { role: role, className: cx(calendarClasses.cell, calendarClasses.cellMode(mode), {
12
12
  [calendarClasses.cellToday]: today,
13
13
  [calendarClasses.cellActive]: active,
14
14
  [calendarClasses.cellDisabled]: disabled,
15
+ [calendarClasses.cellWithAnnotation]: withAnnotation,
16
+ [calendarClasses.cellWeekend]: isWeekend,
17
+ [calendarClasses.cellRangeStart]: isRangeStart,
18
+ [calendarClasses.cellRangeEnd]: isRangeEnd,
15
19
  }, className), ...restCalendarCellProps, children: jsx("span", { className: calendarClasses.cellInner, children: children }) }));
16
20
  }
17
21
 
@@ -10,7 +10,7 @@ import cx from 'clsx';
10
10
  */
11
11
  function CalendarControls(props) {
12
12
  const { children, className, disableOnNext, disableOnDoubleNext, disableOnPrev, disableOnDoublePrev, onPrev, onNext, onDoubleNext, onDoublePrev, ...restElementProps } = props;
13
- return (jsxs("div", { ...restElementProps, className: cx(calendarClasses.controls, className), children: [jsxs("div", { className: cx(calendarClasses.controlsActions), children: [onDoublePrev && (jsx("button", { type: "button", "aria-disabled": disableOnDoublePrev, disabled: disableOnDoublePrev, onClick: onDoublePrev, "aria-label": "Go to previous year", title: "Previous Year", className: cx(calendarClasses.controlsButton), children: jsx(Icon, { icon: DoubleChevronLeftIcon, "aria-hidden": "true" }) })), onPrev && (jsx("button", { type: "button", "aria-disabled": disableOnPrev, disabled: disableOnPrev, onClick: onPrev, "aria-label": "Go to previous month", title: "Previous Month", className: cx(calendarClasses.controlsButton), children: jsx(Icon, { icon: ChevronLeftIcon, "aria-hidden": "true" }) }))] }), jsx("div", { className: cx(calendarClasses.controlsMain), children: children }), jsxs("div", { className: cx(calendarClasses.controlsActions), children: [onNext && (jsx("button", { type: "button", "aria-disabled": disableOnNext, disabled: disableOnNext, onClick: onNext, "aria-label": "Go to next month", title: "Next Month", className: cx(calendarClasses.controlsButton), children: jsx(Icon, { icon: ChevronRightIcon, "aria-hidden": "true" }) })), onDoubleNext && (jsx("button", { type: "button", "aria-disabled": disableOnDoubleNext, disabled: disableOnDoubleNext, onClick: onDoubleNext, "aria-label": "Go to next year", title: "Next Year", className: cx(calendarClasses.controlsButton), children: jsx(Icon, { icon: DoubleChevronRightIcon, "aria-hidden": "true" }) }))] })] }));
13
+ return (jsxs("div", { ...restElementProps, className: cx(calendarClasses.controls, className), children: [jsxs("div", { className: cx(calendarClasses.controlsActions), children: [onDoublePrev ? (jsx("button", { type: "button", "aria-disabled": disableOnDoublePrev, disabled: disableOnDoublePrev, onClick: onDoublePrev, "aria-label": "Go to previous year", title: "Previous Year", className: cx(calendarClasses.controlsButton), children: jsx(Icon, { icon: DoubleChevronLeftIcon, "aria-hidden": "true" }) })) : null, onPrev ? (jsx("button", { type: "button", "aria-disabled": disableOnPrev, disabled: disableOnPrev, onClick: onPrev, "aria-label": "Go to previous month", title: "Previous Month", className: cx(calendarClasses.controlsButton), children: jsx(Icon, { icon: ChevronLeftIcon, "aria-hidden": "true" }) })) : null, !onPrev && !onDoublePrev ? (jsx("div", { className: calendarClasses.controlsButton, style: { pointerEvents: 'none' } })) : null] }), jsx("div", { className: cx(calendarClasses.controlsMain), children: children }), jsxs("div", { className: cx(calendarClasses.controlsActions), children: [onNext ? (jsx("button", { type: "button", "aria-disabled": disableOnNext, disabled: disableOnNext, onClick: onNext, "aria-label": "Go to next month", title: "Next Month", className: cx(calendarClasses.controlsButton), children: jsx(Icon, { icon: ChevronRightIcon, "aria-hidden": "true" }) })) : null, onDoubleNext ? (jsx("button", { type: "button", "aria-disabled": disableOnDoubleNext, disabled: disableOnDoubleNext, onClick: onDoubleNext, "aria-label": "Go to next year", title: "Next Year", className: cx(calendarClasses.controlsButton), children: jsx(Icon, { icon: DoubleChevronRightIcon, "aria-hidden": "true" }) })) : null, !onNext && !onDoubleNext ? (jsx("div", { className: calendarClasses.controlsButton, style: { pointerEvents: 'none' } })) : null] })] }));
14
14
  }
15
15
 
16
16
  export { CalendarControls as default };
@@ -10,10 +10,11 @@ import cx from 'clsx';
10
10
  * You may use it to compose your own calendar.
11
11
  */
12
12
  function CalendarDayOfWeek(props) {
13
- const { getWeekDayNames, locale } = useCalendarContext();
13
+ const { getWeekDayNames, getWeekends, locale } = useCalendarContext();
14
14
  const { displayWeekDayLocale = locale, className, ...restRowProps } = props;
15
15
  const weekDayNames = getWeekDayNames(displayWeekDayLocale);
16
- return (jsx("div", { className: cx(calendarClasses.row, className), role: "row", "aria-label": "Days of the week", ...restRowProps, children: weekDayNames.map((name, idx) => (jsx(CalendarCell, { role: "columnheader", children: name }, `CALENDAR_DAY_OF_WEEK/${name}-${idx}`))) }));
16
+ const weekends = getWeekends(displayWeekDayLocale);
17
+ return (jsx("div", { className: cx(calendarClasses.row, className), role: "row", "aria-label": "Days of the week", ...restRowProps, children: weekDayNames.map((name, idx) => (jsx(CalendarCell, { role: "columnheader", isWeekend: weekends[idx], children: name }, `CALENDAR_DAY_OF_WEEK/${name}-${idx}`))) }));
17
18
  }
18
19
 
19
20
  export { CalendarDayOfWeek as default };
@@ -33,6 +33,10 @@ function CalendarDays(props) {
33
33
  false;
34
34
  const inactive = !disabled && (isPrevMonth || isNextMonth);
35
35
  const inRange = !inactive && isDateInRange && isDateInRange(date);
36
+ const inRangeStart = inRange && value ? isSameDate(date, value[0]) : false;
37
+ const inRangeEnd = inRange && value
38
+ ? isSameDate(date, value[value.length - 1])
39
+ : false;
36
40
  const active = !disabled && !inactive && value && isDateIncluded(date, value);
37
41
  const onMouseEnter = onDateHover
38
42
  ? () => {
@@ -62,7 +66,7 @@ function CalendarDays(props) {
62
66
  ]
63
67
  .filter(Boolean)
64
68
  .join(', ');
65
- return (jsx(CalendarCell, { today: isSameDate(date, getNow()), active: active, disabled: isPrevMonth || isNextMonth, children: jsxs("button", { type: "button", "aria-disabled": disabled, disabled: disabled, "aria-label": ariaLabel, "aria-pressed": active, "aria-current": isToday ? 'date' : undefined, onMouseEnter: onMouseEnter, className: cx(calendarClasses.button, {
69
+ return (jsx(CalendarCell, { mode: "day", today: isSameDate(date, getNow()), active: active, disabled: isPrevMonth || isNextMonth, withAnnotation: Boolean(renderAnnotations), isRangeStart: inRangeStart, isRangeEnd: inRangeEnd, children: jsxs("button", { type: "button", "aria-disabled": disabled, disabled: disabled, "aria-label": ariaLabel, "aria-pressed": active, "aria-current": isToday ? 'date' : undefined, onMouseEnter: onMouseEnter, className: cx(calendarClasses.button, {
66
70
  [calendarClasses.buttonInRange]: inRange,
67
71
  [calendarClasses.buttonActive]: active,
68
72
  [calendarClasses.buttonDisabled]: disabled,
@@ -12,7 +12,7 @@ import cx from 'clsx';
12
12
  * You may use it to compose your own calendar.
13
13
  */
14
14
  function CalendarHalfYears(props) {
15
- const { getYear, getCurrentHalfYearFirstDate, isHalfYearIncluded, setYear, setMonth, } = useCalendarContext();
15
+ const { getNow, getYear, getCurrentHalfYearFirstDate, isHalfYearIncluded, setYear, setMonth, } = useCalendarContext();
16
16
  const { className, isHalfYearDisabled, isHalfYearInRange, onClick: onClickProp, onHalfYearHover, referenceDate, value, ...rest } = props;
17
17
  const currentYear = getYear(referenceDate);
18
18
  const [start] = useMemo(() => getYearRange(currentYear, calendarHalfYearYearsCount), [currentYear]);
@@ -22,7 +22,7 @@ function CalendarHalfYears(props) {
22
22
  return (jsx("div", { className: cx(calendarClasses.board, className), ...rest, children: years.map((year, yearIndex) => {
23
23
  return (jsxs("div", { className: cx(calendarClasses.row, {
24
24
  [calendarClasses.rowWithBorder]: yearIndex > 0,
25
- }), children: [jsx(CalendarCell, { disabled: true, children: year }), calendarHalfYears.map((halfYear) => {
25
+ }), children: [jsx(CalendarCell, { disabled: true, mode: "half-year", children: year }), calendarHalfYears.map((halfYear) => {
26
26
  const halfYearStartMonth = (halfYear - 1) * 6;
27
27
  const halfYearDate = setMonth(setYear(getCurrentHalfYearFirstDate(referenceDate), year), halfYearStartMonth);
28
28
  const disabled = isHalfYearDisabled && isHalfYearDisabled(halfYearDate);
@@ -30,6 +30,12 @@ function CalendarHalfYears(props) {
30
30
  isHalfYearInRange &&
31
31
  isHalfYearInRange(halfYearDate);
32
32
  const active = !disabled && value && isHalfYearIncluded(halfYearDate, value);
33
+ const isRangeStart = value && value.length > 0
34
+ ? isHalfYearIncluded(halfYearDate, [value[0]])
35
+ : false;
36
+ const isRangeEnd = value && value.length > 0
37
+ ? isHalfYearIncluded(halfYearDate, [value[value.length - 1]])
38
+ : false;
33
39
  const onClick = () => {
34
40
  if (disabled)
35
41
  return;
@@ -50,11 +56,11 @@ function CalendarHalfYears(props) {
50
56
  ]
51
57
  .filter(Boolean)
52
58
  .join(', ');
53
- return (jsxs("button", { type: "button", disabled: disabled, "aria-disabled": disabled, "aria-label": ariaLabel, "aria-pressed": active, className: cx(calendarClasses.button, {
54
- [calendarClasses.buttonDisabled]: disabled,
55
- [calendarClasses.buttonInRange]: inRange,
56
- [calendarClasses.buttonActive]: active,
57
- }), onClick: onClick, onMouseEnter: onMouseEnter, children: ["H", halfYear] }, halfYear));
59
+ return (jsx(CalendarCell, { mode: "half-year", today: isHalfYearIncluded(halfYearDate, [getNow()]), active: active, isRangeStart: isRangeStart, isRangeEnd: isRangeEnd, children: jsxs("button", { type: "button", disabled: disabled, "aria-disabled": disabled, "aria-label": ariaLabel, "aria-pressed": active, className: cx(calendarClasses.button, {
60
+ [calendarClasses.buttonDisabled]: disabled,
61
+ [calendarClasses.buttonInRange]: inRange,
62
+ [calendarClasses.buttonActive]: active,
63
+ }), onClick: onClick, onMouseEnter: onMouseEnter, children: ["H", halfYear] }) }, halfYear));
58
64
  })] }, year));
59
65
  }) }));
60
66
  }
@@ -2,6 +2,7 @@
2
2
  import { jsx } from 'react/jsx-runtime';
3
3
  import { calendarMonths, calendarClasses } from '@mezzanine-ui/core/calendar';
4
4
  import { useCalendarContext } from './CalendarContext.js';
5
+ import CalendarCell from './CalendarCell.js';
5
6
  import cx from 'clsx';
6
7
 
7
8
  /**
@@ -10,7 +11,7 @@ import cx from 'clsx';
10
11
  * You may use it to compose your own calendar.
11
12
  */
12
13
  function CalendarMonths(props) {
13
- const { locale, getMonthShortNames, isMonthIncluded, getCurrentMonthFirstDate, setMonth, } = useCalendarContext();
14
+ const { locale, getNow, getMonth, getMonthShortNames, isInMonth, isMonthIncluded, getCurrentMonthFirstDate, setMonth, } = useCalendarContext();
14
15
  const { className, displayMonthLocale = locale, isMonthDisabled, isMonthInRange, isYearDisabled, onClick: onClickProp, onMonthHover, referenceDate, value, ...rest } = props;
15
16
  const monthNames = getMonthShortNames(displayMonthLocale);
16
17
  return (jsx("div", { className: cx(calendarClasses.board, className), ...rest, children: jsx("div", { className: calendarClasses.twelveGrid, children: calendarMonths.map((month) => {
@@ -21,6 +22,12 @@ function CalendarMonths(props) {
21
22
  (isMonthDisabled === null || isMonthDisabled === void 0 ? void 0 : isMonthDisabled(monthDateType)) ||
22
23
  false;
23
24
  const inRange = isMonthInRange && isMonthInRange(monthDateType);
25
+ const isRangeStart = value && value.length > 0
26
+ ? isMonthIncluded(monthDateType, [value[0]])
27
+ : false;
28
+ const isRangeEnd = value && value.length > 0
29
+ ? isMonthIncluded(monthDateType, [value[value.length - 1]])
30
+ : false;
24
31
  const onClick = onClickProp
25
32
  ? () => {
26
33
  onClickProp(monthDateType);
@@ -42,11 +49,11 @@ function CalendarMonths(props) {
42
49
  ]
43
50
  .filter(Boolean)
44
51
  .join(', ');
45
- return (jsx("button", { type: "button", "aria-disabled": disabled, disabled: disabled, "aria-label": ariaLabel, "aria-pressed": active, className: cx(calendarClasses.button, {
46
- [calendarClasses.buttonActive]: active,
47
- [calendarClasses.buttonInRange]: inRange,
48
- [calendarClasses.buttonDisabled]: disabled,
49
- }), onClick: onClick, onMouseEnter: onMouseEnter, children: monthNames[month] }, month));
52
+ return (jsx(CalendarCell, { mode: "month", today: isInMonth(monthDateType, getMonth(getNow())), active: active, isRangeStart: isRangeStart, isRangeEnd: isRangeEnd, children: jsx("button", { type: "button", "aria-disabled": disabled, disabled: disabled, "aria-label": ariaLabel, "aria-pressed": active, className: cx(calendarClasses.button, {
53
+ [calendarClasses.buttonActive]: active,
54
+ [calendarClasses.buttonInRange]: inRange,
55
+ [calendarClasses.buttonDisabled]: disabled,
56
+ }), onClick: onClick, onMouseEnter: onMouseEnter, children: monthNames[month] }) }, month));
50
57
  }) }) }));
51
58
  }
52
59
 
@@ -10,7 +10,7 @@ import cx from 'clsx';
10
10
  * The react component for `mezzanine` calendar quarters.
11
11
  */
12
12
  function CalendarQuarters(props) {
13
- const { getYear, getCurrentQuarterFirstDate, isQuarterIncluded, setYear, setMonth, } = useCalendarContext();
13
+ const { getNow, getYear, getCurrentQuarterFirstDate, isQuarterIncluded, setYear, setMonth, } = useCalendarContext();
14
14
  const { className, isQuarterDisabled, isQuarterInRange, onClick: onClickProp, onQuarterHover, referenceDate, value, ...rest } = props;
15
15
  const currentYear = getYear(referenceDate);
16
16
  const [start] = useMemo(() => getYearRange(currentYear, calendarQuarterYearsCount), [currentYear]);
@@ -20,12 +20,18 @@ function CalendarQuarters(props) {
20
20
  return (jsx("div", { className: cx(calendarClasses.board, className), ...rest, children: years.map((year, yearIndex) => {
21
21
  return (jsxs("div", { className: cx(calendarClasses.row, {
22
22
  [calendarClasses.rowWithBorder]: yearIndex > 0,
23
- }), children: [jsx(CalendarCell, { disabled: true, children: year }), calendarQuarters.map((quarter) => {
23
+ }), children: [jsx(CalendarCell, { disabled: true, mode: "quarter", children: year }), calendarQuarters.map((quarter) => {
24
24
  const quarterStartMonth = (quarter - 1) * 3;
25
25
  const quarterDate = setMonth(setYear(getCurrentQuarterFirstDate(getCurrentQuarterFirstDate(referenceDate)), year), quarterStartMonth);
26
26
  const active = value && isQuarterIncluded(quarterDate, value);
27
27
  const disabled = isQuarterDisabled && isQuarterDisabled(quarterDate);
28
28
  const inRange = isQuarterInRange && isQuarterInRange(quarterDate);
29
+ const isRangeStart = value && value.length > 0
30
+ ? isQuarterIncluded(quarterDate, [value[0]])
31
+ : false;
32
+ const isRangeEnd = value && value.length > 0
33
+ ? isQuarterIncluded(quarterDate, [value[value.length - 1]])
34
+ : false;
29
35
  const onClick = onClickProp
30
36
  ? () => {
31
37
  onClickProp(quarterDate);
@@ -52,11 +58,11 @@ function CalendarQuarters(props) {
52
58
  ]
53
59
  .filter(Boolean)
54
60
  .join(', ');
55
- return (jsxs("button", { type: "button", disabled: disabled, "aria-disabled": disabled, "aria-label": ariaLabel, "aria-pressed": active, className: cx(calendarClasses.button, {
56
- [calendarClasses.buttonActive]: active,
57
- [calendarClasses.buttonInRange]: inRange,
58
- [calendarClasses.buttonDisabled]: disabled,
59
- }), onClick: onClick, onMouseEnter: onMouseEnter, children: ["Q", quarter] }, quarter));
61
+ return (jsx(CalendarCell, { mode: "quarter", today: isQuarterIncluded(quarterDate, [getNow()]), active: active, isRangeStart: isRangeStart, isRangeEnd: isRangeEnd, children: jsxs("button", { type: "button", disabled: disabled, "aria-disabled": disabled, "aria-label": ariaLabel, "aria-pressed": active, className: cx(calendarClasses.button, {
62
+ [calendarClasses.buttonActive]: active,
63
+ [calendarClasses.buttonInRange]: inRange,
64
+ [calendarClasses.buttonDisabled]: disabled,
65
+ }), onClick: onClick, onMouseEnter: onMouseEnter, children: ["Q", quarter] }) }, quarter));
60
66
  })] }, year));
61
67
  }) }));
62
68
  }
@@ -16,19 +16,32 @@ function CalendarWeeks(props) {
16
16
  const { locale, getCalendarGrid, getWeek, getDate, getMonth, getNow, isInMonth, isSameDate, isWeekIncluded, setDate, setMonth, setHour, setMinute, setSecond, setMillisecond, getCurrentWeekFirstDate, } = useCalendarContext();
17
17
  const { className, displayWeekDayLocale = locale, isYearDisabled, isMonthDisabled, isWeekDisabled, isWeekInRange, onClick: onClickProp, onWeekHover, referenceDate, value, ...rest } = props;
18
18
  const daysGrid = useMemo(() => getCalendarGrid(referenceDate, displayWeekDayLocale), [getCalendarGrid, referenceDate, displayWeekDayLocale]);
19
- const weekFirstDates = useMemo(() => {
19
+ // Pre-calculate all weeks data including dates and week first dates
20
+ const weeksData = useMemo(() => {
21
+ const thisMonth = getMonth(referenceDate);
20
22
  return daysGrid.map((week, index) => {
21
- const dateNum = week[0];
22
- const isPrevMonth = index === 0 && dateNum > 7;
23
- const isNextMonth = index > 3 && dateNum <= 14;
24
- const thisMonth = getMonth(referenceDate);
25
- const month = isPrevMonth
26
- ? thisMonth - 1
27
- : isNextMonth
28
- ? thisMonth + 1
29
- : thisMonth;
30
- const weekFirstDate = setDate(setMonth(referenceDate, month), dateNum);
31
- return getCurrentWeekFirstDate(weekFirstDate, displayWeekDayLocale);
23
+ const dates = [];
24
+ const weekStartInPrevMonth = index === 0 && week[0] > 7;
25
+ const weekStartInNextMonth = index > 3 && week[0] <= 14;
26
+ week.forEach((dateNum) => {
27
+ const isPrevMonth = index === 0 && dateNum > 7;
28
+ const isNextMonth = index > 3 && dateNum <= 14;
29
+ const month = isPrevMonth
30
+ ? thisMonth - 1
31
+ : isNextMonth
32
+ ? thisMonth + 1
33
+ : thisMonth;
34
+ const date = setMillisecond(setSecond(setMinute(setHour(setDate(setMonth(referenceDate, month), dateNum), 0), 0), 0), 0);
35
+ dates.push(date);
36
+ });
37
+ const weekFirstDate = getCurrentWeekFirstDate(dates[0], displayWeekDayLocale);
38
+ return {
39
+ week,
40
+ dates,
41
+ weekStartInPrevMonth,
42
+ weekStartInNextMonth,
43
+ weekFirstDate,
44
+ };
32
45
  });
33
46
  }, [
34
47
  daysGrid,
@@ -36,35 +49,52 @@ function CalendarWeeks(props) {
36
49
  referenceDate,
37
50
  setDate,
38
51
  setMonth,
52
+ setHour,
53
+ setMinute,
54
+ setSecond,
55
+ setMillisecond,
39
56
  getCurrentWeekFirstDate,
40
57
  displayWeekDayLocale,
41
58
  ]);
42
- return (jsxs("div", { ...rest, className: cx(calendarClasses.board, className), children: [jsx("div", { className: calendarClasses.week, children: weekFirstDates.map((firstDate, idx) => (jsx("div", { className: calendarClasses.weekRow, children: jsx(CalendarCell, { disabled: true, children: getWeek(firstDate, displayWeekDayLocale) }) }, idx))) }), jsxs("div", { className: calendarClasses.daysGrid, children: [jsx(CalendarDayOfWeek, { displayWeekDayLocale: displayWeekDayLocale }), daysGrid.map((week, index) => {
43
- const dates = [];
44
- const weekStartInPrevMonth = index === 0 && week[0] > 7;
45
- const weekStartInNextMonth = index > 3 && week[0] <= 14;
46
- week.forEach((dateNum) => {
47
- const isPrevMonth = index === 0 && dateNum > 7;
48
- const isNextMonth = index > 3 && dateNum <= 14;
49
- const thisMonth = getMonth(referenceDate);
50
- const month = isPrevMonth
51
- ? thisMonth - 1
52
- : isNextMonth
53
- ? thisMonth + 1
54
- : thisMonth;
55
- const date = setMillisecond(setSecond(setMinute(setHour(setDate(setMonth(referenceDate, month), dateNum), 0), 0), 0), 0);
56
- dates.push(date);
57
- });
59
+ // Pre-calculate last week dates for range end comparison
60
+ const lastWeekDatesMap = useMemo(() => {
61
+ if (!value || value.length === 0)
62
+ return null;
63
+ const rangeLastDate = value.length === 1
64
+ ? setDate(value[0], getDate(value[0]) + 6)
65
+ : value[value.length - 1];
66
+ const lastWeekFirstDate = getCurrentWeekFirstDate(rangeLastDate, displayWeekDayLocale);
67
+ const lastWeekDates = [];
68
+ for (let i = 0; i < 7; i++) {
69
+ lastWeekDates.push(setDate(setMonth(lastWeekFirstDate, getMonth(lastWeekFirstDate)), getDate(lastWeekFirstDate) + i));
70
+ }
71
+ return {
72
+ rangeLastDate,
73
+ lastWeekDates,
74
+ };
75
+ }, [
76
+ value,
77
+ setDate,
78
+ setMonth,
79
+ getDate,
80
+ getMonth,
81
+ getCurrentWeekFirstDate,
82
+ displayWeekDayLocale,
83
+ ]);
84
+ return (jsxs("div", { ...rest, className: cx(calendarClasses.board, className), children: [jsx("div", { className: calendarClasses.week, children: weeksData.map(({ weekFirstDate }, idx) => (jsx("div", { className: calendarClasses.weekRow, children: jsx(CalendarCell, { disabled: true, children: getWeek(weekFirstDate, displayWeekDayLocale) }) }, idx))) }), jsxs("div", { className: calendarClasses.daysGrid, children: [jsx(CalendarDayOfWeek, { displayWeekDayLocale: displayWeekDayLocale }), weeksData.map(({ week, dates, weekStartInPrevMonth, weekStartInNextMonth }, index) => {
85
+ var _a;
58
86
  const disabled = (isYearDisabled === null || isYearDisabled === void 0 ? void 0 : isYearDisabled(dates[0])) ||
59
87
  (isMonthDisabled === null || isMonthDisabled === void 0 ? void 0 : isMonthDisabled(dates[0])) ||
60
88
  (isWeekDisabled === null || isWeekDisabled === void 0 ? void 0 : isWeekDisabled(dates[0])) ||
61
89
  false;
62
90
  const inactive = !disabled && (weekStartInPrevMonth || weekStartInNextMonth);
63
- const active = !disabled &&
91
+ const weekIncluded = !disabled &&
64
92
  !inactive &&
65
93
  value &&
66
94
  isWeekIncluded(dates[0], value, displayWeekDayLocale);
67
- const inRange = !disabled && !inactive && isWeekInRange && isWeekInRange(dates[0]);
95
+ const rangeFirstDate = value && value.length > 0 ? value[0] : null;
96
+ const rangeLastDate = (_a = lastWeekDatesMap === null || lastWeekDatesMap === void 0 ? void 0 : lastWeekDatesMap.rangeLastDate) !== null && _a !== void 0 ? _a : null;
97
+ const inRange = !disabled && isWeekInRange && isWeekInRange(dates[0]);
68
98
  const onMouseEnter = onWeekHover
69
99
  ? () => {
70
100
  onWeekHover(getCurrentWeekFirstDate(dates[0], displayWeekDayLocale));
@@ -88,18 +118,41 @@ function CalendarWeeks(props) {
88
118
  const ariaLabel = [
89
119
  `Week ${weekNum}`,
90
120
  `${startMonth} ${startDay} to ${endMonth} ${endDay}`,
91
- active && 'Selected',
121
+ weekIncluded && 'Selected',
92
122
  disabled && 'Not available',
93
123
  inactive && 'Outside current month',
94
124
  ]
95
125
  .filter(Boolean)
96
126
  .join(', ');
97
127
  return (jsx("button", { type: "button", className: cx(calendarClasses.button, calendarClasses.row, {
98
- [calendarClasses.buttonActive]: active,
99
128
  [calendarClasses.buttonInRange]: inRange,
100
129
  [calendarClasses.buttonDisabled]: disabled,
101
- }), disabled: disabled, "aria-disabled": disabled, "aria-label": ariaLabel, "aria-pressed": active, onClick: onClick, onMouseEnter: onMouseEnter, children: week.map((dateNum, dateIndex) => (jsx(CalendarCell, { today: isSameDate(dates[dateIndex], getNow()), disabled: disabled ||
102
- !isInMonth(dates[dateIndex], getMonth(referenceDate)), active: active, children: dateNum }, `${getMonth(dates[dateIndex])}/${getDate(dates[dateIndex])}`))) }, `CALENDAR_WEEKS/WEEK_OF/${index}`));
130
+ }), disabled: disabled, "aria-disabled": disabled, "aria-label": ariaLabel, "aria-pressed": weekIncluded, onClick: onClick, onMouseEnter: onMouseEnter, children: week.map((dateNum, dateIndex) => {
131
+ let cellActive = false;
132
+ let isFirstWeekFirstDate = false;
133
+ let isLastWeekLastDate = false;
134
+ if (weekIncluded &&
135
+ rangeFirstDate &&
136
+ rangeLastDate &&
137
+ lastWeekDatesMap) {
138
+ const currentDate = dates[dateIndex];
139
+ isFirstWeekFirstDate =
140
+ isWeekIncluded(currentDate, [rangeFirstDate], displayWeekDayLocale) && isSameDate(currentDate, rangeFirstDate);
141
+ isLastWeekLastDate =
142
+ isWeekIncluded(currentDate, [rangeLastDate], displayWeekDayLocale) &&
143
+ isSameDate(currentDate, lastWeekDatesMap.lastWeekDates[6]);
144
+ cellActive = isFirstWeekFirstDate || isLastWeekLastDate;
145
+ }
146
+ return (jsx(CalendarCell, { mode: "week", today: isSameDate(dates[dateIndex], getNow()), disabled: disabled ||
147
+ !isInMonth(dates[dateIndex], getMonth(referenceDate)), active: cellActive, isRangeStart: isFirstWeekFirstDate, isRangeEnd: isLastWeekLastDate, children: jsx("div", { className: cx(calendarClasses.button, {
148
+ [calendarClasses.buttonInRange]: weekIncluded,
149
+ [calendarClasses.buttonActive]: cellActive,
150
+ }), style: {
151
+ width: '100%',
152
+ height: '100%',
153
+ pointerEvents: 'none',
154
+ }, children: dateNum }) }, `${getMonth(dates[dateIndex])}/${getDate(dates[dateIndex])}`));
155
+ }) }, `CALENDAR_WEEKS/WEEK_OF/${index}`));
103
156
  })] })] }));
104
157
  }
105
158
 
@@ -2,6 +2,7 @@
2
2
  import { jsx } from 'react/jsx-runtime';
3
3
  import { getCalendarYearRange, calendarYearsBase, calendarClasses } from '@mezzanine-ui/core/calendar';
4
4
  import { useMemo } from 'react';
5
+ import CalendarCell from './CalendarCell.js';
5
6
  import { useCalendarContext } from './CalendarContext.js';
6
7
  import cx from 'clsx';
7
8
 
@@ -18,12 +19,14 @@ function CalendarYears(props) {
18
19
  const thisYear = base + start;
19
20
  const yearDateType = setYear(getCurrentYearFirstDate(getNow()), thisYear);
20
21
  const disabled = isYearDisabled && isYearDisabled(yearDateType);
21
- const inactive = !disabled && (base === 0 || base === 11);
22
- const active = !disabled &&
23
- !inactive &&
24
- value &&
25
- isYearIncluded(yearDateType, value);
22
+ const active = !disabled && value && isYearIncluded(yearDateType, value);
26
23
  const inRange = isYearInRange && isYearInRange(yearDateType);
24
+ const isRangeStart = value && value.length > 0
25
+ ? isYearIncluded(yearDateType, [value[0]])
26
+ : false;
27
+ const isRangeEnd = value && value.length > 0
28
+ ? isYearIncluded(yearDateType, [value[value.length - 1]])
29
+ : false;
27
30
  const onClick = onClickProp
28
31
  ? () => {
29
32
  onClickProp(yearDateType);
@@ -39,16 +42,14 @@ function CalendarYears(props) {
39
42
  `Year ${thisYear}`,
40
43
  active && 'Selected',
41
44
  disabled && 'Not available',
42
- inactive && 'Outside range',
43
45
  ]
44
46
  .filter(Boolean)
45
47
  .join(', ');
46
- return (jsx("button", { type: "button", "aria-disabled": disabled, disabled: disabled, "aria-label": ariaLabel, "aria-pressed": active, className: cx(calendarClasses.button, {
47
- [calendarClasses.buttonActive]: active,
48
- [calendarClasses.buttonInRange]: inRange,
49
- [calendarClasses.buttonDisabled]: disabled,
50
- [calendarClasses.buttonInactive]: inactive,
51
- }), onClick: onClick, onMouseEnter: onMouseEnter, children: thisYear }, base + start));
48
+ return (jsx(CalendarCell, { mode: "year", today: getYear(getNow()) === thisYear, active: active, isRangeStart: isRangeStart, isRangeEnd: isRangeEnd, children: jsx("button", { type: "button", "aria-disabled": disabled, disabled: disabled, "aria-label": ariaLabel, "aria-pressed": active, className: cx(calendarClasses.button, {
49
+ [calendarClasses.buttonActive]: active,
50
+ [calendarClasses.buttonInRange]: inRange,
51
+ [calendarClasses.buttonDisabled]: disabled,
52
+ }), onClick: onClick, onMouseEnter: onMouseEnter, children: thisYear }) }, base + start));
52
53
  }) }) }));
53
54
  }
54
55
 
@@ -2,6 +2,6 @@ import { CalendarMode, DateType } from '@mezzanine-ui/core/calendar';
2
2
  export type CalendarControlModifier = (value: DateType) => DateType;
3
3
  export type UseCalendarControlModifiersResult = Record<CalendarMode, {
4
4
  single: [CalendarControlModifier, CalendarControlModifier] | null;
5
- double: [CalendarControlModifier, CalendarControlModifier];
5
+ double: [CalendarControlModifier, CalendarControlModifier] | null;
6
6
  }>;
7
7
  export declare function useCalendarControlModifiers(): UseCalendarControlModifiersResult;
@@ -15,34 +15,34 @@ function useCalendarControlModifiers() {
15
15
  single: [(date) => addMonth(date, -1), (date) => addMonth(date, 1)],
16
16
  double: [(date) => addYear(date, -1), (date) => addYear(date, 1)],
17
17
  },
18
- // month mode: only double (year)
18
+ // month mode: only single
19
19
  month: {
20
- single: null,
21
- double: [(date) => addYear(date, -1), (date) => addYear(date, 1)],
20
+ single: [(date) => addYear(date, -1), (date) => addYear(date, 1)],
21
+ double: null,
22
22
  },
23
- // year mode: only double (10 years)
23
+ // year mode: only single
24
24
  year: {
25
- single: null,
26
- double: [
25
+ single: [
27
26
  (date) => addYear(date, -calendarYearModuler),
28
27
  (date) => addYear(date, calendarYearModuler),
29
28
  ],
29
+ double: null,
30
30
  },
31
- // quarter mode: only double (5 years)
31
+ // quarter mode: only single
32
32
  quarter: {
33
- single: null,
34
- double: [
33
+ single: [
35
34
  (date) => addYear(date, -calendarQuarterYearsCount),
36
35
  (date) => addYear(date, calendarQuarterYearsCount),
37
36
  ],
37
+ double: null,
38
38
  },
39
- // half-year mode: only double (5 years)
39
+ // half-year mode: only single
40
40
  'half-year': {
41
- single: null,
42
- double: [
41
+ single: [
43
42
  (date) => addYear(date, -calendarHalfYearYearsCount),
44
43
  (date) => addYear(date, calendarHalfYearYearsCount),
45
44
  ],
45
+ double: null,
46
46
  },
47
47
  }), [addYear, addMonth]);
48
48
  }
@@ -2,10 +2,10 @@ import { DateType, CalendarMode } from '@mezzanine-ui/core/calendar';
2
2
  export declare function useCalendarControls(referenceDateProp: DateType, mode?: CalendarMode): {
3
3
  currentMode: CalendarMode;
4
4
  onMonthControlClick: () => void;
5
- onNext: () => void;
6
- onPrev: () => void;
7
- onDoubleNext: () => void;
8
- onDoublePrev: () => void;
5
+ onNext: (() => void) | undefined;
6
+ onPrev: (() => void) | undefined;
7
+ onDoubleNext: (() => void) | undefined;
8
+ onDoublePrev: (() => void) | undefined;
9
9
  onYearControlClick: () => void;
10
10
  popModeStack: () => void;
11
11
  referenceDate: string;
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- import { useState, useEffect } from 'react';
2
+ import { useState, useEffect, useMemo, useCallback } from 'react';
3
3
  import { useCalendarControlModifiers } from './useCalendarControlModifiers.js';
4
4
  import { useCalendarModeStack } from './useCalendarModeStack.js';
5
5
 
@@ -10,30 +10,44 @@ function useCalendarControls(referenceDateProp, mode) {
10
10
  }, [referenceDateProp]);
11
11
  const { currentMode, pushModeStack, popModeStack } = useCalendarModeStack(mode || 'day');
12
12
  const modifierGroup = useCalendarControlModifiers();
13
- const onPrev = () => {
13
+ const onPrev = useMemo(() => {
14
14
  const modifiers = modifierGroup[currentMode].single;
15
15
  if (!modifiers)
16
16
  return;
17
- const [handleMinus] = modifiers;
18
- setReferenceDate(handleMinus(referenceDate));
19
- };
20
- const onNext = () => {
17
+ return () => {
18
+ const [handleMinus] = modifiers;
19
+ setReferenceDate(handleMinus(referenceDate));
20
+ };
21
+ }, [currentMode, modifierGroup, referenceDate]);
22
+ const onNext = useMemo(() => {
21
23
  const modifiers = modifierGroup[currentMode].single;
22
24
  if (!modifiers)
23
25
  return;
24
- const [, handleAdd] = modifiers;
25
- setReferenceDate(handleAdd(referenceDate));
26
- };
27
- const onDoublePrev = () => {
28
- const [handleMinus] = modifierGroup[currentMode].double;
29
- setReferenceDate(handleMinus(referenceDate));
30
- };
31
- const onDoubleNext = () => {
32
- const [, handleAdd] = modifierGroup[currentMode].double;
33
- setReferenceDate(handleAdd(referenceDate));
34
- };
35
- const onMonthControlClick = () => pushModeStack('month');
36
- const onYearControlClick = () => pushModeStack('year');
26
+ return () => {
27
+ const [, handleAdd] = modifiers;
28
+ setReferenceDate(handleAdd(referenceDate));
29
+ };
30
+ }, [currentMode, modifierGroup, referenceDate]);
31
+ const onDoublePrev = useMemo(() => {
32
+ const modifiers = modifierGroup[currentMode].double;
33
+ if (!modifiers)
34
+ return;
35
+ return () => {
36
+ const [handleMinus] = modifiers;
37
+ setReferenceDate(handleMinus(referenceDate));
38
+ };
39
+ }, [currentMode, modifierGroup, referenceDate]);
40
+ const onDoubleNext = useMemo(() => {
41
+ const modifiers = modifierGroup[currentMode].double;
42
+ if (!modifiers)
43
+ return;
44
+ return () => {
45
+ const [, handleAdd] = modifiers;
46
+ setReferenceDate(handleAdd(referenceDate));
47
+ };
48
+ }, [currentMode, modifierGroup, referenceDate]);
49
+ const onMonthControlClick = useCallback(() => pushModeStack('month'), [pushModeStack]);
50
+ const onYearControlClick = useCallback(() => pushModeStack('year'), [pushModeStack]);
37
51
  return {
38
52
  currentMode,
39
53
  onMonthControlClick,