chore: upgrade calendar dependencies and add the date foundation - #894
chore: upgrade calendar dependencies and add the date foundation#894Shreyag02 wants to merge 1 commit into
Conversation
Phase 0 of RFC 005. Moves the calendar dependencies to the versions the
rewrite targets and lands `lib/` — the scale maths and input parsing —
tested, before any UI exists to use it.
Dependencies, in `packages/raystack` only:
- `react-day-picker` ^9.6.7 -> ~10.0.1
- `@base-ui/react` ~1.6.0 -> ~1.7.0, which pins `@base-ui/utils` at 0.3.2
- `dayjs` ^1.11.20 -> ^1.11.23, kept because the old family still imports
it; it goes with `components/calendar/` at phase 6
The v10 major needs no source change. It drops the 16 `@deprecated` v8-era
props and the `Button` component slot, none of which this package
references, and the `mode`/`required` union is unchanged from 9.6.7 — so
the four component slots the family overrides (`PreviousMonthButton`,
`NextMonthButton`, `Dropdown`, `DayButton`, `MonthGrid`) and all twenty
`classNames` keys still resolve. The existing 97 calendar tests pass
against it untouched.
`date-fns` and `@date-fns/tz` become explicit dependencies. They already
reached the published tarball through react-day-picker, but pnpm's
isolated layout does not resolve a transitive dependency from our own
source, and `nodeExternals({ deps: true })` only externalises what the
manifest declares. Importing them undeclared would break both.
`date-adapter.ts` is the one module allowed to call a date library, so the
plugin set is a single fact in one place and the import-order-dependent
`dayjs.extend()` failure class has nowhere to live. No `extend()` is added
anywhere. Values cross `lib/` as `DayKey`s — `'YYYY-MM-DD'`, timeless —
whose lexicographic order is chronological, so comparing a day against a
bound needs no library call and cannot drift by a timezone.
`lib/scale.ts` implements the model verbatim: conversion takes the anchor
date, finds the period of the target scale containing it, and emits that
period's start when leading or its end when trailing; availability tests
the date the period would produce, not the period start, so July 2026 and
Q3 2026 are selectable in an end field bounded at 15 July while H1 2026 is
not. Month ends are calendar-correct — February 2028 trailing is
2028-02-29, February 2100 is 2100-02-28.
`lib/parse.ts` reads a typed string as a date and a scale together. A bare
`Q4`, `H1` or `May` resolves inside the reference year and never rolls
forward, so the same string does not change meaning across midnight on 31
December; the rule is documented on the function and tested at both ends
of a year.
100% statement, branch, function and line coverage on all three modules.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Team Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
commit: |
PR 1 of 7 in the RFC 005 stack — RFC 005: Calendar Rewrite
CalendarPreview(docs/rfcs/005-calendar-preview.md).This PR ships no UI.
lib/lands tested before any component exists to use it, per review point 5 on #890 and the phase 0 exit criteria in the RFC's Plan.Dependencies
Bumped in
packages/raystackonly. Nothing else in the manifest moves — tanstack, dnd-kit, prosemirror, culori, class-variance-authority and prism-react-renderer are untouched.react-day-picker^9.6.7~10.0.1@base-ui/react~1.6.0~1.7.0@base-ui/utils~0.3.1~0.3.2— pinned exactly by Base UI 1.7.0dayjs^1.11.20^1.11.23dayjsstays in the manifest: the old family imports it untilcomponents/calendar/is deleted at phase 6.react-day-picker 10 needs no source change
Verified against the installed v10 types rather than the changelog:
@deprecatedv8-era props and theButtonCustomComponentsentry are gone;packages/raystackreferences none of them. TheButton:hits in the tree areToolbar.Button,CodeBlock.CopyButtonand friends — unrelated components.PreviousMonthButton,NextMonthButton,Dropdown,DayButton,MonthGrid— as do all twentyclassNameskeys it sets.mode/requiredunion is unchanged from 9.6.7, so there is no selection-type churn, as the RFC's Dependencies predicted.components/calendar/untouched.One addition beyond the four bumps
date-fns(^4.1.0) and@date-fns/tz(^1.5.0) are now explicit dependencies.The RFC notes they already ship transitively via react-day-picker, and they do — in the published tarball's runtime graph. But that is not enough to import them here: pnpm's isolated
node_modulesdoes not resolve a transitive dependency from our own source (confirmed —require.resolve('date-fns')frompackages/raystack/componentsfails without the declaration), andnodeExternals({ deps: true })inrollup.config.mjsonly externalises what the manifest declares, so an undeclared import would also get inlined into the bundle. Both are declared at ranges that satisfy react-day-picker's dependency and Base UI's optional peer, and the lockfile still resolves a single instance of each.What lands
No component, part, hook, CSS, story or barrel export — nothing is wired into
packages/raystack/index.tsxyet.date-adapter.tsOne module owns every date-library call, so the plugin set is a single fact in one place and the import-order-dependent
dayjs.extend()failure class has nowhere to live. Noextend()is added anywhere in this PR.Values cross
lib/asDayKeys —'YYYY-MM-DD', timeless. Their lexicographic order is chronological, so comparing a day against a bound needs no library call and cannot drift by a timezone.dayKey()takes an optionaltimeZone, which is where@date-fns/tzearns its place: it is the call that stops a grid rendered at atimeZonefrom keying its cells a day off, the shape of the current family's tooltip/dateInfobug.lib/scale.tsThe model verbatim from The Scale Model:
min = 2026-07-15and trailing, Jul 2026 (emits 31 Jul) and Q3 2026 (emits 30 Sep) are available while H1 2026 (emits 30 Jun) is disabled — each asserted individually, alongside a test that all three periods start before the bound, so only the produced-date rule separates them. A second test asserts the two rules coincide whenevertrailingValueis false.2028-02-29; February 2100 is2100-02-28and February 2000 is2000-02-29, so the century rule is covered in both directions.halfYearis H1 Jan–Jun, H2 Jul–Dec — ours to derive, since no date library has it.lib/parse.tsReads a typed string as a date and a scale together:
20/05/2027→ day,May 2027→ month,Q4→ quarter,H1 2026→ halfYear,2025→ year.2027-05-20is also accepted so a stored value round-trips.Year inference for a bare
Q4,H1orMay: the period resolves inside the reference year — the calendar year ofreferenceDate, defaulting to now — and the rule never rolls forward.Q1typed in December 2026 is Q1 2026, not Q1 2027. A "next occurrence" rule would make the same typed string mean different years depending on the day it was typed, soQ1would change meaning across midnight on 31 December and a stored value would not agree with the string that produced it after a reload. The rule is documented on the function and tested from both the first and last day of a year.Recognition is pinned by a regex before any date maths runs, so near-misses are rejected rather than coerced — including
20/05/27, the two-digit year that dayjs'customParseFormatreads as year 27. 26 rejection cases are asserted, each named.Testing
lib/scale.ts,lib/parse.tsanddate-adapter.tsat 100% statement, branch, function and line coverage — leap years, month-end snapping, period boundaries at both edges, day→year→day round trips, availability at both edges againstminandmax, and all 25 scale-to-scale conversion directions at both edges.pnpm --filter @raystack/apsara testis green: 2961 passed, 1 skipped (pre-existingdata-view/debug.test.tsx).pnpm --filter @raystack/apsara buildis clean.biome checkclean on the new directory.tsc --noEmitreports the same 6 pre-existing errors as the base branch — data-table, data-view, menu and popover — and none incalendar/orcalendar-preview/. Confirmed by installing the base branch'spackage.jsonand lockfile and re-running.🤖 Generated with Claude Code