@mezzanine-ui/react 1.0.0-beta.4 → 1.0.0-beta.6

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 (103) hide show
  1. package/AutoComplete/AutoComplete.d.ts +5 -0
  2. package/AutoComplete/AutoComplete.js +19 -2
  3. package/Breadcrumb/BreadcrumbDropdown.js +1 -1
  4. package/Breadcrumb/BreadcrumbItem.js +1 -1
  5. package/Breadcrumb/BreadcrumbOverflowMenuItem.js +1 -1
  6. package/Calendar/Calendar.js +2 -6
  7. package/Calendar/CalendarCell.d.ts +22 -0
  8. package/Calendar/CalendarCell.js +6 -2
  9. package/Calendar/CalendarControls.js +1 -1
  10. package/Calendar/CalendarDayOfWeek.js +3 -2
  11. package/Calendar/CalendarDays.js +5 -1
  12. package/Calendar/CalendarHalfYears.js +13 -7
  13. package/Calendar/CalendarMonths.js +13 -6
  14. package/Calendar/CalendarQuarters.js +13 -7
  15. package/Calendar/CalendarWeeks.js +87 -34
  16. package/Calendar/CalendarYears.js +13 -12
  17. package/Calendar/useCalendarControlModifiers.d.ts +1 -1
  18. package/Calendar/useCalendarControlModifiers.js +12 -12
  19. package/Calendar/useCalendarControls.d.ts +4 -4
  20. package/Calendar/useCalendarControls.js +33 -19
  21. package/Calendar/useRangeCalendarControls.d.ts +8 -8
  22. package/Calendar/useRangeCalendarControls.js +42 -31
  23. package/DateRangePicker/useDateRangeCalendarControls.js +8 -2
  24. package/DateTimePicker/DateTimePicker.js +8 -4
  25. package/DateTimeRangePicker/DateTimeRangePicker.d.ts +34 -0
  26. package/DateTimeRangePicker/DateTimeRangePicker.js +118 -0
  27. package/DateTimeRangePicker/index.d.ts +2 -0
  28. package/DateTimeRangePicker/index.js +1 -0
  29. package/Drawer/Drawer.d.ts +132 -1
  30. package/Drawer/Drawer.js +47 -3
  31. package/Dropdown/Dropdown.d.ts +34 -3
  32. package/Dropdown/Dropdown.js +17 -29
  33. package/Dropdown/DropdownItem.d.ts +32 -0
  34. package/Dropdown/DropdownItem.js +112 -10
  35. package/Dropdown/DropdownItemCard.d.ts +5 -0
  36. package/Dropdown/DropdownItemCard.js +2 -2
  37. package/Form/FormField.d.ts +14 -2
  38. package/Form/FormField.js +3 -3
  39. package/Form/useSelectValueControl.d.ts +3 -4
  40. package/Form/useSelectValueControl.js +51 -39
  41. package/Input/Input.js +3 -19
  42. package/Input/SelectButton/SelectButton.d.ts +25 -4
  43. package/Input/SelectButton/SelectButton.js +21 -9
  44. package/Modal/MediaPreviewModal.d.ts +11 -0
  45. package/Modal/MediaPreviewModal.js +24 -7
  46. package/Modal/Modal.d.ts +1 -1
  47. package/Modal/Modal.js +1 -1
  48. package/Modal/useModalContainer.js +6 -2
  49. package/MultipleDatePicker/MultipleDatePicker.d.ts +62 -0
  50. package/MultipleDatePicker/MultipleDatePicker.js +176 -0
  51. package/MultipleDatePicker/MultipleDatePickerTrigger.d.ts +56 -0
  52. package/MultipleDatePicker/MultipleDatePickerTrigger.js +92 -0
  53. package/MultipleDatePicker/index.d.ts +6 -0
  54. package/MultipleDatePicker/index.js +3 -0
  55. package/MultipleDatePicker/useMultipleDatePickerValue.d.ts +55 -0
  56. package/MultipleDatePicker/useMultipleDatePickerValue.js +68 -0
  57. package/NotificationCenter/NotificationCenterDrawer.d.ts +10 -52
  58. package/NotificationCenter/NotificationCenterDrawer.js +128 -0
  59. package/NotificationCenter/index.d.ts +2 -0
  60. package/NotificationCenter/index.js +1 -0
  61. package/OverflowTooltip/index.d.ts +2 -2
  62. package/Picker/RangePickerTrigger.js +1 -1
  63. package/Popper/Popper.js +2 -1
  64. package/Scrollbar/Scrollbar.js +1 -0
  65. package/Section/Section.d.ts +32 -0
  66. package/Section/Section.js +62 -0
  67. package/Section/index.d.ts +2 -0
  68. package/Select/Select.d.ts +42 -18
  69. package/Select/Select.js +165 -51
  70. package/Select/TreeSelect.d.ts +10 -5
  71. package/Select/TreeSelect.js +12 -5
  72. package/Select/index.d.ts +8 -9
  73. package/Select/index.js +3 -3
  74. package/TimePanel/TimePanelColumn.js +16 -14
  75. package/TimeRangePicker/TimeRangePicker.d.ts +29 -0
  76. package/TimeRangePicker/TimeRangePicker.js +96 -0
  77. package/TimeRangePicker/index.d.ts +3 -0
  78. package/TimeRangePicker/index.js +2 -0
  79. package/TimeRangePicker/useTimeRangePickerValue.d.ts +30 -0
  80. package/TimeRangePicker/useTimeRangePickerValue.js +92 -0
  81. package/Transition/Rotate.js +2 -5
  82. package/Tree/TreeNode.js +2 -2
  83. package/index.d.ts +9 -6
  84. package/index.js +7 -6
  85. package/package.json +4 -4
  86. package/AppBar/AppBar.d.ts +0 -14
  87. package/AppBar/AppBar.js +0 -33
  88. package/AppBar/AppBarBrand.d.ts +0 -4
  89. package/AppBar/AppBarBrand.js +0 -11
  90. package/AppBar/AppBarMain.d.ts +0 -4
  91. package/AppBar/AppBarMain.js +0 -11
  92. package/AppBar/AppBarSupport.d.ts +0 -4
  93. package/AppBar/AppBarSupport.js +0 -11
  94. package/AppBar/index.d.ts +0 -8
  95. package/AppBar/index.js +0 -4
  96. package/Popconfirm/Popconfirm.d.ts +0 -16
  97. package/Popconfirm/Popconfirm.js +0 -15
  98. package/Popconfirm/index.d.ts +0 -2
  99. package/Popconfirm/index.js +0 -1
  100. package/Popover/Popover.d.ts +0 -23
  101. package/Popover/Popover.js +0 -35
  102. package/Popover/index.d.ts +0 -2
  103. package/Popover/index.js +0 -1
