@codecademy/gamut 68.1.2 → 68.1.3-alpha.bcf87d.0

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 (44) hide show
  1. package/dist/ConnectedForm/utils.d.ts +1 -1
  2. package/dist/DatePicker/Calendar/Calendar.d.ts +11 -0
  3. package/dist/DatePicker/Calendar/Calendar.js +15 -0
  4. package/dist/DatePicker/Calendar/CalendarBody.d.ts +3 -0
  5. package/dist/DatePicker/Calendar/CalendarBody.js +155 -0
  6. package/dist/DatePicker/Calendar/CalendarFooter.d.ts +3 -0
  7. package/dist/DatePicker/Calendar/CalendarFooter.js +60 -0
  8. package/dist/DatePicker/Calendar/CalendarHeader.d.ts +3 -0
  9. package/dist/DatePicker/Calendar/CalendarHeader.js +63 -0
  10. package/dist/DatePicker/Calendar/index.d.ts +6 -0
  11. package/dist/DatePicker/Calendar/index.js +5 -0
  12. package/dist/DatePicker/Calendar/types.d.ts +59 -0
  13. package/dist/DatePicker/Calendar/types.js +1 -0
  14. package/dist/DatePicker/Calendar/utils/dateGrid.d.ts +30 -0
  15. package/dist/DatePicker/Calendar/utils/dateGrid.js +93 -0
  16. package/dist/DatePicker/Calendar/utils/format.d.ts +39 -0
  17. package/dist/DatePicker/Calendar/utils/format.js +130 -0
  18. package/dist/DatePicker/Calendar/utils/index.d.ts +3 -0
  19. package/dist/DatePicker/Calendar/utils/index.js +3 -0
  20. package/dist/DatePicker/Calendar/utils/keyHandler.d.ts +13 -0
  21. package/dist/DatePicker/Calendar/utils/keyHandler.js +116 -0
  22. package/dist/DatePicker/Calendar/utils/validation.d.ts +13 -0
  23. package/dist/DatePicker/Calendar/utils/validation.js +23 -0
  24. package/dist/DatePicker/DatePicker.d.ts +8 -0
  25. package/dist/DatePicker/DatePicker.js +127 -0
  26. package/dist/DatePicker/DatePickerCalendar.d.ts +13 -0
  27. package/dist/DatePicker/DatePickerCalendar.js +127 -0
  28. package/dist/DatePicker/DatePickerContext.d.ts +11 -0
  29. package/dist/DatePicker/DatePickerContext.js +18 -0
  30. package/dist/DatePicker/DatePickerInput.d.ts +16 -0
  31. package/dist/DatePicker/DatePickerInput.js +126 -0
  32. package/dist/DatePicker/index.d.ts +13 -0
  33. package/dist/DatePicker/index.js +10 -0
  34. package/dist/DatePicker/types.d.ts +76 -0
  35. package/dist/DatePicker/types.js +1 -0
  36. package/dist/DatePicker/utils.d.ts +3 -0
  37. package/dist/DatePicker/utils.js +71 -0
  38. package/dist/FocusTrap/index.d.ts +2 -2
  39. package/dist/List/elements.d.ts +1 -1
  40. package/dist/PopoverContainer/PopoverContainer.js +3 -1
  41. package/dist/PopoverContainer/types.d.ts +5 -0
  42. package/dist/index.d.ts +1 -0
  43. package/dist/index.js +1 -0
  44. package/package.json +2 -2
