@vielzeug/refine 2.0.0 → 2.0.2

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.
@@ -1 +1 @@
1
- {"version":3,"file":"date-picker.js","names":[],"sources":["../../src/core/date-picker.ts"],"sourcesContent":["import { Temporal, format, parsePlainDate } from '@vielzeug/tempo';\n\n// ── Public ISO helpers (single source of truth for both components) ───────────\n\n/**\n * Parses an ISO 8601 date string (`yyyy-MM-dd`) into a `Temporal.PlainDate`.\n * Returns `null` for any invalid / empty input — never throws.\n */\nexport function parseIso(iso: string | undefined | null): Temporal.PlainDate | null {\n if (!iso) return null;\n\n try {\n return parsePlainDate(iso);\n } catch {\n return null;\n }\n}\n\n/**\n * Serialises a `Temporal.PlainDate` (or `null`) to an ISO 8601 string (`yyyy-MM-dd`).\n * Returns `null` when the input is `null`.\n */\nexport function toIsoString(date: Temporal.PlainDate | null): string | null {\n return date ? date.toString() : null;\n}\n\n/**\n * Formats a `Temporal.PlainDate` for display in a given locale.\n * e.g. \"15 Jun 2025\" (default medium pattern).\n */\nexport function formatDisplayDate(date: Temporal.PlainDate, locale: string): string {\n return format(date, { intl: { day: 'numeric', month: 'short', year: 'numeric' }, locale, tz: 'UTC' });\n}\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport type DatePickerView = 'day' | 'month' | 'year';\n\nexport type DateCell = {\n /** Day-of-month number (1–31) */\n day: number;\n isDisabled: boolean;\n /** ISO date string yyyy-MM-dd — stable key for rendering */\n iso: string;\n isOutsideMonth: boolean;\n isSelected: boolean;\n isToday: boolean;\n plain: Temporal.PlainDate;\n};\n\nexport type MonthCell = {\n isDisabled: boolean;\n isSelected: boolean;\n label: string;\n /** 1-based month number (Temporal convention: 1 = January … 12 = December) */\n month: number;\n shortLabel: string;\n};\n\nexport type YearCell = {\n isDisabled: boolean;\n isSelected: boolean;\n year: number;\n};\n\nexport type DatePickerControlOptions = {\n /** Locale for day/month names, defaults to `navigator.language` or `'en'` */\n locale?: string;\n /** Maximum selectable date (inclusive) */\n max?: Temporal.PlainDate | null;\n /** Minimum selectable date (inclusive) */\n min?: Temporal.PlainDate | null;\n /** Called when a date is committed by the user */\n onChange: (date: Temporal.PlainDate | null) => void;\n /** Currently selected date */\n value?: Temporal.PlainDate | null;\n /**\n * Which days of the week to disable (0 = Sunday … 6 = Saturday).\n * @example [0, 6] disables weekends\n */\n weekendDays?: number[];\n};\n\nexport type DatePickerControl = {\n /** Ordered day cells for the visible month grid (includes leading/trailing days) */\n dayCells(): DateCell[];\n /** Month currently shown in the header (1-indexed, Temporal convention) */\n displayMonth(): number;\n /** Year currently shown in the header */\n displayYear(): number;\n /** Jump to a specific display month/year without selecting */\n goTo(year: number, month: number): void;\n /** All 12 month cells */\n monthCells(): MonthCell[];\n /** Move display month forward by one */\n nextMonth(): void;\n /** Move display year forward by one */\n nextYear(): void;\n /** Move display month backward by one */\n prevMonth(): void;\n /** Move display year backward by one */\n prevYear(): void;\n /** Select a date. Pass null to clear. */\n select(date: Temporal.PlainDate | null): void;\n /** The currently selected date, or null */\n selected(): Temporal.PlainDate | null;\n /** Switch the calendar view */\n setView(view: DatePickerView): void;\n /** Currently rendered calendar view */\n view(): DatePickerView;\n /** Short week-day labels in locale order e.g. [\"Su\",\"Mo\",…] */\n weekdayLabels(): string[];\n /** Year cells for the visible decade window */\n yearCells(): YearCell[];\n};\n\n// ── Internal helpers ──────────────────────────────────────────────────────────\n\n/**\n * Returns today as a `Temporal.PlainDate` in the ISO calendar.\n * @internal\n */\nfunction todayPlain(): Temporal.PlainDate {\n return Temporal.Now.plainDateISO();\n}\n\n/**\n * Converts a `Temporal.PlainDate.dayOfWeek` value (1=Mon…7=Sun) to the\n * 0-based weekday index (0=Sun…6=Sat) used in the `weekendDays` prop.\n * @internal\n */\nfunction temporalDowToIndex(dow: number): number {\n // Temporal: 1=Mon, 2=Tue, …, 7=Sun → 0=Sun, 1=Mon, …, 6=Sat\n return dow % 7;\n}\n\n// ── Factory ───────────────────────────────────────────────────────────────────\n\n/**\n * Pure, framework-agnostic date-picker state machine backed by `Temporal.PlainDate`.\n *\n * All state is held in plain mutable variables — suitable for wrapping in any\n * reactive layer (ore `signal`, Vue ref, etc.). The factory returns a stable\n * handle object; callers are responsible for reactivity.\n *\n * Options with getter-based live bindings (e.g. `get min() { ... }`) are read\n * on every call so the control always reflects the latest reactive state.\n *\n * @example\n * ```ts\n * const ctrl = createDatePickerControl({\n * value: Temporal.PlainDate.from('2025-06-15'),\n * locale: 'en-US',\n * onChange: (date) => console.log(date?.toString()),\n * });\n *\n * ctrl.nextMonth();\n * ctrl.select(Temporal.PlainDate.from('2025-07-04'));\n * ```\n */\nexport function createDatePickerControl(options: DatePickerControlOptions): DatePickerControl {\n // ── Mutable state ─────────────────────────────────────────────────────────\n\n let _selected: Temporal.PlainDate | null = options.value ?? null;\n let _view: DatePickerView = 'day';\n\n const initial = _selected ?? todayPlain();\n\n let _displayYear = initial.year;\n let _displayMonth = initial.month; // 1-indexed (Temporal convention)\n\n // ── Live option accessors (always read from options for reactive compat) ───\n\n function locale(): string {\n return options.locale ?? (typeof navigator !== 'undefined' ? navigator.language : 'en');\n }\n\n function weekendDays(): number[] {\n return options.weekendDays ?? [];\n }\n\n // ── Range / disabled helpers ───────────────────────────────────────────────\n\n function isOutOfRange(date: Temporal.PlainDate): boolean {\n if (options.min && Temporal.PlainDate.compare(date, options.min) < 0) return true;\n\n if (options.max && Temporal.PlainDate.compare(date, options.max) > 0) return true;\n\n return false;\n }\n\n function isDayDisabled(date: Temporal.PlainDate): boolean {\n if (isOutOfRange(date)) return true;\n\n if (weekendDays().includes(temporalDowToIndex(date.dayOfWeek))) return true;\n\n return false;\n }\n\n // ── Grid builders ─────────────────────────────────────────────────────────\n\n function buildDayCells(): DateCell[] {\n const todayDate = todayPlain();\n const firstOfMonth = Temporal.PlainDate.from({ day: 1, month: _displayMonth, year: _displayYear });\n\n // Sunday-start grid: Temporal dayOfWeek is 1=Mon…7=Sun, convert to 0=Sun offset\n const startOffset = temporalDowToIndex(firstOfMonth.dayOfWeek);\n const cells: DateCell[] = [];\n\n // Leading days from previous month\n for (let i = startOffset - 1; i >= 0; i--) {\n const d = firstOfMonth.subtract({ days: i + 1 });\n\n cells.push({\n day: d.day,\n isDisabled: isDayDisabled(d),\n iso: d.toString(),\n isOutsideMonth: true,\n isSelected: _selected !== null && Temporal.PlainDate.compare(d, _selected) === 0,\n isToday: Temporal.PlainDate.compare(d, todayDate) === 0,\n plain: d,\n });\n }\n\n // Days in current month\n const daysInMonth = firstOfMonth.daysInMonth;\n\n for (let day = 1; day <= daysInMonth; day++) {\n const d = Temporal.PlainDate.from({ day, month: _displayMonth, year: _displayYear });\n\n cells.push({\n day,\n isDisabled: isDayDisabled(d),\n iso: d.toString(),\n isOutsideMonth: false,\n isSelected: _selected !== null && Temporal.PlainDate.compare(d, _selected) === 0,\n isToday: Temporal.PlainDate.compare(d, todayDate) === 0,\n plain: d,\n });\n }\n\n // Trailing days to fill last row (always end at multiple of 7)\n const remaining = (7 - (cells.length % 7)) % 7;\n const firstOfNext = firstOfMonth.add({ months: 1 });\n\n for (let i = 0; i < remaining; i++) {\n const d = firstOfNext.add({ days: i });\n\n cells.push({\n day: d.day,\n isDisabled: isDayDisabled(d),\n iso: d.toString(),\n isOutsideMonth: true,\n isSelected: _selected !== null && Temporal.PlainDate.compare(d, _selected) === 0,\n isToday: Temporal.PlainDate.compare(d, todayDate) === 0,\n plain: d,\n });\n }\n\n return cells;\n }\n\n function buildMonthCells(): MonthCell[] {\n const cells: MonthCell[] = [];\n const loc = locale();\n\n for (let m = 1; m <= 12; m++) {\n const plain = Temporal.PlainDate.from({ day: 1, month: m, year: _displayYear });\n const lastOfMonth = plain.with({ day: plain.daysInMonth });\n\n const isDisabled =\n (options.min !== null && options.min !== undefined\n ? Temporal.PlainDate.compare(lastOfMonth, options.min) < 0\n : false) ||\n (options.max !== null && options.max !== undefined\n ? Temporal.PlainDate.compare(plain, options.max) > 0\n : false);\n\n cells.push({\n isDisabled,\n isSelected: _selected !== null && _selected.year === _displayYear && _selected.month === m,\n label: format(plain, { intl: { month: 'long' }, locale: loc, tz: 'UTC' }),\n month: m,\n shortLabel: format(plain, { intl: { month: 'short' }, locale: loc, tz: 'UTC' }),\n });\n }\n\n return cells;\n }\n\n function buildYearCells(): YearCell[] {\n const decadeStart = Math.floor(_displayYear / 10) * 10;\n const cells: YearCell[] = [];\n\n for (let y = decadeStart; y < decadeStart + 12; y++) {\n const firstOfYear = Temporal.PlainDate.from({ day: 1, month: 1, year: y });\n const lastOfYear = Temporal.PlainDate.from({ day: 31, month: 12, year: y });\n\n const isDisabled =\n (options.min !== null && options.min !== undefined\n ? Temporal.PlainDate.compare(lastOfYear, options.min) < 0\n : false) ||\n (options.max !== null && options.max !== undefined\n ? Temporal.PlainDate.compare(firstOfYear, options.max) > 0\n : false);\n\n cells.push({\n isDisabled,\n isSelected: _selected !== null && _selected.year === y,\n year: y,\n });\n }\n\n return cells;\n }\n\n function buildWeekdayLabels(): string[] {\n // 2024-01-07 is a Sunday — use it as the Sunday anchor\n const sunday = parsePlainDate('2024-01-07');\n const loc = locale();\n\n return Array.from({ length: 7 }, (_, i) =>\n format(sunday.add({ days: i }), { intl: { weekday: 'short' }, locale: loc, tz: 'UTC' }),\n );\n }\n\n // ── Handle ────────────────────────────────────────────────────────────────\n\n return {\n dayCells: buildDayCells,\n displayMonth: () => _displayMonth,\n displayYear: () => _displayYear,\n\n goTo(year: number, month: number): void {\n if (!Number.isFinite(year)) return;\n\n _displayYear = year;\n _displayMonth = Math.max(1, Math.min(12, month));\n },\n\n monthCells: buildMonthCells,\n\n nextMonth(): void {\n if (_displayMonth === 12) {\n _displayMonth = 1;\n _displayYear++;\n } else {\n _displayMonth++;\n }\n },\n\n nextYear(): void {\n _displayYear++;\n },\n\n prevMonth(): void {\n if (_displayMonth === 1) {\n _displayMonth = 12;\n _displayYear--;\n } else {\n _displayMonth--;\n }\n },\n\n prevYear(): void {\n _displayYear--;\n },\n\n select(date: Temporal.PlainDate | null): void {\n if (date !== null && isDayDisabled(date)) return;\n\n _selected = date;\n\n if (_selected) {\n _displayYear = _selected.year;\n _displayMonth = _selected.month;\n }\n\n options.onChange(_selected);\n },\n\n selected: () => _selected,\n\n setView(view: DatePickerView): void {\n _view = view;\n },\n\n view: () => _view,\n\n weekdayLabels: buildWeekdayLabels,\n\n yearCells: buildYearCells,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"date-picker.js","names":[],"sources":["../../src/core/date-picker.ts"],"sourcesContent":["import { Temporal, format, parse } from '@vielzeug/tempo';\n\n// ── Public ISO helpers (single source of truth for both components) ───────────\n\n/**\n * Parses an ISO 8601 date string (`yyyy-MM-dd`) into a `Temporal.PlainDate`.\n * Returns `null` for any invalid / empty input — never throws.\n */\nexport function parseIso(iso: string | undefined | null): Temporal.PlainDate | null {\n if (!iso) return null;\n\n try {\n return parse(iso, { as: 'plainDate' });\n } catch {\n return null;\n }\n}\n\n/**\n * Serialises a `Temporal.PlainDate` (or `null`) to an ISO 8601 string (`yyyy-MM-dd`).\n * Returns `null` when the input is `null`.\n */\nexport function toIsoString(date: Temporal.PlainDate | null): string | null {\n return date ? date.toString() : null;\n}\n\n/**\n * Formats a `Temporal.PlainDate` for display in a given locale.\n * e.g. \"15 Jun 2025\" (default medium pattern).\n */\nexport function formatDisplayDate(date: Temporal.PlainDate, locale: string): string {\n return format(date, { intl: { day: 'numeric', month: 'short', year: 'numeric' }, locale, timeZone: 'UTC' });\n}\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport type DatePickerView = 'day' | 'month' | 'year';\n\nexport type DateCell = {\n /** Day-of-month number (1–31) */\n day: number;\n isDisabled: boolean;\n /** ISO date string yyyy-MM-dd — stable key for rendering */\n iso: string;\n isOutsideMonth: boolean;\n isSelected: boolean;\n isToday: boolean;\n plain: Temporal.PlainDate;\n};\n\nexport type MonthCell = {\n isDisabled: boolean;\n isSelected: boolean;\n label: string;\n /** 1-based month number (Temporal convention: 1 = January … 12 = December) */\n month: number;\n shortLabel: string;\n};\n\nexport type YearCell = {\n isDisabled: boolean;\n isSelected: boolean;\n year: number;\n};\n\nexport type DatePickerControlOptions = {\n /** Locale for day/month names, defaults to `navigator.language` or `'en'` */\n locale?: string;\n /** Maximum selectable date (inclusive) */\n max?: Temporal.PlainDate | null;\n /** Minimum selectable date (inclusive) */\n min?: Temporal.PlainDate | null;\n /** Called when a date is committed by the user */\n onChange: (date: Temporal.PlainDate | null) => void;\n /** Currently selected date */\n value?: Temporal.PlainDate | null;\n /**\n * Which days of the week to disable (0 = Sunday … 6 = Saturday).\n * @example [0, 6] disables weekends\n */\n weekendDays?: number[];\n};\n\nexport type DatePickerControl = {\n /** Ordered day cells for the visible month grid (includes leading/trailing days) */\n dayCells(): DateCell[];\n /** Month currently shown in the header (1-indexed, Temporal convention) */\n displayMonth(): number;\n /** Year currently shown in the header */\n displayYear(): number;\n /** Jump to a specific display month/year without selecting */\n goTo(year: number, month: number): void;\n /** All 12 month cells */\n monthCells(): MonthCell[];\n /** Move display month forward by one */\n nextMonth(): void;\n /** Move display year forward by one */\n nextYear(): void;\n /** Move display month backward by one */\n prevMonth(): void;\n /** Move display year backward by one */\n prevYear(): void;\n /** Select a date. Pass null to clear. */\n select(date: Temporal.PlainDate | null): void;\n /** The currently selected date, or null */\n selected(): Temporal.PlainDate | null;\n /** Switch the calendar view */\n setView(view: DatePickerView): void;\n /** Currently rendered calendar view */\n view(): DatePickerView;\n /** Short week-day labels in locale order e.g. [\"Su\",\"Mo\",…] */\n weekdayLabels(): string[];\n /** Year cells for the visible decade window */\n yearCells(): YearCell[];\n};\n\n// ── Internal helpers ──────────────────────────────────────────────────────────\n\n/**\n * Returns today as a `Temporal.PlainDate` in the ISO calendar.\n * @internal\n */\nfunction todayPlain(): Temporal.PlainDate {\n return Temporal.Now.plainDateISO();\n}\n\n/**\n * Converts a `Temporal.PlainDate.dayOfWeek` value (1=Mon…7=Sun) to the\n * 0-based weekday index (0=Sun…6=Sat) used in the `weekendDays` prop.\n * @internal\n */\nfunction temporalDowToIndex(dow: number): number {\n // Temporal: 1=Mon, 2=Tue, …, 7=Sun → 0=Sun, 1=Mon, …, 6=Sat\n return dow % 7;\n}\n\n// ── Factory ───────────────────────────────────────────────────────────────────\n\n/**\n * Pure, framework-agnostic date-picker state machine backed by `Temporal.PlainDate`.\n *\n * All state is held in plain mutable variables — suitable for wrapping in any\n * reactive layer (ore `signal`, Vue ref, etc.). The factory returns a stable\n * handle object; callers are responsible for reactivity.\n *\n * Options with getter-based live bindings (e.g. `get min() { ... }`) are read\n * on every call so the control always reflects the latest reactive state.\n *\n * @example\n * ```ts\n * const ctrl = createDatePickerControl({\n * value: Temporal.PlainDate.from('2025-06-15'),\n * locale: 'en-US',\n * onChange: (date) => console.log(date?.toString()),\n * });\n *\n * ctrl.nextMonth();\n * ctrl.select(Temporal.PlainDate.from('2025-07-04'));\n * ```\n */\nexport function createDatePickerControl(options: DatePickerControlOptions): DatePickerControl {\n // ── Mutable state ─────────────────────────────────────────────────────────\n\n let _selected: Temporal.PlainDate | null = options.value ?? null;\n let _view: DatePickerView = 'day';\n\n const initial = _selected ?? todayPlain();\n\n let _displayYear = initial.year;\n let _displayMonth = initial.month; // 1-indexed (Temporal convention)\n\n // ── Live option accessors (always read from options for reactive compat) ───\n\n function locale(): string {\n return options.locale ?? (typeof navigator !== 'undefined' ? navigator.language : 'en');\n }\n\n function weekendDays(): number[] {\n return options.weekendDays ?? [];\n }\n\n // ── Range / disabled helpers ───────────────────────────────────────────────\n\n function isOutOfRange(date: Temporal.PlainDate): boolean {\n if (options.min && Temporal.PlainDate.compare(date, options.min) < 0) return true;\n\n if (options.max && Temporal.PlainDate.compare(date, options.max) > 0) return true;\n\n return false;\n }\n\n function isDayDisabled(date: Temporal.PlainDate): boolean {\n if (isOutOfRange(date)) return true;\n\n if (weekendDays().includes(temporalDowToIndex(date.dayOfWeek))) return true;\n\n return false;\n }\n\n // ── Grid builders ─────────────────────────────────────────────────────────\n\n function buildDayCells(): DateCell[] {\n const todayDate = todayPlain();\n const firstOfMonth = Temporal.PlainDate.from({ day: 1, month: _displayMonth, year: _displayYear });\n\n // Sunday-start grid: Temporal dayOfWeek is 1=Mon…7=Sun, convert to 0=Sun offset\n const startOffset = temporalDowToIndex(firstOfMonth.dayOfWeek);\n const cells: DateCell[] = [];\n\n // Leading days from previous month\n for (let i = startOffset - 1; i >= 0; i--) {\n const d = firstOfMonth.subtract({ days: i + 1 });\n\n cells.push({\n day: d.day,\n isDisabled: isDayDisabled(d),\n iso: d.toString(),\n isOutsideMonth: true,\n isSelected: _selected !== null && Temporal.PlainDate.compare(d, _selected) === 0,\n isToday: Temporal.PlainDate.compare(d, todayDate) === 0,\n plain: d,\n });\n }\n\n // Days in current month\n const daysInMonth = firstOfMonth.daysInMonth;\n\n for (let day = 1; day <= daysInMonth; day++) {\n const d = Temporal.PlainDate.from({ day, month: _displayMonth, year: _displayYear });\n\n cells.push({\n day,\n isDisabled: isDayDisabled(d),\n iso: d.toString(),\n isOutsideMonth: false,\n isSelected: _selected !== null && Temporal.PlainDate.compare(d, _selected) === 0,\n isToday: Temporal.PlainDate.compare(d, todayDate) === 0,\n plain: d,\n });\n }\n\n // Trailing days to fill last row (always end at multiple of 7)\n const remaining = (7 - (cells.length % 7)) % 7;\n const firstOfNext = firstOfMonth.add({ months: 1 });\n\n for (let i = 0; i < remaining; i++) {\n const d = firstOfNext.add({ days: i });\n\n cells.push({\n day: d.day,\n isDisabled: isDayDisabled(d),\n iso: d.toString(),\n isOutsideMonth: true,\n isSelected: _selected !== null && Temporal.PlainDate.compare(d, _selected) === 0,\n isToday: Temporal.PlainDate.compare(d, todayDate) === 0,\n plain: d,\n });\n }\n\n return cells;\n }\n\n function buildMonthCells(): MonthCell[] {\n const cells: MonthCell[] = [];\n const loc = locale();\n\n for (let m = 1; m <= 12; m++) {\n const plain = Temporal.PlainDate.from({ day: 1, month: m, year: _displayYear });\n const lastOfMonth = plain.with({ day: plain.daysInMonth });\n\n const isDisabled =\n (options.min !== null && options.min !== undefined\n ? Temporal.PlainDate.compare(lastOfMonth, options.min) < 0\n : false) ||\n (options.max !== null && options.max !== undefined\n ? Temporal.PlainDate.compare(plain, options.max) > 0\n : false);\n\n cells.push({\n isDisabled,\n isSelected: _selected !== null && _selected.year === _displayYear && _selected.month === m,\n label: format(plain, { intl: { month: 'long' }, locale: loc, timeZone: 'UTC' }),\n month: m,\n shortLabel: format(plain, { intl: { month: 'short' }, locale: loc, timeZone: 'UTC' }),\n });\n }\n\n return cells;\n }\n\n function buildYearCells(): YearCell[] {\n const decadeStart = Math.floor(_displayYear / 10) * 10;\n const cells: YearCell[] = [];\n\n for (let y = decadeStart; y < decadeStart + 12; y++) {\n const firstOfYear = Temporal.PlainDate.from({ day: 1, month: 1, year: y });\n const lastOfYear = Temporal.PlainDate.from({ day: 31, month: 12, year: y });\n\n const isDisabled =\n (options.min !== null && options.min !== undefined\n ? Temporal.PlainDate.compare(lastOfYear, options.min) < 0\n : false) ||\n (options.max !== null && options.max !== undefined\n ? Temporal.PlainDate.compare(firstOfYear, options.max) > 0\n : false);\n\n cells.push({\n isDisabled,\n isSelected: _selected !== null && _selected.year === y,\n year: y,\n });\n }\n\n return cells;\n }\n\n function buildWeekdayLabels(): string[] {\n // 2024-01-07 is a Sunday — use it as the Sunday anchor\n const sunday = parse('2024-01-07', { as: 'plainDate' });\n const loc = locale();\n\n return Array.from({ length: 7 }, (_, i) =>\n format(sunday.add({ days: i }), { intl: { weekday: 'short' }, locale: loc, timeZone: 'UTC' }),\n );\n }\n\n // ── Handle ────────────────────────────────────────────────────────────────\n\n return {\n dayCells: buildDayCells,\n displayMonth: () => _displayMonth,\n displayYear: () => _displayYear,\n\n goTo(year: number, month: number): void {\n if (!Number.isFinite(year)) return;\n\n _displayYear = year;\n _displayMonth = Math.max(1, Math.min(12, month));\n },\n\n monthCells: buildMonthCells,\n\n nextMonth(): void {\n if (_displayMonth === 12) {\n _displayMonth = 1;\n _displayYear++;\n } else {\n _displayMonth++;\n }\n },\n\n nextYear(): void {\n _displayYear++;\n },\n\n prevMonth(): void {\n if (_displayMonth === 1) {\n _displayMonth = 12;\n _displayYear--;\n } else {\n _displayMonth--;\n }\n },\n\n prevYear(): void {\n _displayYear--;\n },\n\n select(date: Temporal.PlainDate | null): void {\n if (date !== null && isDayDisabled(date)) return;\n\n _selected = date;\n\n if (_selected) {\n _displayYear = _selected.year;\n _displayMonth = _selected.month;\n }\n\n options.onChange(_selected);\n },\n\n selected: () => _selected,\n\n setView(view: DatePickerView): void {\n _view = view;\n },\n\n view: () => _view,\n\n weekdayLabels: buildWeekdayLabels,\n\n yearCells: buildYearCells,\n };\n}\n"],"mappings":"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"}