@@ -148,6 +148,11 @@ export interface AutoCompleteBaseProps extends Omit<SelectTriggerProps, 'active'
148
148
  * The z-index of the dropdown.
149
149
  */
150
150
  dropdownZIndex?: number | string;
151
+ /**
152
+ * Whether to enable portal for the dropdown.
153
+ * @default true
154
+ */
155
+ globalPortal?: boolean;
151
156
  /**
152
157
  * Callback fired when the dropdown list reaches the bottom.
153
158
  * Only fires when `menuMaxHeight` is set and the list is scrollable.
@@ -46,7 +46,7 @@ function isOptionSelected(option, value, isMultiple) {
46
46
  */
47
47
  const AutoComplete = forwardRef(function AutoComplete(props, ref) {
48
48
  const { disabled: disabledFromFormControl, fullWidth: fullWidthFromFormControl, required: requiredFromFormControl, severity, } = useContext(FormControlContext) || {};
49
- const { addable = false, asyncData = false, className, createSeparators = [',', '+', '\n'], defaultValue, disabled = disabledFromFormControl || false, disabledOptionsFilter = false, emptyText, error = severity === 'error' || false, fullWidth = fullWidthFromFormControl || false, id, keepSearchTextOnBlur = false, inputPosition = 'outside', inputProps, inputRef, loading = false, loadingText, menuMaxHeight, mode = 'single', name, onClear: onClearProp, onChange: onChangeProp, onInsert, onSearch, onSearchTextChange, onVisibilityChange, open: openProp, options: optionsProp, placeholder = '', prefix, required = requiredFromFormControl || false, searchDebounceTime = 300, searchTextControlRef, size, trimOnCreate = true, value: valueProp, createActionText, createActionTextTemplate = '建立 "{text}"', dropdownZIndex, onReachBottom, onLeaveBottom, } = props;
49
+ const { addable = false, asyncData = false, className, createSeparators = [',', '+', '\n'], defaultValue, disabled = disabledFromFormControl || false, disabledOptionsFilter = false, emptyText, error = severity === 'error' || false, fullWidth = fullWidthFromFormControl || false, id, keepSearchTextOnBlur = false, inputPosition = 'outside', inputProps, inputRef, loading = false, loadingText, menuMaxHeight, mode = 'single', name, onClear: onClearProp, onChange: onChangeProp, onInsert, onSearch, onSearchTextChange, onVisibilityChange, open: openProp, options: optionsProp, placeholder = '', prefix, required = requiredFromFormControl || false, searchDebounceTime = 300, searchTextControlRef, size, trimOnCreate = true, value: valueProp, createActionText, createActionTextTemplate = '建立 "{text}"', dropdownZIndex, globalPortal = true, onReachBottom, onLeaveBottom, } = props;
50
50
  const [uncontrolledOpen, setUncontrolledOpen] = useState(false);
51
51
  const isMultiple = mode === 'multiple';
52
52
  const isSingle = !isMultiple;
@@ -203,17 +203,33 @@ const AutoComplete = forwardRef(function AutoComplete(props, ref) {
203
203
  // Don't let Dropdown's onBlur close the dropdown when controlled
204
204
  // Only call onFocus(false) to update internal state
205
205
  onFocus(false);
206
+ // Clear search text and insert text when blur if keepSearchTextOnBlur is false
207
+ if (!keepSearchTextOnBlur) {
208
+ resetCreationInputs();
209
+ }
206
210
  (_a = inputProps === null || inputProps === void 0 ? void 0 : inputProps.onBlur) === null || _a === void 0 ? void 0 : _a.call(inputProps, e);
207
211
  return;
208
212
  }
209
213
  // For uncontrolled mode, let Dropdown handle it normally
210
214
  // Dropdown's inlineTriggerElement will handle the blur and close logic
215
+ // Clear search text and insert text when blur if keepSearchTextOnBlur is false
216
+ if (!keepSearchTextOnBlur) {
217
+ resetCreationInputs();
218
+ }
211
219
  (_b = inputProps === null || inputProps === void 0 ? void 0 : inputProps.onBlur) === null || _b === void 0 ? void 0 : _b.call(inputProps, e);
212
220
  return;
213
221
  }
214
222
  onFocus(false);
223
+ // Clear search text and insert text when blur if keepSearchTextOnBlur is false
224
+ if (!keepSearchTextOnBlur) {
225
+ resetCreationInputs();
226
+ }
215
227
  (_c = inputProps === null || inputProps === void 0 ? void 0 : inputProps.onBlur) === null || _c === void 0 ? void 0 : _c.call(inputProps, e);
216
228
  };
229
+ const handleClear = useCallback((e) => {
230
+ onClear(e);
231
+ resetCreationInputs();
232
+ }, [onClear, resetCreationInputs]);
217
233
  const onClickSuffixActionIcon = () => {
218
234
  toggleOpen((prev) => !prev);
219
235
  };
@@ -408,13 +424,14 @@ const AutoComplete = forwardRef(function AutoComplete(props, ref) {
408
424
  return (jsx(SelectControlContext.Provider, { value: context, children: jsx("div", { ref: nodeRef, className: cx(autocompleteClasses.host, {
409
425
  [autocompleteClasses.hostFullWidth]: fullWidth,
410
426
  [autocompleteClasses.hostInsideClosed]: inputPosition === 'inside' && !open,
427
+ [autocompleteClasses.hostMode(mode)]: mode,
411
428
  }), children: jsx(Dropdown, { actionText: shouldShowCreateAction
412
429
  ? (createActionText
413
430
  ? createActionText(insertText)
414
431
  : createActionTextTemplate.replace('{text}', insertText))
415
432
  : undefined, activeIndex: activeIndex, disabled: isInputDisabled, emptyText: emptyText, followText: searchText, inputPosition: inputPosition, isMatchInputValue: true, listboxId: menuId, loadingText: loadingText, maxHeight: menuMaxHeight, mode: mode, onActionCustom: shouldShowCreateAction
416
433
  ? handleActionCustom
417
- : undefined, onItemHover: setActiveIndex, onSelect: handleDropdownSelect, onVisibilityChange: handleVisibilityChange, open: open, options: dropdownOptionsForRender, placement: "bottom", sameWidth: true, showDropdownActions: shouldShowCreateAction, showActionShowTopBar: shouldShowCreateAction, status: dropdownStatus, type: "default", value: dropdownValue, zIndex: dropdownZIndex, onReachBottom: onReachBottom, onLeaveBottom: onLeaveBottom, children: jsx(SelectTrigger, { ref: composedRef, active: open, className: className, clearable: true, isForceClearable: true, disabled: isInputDisabled, fullWidth: fullWidth, inputRef: inputRef, mode: mode, onTagClose: wrappedOnChange, onClear: onClear, placeholder: getPlaceholder(), prefix: prefix, readOnly: false, required: required, type: error ? 'error' : 'default', inputProps: {
434
+ : undefined, onItemHover: setActiveIndex, onSelect: handleDropdownSelect, onVisibilityChange: handleVisibilityChange, open: open, options: dropdownOptionsForRender, placement: "bottom", sameWidth: true, showDropdownActions: shouldShowCreateAction, showActionShowTopBar: shouldShowCreateAction, status: dropdownStatus, type: "default", value: dropdownValue, zIndex: dropdownZIndex, globalPortal: globalPortal, onReachBottom: onReachBottom, onLeaveBottom: onLeaveBottom, children: jsx(SelectTrigger, { ref: composedRef, active: open, className: className, clearable: true, isForceClearable: true, disabled: isInputDisabled, fullWidth: fullWidth, inputRef: inputRef, mode: mode, onTagClose: wrappedOnChange, onClear: handleClear, placeholder: getPlaceholder(), prefix: prefix, readOnly: false, required: required, type: error ? 'error' : 'default', inputProps: {
418
435
  ...resolvedInputProps,
419
436
  onClick: (e) => {
420
437
  var _a;
@@ -16,7 +16,7 @@ const BreadcrumbDropdown = forwardRef(function BreadcrumbDropdown(props, ref) {
16
16
  setOpen(!open);
17
17
  onClick === null || onClick === void 0 ? void 0 : onClick();
18
18
  };
19
- return (jsx("span", { className: cx(breadcrumbItemClasses.host, className), ref: ref, children: jsx(Dropdown, { onClose: () => setOpen(false), onOpen: () => handleClick(), options: options, placement: "bottom-start", ...rest, children: jsxs("button", { className: cx(breadcrumbItemClasses.trigger, open && breadcrumbItemClasses.expanded, current && breadcrumbItemClasses.current), type: "button", children: [name && (jsx(Typography, { variant: current ? 'caption-highlight' : 'caption', children: name })), jsx(Rotate, { in: open, children: jsx(Icon, { className: breadcrumbItemClasses.icon, icon: ChevronDownIcon, size: 14 }) })] }) }) }));
19
+ return (jsx("span", { className: cx(breadcrumbItemClasses.host, open && breadcrumbItemClasses.expanded, current && breadcrumbItemClasses.current, className), ref: ref, children: jsx(Dropdown, { onClose: () => setOpen(false), onOpen: () => handleClick(), options: options, placement: "bottom-start", ...rest, children: jsxs("button", { className: breadcrumbItemClasses.trigger, type: "button", children: [name && (jsx(Typography, { variant: current ? 'caption-highlight' : 'caption', children: name })), jsx(Rotate, { in: open, children: jsx(Icon, { className: breadcrumbItemClasses.icon, icon: ChevronDownIcon, size: 14 }) })] }) }) }));
20
20
  });
21
21
 
22
22
  export { BreadcrumbDropdown as default };
@@ -21,7 +21,7 @@ const BreadcrumbItem = forwardRef(function BreadcrumbItem(props, ref) {
21
21
  const handleClick = () => {
22
22
  onClick === null || onClick === void 0 ? void 0 : onClick();
23
23
  };
24
- return (jsx("span", { ...rest, className: cx(breadcrumbItemClasses.host, className), ref: ref, children: jsx(TriggerComponent, { className: cx(breadcrumbItemClasses.trigger, current && breadcrumbItemClasses.current), href: TriggerComponent === 'a' ? href : undefined, onClick: TriggerComponent === 'a' ? handleClick : undefined, rel: TriggerComponent === 'a' ? rel : undefined, target: TriggerComponent === 'a' ? target : undefined, children: name && (jsx(Typography, { variant: current ? 'caption-highlight' : 'caption', children: name })) }) }));
24
+ return (jsx("span", { ...rest, className: cx(breadcrumbItemClasses.host, current && breadcrumbItemClasses.current, className), ref: ref, children: jsx(TriggerComponent, { className: breadcrumbItemClasses.trigger, href: TriggerComponent === 'a' ? href : undefined, onClick: TriggerComponent === 'a' ? handleClick : undefined, rel: TriggerComponent === 'a' ? rel : undefined, target: TriggerComponent === 'a' ? target : undefined, children: name && (jsx(Typography, { variant: current ? 'caption-highlight' : 'caption', children: name })) }) }));
25
25
  });
26
26
 
27
27
  export { BreadcrumbItem as default };
@@ -21,7 +21,7 @@ const BreadcrumbOverflowMenuItem = forwardRef(function BreadcrumbOverflowMenuIte
21
21
  const handleClick = () => {
22
22
  onClick === null || onClick === void 0 ? void 0 : onClick();
23
23
  };
24
- return (jsx("span", { ...rest, className: cx(breadcrumbOverflowMenuItemClasses.host, className), ref: ref, children: jsx(TriggerComponent, { className: cx(breadcrumbOverflowMenuItemClasses.trigger), href: TriggerComponent === 'a' ? href : undefined, onClick: TriggerComponent === 'a' ? handleClick : undefined, rel: TriggerComponent === 'a' ? rel : undefined, target: TriggerComponent === 'a' ? target : undefined, children: jsx(Typography, { variant: 'label-primary', children: name }) }) }));
24
+ return (jsx("span", { ...rest, className: cx(breadcrumbOverflowMenuItemClasses.host, className), ref: ref, children: jsx(TriggerComponent, { className: breadcrumbOverflowMenuItemClasses.trigger, href: TriggerComponent === 'a' ? href : undefined, onClick: TriggerComponent === 'a' ? handleClick : undefined, rel: TriggerComponent === 'a' ? rel : undefined, target: TriggerComponent === 'a' ? target : undefined, children: jsx(Typography, { variant: 'label-primary', children: name }) }) }));
25
25
  });
26
26
 
27
27
  export { BreadcrumbOverflowMenuItem as default };
@@ -93,9 +93,7 @@ const Calendar = forwardRef(function Calendar(props, ref) {
93
93
  ? () => {
94
94
  onDoubleNext(mode);
95
95
  }
96
- : undefined, onNext:
97
- // Only day and week modes have single next/prev (for month navigation)
98
- onNext && (mode === 'day' || mode === 'week')
96
+ : undefined, onNext: onNext
99
97
  ? () => {
100
98
  onNext(mode);
101
99
  }
@@ -103,9 +101,7 @@ const Calendar = forwardRef(function Calendar(props, ref) {
103
101
  ? () => {
104
102
  onDoublePrev(mode);
105
103
  }
106
- : undefined, onPrev:
107
- // Only day and week modes have single next/prev (for month navigation)
108
- onPrev && (mode === 'day' || mode === 'week')
104
+ : undefined, onPrev: onPrev
109
105
  ? () => {
110
106
  onPrev(mode);
111
107
  }
@@ -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;