@@ -122,9 +122,9 @@ export declare function useDebouncedField<T extends InputTypes>({ name, watchUpd
122
122
  value: T extends "checkbox" ? boolean : string;
123
123
  error: string | FieldError | Merge<FieldError, FieldErrorsImpl<any>> | undefined;
124
124
  ref: import("react-hook-form").UseFormRegisterReturn<string>;
125
- control: import("react-hook-form").Control<import("react-hook-form").FieldValues, any, import("react-hook-form").FieldValues>;
126
125
  isDisabled: boolean;
127
126
  isLoading: boolean | undefined;
127
+ control: import("react-hook-form").Control<import("react-hook-form").FieldValues, any, import("react-hook-form").FieldValues>;
128
128
  isSoloField: boolean | undefined;
129
129
  validation: RegisterOptions | undefined;
130
130
  getValues: import("react-hook-form").UseFormGetValues<import("react-hook-form").FieldValues>;
@@ -0,0 +1,11 @@
1
+ /// <reference types="react" />
2
+ /**
3
+ * Outer wrapper for the calendar (header + body + footer).
4
+ * Used by DatePickerCalendar to group the calendar content.
5
+ */
6
+ export declare const Calendar: import("@emotion/styled").StyledComponent<{
7
+ theme?: import("@emotion/react").Theme | undefined;
8
+ as?: import("react").ElementType<any, keyof import("react").JSX.IntrinsicElements> | undefined;
9
+ } & {
10
+ theme?: import("@emotion/react").Theme | undefined;
11
+ }, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {}>;
@@ -0,0 +1,15 @@
1
+ import _styled from "@emotion/styled/base";
2
+ import { css } from '@codecademy/gamut-styles';
3
+ /**
4
+ * Outer wrapper for the calendar (header + body + footer).
5
+ * Used by DatePickerCalendar to group the calendar content.
6
+ */
7
+ export const Calendar = /*#__PURE__*/_styled("div", {
8
+ target: "eq0g1i20",
9
+ label: "Calendar"
10
+ })(css({
11
+ backgroundColor: 'background',
12
+ borderRadius: 'lg',
13
+ boxShadow: '0 4px 16px rgba(0, 0, 0, 0.12)',
14
+ width: 'max-content'
15
+ }), process.env.NODE_ENV === "production" ? "" : "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9EYXRlUGlja2VyL0NhbGVuZGFyL0NhbGVuZGFyLnRzeCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFPd0IiLCJmaWxlIjoiLi4vLi4vLi4vc3JjL0RhdGVQaWNrZXIvQ2FsZW5kYXIvQ2FsZW5kYXIudHN4Iiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgY3NzIH0gZnJvbSAnQGNvZGVjYWRlbXkvZ2FtdXQtc3R5bGVzJztcbmltcG9ydCBzdHlsZWQgZnJvbSAnQGVtb3Rpb24vc3R5bGVkJztcblxuLyoqXG4gKiBPdXRlciB3cmFwcGVyIGZvciB0aGUgY2FsZW5kYXIgKGhlYWRlciArIGJvZHkgKyBmb290ZXIpLlxuICogVXNlZCBieSBEYXRlUGlja2VyQ2FsZW5kYXIgdG8gZ3JvdXAgdGhlIGNhbGVuZGFyIGNvbnRlbnQuXG4gKi9cbmV4cG9ydCBjb25zdCBDYWxlbmRhciA9IHN0eWxlZC5kaXYoXG4gIGNzcyh7XG4gICAgYmFja2dyb3VuZENvbG9yOiAnYmFja2dyb3VuZCcsXG4gICAgYm9yZGVyUmFkaXVzOiAnbGcnLFxuICAgIGJveFNoYWRvdzogJzAgNHB4IDE2cHggcmdiYSgwLCAwLCAwLCAwLjEyKScsXG4gICAgd2lkdGg6ICdtYXgtY29udGVudCcsXG4gIH0pXG4pO1xuIl19 */");
@@ -0,0 +1,3 @@
1
+ import * as React from 'react';
2
+ import { CalendarBodyProps } from './types';
3
+ export declare const CalendarBody: React.FC<CalendarBodyProps>;
@@ -0,0 +1,155 @@
1
+ import _styled from "@emotion/styled/base";
2
+ import { css, states } from '@codecademy/gamut-styles';
3
+ import { useCallback, useEffect, useMemo, useRef } from 'react';
4
+ import * as React from 'react';
5
+ import { TextButton } from '../../Button';
6
+ import { getMonthGrid, isDateDisabled, isDateInRange, isSameDay } from './utils/dateGrid';
7
+ import { getWeekdayFullNames, getWeekdayLabels } from './utils/format';
8
+ import { getDatesWithRow, keyHandler } from './utils/keyHandler';
9
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
10
+ const TableHeader = /*#__PURE__*/_styled("th", {
11
+ target: "e12sl4cx1",
12
+ label: "TableHeader"
13
+ })(css({
14
+ fontSize: 14,
15
+ fontWeight: 'base',
16
+ color: 'text-disabled',
17
+ textAlign: 'center'
18
+ }), process.env.NODE_ENV === "production" ? "" : "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9EYXRlUGlja2VyL0NhbGVuZGFyL0NhbGVuZGFyQm9keS50c3giXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBZ0JvQiIsImZpbGUiOiIuLi8uLi8uLi9zcmMvRGF0ZVBpY2tlci9DYWxlbmRhci9DYWxlbmRhckJvZHkudHN4Iiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgY3NzLCBzdGF0ZXMgfSBmcm9tICdAY29kZWNhZGVteS9nYW11dC1zdHlsZXMnO1xuaW1wb3J0IHN0eWxlZCBmcm9tICdAZW1vdGlvbi9zdHlsZWQnO1xuaW1wb3J0IHsgdXNlQ2FsbGJhY2ssIHVzZUVmZmVjdCwgdXNlTWVtbywgdXNlUmVmIH0gZnJvbSAncmVhY3QnO1xuaW1wb3J0ICogYXMgUmVhY3QgZnJvbSAncmVhY3QnO1xuXG5pbXBvcnQgeyBUZXh0QnV0dG9uIH0gZnJvbSAnLi4vLi4vQnV0dG9uJztcbmltcG9ydCB7IENhbGVuZGFyQm9keVByb3BzIH0gZnJvbSAnLi90eXBlcyc7XG5pbXBvcnQge1xuICBnZXRNb250aEdyaWQsXG4gIGlzRGF0ZURpc2FibGVkLFxuICBpc0RhdGVJblJhbmdlLFxuICBpc1NhbWVEYXksXG59IGZyb20gJy4vdXRpbHMvZGF0ZUdyaWQnO1xuaW1wb3J0IHsgZ2V0V2Vla2RheUZ1bGxOYW1lcywgZ2V0V2Vla2RheUxhYmVscyB9IGZyb20gJy4vdXRpbHMvZm9ybWF0JztcbmltcG9ydCB7IGdldERhdGVzV2l0aFJvdywga2V5SGFuZGxlciB9IGZyb20gJy4vdXRpbHMva2V5SGFuZGxlcic7XG5cbmNvbnN0IFRhYmxlSGVhZGVyID0gc3R5bGVkLnRoKFxuICBjc3Moe1xuICAgIGZvbnRTaXplOiAxNCxcbiAgICBmb250V2VpZ2h0OiAnYmFzZScsXG4gICAgY29sb3I6ICd0ZXh0LWRpc2FibGVkJyxcbiAgICB0ZXh0QWxpZ246ICdjZW50ZXInLFxuICB9KVxuKTtcblxuY29uc3QgRGF0ZUJ1dHRvbiA9IHN0eWxlZChUZXh0QnV0dG9uKShcbiAgc3RhdGVzKHtcbiAgICBpc1RvZGF5OiB7XG4gICAgICBwb3NpdGlvbjogJ3JlbGF0aXZlJyxcbiAgICAgICcmOjphZnRlcic6IHtcbiAgICAgICAgY29udGVudDogJ1wiXCInLFxuICAgICAgICBwb3NpdGlvbjogJ2Fic29sdXRlJyxcbiAgICAgICAgYm90dG9tOiA0LFxuICAgICAgICBsZWZ0OiAnNTAlJyxcbiAgICAgICAgd2lkdGg6IDQsXG4gICAgICAgIGhlaWdodDogNCxcbiAgICAgICAgYm9yZGVyUmFkaXVzOiAnZnVsbCcsXG4gICAgICAgIGJnOiAnaHlwZXInLFxuICAgICAgfSxcbiAgICB9LFxuICAgIGlzU2VsZWN0ZWQ6IHtcbiAgICAgIGJnOiAndGV4dCcsXG4gICAgICBjb2xvcjogJ2JhY2tncm91bmQnLFxuICAgICAgJyY6aG92ZXIsICY6Zm9jdXMnOiB7XG4gICAgICAgIGJnOiAnc2Vjb25kYXJ5LWhvdmVyJyxcbiAgICAgICAgY29sb3I6ICdiYWNrZ3JvdW5kJyxcbiAgICAgIH0sXG4gICAgICAnJjo6YWZ0ZXInOiB7XG4gICAgICAgIGJnOiAnYmFja2dyb3VuZCcsXG4gICAgICB9LFxuICAgIH0sXG4gICAgaXNJblJhbmdlOiB7XG4gICAgICBiZzogJ3RleHQtZGlzYWJsZWQnLFxuICAgICAgY29sb3I6ICdiYWNrZ3JvdW5kJyxcbiAgICAgIGJvcmRlclJhZGl1czogJ25vbmUnLFxuICAgICAgJyY6aG92ZXIsICY6Zm9jdXMnOiB7XG4gICAgICAgIGJnOiAnc2Vjb25kYXJ5LWhvdmVyJyxcbiAgICAgICAgY29sb3I6ICdiYWNrZ3JvdW5kJyxcbiAgICAgIH0sXG4gICAgICAnJjo6YWZ0ZXInOiB7XG4gICAgICAgIGJnOiAnYmFja2dyb3VuZCcsXG4gICAgICB9LFxuICAgIH0sXG4gICAgZGlzYWJsZWQ6IHtcbiAgICAgIGNvbG9yOiAndGV4dC1kaXNhYmxlZCcsXG4gICAgICB0ZXh0RGVjb3JhdGlvbjogJ2xpbmUtdGhyb3VnaCcsXG4gICAgfSxcbiAgfSksXG4gIGNzcyh7XG4gICAgZm9udFdlaWdodDogJ2Jhc2UnLFxuICAgIHdpZHRoOiAnMzJweCcsXG4gIH0pXG4pO1xuXG5leHBvcnQgY29uc3QgQ2FsZW5kYXJCb2R5OiBSZWFjdC5GQzxDYWxlbmRhckJvZHlQcm9wcz4gPSAoe1xuICB2aXNpYmxlRGF0ZSxcbiAgc2VsZWN0ZWREYXRlLFxuICBlbmREYXRlID0gbnVsbCxcbiAgZGlzYWJsZWREYXRlcyA9IFtdLFxuICBvbkRhdGVTZWxlY3QsXG4gIGxvY2FsZSxcbiAgd2Vla1N0YXJ0c09uID0gMCxcbiAgbGFiZWxsZWRCeUlkLFxuICBmb2N1c2VkRGF0ZSxcbiAgb25Gb2N1c2VkRGF0ZUNoYW5nZSxcbiAgb25WaXNpYmxlRGF0ZUNoYW5nZSxcbiAgb25Fc2NhcGVLZXlQcmVzcyxcbn0pID0+IHtcbiAgY29uc3QgeWVhciA9IHZpc2libGVEYXRlLmdldEZ1bGxZZWFyKCk7XG4gIGNvbnN0IG1vbnRoID0gdmlzaWJsZURhdGUuZ2V0TW9udGgoKTtcbiAgY29uc3Qgd2Vla3MgPSBnZXRNb250aEdyaWQoeWVhciwgbW9udGgsIHdlZWtTdGFydHNPbik7XG4gIGNvbnN0IHdlZWtkYXlMYWJlbHMgPSBnZXRXZWVrZGF5TGFiZWxzKGxvY2FsZSwgd2Vla1N0YXJ0c09uKTtcbiAgY29uc3Qgd2Vla2RheUZ1bGxOYW1lcyA9IGdldFdlZWtkYXlGdWxsTmFtZXMobG9jYWxlLCB3ZWVrU3RhcnRzT24pO1xuICBjb25zdCBidXR0b25SZWZzID0gdXNlUmVmPE1hcDxudW1iZXIsIEhUTUxFbGVtZW50Pj4obmV3IE1hcCgpKTtcblxuICBjb25zdCBkYXRlc1dpdGhSb3cgPSB1c2VNZW1vKCgpID0+IGdldERhdGVzV2l0aFJvdyh3ZWVrcyksIFt3ZWVrc10pO1xuICBjb25zdCBmb2N1c1RhcmdldCA9IGZvY3VzZWREYXRlID8/IHNlbGVjdGVkRGF0ZTtcblxuICBjb25zdCBpc1RvZGF5ID0gdXNlQ2FsbGJhY2soXG4gICAgKGQ6IERhdGUgfCBudWxsKSA9PiBkICE9PSBudWxsICYmIGlzU2FtZURheShkLCBuZXcgRGF0ZSgpKSxcbiAgICBbXVxuICApO1xuXG4gIGNvbnN0IGZvY3VzQnV0dG9uID0gdXNlQ2FsbGJhY2soKGRhdGU6IERhdGUgfCBudWxsKSA9PiB7XG4gICAgaWYgKGRhdGUgPT09IG51bGwpIHJldHVybjtcbiAgICBjb25zdCBrZXkgPSBuZXcgRGF0ZShcbiAgICAgIGRhdGUuZ2V0RnVsbFllYXIoKSxcbiAgICAgIGRhdGUuZ2V0TW9udGgoKSxcbiAgICAgIGRhdGUuZ2V0RGF0ZSgpXG4gICAgKS5nZXRUaW1lKCk7XG4gICAgYnV0dG9uUmVmcy5jdXJyZW50LmdldChrZXkpPy5mb2N1cygpO1xuICB9LCBbXSk7XG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBpZiAoZm9jdXNUYXJnZXQgIT09IG51bGwpIGZvY3VzQnV0dG9uKGZvY3VzVGFyZ2V0KTtcbiAgfSwgW2ZvY3VzVGFyZ2V0LCBmb2N1c0J1dHRvbl0pO1xuXG4gIGNvbnN0IGhhbmRsZUtleURvd24gPSB1c2VDYWxsYmFjayhcbiAgICAoZTogUmVhY3QuS2V5Ym9hcmRFdmVudCwgZGF0ZTogRGF0ZSkgPT5cbiAgICAgIGtleUhhbmRsZXIoXG4gICAgICAgIGUsXG4gICAgICAgIGRhdGUsXG4gICAgICAgIG9uRm9jdXNlZERhdGVDaGFuZ2UsXG4gICAgICAgIGRhdGVzV2l0aFJvdyxcbiAgICAgICAgbW9udGgsXG4gICAgICAgIHllYXIsXG4gICAgICAgIGRpc2FibGVkRGF0ZXMsXG4gICAgICAgIG9uRGF0ZVNlbGVjdCxcbiAgICAgICAgb25Fc2NhcGVLZXlQcmVzcyxcbiAgICAgICAgb25WaXNpYmxlRGF0ZUNoYW5nZVxuICAgICAgKSxcbiAgICBbXG4gICAgICBvbkZvY3VzZWREYXRlQ2hhbmdlLFxuICAgICAgZGF0ZXNXaXRoUm93LFxuICAgICAgbW9udGgsXG4gICAgICB5ZWFyLFxuICAgICAgZGlzYWJsZWREYXRlcyxcbiAgICAgIG9uRGF0ZVNlbGVjdCxcbiAgICAgIG9uRXNjYXBlS2V5UHJlc3MsXG4gICAgICBvblZpc2libGVEYXRlQ2hhbmdlLFxuICAgIF1cbiAgKTtcblxuICBjb25zdCBzZXRCdXR0b25SZWYgPSB1c2VDYWxsYmFjaygoZGF0ZTogRGF0ZSwgZWw6IEhUTUxFbGVtZW50IHwgbnVsbCkgPT4ge1xuICAgIGNvbnN0IGsgPSBuZXcgRGF0ZShcbiAgICAgIGRhdGUuZ2V0RnVsbFllYXIoKSxcbiAgICAgIGRhdGUuZ2V0TW9udGgoKSxcbiAgICAgIGRhdGUuZ2V0RGF0ZSgpXG4gICAgKS5nZXRUaW1lKCk7XG4gICAgaWYgKGVsKSBidXR0b25SZWZzLmN1cnJlbnQuc2V0KGssIGVsKTtcbiAgICBlbHNlIGJ1dHRvblJlZnMuY3VycmVudC5kZWxldGUoayk7XG4gIH0sIFtdKTtcblxuICByZXR1cm4gKFxuICAgIDx0YWJsZSBhcmlhLWxhYmVsbGVkYnk9e2xhYmVsbGVkQnlJZH0gcm9sZT1cImdyaWRcIiB3aWR0aD1cIjEwMCVcIj5cbiAgICAgIDx0aGVhZD5cbiAgICAgICAgPHRyPlxuICAgICAgICAgIHt3ZWVrZGF5TGFiZWxzLm1hcCgobGFiZWwsIGkpID0+IChcbiAgICAgICAgICAgIDxUYWJsZUhlYWRlciBhYmJyPXt3ZWVrZGF5RnVsbE5hbWVzW2ldfSBrZXk9e2xhYmVsfSBzY29wZT1cImNvbFwiPlxuICAgICAgICAgICAgICB7bGFiZWx9XG4gICAgICAgICAgICA8L1RhYmxlSGVhZGVyPlxuICAgICAgICAgICkpfVxuICAgICAgICA8L3RyPlxuICAgICAgPC90aGVhZD5cbiAgICAgIDx0Ym9keT5cbiAgICAgICAge3dlZWtzLm1hcCgod2Vlaywgcm93SW5kZXgpID0+IChcbiAgICAgICAgICA8dHIga2V5PXt3ZWVrLmpvaW4oJy0nKX0+XG4gICAgICAgICAgICB7d2Vlay5tYXAoKGRhdGUsIGNvbEluZGV4KSA9PiB7XG4gICAgICAgICAgICAgIGlmIChkYXRlID09PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgICAgIC8vIGZpeCB0aGlzIGVycm9yXG4gICAgICAgICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgcmVhY3Qvbm8tYXJyYXktaW5kZXgta2V5LCBqc3gtYTExeS9jb250cm9sLWhhcy1hc3NvY2lhdGVkLWxhYmVsXG4gICAgICAgICAgICAgICAgICA8dGQga2V5PXtgZW1wdHktJHtyb3dJbmRleH0tJHtjb2xJbmRleH1gfSByb2xlPVwiZ3JpZGNlbGxcIiAvPlxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgY29uc3Qgc2VsZWN0ZWQgPVxuICAgICAgICAgICAgICAgIGlzU2FtZURheShkYXRlLCBzZWxlY3RlZERhdGUpIHx8IGlzU2FtZURheShkYXRlLCBlbmREYXRlKTtcbiAgICAgICAgICAgICAgY29uc3QgaW5SYW5nZSA9XG4gICAgICAgICAgICAgICAgISFzZWxlY3RlZERhdGUgJiZcbiAgICAgICAgICAgICAgICAhIWVuZERhdGUgJiZcbiAgICAgICAgICAgICAgICBpc0RhdGVJblJhbmdlKGRhdGUsIHNlbGVjdGVkRGF0ZSwgZW5kRGF0ZSk7XG4gICAgICAgICAgICAgIGNvbnN0IGRpc2FibGVkID0gaXNEYXRlRGlzYWJsZWQoZGF0ZSwgZGlzYWJsZWREYXRlcyk7XG4gICAgICAgICAgICAgIGNvbnN0IHRvZGF5ID0gaXNUb2RheShkYXRlKTtcbiAgICAgICAgICAgICAgLy8gdGhpcyBpcyBtYWtpbmcgdGhlIHNlbGVjdGVkIGRhdGUgYSBkaWZmZXJuZXQgY29sb3IgYmMgaXQgaXMgZm9jdXNlZCwgbG9vayBpbnRvIGZ1cnRoZXJcbiAgICAgICAgICAgICAgY29uc3QgaXNGb2N1c2VkID1cbiAgICAgICAgICAgICAgICBmb2N1c1RhcmdldCAhPT0gbnVsbCAmJiBpc1NhbWVEYXkoZGF0ZSwgZm9jdXNUYXJnZXQpO1xuXG4gICAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgPHRkXG4gICAgICAgICAgICAgICAgICBhcmlhLXNlbGVjdGVkPXtzZWxlY3RlZH1cbiAgICAgICAgICAgICAgICAgIGtleT17ZGF0ZS5nZXRUaW1lKCl9XG4gICAgICAgICAgICAgICAgICByb2xlPVwiZ3JpZGNlbGxcIlxuICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgIDxEYXRlQnV0dG9uXG4gICAgICAgICAgICAgICAgICAgIGRpc2FibGVkPXtkaXNhYmxlZH1cbiAgICAgICAgICAgICAgICAgICAgaXNJblJhbmdlPXtpblJhbmdlfVxuICAgICAgICAgICAgICAgICAgICBpc1NlbGVjdGVkPXtzZWxlY3RlZH1cbiAgICAgICAgICAgICAgICAgICAgaXNUb2RheT17dG9kYXl9XG4gICAgICAgICAgICAgICAgICAgIHJlZj17KGVsKSA9PiBzZXRCdXR0b25SZWYoZGF0ZSwgZWwgYXMgSFRNTEVsZW1lbnQgfCBudWxsKX1cbiAgICAgICAgICAgICAgICAgICAgdGFiSW5kZXg9e2lzRm9jdXNlZCA/IDAgOiAtMX1cbiAgICAgICAgICAgICAgICAgICAgdmFyaWFudD1cInNlY29uZGFyeVwiXG4gICAgICAgICAgICAgICAgICAgIG9uQ2xpY2s9eygpID0+IG9uRGF0ZVNlbGVjdChkYXRlKX1cbiAgICAgICAgICAgICAgICAgICAgb25Gb2N1cz17KCkgPT4gb25Gb2N1c2VkRGF0ZUNoYW5nZT8uKGRhdGUpfVxuICAgICAgICAgICAgICAgICAgICBvbktleURvd249eyhlOiBSZWFjdC5LZXlib2FyZEV2ZW50KSA9PlxuICAgICAgICAgICAgICAgICAgICAgIGhhbmRsZUtleURvd24oZSwgZGF0ZSlcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICB7ZGF0ZS5nZXREYXRlKCl9XG4gICAgICAgICAgICAgICAgICA8L0RhdGVCdXR0b24+XG4gICAgICAgICAgICAgICAgPC90ZD5cbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH0pfVxuICAgICAgICAgIDwvdHI+XG4gICAgICAgICkpfVxuICAgICAgPC90Ym9keT5cbiAgICA8L3RhYmxlPlxuICApO1xufTtcbiJdfQ== */");
19
+ const DateButton = /*#__PURE__*/_styled(TextButton, {
20
+ target: "e12sl4cx0",
21
+ label: "DateButton"
22
+ })(states({
23
+ isToday: {
24
+ position: 'relative',
25
+ '&::after': {
26
+ content: '""',
27
+ position: 'absolute',
28
+ bottom: 4,
29
+ left: '50%',
30
+ width: 4,
31
+ height: 4,
32
+ borderRadius: 'full',
33
+ bg: 'hyper'
34
+ }
35
+ },
36
+ isSelected: {
37
+ bg: 'text',
38
+ color: 'background',
39
+ '&:hover, &:focus': {
40
+ bg: 'secondary-hover',
41
+ color: 'background'
42
+ },
43
+ '&::after': {
44
+ bg: 'background'
45
+ }
46
+ },
47
+ isInRange: {
48
+ bg: 'text-disabled',
49
+ color: 'background',
50
+ borderRadius: 'none',
51
+ '&:hover, &:focus': {
52
+ bg: 'secondary-hover',
53
+ color: 'background'
54
+ },
55
+ '&::after': {
56
+ bg: 'background'
57
+ }
58
+ },
59
+ disabled: {
60
+ color: 'text-disabled',
61
+ textDecoration: 'line-through'
62
+ }
63
+ }), css({
64
+ fontWeight: 'base',
65
+ width: '32px'
66
+ }), process.env.NODE_ENV === "production" ? "" : "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9EYXRlUGlja2VyL0NhbGVuZGFyL0NhbGVuZGFyQm9keS50c3giXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBeUJtQiIsImZpbGUiOiIuLi8uLi8uLi9zcmMvRGF0ZVBpY2tlci9DYWxlbmRhci9DYWxlbmRhckJvZHkudHN4Iiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgY3NzLCBzdGF0ZXMgfSBmcm9tICdAY29kZWNhZGVteS9nYW11dC1zdHlsZXMnO1xuaW1wb3J0IHN0eWxlZCBmcm9tICdAZW1vdGlvbi9zdHlsZWQnO1xuaW1wb3J0IHsgdXNlQ2FsbGJhY2ssIHVzZUVmZmVjdCwgdXNlTWVtbywgdXNlUmVmIH0gZnJvbSAncmVhY3QnO1xuaW1wb3J0ICogYXMgUmVhY3QgZnJvbSAncmVhY3QnO1xuXG5pbXBvcnQgeyBUZXh0QnV0dG9uIH0gZnJvbSAnLi4vLi4vQnV0dG9uJztcbmltcG9ydCB7IENhbGVuZGFyQm9keVByb3BzIH0gZnJvbSAnLi90eXBlcyc7XG5pbXBvcnQge1xuICBnZXRNb250aEdyaWQsXG4gIGlzRGF0ZURpc2FibGVkLFxuICBpc0RhdGVJblJhbmdlLFxuICBpc1NhbWVEYXksXG59IGZyb20gJy4vdXRpbHMvZGF0ZUdyaWQnO1xuaW1wb3J0IHsgZ2V0V2Vla2RheUZ1bGxOYW1lcywgZ2V0V2Vla2RheUxhYmVscyB9IGZyb20gJy4vdXRpbHMvZm9ybWF0JztcbmltcG9ydCB7IGdldERhdGVzV2l0aFJvdywga2V5SGFuZGxlciB9IGZyb20gJy4vdXRpbHMva2V5SGFuZGxlcic7XG5cbmNvbnN0IFRhYmxlSGVhZGVyID0gc3R5bGVkLnRoKFxuICBjc3Moe1xuICAgIGZvbnRTaXplOiAxNCxcbiAgICBmb250V2VpZ2h0OiAnYmFzZScsXG4gICAgY29sb3I6ICd0ZXh0LWRpc2FibGVkJyxcbiAgICB0ZXh0QWxpZ246ICdjZW50ZXInLFxuICB9KVxuKTtcblxuY29uc3QgRGF0ZUJ1dHRvbiA9IHN0eWxlZChUZXh0QnV0dG9uKShcbiAgc3RhdGVzKHtcbiAgICBpc1RvZGF5OiB7XG4gICAgICBwb3NpdGlvbjogJ3JlbGF0aXZlJyxcbiAgICAgICcmOjphZnRlcic6IHtcbiAgICAgICAgY29udGVudDogJ1wiXCInLFxuICAgICAgICBwb3NpdGlvbjogJ2Fic29sdXRlJyxcbiAgICAgICAgYm90dG9tOiA0LFxuICAgICAgICBsZWZ0OiAnNTAlJyxcbiAgICAgICAgd2lkdGg6IDQsXG4gICAgICAgIGhlaWdodDogNCxcbiAgICAgICAgYm9yZGVyUmFkaXVzOiAnZnVsbCcsXG4gICAgICAgIGJnOiAnaHlwZXInLFxuICAgICAgfSxcbiAgICB9LFxuICAgIGlzU2VsZWN0ZWQ6IHtcbiAgICAgIGJnOiAndGV4dCcsXG4gICAgICBjb2xvcjogJ2JhY2tncm91bmQnLFxuICAgICAgJyY6aG92ZXIsICY6Zm9jdXMnOiB7XG4gICAgICAgIGJnOiAnc2Vjb25kYXJ5LWhvdmVyJyxcbiAgICAgICAgY29sb3I6ICdiYWNrZ3JvdW5kJyxcbiAgICAgIH0sXG4gICAgICAnJjo6YWZ0ZXInOiB7XG4gICAgICAgIGJnOiAnYmFja2dyb3VuZCcsXG4gICAgICB9LFxuICAgIH0sXG4gICAgaXNJblJhbmdlOiB7XG4gICAgICBiZzogJ3RleHQtZGlzYWJsZWQnLFxuICAgICAgY29sb3I6ICdiYWNrZ3JvdW5kJyxcbiAgICAgIGJvcmRlclJhZGl1czogJ25vbmUnLFxuICAgICAgJyY6aG92ZXIsICY6Zm9jdXMnOiB7XG4gICAgICAgIGJnOiAnc2Vjb25kYXJ5LWhvdmVyJyxcbiAgICAgICAgY29sb3I6ICdiYWNrZ3JvdW5kJyxcbiAgICAgIH0sXG4gICAgICAnJjo6YWZ0ZXInOiB7XG4gICAgICAgIGJnOiAnYmFja2dyb3VuZCcsXG4gICAgICB9LFxuICAgIH0sXG4gICAgZGlzYWJsZWQ6IHtcbiAgICAgIGNvbG9yOiAndGV4dC1kaXNhYmxlZCcsXG4gICAgICB0ZXh0RGVjb3JhdGlvbjogJ2xpbmUtdGhyb3VnaCcsXG4gICAgfSxcbiAgfSksXG4gIGNzcyh7XG4gICAgZm9udFdlaWdodDogJ2Jhc2UnLFxuICAgIHdpZHRoOiAnMzJweCcsXG4gIH0pXG4pO1xuXG5leHBvcnQgY29uc3QgQ2FsZW5kYXJCb2R5OiBSZWFjdC5GQzxDYWxlbmRhckJvZHlQcm9wcz4gPSAoe1xuICB2aXNpYmxlRGF0ZSxcbiAgc2VsZWN0ZWREYXRlLFxuICBlbmREYXRlID0gbnVsbCxcbiAgZGlzYWJsZWREYXRlcyA9IFtdLFxuICBvbkRhdGVTZWxlY3QsXG4gIGxvY2FsZSxcbiAgd2Vla1N0YXJ0c09uID0gMCxcbiAgbGFiZWxsZWRCeUlkLFxuICBmb2N1c2VkRGF0ZSxcbiAgb25Gb2N1c2VkRGF0ZUNoYW5nZSxcbiAgb25WaXNpYmxlRGF0ZUNoYW5nZSxcbiAgb25Fc2NhcGVLZXlQcmVzcyxcbn0pID0+IHtcbiAgY29uc3QgeWVhciA9IHZpc2libGVEYXRlLmdldEZ1bGxZZWFyKCk7XG4gIGNvbnN0IG1vbnRoID0gdmlzaWJsZURhdGUuZ2V0TW9udGgoKTtcbiAgY29uc3Qgd2Vla3MgPSBnZXRNb250aEdyaWQoeWVhciwgbW9udGgsIHdlZWtTdGFydHNPbik7XG4gIGNvbnN0IHdlZWtkYXlMYWJlbHMgPSBnZXRXZWVrZGF5TGFiZWxzKGxvY2FsZSwgd2Vla1N0YXJ0c09uKTtcbiAgY29uc3Qgd2Vla2RheUZ1bGxOYW1lcyA9IGdldFdlZWtkYXlGdWxsTmFtZXMobG9jYWxlLCB3ZWVrU3RhcnRzT24pO1xuICBjb25zdCBidXR0b25SZWZzID0gdXNlUmVmPE1hcDxudW1iZXIsIEhUTUxFbGVtZW50Pj4obmV3IE1hcCgpKTtcblxuICBjb25zdCBkYXRlc1dpdGhSb3cgPSB1c2VNZW1vKCgpID0+IGdldERhdGVzV2l0aFJvdyh3ZWVrcyksIFt3ZWVrc10pO1xuICBjb25zdCBmb2N1c1RhcmdldCA9IGZvY3VzZWREYXRlID8/IHNlbGVjdGVkRGF0ZTtcblxuICBjb25zdCBpc1RvZGF5ID0gdXNlQ2FsbGJhY2soXG4gICAgKGQ6IERhdGUgfCBudWxsKSA9PiBkICE9PSBudWxsICYmIGlzU2FtZURheShkLCBuZXcgRGF0ZSgpKSxcbiAgICBbXVxuICApO1xuXG4gIGNvbnN0IGZvY3VzQnV0dG9uID0gdXNlQ2FsbGJhY2soKGRhdGU6IERhdGUgfCBudWxsKSA9PiB7XG4gICAgaWYgKGRhdGUgPT09IG51bGwpIHJldHVybjtcbiAgICBjb25zdCBrZXkgPSBuZXcgRGF0ZShcbiAgICAgIGRhdGUuZ2V0RnVsbFllYXIoKSxcbiAgICAgIGRhdGUuZ2V0TW9udGgoKSxcbiAgICAgIGRhdGUuZ2V0RGF0ZSgpXG4gICAgKS5nZXRUaW1lKCk7XG4gICAgYnV0dG9uUmVmcy5jdXJyZW50LmdldChrZXkpPy5mb2N1cygpO1xuICB9LCBbXSk7XG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBpZiAoZm9jdXNUYXJnZXQgIT09IG51bGwpIGZvY3VzQnV0dG9uKGZvY3VzVGFyZ2V0KTtcbiAgfSwgW2ZvY3VzVGFyZ2V0LCBmb2N1c0J1dHRvbl0pO1xuXG4gIGNvbnN0IGhhbmRsZUtleURvd24gPSB1c2VDYWxsYmFjayhcbiAgICAoZTogUmVhY3QuS2V5Ym9hcmRFdmVudCwgZGF0ZTogRGF0ZSkgPT5cbiAgICAgIGtleUhhbmRsZXIoXG4gICAgICAgIGUsXG4gICAgICAgIGRhdGUsXG4gICAgICAgIG9uRm9jdXNlZERhdGVDaGFuZ2UsXG4gICAgICAgIGRhdGVzV2l0aFJvdyxcbiAgICAgICAgbW9udGgsXG4gICAgICAgIHllYXIsXG4gICAgICAgIGRpc2FibGVkRGF0ZXMsXG4gICAgICAgIG9uRGF0ZVNlbGVjdCxcbiAgICAgICAgb25Fc2NhcGVLZXlQcmVzcyxcbiAgICAgICAgb25WaXNpYmxlRGF0ZUNoYW5nZVxuICAgICAgKSxcbiAgICBbXG4gICAgICBvbkZvY3VzZWREYXRlQ2hhbmdlLFxuICAgICAgZGF0ZXNXaXRoUm93LFxuICAgICAgbW9udGgsXG4gICAgICB5ZWFyLFxuICAgICAgZGlzYWJsZWREYXRlcyxcbiAgICAgIG9uRGF0ZVNlbGVjdCxcbiAgICAgIG9uRXNjYXBlS2V5UHJlc3MsXG4gICAgICBvblZpc2libGVEYXRlQ2hhbmdlLFxuICAgIF1cbiAgKTtcblxuICBjb25zdCBzZXRCdXR0b25SZWYgPSB1c2VDYWxsYmFjaygoZGF0ZTogRGF0ZSwgZWw6IEhUTUxFbGVtZW50IHwgbnVsbCkgPT4ge1xuICAgIGNvbnN0IGsgPSBuZXcgRGF0ZShcbiAgICAgIGRhdGUuZ2V0RnVsbFllYXIoKSxcbiAgICAgIGRhdGUuZ2V0TW9udGgoKSxcbiAgICAgIGRhdGUuZ2V0RGF0ZSgpXG4gICAgKS5nZXRUaW1lKCk7XG4gICAgaWYgKGVsKSBidXR0b25SZWZzLmN1cnJlbnQuc2V0KGssIGVsKTtcbiAgICBlbHNlIGJ1dHRvblJlZnMuY3VycmVudC5kZWxldGUoayk7XG4gIH0sIFtdKTtcblxuICByZXR1cm4gKFxuICAgIDx0YWJsZSBhcmlhLWxhYmVsbGVkYnk9e2xhYmVsbGVkQnlJZH0gcm9sZT1cImdyaWRcIiB3aWR0aD1cIjEwMCVcIj5cbiAgICAgIDx0aGVhZD5cbiAgICAgICAgPHRyPlxuICAgICAgICAgIHt3ZWVrZGF5TGFiZWxzLm1hcCgobGFiZWwsIGkpID0+IChcbiAgICAgICAgICAgIDxUYWJsZUhlYWRlciBhYmJyPXt3ZWVrZGF5RnVsbE5hbWVzW2ldfSBrZXk9e2xhYmVsfSBzY29wZT1cImNvbFwiPlxuICAgICAgICAgICAgICB7bGFiZWx9XG4gICAgICAgICAgICA8L1RhYmxlSGVhZGVyPlxuICAgICAgICAgICkpfVxuICAgICAgICA8L3RyPlxuICAgICAgPC90aGVhZD5cbiAgICAgIDx0Ym9keT5cbiAgICAgICAge3dlZWtzLm1hcCgod2Vlaywgcm93SW5kZXgpID0+IChcbiAgICAgICAgICA8dHIga2V5PXt3ZWVrLmpvaW4oJy0nKX0+XG4gICAgICAgICAgICB7d2Vlay5tYXAoKGRhdGUsIGNvbEluZGV4KSA9PiB7XG4gICAgICAgICAgICAgIGlmIChkYXRlID09PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgICAgIC8vIGZpeCB0aGlzIGVycm9yXG4gICAgICAgICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgcmVhY3Qvbm8tYXJyYXktaW5kZXgta2V5LCBqc3gtYTExeS9jb250cm9sLWhhcy1hc3NvY2lhdGVkLWxhYmVsXG4gICAgICAgICAgICAgICAgICA8dGQga2V5PXtgZW1wdHktJHtyb3dJbmRleH0tJHtjb2xJbmRleH1gfSByb2xlPVwiZ3JpZGNlbGxcIiAvPlxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgY29uc3Qgc2VsZWN0ZWQgPVxuICAgICAgICAgICAgICAgIGlzU2FtZURheShkYXRlLCBzZWxlY3RlZERhdGUpIHx8IGlzU2FtZURheShkYXRlLCBlbmREYXRlKTtcbiAgICAgICAgICAgICAgY29uc3QgaW5SYW5nZSA9XG4gICAgICAgICAgICAgICAgISFzZWxlY3RlZERhdGUgJiZcbiAgICAgICAgICAgICAgICAhIWVuZERhdGUgJiZcbiAgICAgICAgICAgICAgICBpc0RhdGVJblJhbmdlKGRhdGUsIHNlbGVjdGVkRGF0ZSwgZW5kRGF0ZSk7XG4gICAgICAgICAgICAgIGNvbnN0IGRpc2FibGVkID0gaXNEYXRlRGlzYWJsZWQoZGF0ZSwgZGlzYWJsZWREYXRlcyk7XG4gICAgICAgICAgICAgIGNvbnN0IHRvZGF5ID0gaXNUb2RheShkYXRlKTtcbiAgICAgICAgICAgICAgLy8gdGhpcyBpcyBtYWtpbmcgdGhlIHNlbGVjdGVkIGRhdGUgYSBkaWZmZXJuZXQgY29sb3IgYmMgaXQgaXMgZm9jdXNlZCwgbG9vayBpbnRvIGZ1cnRoZXJcbiAgICAgICAgICAgICAgY29uc3QgaXNGb2N1c2VkID1cbiAgICAgICAgICAgICAgICBmb2N1c1RhcmdldCAhPT0gbnVsbCAmJiBpc1NhbWVEYXkoZGF0ZSwgZm9jdXNUYXJnZXQpO1xuXG4gICAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgPHRkXG4gICAgICAgICAgICAgICAgICBhcmlhLXNlbGVjdGVkPXtzZWxlY3RlZH1cbiAgICAgICAgICAgICAgICAgIGtleT17ZGF0ZS5nZXRUaW1lKCl9XG4gICAgICAgICAgICAgICAgICByb2xlPVwiZ3JpZGNlbGxcIlxuICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgIDxEYXRlQnV0dG9uXG4gICAgICAgICAgICAgICAgICAgIGRpc2FibGVkPXtkaXNhYmxlZH1cbiAgICAgICAgICAgICAgICAgICAgaXNJblJhbmdlPXtpblJhbmdlfVxuICAgICAgICAgICAgICAgICAgICBpc1NlbGVjdGVkPXtzZWxlY3RlZH1cbiAgICAgICAgICAgICAgICAgICAgaXNUb2RheT17dG9kYXl9XG4gICAgICAgICAgICAgICAgICAgIHJlZj17KGVsKSA9PiBzZXRCdXR0b25SZWYoZGF0ZSwgZWwgYXMgSFRNTEVsZW1lbnQgfCBudWxsKX1cbiAgICAgICAgICAgICAgICAgICAgdGFiSW5kZXg9e2lzRm9jdXNlZCA/IDAgOiAtMX1cbiAgICAgICAgICAgICAgICAgICAgdmFyaWFudD1cInNlY29uZGFyeVwiXG4gICAgICAgICAgICAgICAgICAgIG9uQ2xpY2s9eygpID0+IG9uRGF0ZVNlbGVjdChkYXRlKX1cbiAgICAgICAgICAgICAgICAgICAgb25Gb2N1cz17KCkgPT4gb25Gb2N1c2VkRGF0ZUNoYW5nZT8uKGRhdGUpfVxuICAgICAgICAgICAgICAgICAgICBvbktleURvd249eyhlOiBSZWFjdC5LZXlib2FyZEV2ZW50KSA9PlxuICAgICAgICAgICAgICAgICAgICAgIGhhbmRsZUtleURvd24oZSwgZGF0ZSlcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICB7ZGF0ZS5nZXREYXRlKCl9XG4gICAgICAgICAgICAgICAgICA8L0RhdGVCdXR0b24+XG4gICAgICAgICAgICAgICAgPC90ZD5cbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH0pfVxuICAgICAgICAgIDwvdHI+XG4gICAgICAgICkpfVxuICAgICAgPC90Ym9keT5cbiAgICA8L3RhYmxlPlxuICApO1xufTtcbiJdfQ== */");
67
+ export const CalendarBody = ({
68
+ visibleDate,
69
+ selectedDate,
70
+ endDate = null,
71
+ disabledDates = [],
72
+ onDateSelect,
73
+ locale,
74
+ weekStartsOn = 0,
75
+ labelledById,
76
+ focusedDate,
77
+ onFocusedDateChange,
78
+ onVisibleDateChange,
79
+ onEscapeKeyPress
80
+ }) => {
81
+ const year = visibleDate.getFullYear();
82
+ const month = visibleDate.getMonth();
83
+ const weeks = getMonthGrid(year, month, weekStartsOn);
84
+ const weekdayLabels = getWeekdayLabels(locale, weekStartsOn);
85
+ const weekdayFullNames = getWeekdayFullNames(locale, weekStartsOn);
86
+ const buttonRefs = useRef(new Map());
87
+ const datesWithRow = useMemo(() => getDatesWithRow(weeks), [weeks]);
88
+ const focusTarget = focusedDate ?? selectedDate;
89
+ const isToday = useCallback(d => d !== null && isSameDay(d, new Date()), []);
90
+ const focusButton = useCallback(date => {
91
+ if (date === null) return;
92
+ const key = new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime();
93
+ buttonRefs.current.get(key)?.focus();
94
+ }, []);
95
+ useEffect(() => {
96
+ if (focusTarget !== null) focusButton(focusTarget);
97
+ }, [focusTarget, focusButton]);
98
+ const handleKeyDown = useCallback((e, date) => keyHandler(e, date, onFocusedDateChange, datesWithRow, month, year, disabledDates, onDateSelect, onEscapeKeyPress, onVisibleDateChange), [onFocusedDateChange, datesWithRow, month, year, disabledDates, onDateSelect, onEscapeKeyPress, onVisibleDateChange]);
99
+ const setButtonRef = useCallback((date, el) => {
100
+ const k = new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime();
101
+ if (el) buttonRefs.current.set(k, el);else buttonRefs.current.delete(k);
102
+ }, []);
103
+ return /*#__PURE__*/_jsxs("table", {
104
+ "aria-labelledby": labelledById,
105
+ role: "grid",
106
+ width: "100%",
107
+ children: [/*#__PURE__*/_jsx("thead", {
108
+ children: /*#__PURE__*/_jsx("tr", {
109
+ children: weekdayLabels.map((label, i) => /*#__PURE__*/_jsx(TableHeader, {
110
+ abbr: weekdayFullNames[i],
111
+ scope: "col",
112
+ children: label
113
+ }, label))
114
+ })
115
+ }), /*#__PURE__*/_jsx("tbody", {
116
+ children: weeks.map((week, rowIndex) => /*#__PURE__*/_jsx("tr", {
117
+ children: week.map((date, colIndex) => {
118
+ if (date === null) {
119
+ return (
120
+ /*#__PURE__*/
121
+ // fix this error
122
+ // eslint-disable-next-line react/no-array-index-key, jsx-a11y/control-has-associated-label
123
+ _jsx("td", {
124
+ role: "gridcell"
125
+ }, `empty-${rowIndex}-${colIndex}`)
126
+ );
127
+ }
128
+ const selected = isSameDay(date, selectedDate) || isSameDay(date, endDate);
129
+ const inRange = !!selectedDate && !!endDate && isDateInRange(date, selectedDate, endDate);
130
+ const disabled = isDateDisabled(date, disabledDates);
131
+ const today = isToday(date);
132
+ // this is making the selected date a differnet color bc it is focused, look into further
133
+ const isFocused = focusTarget !== null && isSameDay(date, focusTarget);
134
+ return /*#__PURE__*/_jsx("td", {
135
+ "aria-selected": selected,
136
+ role: "gridcell",
137
+ children: /*#__PURE__*/_jsx(DateButton, {
138
+ disabled: disabled,
139
+ isInRange: inRange,
140
+ isSelected: selected,
141
+ isToday: today,
142
+ ref: el => setButtonRef(date, el),
143
+ tabIndex: isFocused ? 0 : -1,
144
+ variant: "secondary",
145
+ onClick: () => onDateSelect(date),
146
+ onFocus: () => onFocusedDateChange?.(date),
147
+ onKeyDown: e => handleKeyDown(e, date),
148
+ children: date.getDate()
149
+ })
150
+ }, date.getTime());
151
+ })
152
+ }, week.join('-')))
153
+ })]
154
+ });
155
+ };
@@ -0,0 +1,3 @@
1
+ import * as React from 'react';
2
+ import { CalendarFooterProps } from './types';
3
+ export declare const CalendarFooter: React.FC<CalendarFooterProps>;
@@ -0,0 +1,60 @@
1
+ import * as React from 'react';
2
+ import { FlexBox } from '../../Box';
3
+ import { TextButton } from '../../Button';
4
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
5
+ // function formatQuickActionLabel(action: QuickAction): string {
6
+ // const { num, timePeriod } = action;
7
+ // const period =
8
+ // timePeriod === 'day'
9
+ // ? num === 1
10
+ // ? 'day'
11
+ // : 'days'
12
+ // : timePeriod === 'week'
13
+ // ? num === 1
14
+ // ? 'week'
15
+ // : 'weeks'
16
+ // : timePeriod === 'month'
17
+ // ? num === 1
18
+ // ? 'month'
19
+ // : 'months'
20
+ // : num === 1
21
+ // ? 'year'
22
+ // : 'years';
23
+ // return `${num} ${period}`;
24
+ // }
25
+
26
+ export const CalendarFooter = ({
27
+ onClearDate,
28
+ onTodayClick,
29
+ onSelectedDateChange,
30
+ onCurrentMonthYearChange
31
+ }) => {
32
+ const handleClearDate = () => {
33
+ onSelectedDateChange(null);
34
+ onClearDate?.();
35
+ };
36
+ const handleTodayClick = () => {
37
+ const today = new Date();
38
+ onSelectedDateChange(today);
39
+ onCurrentMonthYearChange(new Date(today.getFullYear(), today.getMonth(), 1));
40
+ onTodayClick?.();
41
+ };
42
+ // const actions = quickActions.slice(0, 3);
43
+
44
+ return /*#__PURE__*/_jsxs(FlexBox, {
45
+ alignItems: "center",
46
+ borderTop: 1,
47
+ justifyContent: "space-between",
48
+ p: 12,
49
+ children: [/*#__PURE__*/_jsx(TextButton, {
50
+ onClick: handleClearDate,
51
+ children: "Clear"
52
+ }), /*#__PURE__*/_jsx(FlexBox, {
53
+ gap: 32,
54
+ children: /*#__PURE__*/_jsx(TextButton, {
55
+ onClick: handleTodayClick,
56
+ children: "Today"
57
+ })
58
+ })]
59
+ });
60
+ };
@@ -0,0 +1,3 @@
1
+ import * as React from 'react';
2
+ import { CalendarHeaderProps } from './types';
3
+ export declare const CalendarHeader: React.FC<CalendarHeaderProps>;
@@ -0,0 +1,63 @@
1
+ import { MiniChevronLeftIcon, MiniChevronRightIcon } from '@codecademy/gamut-icons';
2
+ import * as React from 'react';
3
+ import { FlexBox } from '../../Box';
4
+ import { IconButton } from '../../Button';
5
+ import { Text } from '../../Typography';
6
+ import { formatMonthYear } from './utils/format';
7
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
8
+ export const CalendarHeader = ({
9
+ currentMonthYear,
10
+ onCurrentMonthYearChange,
11
+ secondMonthYear,
12
+ onPreviousMonthClick,
13
+ onNextMonthClick,
14
+ locale,
15
+ headingId
16
+ }) => {
17
+ const handlePreviousMonth = () => {
18
+ const previousMonth = new Date(currentMonthYear.getFullYear(), currentMonthYear.getMonth() - 1, 1);
19
+ onCurrentMonthYearChange?.(previousMonth);
20
+ onPreviousMonthClick?.();
21
+ };
22
+ const handleNextMonth = () => {
23
+ const nextMonth = new Date(currentMonthYear.getFullYear(), currentMonthYear.getMonth() + 1, 1);
24
+ onCurrentMonthYearChange?.(nextMonth);
25
+ onNextMonthClick?.();
26
+ };
27
+ return /*#__PURE__*/_jsxs(FlexBox, {
28
+ alignItems: "center",
29
+ justifyContent: "space-between",
30
+ pb: 16,
31
+ children: [/*#__PURE__*/_jsx(IconButton, {
32
+ "aria-label": "Previous month",
33
+ icon: MiniChevronLeftIcon,
34
+ size: "small",
35
+ tip: "Previous month",
36
+ onClick: handlePreviousMonth
37
+ }), /*#__PURE__*/_jsx(Text, {
38
+ "aria-live": "polite",
39
+ as: "h2",
40
+ fontSize: 16,
41
+ fontWeight: "title",
42
+ id: headingId,
43
+ children: formatMonthYear(currentMonthYear, locale)
44
+ }), secondMonthYear && /*#__PURE__*/_jsx(Text, {
45
+ "aria-live": "polite",
46
+ as: "h2",
47
+ display: {
48
+ _: 'none',
49
+ xs: 'initial'
50
+ },
51
+ fontSize: 16,
52
+ fontWeight: "title",
53
+ id: headingId,
54
+ children: formatMonthYear(secondMonthYear, locale)
55
+ }), /*#__PURE__*/_jsx(IconButton, {
56
+ "aria-label": "Next month",
57
+ icon: MiniChevronRightIcon,
58
+ size: "small",
59
+ tip: "Next month",
60
+ onClick: handleNextMonth
61
+ })]
62
+ });
63
+ };
@@ -0,0 +1,6 @@
1
+ export { Calendar } from './Calendar';
2
+ export { CalendarHeader } from './CalendarHeader';
3
+ export { CalendarBody } from './CalendarBody';
4
+ export { CalendarFooter } from './CalendarFooter';
5
+ export type { CalendarHeaderProps, CalendarBodyProps, CalendarFooterProps, QuickAction, } from './types';
6
+ export * from './utils';
@@ -0,0 +1,5 @@
1
+ export { Calendar } from './Calendar';
2
+ export { CalendarHeader } from './CalendarHeader';
3
+ export { CalendarBody } from './CalendarBody';
4
+ export { CalendarFooter } from './CalendarFooter';
5
+ export * from './utils';
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Internal types for the Calendar subcomponents (used by DatePickerCalendar).
3
+ */
4
+ export interface CalendarHeaderProps {
5
+ /** Currently displayed month and year (used for heading and prev/next range) */
6
+ currentMonthYear: Date;
7
+ /** Called when the user navigates to a different month. Pass the new date (e.g. setVisibleDate) so the calendar updates. */
8
+ onCurrentMonthYearChange: (newDate: Date) => void;
9
+ /** Currently displayed second month and year (used for heading and prev/next range) */
10
+ secondMonthYear?: Date;
11
+ /** Called after navigating to previous month; use for click tracking. */
12
+ onPreviousMonthClick?: () => void;
13
+ /** Called after navigating to next month; use for click tracking. */
14
+ onNextMonthClick?: () => void;
15
+ /** Locale for month/year formatting (e.g. 'en-US') */
16
+ locale?: string;
17
+ /** id for the heading (for grid aria-labelledby) */
18
+ headingId: string;
19
+ }
20
+ export interface CalendarBodyProps {
21
+ /** The month to display (typically first day of that month) */
22
+ visibleDate: Date;
23
+ /** Selected start date (single or range start) */
24
+ selectedDate: Date | null;
25
+ /** Selected end date (range only; undefined for single-date mode) */
26
+ endDate?: Date | null;
27
+ /** Dates that should be disabled (unselectable) */
28
+ disabledDates?: Date[];
29
+ /** Called when a date cell is selected */
30
+ onDateSelect: (date: Date) => void;
31
+ /** Locale for weekday names and week start */
32
+ locale?: string;
33
+ /** 0 = Sunday, 1 = Monday (default from locale if not set) */
34
+ weekStartsOn?: 0 | 1;
35
+ /** Id of the month/year heading (aria-labelledby on grid) */
36
+ labelledById: string;
37
+ /** For keyboard nav: which cell has focus (roving tabindex) */
38
+ focusedDate: Date | null;
39
+ /** Callback when focused date changes (e.g. arrow keys) */
40
+ onFocusedDateChange: (date: Date | null) => void;
41
+ /** Called when grid keyboard nav changes month (e.g. Page Up/Down). Pass setVisibleDate so the calendar updates. */
42
+ onVisibleDateChange: (newDate: Date) => void;
43
+ /** Called when the escape key is pressed */
44
+ onEscapeKeyPress?: () => void;
45
+ }
46
+ export interface QuickAction {
47
+ num: number;
48
+ timePeriod: 'day' | 'week' | 'month' | 'year';
49
+ onClick: () => void;
50
+ }
51
+ export interface CalendarFooterProps {
52
+ onClearDate?: () => void;
53
+ onTodayClick?: () => void;
54
+ /** Called when the user navigates to a different month. Pass the new date (e.g. setVisibleDate) so the calendar updates. */
55
+ onSelectedDateChange: (newDate: Date | null) => void;
56
+ onCurrentMonthYearChange: (newDate: Date) => void;
57
+ /** Max 3 quick actions (e.g. "7 days", "1 month") */
58
+ quickActions?: QuickAction[];
59
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Builds a grid of days for a calendar month using native Date and Intl.
3
+ * Each row has 7 cells; leading/trailing cells may be null (padding from adjacent months).
4
+ */
5
+ /**
6
+ * Get the weekday for a date (0 = Sunday, 6 = Saturday).
7
+ * Optionally use weekStartsOn to compute "offset" for display (e.g. Monday = 0).
8
+ */
9
+ export declare const getDayOfWeek: (date: Date, weekStartsOn?: 0 | 1) => number;
10
+ /**
11
+ * Returns an array of weeks for the given month. Each week is an array of 7 items:
12
+ * each item is either a Date (that day) or null (padding from previous/next month).
13
+ *
14
+ * @param year - Full year (e.g. 2026)
15
+ * @param month - Month 0-11 (0 = January)
16
+ * @param weekStartsOn - 0 = Sunday, 1 = Monday
17
+ */
18
+ export declare const getMonthGrid: (year: number, month: number, weekStartsOn?: 0 | 1) => (Date | null)[][];
19
+ /**
20
+ * Check if two dates are the same calendar day (ignoring time).
21
+ */
22
+ export declare const isSameDay: (a: Date | null, b: Date | null) => boolean;
23
+ /**
24
+ * Check if `date` is between `start` and `end` (exclusive), ignoring time.
25
+ */
26
+ export declare const isDateInRange: (date: Date, start: Date | null, end: Date | null) => boolean;
27
+ /**
28
+ * Check if `date` is in the `disabledDates` list (by calendar day).
29
+ */
30
+ export declare const isDateDisabled: (date: Date, disabledDates?: Date[]) => boolean;
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Builds a grid of days for a calendar month using native Date and Intl.
3
+ * Each row has 7 cells; leading/trailing cells may be null (padding from adjacent months).
4
+ */
5
+
6
+ const DAYS_PER_WEEK = 7;
7
+
8
+ /**
9
+ * Normalize to start of day in local time for comparison.
10
+ */
11
+ const toDateOnly = date => {
12
+ return new Date(date.getFullYear(), date.getMonth(), date.getDate());
13
+ };
14
+
15
+ /**
16
+ * Get the weekday for a date (0 = Sunday, 6 = Saturday).
17
+ * Optionally use weekStartsOn to compute "offset" for display (e.g. Monday = 0).
18
+ */
19
+ export const getDayOfWeek = (date, weekStartsOn = 0) => {
20
+ const sundayBased = date.getDay();
21
+ if (weekStartsOn === 0) return sundayBased;
22
+ return (sundayBased + 6) % 7; // Monday = 0
23
+ };
24
+
25
+ /**
26
+ * Returns an array of weeks for the given month. Each week is an array of 7 items:
27
+ * each item is either a Date (that day) or null (padding from previous/next month).
28
+ *
29
+ * @param year - Full year (e.g. 2026)
30
+ * @param month - Month 0-11 (0 = January)
31
+ * @param weekStartsOn - 0 = Sunday, 1 = Monday
32
+ */
33
+ export const getMonthGrid = (year, month, weekStartsOn = 0) => {
34
+ const first = new Date(year, month, 1);
35
+ const last = new Date(year, month + 1, 0);
36
+ const firstDayOfWeek = getDayOfWeek(first, weekStartsOn);
37
+ const daysInMonth = last.getDate();
38
+ const weeks = [];
39
+ let currentWeek = [];
40
+
41
+ // Pad start of first week with nulls
42
+ // eslint-disable-next-line no-plusplus
43
+ for (let i = 0; i < firstDayOfWeek; i++) {
44
+ currentWeek.push(null);
45
+ }
46
+
47
+ // fix these
48
+ // eslint-disable-next-line no-plusplus
49
+ for (let day = 1; day <= daysInMonth; day++) {
50
+ currentWeek.push(new Date(year, month, day));
51
+ if (currentWeek.length === DAYS_PER_WEEK) {
52
+ weeks.push(currentWeek);
53
+ currentWeek = [];
54
+ }
55
+ }
56
+
57
+ // Pad end of last week with nulls
58
+ if (currentWeek.length > 0) {
59
+ while (currentWeek.length < DAYS_PER_WEEK) {
60
+ currentWeek.push(null);
61
+ }
62
+ weeks.push(currentWeek);
63
+ }
64
+ return weeks;
65
+ };
66
+
67
+ /**
68
+ * Check if two dates are the same calendar day (ignoring time).
69
+ */
70
+ export const isSameDay = (a, b) => {
71
+ if (a === null || b === null) return false;
72
+ return toDateOnly(a).getTime() === toDateOnly(b).getTime();
73
+ };
74
+
75
+ /**
76
+ * Check if `date` is between `start` and `end` (exclusive), ignoring time.
77
+ */
78
+ export const isDateInRange = (date, start, end) => {
79
+ if (start === null) return false;
80
+ const normalizedDateTime = toDateOnly(date).getTime();
81
+ const normalizedStartDateTime = toDateOnly(start).getTime();
82
+ const normalizedEndDateTime = end !== null ? toDateOnly(end).getTime() : normalizedStartDateTime;
83
+ const low = Math.min(normalizedStartDateTime, normalizedEndDateTime);
84
+ const high = Math.max(normalizedStartDateTime, normalizedEndDateTime);
85
+ return normalizedDateTime > low && normalizedDateTime < high;
86
+ };
87
+
88
+ /**
89
+ * Check if `date` is in the `disabledDates` list (by calendar day).
90
+ */
91
+ export const isDateDisabled = (date, disabledDates = []) => {
92
+ return disabledDates.some(d => isSameDay(date, d));
93
+ };
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Date formatting for the calendar using Intl.DateTimeFormat.
3
+ */
4
+ /**
5
+ * Format month and year for the calendar header (e.g. "February 2026").
6
+ */
7
+ export declare const formatMonthYear: (date: Date, locale?: string) => string;
8
+ /**
9
+ * Get short weekday labels for column headers (e.g. ["Su", "Mo", ...]).
10
+ * Order depends on weekStartsOn: 0 = Sunday first, 1 = Monday first.
11
+ */
12
+ export declare const getWeekdayLabels: (locale?: string, weekStartsOn?: 0 | 1) => string[];
13
+ /**
14
+ * Get full weekday names for abbr attributes (e.g. "Sunday", "Monday").
15
+ * Same order as getWeekdayLabels.
16
+ */
17
+ export declare const getWeekdayFullNames: (locale?: string, weekStartsOn?: 0 | 1) => string[];
18
+ /**
19
+ * Format a date for display in the date picker input (e.g. "2/15/2026").
20
+ */
21
+ export declare const formatDateForInput: (date: Date, locale?: string) => string;
22
+ /**
23
+ * Parse a string from the date input into a Date, or null if invalid.
24
+ * Only returns a date when the input is a complete valid date (e.g. "2/15/2026").
25
+ * Partial input like "1" or "2/15" returns null even though Date("1") would parse.
26
+ */
27
+ export declare const parseDateFromInput: (value: string, locale?: string) => Date | null;
28
+ /**
29
+ * Format a date range for the input (e.g. "2/15/2026 – 2/20/2026").
30
+ */
31
+ export declare const formatDateRangeForInput: (startDate: Date | null, endDate: Date | null, locale?: string) => string;
32
+ /**
33
+ * Parse a range string (e.g. "2/15/2026 – 2/20/2026") into { startDate, endDate }.
34
+ * Returns null if invalid. Single date is allowed and yields startDate = endDate.
35
+ */
36
+ export declare const parseDateRangeFromInput: (value: string, locale?: string) => {
37
+ startDate: Date;
38
+ endDate: Date;
39
+ } | null;