Replies: 1 comment 5 replies
-
|
Time zone issues disappear altogether when using PlainDate, so none of the tz handling needs to be ported over. Temporal-polyfill seems to be more popular right now. (It's what I used). But it isn't 100% spec compliant because some temporal operations require BigInt support and only the @js-temporal one has that. (Though I'm not sure which operations and if they are needed for PlainDate.) https://npmtrends.com/@js-temporal/polyfill-vs-temporal-polyfill Edit: Also, Typescript 6 will include the types for Temporal (microsoft/TypeScript#62628) |
Beta Was this translation helpful? Give feedback.
5 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
1. Summary
This RFC proposes that DayPicker v11 remains
date-fns-based by default, while introducing a new optional Temporal implementation under a dedicated subpath:date-fns-based:import { DayPicker } from "react-day-picker"import { DayPicker } from "react-day-picker/temporal"The Temporal path is designed as a day-first API:
Temporal.PlainDate.todayis derived asTemporal.PlainDateviaTemporal.Now.plainDateISO(resolvedTimeZone).timeZoneprop controls zone-sensitive behavior such as derivingtodayand formatting/labels.This offers Temporal adoption without forcing a breaking engine migration for existing users.
2. Motivation
We want to support two valid user needs at the same time:
Replacing the default engine in v11 increases migration risk across selection behavior, timezone handling, locale expectations, and userland utilities. A dedicated
/temporalpath reduces that risk while allowing full Temporal implementation to mature in production.A day picker primarily operates on calendar days, not instants. Making
Temporal.PlainDatethe public type keeps selection and matcher logic stable, avoids time-of-day drift, and aligns with DayPicker's existing mental model. Time zone still matters for "what day is today" and localized output, so zone handling remains explicit but internal.3. Goals
react-day-picker) backward-compatible and date-fns-based.react-day-picker/temporal.todaybehavior.4. Non-Goals
date-fns,date-fns-jalali, or@date-fns/tzfrom default runtime path in v11.react-day-pickerimports./temporal./temporalAPI.5. Locked Decisions
react-day-picker(default path) remains date-fns-based in v11.react-day-picker/temporalsubpath is introduced./temporalpath./temporaluseTemporal.PlainDate.today) are derived withTemporal.Now.plainDateISO(resolvedTimeZone)and stored asTemporal.PlainDate./persian,/buddhist,/ethiopic,/hebrew) remain unchanged for v11 scope unless explicitly extended later.6. Public API Design
6.1 Default Path (Unchanged)
6.2 Temporal Path (New)
Temporal path uses
Temporal.PlainDateas the public value type for day-bearing fields.6.3 Time Zone Contract in
/temporaltimeZoneremains a supported prop in the Temporal path, but it does not change the public selected-value type.Temporal.PlainDate.timeZoneaffects zone-sensitive defaults and presentation, not the shape of selected values.todayis not passed, DayPicker derives it from the configured zone:Temporal.Now.plainDateISO(resolvedTimeZone)todaycan be overridden viatoday?: Temporal.PlainDate.timeZonechanges, derivedtodayand dependent month calculations must update.6.4 Naming and Exports
The
/temporalentry point exports its own DayPicker and related types:DayPicker(Temporal variant)DayPickerProps(Temporal variant)TemporalDateRangeandTemporalMatcherNo API surface changes are required in default path exports.
7. Runtime and Dependency Model
7.1 Default Path
7.2 Temporal Path
Temporalor@js-temporal/polyfill.Suggested error guidance:
@js-temporal/polyfill.7.3 Packaging
package.json("./temporal")./temporalcode is isolated to avoid affecting default bundle size.8. Internal Architecture
8.1 Shared UI Core with Pluggable Date Backend
Refactor toward a shared rendering and interaction core with separate date backends:
/temporal.This avoids duplicating components while isolating date logic differences.
8.2 Temporal Backend Rules
Temporal.PlainDate.Temporal.PlainDate.Temporal.PlainDatewithTemporal.Now.plainDateISO(resolvedTimeZone).Temporal.PlainDateplus locale/timezone metadata.8.3 "Today" Modifier Semantics in Temporal Path
todayis treated as a date-only value in the same model as all other day cells.todayfrom resolvedtimeZoneusingTemporal.Now.plainDateISO(resolvedTimeZone).day.equals(today)(date equality only).todayprop is provided, it is authoritative.timeZonechanges recompute derivedtodayand refresh modifiers.timeZoneso long-lived mounted calendars roll over automatically.8.4 Accessibility and Interaction Contract
Both backends must preserve:
9. Implementation Plan
Concretely, the code changes should be implemented as the following explicit work items:
Add temporal subpath exports in package metadata.
Update
package.jsonexportsso./temporalhas ESM, CJS, and type declarations, matching the existing packaging pattern used by the main entry point and calendar subpaths.Create a dedicated Temporal public entry point.
Add
src/temporal/index.ts(and corresponding build outputs) to export the Temporal DayPicker component and Temporal-specific types without changingsrc/index.tsbehavior.Define Temporal-specific public type contracts.
Introduce new type modules (for example
src/types/props-temporal.ts,src/types/shared-temporal.ts, and matcher/range type files) where date-bearing fields are based onTemporal.PlainDateinstead ofDate, includingtoday?: Temporal.PlainDateandtimeZone?: string.Extract backend-agnostic UI logic from current core modules.
Refactor shared rendering and interaction flow from
src/DayPicker.tsx,src/useCalendar.ts, andsrc/useSelection.tsinto reusable modules that can be wired to either the existing date-fns backend or the new Temporal backend.Implement the Temporal date backend under
src/temporal/.Add Temporal-native utilities for date arithmetic, month/week boundaries, comparison/equality, interval traversal, selection math, and matcher evaluation using
Temporal.PlainDate.Implement timezone context helpers for Temporal path.
Add internal helpers to:
propor runtime default)todayasPlainDatefrom zone-aware "now"Implement Temporal formatting and localization adapters.
Add formatter/label helpers in
src/temporal/that consumeTemporal.PlainDateand use Intl APIs (and locale metadata) to provide parity with existing captions, weekday labels, and accessible strings.Add a runtime guard for Temporal availability.
Create
src/temporal/getTemporal.ts(or equivalent) to resolveglobalThis.Temporaland throw a deterministic, user-facing error when neither native Temporal nor@js-temporal/polyfillis available.Keep default path behavior unchanged by strict isolation.
Ensure the
react-day-pickerdefault import path continues to use current date-fns code paths, and verify no temporal-only code is pulled into the default bundle via accidental shared imports.Add a dedicated Temporal test matrix.
Add tests under
src/temporal/**/*.test.tsxfor Temporal-only behavior, and add parity tests that compare user-visible behavior between default and temporal paths for selection, navigation, modifiers, and accessibility labels.Update examples and documentation for the new import path.
Add focused docs and examples showing
import { DayPicker } from "react-day-picker/temporal", required runtime/polyfill setup, and migration patterns from Date-based state toTemporal.PlainDate.Phase A: Export and Scaffolding
./temporalsubpath exports.Phase B: Temporal Date Backend
PlainDatearithmetic and comparison utilities.Temporal.PlainDate.Phase C: Time Zone and "Today"
timeZoneresolution and zone-awaretodayderivation.todaymodifier comparisons withPlainDateequality.timeZonechanges and optional midnight rollover behavior.Phase D: UI Integration
Phase E: Testing and Docs
/temporalusage, polyfill setup, and timezone semantics.Phase F: Release and Validation
/temporal.10. Testing Strategy
Mandatory coverage for both paths:
Selection modes:
Navigation:
Modifiers:
Accessibility:
Localization:
Temporal-only:
PlainDatematcher and range correctnesstodaymodifier correctness in selectedtimeZonetimeZonechanges at runtime11. Acceptance Criteria
react-day-pickerimport path remains behaviorally compatible for existing Date-based users.react-day-picker/temporalis production-usable with Temporal-native types.Temporal.PlainDatefor date-bearing values.todaymodifier in/temporalreflects the resolvedtimeZone.12. Risks and Mitigations
Dual-backend maintenance complexity:
API confusion between paths:
Confusion about timezone with
PlainDate:timeZonecontrolstodayderivation and formatting, while selected values remainPlainDate.Polyfill setup issues:
Behavioral drift between paths:
13. Migration Guidance
For existing users
No change required. Keep using:
For Temporal adopters
Switch to:
Then migrate date-bearing state and handlers from
DatetoTemporal.PlainDate.If your app persists instants, convert at your app boundary:
Temporal.PlainDate.PlainDatewith app time zone and chosen wall-clock time at your app boundary.14. Release Notes Guidance
v11 release notes should state:
/temporal./temporal.Temporal.PlainDatepublic values; timezone is used fortodayand formatting semantics.15. Open Follow-Ups
/persian/temporal, etc.)?/temporalor kept opt-in?Beta Was this translation helpful? Give feedback.
All reactions