reshaped 2.6.4 → 2.7.1

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/CHANGELOG.md +1 -10
  2. package/bundle.css +1 -1
  3. package/bundle.d.ts +2 -0
  4. package/bundle.js +10 -10
  5. package/components/Calendar/Calendar.d.ts +4 -0
  6. package/components/Calendar/Calendar.js +9 -0
  7. package/components/Calendar/Calendar.module.css +1 -0
  8. package/components/Calendar/Calendar.types.d.ts +102 -0
  9. package/components/Calendar/Calendar.types.js +1 -0
  10. package/components/Calendar/Calendar.utils.d.ts +43 -0
  11. package/components/Calendar/Calendar.utils.js +110 -0
  12. package/components/Calendar/CalendarControlled.d.ts +4 -0
  13. package/components/Calendar/CalendarControlled.js +72 -0
  14. package/components/Calendar/CalendarControls.d.ts +4 -0
  15. package/components/Calendar/CalendarControls.js +56 -0
  16. package/components/Calendar/CalendarDate.d.ts +4 -0
  17. package/components/Calendar/CalendarDate.js +58 -0
  18. package/components/Calendar/CalendarMonth.d.ts +4 -0
  19. package/components/Calendar/CalendarMonth.js +54 -0
  20. package/components/Calendar/CalendarUncontrolled.d.ts +4 -0
  21. package/components/Calendar/CalendarUncontrolled.js +29 -0
  22. package/components/Calendar/CalendarYear.d.ts +4 -0
  23. package/components/Calendar/CalendarYear.js +45 -0
  24. package/components/Calendar/index.d.ts +2 -0
  25. package/components/Calendar/index.js +1 -0
  26. package/components/Calendar/tests/Calendar.stories.d.ts +9 -0
  27. package/components/Calendar/tests/Calendar.stories.js +30 -0
  28. package/components/Calendar/useCalendarKeyboardNavigation.d.ts +11 -0
  29. package/components/Calendar/useCalendarKeyboardNavigation.js +67 -0
  30. package/components/Modal/Modal.js +110 -3
  31. package/components/Modal/Modal.module.css +1 -1
  32. package/components/Modal/tests/Modal.stories.js +3 -0
  33. package/components/Overlay/Overlay.js +14 -10
  34. package/components/Overlay/Overlay.module.css +1 -1
  35. package/components/Overlay/Overlay.types.d.ts +1 -1
  36. package/components/Slider/Slider.module.css +1 -1
  37. package/components/Text/Text.js +1 -1
  38. package/components/Text/Text.module.css +1 -1
  39. package/components/Text/tests/Text.stories.js +1 -1
  40. package/hooks/useResponsiveClientValue.d.ts +1 -1
  41. package/hooks/useResponsiveClientValue.js +3 -0
  42. package/index.d.ts +2 -0
  43. package/index.js +1 -0
  44. package/package.json +6 -6
