@nepdatejs/react 0.1.0 → 0.1.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.
@@ -5,7 +5,7 @@ let _nepdatejs_core = require("@nepdatejs/core");
5
5
  * A server date shown in BS (or AD), with the other calendar alongside:
6
6
  * "10 Ashwin 2083 · 26 Sep 2026". No hooks, so it works in server components.
7
7
  */
8
- function DateText({ value, calendar = "BS", withEquivalent = true, format = "long", locale = "en", fallback = "—", className }) {
8
+ function DateText({ value, calendar = "BS", withEquivalent = true, format = "long", locale, fallback = "—", className }) {
9
9
  const date = (0, _nepdatejs_core.fromIsoDate)(value);
10
10
  if (!date) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
11
11
  className,
@@ -81,4 +81,4 @@ Object.defineProperty(exports, "shortDate", {
81
81
  }
82
82
  });
83
83
 
84
- //# sourceMappingURL=date-text-BT82cZ7i.cjs.map
84
+ //# sourceMappingURL=date-text-BX3Uag0O.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"date-text-BX3Uag0O.cjs","names":["fromIsoDate","formatDate","toCalendar","fromIsoTimestamp"],"sources":["../src/date-text.tsx"],"sourcesContent":["import type { ReactElement } from 'react';\nimport {\n formatDate,\n fromIsoDate,\n fromIsoTimestamp,\n toCalendar,\n type CalendarSystem,\n type DateFormatPattern,\n type LocaleCode,\n} from '@nepdatejs/core';\n\nexport interface DateTextProps {\n /** An AD date or timestamp from the server (\"2026-09-26\" or an ISO timestamp). */\n value: string | null | undefined;\n /** Which calendar to show first. Default 'BS'. */\n calendar?: CalendarSystem | undefined;\n /** Also show the day in the other calendar, muted. Default true. */\n withEquivalent?: boolean | undefined;\n format?: DateFormatPattern | undefined;\n locale?: LocaleCode | undefined;\n fallback?: string | undefined;\n className?: string | undefined;\n}\n\n/**\n * A server date shown in BS (or AD), with the other calendar alongside:\n * \"10 Ashwin 2083 · 26 Sep 2026\". No hooks, so it works in server components.\n */\nexport function DateText({\n value,\n calendar = 'BS',\n withEquivalent = true,\n format = 'long',\n locale,\n fallback = '—',\n className,\n}: DateTextProps): ReactElement {\n const date = fromIsoDate(value);\n if (!date) {\n return <span className={className}>{fallback}</span>;\n }\n const other: CalendarSystem = calendar === 'BS' ? 'AD' : 'BS';\n\n return (\n <time dateTime={formatDate(date, 'Y-m-d')} className={className}>\n {formatDate(toCalendar(date, calendar), format, locale)}\n {withEquivalent && (\n <span className=\"ndp-muted\" style={{ color: 'var(--ndp-text-muted, #64748b)' }}>\n {' · '}\n {formatDate(toCalendar(date, other), other === 'AD' ? 'j M Y' : format, locale)}\n </span>\n )}\n </time>\n );\n}\n\n/**\n * A server date as short text: \"12 Ashwin 2083\", keeping the time of day when\n * the value has one. A timestamp with a zone is read in the configured zone\n * (Nepal by default). Anything that is not a date is returned unchanged.\n */\nexport function shortDate(value: string | null | undefined): string | null {\n if (!value) {\n return null;\n }\n const instant = fromIsoTimestamp(value);\n const date = instant?.date ?? fromIsoDate(value);\n if (!date) {\n return value;\n }\n const time = instant?.time ?? /[T ](\\d{2}:\\d{2})/.exec(value)?.[1];\n\n return `${formatDate(toCalendar(date, 'BS'), 'j F Y')}${time ? `, ${time}` : ''}`;\n}\n\n/** A server date as documents print it, in both calendars: \"31 Shrawan 2083 (16 Aug 2026)\". */\nexport function bothDates(value: string | null | undefined): string {\n const date = fromIsoDate(value);\n\n return date\n ? `${formatDate(toCalendar(date, 'BS'), 'j F Y')} (${formatDate(date, 'j M Y')})`\n : (value ?? '');\n}\n\n/** A server date for a table cell or list row, with the AD day on hover. */\nexport function ShortDate({\n value,\n fallback = '—',\n className,\n}: {\n value: string | null | undefined;\n fallback?: string | undefined;\n className?: string | undefined;\n}): ReactElement {\n const text = shortDate(value);\n const date = fromIsoDate(value);\n if (!text) {\n return <span className={className}>{fallback}</span>;\n }\n\n return (\n <time\n dateTime={value ?? undefined}\n title={date ? formatDate(date, 'j M Y') : undefined}\n className={className}\n >\n {text}\n </time>\n );\n}\n"],"mappings":";;;;;;;AA4BA,SAAgB,SAAS,EACvB,OACA,WAAW,MACX,iBAAiB,MACjB,SAAS,QACT,QACA,WAAW,KACX,aAC8B;CAC9B,MAAM,QAAA,GAAOA,gBAAAA,YAAAA,CAAY,KAAK;CAC9B,IAAI,CAAC,MACH,OAAO,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;EAAiB;EAAY,UAAA;CAAe,CAAA;CAErD,MAAM,QAAwB,aAAa,OAAO,OAAO;CAEzD,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,QAAD;EAAM,WAAA,GAAUC,gBAAAA,WAAAA,CAAW,MAAM,OAAO;EAAc;EAAtD,UAAA,EAAA,GACGA,gBAAAA,WAAAA,EAAAA,GAAWC,gBAAAA,WAAAA,CAAW,MAAM,QAAQ,GAAG,QAAQ,MAAM,GACrD,kBACC,iBAAA,GAAA,kBAAA,KAAA,CAAC,QAAD;GAAM,WAAU;GAAY,OAAO,EAAE,OAAO,iCAAiC;GAA7E,UAAA,CACG,QAAA,GACAD,gBAAAA,WAAAA,EAAAA,GAAWC,gBAAAA,WAAAA,CAAW,MAAM,KAAK,GAAG,UAAU,OAAO,UAAU,QAAQ,MAAM,CAC1E;EAEJ,CAAA,CAAA;;AAEV;;;;;;AAOA,SAAgB,UAAU,OAAiD;CACzE,IAAI,CAAC,OACH,OAAO;CAET,MAAM,WAAA,GAAUC,gBAAAA,iBAAAA,CAAiB,KAAK;CACtC,MAAM,OAAO,SAAS,SAAA,GAAQH,gBAAAA,YAAAA,CAAY,KAAK;CAC/C,IAAI,CAAC,MACH,OAAO;CAET,MAAM,OAAO,SAAS,QAAQ,oBAAoB,KAAK,KAAK,CAAC,GAAG;CAEhE,OAAO,IAAA,GAAGC,gBAAAA,WAAAA,EAAAA,GAAWC,gBAAAA,WAAAA,CAAW,MAAM,IAAI,GAAG,OAAO,IAAI,OAAO,KAAK,SAAS;AAC/E;;AAGA,SAAgB,UAAU,OAA0C;CAClE,MAAM,QAAA,GAAOF,gBAAAA,YAAAA,CAAY,KAAK;CAE9B,OAAO,OACH,IAAA,GAAGC,gBAAAA,WAAAA,EAAAA,GAAWC,gBAAAA,WAAAA,CAAW,MAAM,IAAI,GAAG,OAAO,EAAE,KAAA,GAAID,gBAAAA,WAAAA,CAAW,MAAM,OAAO,EAAE,KAC5E,SAAS;AAChB;;AAGA,SAAgB,UAAU,EACxB,OACA,WAAW,KACX,aAKe;CACf,MAAM,OAAO,UAAU,KAAK;CAC5B,MAAM,QAAA,GAAOD,gBAAAA,YAAAA,CAAY,KAAK;CAC9B,IAAI,CAAC,MACH,OAAO,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;EAAiB;EAAY,UAAA;CAAe,CAAA;CAGrD,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD;EACE,UAAU,SAAS,KAAA;EACnB,OAAO,QAAA,GAAOC,gBAAAA,WAAAA,CAAW,MAAM,OAAO,IAAI,KAAA;EAC/B;EAEV,UAAA;CACG,CAAA;AAEV"}
@@ -5,7 +5,7 @@ import { formatDate, fromIsoDate, fromIsoTimestamp, toCalendar } from "@nepdatej
5
5
  * A server date shown in BS (or AD), with the other calendar alongside:
6
6
  * "10 Ashwin 2083 · 26 Sep 2026". No hooks, so it works in server components.
7
7
  */
8
- function DateText({ value, calendar = "BS", withEquivalent = true, format = "long", locale = "en", fallback = "—", className }) {
8
+ function DateText({ value, calendar = "BS", withEquivalent = true, format = "long", locale, fallback = "—", className }) {
9
9
  const date = fromIsoDate(value);
10
10
  if (!date) return /* @__PURE__ */ jsx("span", {
11
11
  className,
@@ -58,4 +58,4 @@ function ShortDate({ value, fallback = "—", className }) {
58
58
  //#endregion
59
59
  export { shortDate as i, ShortDate as n, bothDates as r, DateText as t };
60
60
 
61
- //# sourceMappingURL=date-text-Df1gFksR.js.map
61
+ //# sourceMappingURL=date-text-DLwhBmYj.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"date-text-DLwhBmYj.js","names":[],"sources":["../src/date-text.tsx"],"sourcesContent":["import type { ReactElement } from 'react';\nimport {\n formatDate,\n fromIsoDate,\n fromIsoTimestamp,\n toCalendar,\n type CalendarSystem,\n type DateFormatPattern,\n type LocaleCode,\n} from '@nepdatejs/core';\n\nexport interface DateTextProps {\n /** An AD date or timestamp from the server (\"2026-09-26\" or an ISO timestamp). */\n value: string | null | undefined;\n /** Which calendar to show first. Default 'BS'. */\n calendar?: CalendarSystem | undefined;\n /** Also show the day in the other calendar, muted. Default true. */\n withEquivalent?: boolean | undefined;\n format?: DateFormatPattern | undefined;\n locale?: LocaleCode | undefined;\n fallback?: string | undefined;\n className?: string | undefined;\n}\n\n/**\n * A server date shown in BS (or AD), with the other calendar alongside:\n * \"10 Ashwin 2083 · 26 Sep 2026\". No hooks, so it works in server components.\n */\nexport function DateText({\n value,\n calendar = 'BS',\n withEquivalent = true,\n format = 'long',\n locale,\n fallback = '—',\n className,\n}: DateTextProps): ReactElement {\n const date = fromIsoDate(value);\n if (!date) {\n return <span className={className}>{fallback}</span>;\n }\n const other: CalendarSystem = calendar === 'BS' ? 'AD' : 'BS';\n\n return (\n <time dateTime={formatDate(date, 'Y-m-d')} className={className}>\n {formatDate(toCalendar(date, calendar), format, locale)}\n {withEquivalent && (\n <span className=\"ndp-muted\" style={{ color: 'var(--ndp-text-muted, #64748b)' }}>\n {' · '}\n {formatDate(toCalendar(date, other), other === 'AD' ? 'j M Y' : format, locale)}\n </span>\n )}\n </time>\n );\n}\n\n/**\n * A server date as short text: \"12 Ashwin 2083\", keeping the time of day when\n * the value has one. A timestamp with a zone is read in the configured zone\n * (Nepal by default). Anything that is not a date is returned unchanged.\n */\nexport function shortDate(value: string | null | undefined): string | null {\n if (!value) {\n return null;\n }\n const instant = fromIsoTimestamp(value);\n const date = instant?.date ?? fromIsoDate(value);\n if (!date) {\n return value;\n }\n const time = instant?.time ?? /[T ](\\d{2}:\\d{2})/.exec(value)?.[1];\n\n return `${formatDate(toCalendar(date, 'BS'), 'j F Y')}${time ? `, ${time}` : ''}`;\n}\n\n/** A server date as documents print it, in both calendars: \"31 Shrawan 2083 (16 Aug 2026)\". */\nexport function bothDates(value: string | null | undefined): string {\n const date = fromIsoDate(value);\n\n return date\n ? `${formatDate(toCalendar(date, 'BS'), 'j F Y')} (${formatDate(date, 'j M Y')})`\n : (value ?? '');\n}\n\n/** A server date for a table cell or list row, with the AD day on hover. */\nexport function ShortDate({\n value,\n fallback = '—',\n className,\n}: {\n value: string | null | undefined;\n fallback?: string | undefined;\n className?: string | undefined;\n}): ReactElement {\n const text = shortDate(value);\n const date = fromIsoDate(value);\n if (!text) {\n return <span className={className}>{fallback}</span>;\n }\n\n return (\n <time\n dateTime={value ?? undefined}\n title={date ? formatDate(date, 'j M Y') : undefined}\n className={className}\n >\n {text}\n </time>\n );\n}\n"],"mappings":";;;;;;;AA4BA,SAAgB,SAAS,EACvB,OACA,WAAW,MACX,iBAAiB,MACjB,SAAS,QACT,QACA,WAAW,KACX,aAC8B;CAC9B,MAAM,OAAO,YAAY,KAAK;CAC9B,IAAI,CAAC,MACH,OAAO,oBAAC,QAAD;EAAiB;EAAY,UAAA;CAAe,CAAA;CAErD,MAAM,QAAwB,aAAa,OAAO,OAAO;CAEzD,OACE,qBAAC,QAAD;EAAM,UAAU,WAAW,MAAM,OAAO;EAAc;EAAtD,UAAA,CACG,WAAW,WAAW,MAAM,QAAQ,GAAG,QAAQ,MAAM,GACrD,kBACC,qBAAC,QAAD;GAAM,WAAU;GAAY,OAAO,EAAE,OAAO,iCAAiC;GAA7E,UAAA,CACG,OACA,WAAW,WAAW,MAAM,KAAK,GAAG,UAAU,OAAO,UAAU,QAAQ,MAAM,CAC1E;EAEJ,CAAA,CAAA;;AAEV;;;;;;AAOA,SAAgB,UAAU,OAAiD;CACzE,IAAI,CAAC,OACH,OAAO;CAET,MAAM,UAAU,iBAAiB,KAAK;CACtC,MAAM,OAAO,SAAS,QAAQ,YAAY,KAAK;CAC/C,IAAI,CAAC,MACH,OAAO;CAET,MAAM,OAAO,SAAS,QAAQ,oBAAoB,KAAK,KAAK,CAAC,GAAG;CAEhE,OAAO,GAAG,WAAW,WAAW,MAAM,IAAI,GAAG,OAAO,IAAI,OAAO,KAAK,SAAS;AAC/E;;AAGA,SAAgB,UAAU,OAA0C;CAClE,MAAM,OAAO,YAAY,KAAK;CAE9B,OAAO,OACH,GAAG,WAAW,WAAW,MAAM,IAAI,GAAG,OAAO,EAAE,IAAI,WAAW,MAAM,OAAO,EAAE,KAC5E,SAAS;AAChB;;AAGA,SAAgB,UAAU,EACxB,OACA,WAAW,KACX,aAKe;CACf,MAAM,OAAO,UAAU,KAAK;CAC5B,MAAM,OAAO,YAAY,KAAK;CAC9B,IAAI,CAAC,MACH,OAAO,oBAAC,QAAD;EAAiB;EAAY,UAAA;CAAe,CAAA;CAGrD,OACE,oBAAC,QAAD;EACE,UAAU,SAAS,KAAA;EACnB,OAAO,OAAO,WAAW,MAAM,OAAO,IAAI,KAAA;EAC/B;EAEV,UAAA;CACG,CAAA;AAEV"}
@@ -154,6 +154,12 @@ function splitTitle(title) {
154
154
  }
155
155
  //#endregion
156
156
  //#region src/use-store.ts
157
+ /** Function options whose answers decide how the calendar's days look. */
158
+ const DAY_FUNCTIONS = [
159
+ "isDateDisabled",
160
+ "holidays",
161
+ "events"
162
+ ];
157
163
  /** useLayoutEffect in the browser, useEffect on the server (no warning). */
158
164
  const useIsomorphicLayoutEffect = typeof window === "undefined" ? react.useEffect : react.useLayoutEffect;
159
165
  /**
@@ -179,19 +185,58 @@ function useStore(create, options) {
179
185
  };
180
186
  const [store] = (0, react.useState)(() => create(prepare(options)));
181
187
  const previous = (0, react.useRef)(prepare(options));
188
+ const dayAnswers = (0, react.useRef)(null);
189
+ const storeValue = (0, react.useRef)(valueOf(store.getState()));
182
190
  useIsomorphicLayoutEffect(() => {
183
191
  const next = prepare(options);
184
192
  const before = previous.current;
185
193
  const changes = {};
186
194
  for (const key of /* @__PURE__ */ new Set([...Object.keys(before), ...Object.keys(next)])) if (!deepEqual(before[key], next[key])) changes[key] = next[key];
187
195
  previous.current = next;
196
+ const current = askDayFunctions(options, store.getState());
197
+ const asked = dayAnswers.current;
198
+ dayAnswers.current = current;
199
+ if (asked?.days === current?.days && asked?.answers !== current?.answers) {
200
+ for (const key of DAY_FUNCTIONS) if (key in next) changes[key] = next[key];
201
+ }
188
202
  if (Object.keys(changes).length > 0) store.setOptions(changes);
203
+ const value = valueOf(store.getState());
204
+ const changedByUser = !deepEqual(value, storeValue.current) && !("value" in changes);
205
+ storeValue.current = value;
206
+ const held = next["value"];
207
+ if (changedByUser && held !== void 0 && isChosen(value) && !deepEqual(value, held)) {
208
+ store.actions?.setValue?.(held);
209
+ storeValue.current = valueOf(store.getState());
210
+ }
189
211
  });
190
212
  return {
191
213
  store,
192
214
  state: (0, react.useSyncExternalStore)((listener) => store.subscribe(listener), () => store.getState(), () => store.getState())
193
215
  };
194
216
  }
217
+ function valueOf(state) {
218
+ return state.value;
219
+ }
220
+ /** A finished value: not empty, half typed, or a range with one end still to pick. */
221
+ function isChosen(value) {
222
+ if (Array.isArray(value)) return value.length > 0;
223
+ if (typeof value === "object" && value !== null) return Object.values(value).every((part) => part !== "");
224
+ return value !== "" && value !== void 0;
225
+ }
226
+ /** What the day functions say about the days on screen, or null when there are none. */
227
+ function askDayFunctions(options, state) {
228
+ const given = DAY_FUNCTIONS.flatMap((key) => {
229
+ const option = options[key];
230
+ return typeof option === "function" ? [option] : [];
231
+ });
232
+ if (given.length === 0) return null;
233
+ const { weeks, calendarState } = state;
234
+ const dates = (weeks ?? calendarState?.weeks ?? []).flat().flatMap((cell) => cell ? [cell.date] : []);
235
+ return {
236
+ days: JSON.stringify(dates),
237
+ answers: JSON.stringify(dates.map((date) => given.map((ask) => ask(date))))
238
+ };
239
+ }
195
240
  /** Structural equality for plain data (dates, ranges, lists); identity for everything else. */
196
241
  function deepEqual(a, b) {
197
242
  if (Object.is(a, b)) return true;
@@ -408,7 +453,8 @@ function useDateRangePicker(options = {}) {
408
453
  function useDateTimePicker(options = {}) {
409
454
  const { id: givenId, ...storeOptions } = options;
410
455
  const { store, state } = useStore(_nepdatejs_datepicker.createDateTimePicker, storeOptions);
411
- const base = givenId ?? `ndp${(0, react.useId)().replace(/:/g, "")}`;
456
+ const generated = (0, react.useId)();
457
+ const base = givenId ?? `ndp${generated.replace(/:/g, "")}`;
412
458
  const calendar = useCalendarBindings(state.calendarState, store.calendar.actions, options.locale, {
413
459
  getSnapshot: () => store.calendar.getState(),
414
460
  onDayActivate: (date) => {
@@ -432,7 +478,8 @@ function useDateTimePicker(options = {}) {
432
478
  function useMultiDatePicker(options = {}) {
433
479
  const { id: givenId, ...storeOptions } = options;
434
480
  const { store, state } = useStore(_nepdatejs_datepicker.createMultiDatePicker, storeOptions);
435
- const input = givenId ?? `ndp${(0, react.useId)().replace(/:/g, "")}`;
481
+ const generated = (0, react.useId)();
482
+ const input = givenId ?? `ndp${generated.replace(/:/g, "")}`;
436
483
  const ids = {
437
484
  input,
438
485
  panel: `${input}-panel`,
@@ -569,4 +616,4 @@ Object.defineProperty(exports, "useStore", {
569
616
  }
570
617
  });
571
618
 
572
- //# sourceMappingURL=headless-HxTkvgbz.cjs.map
619
+ //# sourceMappingURL=headless-AEI6dxTJ.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"headless-AEI6dxTJ.cjs","names":["useRef","getLocale","useCallback","useEffect","useLayoutEffect","useRef","useState","useSyncExternalStore","createCalendar","createDatePicker","useId","getLocale","createDateRangePicker","createDateTimePicker","createMultiDatePicker"],"sources":["../src/bindings.ts","../src/use-store.ts","../src/hooks.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, type KeyboardEvent, type Ref } from 'react';\nimport { getLocale, type CalendarDate, type LocaleCode } from '@nepdatejs/core';\nimport type {\n CalendarActions,\n CalendarState,\n DayCell,\n FocusKey,\n PickerCell,\n} from '@nepdatejs/calendar';\n\nconst FOCUS_KEYS: ReadonlySet<string> = new Set([\n 'ArrowLeft',\n 'ArrowRight',\n 'ArrowUp',\n 'ArrowDown',\n 'Home',\n 'End',\n 'PageUp',\n 'PageDown',\n]);\n\ntype DataAttrs = Record<`data-${string}`, string | boolean | undefined>;\n\nexport interface ButtonProps extends DataAttrs {\n type: 'button';\n tabIndex?: number;\n disabled?: boolean;\n 'aria-label'?: string;\n 'aria-pressed'?: boolean;\n 'aria-current'?: 'date';\n onClick: () => void;\n onFocus?: () => void;\n onMouseEnter?: () => void;\n}\n\nexport interface GridProps {\n role: 'grid';\n 'aria-label': string;\n ref: Ref<HTMLTableElement>;\n onKeyDown: (event: KeyboardEvent) => void;\n onMouseLeave: () => void;\n}\n\n/** Prop getters that turn a calendar store into accessible markup. */\nexport interface CalendarBindings {\n readonly state: CalendarState;\n readonly actions: CalendarActions;\n readonly getGridProps: () => GridProps;\n readonly getDayProps: (cell: DayCell) => ButtonProps;\n readonly getPrevProps: () => ButtonProps;\n readonly getNextProps: () => ButtonProps;\n /** The title buttons: month and year in the day view, the year (or page) otherwise. */\n readonly getTitleButtons: () => { key: string; label: string; props: ButtonProps }[];\n readonly getOptionProps: (\n tile: PickerCell,\n index: number,\n tiles: readonly PickerCell[],\n ) => ButtonProps;\n /** Move focus into the grid (e.g. when a panel opens). */\n readonly focusGrid: () => void;\n}\n\nexport function useCalendarBindings(\n state: CalendarState,\n actions: CalendarActions,\n locale: LocaleCode | undefined,\n options: {\n /** The store's latest snapshot, to tell whether a key press changed anything. */\n readonly getSnapshot: () => CalendarState;\n readonly onDayActivate?: ((date: CalendarDate) => void) | undefined;\n },\n): CalendarBindings {\n const { getSnapshot, onDayActivate } = options;\n const grid = useRef<HTMLTableElement | null>(null);\n const root = useRef<HTMLElement | null>(null);\n const focusRequested = useRef(false);\n const labels = getLocale(locale).labels;\n\n const focusGrid = useCallback((): void => {\n const scope = grid.current?.closest('.ndp-calendar') ?? grid.current ?? root.current;\n scope\n ?.querySelector<HTMLElement>('.ndp-day[tabindex=\"0\"], .ndp-option[tabindex=\"0\"]')\n ?.focus();\n }, []);\n\n useEffect(() => {\n if (focusRequested.current) {\n focusRequested.current = false;\n focusGrid();\n }\n });\n\n const requestFocus = (): void => {\n focusRequested.current = true;\n };\n\n const activate = onDayActivate ?? ((date: CalendarDate) => actions.select(date));\n const [monthName, yearText] = splitTitle(state.title);\n const focusIndex = (tiles: readonly PickerCell[]): number => {\n const selected = tiles.findIndex((tile) => tile.isSelected);\n const current = tiles.findIndex((tile) => tile.isCurrent);\n\n return Math.max(0, selected === -1 ? current : selected);\n };\n\n return {\n state,\n actions,\n focusGrid,\n getGridProps: () => ({\n role: 'grid',\n 'aria-label': state.title,\n ref: (node: HTMLTableElement | null) => {\n grid.current = node;\n },\n onKeyDown: (event) => {\n if (!FOCUS_KEYS.has(event.key)) {\n return;\n }\n event.preventDefault();\n requestFocus();\n actions.moveFocus(event.key as FocusKey, { shift: event.shiftKey });\n // Nothing moved (at a limit): keep focus here. Otherwise the effect focuses after React renders.\n if (getSnapshot() === state) {\n focusRequested.current = false;\n focusGrid();\n }\n },\n onMouseLeave: () => {\n if (state.selectionMode === 'range') {\n actions.hover(null);\n }\n },\n }),\n getDayProps: (cell) => ({\n type: 'button',\n tabIndex: cell.isFocusTarget ? 0 : -1,\n disabled: cell.isDisabled,\n 'aria-pressed': cell.isSelected,\n ...(cell.isToday ? { 'aria-current': 'date' as const } : {}),\n 'data-state': cell.state,\n 'data-weekend': cell.isWeekend || undefined,\n 'data-preview': (cell.isInRangePreview && !cell.isSelected) || undefined,\n 'data-outside': cell.isOutside || undefined,\n onClick: () => {\n if (!cell.isDisabled) {\n activate(cell.date);\n }\n },\n onFocus: () => {\n if (!cell.isFocusTarget) {\n actions.focus(cell.date);\n }\n },\n onMouseEnter: () => {\n if (state.selectionMode === 'range') {\n actions.hover(cell.isDisabled ? null : cell.date);\n }\n },\n }),\n getPrevProps: () => ({\n type: 'button',\n disabled: !state.canPrev,\n 'aria-label': state.view === 'day' ? labels.previousMonth : labels.previousYear,\n onClick: () => {\n actions.prev();\n },\n }),\n getNextProps: () => ({\n type: 'button',\n disabled: !state.canNext,\n 'aria-label': state.view === 'day' ? labels.nextMonth : labels.nextYear,\n onClick: () => {\n actions.next();\n },\n }),\n getTitleButtons: () =>\n state.view === 'day'\n ? [\n {\n key: 'month',\n label: monthName,\n props: {\n type: 'button',\n 'aria-label': `${labels.month}: ${monthName}`,\n onClick: () => {\n requestFocus();\n actions.setView('month');\n },\n },\n },\n {\n key: 'year',\n label: yearText,\n props: {\n type: 'button',\n 'aria-label': `${labels.year}: ${yearText}`,\n onClick: () => {\n requestFocus();\n actions.setView('year');\n },\n },\n },\n ]\n : [\n {\n key: 'up',\n label: state.title,\n props: {\n type: 'button',\n 'aria-label':\n state.view === 'fiscal'\n ? state.title\n : `${labels.year}: ${state.title}`,\n onClick: () => {\n requestFocus();\n actions.setView(state.view === 'month' ? 'year' : 'day');\n },\n },\n },\n ],\n getOptionProps: (tile, index, tiles) => ({\n type: 'button',\n tabIndex: index === focusIndex(tiles) ? 0 : -1,\n disabled: tile.isDisabled,\n 'aria-pressed': tile.isSelected,\n 'data-state': tile.isSelected ? 'selected' : tile.isCurrent ? 'current' : 'default',\n onClick: () => {\n requestFocus();\n if (state.view === 'month') {\n actions.chooseMonth(tile.value as 1);\n } else if (state.view === 'year') {\n actions.chooseYear(tile.value);\n } else {\n actions.chooseFiscalYear(tile.value);\n }\n },\n }),\n };\n}\n\n/** \"Kartik 2083\" → [\"Kartik\", \"2083\"]. */\nfunction splitTitle(title: string): [string, string] {\n const space = title.lastIndexOf(' ');\n\n return space === -1 ? [title, ''] : [title.slice(0, space), title.slice(space + 1)];\n}\n","import {\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n useSyncExternalStore,\n} from 'react';\n\ninterface StoreLike<O, S> {\n getState(): S;\n subscribe(listener: () => void): () => void;\n setOptions(changes: Partial<O>): void;\n readonly actions?: object;\n}\n\n/** Function options whose answers decide how the calendar's days look. */\nconst DAY_FUNCTIONS = ['isDateDisabled', 'holidays', 'events'] as const;\n\ninterface DayAnswers {\n /** The days on screen; moving to another month isn't a change of answers. */\n readonly days: string;\n readonly answers: string;\n}\n\n/** useLayoutEffect in the browser, useEffect on the server (no warning). */\nexport const useIsomorphicLayoutEffect: typeof useEffect =\n typeof window === 'undefined' ? useEffect : useLayoutEffect;\n\ntype Fn = (...args: never[]) => unknown;\n\n/**\n * Create a store once and keep its options in step with props, without\n * loops: functions are wrapped once so their identity never changes, and data\n * options are compared by value, so inline objects and arrays are fine.\n */\nexport function useStore<O extends object, S, T extends StoreLike<O, S>>(\n create: (options: O) => T,\n options: O,\n): { store: T; state: S } {\n const latest = useRef(options);\n latest.current = options;\n const wrappers = useRef(new Map<string, Fn>());\n\n const prepare = (input: O): O => {\n const out: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(input)) {\n if (typeof value === 'function') {\n let wrapper = wrappers.current.get(key);\n if (!wrapper) {\n wrapper = (...args: never[]) =>\n ((latest.current as Record<string, unknown>)[key] as Fn | undefined)?.(\n ...args,\n );\n wrappers.current.set(key, wrapper);\n }\n out[key] = wrapper;\n } else {\n out[key] = value;\n }\n }\n\n return out as O;\n };\n\n const [store] = useState(() => create(prepare(options)));\n const previous = useRef<O>(prepare(options));\n const dayAnswers = useRef<DayAnswers | null>(null);\n const storeValue = useRef(valueOf(store.getState()));\n\n useIsomorphicLayoutEffect(() => {\n const next = prepare(options) as Record<string, unknown>;\n const before = previous.current as Record<string, unknown>;\n const changes: Record<string, unknown> = {};\n for (const key of new Set([...Object.keys(before), ...Object.keys(next)])) {\n if (!deepEqual(before[key], next[key])) {\n changes[key] = next[key];\n }\n }\n previous.current = next as O;\n\n // An inline function is wrapped once, so it never looks changed above. Ask it\n // about the days on screen instead, and redraw only if an answer is different.\n const current = askDayFunctions(options, store.getState());\n const asked = dayAnswers.current;\n dayAnswers.current = current;\n if (asked?.days === current?.days && asked?.answers !== current?.answers) {\n for (const key of DAY_FUNCTIONS) {\n if (key in next) {\n changes[key] = next[key];\n }\n }\n }\n if (Object.keys(changes).length > 0) {\n store.setOptions(changes as Partial<O>);\n }\n\n // A controlled picker shows what its parent holds. If the person entered a\n // date and the parent kept its value, put that value back.\n const value = valueOf(store.getState());\n const changedByUser = !deepEqual(value, storeValue.current) && !('value' in changes);\n storeValue.current = value;\n const held = next['value'];\n if (\n changedByUser &&\n held !== undefined &&\n isChosen(value) &&\n !deepEqual(value, held)\n ) {\n (store.actions as { setValue?: (value: unknown) => void } | undefined)?.setValue?.(\n held,\n );\n storeValue.current = valueOf(store.getState());\n }\n });\n\n const state = useSyncExternalStore(\n (listener) => store.subscribe(listener),\n () => store.getState(),\n () => store.getState(),\n );\n\n return { store, state };\n}\n\nfunction valueOf(state: unknown): unknown {\n return (state as { value?: unknown }).value;\n}\n\n/** A finished value: not empty, half typed, or a range with one end still to pick. */\nfunction isChosen(value: unknown): boolean {\n if (Array.isArray(value)) {\n return value.length > 0;\n }\n if (typeof value === 'object' && value !== null) {\n return Object.values(value).every((part) => part !== '');\n }\n\n return value !== '' && value !== undefined;\n}\n\n/** What the day functions say about the days on screen, or null when there are none. */\nfunction askDayFunctions(options: object, state: unknown): DayAnswers | null {\n const given = DAY_FUNCTIONS.flatMap((key) => {\n const option = (options as Record<string, unknown>)[key];\n\n return typeof option === 'function' ? [option as (date: unknown) => unknown] : [];\n });\n if (given.length === 0) {\n return null;\n }\n const { weeks, calendarState } = state as {\n weeks?: readonly (readonly ({ date: unknown } | null)[])[];\n calendarState?: { weeks: readonly (readonly ({ date: unknown } | null)[])[] };\n };\n const dates = (weeks ?? calendarState?.weeks ?? [])\n .flat()\n .flatMap((cell) => (cell ? [cell.date] : []));\n\n return {\n days: JSON.stringify(dates),\n answers: JSON.stringify(dates.map((date) => given.map((ask) => ask(date)))),\n };\n}\n\n/** Structural equality for plain data (dates, ranges, lists); identity for everything else. */\nexport function deepEqual(a: unknown, b: unknown): boolean {\n if (Object.is(a, b)) {\n return true;\n }\n if (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null) {\n return false;\n }\n if (Array.isArray(a) || Array.isArray(b)) {\n return (\n Array.isArray(a) &&\n Array.isArray(b) &&\n a.length === b.length &&\n a.every((item, index) => deepEqual(item, b[index]))\n );\n }\n if (\n Object.getPrototypeOf(a) !== Object.prototype ||\n Object.getPrototypeOf(b) !== Object.prototype\n ) {\n return false;\n }\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n\n return (\n keysA.length === keysB.length &&\n keysA.every((key) =>\n deepEqual((a as Record<string, unknown>)[key], (b as Record<string, unknown>)[key]),\n )\n );\n}\n","import { useId, type ChangeEvent, type KeyboardEvent } from 'react';\nimport { getLocale, type CalendarSystem } from '@nepdatejs/core';\nimport {\n createCalendar,\n type CalendarOptions,\n type CalendarState,\n type CalendarStore,\n} from '@nepdatejs/calendar';\nimport type { PresetState } from '@nepdatejs/datepicker';\nimport {\n createDatePicker,\n createDateRangePicker,\n createDateTimePicker,\n createMultiDatePicker,\n type DateTimePickerOptions,\n type DateTimePickerState,\n type DateTimePickerStore,\n type DatePickerOptions,\n type DatePickerState,\n type DatePickerStore,\n type DateRangePickerOptions,\n type DateRangePickerState,\n type DateRangePickerStore,\n type MultiDatePickerOptions,\n type MultiDatePickerState,\n type MultiDatePickerStore,\n type RangeField,\n} from '@nepdatejs/datepicker';\nimport { useCalendarBindings, type ButtonProps, type CalendarBindings } from './bindings';\nimport { useStore } from './use-store';\n\n/** A standalone calendar: state, actions and prop getters. */\nexport function useCalendar(\n options: CalendarOptions = {},\n): CalendarBindings & { store: CalendarStore } {\n const { store, state } = useStore<CalendarOptions, CalendarState, CalendarStore>(\n createCalendar,\n options,\n );\n const bindings = useCalendarBindings(state, store.actions, options.locale, {\n getSnapshot: () => store.getState(),\n });\n\n return { ...bindings, store };\n}\n\nexport interface InputProps {\n id: string;\n /** Left out for an inline picker, whose calendar is always in the page. */\n role?: 'combobox';\n type: 'text';\n inputMode: 'numeric';\n autoComplete: 'off';\n value: string;\n placeholder: string;\n 'aria-haspopup'?: 'dialog';\n 'aria-expanded'?: boolean;\n 'aria-controls': string;\n 'aria-invalid'?: true;\n 'aria-describedby'?: string;\n onChange: (event: ChangeEvent<HTMLInputElement>) => void;\n onBlur: () => void;\n onKeyDown: (event: KeyboardEvent<HTMLInputElement>) => void;\n}\n\nexport interface PanelProps {\n id: string;\n /** 'group' for an inline picker. */\n role: 'dialog' | 'group';\n 'aria-label': string;\n}\n\nexport interface DatePickerBindings {\n readonly state: DatePickerState;\n readonly actions: DatePickerStore['actions'];\n readonly store: DatePickerStore;\n /** Prop getters for the panel's calendar. */\n readonly calendar: CalendarBindings;\n readonly ids: { input: string; panel: string; hint: string };\n getInputProps(extra?: { id?: string | undefined }): InputProps;\n getToggleProps(): ButtonProps & { 'aria-expanded': boolean; 'aria-controls': string };\n getClearProps(): ButtonProps;\n /** The BS/AD switch inside the input. */\n getSwitchProps(): ButtonProps;\n /** One button of the BS/AD segment in the panel footer. */\n getCalendarOptionProps(calendar: CalendarSystem): ButtonProps;\n getTodayProps(): ButtonProps;\n getPanelProps(): PanelProps;\n /** A shortcut button (see state.presets). */\n getPresetProps(preset: PresetState): ButtonProps;\n}\n\n/** A BS/AD date picker without markup: wire the getters to your own elements. */\nexport function useDatePicker(\n options: DatePickerOptions & { id?: string | undefined } = {},\n): DatePickerBindings {\n const { id: givenId, ...storeOptions } = options;\n const { store, state } = useStore<DatePickerOptions, DatePickerState, DatePickerStore>(\n createDatePicker,\n storeOptions,\n );\n const generated = useId();\n const input = givenId ?? `ndp${generated.replace(/:/g, '')}`;\n const ids = { input, panel: `${input}-panel`, hint: `${input}-hint` };\n const labels = getLocale(options.locale);\n const calendar = useCalendarBindings(\n state.calendarState,\n store.calendar.actions,\n options.locale,\n {\n getSnapshot: () => store.calendar.getState(),\n onDayActivate: (date) => {\n store.actions.select(date);\n },\n },\n );\n const hasHint = state.error !== null || state.equivalentText !== null;\n\n return {\n state,\n actions: store.actions,\n store,\n calendar,\n ids,\n getInputProps: () => ({\n id: ids.input,\n ...popupProps(state),\n type: 'text',\n inputMode: 'numeric',\n autoComplete: 'off',\n value: state.text,\n placeholder: state.placeholder,\n 'aria-controls': ids.panel,\n ...(state.error ? { 'aria-invalid': true as const } : {}),\n ...(hasHint ? { 'aria-describedby': ids.hint } : {}),\n onChange: (event) => {\n store.actions.type(event.target.value);\n },\n onBlur: () => {\n store.actions.blur();\n },\n onKeyDown: (event) => {\n if (event.key === 'ArrowDown' && (event.altKey || state.text === '')) {\n event.preventDefault();\n store.actions.open();\n }\n },\n }),\n getToggleProps: () => ({\n type: 'button',\n 'aria-label': labels.labels.openCalendar,\n 'aria-expanded': state.open,\n 'aria-controls': ids.panel,\n onClick: () => {\n store.actions.toggle();\n },\n }),\n getClearProps: () => ({\n type: 'button',\n 'aria-label': labels.labels.clear,\n onClick: () => {\n store.actions.clear();\n },\n }),\n getSwitchProps: () => {\n const other: CalendarSystem = state.calendar === 'BS' ? 'AD' : 'BS';\n\n return {\n type: 'button',\n 'aria-label': `${labels.labels.calendar}: ${labels.calendarNames[state.calendar]} → ${labels.calendarNames[other]}`,\n onClick: () => {\n store.actions.switchCalendar(other);\n },\n };\n },\n getCalendarOptionProps: (option) => ({\n type: 'button',\n 'aria-pressed': state.calendar === option,\n onClick: () => {\n store.actions.switchCalendar(option);\n },\n }),\n getTodayProps: () => ({\n type: 'button',\n onClick: () => {\n store.actions.selectToday();\n },\n }),\n getPanelProps: () => ({\n id: ids.panel,\n role: state.inline ? 'group' : 'dialog',\n 'aria-label': labels.labels.chooseDate,\n }),\n getPresetProps: (preset) =>\n presetProps(preset, (id) => store.actions.applyPreset(id)),\n };\n}\n\n/** Combobox ARIA for a popup picker; an inline picker's input is a plain text field. */\nexport function popupProps(state: {\n readonly open: boolean;\n readonly inline: boolean;\n}): Pick<InputProps, 'role' | 'aria-haspopup' | 'aria-expanded'> {\n return state.inline\n ? {}\n : { role: 'combobox', 'aria-haspopup': 'dialog', 'aria-expanded': state.open };\n}\n\nfunction presetProps(preset: PresetState, apply: (id: string) => boolean): ButtonProps {\n return {\n type: 'button',\n 'aria-pressed': preset.isActive,\n disabled: preset.isDisabled,\n onClick: () => {\n apply(preset.id);\n },\n };\n}\n\nexport interface DateRangePickerBindings {\n readonly state: DateRangePickerState;\n readonly actions: DateRangePickerStore['actions'];\n readonly store: DateRangePickerStore;\n readonly calendar: CalendarBindings;\n readonly ids: { start: string; end: string; panel: string; hint: string };\n getInputProps(field: RangeField): Omit<InputProps, 'onChange' | 'onBlur'> & {\n onChange: (event: ChangeEvent<HTMLInputElement>) => void;\n onBlur: () => void;\n };\n getToggleProps(): ButtonProps & { 'aria-expanded': boolean; 'aria-controls': string };\n getCalendarOptionProps(calendar: CalendarSystem): ButtonProps;\n getPanelProps(): PanelProps;\n getPresetProps(preset: PresetState): ButtonProps;\n}\n\n/** A BS/AD date range picker without markup. */\nexport function useDateRangePicker(\n options: DateRangePickerOptions = {},\n): DateRangePickerBindings {\n const { store, state } = useStore<\n DateRangePickerOptions,\n DateRangePickerState,\n DateRangePickerStore\n >(createDateRangePicker, options);\n const base = `ndp${useId().replace(/:/g, '')}`;\n const ids = {\n start: `${base}-start`,\n end: `${base}-end`,\n panel: `${base}-panel`,\n hint: `${base}-hint`,\n };\n const labels = getLocale(options.locale);\n const calendar = useCalendarBindings(\n state.calendarState,\n store.calendar.actions,\n options.locale,\n {\n getSnapshot: () => store.calendar.getState(),\n onDayActivate: (date) => {\n store.actions.select(date);\n },\n },\n );\n const texts: Record<RangeField, string> = {\n start: state.startText,\n end: state.endText,\n };\n\n return {\n state,\n actions: store.actions,\n store,\n calendar,\n ids,\n getInputProps: (field) => {\n const invalid =\n state.error !== null &&\n (state.error.field === field || state.error.field === 'range');\n\n return {\n id: ids[field],\n ...popupProps(state),\n type: 'text',\n inputMode: 'numeric',\n autoComplete: 'off',\n value: texts[field],\n placeholder: state.placeholder,\n 'aria-controls': ids.panel,\n ...(invalid ? { 'aria-invalid': true as const } : {}),\n ...(state.error ? { 'aria-describedby': ids.hint } : {}),\n onChange: (event) => {\n store.actions.type(field, event.target.value);\n },\n onBlur: () => {\n store.actions.blur(field);\n },\n onKeyDown: (event) => {\n if (event.key === 'ArrowDown' && (event.altKey || texts[field] === '')) {\n event.preventDefault();\n store.actions.open();\n }\n },\n };\n },\n getToggleProps: () => ({\n type: 'button',\n 'aria-label': labels.labels.openCalendar,\n 'aria-expanded': state.open,\n 'aria-controls': ids.panel,\n onClick: () => {\n store.actions.toggle();\n },\n }),\n getCalendarOptionProps: (option) => ({\n type: 'button',\n 'aria-pressed': state.calendar === option,\n onClick: () => {\n store.actions.switchCalendar(option);\n },\n }),\n getPanelProps: () => ({\n id: ids.panel,\n role: state.inline ? 'group' : 'dialog',\n 'aria-label': labels.labels.chooseDate,\n }),\n getPresetProps: (preset) =>\n presetProps(preset, (id) => store.actions.applyPreset(id)),\n };\n}\n\nexport interface DateTimePickerBindings {\n readonly state: DateTimePickerState;\n readonly actions: DateTimePickerStore['actions'];\n readonly store: DateTimePickerStore;\n readonly calendar: CalendarBindings;\n readonly ids: { date: string; time: string; panel: string; hint: string };\n}\n\n/** A BS/AD date + time picker without markup. The value is a zoned ISO timestamp. */\nexport function useDateTimePicker(\n options: DateTimePickerOptions & { id?: string | undefined } = {},\n): DateTimePickerBindings {\n const { id: givenId, ...storeOptions } = options;\n const { store, state } = useStore<\n DateTimePickerOptions,\n DateTimePickerState,\n DateTimePickerStore\n >(createDateTimePicker, storeOptions);\n const generated = useId();\n const base = givenId ?? `ndp${generated.replace(/:/g, '')}`;\n const calendar = useCalendarBindings(\n state.calendarState,\n store.calendar.actions,\n options.locale,\n {\n getSnapshot: () => store.calendar.getState(),\n onDayActivate: (date) => {\n store.actions.selectDate(date);\n },\n },\n );\n\n return {\n state,\n actions: store.actions,\n store,\n calendar,\n ids: {\n date: base,\n time: `${base}-time`,\n panel: `${base}-panel`,\n hint: `${base}-hint`,\n },\n };\n}\n\nexport interface MultiDatePickerBindings {\n readonly state: MultiDatePickerState;\n readonly actions: MultiDatePickerStore['actions'];\n readonly store: MultiDatePickerStore;\n readonly calendar: CalendarBindings;\n readonly ids: { input: string; panel: string; hint: string };\n getInputProps(): InputProps;\n getToggleProps(): ButtonProps & { 'aria-expanded': boolean; 'aria-controls': string };\n getClearProps(): ButtonProps;\n getCalendarOptionProps(calendar: CalendarSystem): ButtonProps;\n getPanelProps(): PanelProps;\n}\n\n/** A picker for several separate BS/AD days, without markup (PICK-001). */\nexport function useMultiDatePicker(\n options: MultiDatePickerOptions & { id?: string | undefined } = {},\n): MultiDatePickerBindings {\n const { id: givenId, ...storeOptions } = options;\n const { store, state } = useStore<\n MultiDatePickerOptions,\n MultiDatePickerState,\n MultiDatePickerStore\n >(createMultiDatePicker, storeOptions);\n const generated = useId();\n const input = givenId ?? `ndp${generated.replace(/:/g, '')}`;\n const ids = { input, panel: `${input}-panel`, hint: `${input}-hint` };\n const labels = getLocale(options.locale);\n const calendar = useCalendarBindings(\n state.calendarState,\n store.calendar.actions,\n options.locale,\n {\n getSnapshot: () => store.calendar.getState(),\n onDayActivate: (date) => {\n store.actions.select(date);\n },\n },\n );\n\n return {\n state,\n actions: store.actions,\n store,\n calendar,\n ids,\n getInputProps: () => ({\n id: ids.input,\n ...popupProps(state),\n type: 'text',\n inputMode: 'numeric',\n autoComplete: 'off',\n value: state.text,\n placeholder: state.placeholder,\n 'aria-controls': ids.panel,\n ...(state.error\n ? { 'aria-invalid': true as const, 'aria-describedby': ids.hint }\n : {}),\n onChange: (event) => {\n store.actions.type(event.target.value);\n },\n onBlur: () => {\n store.actions.blur();\n },\n onKeyDown: (event) => {\n if (event.key === 'ArrowDown' && (event.altKey || state.text === '')) {\n event.preventDefault();\n store.actions.open();\n }\n },\n }),\n getToggleProps: () => ({\n type: 'button',\n 'aria-label': labels.labels.openCalendar,\n 'aria-expanded': state.open,\n 'aria-controls': ids.panel,\n onClick: () => {\n store.actions.toggle();\n },\n }),\n getClearProps: () => ({\n type: 'button',\n 'aria-label': labels.labels.clear,\n onClick: () => {\n store.actions.clear();\n },\n }),\n getCalendarOptionProps: (option) => ({\n type: 'button',\n 'aria-pressed': state.calendar === option,\n onClick: () => {\n store.actions.switchCalendar(option);\n },\n }),\n getPanelProps: () => ({\n id: ids.panel,\n role: state.inline ? 'group' : 'dialog',\n 'aria-label': labels.labels.chooseDate,\n }),\n };\n}\n"],"mappings":";;;;;AAUA,MAAM,6BAAkC,IAAI,IAAI;CAC9C;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;AA2CD,SAAgB,oBACd,OACA,SACA,QACA,SAKkB;CAClB,MAAM,EAAE,aAAa,kBAAkB;CACvC,MAAM,QAAA,GAAOA,MAAAA,OAAAA,CAAgC,IAAI;CACjD,MAAM,QAAA,GAAOA,MAAAA,OAAAA,CAA2B,IAAI;CAC5C,MAAM,kBAAA,GAAiBA,MAAAA,OAAAA,CAAO,KAAK;CACnC,MAAM,UAAA,GAASC,gBAAAA,UAAAA,CAAU,MAAM,CAAC,CAAC;CAEjC,MAAM,aAAA,GAAYC,MAAAA,YAAAA,OAAwB;EAExC,CADc,KAAK,SAAS,QAAQ,eAAe,KAAK,KAAK,WAAW,KAAK,QAAA,EAEzE,cAA2B,uDAAmD,CAAC,EAC/E,MAAM;CACZ,GAAG,CAAC,CAAC;CAEL,CAAA,GAAA,MAAA,UAAA,OAAgB;EACd,IAAI,eAAe,SAAS;GAC1B,eAAe,UAAU;GACzB,UAAU;EACZ;CACF,CAAC;CAED,MAAM,qBAA2B;EAC/B,eAAe,UAAU;CAC3B;CAEA,MAAM,WAAW,mBAAmB,SAAuB,QAAQ,OAAO,IAAI;CAC9E,MAAM,CAAC,WAAW,YAAY,WAAW,MAAM,KAAK;CACpD,MAAM,cAAc,UAAyC;EAC3D,MAAM,WAAW,MAAM,WAAW,SAAS,KAAK,UAAU;EAC1D,MAAM,UAAU,MAAM,WAAW,SAAS,KAAK,SAAS;EAExD,OAAO,KAAK,IAAI,GAAG,aAAa,KAAK,UAAU,QAAQ;CACzD;CAEA,OAAO;EACL;EACA;EACA;EACA,qBAAqB;GACnB,MAAM;GACN,cAAc,MAAM;GACpB,MAAM,SAAkC;IACtC,KAAK,UAAU;GACjB;GACA,YAAY,UAAU;IACpB,IAAI,CAAC,WAAW,IAAI,MAAM,GAAG,GAC3B;IAEF,MAAM,eAAe;IACrB,aAAa;IACb,QAAQ,UAAU,MAAM,KAAiB,EAAE,OAAO,MAAM,SAAS,CAAC;IAElE,IAAI,YAAY,MAAM,OAAO;KAC3B,eAAe,UAAU;KACzB,UAAU;IACZ;GACF;GACA,oBAAoB;IAClB,IAAI,MAAM,kBAAkB,SAC1B,QAAQ,MAAM,IAAI;GAEtB;EACF;EACA,cAAc,UAAU;GACtB,MAAM;GACN,UAAU,KAAK,gBAAgB,IAAI;GACnC,UAAU,KAAK;GACf,gBAAgB,KAAK;GACrB,GAAI,KAAK,UAAU,EAAE,gBAAgB,OAAgB,IAAI,CAAC;GAC1D,cAAc,KAAK;GACnB,gBAAgB,KAAK,aAAa,KAAA;GAClC,gBAAiB,KAAK,oBAAoB,CAAC,KAAK,cAAe,KAAA;GAC/D,gBAAgB,KAAK,aAAa,KAAA;GAClC,eAAe;IACb,IAAI,CAAC,KAAK,YACR,SAAS,KAAK,IAAI;GAEtB;GACA,eAAe;IACb,IAAI,CAAC,KAAK,eACR,QAAQ,MAAM,KAAK,IAAI;GAE3B;GACA,oBAAoB;IAClB,IAAI,MAAM,kBAAkB,SAC1B,QAAQ,MAAM,KAAK,aAAa,OAAO,KAAK,IAAI;GAEpD;EACF;EACA,qBAAqB;GACnB,MAAM;GACN,UAAU,CAAC,MAAM;GACjB,cAAc,MAAM,SAAS,QAAQ,OAAO,gBAAgB,OAAO;GACnE,eAAe;IACb,QAAQ,KAAK;GACf;EACF;EACA,qBAAqB;GACnB,MAAM;GACN,UAAU,CAAC,MAAM;GACjB,cAAc,MAAM,SAAS,QAAQ,OAAO,YAAY,OAAO;GAC/D,eAAe;IACb,QAAQ,KAAK;GACf;EACF;EACA,uBACE,MAAM,SAAS,QACX,CACE;GACE,KAAK;GACL,OAAO;GACP,OAAO;IACL,MAAM;IACN,cAAc,GAAG,OAAO,MAAM,IAAI;IAClC,eAAe;KACb,aAAa;KACb,QAAQ,QAAQ,OAAO;IACzB;GACF;EACF,GACA;GACE,KAAK;GACL,OAAO;GACP,OAAO;IACL,MAAM;IACN,cAAc,GAAG,OAAO,KAAK,IAAI;IACjC,eAAe;KACb,aAAa;KACb,QAAQ,QAAQ,MAAM;IACxB;GACF;EACF,CACF,IACA,CACE;GACE,KAAK;GACL,OAAO,MAAM;GACb,OAAO;IACL,MAAM;IACN,cACE,MAAM,SAAS,WACX,MAAM,QACN,GAAG,OAAO,KAAK,IAAI,MAAM;IAC/B,eAAe;KACb,aAAa;KACb,QAAQ,QAAQ,MAAM,SAAS,UAAU,SAAS,KAAK;IACzD;GACF;EACF,CACF;EACN,iBAAiB,MAAM,OAAO,WAAW;GACvC,MAAM;GACN,UAAU,UAAU,WAAW,KAAK,IAAI,IAAI;GAC5C,UAAU,KAAK;GACf,gBAAgB,KAAK;GACrB,cAAc,KAAK,aAAa,aAAa,KAAK,YAAY,YAAY;GAC1E,eAAe;IACb,aAAa;IACb,IAAI,MAAM,SAAS,SACjB,QAAQ,YAAY,KAAK,KAAU;SAC9B,IAAI,MAAM,SAAS,QACxB,QAAQ,WAAW,KAAK,KAAK;SAE7B,QAAQ,iBAAiB,KAAK,KAAK;GAEvC;EACF;CACF;AACF;;AAGA,SAAS,WAAW,OAAiC;CACnD,MAAM,QAAQ,MAAM,YAAY,GAAG;CAEnC,OAAO,UAAU,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,MAAM,GAAG,KAAK,GAAG,MAAM,MAAM,QAAQ,CAAC,CAAC;AACpF;;;;ACtOA,MAAM,gBAAgB;CAAC;CAAkB;CAAY;AAAQ;;AAS7D,MAAa,4BACX,OAAO,WAAW,cAAcC,MAAAA,YAAYC,MAAAA;;;;;;AAS9C,SAAgB,SACd,QACA,SACwB;CACxB,MAAM,UAAA,GAASC,MAAAA,OAAAA,CAAO,OAAO;CAC7B,OAAO,UAAU;CACjB,MAAM,YAAA,GAAWA,MAAAA,OAAAA,iBAAO,IAAI,IAAgB,CAAC;CAE7C,MAAM,WAAW,UAAgB;EAC/B,MAAM,MAA+B,CAAC;EACtC,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,KAAK,GAC7C,IAAI,OAAO,UAAU,YAAY;GAC/B,IAAI,UAAU,SAAS,QAAQ,IAAI,GAAG;GACtC,IAAI,CAAC,SAAS;IACZ,WAAW,GAAG,SACV,OAAO,QAAoC,IAAI,GAC/C,GAAG,IACL;IACF,SAAS,QAAQ,IAAI,KAAK,OAAO;GACnC;GACA,IAAI,OAAO;EACb,OACE,IAAI,OAAO;EAIf,OAAO;CACT;CAEA,MAAM,CAAC,UAAA,GAASC,MAAAA,SAAAA,OAAe,OAAO,QAAQ,OAAO,CAAC,CAAC;CACvD,MAAM,YAAA,GAAWD,MAAAA,OAAAA,CAAU,QAAQ,OAAO,CAAC;CAC3C,MAAM,cAAA,GAAaA,MAAAA,OAAAA,CAA0B,IAAI;CACjD,MAAM,cAAA,GAAaA,MAAAA,OAAAA,CAAO,QAAQ,MAAM,SAAS,CAAC,CAAC;CAEnD,gCAAgC;EAC9B,MAAM,OAAO,QAAQ,OAAO;EAC5B,MAAM,SAAS,SAAS;EACxB,MAAM,UAAmC,CAAC;EAC1C,KAAK,MAAM,uBAAO,IAAI,IAAI,CAAC,GAAG,OAAO,KAAK,MAAM,GAAG,GAAG,OAAO,KAAK,IAAI,CAAC,CAAC,GACtE,IAAI,CAAC,UAAU,OAAO,MAAM,KAAK,IAAI,GACnC,QAAQ,OAAO,KAAK;EAGxB,SAAS,UAAU;EAInB,MAAM,UAAU,gBAAgB,SAAS,MAAM,SAAS,CAAC;EACzD,MAAM,QAAQ,WAAW;EACzB,WAAW,UAAU;EACrB,IAAI,OAAO,SAAS,SAAS,QAAQ,OAAO,YAAY,SAAS,SAC1D;QAAA,MAAM,OAAO,eAChB,IAAI,OAAO,MACT,QAAQ,OAAO,KAAK;EAAA;EAI1B,IAAI,OAAO,KAAK,OAAO,CAAC,CAAC,SAAS,GAChC,MAAM,WAAW,OAAqB;EAKxC,MAAM,QAAQ,QAAQ,MAAM,SAAS,CAAC;EACtC,MAAM,gBAAgB,CAAC,UAAU,OAAO,WAAW,OAAO,KAAK,EAAE,WAAW;EAC5E,WAAW,UAAU;EACrB,MAAM,OAAO,KAAK;EAClB,IACE,iBACA,SAAS,KAAA,KACT,SAAS,KAAK,KACd,CAAC,UAAU,OAAO,IAAI,GACtB;GACA,MAAO,SAAiE,WACtE,IACF;GACA,WAAW,UAAU,QAAQ,MAAM,SAAS,CAAC;EAC/C;CACF,CAAC;CAQD,OAAO;EAAE;EAAO,QAAA,GANFE,MAAAA,qBAAAA,EACX,aAAa,MAAM,UAAU,QAAQ,SAChC,MAAM,SAAS,SACf,MAAM,SAAS,CAGH;CAAE;AACxB;AAEA,SAAS,QAAQ,OAAyB;CACxC,OAAQ,MAA8B;AACxC;;AAGA,SAAS,SAAS,OAAyB;CACzC,IAAI,MAAM,QAAQ,KAAK,GACrB,OAAO,MAAM,SAAS;CAExB,IAAI,OAAO,UAAU,YAAY,UAAU,MACzC,OAAO,OAAO,OAAO,KAAK,CAAC,CAAC,OAAO,SAAS,SAAS,EAAE;CAGzD,OAAO,UAAU,MAAM,UAAU,KAAA;AACnC;;AAGA,SAAS,gBAAgB,SAAiB,OAAmC;CAC3E,MAAM,QAAQ,cAAc,SAAS,QAAQ;EAC3C,MAAM,SAAU,QAAoC;EAEpD,OAAO,OAAO,WAAW,aAAa,CAAC,MAAoC,IAAI,CAAC;CAClF,CAAC;CACD,IAAI,MAAM,WAAW,GACnB,OAAO;CAET,MAAM,EAAE,OAAO,kBAAkB;CAIjC,MAAM,SAAS,SAAS,eAAe,SAAS,CAAC,EAAA,CAC9C,KAAK,CAAC,CACN,SAAS,SAAU,OAAO,CAAC,KAAK,IAAI,IAAI,CAAC,CAAE;CAE9C,OAAO;EACL,MAAM,KAAK,UAAU,KAAK;EAC1B,SAAS,KAAK,UAAU,MAAM,KAAK,SAAS,MAAM,KAAK,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC;CAC5E;AACF;;AAGA,SAAgB,UAAU,GAAY,GAAqB;CACzD,IAAI,OAAO,GAAG,GAAG,CAAC,GAChB,OAAO;CAET,IAAI,OAAO,MAAM,YAAY,OAAO,MAAM,YAAY,MAAM,QAAQ,MAAM,MACxE,OAAO;CAET,IAAI,MAAM,QAAQ,CAAC,KAAK,MAAM,QAAQ,CAAC,GACrC,OACE,MAAM,QAAQ,CAAC,KACf,MAAM,QAAQ,CAAC,KACf,EAAE,WAAW,EAAE,UACf,EAAE,OAAO,MAAM,UAAU,UAAU,MAAM,EAAE,MAAM,CAAC;CAGtD,IACE,OAAO,eAAe,CAAC,MAAM,OAAO,aACpC,OAAO,eAAe,CAAC,MAAM,OAAO,WAEpC,OAAO;CAET,MAAM,QAAQ,OAAO,KAAK,CAAC;CAC3B,MAAM,QAAQ,OAAO,KAAK,CAAC;CAE3B,OACE,MAAM,WAAW,MAAM,UACvB,MAAM,OAAO,QACX,UAAW,EAA8B,MAAO,EAA8B,IAAI,CACpF;AAEJ;;;;ACnKA,SAAgB,YACd,UAA2B,CAAC,GACiB;CAC7C,MAAM,EAAE,OAAO,UAAU,SACvBC,oBAAAA,gBACA,OACF;CAKA,OAAO;EAAE,GAJQ,oBAAoB,OAAO,MAAM,SAAS,QAAQ,QAAQ,EACzE,mBAAmB,MAAM,SAAS,EACpC,CAEmB;EAAG;CAAM;AAC9B;;AAiDA,SAAgB,cACd,UAA2D,CAAC,GACxC;CACpB,MAAM,EAAE,IAAI,SAAS,GAAG,iBAAiB;CACzC,MAAM,EAAE,OAAO,UAAU,SACvBC,sBAAAA,kBACA,YACF;CACA,MAAM,aAAA,GAAYC,MAAAA,MAAAA,CAAM;CACxB,MAAM,QAAQ,WAAW,MAAM,UAAU,QAAQ,MAAM,EAAE;CACzD,MAAM,MAAM;EAAE;EAAO,OAAO,GAAG,MAAM;EAAS,MAAM,GAAG,MAAM;CAAO;CACpE,MAAM,UAAA,GAASC,gBAAAA,UAAAA,CAAU,QAAQ,MAAM;CACvC,MAAM,WAAW,oBACf,MAAM,eACN,MAAM,SAAS,SACf,QAAQ,QACR;EACE,mBAAmB,MAAM,SAAS,SAAS;EAC3C,gBAAgB,SAAS;GACvB,MAAM,QAAQ,OAAO,IAAI;EAC3B;CACF,CACF;CACA,MAAM,UAAU,MAAM,UAAU,QAAQ,MAAM,mBAAmB;CAEjE,OAAO;EACL;EACA,SAAS,MAAM;EACf;EACA;EACA;EACA,sBAAsB;GACpB,IAAI,IAAI;GACR,GAAG,WAAW,KAAK;GACnB,MAAM;GACN,WAAW;GACX,cAAc;GACd,OAAO,MAAM;GACb,aAAa,MAAM;GACnB,iBAAiB,IAAI;GACrB,GAAI,MAAM,QAAQ,EAAE,gBAAgB,KAAc,IAAI,CAAC;GACvD,GAAI,UAAU,EAAE,oBAAoB,IAAI,KAAK,IAAI,CAAC;GAClD,WAAW,UAAU;IACnB,MAAM,QAAQ,KAAK,MAAM,OAAO,KAAK;GACvC;GACA,cAAc;IACZ,MAAM,QAAQ,KAAK;GACrB;GACA,YAAY,UAAU;IACpB,IAAI,MAAM,QAAQ,gBAAgB,MAAM,UAAU,MAAM,SAAS,KAAK;KACpE,MAAM,eAAe;KACrB,MAAM,QAAQ,KAAK;IACrB;GACF;EACF;EACA,uBAAuB;GACrB,MAAM;GACN,cAAc,OAAO,OAAO;GAC5B,iBAAiB,MAAM;GACvB,iBAAiB,IAAI;GACrB,eAAe;IACb,MAAM,QAAQ,OAAO;GACvB;EACF;EACA,sBAAsB;GACpB,MAAM;GACN,cAAc,OAAO,OAAO;GAC5B,eAAe;IACb,MAAM,QAAQ,MAAM;GACtB;EACF;EACA,sBAAsB;GACpB,MAAM,QAAwB,MAAM,aAAa,OAAO,OAAO;GAE/D,OAAO;IACL,MAAM;IACN,cAAc,GAAG,OAAO,OAAO,SAAS,IAAI,OAAO,cAAc,MAAM,UAAU,KAAK,OAAO,cAAc;IAC3G,eAAe;KACb,MAAM,QAAQ,eAAe,KAAK;IACpC;GACF;EACF;EACA,yBAAyB,YAAY;GACnC,MAAM;GACN,gBAAgB,MAAM,aAAa;GACnC,eAAe;IACb,MAAM,QAAQ,eAAe,MAAM;GACrC;EACF;EACA,sBAAsB;GACpB,MAAM;GACN,eAAe;IACb,MAAM,QAAQ,YAAY;GAC5B;EACF;EACA,sBAAsB;GACpB,IAAI,IAAI;GACR,MAAM,MAAM,SAAS,UAAU;GAC/B,cAAc,OAAO,OAAO;EAC9B;EACA,iBAAiB,WACf,YAAY,SAAS,OAAO,MAAM,QAAQ,YAAY,EAAE,CAAC;CAC7D;AACF;;AAGA,SAAgB,WAAW,OAGsC;CAC/D,OAAO,MAAM,SACT,CAAC,IACD;EAAE,MAAM;EAAY,iBAAiB;EAAU,iBAAiB,MAAM;CAAK;AACjF;AAEA,SAAS,YAAY,QAAqB,OAA6C;CACrF,OAAO;EACL,MAAM;EACN,gBAAgB,OAAO;EACvB,UAAU,OAAO;EACjB,eAAe;GACb,MAAM,OAAO,EAAE;EACjB;CACF;AACF;;AAmBA,SAAgB,mBACd,UAAkC,CAAC,GACV;CACzB,MAAM,EAAE,OAAO,UAAU,SAIvBC,sBAAAA,uBAAuB,OAAO;CAChC,MAAM,OAAO,OAAA,GAAMF,MAAAA,MAAAA,CAAM,CAAC,CAAC,QAAQ,MAAM,EAAE;CAC3C,MAAM,MAAM;EACV,OAAO,GAAG,KAAK;EACf,KAAK,GAAG,KAAK;EACb,OAAO,GAAG,KAAK;EACf,MAAM,GAAG,KAAK;CAChB;CACA,MAAM,UAAA,GAASC,gBAAAA,UAAAA,CAAU,QAAQ,MAAM;CACvC,MAAM,WAAW,oBACf,MAAM,eACN,MAAM,SAAS,SACf,QAAQ,QACR;EACE,mBAAmB,MAAM,SAAS,SAAS;EAC3C,gBAAgB,SAAS;GACvB,MAAM,QAAQ,OAAO,IAAI;EAC3B;CACF,CACF;CACA,MAAM,QAAoC;EACxC,OAAO,MAAM;EACb,KAAK,MAAM;CACb;CAEA,OAAO;EACL;EACA,SAAS,MAAM;EACf;EACA;EACA;EACA,gBAAgB,UAAU;GACxB,MAAM,UACJ,MAAM,UAAU,SACf,MAAM,MAAM,UAAU,SAAS,MAAM,MAAM,UAAU;GAExD,OAAO;IACL,IAAI,IAAI;IACR,GAAG,WAAW,KAAK;IACnB,MAAM;IACN,WAAW;IACX,cAAc;IACd,OAAO,MAAM;IACb,aAAa,MAAM;IACnB,iBAAiB,IAAI;IACrB,GAAI,UAAU,EAAE,gBAAgB,KAAc,IAAI,CAAC;IACnD,GAAI,MAAM,QAAQ,EAAE,oBAAoB,IAAI,KAAK,IAAI,CAAC;IACtD,WAAW,UAAU;KACnB,MAAM,QAAQ,KAAK,OAAO,MAAM,OAAO,KAAK;IAC9C;IACA,cAAc;KACZ,MAAM,QAAQ,KAAK,KAAK;IAC1B;IACA,YAAY,UAAU;KACpB,IAAI,MAAM,QAAQ,gBAAgB,MAAM,UAAU,MAAM,WAAW,KAAK;MACtE,MAAM,eAAe;MACrB,MAAM,QAAQ,KAAK;KACrB;IACF;GACF;EACF;EACA,uBAAuB;GACrB,MAAM;GACN,cAAc,OAAO,OAAO;GAC5B,iBAAiB,MAAM;GACvB,iBAAiB,IAAI;GACrB,eAAe;IACb,MAAM,QAAQ,OAAO;GACvB;EACF;EACA,yBAAyB,YAAY;GACnC,MAAM;GACN,gBAAgB,MAAM,aAAa;GACnC,eAAe;IACb,MAAM,QAAQ,eAAe,MAAM;GACrC;EACF;EACA,sBAAsB;GACpB,IAAI,IAAI;GACR,MAAM,MAAM,SAAS,UAAU;GAC/B,cAAc,OAAO,OAAO;EAC9B;EACA,iBAAiB,WACf,YAAY,SAAS,OAAO,MAAM,QAAQ,YAAY,EAAE,CAAC;CAC7D;AACF;;AAWA,SAAgB,kBACd,UAA+D,CAAC,GACxC;CACxB,MAAM,EAAE,IAAI,SAAS,GAAG,iBAAiB;CACzC,MAAM,EAAE,OAAO,UAAU,SAIvBE,sBAAAA,sBAAsB,YAAY;CACpC,MAAM,aAAA,GAAYH,MAAAA,MAAAA,CAAM;CACxB,MAAM,OAAO,WAAW,MAAM,UAAU,QAAQ,MAAM,EAAE;CACxD,MAAM,WAAW,oBACf,MAAM,eACN,MAAM,SAAS,SACf,QAAQ,QACR;EACE,mBAAmB,MAAM,SAAS,SAAS;EAC3C,gBAAgB,SAAS;GACvB,MAAM,QAAQ,WAAW,IAAI;EAC/B;CACF,CACF;CAEA,OAAO;EACL;EACA,SAAS,MAAM;EACf;EACA;EACA,KAAK;GACH,MAAM;GACN,MAAM,GAAG,KAAK;GACd,OAAO,GAAG,KAAK;GACf,MAAM,GAAG,KAAK;EAChB;CACF;AACF;;AAgBA,SAAgB,mBACd,UAAgE,CAAC,GACxC;CACzB,MAAM,EAAE,IAAI,SAAS,GAAG,iBAAiB;CACzC,MAAM,EAAE,OAAO,UAAU,SAIvBI,sBAAAA,uBAAuB,YAAY;CACrC,MAAM,aAAA,GAAYJ,MAAAA,MAAAA,CAAM;CACxB,MAAM,QAAQ,WAAW,MAAM,UAAU,QAAQ,MAAM,EAAE;CACzD,MAAM,MAAM;EAAE;EAAO,OAAO,GAAG,MAAM;EAAS,MAAM,GAAG,MAAM;CAAO;CACpE,MAAM,UAAA,GAASC,gBAAAA,UAAAA,CAAU,QAAQ,MAAM;CACvC,MAAM,WAAW,oBACf,MAAM,eACN,MAAM,SAAS,SACf,QAAQ,QACR;EACE,mBAAmB,MAAM,SAAS,SAAS;EAC3C,gBAAgB,SAAS;GACvB,MAAM,QAAQ,OAAO,IAAI;EAC3B;CACF,CACF;CAEA,OAAO;EACL;EACA,SAAS,MAAM;EACf;EACA;EACA;EACA,sBAAsB;GACpB,IAAI,IAAI;GACR,GAAG,WAAW,KAAK;GACnB,MAAM;GACN,WAAW;GACX,cAAc;GACd,OAAO,MAAM;GACb,aAAa,MAAM;GACnB,iBAAiB,IAAI;GACrB,GAAI,MAAM,QACN;IAAE,gBAAgB;IAAe,oBAAoB,IAAI;GAAK,IAC9D,CAAC;GACL,WAAW,UAAU;IACnB,MAAM,QAAQ,KAAK,MAAM,OAAO,KAAK;GACvC;GACA,cAAc;IACZ,MAAM,QAAQ,KAAK;GACrB;GACA,YAAY,UAAU;IACpB,IAAI,MAAM,QAAQ,gBAAgB,MAAM,UAAU,MAAM,SAAS,KAAK;KACpE,MAAM,eAAe;KACrB,MAAM,QAAQ,KAAK;IACrB;GACF;EACF;EACA,uBAAuB;GACrB,MAAM;GACN,cAAc,OAAO,OAAO;GAC5B,iBAAiB,MAAM;GACvB,iBAAiB,IAAI;GACrB,eAAe;IACb,MAAM,QAAQ,OAAO;GACvB;EACF;EACA,sBAAsB;GACpB,MAAM;GACN,cAAc,OAAO,OAAO;GAC5B,eAAe;IACb,MAAM,QAAQ,MAAM;GACtB;EACF;EACA,yBAAyB,YAAY;GACnC,MAAM;GACN,gBAAgB,MAAM,aAAa;GACnC,eAAe;IACb,MAAM,QAAQ,eAAe,MAAM;GACrC;EACF;EACA,sBAAsB;GACpB,IAAI,IAAI;GACR,MAAM,MAAM,SAAS,UAAU;GAC/B,cAAc,OAAO,OAAO;EAC9B;CACF;AACF"}
@@ -154,6 +154,12 @@ function splitTitle(title) {
154
154
  }
155
155
  //#endregion
156
156
  //#region src/use-store.ts
157
+ /** Function options whose answers decide how the calendar's days look. */
158
+ const DAY_FUNCTIONS = [
159
+ "isDateDisabled",
160
+ "holidays",
161
+ "events"
162
+ ];
157
163
  /** useLayoutEffect in the browser, useEffect on the server (no warning). */
158
164
  const useIsomorphicLayoutEffect = typeof window === "undefined" ? useEffect : useLayoutEffect;
159
165
  /**
@@ -179,19 +185,58 @@ function useStore(create, options) {
179
185
  };
180
186
  const [store] = useState(() => create(prepare(options)));
181
187
  const previous = useRef(prepare(options));
188
+ const dayAnswers = useRef(null);
189
+ const storeValue = useRef(valueOf(store.getState()));
182
190
  useIsomorphicLayoutEffect(() => {
183
191
  const next = prepare(options);
184
192
  const before = previous.current;
185
193
  const changes = {};
186
194
  for (const key of /* @__PURE__ */ new Set([...Object.keys(before), ...Object.keys(next)])) if (!deepEqual(before[key], next[key])) changes[key] = next[key];
187
195
  previous.current = next;
196
+ const current = askDayFunctions(options, store.getState());
197
+ const asked = dayAnswers.current;
198
+ dayAnswers.current = current;
199
+ if (asked?.days === current?.days && asked?.answers !== current?.answers) {
200
+ for (const key of DAY_FUNCTIONS) if (key in next) changes[key] = next[key];
201
+ }
188
202
  if (Object.keys(changes).length > 0) store.setOptions(changes);
203
+ const value = valueOf(store.getState());
204
+ const changedByUser = !deepEqual(value, storeValue.current) && !("value" in changes);
205
+ storeValue.current = value;
206
+ const held = next["value"];
207
+ if (changedByUser && held !== void 0 && isChosen(value) && !deepEqual(value, held)) {
208
+ store.actions?.setValue?.(held);
209
+ storeValue.current = valueOf(store.getState());
210
+ }
189
211
  });
190
212
  return {
191
213
  store,
192
214
  state: useSyncExternalStore((listener) => store.subscribe(listener), () => store.getState(), () => store.getState())
193
215
  };
194
216
  }
217
+ function valueOf(state) {
218
+ return state.value;
219
+ }
220
+ /** A finished value: not empty, half typed, or a range with one end still to pick. */
221
+ function isChosen(value) {
222
+ if (Array.isArray(value)) return value.length > 0;
223
+ if (typeof value === "object" && value !== null) return Object.values(value).every((part) => part !== "");
224
+ return value !== "" && value !== void 0;
225
+ }
226
+ /** What the day functions say about the days on screen, or null when there are none. */
227
+ function askDayFunctions(options, state) {
228
+ const given = DAY_FUNCTIONS.flatMap((key) => {
229
+ const option = options[key];
230
+ return typeof option === "function" ? [option] : [];
231
+ });
232
+ if (given.length === 0) return null;
233
+ const { weeks, calendarState } = state;
234
+ const dates = (weeks ?? calendarState?.weeks ?? []).flat().flatMap((cell) => cell ? [cell.date] : []);
235
+ return {
236
+ days: JSON.stringify(dates),
237
+ answers: JSON.stringify(dates.map((date) => given.map((ask) => ask(date))))
238
+ };
239
+ }
195
240
  /** Structural equality for plain data (dates, ranges, lists); identity for everything else. */
196
241
  function deepEqual(a, b) {
197
242
  if (Object.is(a, b)) return true;
@@ -408,7 +453,8 @@ function useDateRangePicker(options = {}) {
408
453
  function useDateTimePicker(options = {}) {
409
454
  const { id: givenId, ...storeOptions } = options;
410
455
  const { store, state } = useStore(createDateTimePicker, storeOptions);
411
- const base = givenId ?? `ndp${useId().replace(/:/g, "")}`;
456
+ const generated = useId();
457
+ const base = givenId ?? `ndp${generated.replace(/:/g, "")}`;
412
458
  const calendar = useCalendarBindings(state.calendarState, store.calendar.actions, options.locale, {
413
459
  getSnapshot: () => store.calendar.getState(),
414
460
  onDayActivate: (date) => {
@@ -432,7 +478,8 @@ function useDateTimePicker(options = {}) {
432
478
  function useMultiDatePicker(options = {}) {
433
479
  const { id: givenId, ...storeOptions } = options;
434
480
  const { store, state } = useStore(createMultiDatePicker, storeOptions);
435
- const input = givenId ?? `ndp${useId().replace(/:/g, "")}`;
481
+ const generated = useId();
482
+ const input = givenId ?? `ndp${generated.replace(/:/g, "")}`;
436
483
  const ids = {
437
484
  input,
438
485
  panel: `${input}-panel`,
@@ -510,4 +557,4 @@ function useMultiDatePicker(options = {}) {
510
557
  //#endregion
511
558
  export { useDateTimePicker as a, useIsomorphicLayoutEffect as c, useDateRangePicker as i, useStore as l, useCalendar as n, useMultiDatePicker as o, useDatePicker as r, deepEqual as s, popupProps as t, useCalendarBindings as u };
512
559
 
513
- //# sourceMappingURL=headless-BK0XRHKb.js.map
560
+ //# sourceMappingURL=headless-CVj0DhD4.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"headless-CVj0DhD4.js","names":[],"sources":["../src/bindings.ts","../src/use-store.ts","../src/hooks.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, type KeyboardEvent, type Ref } from 'react';\nimport { getLocale, type CalendarDate, type LocaleCode } from '@nepdatejs/core';\nimport type {\n CalendarActions,\n CalendarState,\n DayCell,\n FocusKey,\n PickerCell,\n} from '@nepdatejs/calendar';\n\nconst FOCUS_KEYS: ReadonlySet<string> = new Set([\n 'ArrowLeft',\n 'ArrowRight',\n 'ArrowUp',\n 'ArrowDown',\n 'Home',\n 'End',\n 'PageUp',\n 'PageDown',\n]);\n\ntype DataAttrs = Record<`data-${string}`, string | boolean | undefined>;\n\nexport interface ButtonProps extends DataAttrs {\n type: 'button';\n tabIndex?: number;\n disabled?: boolean;\n 'aria-label'?: string;\n 'aria-pressed'?: boolean;\n 'aria-current'?: 'date';\n onClick: () => void;\n onFocus?: () => void;\n onMouseEnter?: () => void;\n}\n\nexport interface GridProps {\n role: 'grid';\n 'aria-label': string;\n ref: Ref<HTMLTableElement>;\n onKeyDown: (event: KeyboardEvent) => void;\n onMouseLeave: () => void;\n}\n\n/** Prop getters that turn a calendar store into accessible markup. */\nexport interface CalendarBindings {\n readonly state: CalendarState;\n readonly actions: CalendarActions;\n readonly getGridProps: () => GridProps;\n readonly getDayProps: (cell: DayCell) => ButtonProps;\n readonly getPrevProps: () => ButtonProps;\n readonly getNextProps: () => ButtonProps;\n /** The title buttons: month and year in the day view, the year (or page) otherwise. */\n readonly getTitleButtons: () => { key: string; label: string; props: ButtonProps }[];\n readonly getOptionProps: (\n tile: PickerCell,\n index: number,\n tiles: readonly PickerCell[],\n ) => ButtonProps;\n /** Move focus into the grid (e.g. when a panel opens). */\n readonly focusGrid: () => void;\n}\n\nexport function useCalendarBindings(\n state: CalendarState,\n actions: CalendarActions,\n locale: LocaleCode | undefined,\n options: {\n /** The store's latest snapshot, to tell whether a key press changed anything. */\n readonly getSnapshot: () => CalendarState;\n readonly onDayActivate?: ((date: CalendarDate) => void) | undefined;\n },\n): CalendarBindings {\n const { getSnapshot, onDayActivate } = options;\n const grid = useRef<HTMLTableElement | null>(null);\n const root = useRef<HTMLElement | null>(null);\n const focusRequested = useRef(false);\n const labels = getLocale(locale).labels;\n\n const focusGrid = useCallback((): void => {\n const scope = grid.current?.closest('.ndp-calendar') ?? grid.current ?? root.current;\n scope\n ?.querySelector<HTMLElement>('.ndp-day[tabindex=\"0\"], .ndp-option[tabindex=\"0\"]')\n ?.focus();\n }, []);\n\n useEffect(() => {\n if (focusRequested.current) {\n focusRequested.current = false;\n focusGrid();\n }\n });\n\n const requestFocus = (): void => {\n focusRequested.current = true;\n };\n\n const activate = onDayActivate ?? ((date: CalendarDate) => actions.select(date));\n const [monthName, yearText] = splitTitle(state.title);\n const focusIndex = (tiles: readonly PickerCell[]): number => {\n const selected = tiles.findIndex((tile) => tile.isSelected);\n const current = tiles.findIndex((tile) => tile.isCurrent);\n\n return Math.max(0, selected === -1 ? current : selected);\n };\n\n return {\n state,\n actions,\n focusGrid,\n getGridProps: () => ({\n role: 'grid',\n 'aria-label': state.title,\n ref: (node: HTMLTableElement | null) => {\n grid.current = node;\n },\n onKeyDown: (event) => {\n if (!FOCUS_KEYS.has(event.key)) {\n return;\n }\n event.preventDefault();\n requestFocus();\n actions.moveFocus(event.key as FocusKey, { shift: event.shiftKey });\n // Nothing moved (at a limit): keep focus here. Otherwise the effect focuses after React renders.\n if (getSnapshot() === state) {\n focusRequested.current = false;\n focusGrid();\n }\n },\n onMouseLeave: () => {\n if (state.selectionMode === 'range') {\n actions.hover(null);\n }\n },\n }),\n getDayProps: (cell) => ({\n type: 'button',\n tabIndex: cell.isFocusTarget ? 0 : -1,\n disabled: cell.isDisabled,\n 'aria-pressed': cell.isSelected,\n ...(cell.isToday ? { 'aria-current': 'date' as const } : {}),\n 'data-state': cell.state,\n 'data-weekend': cell.isWeekend || undefined,\n 'data-preview': (cell.isInRangePreview && !cell.isSelected) || undefined,\n 'data-outside': cell.isOutside || undefined,\n onClick: () => {\n if (!cell.isDisabled) {\n activate(cell.date);\n }\n },\n onFocus: () => {\n if (!cell.isFocusTarget) {\n actions.focus(cell.date);\n }\n },\n onMouseEnter: () => {\n if (state.selectionMode === 'range') {\n actions.hover(cell.isDisabled ? null : cell.date);\n }\n },\n }),\n getPrevProps: () => ({\n type: 'button',\n disabled: !state.canPrev,\n 'aria-label': state.view === 'day' ? labels.previousMonth : labels.previousYear,\n onClick: () => {\n actions.prev();\n },\n }),\n getNextProps: () => ({\n type: 'button',\n disabled: !state.canNext,\n 'aria-label': state.view === 'day' ? labels.nextMonth : labels.nextYear,\n onClick: () => {\n actions.next();\n },\n }),\n getTitleButtons: () =>\n state.view === 'day'\n ? [\n {\n key: 'month',\n label: monthName,\n props: {\n type: 'button',\n 'aria-label': `${labels.month}: ${monthName}`,\n onClick: () => {\n requestFocus();\n actions.setView('month');\n },\n },\n },\n {\n key: 'year',\n label: yearText,\n props: {\n type: 'button',\n 'aria-label': `${labels.year}: ${yearText}`,\n onClick: () => {\n requestFocus();\n actions.setView('year');\n },\n },\n },\n ]\n : [\n {\n key: 'up',\n label: state.title,\n props: {\n type: 'button',\n 'aria-label':\n state.view === 'fiscal'\n ? state.title\n : `${labels.year}: ${state.title}`,\n onClick: () => {\n requestFocus();\n actions.setView(state.view === 'month' ? 'year' : 'day');\n },\n },\n },\n ],\n getOptionProps: (tile, index, tiles) => ({\n type: 'button',\n tabIndex: index === focusIndex(tiles) ? 0 : -1,\n disabled: tile.isDisabled,\n 'aria-pressed': tile.isSelected,\n 'data-state': tile.isSelected ? 'selected' : tile.isCurrent ? 'current' : 'default',\n onClick: () => {\n requestFocus();\n if (state.view === 'month') {\n actions.chooseMonth(tile.value as 1);\n } else if (state.view === 'year') {\n actions.chooseYear(tile.value);\n } else {\n actions.chooseFiscalYear(tile.value);\n }\n },\n }),\n };\n}\n\n/** \"Kartik 2083\" → [\"Kartik\", \"2083\"]. */\nfunction splitTitle(title: string): [string, string] {\n const space = title.lastIndexOf(' ');\n\n return space === -1 ? [title, ''] : [title.slice(0, space), title.slice(space + 1)];\n}\n","import {\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n useSyncExternalStore,\n} from 'react';\n\ninterface StoreLike<O, S> {\n getState(): S;\n subscribe(listener: () => void): () => void;\n setOptions(changes: Partial<O>): void;\n readonly actions?: object;\n}\n\n/** Function options whose answers decide how the calendar's days look. */\nconst DAY_FUNCTIONS = ['isDateDisabled', 'holidays', 'events'] as const;\n\ninterface DayAnswers {\n /** The days on screen; moving to another month isn't a change of answers. */\n readonly days: string;\n readonly answers: string;\n}\n\n/** useLayoutEffect in the browser, useEffect on the server (no warning). */\nexport const useIsomorphicLayoutEffect: typeof useEffect =\n typeof window === 'undefined' ? useEffect : useLayoutEffect;\n\ntype Fn = (...args: never[]) => unknown;\n\n/**\n * Create a store once and keep its options in step with props, without\n * loops: functions are wrapped once so their identity never changes, and data\n * options are compared by value, so inline objects and arrays are fine.\n */\nexport function useStore<O extends object, S, T extends StoreLike<O, S>>(\n create: (options: O) => T,\n options: O,\n): { store: T; state: S } {\n const latest = useRef(options);\n latest.current = options;\n const wrappers = useRef(new Map<string, Fn>());\n\n const prepare = (input: O): O => {\n const out: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(input)) {\n if (typeof value === 'function') {\n let wrapper = wrappers.current.get(key);\n if (!wrapper) {\n wrapper = (...args: never[]) =>\n ((latest.current as Record<string, unknown>)[key] as Fn | undefined)?.(\n ...args,\n );\n wrappers.current.set(key, wrapper);\n }\n out[key] = wrapper;\n } else {\n out[key] = value;\n }\n }\n\n return out as O;\n };\n\n const [store] = useState(() => create(prepare(options)));\n const previous = useRef<O>(prepare(options));\n const dayAnswers = useRef<DayAnswers | null>(null);\n const storeValue = useRef(valueOf(store.getState()));\n\n useIsomorphicLayoutEffect(() => {\n const next = prepare(options) as Record<string, unknown>;\n const before = previous.current as Record<string, unknown>;\n const changes: Record<string, unknown> = {};\n for (const key of new Set([...Object.keys(before), ...Object.keys(next)])) {\n if (!deepEqual(before[key], next[key])) {\n changes[key] = next[key];\n }\n }\n previous.current = next as O;\n\n // An inline function is wrapped once, so it never looks changed above. Ask it\n // about the days on screen instead, and redraw only if an answer is different.\n const current = askDayFunctions(options, store.getState());\n const asked = dayAnswers.current;\n dayAnswers.current = current;\n if (asked?.days === current?.days && asked?.answers !== current?.answers) {\n for (const key of DAY_FUNCTIONS) {\n if (key in next) {\n changes[key] = next[key];\n }\n }\n }\n if (Object.keys(changes).length > 0) {\n store.setOptions(changes as Partial<O>);\n }\n\n // A controlled picker shows what its parent holds. If the person entered a\n // date and the parent kept its value, put that value back.\n const value = valueOf(store.getState());\n const changedByUser = !deepEqual(value, storeValue.current) && !('value' in changes);\n storeValue.current = value;\n const held = next['value'];\n if (\n changedByUser &&\n held !== undefined &&\n isChosen(value) &&\n !deepEqual(value, held)\n ) {\n (store.actions as { setValue?: (value: unknown) => void } | undefined)?.setValue?.(\n held,\n );\n storeValue.current = valueOf(store.getState());\n }\n });\n\n const state = useSyncExternalStore(\n (listener) => store.subscribe(listener),\n () => store.getState(),\n () => store.getState(),\n );\n\n return { store, state };\n}\n\nfunction valueOf(state: unknown): unknown {\n return (state as { value?: unknown }).value;\n}\n\n/** A finished value: not empty, half typed, or a range with one end still to pick. */\nfunction isChosen(value: unknown): boolean {\n if (Array.isArray(value)) {\n return value.length > 0;\n }\n if (typeof value === 'object' && value !== null) {\n return Object.values(value).every((part) => part !== '');\n }\n\n return value !== '' && value !== undefined;\n}\n\n/** What the day functions say about the days on screen, or null when there are none. */\nfunction askDayFunctions(options: object, state: unknown): DayAnswers | null {\n const given = DAY_FUNCTIONS.flatMap((key) => {\n const option = (options as Record<string, unknown>)[key];\n\n return typeof option === 'function' ? [option as (date: unknown) => unknown] : [];\n });\n if (given.length === 0) {\n return null;\n }\n const { weeks, calendarState } = state as {\n weeks?: readonly (readonly ({ date: unknown } | null)[])[];\n calendarState?: { weeks: readonly (readonly ({ date: unknown } | null)[])[] };\n };\n const dates = (weeks ?? calendarState?.weeks ?? [])\n .flat()\n .flatMap((cell) => (cell ? [cell.date] : []));\n\n return {\n days: JSON.stringify(dates),\n answers: JSON.stringify(dates.map((date) => given.map((ask) => ask(date)))),\n };\n}\n\n/** Structural equality for plain data (dates, ranges, lists); identity for everything else. */\nexport function deepEqual(a: unknown, b: unknown): boolean {\n if (Object.is(a, b)) {\n return true;\n }\n if (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null) {\n return false;\n }\n if (Array.isArray(a) || Array.isArray(b)) {\n return (\n Array.isArray(a) &&\n Array.isArray(b) &&\n a.length === b.length &&\n a.every((item, index) => deepEqual(item, b[index]))\n );\n }\n if (\n Object.getPrototypeOf(a) !== Object.prototype ||\n Object.getPrototypeOf(b) !== Object.prototype\n ) {\n return false;\n }\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n\n return (\n keysA.length === keysB.length &&\n keysA.every((key) =>\n deepEqual((a as Record<string, unknown>)[key], (b as Record<string, unknown>)[key]),\n )\n );\n}\n","import { useId, type ChangeEvent, type KeyboardEvent } from 'react';\nimport { getLocale, type CalendarSystem } from '@nepdatejs/core';\nimport {\n createCalendar,\n type CalendarOptions,\n type CalendarState,\n type CalendarStore,\n} from '@nepdatejs/calendar';\nimport type { PresetState } from '@nepdatejs/datepicker';\nimport {\n createDatePicker,\n createDateRangePicker,\n createDateTimePicker,\n createMultiDatePicker,\n type DateTimePickerOptions,\n type DateTimePickerState,\n type DateTimePickerStore,\n type DatePickerOptions,\n type DatePickerState,\n type DatePickerStore,\n type DateRangePickerOptions,\n type DateRangePickerState,\n type DateRangePickerStore,\n type MultiDatePickerOptions,\n type MultiDatePickerState,\n type MultiDatePickerStore,\n type RangeField,\n} from '@nepdatejs/datepicker';\nimport { useCalendarBindings, type ButtonProps, type CalendarBindings } from './bindings';\nimport { useStore } from './use-store';\n\n/** A standalone calendar: state, actions and prop getters. */\nexport function useCalendar(\n options: CalendarOptions = {},\n): CalendarBindings & { store: CalendarStore } {\n const { store, state } = useStore<CalendarOptions, CalendarState, CalendarStore>(\n createCalendar,\n options,\n );\n const bindings = useCalendarBindings(state, store.actions, options.locale, {\n getSnapshot: () => store.getState(),\n });\n\n return { ...bindings, store };\n}\n\nexport interface InputProps {\n id: string;\n /** Left out for an inline picker, whose calendar is always in the page. */\n role?: 'combobox';\n type: 'text';\n inputMode: 'numeric';\n autoComplete: 'off';\n value: string;\n placeholder: string;\n 'aria-haspopup'?: 'dialog';\n 'aria-expanded'?: boolean;\n 'aria-controls': string;\n 'aria-invalid'?: true;\n 'aria-describedby'?: string;\n onChange: (event: ChangeEvent<HTMLInputElement>) => void;\n onBlur: () => void;\n onKeyDown: (event: KeyboardEvent<HTMLInputElement>) => void;\n}\n\nexport interface PanelProps {\n id: string;\n /** 'group' for an inline picker. */\n role: 'dialog' | 'group';\n 'aria-label': string;\n}\n\nexport interface DatePickerBindings {\n readonly state: DatePickerState;\n readonly actions: DatePickerStore['actions'];\n readonly store: DatePickerStore;\n /** Prop getters for the panel's calendar. */\n readonly calendar: CalendarBindings;\n readonly ids: { input: string; panel: string; hint: string };\n getInputProps(extra?: { id?: string | undefined }): InputProps;\n getToggleProps(): ButtonProps & { 'aria-expanded': boolean; 'aria-controls': string };\n getClearProps(): ButtonProps;\n /** The BS/AD switch inside the input. */\n getSwitchProps(): ButtonProps;\n /** One button of the BS/AD segment in the panel footer. */\n getCalendarOptionProps(calendar: CalendarSystem): ButtonProps;\n getTodayProps(): ButtonProps;\n getPanelProps(): PanelProps;\n /** A shortcut button (see state.presets). */\n getPresetProps(preset: PresetState): ButtonProps;\n}\n\n/** A BS/AD date picker without markup: wire the getters to your own elements. */\nexport function useDatePicker(\n options: DatePickerOptions & { id?: string | undefined } = {},\n): DatePickerBindings {\n const { id: givenId, ...storeOptions } = options;\n const { store, state } = useStore<DatePickerOptions, DatePickerState, DatePickerStore>(\n createDatePicker,\n storeOptions,\n );\n const generated = useId();\n const input = givenId ?? `ndp${generated.replace(/:/g, '')}`;\n const ids = { input, panel: `${input}-panel`, hint: `${input}-hint` };\n const labels = getLocale(options.locale);\n const calendar = useCalendarBindings(\n state.calendarState,\n store.calendar.actions,\n options.locale,\n {\n getSnapshot: () => store.calendar.getState(),\n onDayActivate: (date) => {\n store.actions.select(date);\n },\n },\n );\n const hasHint = state.error !== null || state.equivalentText !== null;\n\n return {\n state,\n actions: store.actions,\n store,\n calendar,\n ids,\n getInputProps: () => ({\n id: ids.input,\n ...popupProps(state),\n type: 'text',\n inputMode: 'numeric',\n autoComplete: 'off',\n value: state.text,\n placeholder: state.placeholder,\n 'aria-controls': ids.panel,\n ...(state.error ? { 'aria-invalid': true as const } : {}),\n ...(hasHint ? { 'aria-describedby': ids.hint } : {}),\n onChange: (event) => {\n store.actions.type(event.target.value);\n },\n onBlur: () => {\n store.actions.blur();\n },\n onKeyDown: (event) => {\n if (event.key === 'ArrowDown' && (event.altKey || state.text === '')) {\n event.preventDefault();\n store.actions.open();\n }\n },\n }),\n getToggleProps: () => ({\n type: 'button',\n 'aria-label': labels.labels.openCalendar,\n 'aria-expanded': state.open,\n 'aria-controls': ids.panel,\n onClick: () => {\n store.actions.toggle();\n },\n }),\n getClearProps: () => ({\n type: 'button',\n 'aria-label': labels.labels.clear,\n onClick: () => {\n store.actions.clear();\n },\n }),\n getSwitchProps: () => {\n const other: CalendarSystem = state.calendar === 'BS' ? 'AD' : 'BS';\n\n return {\n type: 'button',\n 'aria-label': `${labels.labels.calendar}: ${labels.calendarNames[state.calendar]} → ${labels.calendarNames[other]}`,\n onClick: () => {\n store.actions.switchCalendar(other);\n },\n };\n },\n getCalendarOptionProps: (option) => ({\n type: 'button',\n 'aria-pressed': state.calendar === option,\n onClick: () => {\n store.actions.switchCalendar(option);\n },\n }),\n getTodayProps: () => ({\n type: 'button',\n onClick: () => {\n store.actions.selectToday();\n },\n }),\n getPanelProps: () => ({\n id: ids.panel,\n role: state.inline ? 'group' : 'dialog',\n 'aria-label': labels.labels.chooseDate,\n }),\n getPresetProps: (preset) =>\n presetProps(preset, (id) => store.actions.applyPreset(id)),\n };\n}\n\n/** Combobox ARIA for a popup picker; an inline picker's input is a plain text field. */\nexport function popupProps(state: {\n readonly open: boolean;\n readonly inline: boolean;\n}): Pick<InputProps, 'role' | 'aria-haspopup' | 'aria-expanded'> {\n return state.inline\n ? {}\n : { role: 'combobox', 'aria-haspopup': 'dialog', 'aria-expanded': state.open };\n}\n\nfunction presetProps(preset: PresetState, apply: (id: string) => boolean): ButtonProps {\n return {\n type: 'button',\n 'aria-pressed': preset.isActive,\n disabled: preset.isDisabled,\n onClick: () => {\n apply(preset.id);\n },\n };\n}\n\nexport interface DateRangePickerBindings {\n readonly state: DateRangePickerState;\n readonly actions: DateRangePickerStore['actions'];\n readonly store: DateRangePickerStore;\n readonly calendar: CalendarBindings;\n readonly ids: { start: string; end: string; panel: string; hint: string };\n getInputProps(field: RangeField): Omit<InputProps, 'onChange' | 'onBlur'> & {\n onChange: (event: ChangeEvent<HTMLInputElement>) => void;\n onBlur: () => void;\n };\n getToggleProps(): ButtonProps & { 'aria-expanded': boolean; 'aria-controls': string };\n getCalendarOptionProps(calendar: CalendarSystem): ButtonProps;\n getPanelProps(): PanelProps;\n getPresetProps(preset: PresetState): ButtonProps;\n}\n\n/** A BS/AD date range picker without markup. */\nexport function useDateRangePicker(\n options: DateRangePickerOptions = {},\n): DateRangePickerBindings {\n const { store, state } = useStore<\n DateRangePickerOptions,\n DateRangePickerState,\n DateRangePickerStore\n >(createDateRangePicker, options);\n const base = `ndp${useId().replace(/:/g, '')}`;\n const ids = {\n start: `${base}-start`,\n end: `${base}-end`,\n panel: `${base}-panel`,\n hint: `${base}-hint`,\n };\n const labels = getLocale(options.locale);\n const calendar = useCalendarBindings(\n state.calendarState,\n store.calendar.actions,\n options.locale,\n {\n getSnapshot: () => store.calendar.getState(),\n onDayActivate: (date) => {\n store.actions.select(date);\n },\n },\n );\n const texts: Record<RangeField, string> = {\n start: state.startText,\n end: state.endText,\n };\n\n return {\n state,\n actions: store.actions,\n store,\n calendar,\n ids,\n getInputProps: (field) => {\n const invalid =\n state.error !== null &&\n (state.error.field === field || state.error.field === 'range');\n\n return {\n id: ids[field],\n ...popupProps(state),\n type: 'text',\n inputMode: 'numeric',\n autoComplete: 'off',\n value: texts[field],\n placeholder: state.placeholder,\n 'aria-controls': ids.panel,\n ...(invalid ? { 'aria-invalid': true as const } : {}),\n ...(state.error ? { 'aria-describedby': ids.hint } : {}),\n onChange: (event) => {\n store.actions.type(field, event.target.value);\n },\n onBlur: () => {\n store.actions.blur(field);\n },\n onKeyDown: (event) => {\n if (event.key === 'ArrowDown' && (event.altKey || texts[field] === '')) {\n event.preventDefault();\n store.actions.open();\n }\n },\n };\n },\n getToggleProps: () => ({\n type: 'button',\n 'aria-label': labels.labels.openCalendar,\n 'aria-expanded': state.open,\n 'aria-controls': ids.panel,\n onClick: () => {\n store.actions.toggle();\n },\n }),\n getCalendarOptionProps: (option) => ({\n type: 'button',\n 'aria-pressed': state.calendar === option,\n onClick: () => {\n store.actions.switchCalendar(option);\n },\n }),\n getPanelProps: () => ({\n id: ids.panel,\n role: state.inline ? 'group' : 'dialog',\n 'aria-label': labels.labels.chooseDate,\n }),\n getPresetProps: (preset) =>\n presetProps(preset, (id) => store.actions.applyPreset(id)),\n };\n}\n\nexport interface DateTimePickerBindings {\n readonly state: DateTimePickerState;\n readonly actions: DateTimePickerStore['actions'];\n readonly store: DateTimePickerStore;\n readonly calendar: CalendarBindings;\n readonly ids: { date: string; time: string; panel: string; hint: string };\n}\n\n/** A BS/AD date + time picker without markup. The value is a zoned ISO timestamp. */\nexport function useDateTimePicker(\n options: DateTimePickerOptions & { id?: string | undefined } = {},\n): DateTimePickerBindings {\n const { id: givenId, ...storeOptions } = options;\n const { store, state } = useStore<\n DateTimePickerOptions,\n DateTimePickerState,\n DateTimePickerStore\n >(createDateTimePicker, storeOptions);\n const generated = useId();\n const base = givenId ?? `ndp${generated.replace(/:/g, '')}`;\n const calendar = useCalendarBindings(\n state.calendarState,\n store.calendar.actions,\n options.locale,\n {\n getSnapshot: () => store.calendar.getState(),\n onDayActivate: (date) => {\n store.actions.selectDate(date);\n },\n },\n );\n\n return {\n state,\n actions: store.actions,\n store,\n calendar,\n ids: {\n date: base,\n time: `${base}-time`,\n panel: `${base}-panel`,\n hint: `${base}-hint`,\n },\n };\n}\n\nexport interface MultiDatePickerBindings {\n readonly state: MultiDatePickerState;\n readonly actions: MultiDatePickerStore['actions'];\n readonly store: MultiDatePickerStore;\n readonly calendar: CalendarBindings;\n readonly ids: { input: string; panel: string; hint: string };\n getInputProps(): InputProps;\n getToggleProps(): ButtonProps & { 'aria-expanded': boolean; 'aria-controls': string };\n getClearProps(): ButtonProps;\n getCalendarOptionProps(calendar: CalendarSystem): ButtonProps;\n getPanelProps(): PanelProps;\n}\n\n/** A picker for several separate BS/AD days, without markup (PICK-001). */\nexport function useMultiDatePicker(\n options: MultiDatePickerOptions & { id?: string | undefined } = {},\n): MultiDatePickerBindings {\n const { id: givenId, ...storeOptions } = options;\n const { store, state } = useStore<\n MultiDatePickerOptions,\n MultiDatePickerState,\n MultiDatePickerStore\n >(createMultiDatePicker, storeOptions);\n const generated = useId();\n const input = givenId ?? `ndp${generated.replace(/:/g, '')}`;\n const ids = { input, panel: `${input}-panel`, hint: `${input}-hint` };\n const labels = getLocale(options.locale);\n const calendar = useCalendarBindings(\n state.calendarState,\n store.calendar.actions,\n options.locale,\n {\n getSnapshot: () => store.calendar.getState(),\n onDayActivate: (date) => {\n store.actions.select(date);\n },\n },\n );\n\n return {\n state,\n actions: store.actions,\n store,\n calendar,\n ids,\n getInputProps: () => ({\n id: ids.input,\n ...popupProps(state),\n type: 'text',\n inputMode: 'numeric',\n autoComplete: 'off',\n value: state.text,\n placeholder: state.placeholder,\n 'aria-controls': ids.panel,\n ...(state.error\n ? { 'aria-invalid': true as const, 'aria-describedby': ids.hint }\n : {}),\n onChange: (event) => {\n store.actions.type(event.target.value);\n },\n onBlur: () => {\n store.actions.blur();\n },\n onKeyDown: (event) => {\n if (event.key === 'ArrowDown' && (event.altKey || state.text === '')) {\n event.preventDefault();\n store.actions.open();\n }\n },\n }),\n getToggleProps: () => ({\n type: 'button',\n 'aria-label': labels.labels.openCalendar,\n 'aria-expanded': state.open,\n 'aria-controls': ids.panel,\n onClick: () => {\n store.actions.toggle();\n },\n }),\n getClearProps: () => ({\n type: 'button',\n 'aria-label': labels.labels.clear,\n onClick: () => {\n store.actions.clear();\n },\n }),\n getCalendarOptionProps: (option) => ({\n type: 'button',\n 'aria-pressed': state.calendar === option,\n onClick: () => {\n store.actions.switchCalendar(option);\n },\n }),\n getPanelProps: () => ({\n id: ids.panel,\n role: state.inline ? 'group' : 'dialog',\n 'aria-label': labels.labels.chooseDate,\n }),\n };\n}\n"],"mappings":"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"}
@@ -177,6 +177,7 @@ interface StoreLike<O, S> {
177
177
  getState(): S;
178
178
  subscribe(listener: () => void): () => void;
179
179
  setOptions(changes: Partial<O>): void;
180
+ readonly actions?: object;
180
181
  }
181
182
  /**
182
183
  * Create a store once and keep its options in step with props, without
@@ -191,4 +192,4 @@ declare function useStore<O extends object, S, T extends StoreLike<O, S>>(create
191
192
  declare function deepEqual(a: unknown, b: unknown): boolean;
192
193
  //#endregion
193
194
  export { useCalendarBindings as _, DateTimePickerBindings as a, PanelProps as c, useDateRangePicker as d, useDateTimePicker as f, GridProps as g, CalendarBindings as h, DateRangePickerBindings as i, useCalendar as l, ButtonProps as m, useStore as n, InputProps as o, useMultiDatePicker as p, DatePickerBindings as r, MultiDatePickerBindings as s, deepEqual as t, useDatePicker as u };
194
- //# sourceMappingURL=headless-CFZ06zLn.d.ts.map
195
+ //# sourceMappingURL=headless-ChE3zuYj.d.ts.map
@@ -177,6 +177,7 @@ interface StoreLike<O, S> {
177
177
  getState(): S;
178
178
  subscribe(listener: () => void): () => void;
179
179
  setOptions(changes: Partial<O>): void;
180
+ readonly actions?: object;
180
181
  }
181
182
  /**
182
183
  * Create a store once and keep its options in step with props, without
@@ -191,4 +192,4 @@ declare function useStore<O extends object, S, T extends StoreLike<O, S>>(create
191
192
  declare function deepEqual(a: unknown, b: unknown): boolean;
192
193
  //#endregion
193
194
  export { useCalendarBindings as _, DateTimePickerBindings as a, PanelProps as c, useDateRangePicker as d, useDateTimePicker as f, GridProps as g, CalendarBindings as h, DateRangePickerBindings as i, useCalendar as l, ButtonProps as m, useStore as n, InputProps as o, useMultiDatePicker as p, DatePickerBindings as r, MultiDatePickerBindings as s, deepEqual as t, useDatePicker as u };
194
- //# sourceMappingURL=headless-6BuUOtOR.d.cts.map
195
+ //# sourceMappingURL=headless-CrIIPnOF.d.cts.map
package/dist/headless.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const require_headless = require("./headless-HxTkvgbz.cjs");
3
+ const require_headless = require("./headless-AEI6dxTJ.cjs");
4
4
  exports.deepEqual = require_headless.deepEqual;
5
5
  exports.useCalendar = require_headless.useCalendar;
6
6
  exports.useCalendarBindings = require_headless.useCalendarBindings;
@@ -1,2 +1,2 @@
1
- import { _ as useCalendarBindings, a as DateTimePickerBindings, c as PanelProps, d as useDateRangePicker, f as useDateTimePicker, g as GridProps, h as CalendarBindings, i as DateRangePickerBindings, l as useCalendar, m as ButtonProps, n as useStore, o as InputProps, p as useMultiDatePicker, r as DatePickerBindings, s as MultiDatePickerBindings, t as deepEqual, u as useDatePicker } from "./headless-6BuUOtOR.cjs";
1
+ import { _ as useCalendarBindings, a as DateTimePickerBindings, c as PanelProps, d as useDateRangePicker, f as useDateTimePicker, g as GridProps, h as CalendarBindings, i as DateRangePickerBindings, l as useCalendar, m as ButtonProps, n as useStore, o as InputProps, p as useMultiDatePicker, r as DatePickerBindings, s as MultiDatePickerBindings, t as deepEqual, u as useDatePicker } from "./headless-CrIIPnOF.cjs";
2
2
  export { type ButtonProps, type CalendarBindings, type DatePickerBindings, type DateRangePickerBindings, type DateTimePickerBindings, type GridProps, type InputProps, type MultiDatePickerBindings, type PanelProps, deepEqual, useCalendar, useCalendarBindings, useDatePicker, useDateRangePicker, useDateTimePicker, useMultiDatePicker, useStore };
@@ -1,2 +1,2 @@
1
- import { _ as useCalendarBindings, a as DateTimePickerBindings, c as PanelProps, d as useDateRangePicker, f as useDateTimePicker, g as GridProps, h as CalendarBindings, i as DateRangePickerBindings, l as useCalendar, m as ButtonProps, n as useStore, o as InputProps, p as useMultiDatePicker, r as DatePickerBindings, s as MultiDatePickerBindings, t as deepEqual, u as useDatePicker } from "./headless-CFZ06zLn.js";
1
+ import { _ as useCalendarBindings, a as DateTimePickerBindings, c as PanelProps, d as useDateRangePicker, f as useDateTimePicker, g as GridProps, h as CalendarBindings, i as DateRangePickerBindings, l as useCalendar, m as ButtonProps, n as useStore, o as InputProps, p as useMultiDatePicker, r as DatePickerBindings, s as MultiDatePickerBindings, t as deepEqual, u as useDatePicker } from "./headless-ChE3zuYj.js";
2
2
  export { type ButtonProps, type CalendarBindings, type DatePickerBindings, type DateRangePickerBindings, type DateTimePickerBindings, type GridProps, type InputProps, type MultiDatePickerBindings, type PanelProps, deepEqual, useCalendar, useCalendarBindings, useDatePicker, useDateRangePicker, useDateTimePicker, useMultiDatePicker, useStore };
package/dist/headless.js CHANGED
@@ -1,2 +1,2 @@
1
1
  "use client";
2
- export { s as deepEqual, n as useCalendar, u as useCalendarBindings, r as useDatePicker, i as useDateRangePicker, a as useDateTimePicker, o as useMultiDatePicker, l as useStore } from "./headless-BK0XRHKb.js";
2
+ export { s as deepEqual, n as useCalendar, u as useCalendarBindings, r as useDatePicker, i as useDateRangePicker, a as useDateTimePicker, o as useMultiDatePicker, l as useStore } from "./headless-CVj0DhD4.js";
package/dist/index.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const require_headless = require("./headless-HxTkvgbz.cjs");
4
- const require_date_text = require("./date-text-BT82cZ7i.cjs");
3
+ const require_headless = require("./headless-AEI6dxTJ.cjs");
4
+ const require_date_text = require("./date-text-BX3Uag0O.cjs");
5
5
  let react_jsx_runtime = require("react/jsx-runtime");
6
6
  let react = require("react");
7
7
  let _nepdatejs_core = require("@nepdatejs/core");
@@ -152,6 +152,22 @@ function Calendar({ month, onMonthChange, className, theme, ...options }) {
152
152
  });
153
153
  }
154
154
  //#endregion
155
+ //#region src/page-locale.ts
156
+ const neverChanges = () => () => void 0;
157
+ /** Used on the server and while hydrating, so both render the same text. */
158
+ function defaultLocale() {
159
+ return (0, _nepdatejs_core.getConfig)().defaultLocale;
160
+ }
161
+ /** Nepali names and digits when the page language is Nepali. Browser only. */
162
+ function pageLocale() {
163
+ return document.documentElement.lang.toLowerCase().startsWith("ne") ? "ne" : defaultLocale();
164
+ }
165
+ /** The given locale, or else the page's language. */
166
+ function usePageLocale(given) {
167
+ const page = (0, react.useSyncExternalStore)(neverChanges, pageLocale, defaultLocale);
168
+ return given ?? page;
169
+ }
170
+ //#endregion
155
171
  //#region src/panel.ts
156
172
  /**
157
173
  * While `open`: show the panel in the top layer beside the anchor, close on an
@@ -226,7 +242,7 @@ function PanelBody({ presets, label, onPreset, children }) {
226
242
  */
227
243
  function DatePicker(props) {
228
244
  const { name, placeholder, required, disabled = false, clearable = true, showEquivalent = true, persistCalendar, panelLayout, theme, className, "aria-label": ariaLabel, "aria-invalid": ariaInvalid, "aria-describedby": ariaDescribedBy, locale: localeProp, onCalendarChange, ...options } = props;
229
- const locale = localeProp ?? pageLocale();
245
+ const locale = usePageLocale(localeProp);
230
246
  const picker = require_headless.useDatePicker({
231
247
  ...options,
232
248
  locale,
@@ -382,10 +398,6 @@ function DatePicker(props) {
382
398
  ]
383
399
  });
384
400
  }
385
- /** Nepali names and digits when the page language is Nepali. */
386
- function pageLocale() {
387
- return typeof document !== "undefined" && document.documentElement.lang.toLowerCase().startsWith("ne") ? "ne" : "en";
388
- }
389
401
  function read(key) {
390
402
  if (!key) return null;
391
403
  try {
@@ -405,9 +417,13 @@ function remember(key, calendar) {
405
417
  //#region src/date-range-picker.tsx
406
418
  /** Two BS/AD date fields sharing one calendar panel in range mode. */
407
419
  function DateRangePicker({ startName, endName, startLabel, endLabel, fiscalYearView = false, disabled = false, panelLayout, theme, className, ...options }) {
408
- const picker = require_headless.useDateRangePicker(options);
420
+ const locale = usePageLocale(options.locale);
421
+ const picker = require_headless.useDateRangePicker({
422
+ ...options,
423
+ locale
424
+ });
409
425
  const { state, store, calendar } = picker;
410
- const labels = (0, _nepdatejs_core.getLocale)(options.locale);
426
+ const labels = (0, _nepdatejs_core.getLocale)(locale);
411
427
  const field = (0, react.useRef)(null);
412
428
  const row = (0, react.useRef)(null);
413
429
  const panel = (0, react.useRef)(null);
@@ -564,8 +580,12 @@ function TimeColumns({ hours, minutes, locale, onHour, onMinute }) {
564
580
  //#region src/date-time-picker.tsx
565
581
  /** A BS/AD date and time field. The value is one instant, with the zone's offset. */
566
582
  function DateTimePicker({ name, required, disabled = false, panelLayout, theme, className, "aria-label": ariaLabel, timeLabel, ...options }) {
567
- const { state, store, calendar, ids } = require_headless.useDateTimePicker(options);
568
- const labels = (0, _nepdatejs_core.getLocale)(options.locale);
583
+ const locale = usePageLocale(options.locale);
584
+ const { state, store, calendar, ids } = require_headless.useDateTimePicker({
585
+ ...options,
586
+ locale
587
+ });
588
+ const labels = (0, _nepdatejs_core.getLocale)(locale);
569
589
  const field = (0, react.useRef)(null);
570
590
  const row = (0, react.useRef)(null);
571
591
  const panel = (0, react.useRef)(null);
@@ -746,9 +766,13 @@ function DateTimePicker({ name, required, disabled = false, panelLayout, theme,
746
766
  * the sorted AD days as "YYYY-MM-DD" strings.
747
767
  */
748
768
  function MultiDatePicker({ name, placeholder, required, disabled = false, clearable = true, panelLayout, theme, className, "aria-label": ariaLabel, ...options }) {
749
- const picker = require_headless.useMultiDatePicker(options);
769
+ const locale = usePageLocale(options.locale);
770
+ const picker = require_headless.useMultiDatePicker({
771
+ ...options,
772
+ locale
773
+ });
750
774
  const { state, store, calendar } = picker;
751
- const labels = (0, _nepdatejs_core.getLocale)(options.locale);
775
+ const labels = (0, _nepdatejs_core.getLocale)(locale);
752
776
  const field = (0, react.useRef)(null);
753
777
  const box = (0, react.useRef)(null);
754
778
  const panel = (0, react.useRef)(null);