@viasat/beam-react 2.74.0 → 2.75.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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,13 @@
1
+ ## 2.75.0 (2026-09-24)
2
+
3
+ ### 🚀 Features
4
+
5
+ - **Calendar:** Month navigation header ([#1436](https://git.viasat.com/vega/Beam/pull/1436))
6
+
7
+ ### ❤️ Thank You
8
+
9
+ - Roman-Ionita, Alin
10
+
1
11
  ## 2.74.0 (2026-09-24)
2
12
 
3
13
  ### 🚀 Features
@@ -1 +1 @@
1
- .bm-calendar{inline-size:-moz-fit-content;inline-size:fit-content}.bm-calendar__visually-hidden{clip:rect(0,0,0,0);border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.bm-calendar__grid{border-collapse:collapse}.bm-calendar__day{box-sizing:border-box;inline-size:var(--bm-sem-size-height-md);block-size:var(--bm-sem-size-height-sm);font:var(--bm-sem-typo-label-xs);color:var(--bm-sem-color-text-secondary);text-align:center}.bm-calendar__date{padding:0}.bm-calendar__week+.bm-calendar__week>.bm-calendar__date{padding-block-start:var(--bm-sem-space-25)}.bm-calendar__date-button{box-sizing:border-box;inline-size:var(--bm-sem-size-height-md);block-size:var(--bm-sem-size-height-md);border-radius:var(--bm-sem-radius-round);font:var(--bm-sem-typo-body-sm);color:var(--bm-sem-color-text-primary);cursor:default;background-color:#0000;border:none;justify-content:center;align-items:center;padding:0;display:flex;position:relative}.bm-calendar__date[data-outside-month=true] .bm-calendar__date-button{color:var(--bm-sem-color-text-secondary)}
1
+ .bm-calendar{inline-size:-moz-fit-content;inline-size:fit-content}.bm-calendar__visually-hidden{clip:rect(0,0,0,0);border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.bm-calendar__header{block-size:var(--bm-sem-size-height-md);justify-content:space-between;align-items:center;display:flex}[dir=rtl] .bm-calendar__header .bm-icon{transform:rotate(180deg)}.bm-calendar__header-label{font:var(--bm-sem-typo-label-md);color:var(--bm-sem-color-text-primary)}.bm-calendar__grid{border-collapse:collapse}.bm-calendar__day{box-sizing:border-box;inline-size:var(--bm-sem-size-height-md);block-size:var(--bm-sem-size-height-sm);font:var(--bm-sem-typo-label-xs);color:var(--bm-sem-color-text-secondary);text-align:center}.bm-calendar__dates[data-nav-direction]{animation:.25s ease-out bm-calendar-month-enter}@media (prefers-reduced-motion:reduce){.bm-calendar__dates[data-nav-direction]{animation:none}}.bm-calendar__dates[data-nav-direction=next]{--bm-calendar-month-enter-offset:var(--bm-sem-space-50)}.bm-calendar__dates[data-nav-direction=previous],[dir=rtl] .bm-calendar__dates[data-nav-direction=next]{--bm-calendar-month-enter-offset:calc(0px - var(--bm-sem-space-50))}[dir=rtl] .bm-calendar__dates[data-nav-direction=previous]{--bm-calendar-month-enter-offset:var(--bm-sem-space-50)}.bm-calendar__date{padding:0}.bm-calendar__week+.bm-calendar__week>.bm-calendar__date{padding-block-start:var(--bm-sem-space-25)}.bm-calendar__date-button{box-sizing:border-box;inline-size:var(--bm-sem-size-height-md);block-size:var(--bm-sem-size-height-md);border-radius:var(--bm-sem-radius-round);font:var(--bm-sem-typo-body-sm);color:var(--bm-sem-color-text-primary);cursor:default;background-color:#0000;border:none;justify-content:center;align-items:center;padding:0;display:flex;position:relative}.bm-calendar__date[data-outside-month=true] .bm-calendar__date-button{color:var(--bm-sem-color-text-secondary)}@keyframes bm-calendar-month-enter{0%{opacity:0;transform:translateX(var(--bm-calendar-month-enter-offset,0))}to{opacity:1;transform:none}}
@@ -1,23 +1,31 @@
1
1
  import "../assets/calendar.css";
2
2
  import { g as e } from "./classNames.koX0H7D0.js";
3
- const d = "calendar", { baseClassNamePrefix: n, classModifierPrefix: t, subElementClassPrefix: a } = e(d), r = {
3
+ const d = "calendar", { baseClassNamePrefix: n, classModifierPrefix: s, subElementClassPrefix: a } = e(d), t = {
4
+ header: `${a}header`,
5
+ headerLabel: `${a}header-label`,
4
6
  grid: `${a}grid`,
5
7
  day: `${a}day`,
6
8
  visuallyHidden: `${a}visually-hidden`,
9
+ dates: `${a}dates`,
7
10
  week: `${a}week`,
8
11
  date: `${a}date`,
9
12
  dateButton: `${a}date-button`
10
13
  }, _ = {
11
14
  "bm-calendar": "bm-calendar",
12
15
  "bm-calendar__visually-hidden": "bm-calendar__visually-hidden",
16
+ "bm-calendar__header": "bm-calendar__header",
17
+ "bm-icon": "bm-icon",
18
+ "bm-calendar__header-label": "bm-calendar__header-label",
13
19
  "bm-calendar__grid": "bm-calendar__grid",
14
20
  "bm-calendar__day": "bm-calendar__day",
21
+ "bm-calendar__dates": "bm-calendar__dates",
22
+ "bm-calendar-month-enter": "bm-calendar-month-enter",
15
23
  "bm-calendar__date": "bm-calendar__date",
16
24
  "bm-calendar__week": "bm-calendar__week",
17
25
  "bm-calendar__date-button": "bm-calendar__date-button"
18
26
  };
19
27
  export {
20
- r as a,
28
+ t as a,
21
29
  n as b,
22
30
  _ as s
23
31
  };
@@ -0,0 +1 @@
1
+ var s=require("../assets/calendar.css");const e=require("./classNames.CEoAKlth.js"),d="calendar",{baseClassNamePrefix:l,classModifierPrefix:t,subElementClassPrefix:a}=e.getBEMClassNames(d),r={header:`${a}header`,headerLabel:`${a}header-label`,grid:`${a}grid`,day:`${a}day`,visuallyHidden:`${a}visually-hidden`,dates:`${a}dates`,week:`${a}week`,date:`${a}date`,dateButton:`${a}date-button`},n={"bm-calendar":"bm-calendar","bm-calendar__visually-hidden":"bm-calendar__visually-hidden","bm-calendar__header":"bm-calendar__header","bm-icon":"bm-icon","bm-calendar__header-label":"bm-calendar__header-label","bm-calendar__grid":"bm-calendar__grid","bm-calendar__day":"bm-calendar__day","bm-calendar__dates":"bm-calendar__dates","bm-calendar-month-enter":"bm-calendar-month-enter","bm-calendar__date":"bm-calendar__date","bm-calendar__week":"bm-calendar__week","bm-calendar__date-button":"bm-calendar__date-button"};exports.baseClassNamePrefix=l;exports.staticCalendarClassNames=r;exports.styles=n;
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s=require("react/jsx-runtime"),m=require("clsx"),n=require("react"),e=require("../../../chunks/calendar.module.D09fpoRh.js"),_=require("./Calendar.context.cjs.js"),t=require("./Calendar.utils.cjs.js"),r=n.forwardRef(function({date:a,className:i,"aria-label":d,...o},c){const{locale:l,visibleMonth:u}=_.useCalendar(),C=!t.isSameMonth(a,u);return s.jsxs("td",{...o,ref:c,className:m(e.styles[e.staticCalendarClassNames.date],i),"data-outside-month":C||void 0,children:[s.jsx("span",{className:e.styles[e.staticCalendarClassNames.dateButton],"aria-hidden":"true",children:t.formatDayNumber(a,l)}),s.jsx("span",{className:e.styles[e.staticCalendarClassNames.visuallyHidden],children:d??t.getDateLabel(a,l)})]})});r.displayName="CalendarDate";const b=n.memo(r);exports.CalendarDate=b;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s=require("react/jsx-runtime"),m=require("clsx"),n=require("react"),e=require("../../../chunks/calendar.module.D0wrnDz0.js"),_=require("./Calendar.context.cjs.js"),t=require("./Calendar.utils.cjs.js"),r=n.forwardRef(function({date:a,className:i,"aria-label":d,...o},c){const{locale:l,visibleMonth:u}=_.useCalendar(),C=!t.isSameMonth(a,u);return s.jsxs("td",{...o,ref:c,className:m(e.styles[e.staticCalendarClassNames.date],i),"data-outside-month":C||void 0,children:[s.jsx("span",{className:e.styles[e.staticCalendarClassNames.dateButton],"aria-hidden":"true",children:t.formatDayNumber(a,l)}),s.jsx("span",{className:e.styles[e.staticCalendarClassNames.visuallyHidden],children:d??t.getDateLabel(a,l)})]})});r.displayName="CalendarDate";const b=n.memo(r);exports.CalendarDate=b;
@@ -1,7 +1,7 @@
1
1
  import { jsxs as f, jsx as r } from "react/jsx-runtime";
2
2
  import p from "clsx";
3
3
  import { forwardRef as u, memo as h } from "react";
4
- import { s as e, a as t } from "../../../chunks/calendar.module.CKxTOiJx.js";
4
+ import { s as e, a as t } from "../../../chunks/calendar.module.CXGuMNJB.js";
5
5
  import { useCalendar as C } from "./Calendar.context.es.js";
6
6
  import { isSameMonth as D, formatDayNumber as N, getDateLabel as b } from "./Calendar.utils.es.js";
7
7
  const o = u(
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),o=require("clsx"),u=require("react"),a=require("../../../chunks/calendar.module.D09fpoRh.js");require("../../../chunks/constants.DLsDVPyH.js");const t=require("../../../chunks/dates.CVW08OQ2.js"),_=require("./Calendar.Date.cjs.js"),y=require("./Calendar.Days.cjs.js"),C=require("./Calendar.context.cjs.js"),n=u.forwardRef(function({className:l,...i},c){const{weeks:d}=C.useCalendar();return e.jsxs("table",{...i,ref:c,className:o(a.styles[a.staticCalendarClassNames.grid],l),children:[e.jsx(y.Days,{}),e.jsx("tbody",{children:d.map(s=>e.jsx("tr",{className:a.styles[a.staticCalendarClassNames.week],children:s.map(r=>e.jsx(_.CalendarDate,{date:r},t.dateToDayKey(r)))},t.dateToDayKey(s[0])))})]})});n.displayName="Dates";exports.Dates=n;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("react/jsx-runtime"),C=require("clsx"),m=require("react"),e=require("../../../chunks/calendar.module.D0wrnDz0.js");require("../../../chunks/constants.DLsDVPyH.js");const s=require("../../../chunks/dates.CVW08OQ2.js"),_=require("./Calendar.Date.cjs.js"),D=require("./Calendar.Days.cjs.js"),b=require("./Calendar.context.cjs.js"),l=m.forwardRef(function({className:n,...i},d){const{weeks:c,visibleMonth:o,navDirection:u,monthLabelId:y}=b.useCalendar();return a.jsxs("table",{"aria-labelledby":y,...i,ref:d,className:C(e.styles[e.staticCalendarClassNames.grid],n),children:[a.jsx(D.Days,{}),a.jsx("tbody",{"data-nav-direction":u??void 0,className:e.styles[e.staticCalendarClassNames.dates],children:c.map(t=>a.jsx("tr",{className:e.styles[e.staticCalendarClassNames.week],children:t.map(r=>a.jsx(_.CalendarDate,{date:r},s.dateToDayKey(r)))},s.dateToDayKey(t[0])))},s.dateToDayKey(o))]})});l.displayName="Dates";exports.Dates=l;
@@ -1,22 +1,44 @@
1
- import { jsxs as f, jsx as r } from "react/jsx-runtime";
2
- import d from "clsx";
3
- import { forwardRef as n } from "react";
4
- import { s as e, a as o } from "../../../chunks/calendar.module.CKxTOiJx.js";
1
+ import { jsxs as f, jsx as a } from "react/jsx-runtime";
2
+ import y from "clsx";
3
+ import { forwardRef as D } from "react";
4
+ import { s as r, a as e } from "../../../chunks/calendar.module.CXGuMNJB.js";
5
5
  import "../../../chunks/constants.XFX4nOSf.js";
6
- import { d as t } from "../../../chunks/dates.NqdbQ2fR.js";
7
- import { CalendarDate as c } from "./Calendar.Date.es.js";
8
- import { Days as y } from "./Calendar.Days.es.js";
9
- import { useCalendar as D } from "./Calendar.context.es.js";
10
- const x = n(
6
+ import { d as s } from "../../../chunks/dates.NqdbQ2fR.js";
7
+ import { CalendarDate as b } from "./Calendar.Date.es.js";
8
+ import { Days as h } from "./Calendar.Days.es.js";
9
+ import { useCalendar as N } from "./Calendar.context.es.js";
10
+ const v = D(
11
11
  function({ className: m, ...i }, l) {
12
- const { weeks: p } = D();
13
- return /* @__PURE__ */ f("table", { ...i, ref: l, className: d(e[o.grid], m), children: [
14
- /* @__PURE__ */ r(y, {}),
15
- /* @__PURE__ */ r("tbody", { children: p.map((a) => /* @__PURE__ */ r("tr", { className: e[o.week], children: a.map((s) => /* @__PURE__ */ r(c, { date: s }, t(s))) }, t(a[0]))) })
16
- ] });
12
+ const { weeks: d, visibleMonth: n, navDirection: c, monthLabelId: p } = N();
13
+ return (
14
+ // The grid takes its name from the header's month label, so it announces
15
+ // as "July 2025 table" rather than an unnamed one. Placed before the
16
+ // spread so a consumer can still name it themselves.
17
+ /* @__PURE__ */ f(
18
+ "table",
19
+ {
20
+ "aria-labelledby": p,
21
+ ...i,
22
+ ref: l,
23
+ className: y(r[e.grid], m),
24
+ children: [
25
+ /* @__PURE__ */ a(h, {}),
26
+ /* @__PURE__ */ a(
27
+ "tbody",
28
+ {
29
+ "data-nav-direction": c ?? void 0,
30
+ className: r[e.dates],
31
+ children: d.map((t) => /* @__PURE__ */ a("tr", { className: r[e.week], children: t.map((o) => /* @__PURE__ */ a(b, { date: o }, s(o))) }, s(t[0])))
32
+ },
33
+ s(n)
34
+ )
35
+ ]
36
+ }
37
+ )
38
+ );
17
39
  }
18
40
  );
19
- x.displayName = "Dates";
41
+ v.displayName = "Dates";
20
42
  export {
21
- x as Dates
43
+ v as Dates
22
44
  };
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),m=require("react"),a=require("../../../chunks/calendar.module.D09fpoRh.js"),p=require("./Calendar.context.cjs.js"),r=require("./Calendar.utils.cjs.js"),t=m.forwardRef(function({className:n,...c},d){const{weekdayLabels:i,weekStart:s,locale:o}=p.useCalendar(),u=r.getWeekdayFullLabels(o,s);return e.jsx("thead",{...c,ref:d,className:n,children:e.jsx("tr",{children:i.map((y,l)=>e.jsxs("th",{scope:"col",className:a.styles[a.staticCalendarClassNames.day],children:[e.jsx("span",{"aria-hidden":"true",children:y}),e.jsx("span",{className:a.styles[a.staticCalendarClassNames.visuallyHidden],children:u[l]})]},r.wrapWeekday(s+l)))})})});t.displayName="Days";exports.Days=t;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),m=require("react"),a=require("../../../chunks/calendar.module.D0wrnDz0.js"),p=require("./Calendar.context.cjs.js"),r=require("./Calendar.utils.cjs.js"),t=m.forwardRef(function({className:n,...c},d){const{weekdayLabels:i,weekStart:s,locale:o}=p.useCalendar(),u=r.getWeekdayFullLabels(o,s);return e.jsx("thead",{...c,ref:d,className:n,children:e.jsx("tr",{children:i.map((y,l)=>e.jsxs("th",{scope:"col",className:a.styles[a.staticCalendarClassNames.day],children:[e.jsx("span",{"aria-hidden":"true",children:y}),e.jsx("span",{className:a.styles[a.staticCalendarClassNames.visuallyHidden],children:u[l]})]},r.wrapWeekday(s+l)))})})});t.displayName="Days";exports.Days=t;
@@ -1,6 +1,6 @@
1
1
  import { jsx as a, jsxs as p } from "react/jsx-runtime";
2
2
  import { forwardRef as f } from "react";
3
- import { s as r, a as l } from "../../../chunks/calendar.module.CKxTOiJx.js";
3
+ import { s as r, a as l } from "../../../chunks/calendar.module.CXGuMNJB.js";
4
4
  import { useCalendar as y } from "./Calendar.context.es.js";
5
5
  import { getWeekdayFullLabels as h, wrapWeekday as u } from "./Calendar.utils.es.js";
6
6
  const k = f(
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),h=require("clsx"),C=require("react"),v=require("../../../chunks/ChevronLeftCurved.JKg9pOxN.js"),m=require("../../../chunks/ChevronRightCurved.CoT-Bqyo.js"),r=require("../../../chunks/calendar.module.D0wrnDz0.js"),b=require("../../Button/Button.cjs.js"),x=require("../../Icon/Icon.cjs.js"),g=require("./Calendar.context.cjs.js"),a=({icon:o,label:t,onClick:n})=>e.jsx(b.Button,{type:"button",appearance:"neutral",kind:"ghost",size:"md",iconOnly:!0,iconBefore:e.jsx(x.Icon,{icon:o}),"aria-label":t,onClick:n}),s=C.forwardRef(function({className:t,...n},i){const{monthLabel:l,monthLabelId:c,goToPreviousMonth:u,goToNextMonth:d}=g.useCalendar();return e.jsxs("div",{...n,ref:i,className:h(r.styles[r.staticCalendarClassNames.header],t),children:[e.jsx(a,{icon:v.SvgChevronLeftCurved,label:"Previous month",onClick:u}),e.jsx("span",{id:c,"aria-live":"polite",className:r.styles[r.staticCalendarClassNames.headerLabel],children:l}),e.jsx(a,{icon:m.SvgChevronRightCurved,label:"Next month",onClick:d})]})});s.displayName="Header";exports.Header=s;
@@ -0,0 +1,15 @@
1
+ import { CalendarHeaderProps } from './Calendar.types';
2
+ /**
3
+ * Month label with previous / next arrows.
4
+ *
5
+ * The arrows are Beam `<Button>`s rather than hand-rolled, which supplies the
6
+ * Figma `neutral/ghost` treatment, the 40×40 `md` sizing, and the `StateLayer`.
7
+ * Labels are hardcoded English until `ariaLabels` arrives with I-7.
8
+ *
9
+ * The label is a live region as well as the grid's accessible name. Paging the
10
+ * month replaces the grid's contents without moving focus — the arrow keeps it
11
+ * — so nothing else would tell a screen-reader user the month changed. It
12
+ * announces on update only: the text is already in the region at mount, which
13
+ * is when assistive tech registers it, so the first paint is silent.
14
+ */
15
+ export declare const Header: import('react').ForwardRefExoticComponent<CalendarHeaderProps & import('react').RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,65 @@
1
+ import { jsxs as p, jsx as o } from "react/jsx-runtime";
2
+ import f from "clsx";
3
+ import { forwardRef as h } from "react";
4
+ import { S as u } from "../../../chunks/ChevronLeftCurved.CX7aH27X.js";
5
+ import { S as v } from "../../../chunks/ChevronRightCurved.9hi9Zc8J.js";
6
+ import { s as t, a as n } from "../../../chunks/calendar.module.CXGuMNJB.js";
7
+ import { Button as C } from "../../Button/Button.es.js";
8
+ import { Icon as b } from "../../Icon/Icon.es.js";
9
+ import { useCalendar as N } from "./Calendar.context.es.js";
10
+ const i = ({ icon: a, label: e, onClick: r }) => /* @__PURE__ */ o(
11
+ C,
12
+ {
13
+ type: "button",
14
+ appearance: "neutral",
15
+ kind: "ghost",
16
+ size: "md",
17
+ iconOnly: !0,
18
+ iconBefore: /* @__PURE__ */ o(b, { icon: a }),
19
+ "aria-label": e,
20
+ onClick: r
21
+ }
22
+ ), g = h(
23
+ function({ className: e, ...r }, s) {
24
+ const { monthLabel: m, monthLabelId: l, goToPreviousMonth: c, goToNextMonth: d } = N();
25
+ return /* @__PURE__ */ p(
26
+ "div",
27
+ {
28
+ ...r,
29
+ ref: s,
30
+ className: f(t[n.header], e),
31
+ children: [
32
+ /* @__PURE__ */ o(
33
+ i,
34
+ {
35
+ icon: u,
36
+ label: "Previous month",
37
+ onClick: c
38
+ }
39
+ ),
40
+ /* @__PURE__ */ o(
41
+ "span",
42
+ {
43
+ id: l,
44
+ "aria-live": "polite",
45
+ className: t[n.headerLabel],
46
+ children: m
47
+ }
48
+ ),
49
+ /* @__PURE__ */ o(
50
+ i,
51
+ {
52
+ icon: v,
53
+ label: "Next month",
54
+ onClick: d
55
+ }
56
+ )
57
+ ]
58
+ }
59
+ );
60
+ }
61
+ );
62
+ g.displayName = "Header";
63
+ export {
64
+ g as Header
65
+ };
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("react/jsx-runtime"),S=require("clsx"),s=require("react"),D=require("../../../chunks/calendar.module.D09fpoRh.js"),k=require("../../../chunks/classNames.CEoAKlth.js");require("../../../chunks/constants.DLsDVPyH.js");const _=require("../../../chunks/dates.CVW08OQ2.js"),O=require("../../../utils/spacing.cjs.js"),j=require("./Calendar.context.cjs.js"),v=require("./Calendar.Date.cjs.js"),y=require("./Calendar.Dates.cjs.js"),L=require("./Calendar.Days.cjs.js"),a=require("./Calendar.utils.cjs.js"),e=s.forwardRef(function({today:c,locale:m,role:p="group","aria-label":b="Calendar",className:q,...g},w){const[f,x]=O.partitionSpacingProps(g),r=m??_.DEFAULT_LOCALE,[d]=s.useState(()=>a.startOfDay(new Date)),i=_.isValidDate(c)?a.startOfDay(c).getTime():null,n=s.useMemo(()=>i===null?d:a.startOfDay(new Date(i)),[i,d]),l=s.useMemo(()=>a.startOfMonth(n),[n]),t=a.getWeekStart(r),u=a.getWeekdayLabels(r,t),C=s.useMemo(()=>a.getCalendarWeeks(l,t),[l,t]),N=s.useMemo(()=>({locale:r,today:n,visibleMonth:l,weekStart:t,weeks:C,weekdayLabels:u}),[r,n,l,t,C,u]),M=S(D.styles[D.baseClassNamePrefix],...k.generateSpacingClasses(f),q);return o.jsx(j.CalendarContext.Provider,{value:N,children:o.jsx("div",{...x,ref:w,role:p,"aria-label":b,className:M,children:o.jsx(y.Dates,{})})})});e.displayName="Calendar";e.Days=L.Days;e.Dates=y.Dates;e.Date=v.CalendarDate;e.Days.displayName="Calendar.Days";e.Dates.displayName="Calendar.Dates";e.Date.displayName="Calendar.Date";exports.Calendar=e;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("react/jsx-runtime"),j=require("clsx"),_=require("react"),p=require("../../../chunks/calendar.module.D0wrnDz0.js"),H=require("../../../chunks/classNames.CEoAKlth.js");require("../../../chunks/constants.DLsDVPyH.js");const L=require("../../../chunks/dates.CVW08OQ2.js"),S=require("../../../utils/hooks/useId.cjs.js"),k=require("../../../utils/spacing.cjs.js"),T=require("./Calendar.context.cjs.js"),I=require("./Calendar.Date.cjs.js"),D=require("./Calendar.Dates.cjs.js"),R=require("./Calendar.Days.cjs.js"),q=require("./Calendar.Header.cjs.js");require("./Calendar.utils.cjs.js");const A=require("./useCalendarGrid.cjs.js"),E=require("./useCalendarMonth.cjs.js"),e=_.forwardRef(function({today:y,onVisibleMonthChange:b,locale:m,role:w="group","aria-label":x="Calendar",className:g,...h},N){const[v,M]=k.partitionSpacingProps(h),r=m??L.DEFAULT_LOCALE,{today:n,visibleMonth:s,navDirection:t,goToPreviousMonth:l,goToNextMonth:i}=E.useCalendarMonth({today:y,onVisibleMonthChange:b}),{weekStart:o,weekdayLabels:d,weeks:c,monthLabel:u}=A.useCalendarGrid(s,r),C=S.useId(),P=_.useMemo(()=>({locale:r,today:n,visibleMonth:s,weekStart:o,weeks:c,weekdayLabels:d,monthLabel:u,monthLabelId:C,goToPreviousMonth:l,goToNextMonth:i,navDirection:t}),[r,n,s,o,c,d,u,C,l,i,t]),f=j(p.styles[p.baseClassNamePrefix],...H.generateSpacingClasses(v),g);return a.jsx(T.CalendarContext.Provider,{value:P,children:a.jsxs("div",{...M,ref:N,role:w,"aria-label":x,className:f,children:[a.jsx(q.Header,{}),a.jsx(D.Dates,{})]})})});e.displayName="Calendar";e.Header=q.Header;e.Days=R.Days;e.Dates=D.Dates;e.Date=I.CalendarDate;e.Header.displayName="Calendar.Header";e.Days.displayName="Calendar.Days";e.Dates.displayName="Calendar.Dates";e.Date.displayName="Calendar.Date";exports.Calendar=e;
@@ -2,20 +2,23 @@ import { ForwardRefExoticComponent, RefAttributes } from 'react';
2
2
  import { CalendarDate } from './Calendar.Date';
3
3
  import { Dates } from './Calendar.Dates';
4
4
  import { Days } from './Calendar.Days';
5
+ import { Header } from './Calendar.Header';
5
6
  import { CalendarProps } from './Calendar.types';
6
7
  interface CalendarComponent extends ForwardRefExoticComponent<CalendarProps & RefAttributes<HTMLDivElement>> {
8
+ Header: typeof Header;
7
9
  Days: typeof Days;
8
10
  Dates: typeof Dates;
9
11
  Date: typeof CalendarDate;
10
12
  }
11
13
  /**
12
- * A static grid of a single month, with a weekday header.
14
+ * A month grid with a header for moving between months.
13
15
  *
14
- * The root owns the layout rather than exposing the grid as composable
15
- * children: the weekday row and the date rows can't be reordered or used
16
- * apart, and Figma models the calendar's optional parts (footer, presets) as
17
- * variants rather than slots. Month navigation lands in C-2, selection in C-3,
18
- * keyboard support in C-7.
16
+ * The root owns the layout rather than exposing the parts as composable
17
+ * children: the weekday row and the date rows can't be reordered or used apart,
18
+ * Figma has no variant that hides the header, and modelling it as children
19
+ * would leave `<Calendar />` with no way to change months. Figma treats the
20
+ * genuinely optional parts — footer and presets — as variants, so those become
21
+ * props when they land.
19
22
  */
20
23
  export declare const Calendar: CalendarComponent;
21
24
  export {};
@@ -1,60 +1,91 @@
1
- import { jsx as l } from "react/jsx-runtime";
2
- import L from "clsx";
3
- import { forwardRef as S, useState as h, useMemo as r } from "react";
4
- import { s as v, b as P } from "../../../chunks/calendar.module.CKxTOiJx.js";
5
- import { a as T } from "../../../chunks/classNames.koX0H7D0.js";
1
+ import { jsx as r, jsxs as w } from "react/jsx-runtime";
2
+ import H from "clsx";
3
+ import { forwardRef as k, useMemo as S } from "react";
4
+ import { s as T, b as j } from "../../../chunks/calendar.module.CXGuMNJB.js";
5
+ import { a as A } from "../../../chunks/classNames.koX0H7D0.js";
6
6
  import "../../../chunks/constants.XFX4nOSf.js";
7
- import { i as M, D as O } from "../../../chunks/dates.NqdbQ2fR.js";
8
- import { partitionSpacingProps as W } from "../../../utils/spacing.es.js";
9
- import { CalendarContext as A } from "./Calendar.context.es.js";
10
- import { CalendarDate as E } from "./Calendar.Date.es.js";
7
+ import { D as E } from "../../../chunks/dates.NqdbQ2fR.js";
8
+ import { useId as I } from "../../../utils/hooks/useId.es.js";
9
+ import { partitionSpacingProps as F } from "../../../utils/spacing.es.js";
10
+ import { CalendarContext as G } from "./Calendar.context.es.js";
11
+ import { CalendarDate as O } from "./Calendar.Date.es.js";
11
12
  import { Dates as f } from "./Calendar.Dates.es.js";
12
- import { Days as V } from "./Calendar.Days.es.js";
13
- import { startOfDay as i, startOfMonth as j, getWeekStart as F, getWeekdayLabels as R, getCalendarWeeks as U } from "./Calendar.utils.es.js";
14
- const a = S(
13
+ import { Days as R } from "./Calendar.Days.es.js";
14
+ import { Header as C } from "./Calendar.Header.es.js";
15
+ import "./Calendar.utils.es.js";
16
+ import { useCalendarGrid as U } from "./useCalendarGrid.es.js";
17
+ import { useCalendarMonth as V } from "./useCalendarMonth.es.js";
18
+ const a = k(
15
19
  function({
16
- today: m,
17
- locale: D,
20
+ today: D,
21
+ onVisibleMonthChange: y,
22
+ locale: u,
18
23
  // Destructured with defaults rather than written after the prop spread:
19
24
  // spreading first would silently drop a caller's own `role` or
20
25
  // `aria-label`, and spreading last would let an unrelated pass-through
21
26
  // erase the group semantics. This way the caller wins explicitly.
22
- role: y = "group",
23
- "aria-label": C = "Calendar",
24
- className: g,
25
- ...u
26
- }, b) {
27
- const [N, k] = W(u), t = D ?? O, [p] = h(() => i(/* @__PURE__ */ new Date())), n = M(m) ? i(m).getTime() : null, s = r(
28
- () => n === null ? p : i(new Date(n)),
29
- [n, p]
30
- ), o = r(() => j(s), [s]), e = F(t), c = R(t, e), d = r(
31
- () => U(o, e),
32
- [o, e]
33
- ), w = r(
34
- () => ({ locale: t, today: s, visibleMonth: o, weekStart: e, weeks: d, weekdayLabels: c }),
35
- [t, s, o, e, d, c]
36
- ), x = L(
37
- v[P],
38
- ...T(N),
39
- g
27
+ role: N = "group",
28
+ "aria-label": b = "Calendar",
29
+ className: h,
30
+ ...x
31
+ }, g) {
32
+ const [v, L] = F(x), e = u ?? E, { today: t, visibleMonth: o, navDirection: s, goToPreviousMonth: m, goToNextMonth: n } = V({ today: D, onVisibleMonthChange: y }), { weekStart: i, weekdayLabels: l, weeks: d, monthLabel: p } = U(
33
+ o,
34
+ e
35
+ ), c = I(), P = S(
36
+ () => ({
37
+ locale: e,
38
+ today: t,
39
+ visibleMonth: o,
40
+ weekStart: i,
41
+ weeks: d,
42
+ weekdayLabels: l,
43
+ monthLabel: p,
44
+ monthLabelId: c,
45
+ goToPreviousMonth: m,
46
+ goToNextMonth: n,
47
+ navDirection: s
48
+ }),
49
+ [
50
+ e,
51
+ t,
52
+ o,
53
+ i,
54
+ d,
55
+ l,
56
+ p,
57
+ c,
58
+ m,
59
+ n,
60
+ s
61
+ ]
62
+ ), M = H(
63
+ T[j],
64
+ ...A(v),
65
+ h
40
66
  );
41
- return /* @__PURE__ */ l(A.Provider, { value: w, children: /* @__PURE__ */ l(
67
+ return /* @__PURE__ */ r(G.Provider, { value: P, children: /* @__PURE__ */ w(
42
68
  "div",
43
69
  {
44
- ...k,
45
- ref: b,
46
- role: y,
47
- "aria-label": C,
48
- className: x,
49
- children: /* @__PURE__ */ l(f, {})
70
+ ...L,
71
+ ref: g,
72
+ role: N,
73
+ "aria-label": b,
74
+ className: M,
75
+ children: [
76
+ /* @__PURE__ */ r(C, {}),
77
+ /* @__PURE__ */ r(f, {})
78
+ ]
50
79
  }
51
80
  ) });
52
81
  }
53
82
  );
54
83
  a.displayName = "Calendar";
55
- a.Days = V;
84
+ a.Header = C;
85
+ a.Days = R;
56
86
  a.Dates = f;
57
- a.Date = E;
87
+ a.Date = O;
88
+ a.Header.displayName = "Calendar.Header";
58
89
  a.Days.displayName = "Calendar.Days";
59
90
  a.Dates.displayName = "Calendar.Dates";
60
91
  a.Date.displayName = "Calendar.Date";
@@ -12,6 +12,11 @@ export interface CalendarProps extends MarginSpacingProps, PaddingSpacingProps,
12
12
  * @default new Date()
13
13
  */
14
14
  today?: Date;
15
+ /**
16
+ * Fires whenever the visible month changes, with the first day of the new
17
+ * month at local midnight.
18
+ */
19
+ onVisibleMonthChange?: (date: Date) => void;
15
20
  /**
16
21
  * Specify the BCP-47 locale tag driving weekday and month names, the spoken
17
22
  * date labels, and which day the week starts on (e.g. `de-DE` → Montag first,
@@ -27,6 +32,8 @@ export interface CalendarProps extends MarginSpacingProps, PaddingSpacingProps,
27
32
  */
28
33
  'aria-label'?: string;
29
34
  }
35
+ /** Which way the visible month last moved, for the enter animation. */
36
+ export type CalendarNavDirection = 'previous' | 'next';
30
37
  /**
31
38
  * Everything the sub-components need, derived once by the `Calendar` root.
32
39
  * @internal
@@ -44,7 +51,22 @@ export interface CalendarContextValue {
44
51
  weeks: Date[][];
45
52
  /** Abbreviated weekday names, ordered from `weekStart`. */
46
53
  weekdayLabels: ReadonlyArray<string>;
54
+ /** Localized "Month Year" label for `visibleMonth`. */
55
+ monthLabel: string;
56
+ /**
57
+ * `id` of the element rendering `monthLabel`, so the grid can be named by it.
58
+ * `undefined` only on a React < 18 server render, where `useId` has no id to
59
+ * give yet and both the `id` and the `aria-labelledby` are simply omitted.
60
+ */
61
+ monthLabelId: string | undefined;
62
+ /** Moves the visible month back one and fires `onVisibleMonthChange`. */
63
+ goToPreviousMonth: () => void;
64
+ /** Moves the visible month forward one and fires `onVisibleMonthChange`. */
65
+ goToNextMonth: () => void;
66
+ /** Direction of the last navigation; `null` until the user navigates. */
67
+ navDirection: CalendarNavDirection | null;
47
68
  }
69
+ export type CalendarHeaderProps = Omit<ComponentPropsWithoutRef<'div'>, 'children'>;
48
70
  export type CalendarDaysProps = ComponentPropsWithoutRef<'thead'>;
49
71
  export type CalendarDatesProps = Omit<ComponentPropsWithoutRef<'table'>, 'children'>;
50
72
  export interface CalendarDateProps extends Omit<ComponentPropsWithoutRef<'td'>, 'children'> {
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});require("../../../chunks/constants.DLsDVPyH.js");const o=require("../../../chunks/dates.CVW08OQ2.js"),r=7,y=0,i=1,E=6,c=e=>(e%r+r)%r,g=(e,t,a)=>{const n=new Date;return n.setFullYear(e,t,a),n.setHours(0,0,0,0),n},Y=e=>g(e.getFullYear(),e.getMonth(),e.getDate()),m=e=>g(e.getFullYear(),e.getMonth(),1),d=e=>g(e.getFullYear(),e.getMonth()+1,0),h=e=>d(e).getDate(),u=(e,t)=>g(e.getFullYear(),e.getMonth(),e.getDate()+t),_=(e,t)=>e.getFullYear()===t.getFullYear()&&e.getMonth()===t.getMonth()&&e.getDate()===t.getDate(),F=(e,t)=>e.getFullYear()===t.getFullYear()&&e.getMonth()===t.getMonth(),S=[],l=(e,t)=>{const a=o.createBoundedMemo(e,t);return S.push(a),a},I=e=>{var t,a;try{const n=new Intl.Locale(e),s=((t=n.getWeekInfo)==null?void 0:t.call(n).firstDay)??((a=n.weekInfo)==null?void 0:a.firstDay);return typeof s=="number"?c(s):null}catch{return null}},k=new Set(["BD","BR","CA","CO","ET","HK","ID","IL","IN","JP","KE","KR","MO","MX","NP","PE","PH","PK","PT","SA","SG","TH","TW","US","VE","YE","ZA"]),T=new Set(["AF","BH","DZ","EG","IQ","IR","JO","KW","LY","OM","QA","SD","SY"]),C=e=>{try{const t=new Intl.Locale(e).maximize().region;return t?k.has(t)?y:T.has(t)?E:null:null}catch{return null}},N=l(o.canonicalLocaleKey,e=>{const t=o.resolveLocale(e);return I(t)??C(t)??i}),O=864e5,W=e=>{const t=new Date(0);return t.setUTCFullYear(e.getFullYear(),e.getMonth(),e.getDate()),t},w=Date.UTC(2024,8,1),L=(e,t,a)=>{const n=new Intl.DateTimeFormat(o.resolveLocale(e),{weekday:a,timeZone:"UTC"});return Array.from({length:r},(s,D)=>n.format(w+c(t+D)*O))},A=(e,t)=>`${o.canonicalLocaleKey(e)}|${t}`,R=l(A,(e,t)=>L(e,t,"short")),b=l(A,(e,t)=>L(e,t,"long")),U=(e,t)=>R(e,t),K=(e,t)=>{const a=m(e),n=c(a.getDay()-t),s=u(a,-n),D=Math.ceil((n+h(e))/r);return Array.from({length:D},(V,f)=>Array.from({length:r},(j,M)=>u(s,f*r+M)))},P=(e,t)=>b(e,t),p=new Set(["gregory","buddhist","japanese","roc"]),G=l(o.canonicalLocaleKey,e=>{const t=o.resolveLocale(e),{calendar:a}=new Intl.DateTimeFormat(t).resolvedOptions();return new Intl.DateTimeFormat(t,{weekday:"long",year:"numeric",month:"long",day:"numeric",timeZone:"UTC",...p.has(a)?{}:{calendar:"gregory"}})}),v=(e,t)=>G(t).format(W(e)),H=l(o.canonicalLocaleKey,e=>new Intl.NumberFormat(o.resolveLocale(e))),B=(e,t)=>H(t).format(e.getDate()),Z=()=>{o.__clearLocaleKeyCache(),S.forEach(e=>e.clear())};exports.DEFAULT_LOCALE=o.DEFAULT_LOCALE;exports.isValidDate=o.isValidDate;exports.DAYS_IN_WEEK=r;exports.MONDAY=i;exports.SUNDAY=y;exports.__clearCalendarCaches=Z;exports.addDays=u;exports.endOfMonth=d;exports.formatDayNumber=B;exports.getCalendarWeeks=K;exports.getDateLabel=v;exports.getDaysInMonth=h;exports.getWeekStart=N;exports.getWeekdayFullLabels=P;exports.getWeekdayLabels=U;exports.isSameDay=_;exports.isSameMonth=F;exports.startOfDay=Y;exports.startOfMonth=m;exports.wrapWeekday=c;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});require("../../../chunks/constants.DLsDVPyH.js");const o=require("../../../chunks/dates.CVW08OQ2.js"),r=7,y=0,i=1,E=6,g=e=>(e%r+r)%r,s=(e,t,n)=>{const a=new Date;return a.setFullYear(e,t,n),a.setHours(0,0,0,0),a},_=e=>s(e.getFullYear(),e.getMonth(),e.getDate()),h=e=>s(e.getFullYear(),e.getMonth(),1),d=e=>s(e.getFullYear(),e.getMonth()+1,0),m=e=>d(e).getDate(),D=(e,t)=>s(e.getFullYear(),e.getMonth(),e.getDate()+t),I=(e,t)=>{const n=s(e.getFullYear(),e.getMonth()+t,1),a=Math.min(e.getDate(),m(n));return s(n.getFullYear(),n.getMonth(),a)},T=(e,t)=>e.getFullYear()===t.getFullYear()&&e.getMonth()===t.getMonth()&&e.getDate()===t.getDate(),k=(e,t)=>e.getFullYear()===t.getFullYear()&&e.getMonth()===t.getMonth(),L=[],l=(e,t)=>{const n=o.createBoundedMemo(e,t);return L.push(n),n},C=e=>{var t,n;try{const a=new Intl.Locale(e),c=((t=a.getWeekInfo)==null?void 0:t.call(a).firstDay)??((n=a.weekInfo)==null?void 0:n.firstDay);return typeof c=="number"?g(c):null}catch{return null}},N=new Set(["BD","BR","CA","CO","ET","HK","ID","IL","IN","JP","KE","KR","MO","MX","NP","PE","PH","PK","PT","SA","SG","TH","TW","US","VE","YE","ZA"]),O=new Set(["AF","BH","DZ","EG","IQ","IR","JO","KW","LY","OM","QA","SD","SY"]),W=e=>{try{const t=new Intl.Locale(e).maximize().region;return t?N.has(t)?y:O.has(t)?E:null:null}catch{return null}},w=l(o.canonicalLocaleKey,e=>{const t=o.resolveLocale(e);return C(t)??W(t)??i}),b=864e5,M=e=>{const t=new Date(0);return t.setUTCFullYear(e.getFullYear(),e.getMonth(),e.getDate()),t},U=Date.UTC(2024,8,1),S=(e,t,n)=>{const a=new Intl.DateTimeFormat(o.resolveLocale(e),{weekday:n,timeZone:"UTC"});return Array.from({length:r},(c,u)=>a.format(U+g(t+u)*b))},A=(e,t)=>`${o.canonicalLocaleKey(e)}|${t}`,R=l(A,(e,t)=>S(e,t,"short")),K=l(A,(e,t)=>S(e,t,"long")),v=(e,t)=>R(e,t),P=(e,t)=>{const n=h(e),a=g(n.getDay()-t),c=D(n,-a),u=Math.ceil((a+m(e))/r);return Array.from({length:u},(Q,F)=>Array.from({length:r},($,Y)=>D(c,F*r+Y)))},p=(e,t)=>K(e,t),G=new Set(["gregory","buddhist","japanese","roc"]),f=e=>{const{calendar:t}=new Intl.DateTimeFormat(e).resolvedOptions();return G.has(t)?{}:{calendar:"gregory"}},H=l(o.canonicalLocaleKey,e=>{const t=o.resolveLocale(e);return new Intl.DateTimeFormat(t,{weekday:"long",year:"numeric",month:"long",day:"numeric",timeZone:"UTC",...f(t)})}),Z=(e,t)=>H(t).format(M(e)),B=l(o.canonicalLocaleKey,e=>{const t=o.resolveLocale(e);return new Intl.DateTimeFormat(t,{month:"long",year:"numeric",timeZone:"UTC",...f(t)})}),V=(e,t)=>B(t).format(M(e)),j=l(o.canonicalLocaleKey,e=>new Intl.NumberFormat(o.resolveLocale(e))),q=(e,t)=>j(t).format(e.getDate()),J=()=>{o.__clearLocaleKeyCache(),L.forEach(e=>e.clear())};exports.DEFAULT_LOCALE=o.DEFAULT_LOCALE;exports.isValidDate=o.isValidDate;exports.DAYS_IN_WEEK=r;exports.MONDAY=i;exports.SUNDAY=y;exports.__clearCalendarCaches=J;exports.addDays=D;exports.addMonths=I;exports.endOfMonth=d;exports.formatDayNumber=q;exports.getCalendarWeeks=P;exports.getDateLabel=Z;exports.getDaysInMonth=m;exports.getMonthLabel=V;exports.getWeekStart=w;exports.getWeekdayFullLabels=p;exports.getWeekdayLabels=v;exports.isSameDay=T;exports.isSameMonth=k;exports.startOfDay=_;exports.startOfMonth=h;exports.wrapWeekday=g;
@@ -19,6 +19,13 @@ export declare const endOfMonth: (date: Date) => Date;
19
19
  export declare const getDaysInMonth: (date: Date) => number;
20
20
  /** Shifts by whole calendar days. Negative amounts move backwards. */
21
21
  export declare const addDays: (date: Date, amount: number) => Date;
22
+ /**
23
+ * Shifts by whole calendar months, clamping the day to the target month's
24
+ * length so Jan 31 lands on Feb 28 rather than overflowing into March. The
25
+ * clamp is invisible to month navigation, which always operates on the first
26
+ * of the month, but C-8's `PageUp`/`PageDown` moves arbitrary days and needs it.
27
+ */
28
+ export declare const addMonths: (date: Date, amount: number) => Date;
22
29
  export declare const isSameDay: (a: Date, b: Date) => boolean;
23
30
  export declare const isSameMonth: (a: Date, b: Date) => boolean;
24
31
  /**
@@ -57,7 +64,28 @@ export declare const getCalendarWeeks: (visibleMonth: Date, weekStart: number) =
57
64
  * "mer."). The header shows the short form and announces this one.
58
65
  */
59
66
  export declare const getWeekdayFullLabels: (locale: string, weekStart: number) => ReadonlyArray<string>;
67
+ /**
68
+ * A cell's spoken name — "Wednesday, July 15, 2025".
69
+ *
70
+ * The visible text is only the day number, which leaves a screen reader unable
71
+ * to separate the padding days from the month's own: July 2025 opens on
72
+ * "29, 30, 1", so it sounds like July starts on the 29th. The dimmed colour is
73
+ * the only thing saying otherwise, and colour isn't available to a screen
74
+ * reader.
75
+ *
76
+ * Built by `Intl` rather than assembled from parts, so word order and
77
+ * punctuation follow the locale instead of an English template. C-13 extends
78
+ * this with state suffixes (today, selected, disabled); I-8 adds the per-cell
79
+ * override.
80
+ */
60
81
  export declare const getDateLabel: (date: Date, locale: string) => string;
82
+ /**
83
+ * The header's "Month Year" label. Ordering is the locale's, not a template —
84
+ * en-US gives "July 2025", ja-JP gives "2025年7月", th-TH keeps its Buddhist
85
+ * year. Pinned the same way as {@link getDateLabel}, and for the same reasons,
86
+ * so the header can't name a different month from the cells below it.
87
+ */
88
+ export declare const getMonthLabel: (date: Date, locale: string) => string;
61
89
  /**
62
90
  * The day-of-month number as displayed. Routed through `Intl.NumberFormat` so
63
91
  * locales with non-Latin default digits render correctly, and so the
@@ -1,21 +1,24 @@
1
1
  import "../../../chunks/constants.XFX4nOSf.js";
2
- import { c as f, r as c, b as l, _ as d } from "../../../chunks/dates.NqdbQ2fR.js";
3
- import { D as ee, i as te } from "../../../chunks/dates.NqdbQ2fR.js";
4
- const a = 7, Y = 0, E = 1, F = 6, D = (e) => (e % a + a) % a, g = (e, t, n) => {
2
+ import { c as F, r as l, b as g, _ as Y } from "../../../chunks/dates.NqdbQ2fR.js";
3
+ import { D as re, i as ae } from "../../../chunks/dates.NqdbQ2fR.js";
4
+ const r = 7, L = 0, E = 1, I = 6, u = (e) => (e % r + r) % r, a = (e, t, n) => {
5
5
  const o = /* @__PURE__ */ new Date();
6
6
  return o.setFullYear(e, t, n), o.setHours(0, 0, 0, 0), o;
7
- }, B = (e) => g(e.getFullYear(), e.getMonth(), e.getDate()), M = (e) => g(e.getFullYear(), e.getMonth(), 1), _ = (e) => g(e.getFullYear(), e.getMonth() + 1, 0), I = (e) => _(e).getDate(), m = (e, t) => g(e.getFullYear(), e.getMonth(), e.getDate() + t), Z = (e, t) => e.getFullYear() === t.getFullYear() && e.getMonth() === t.getMonth() && e.getDate() === t.getDate(), x = (e, t) => e.getFullYear() === t.getFullYear() && e.getMonth() === t.getMonth(), y = [], s = (e, t) => {
8
- const n = f(e, t);
9
- return y.push(n), n;
10
- }, L = (e) => {
7
+ }, v = (e) => a(e.getFullYear(), e.getMonth(), e.getDate()), T = (e) => a(e.getFullYear(), e.getMonth(), 1), _ = (e) => a(e.getFullYear(), e.getMonth() + 1, 0), h = (e) => _(e).getDate(), D = (e, t) => a(e.getFullYear(), e.getMonth(), e.getDate() + t), x = (e, t) => {
8
+ const n = a(e.getFullYear(), e.getMonth() + t, 1), o = Math.min(e.getDate(), h(n));
9
+ return a(n.getFullYear(), n.getMonth(), o);
10
+ }, J = (e, t) => e.getFullYear() === t.getFullYear() && e.getMonth() === t.getMonth() && e.getDate() === t.getDate(), Q = (e, t) => e.getFullYear() === t.getFullYear() && e.getMonth() === t.getMonth(), i = [], s = (e, t) => {
11
+ const n = F(e, t);
12
+ return i.push(n), n;
13
+ }, w = (e) => {
11
14
  var t, n;
12
15
  try {
13
- const o = new Intl.Locale(e), r = ((t = o.getWeekInfo) == null ? void 0 : t.call(o).firstDay) ?? ((n = o.weekInfo) == null ? void 0 : n.firstDay);
14
- return typeof r == "number" ? D(r) : null;
16
+ const o = new Intl.Locale(e), c = ((t = o.getWeekInfo) == null ? void 0 : t.call(o).firstDay) ?? ((n = o.weekInfo) == null ? void 0 : n.firstDay);
17
+ return typeof c == "number" ? u(c) : null;
15
18
  } catch {
16
19
  return null;
17
20
  }
18
- }, T = /* @__PURE__ */ new Set([
21
+ }, C = /* @__PURE__ */ new Set([
19
22
  "BD",
20
23
  "BR",
21
24
  "CA",
@@ -43,7 +46,7 @@ const a = 7, Y = 0, E = 1, F = 6, D = (e) => (e % a + a) % a, g = (e, t, n) => {
43
46
  "VE",
44
47
  "YE",
45
48
  "ZA"
46
- ]), w = /* @__PURE__ */ new Set([
49
+ ]), k = /* @__PURE__ */ new Set([
47
50
  "AF",
48
51
  "BH",
49
52
  "DZ",
@@ -57,97 +60,103 @@ const a = 7, Y = 0, E = 1, F = 6, D = (e) => (e % a + a) % a, g = (e, t, n) => {
57
60
  "QA",
58
61
  "SD",
59
62
  "SY"
60
- ]), k = (e) => {
63
+ ]), N = (e) => {
61
64
  try {
62
65
  const t = new Intl.Locale(e).maximize().region;
63
- return t ? T.has(t) ? Y : w.has(t) ? F : null : null;
66
+ return t ? C.has(t) ? L : k.has(t) ? I : null : null;
64
67
  } catch {
65
68
  return null;
66
69
  }
67
- }, v = s(
68
- l,
70
+ }, V = s(
71
+ g,
69
72
  (e) => {
70
- const t = c(e);
71
- return L(t) ?? k(t) ?? E;
73
+ const t = l(e);
74
+ return w(t) ?? N(t) ?? E;
72
75
  }
73
- ), C = 864e5, N = (e) => {
76
+ ), R = 864e5, y = (e) => {
74
77
  const t = /* @__PURE__ */ new Date(0);
75
78
  return t.setUTCFullYear(e.getFullYear(), e.getMonth(), e.getDate()), t;
76
- }, R = Date.UTC(2024, 8, 1), i = (e, t, n) => {
77
- const o = new Intl.DateTimeFormat(c(e), {
79
+ }, U = Date.UTC(2024, 8, 1), d = (e, t, n) => {
80
+ const o = new Intl.DateTimeFormat(l(e), {
78
81
  weekday: n,
79
82
  timeZone: "UTC"
80
83
  });
81
84
  return Array.from(
82
- { length: a },
83
- (r, u) => o.format(
84
- R + D(t + u) * C
85
+ { length: r },
86
+ (c, m) => o.format(
87
+ U + u(t + m) * R
85
88
  )
86
89
  );
87
- }, h = (e, t) => `${l(e)}|${t}`, O = s(
88
- h,
89
- (e, t) => i(e, t, "short")
90
+ }, A = (e, t) => `${g(e)}|${t}`, O = s(
91
+ A,
92
+ (e, t) => d(e, t, "short")
90
93
  ), W = s(
91
- h,
92
- (e, t) => i(e, t, "long")
93
- ), J = (e, t) => O(e, t), Q = (e, t) => {
94
- const n = M(e), o = D(n.getDay() - t), r = m(n, -o), u = Math.ceil(
95
- (o + I(e)) / a
94
+ A,
95
+ (e, t) => d(e, t, "long")
96
+ ), $ = (e, t) => O(e, t), j = (e, t) => {
97
+ const n = T(e), o = u(n.getDay() - t), c = D(n, -o), m = Math.ceil(
98
+ (o + h(e)) / r
96
99
  );
97
100
  return Array.from(
98
- { length: u },
99
- (K, A) => Array.from(
100
- { length: a },
101
- (G, S) => m(r, A * a + S)
101
+ { length: m },
102
+ (P, f) => Array.from(
103
+ { length: r },
104
+ (H, S) => D(c, f * r + S)
102
105
  )
103
106
  );
104
- }, V = (e, t) => W(e, t), U = /* @__PURE__ */ new Set([
107
+ }, z = (e, t) => W(e, t), b = /* @__PURE__ */ new Set([
105
108
  "gregory",
106
109
  "buddhist",
107
110
  "japanese",
108
111
  "roc"
109
- ]), b = s(l, (e) => {
110
- const t = c(e), { calendar: n } = new Intl.DateTimeFormat(t).resolvedOptions();
112
+ ]), M = (e) => {
113
+ const { calendar: t } = new Intl.DateTimeFormat(e).resolvedOptions();
114
+ return b.has(t) ? {} : { calendar: "gregory" };
115
+ }, p = s(g, (e) => {
116
+ const t = l(e);
111
117
  return new Intl.DateTimeFormat(t, {
112
118
  weekday: "long",
113
119
  year: "numeric",
114
120
  month: "long",
115
121
  day: "numeric",
116
122
  timeZone: "UTC",
117
- // The grid is laid out from Gregorian `Date` arithmetic, so a label that
118
- // names a different day describes a month we never drew: unpinned, `fa-IR`
119
- // renders "۸" and announces "۱۴۰۴ تیر ۱۷" — different day, month and year,
120
- // on all 35 cells. Forced only for the calendars that actually diverge, so
121
- // a Thai user keeps 2568 and a Japanese user keeps the era; both name the
122
- // same day the grid drew. A grid that follows the locale's own calendar is
123
- // A-3, still deferred.
124
- ...U.has(n) ? {} : { calendar: "gregory" }
123
+ ...M(t)
125
124
  });
126
- }), $ = (e, t) => b(t).format(N(e)), p = s(
127
- l,
128
- (e) => new Intl.NumberFormat(c(e))
129
- ), j = (e, t) => p(t).format(e.getDate()), z = () => {
130
- d(), y.forEach((e) => e.clear());
125
+ }), X = (e, t) => p(t).format(y(e)), K = s(g, (e) => {
126
+ const t = l(e);
127
+ return new Intl.DateTimeFormat(t, {
128
+ month: "long",
129
+ year: "numeric",
130
+ timeZone: "UTC",
131
+ ...M(t)
132
+ });
133
+ }), q = (e, t) => K(t).format(y(e)), G = s(
134
+ g,
135
+ (e) => new Intl.NumberFormat(l(e))
136
+ ), ee = (e, t) => G(t).format(e.getDate()), te = () => {
137
+ Y(), i.forEach((e) => e.clear());
131
138
  };
132
139
  export {
133
- a as DAYS_IN_WEEK,
134
- ee as DEFAULT_LOCALE,
140
+ r as DAYS_IN_WEEK,
141
+ re as DEFAULT_LOCALE,
135
142
  E as MONDAY,
136
- Y as SUNDAY,
137
- z as __clearCalendarCaches,
138
- m as addDays,
143
+ L as SUNDAY,
144
+ te as __clearCalendarCaches,
145
+ D as addDays,
146
+ x as addMonths,
139
147
  _ as endOfMonth,
140
- j as formatDayNumber,
141
- Q as getCalendarWeeks,
142
- $ as getDateLabel,
143
- I as getDaysInMonth,
144
- v as getWeekStart,
145
- V as getWeekdayFullLabels,
146
- J as getWeekdayLabels,
147
- Z as isSameDay,
148
- x as isSameMonth,
149
- te as isValidDate,
150
- B as startOfDay,
151
- M as startOfMonth,
152
- D as wrapWeekday
148
+ ee as formatDayNumber,
149
+ j as getCalendarWeeks,
150
+ X as getDateLabel,
151
+ h as getDaysInMonth,
152
+ q as getMonthLabel,
153
+ V as getWeekStart,
154
+ z as getWeekdayFullLabels,
155
+ $ as getWeekdayLabels,
156
+ J as isSameDay,
157
+ Q as isSameMonth,
158
+ ae as isValidDate,
159
+ v as startOfDay,
160
+ T as startOfMonth,
161
+ u as wrapWeekday
153
162
  };
@@ -1,2 +1,2 @@
1
1
  export { Calendar } from './Calendar';
2
- export type { CalendarDateProps, CalendarDatesProps, CalendarDaysProps, CalendarProps, } from './Calendar.types';
2
+ export type { CalendarDateProps, CalendarDatesProps, CalendarDaysProps, CalendarHeaderProps, CalendarNavDirection, CalendarProps, } from './Calendar.types';
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s=require("react"),a=require("./Calendar.utils.cjs.js"),o=(e,t)=>{const r=a.getWeekStart(t),n=a.getWeekdayLabels(t,r),d=s.useMemo(()=>a.getCalendarWeeks(e,r),[e,r]),u=s.useMemo(()=>a.getMonthLabel(e,t),[e,t]);return{weekStart:r,weekdayLabels:n,weeks:d,monthLabel:u}};exports.useCalendarGrid=o;
@@ -0,0 +1,18 @@
1
+ export interface CalendarGrid {
2
+ /** First day of the week, in `Date.getDay()` numbering (0 = Sunday). */
3
+ weekStart: number;
4
+ /** Abbreviated weekday names, ordered from `weekStart`. */
5
+ weekdayLabels: ReadonlyArray<string>;
6
+ /** Whole weeks covering the month, padded with adjacent-month days. */
7
+ weeks: Date[][];
8
+ /** Localized "Month Year" label. */
9
+ monthLabel: string;
10
+ }
11
+ /**
12
+ * Everything the grid renders, derived from the month and the locale.
13
+ *
14
+ * Pure: given the same month and locale it returns the same values, and the
15
+ * same references. `getWeekStart` and `getWeekdayLabels` are memoized in the
16
+ * utils layer, so only `weeks` needs a `useMemo` here.
17
+ */
18
+ export declare const useCalendarGrid: (visibleMonth: Date, locale: string) => CalendarGrid;
@@ -0,0 +1,15 @@
1
+ import { useMemo as a } from "react";
2
+ import { getWeekStart as k, getWeekdayLabels as m, getCalendarWeeks as d, getMonthLabel as g } from "./Calendar.utils.es.js";
3
+ const u = (e, t) => {
4
+ const r = k(t), s = m(t, r), n = a(
5
+ () => d(e, r),
6
+ [e, r]
7
+ ), o = a(
8
+ () => g(e, t),
9
+ [e, t]
10
+ );
11
+ return { weekStart: r, weekdayLabels: s, weeks: n, monthLabel: o };
12
+ };
13
+ export {
14
+ u as useCalendarGrid
15
+ };
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("react"),e=require("./Calendar.utils.cjs.js"),C=require("../../../chunks/dates.CVW08OQ2.js"),O=({today:r,onVisibleMonthChange:u})=>{const[c]=t.useState(()=>e.startOfDay(new Date)),a=C.isValidDate(r)?e.startOfDay(r).getTime():null,l=t.useMemo(()=>a===null?c:e.startOfDay(new Date(a)),[a,c]),[i,D]=t.useState(()=>e.startOfMonth(l)),[b,f]=t.useState(null),d=t.useRef(i),s=t.useRef(u);s.current=u;const n=t.useCallback(y=>{var M;const o=e.addMonths(d.current,y);d.current=o,D(o),f(y<0?"previous":"next"),(M=s.current)==null||M.call(s,o)},[]),v=t.useCallback(()=>n(-1),[n]),T=t.useCallback(()=>n(1),[n]);return{today:l,visibleMonth:i,navDirection:b,goToPreviousMonth:v,goToNextMonth:T}};exports.useCalendarMonth=O;
@@ -0,0 +1,24 @@
1
+ import { CalendarNavDirection } from './Calendar.types';
2
+ export interface UseCalendarMonthOptions {
3
+ /** Consumer-supplied "today". Ignored when it isn't a valid `Date`. */
4
+ today?: Date;
5
+ onVisibleMonthChange?: (date: Date) => void;
6
+ }
7
+ export interface CalendarMonthState {
8
+ /** The current date, at local midnight. */
9
+ today: Date;
10
+ /** First day of the rendered month, at local midnight. */
11
+ visibleMonth: Date;
12
+ /** Direction of the last navigation; `null` until the user navigates. */
13
+ navDirection: CalendarNavDirection | null;
14
+ goToPreviousMonth: () => void;
15
+ goToNextMonth: () => void;
16
+ }
17
+ /**
18
+ * Owns which month is on screen, and how it got there.
19
+ *
20
+ * Split out of the root so the one piece of Calendar that holds mutable state
21
+ * can be read, tested, and later extended on its own — C-23 turns
22
+ * `visibleMonth` into a controlled prop here without the root noticing.
23
+ */
24
+ export declare const useCalendarMonth: ({ today: todayProp, onVisibleMonthChange, }: UseCalendarMonthOptions) => CalendarMonthState;
@@ -0,0 +1,30 @@
1
+ import { useState as s, useMemo as h, useRef as v, useCallback as r } from "react";
2
+ import { startOfDay as c, startOfMonth as b, addMonths as w } from "./Calendar.utils.es.js";
3
+ import { i as N } from "../../../chunks/dates.NqdbQ2fR.js";
4
+ const R = ({
5
+ today: a,
6
+ onVisibleMonthChange: i
7
+ }) => {
8
+ const [u] = s(() => c(/* @__PURE__ */ new Date())), o = N(a) ? c(a).getTime() : null, l = h(
9
+ () => o === null ? u : c(new Date(o)),
10
+ [o, u]
11
+ ), [m, D] = s(() => b(l)), [p, y] = s(
12
+ null
13
+ ), d = v(m), t = v(i);
14
+ t.current = i;
15
+ const e = r((M) => {
16
+ var f;
17
+ const n = w(d.current, M);
18
+ d.current = n, D(n), y(M < 0 ? "previous" : "next"), (f = t.current) == null || f.call(t, n);
19
+ }, []), T = r(() => e(-1), [e]), x = r(() => e(1), [e]);
20
+ return {
21
+ today: l,
22
+ visibleMonth: m,
23
+ navDirection: p,
24
+ goToPreviousMonth: T,
25
+ goToNextMonth: x
26
+ };
27
+ };
28
+ export {
29
+ R as useCalendarMonth
30
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@viasat/beam-react",
3
- "version": "2.74.0",
3
+ "version": "2.75.0",
4
4
  "description": "React component library for the Beam design system",
5
5
  "license": "MIT",
6
6
  "author": "Viasat",
@@ -60,12 +60,12 @@
60
60
  "access": "public"
61
61
  },
62
62
  "dependencies": {
63
- "@viasat/beam-fonts": "2.74.0",
64
- "@viasat/beam-shared": "2.74.0",
65
- "@viasat/beam-styles": "2.74.0",
66
- "@viasat/beam-tokens": "2.74.0",
67
- "@viasat/beam-icons": "2.74.0",
68
- "@viasat/beam-react-claude-plugin": "2.74.0",
63
+ "@viasat/beam-fonts": "2.75.0",
64
+ "@viasat/beam-shared": "2.75.0",
65
+ "@viasat/beam-styles": "2.75.0",
66
+ "@viasat/beam-tokens": "2.75.0",
67
+ "@viasat/beam-icons": "2.75.0",
68
+ "@viasat/beam-react-claude-plugin": "2.75.0",
69
69
  "clsx": "^1.2.1",
70
70
  "@floating-ui/react": "^0.26.18",
71
71
  "@stepperize/react": "^5.1.5",
@@ -1 +0,0 @@
1
- var t=require("../assets/calendar.css");const e=require("./classNames.CEoAKlth.js"),s="calendar",{baseClassNamePrefix:d,classModifierPrefix:r,subElementClassPrefix:a}=e.getBEMClassNames(s),l={grid:`${a}grid`,day:`${a}day`,visuallyHidden:`${a}visually-hidden`,week:`${a}week`,date:`${a}date`,dateButton:`${a}date-button`},n={"bm-calendar":"bm-calendar","bm-calendar__visually-hidden":"bm-calendar__visually-hidden","bm-calendar__grid":"bm-calendar__grid","bm-calendar__day":"bm-calendar__day","bm-calendar__date":"bm-calendar__date","bm-calendar__week":"bm-calendar__week","bm-calendar__date-button":"bm-calendar__date-button"};exports.baseClassNamePrefix=d;exports.staticCalendarClassNames=l;exports.styles=n;