diff --git a/package/src/calendar-types.ts b/package/src/calendar-types.ts index 2aaf065..3ff8d47 100644 --- a/package/src/calendar-types.ts +++ b/package/src/calendar-types.ts @@ -53,7 +53,9 @@ interface CalendarProviderPropsBase { */ locale?: string; /** - * Custom Temporal namespace for environments without native Temporal support. + * The `Temporal` implementation to use. Not bundled — provide a `Temporal` + * namespace (e.g. from `temporal-polyfill` or `@js-temporal/polyfill`) unless + * the host exposes native `Temporal`. See `RootOwnProps.temporal` for links. */ temporal?: TemporalNamespace; /** diff --git a/package/src/formats/date.ts b/package/src/formats/date.ts index cd27338..dd51723 100644 --- a/package/src/formats/date.ts +++ b/package/src/formats/date.ts @@ -99,8 +99,6 @@ export { computeWeeksInWindow } from "../compute-weeks-in-window"; export { resolveFirstWeek, resolveFirstWeekSpec } from "../resolve-first-week"; -export { Temporal } from "../temporal-polyfill"; - export { useCalendarStable, useCalendarState } from "../calendar-context"; export { useMonthViewStable, useMonthViewState } from "../month-view-context"; diff --git a/package/src/formats/object.ts b/package/src/formats/object.ts index 88bb4a1..6418475 100644 --- a/package/src/formats/object.ts +++ b/package/src/formats/object.ts @@ -99,8 +99,6 @@ export { computeWeeksInWindow } from "../compute-weeks-in-window"; export { resolveFirstWeek, resolveFirstWeekSpec } from "../resolve-first-week"; -export { Temporal } from "../temporal-polyfill"; - export { useCalendarStable, useCalendarState } from "../calendar-context"; export { useMonthViewStable, useMonthViewState } from "../month-view-context"; diff --git a/package/src/formats/plain-date-time.ts b/package/src/formats/plain-date-time.ts index fe2aca2..cad6d6c 100644 --- a/package/src/formats/plain-date-time.ts +++ b/package/src/formats/plain-date-time.ts @@ -99,8 +99,6 @@ export { computeWeeksInWindow } from "../compute-weeks-in-window"; export { resolveFirstWeek, resolveFirstWeekSpec } from "../resolve-first-week"; -export { Temporal } from "../temporal-polyfill"; - export { useCalendarStable, useCalendarState } from "../calendar-context"; export { useMonthViewStable, useMonthViewState } from "../month-view-context"; diff --git a/package/src/formats/plain-date.ts b/package/src/formats/plain-date.ts index 505b9b5..d9154b4 100644 --- a/package/src/formats/plain-date.ts +++ b/package/src/formats/plain-date.ts @@ -99,8 +99,6 @@ export { computeWeeksInWindow } from "../compute-weeks-in-window"; export { resolveFirstWeek, resolveFirstWeekSpec } from "../resolve-first-week"; -export { Temporal } from "../temporal-polyfill"; - export { useCalendarStable, useCalendarState } from "../calendar-context"; export { useMonthViewStable, useMonthViewState } from "../month-view-context"; diff --git a/package/src/formats/plain-month-day.ts b/package/src/formats/plain-month-day.ts index 3bdcd5f..6c985a7 100644 --- a/package/src/formats/plain-month-day.ts +++ b/package/src/formats/plain-month-day.ts @@ -99,8 +99,6 @@ export { computeWeeksInWindow } from "../compute-weeks-in-window"; export { resolveFirstWeek, resolveFirstWeekSpec } from "../resolve-first-week"; -export { Temporal } from "../temporal-polyfill"; - export { useCalendarStable, useCalendarState } from "../calendar-context"; export { useMonthViewStable, useMonthViewState } from "../month-view-context"; diff --git a/package/src/formats/plain-year-month.ts b/package/src/formats/plain-year-month.ts index 1f64b39..1e18aae 100644 --- a/package/src/formats/plain-year-month.ts +++ b/package/src/formats/plain-year-month.ts @@ -99,8 +99,6 @@ export { computeWeeksInWindow } from "../compute-weeks-in-window"; export { resolveFirstWeek, resolveFirstWeekSpec } from "../resolve-first-week"; -export { Temporal } from "../temporal-polyfill"; - export { useCalendarStable, useCalendarState } from "../calendar-context"; export { useMonthViewStable, useMonthViewState } from "../month-view-context"; diff --git a/package/src/formats/zoned-date-time.ts b/package/src/formats/zoned-date-time.ts index f3f79a5..85b833b 100644 --- a/package/src/formats/zoned-date-time.ts +++ b/package/src/formats/zoned-date-time.ts @@ -99,8 +99,6 @@ export { computeWeeksInWindow } from "../compute-weeks-in-window"; export { resolveFirstWeek, resolveFirstWeekSpec } from "../resolve-first-week"; -export { Temporal } from "../temporal-polyfill"; - export { useCalendarStable, useCalendarState } from "../calendar-context"; export { useMonthViewStable, useMonthViewState } from "../month-view-context"; diff --git a/package/src/index.ts b/package/src/index.ts index a616154..e99024a 100644 --- a/package/src/index.ts +++ b/package/src/index.ts @@ -36,7 +36,6 @@ export { export { computePreviewRange } from "./root-selection"; export { computeWeeksInWindow } from "./compute-weeks-in-window"; export { resolveFirstWeek, resolveFirstWeekSpec } from "./resolve-first-week"; -export { Temporal } from "./temporal-polyfill"; export { useCalendarStable, useCalendarState } from "./calendar-context"; export { useMonthViewStable, useMonthViewState } from "./month-view-context"; export { useViewContext } from "./view-context"; diff --git a/package/src/month-view-types.ts b/package/src/month-view-types.ts index 25a2543..5954506 100644 --- a/package/src/month-view-types.ts +++ b/package/src/month-view-types.ts @@ -33,15 +33,19 @@ export interface MonthViewRootProps { overflowBehavior?: MonthOverflowBehavior | undefined; /** * The controlled visible month. When provided, the component is controlled. + * + * Interpreted in the ISO calendar (the year/month are read as ISO values). + * The `locale` only affects how the month is displayed, so this value + * round-trips directly with {@link onMonthChange}. */ month?: Temporal.PlainYearMonth | undefined; /** - * The initial visible month (uncontrolled). + * The initial visible month (uncontrolled). Interpreted in the ISO calendar. */ defaultMonth?: Temporal.PlainYearMonth | undefined; /** * Called when the visible month changes via navigation or focus movement. - * Not called on initial mount. + * Not called on initial mount. The argument is an ISO `PlainYearMonth`. */ onMonthChange?: ((month: Temporal.PlainYearMonth) => void) | undefined; /** React children. */ diff --git a/package/src/month-view.test.tsx b/package/src/month-view.test.tsx index 1bdb1ac..1dcabea 100644 --- a/package/src/month-view.test.tsx +++ b/package/src/month-view.test.tsx @@ -1504,6 +1504,135 @@ describe("numberOfMonths", () => { }); }); +describe("non-Gregorian locale (th-TH)", () => { + // th-TH defaults to the Buddhist calendar (ISO year + 543). All + // PlainYearMonth values the component exposes must be ISO; the locale + // calendar only affects display. + const thProps = { ...defaultProps, locale: "th-TH" } as const; + const march15 = Temporal.PlainDate.from("2026-03-15"); + + /** Captures rootState.viewing from MonthView context. */ + function ViewingCapture({ + onCapture, + }: { + onCapture: (viewing: Temporal.PlainYearMonth) => void; + }) { + const { rootState } = useMonthViewState(); + onCapture(rootState.viewing as Temporal.PlainYearMonth); + return null; + } + + it("onMonthChange emits an ISO PlainYearMonth, not the locale calendar", () => { + const onMonthChange = vi.fn(); + const { container, unmount } = render( + + + , + ); + + act(() => { + container + .querySelector('[data-testid="next"]')! + .dispatchEvent(new MouseEvent("click", { bubbles: true })); + }); + + expect(onMonthChange).toHaveBeenCalledTimes(1); + const arg = onMonthChange.mock.calls[0]![0]; + // ISO April 2026 — NOT Buddhist-2026 (which is ISO 1483-06). + expect(arg.toString()).toBe("2026-04"); + expect(arg.year).toBe(2026); + expect(arg.month).toBe(4); + + unmount(); + }); + + it("rootState.viewing is an ISO PlainYearMonth", () => { + let viewing: Temporal.PlainYearMonth | undefined; + const { unmount } = render( + + { + viewing = v; + }} + /> + , + ); + + expect(viewing!.toString()).toBe("2026-03"); + + unmount(); + }); + + it("NavButtonState.target is an ISO PlainYearMonth", () => { + let nextTarget: Temporal.PlainYearMonth | undefined; + const { unmount } = render( + + { + nextTarget = state.target; + return