@@ -0,0 +1,4 @@
1
+ import React from "react";
2
+ import type * as T from "./Calendar.types";
3
+ declare const Calendar: (props: T.Props) => React.JSX.Element;
4
+ export default Calendar;
@@ -0,0 +1,9 @@
1
+ import React from "react";
2
+ import CalendarControlled from "./CalendarControlled.js";
3
+ import CalendarUncontrolled from "./CalendarUncontrolled.js";
4
+ const Calendar = (props) => {
5
+ if (props.value !== undefined)
6
+ return React.createElement(CalendarControlled, Object.assign({}, props));
7
+ return React.createElement(CalendarUncontrolled, Object.assign({}, props));
8
+ };
9
+ export default Calendar;
@@ -0,0 +1 @@
1
+ .selection{table-layout:fixed;width:100%}.weekday{color:var(--rs-color-foreground-neutral-faded);font-weight:var(--rs-font-weight-regular);padding-bottom:var(--rs-unit-x2)}.row{border-top:2px solid transparent}[dir=rtl] .control{transform:scaleX(-1)}.cell-button{padding:var(--rs-unit-x2);text-align:center;transition:var(--rs-duration-fast) var(--rs-easing-standard);transition-property:border-radius,background-color,box-shadow}.cell-button[disabled],.cell-button[disabled]:hover{background-color:transparent!important;color:var(--rs-color-foreground-disabled)!important}.cell{padding:0}.cell .cell-button:hover,.cell--in-range .cell-button{background-color:rgba(var(--rs-color-rgb-background-neutral),32%)}.cell--active-end .cell-button,.cell--active-end:hover .cell-button,.cell--active-start .cell-button,.cell--active-start:hover .cell-button{background-color:var(--rs-color-background-primary);color:var(--rs-color-on-background-primary)}.cell--active-start .cell-button,.cell:first-child .cell-button{border-end-start-radius:var(--rs-unit-radius-small);border-start-start-radius:var(--rs-unit-radius-small)}.cell--active-end .cell-button,.cell--active-start+.cell:hover:not(.cell--in-range) .cell-button,.cell--in-range+.cell:hover:not(.cell--in-range) .cell-button,.cell:last-child .cell-button{border-end-end-radius:var(--rs-unit-radius-small);border-start-end-radius:var(--rs-unit-radius-small)}.cell--active-single+.cell:hover .cell-button,.cell:hover:not(.cell--in-range,.cell--in-range+.cell:hover,.cell--active-start+.cell:hover) .cell-button{border-radius:var(--rs-unit-radius-small)}
@@ -0,0 +1,102 @@
1
+ export type SelectionMode = "date" | "month";
2
+ export type BaseProps = {
3
+ defaultMonth?: Date;
4
+ min?: Date;
5
+ max?: Date;
6
+ firstWeekDay?: number;
7
+ renderWeekDay?: (args: {
8
+ weekDay: number;
9
+ date: Date;
10
+ }) => string;
11
+ renderSelectedMonthLabel?: (args: {
12
+ date: Date;
13
+ }) => string;
14
+ renderMonthLabel?: (args: {
15
+ month: number;
16
+ date: Date;
17
+ }) => string;
18
+ previousMonthAriaLabel?: string;
19
+ nextMonthAriaLabel?: string;
20
+ previousYearAriaLabel?: string;
21
+ nextYearAriaLabel?: string;
22
+ monthSelectionAriaLabel?: string;
23
+ renderDateAriaLabel?: (args: {
24
+ date: Date;
25
+ }) => string;
26
+ renderMonthAriaLabel?: (args: {
27
+ month: number;
28
+ }) => string;
29
+ };
30
+ export type SingleValue = Date;
31
+ export type RangeValue = {
32
+ start: Date | null;
33
+ end: Date | null;
34
+ };
35
+ export type ControlledSingleProps = {
36
+ range?: false;
37
+ value: SingleValue | null;
38
+ defaultValue?: never;
39
+ onChange?: (args: {
40
+ value: SingleValue;
41
+ }) => void;
42
+ };
43
+ export type UncontrolledSingleProps = {
44
+ range?: false;
45
+ value?: never;
46
+ defaultValue?: SingleValue;
47
+ onChange?: (args: {
48
+ value: SingleValue;
49
+ }) => void;
50
+ };
51
+ export type ControlledRangeProps = {
52
+ range: true;
53
+ value: RangeValue;
54
+ defaultValue?: never;
55
+ onChange?: (args: {
56
+ value: RangeValue;
57
+ }) => void;
58
+ };
59
+ export type UncontrolledRangeProps = {
60
+ range: true;
61
+ value?: never;
62
+ defaultValue?: RangeValue;
63
+ onChange?: (args: {
64
+ value: RangeValue;
65
+ }) => void;
66
+ };
67
+ export type UncontrolledProps = UncontrolledSingleProps | UncontrolledRangeProps;
68
+ export type ControlledProps = ControlledSingleProps | ControlledRangeProps;
69
+ export type SingleProps = ControlledSingleProps | UncontrolledSingleProps;
70
+ export type RangeProps = ControlledRangeProps | UncontrolledRangeProps;
71
+ export type Props = (SingleProps | RangeProps) & BaseProps;
72
+ export type MonthProps = {
73
+ date: Date;
74
+ hoveredDate: Date | null;
75
+ onDateHover: (date: Date) => void;
76
+ onDateHoverEnd: (date: Date) => void;
77
+ } & Pick<BaseProps, "max" | "min" | "firstWeekDay" | "renderMonthLabel" | "renderWeekDay" | "renderSelectedMonthLabel" | "renderDateAriaLabel"> & Pick<ControlledProps, "value" | "onChange" | "range">;
78
+ export type YearProps = {
79
+ monthDate: Date;
80
+ onMonthClick: (month: number) => void;
81
+ } & Pick<BaseProps, "renderMonthLabel" | "min" | "max" | "renderMonthAriaLabel">;
82
+ export type DateProps = {
83
+ date: Date | null;
84
+ disabled?: boolean;
85
+ focusable?: boolean;
86
+ startValue: Date | null;
87
+ endValue: Date | null;
88
+ isActiveStart: boolean;
89
+ isActiveEnd: boolean;
90
+ renderAriaLabel?: MonthProps["renderDateAriaLabel"];
91
+ } & Pick<MonthProps, "hoveredDate" | "onDateHover" | "onDateHoverEnd" | "onChange" | "range" | "min" | "max">;
92
+ export type ControlsProps = {
93
+ selectionMode: SelectionMode;
94
+ onMonthTitleClick: () => void;
95
+ monthTitleRef: React.MutableRefObject<HTMLButtonElement | null>;
96
+ monthDate: Date;
97
+ renderSelectedMonthLabel?: BaseProps["renderSelectedMonthLabel"];
98
+ isFirstMonth?: boolean;
99
+ isLastMonth?: boolean;
100
+ onNextClick: () => void;
101
+ onPreviousClick: () => void;
102
+ } & Pick<BaseProps, "nextMonthAriaLabel" | "nextYearAriaLabel" | "previousMonthAriaLabel" | "previousYearAriaLabel" | "monthSelectionAriaLabel">;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,43 @@
1
+ import type * as T from "./Calendar.types";
2
+ /**
3
+ * Return the ISO date format without the timezones adjustemnts
4
+ */
5
+ export declare const getLocalISODate: (args: {
6
+ date: Date;
7
+ }) => string;
8
+ /**
9
+ * Return an array of US weekday names for the calendar
10
+ */
11
+ export declare const getWeekdayNames: (args: {
12
+ firstWeekDay?: number;
13
+ renderWeekDay: T.BaseProps["renderWeekDay"];
14
+ }) => string[];
15
+ /**
16
+ * Return an array of all month names
17
+ */
18
+ export declare const getMonthNames: (args: {
19
+ renderMonthLabel: T.BaseProps["renderMonthLabel"];
20
+ }) => string[];
21
+ /**
22
+ * Return an array of weeks based on the month passed to the function
23
+ */
24
+ export declare const getMonthWeeks: (args: {
25
+ date: Date;
26
+ firstWeekDay?: number;
27
+ }) => (Date | null)[][];
28
+ export declare const getFocusableDates: (rootEl: HTMLElement | null) => HTMLButtonElement[];
29
+ export declare const changeDate: (date: Date, delta: number) => Date;
30
+ export declare const setMonthTo: (date: Date, value: number) => Date;
31
+ export declare const setMonthToPrevious: (date: Date) => Date;
32
+ export declare const setMonthToNext: (date: Date) => Date;
33
+ export declare const setYearTo: (date: Date, value: number) => Date;
34
+ export declare const setYearToPrevious: (date: Date) => Date;
35
+ export declare const setYearToNext: (date: Date) => Date;
36
+ export declare const applyNavigationBounds: (args: {
37
+ date: Date;
38
+ min?: Date;
39
+ max?: Date;
40
+ }) => {
41
+ isFirstMonth: boolean | undefined;
42
+ isLastMonth: boolean | undefined;
43
+ };
@@ -0,0 +1,110 @@
1
+ const DAYS_IN_WEEK = 7;
2
+ const FIRST_WEEK_DAY = 1;
3
+ /**
4
+ * Return the ISO date format without the timezones adjustemnts
5
+ */
6
+ export const getLocalISODate = (args) => {
7
+ const { date } = args;
8
+ return [
9
+ date.getFullYear(),
10
+ (date.getMonth() + 1).toString().padStart(2, "0"),
11
+ date.getDate().toString().padStart(2, "0"),
12
+ ].join("-");
13
+ };
14
+ const getNormalizedDay = (args) => {
15
+ const { date, firstWeekDay = FIRST_WEEK_DAY } = args;
16
+ const day = date.getDay();
17
+ return day < firstWeekDay ? DAYS_IN_WEEK - day - firstWeekDay : day - firstWeekDay;
18
+ };
19
+ /**
20
+ * Return an array of US weekday names for the calendar
21
+ */
22
+ export const getWeekdayNames = (args) => {
23
+ const { firstWeekDay = FIRST_WEEK_DAY, renderWeekDay } = args;
24
+ const baseDate = new Date(2021, 1, firstWeekDay); // Starting from Sunday + firstWeekDay
25
+ const weekdays = [];
26
+ for (let i = firstWeekDay; i < firstWeekDay + DAYS_IN_WEEK; i++) {
27
+ const weekday = renderWeekDay
28
+ ? renderWeekDay({ weekDay: i, date: baseDate })
29
+ : baseDate.toLocaleDateString("en-US", { weekday: "short" });
30
+ weekdays.push(weekday.slice(0, 2));
31
+ baseDate.setDate(baseDate.getDate() + 1);
32
+ }
33
+ return weekdays;
34
+ };
35
+ /**
36
+ * Return an array of all month names
37
+ */
38
+ export const getMonthNames = (args) => {
39
+ const { renderMonthLabel } = args;
40
+ return new Array(12).fill(null).map((_, i) => {
41
+ const date = new Date(0, i);
42
+ return renderMonthLabel
43
+ ? renderMonthLabel({ month: i, date })
44
+ : date.toLocaleString("default", { month: "short" });
45
+ });
46
+ };
47
+ /**
48
+ * Return an array of weeks based on the month passed to the function
49
+ */
50
+ export const getMonthWeeks = (args) => {
51
+ const { date, firstWeekDay } = args;
52
+ const month = date.getMonth();
53
+ const year = date.getFullYear();
54
+ const weeks = [];
55
+ const currentDate = new Date(year, month, 1);
56
+ // Fill in the days if month starts in the middle of the week
57
+ const firstDay = getNormalizedDay({ date: currentDate, firstWeekDay });
58
+ if (firstDay !== 0)
59
+ weeks.push(new Array(firstDay).fill(null));
60
+ while (month === currentDate.getMonth()) {
61
+ const day = getNormalizedDay({ date: currentDate, firstWeekDay });
62
+ if (day === 0 || !weeks.length)
63
+ weeks.push([]);
64
+ weeks[weeks.length - 1].push(new Date(currentDate));
65
+ currentDate.setDate(currentDate.getDate() + 1);
66
+ }
67
+ // Fill in the days if month ends in the middle of the week
68
+ const lastDay = getNormalizedDay({ date: currentDate, firstWeekDay });
69
+ if (lastDay !== 0)
70
+ weeks[weeks.length - 1].push(...new Array(7 - lastDay).fill(null));
71
+ return weeks;
72
+ };
73
+ export const getFocusableDates = (rootEl) => {
74
+ return ((rootEl === null || rootEl === void 0 ? void 0 : rootEl.querySelectorAll("[data-rs-date]")) || []);
75
+ };
76
+ export const changeDate = (date, delta) => new Date(date.getFullYear(), date.getMonth(), date.getDate() + delta);
77
+ export const setMonthTo = (date, value) => {
78
+ const resultDate = new Date(date);
79
+ resultDate.setMonth(value);
80
+ return resultDate;
81
+ };
82
+ export const setMonthToPrevious = (date) => {
83
+ return setMonthTo(date, date.getMonth() - 1);
84
+ };
85
+ export const setMonthToNext = (date) => {
86
+ return setMonthTo(date, date.getMonth() + 1);
87
+ };
88
+ export const setYearTo = (date, value) => {
89
+ const resultDate = new Date(date);
90
+ resultDate.setFullYear(value);
91
+ return resultDate;
92
+ };
93
+ export const setYearToPrevious = (date) => {
94
+ return setYearTo(date, date.getFullYear() - 1);
95
+ };
96
+ export const setYearToNext = (date) => {
97
+ return setYearTo(date, date.getFullYear() + 1);
98
+ };
99
+ export const applyNavigationBounds = (args) => {
100
+ const { date, min, max } = args;
101
+ const currentMonth = date.getMonth();
102
+ const currentYear = date.getFullYear();
103
+ const prevMonthLastDate = new Date(currentYear, currentMonth, 0);
104
+ const nextMonthFirstDate = setMonthToNext(date);
105
+ nextMonthFirstDate.setDate(0);
106
+ return {
107
+ isFirstMonth: min && min > prevMonthLastDate,
108
+ isLastMonth: max && max < nextMonthFirstDate,
109
+ };
110
+ };
@@ -0,0 +1,4 @@
1
+ import React from "react";
2
+ import type * as T from "./Calendar.types";
3
+ declare const CalendarControlled: (props: T.ControlledProps & T.BaseProps) => React.JSX.Element;
4
+ export default CalendarControlled;
@@ -0,0 +1,72 @@
1
+ "use client";
2
+ import React from "react";
3
+ import View from "../View/index.js";
4
+ import { onNextFrame } from "../../utilities/animation.js";
5
+ import { setMonthToPrevious, setMonthToNext, setMonthTo, setYearToNext, setYearToPrevious, applyNavigationBounds, } from "./Calendar.utils.js";
6
+ import useCalendarKeyboardNavigation from "./useCalendarKeyboardNavigation.js";
7
+ import CalendarMonth from "./CalendarMonth.js";
8
+ import CalendarYear from "./CalendarYear.js";
9
+ import CalendarControls from "./CalendarControls.js";
10
+ const CalendarControlled = (props) => {
11
+ const { value, onChange, defaultMonth, min, max, range, firstWeekDay, renderMonthLabel, renderSelectedMonthLabel, renderWeekDay, previousMonthAriaLabel, previousYearAriaLabel, nextMonthAriaLabel, nextYearAriaLabel, monthSelectionAriaLabel, renderMonthAriaLabel, renderDateAriaLabel, } = props;
12
+ const [selectionMode, setSelectionMode] = React.useState("date");
13
+ const [monthDate, setMonthDate] = React.useState(defaultMonth || new Date());
14
+ const [hoveredDate, setHoveredDate] = React.useState(null);
15
+ const monthTitleRef = React.useRef(null);
16
+ const prevSelectionModeRef = React.useRef(selectionMode);
17
+ const bounds = applyNavigationBounds({ date: monthDate, min, max });
18
+ const selectionRootRef = React.useRef(null);
19
+ const handlePreviousClick = () => {
20
+ if (selectionMode === "month") {
21
+ setMonthDate((prev) => setYearToPrevious(prev));
22
+ return;
23
+ }
24
+ setMonthDate((prev) => setMonthToPrevious(prev));
25
+ };
26
+ const handleNextClick = () => {
27
+ if (selectionMode === "month") {
28
+ setMonthDate((prev) => setYearToNext(prev));
29
+ return;
30
+ }
31
+ setMonthDate((prev) => setMonthToNext(prev));
32
+ };
33
+ const handleMonthTitleClick = () => {
34
+ setSelectionMode("month");
35
+ };
36
+ const handleMonthClick = (i) => {
37
+ setMonthDate((prev) => setMonthTo(prev, i));
38
+ setSelectionMode("date");
39
+ };
40
+ const handleDateHover = (date) => {
41
+ setHoveredDate(date);
42
+ };
43
+ const handleDateHoverEnd = (date) => {
44
+ if (hoveredDate && +hoveredDate === +date)
45
+ setHoveredDate(null);
46
+ };
47
+ React.useEffect(() => {
48
+ if (selectionMode === "date" && selectionMode !== prevSelectionModeRef.current) {
49
+ onNextFrame(() => {
50
+ var _a;
51
+ (_a = monthTitleRef.current) === null || _a === void 0 ? void 0 : _a.focus();
52
+ });
53
+ }
54
+ prevSelectionModeRef.current = selectionMode;
55
+ }, [selectionMode]);
56
+ useCalendarKeyboardNavigation({
57
+ monthDate,
58
+ rootRef: selectionRootRef,
59
+ changeToNextMonth: handleNextClick,
60
+ changeToPreviousMonth: handlePreviousClick,
61
+ // Each row has 7 days in date selection and 3 months in month
62
+ verticalDelta: selectionMode === "date" ? 7 : 3,
63
+ min,
64
+ max,
65
+ });
66
+ return (React.createElement(View, { gap: 2 },
67
+ React.createElement(CalendarControls, { renderSelectedMonthLabel: renderSelectedMonthLabel, monthDate: monthDate, selectionMode: selectionMode, isFirstMonth: bounds.isFirstMonth, isLastMonth: bounds.isLastMonth, monthTitleRef: monthTitleRef, onMonthTitleClick: handleMonthTitleClick, onNextClick: handleNextClick, onPreviousClick: handlePreviousClick, previousMonthAriaLabel: previousMonthAriaLabel, previousYearAriaLabel: previousYearAriaLabel, nextMonthAriaLabel: nextMonthAriaLabel, nextYearAriaLabel: nextYearAriaLabel, monthSelectionAriaLabel: monthSelectionAriaLabel }),
68
+ React.createElement(View.Item, { attributes: { ref: selectionRootRef } },
69
+ selectionMode === "date" && (React.createElement(CalendarMonth, { date: monthDate, value: value, onChange: onChange, min: min, max: max, range: range, firstWeekDay: firstWeekDay, hoveredDate: hoveredDate, onDateHover: handleDateHover, onDateHoverEnd: handleDateHoverEnd, renderWeekDay: renderWeekDay, renderDateAriaLabel: renderDateAriaLabel })),
70
+ selectionMode === "month" && (React.createElement(CalendarYear, { monthDate: monthDate, onMonthClick: handleMonthClick, renderMonthLabel: renderMonthLabel, renderMonthAriaLabel: renderMonthAriaLabel, min: min, max: max })))));
71
+ };
72
+ export default CalendarControlled;
@@ -0,0 +1,4 @@
1
+ import React from "react";
2
+ import type * as T from "./Calendar.types";
3
+ declare const CalendarControls: (props: T.ControlsProps) => React.JSX.Element;
4
+ export default CalendarControls;
@@ -0,0 +1,56 @@
1
+ import React from "react";
2
+ import Button from "../Button/index.js";
3
+ import View from "../View/index.js";
4
+ import Hidden from "../Hidden/index.js";
5
+ import Text from "../Text/index.js";
6
+ import HiddenVisually from "../HiddenVisually/index.js";
7
+ import IconChevronLeft from "../../icons/ChevronLeft.js";
8
+ import IconChevronRight from "../../icons/ChevronRight.js";
9
+ import { onNextFrame } from "../../utilities/animation.js";
10
+ import s from "./Calendar.module.css";
11
+ const CalendarControls = (props) => {
12
+ const { selectionMode, onMonthTitleClick, monthTitleRef, monthDate, renderSelectedMonthLabel, isFirstMonth, isLastMonth, onNextClick, onPreviousClick, monthSelectionAriaLabel = "Select a month", previousMonthAriaLabel = "Previous month", previousYearAriaLabel = "Previous year", nextMonthAriaLabel = "Next month", nextYearAriaLabel = "Next year", } = props;
13
+ const prevRef = React.useRef(null);
14
+ const nextRef = React.useRef(null);
15
+ React.useEffect(() => {
16
+ if (!isFirstMonth)
17
+ return;
18
+ if (document.activeElement !== prevRef.current)
19
+ return;
20
+ const targetEl = nextRef.current || monthTitleRef.current;
21
+ onNextFrame(() => {
22
+ targetEl === null || targetEl === void 0 ? void 0 : targetEl.focus();
23
+ });
24
+ }, [isFirstMonth, monthTitleRef]);
25
+ React.useEffect(() => {
26
+ if (!isLastMonth)
27
+ return;
28
+ if (document.activeElement !== nextRef.current)
29
+ return;
30
+ const targetEl = prevRef.current || monthTitleRef.current;
31
+ onNextFrame(() => {
32
+ targetEl === null || targetEl === void 0 ? void 0 : targetEl.focus();
33
+ });
34
+ }, [isLastMonth, monthTitleRef]);
35
+ return (React.createElement(View, { direction: "row", gap: 2, align: "center" },
36
+ React.createElement(Hidden, { visibility: true, hide: isFirstMonth },
37
+ React.createElement("div", { className: s.control },
38
+ React.createElement(Button, { variant: "ghost", icon: IconChevronLeft, onClick: onPreviousClick, attributes: {
39
+ ref: prevRef,
40
+ "aria-label": selectionMode === "date" ? previousMonthAriaLabel : previousYearAriaLabel,
41
+ } }))),
42
+ React.createElement(View.Item, { grow: true },
43
+ selectionMode === "date" && (React.createElement(Button, { fullWidth: true, variant: "ghost", onClick: onMonthTitleClick, attributes: { ref: monthTitleRef } },
44
+ renderSelectedMonthLabel
45
+ ? renderSelectedMonthLabel({ date: monthDate })
46
+ : monthDate.toLocaleDateString("en-US", { month: "long", year: "numeric" }),
47
+ React.createElement(HiddenVisually, null, monthSelectionAriaLabel))),
48
+ selectionMode === "month" && (React.createElement(Text, { align: "center", weight: "medium" }, monthDate.toLocaleDateString("en-US", { year: "numeric" })))),
49
+ React.createElement(Hidden, { visibility: true, hide: isLastMonth },
50
+ React.createElement("div", { className: s.control },
51
+ React.createElement(Button, { variant: "ghost", icon: IconChevronRight, onClick: onNextClick, attributes: {
52
+ ref: nextRef,
53
+ "aria-label": selectionMode === "date" ? nextMonthAriaLabel : nextYearAriaLabel,
54
+ } })))));
55
+ };
56
+ export default CalendarControls;
@@ -0,0 +1,4 @@
1
+ import React from "react";
2
+ import type * as T from "./Calendar.types";
3
+ declare const CalendarDate: (props: T.DateProps) => React.JSX.Element;
4
+ export default CalendarDate;
@@ -0,0 +1,58 @@
1
+ "use client";
2
+ import React from "react";
3
+ import Actionable from "../Actionable/index.js";
4
+ import { classNames } from "../../utilities/helpers.js";
5
+ import { getLocalISODate } from "./Calendar.utils.js";
6
+ import s from "./Calendar.module.css";
7
+ const CalendarDate = (props) => {
8
+ const { date, startValue, endValue, isActiveStart, isActiveEnd, disabled, focusable, onChange, range, hoveredDate, onDateHover, onDateHoverEnd, renderAriaLabel, } = props;
9
+ if (!date)
10
+ return React.createElement("td", { className: s.cell, "aria-hidden": "true" });
11
+ const inRange = startValue &&
12
+ startValue < date &&
13
+ ((endValue && endValue > date) || (hoveredDate && !endValue && hoveredDate > date));
14
+ const dateClassNames = classNames([
15
+ s.cell,
16
+ !range && isActiveStart && s["cell--active-single"],
17
+ isActiveStart && s["cell--active-start"],
18
+ (isActiveEnd ||
19
+ (!endValue && isActiveStart && !(hoveredDate && startValue && hoveredDate > startValue))) &&
20
+ s["cell--active-end"],
21
+ inRange && s["cell--in-range"],
22
+ ]);
23
+ const handleClick = () => {
24
+ if (!range) {
25
+ onChange === null || onChange === void 0 ? void 0 : onChange({ value: date });
26
+ return;
27
+ }
28
+ const bothDatesSelected = startValue && endValue;
29
+ const noneDatesSelected = !startValue && !endValue;
30
+ const selectingBeforeStart = startValue && date < startValue;
31
+ const selectingStart = bothDatesSelected || noneDatesSelected || selectingBeforeStart;
32
+ const start = selectingStart ? date : startValue;
33
+ const end = !selectingStart ? date : null;
34
+ onChange === null || onChange === void 0 ? void 0 : onChange({ value: { start, end } });
35
+ };
36
+ const handleMouseEnter = () => {
37
+ onDateHover(date);
38
+ };
39
+ const handleMouseLeave = () => {
40
+ onDateHoverEnd(date);
41
+ };
42
+ return (React.createElement("td", { className: dateClassNames, role: disabled ? "presentation" : "gridcell" },
43
+ React.createElement(Actionable, { fullWidth: true, insetFocus: true, className: s["cell-button"], disabled: disabled, onClick: handleClick, attributes: {
44
+ role: "checkbox",
45
+ tabIndex: focusable ? 0 : -1,
46
+ "aria-hidden": disabled,
47
+ "aria-label": renderAriaLabel
48
+ ? renderAriaLabel({ date })
49
+ : date.toLocaleDateString("en-us", { month: "long", day: "numeric", weekday: "long" }),
50
+ "aria-checked": isActiveStart || isActiveEnd,
51
+ "data-rs-date": getLocalISODate({ date }),
52
+ onMouseEnter: handleMouseEnter,
53
+ onMouseLeave: handleMouseLeave,
54
+ onFocus: handleMouseEnter,
55
+ onBlur: handleMouseLeave,
56
+ } }, date.getDate())));
57
+ };
58
+ export default CalendarDate;
@@ -0,0 +1,4 @@
1
+ import React from "react";
2
+ import type * as T from "./Calendar.types";
3
+ declare const CalendarMonth: (props: T.MonthProps) => React.JSX.Element;
4
+ export default CalendarMonth;
@@ -0,0 +1,54 @@
1
+ "use client";
2
+ import React from "react";
3
+ import { getMonthWeeks, getWeekdayNames, getLocalISODate } from "./Calendar.utils.js";
4
+ import CalendarDate from "./CalendarDate.js";
5
+ import s from "./Calendar.module.css";
6
+ const CalendarMonth = (props) => {
7
+ const { date, value, onChange, min, max, range, firstWeekDay, hoveredDate, onDateHover, onDateHoverEnd, renderWeekDay, renderDateAriaLabel, } = props;
8
+ let foundFocusableDate = false;
9
+ const month = date.getMonth();
10
+ const weeks = getMonthWeeks({ date, firstWeekDay });
11
+ const weekdayNames = getWeekdayNames({ firstWeekDay, renderWeekDay });
12
+ return (React.createElement("table", { className: s.selection, role: "grid" },
13
+ React.createElement("thead", { "aria-hidden": "true" },
14
+ React.createElement("tr", null, weekdayNames.map((dayName) => (React.createElement("th", { className: s.weekday, key: dayName, scope: "col" }, dayName))))),
15
+ React.createElement("tbody", null, weeks.map((week) => {
16
+ var _a;
17
+ const key = [month, (_a = week[0]) === null || _a === void 0 ? void 0 : _a.getDate()].filter(Boolean).join("-");
18
+ return (React.createElement("tr", { key: key, className: s.row }, week.map((date, index) => {
19
+ const disabled = !!date && ((min && date < min) || (max && date > max));
20
+ const month = date === null || date === void 0 ? void 0 : date.getMonth();
21
+ const today = new Date();
22
+ const isoToday = getLocalISODate({ date: today });
23
+ const startValue = value && "start" in value ? value.start : value;
24
+ const endValue = value && "end" in value ? value.end : value;
25
+ const isoDate = date && getLocalISODate({ date });
26
+ const isoStartValue = startValue && getLocalISODate({ date: startValue });
27
+ const isoEndValue = endValue && getLocalISODate({ date: endValue });
28
+ const isActiveStart = !!isoDate && !!isoStartValue && isoDate === isoStartValue;
29
+ const isActiveEnd = !!isoDate && !!isoEndValue && isoDate === isoEndValue;
30
+ /**
31
+ * Decide if date has to be focusable with Tab (only one date should be)
32
+ * 1. If there is a selected value - it's focusable
33
+ * 2. Otherwise, today's date is focusable
34
+ * 3. Otherwise, first non-disabled date is focusable
35
+ */
36
+ let focusable = false;
37
+ if (!foundFocusableDate && date) {
38
+ if (!!startValue && startValue.getMonth() === (date === null || date === void 0 ? void 0 : date.getMonth())) {
39
+ focusable = +startValue === +date;
40
+ }
41
+ else if (isoDate && month === today.getMonth()) {
42
+ focusable = isoDate >= isoToday && !disabled;
43
+ }
44
+ else {
45
+ focusable = !disabled;
46
+ }
47
+ }
48
+ if (focusable)
49
+ foundFocusableDate = true;
50
+ return (React.createElement(CalendarDate, { date: date, key: index, disabled: disabled, range: range, focusable: focusable, startValue: startValue, endValue: endValue, isActiveStart: isActiveStart, isActiveEnd: isActiveEnd, onChange: onChange, hoveredDate: hoveredDate, onDateHover: onDateHover, onDateHoverEnd: onDateHoverEnd, renderAriaLabel: renderDateAriaLabel }));
51
+ })));
52
+ }))));
53
+ };
54
+ export default CalendarMonth;
@@ -0,0 +1,4 @@
1
+ import React from "react";
2
+ import type * as T from "./Calendar.types";
3
+ declare const CalendarUncontrolled: (props: T.UncontrolledProps & T.BaseProps) => React.JSX.Element;
4
+ export default CalendarUncontrolled;
@@ -0,0 +1,29 @@
1
+ "use client";
2
+ var __rest = (this && this.__rest) || function (s, e) {
3
+ var t = {};
4
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
5
+ t[p] = s[p];
6
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
7
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
8
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
9
+ t[p[i]] = s[p[i]];
10
+ }
11
+ return t;
12
+ };
13
+ import React from "react";
14
+ import CalendarControlled from "./CalendarControlled.js";
15
+ const CalendarUncontrolled = (props) => {
16
+ const { onChange, defaultValue, range } = props, controlledProps = __rest(props, ["onChange", "defaultValue", "range"]);
17
+ const [value, setValue] = React.useState(defaultValue || null);
18
+ if (range) {
19
+ return (React.createElement(CalendarControlled, Object.assign({ range: true }, controlledProps, { value: value, onChange: (args) => {
20
+ setValue(args.value);
21
+ onChange === null || onChange === void 0 ? void 0 : onChange(args);
22
+ } })));
23
+ }
24
+ return (React.createElement(CalendarControlled, Object.assign({}, controlledProps, { value: value, onChange: (args) => {
25
+ setValue(args.value);
26
+ onChange === null || onChange === void 0 ? void 0 : onChange(args);
27
+ } })));
28
+ };
29
+ export default CalendarUncontrolled;
@@ -0,0 +1,4 @@
1
+ import React from "react";
2
+ import type * as T from "./Calendar.types";
3
+ declare const CalendarYear: (props: T.YearProps) => React.JSX.Element;
4
+ export default CalendarYear;
@@ -0,0 +1,45 @@
1
+ import React from "react";
2
+ import Actionable from "../Actionable/index.js";
3
+ import { onNextFrame } from "../../utilities/animation.js";
4
+ import { getMonthNames } from "./Calendar.utils.js";
5
+ import s from "./Calendar.module.css";
6
+ const MONTHS_PER_ROW = 3;
7
+ const CalendarYear = (props) => {
8
+ const { renderMonthLabel, renderMonthAriaLabel, monthDate, min, max, onMonthClick } = props;
9
+ const rootRef = React.useRef(null);
10
+ const monthNames = getMonthNames({ renderMonthLabel });
11
+ const rows = [];
12
+ for (let i = 0; i < monthNames.length; i += MONTHS_PER_ROW) {
13
+ const chunk = monthNames.slice(i, i + MONTHS_PER_ROW);
14
+ rows.push(chunk);
15
+ }
16
+ React.useEffect(() => {
17
+ var _a;
18
+ const focusableEl = (_a = rootRef.current) === null || _a === void 0 ? void 0 : _a.querySelector('[tabIndex="0"]');
19
+ // Waitinf for key press events to finish before focusing the month
20
+ // To avoid it trigger the month click
21
+ onNextFrame(() => {
22
+ focusableEl === null || focusableEl === void 0 ? void 0 : focusableEl.focus();
23
+ });
24
+ }, []);
25
+ return (React.createElement("table", { ref: rootRef, role: "grid", className: s.selection },
26
+ React.createElement("tbody", null, rows.map((row, i) => (React.createElement("tr", { key: i, className: s.row }, row.map((name, j) => {
27
+ const monthIndex = i * MONTHS_PER_ROW + j;
28
+ const date = new Date(monthDate.getFullYear(), monthIndex);
29
+ const isOutsideMinBound = min && min.getFullYear() >= date.getFullYear() && min.getMonth() > date.getMonth();
30
+ const isOutsideMaxBound = max && max.getFullYear() <= date.getFullYear() && max.getMonth() < date.getMonth();
31
+ const disabled = isOutsideMaxBound || isOutsideMinBound;
32
+ return (React.createElement("td", { key: name, role: disabled ? "presentation" : "gridcell", className: s.cell },
33
+ React.createElement(Actionable, { fullWidth: true, insetFocus: true, className: s["cell-button"], disabled: disabled, onClick: () => onMonthClick(monthIndex), attributes: {
34
+ tabIndex: monthIndex === monthDate.getMonth() ? 0 : -1,
35
+ "aria-hidden": disabled,
36
+ "aria-label": renderMonthAriaLabel
37
+ ? renderMonthAriaLabel({ month: monthIndex })
38
+ : name,
39
+ "data-rs-date": `${monthDate.getFullYear()}-${(monthIndex + 1)
40
+ .toString()
41
+ .padStart(2, "0")}`,
42
+ } }, name)));
43
+ })))))));
44
+ };
45
+ export default CalendarYear;
@@ -0,0 +1,2 @@
1
+ export { default } from "./Calendar";
2
+ export type { Props as CalendarProps } from "./Calendar.types";
@@ -0,0 +1 @@
1
+ export { default } from "./Calendar.js";
@@ -0,0 +1,9 @@
1
+ import React from "react";
2
+ declare const _default: {
3
+ title: string;
4
+ };
5
+ export default _default;
6
+ export declare const base: () => React.JSX.Element;
7
+ export declare const selection: () => React.JSX.Element;
8
+ export declare const boundaries: () => React.JSX.Element;
9
+ export declare const translation: () => React.JSX.Element;