Skip to content

feat!: 2.0.0 — React 18 support, slimmer bundle, tighter types - #30

Merged
baymac merged 10 commits into
mainfrom
baymac/release-2.0
May 30, 2026
Merged

feat!: 2.0.0 — React 18 support, slimmer bundle, tighter types#30
baymac merged 10 commits into
mainfrom
baymac/release-2.0

Conversation

@baymac

@baymac baymac commented May 30, 2026

Copy link
Copy Markdown
Owner

2.0.0 release

Packaging + compatibility work to make the library installable and correct on a
wider range of consumers, plus a real runtime bug fix. No source/behaviour
changes for existing React 19 users.

Highlights

Area Change
React compat Peer range widened to ^18.0.0 || ^19.0.0 (was ^19.2.0). Uses only standard hooks.
Bug fix JSX runtime was being inlined into the bundle, hard-wiring it to React 19 and crashing on React 18 (Cannot read properties of undefined (reading 'recentlyCreatedOwnerStacks')). Now externalized.
Bundle size @mui/icons-material + cron-parser externalized. ESM ~154 KB → ~43 KB gzip, CJS ~135 KB → ~40 KB gzip.
Types CustomSelectProps is now generic over its value type; classes typed as Partial<AutocompleteClasses>. No more any in the public surface.
Docs New CHANGELOG.md, accurate dependency-model wording, license badge fixed to main.

Why a major bump

The bundle now externalizes the JSX runtime, @mui/icons-material, and
cron-parser (all resolved from the consumer's node_modules), and the React
peer range changed. These are packaging-level changes, so 2.0.0 per semver.
Migration: none — installs and runs on both React 18 and 19 with no source
changes.

Verification

  • yarn test146/146 pass (Node unit + real-Chromium browser tests)
  • npx tsc --noEmit, yarn lint, yarn build — all clean
  • React 18 + 19 proof: packed the tarball (npm pack) and, in a throwaway
    consumer, confirmed it type-checks against the shipped .d.ts (skipLibCheck: false)
    and SSR-renders under both React 18.3.1 and React 19.
  • Confirmed in dist/: react/jsx-runtime and cron-parser stay as runtime
    imports; no recentlyCreatedOwnerStacks inlined.

Note

This branch also carries the previously-pushed docs: rework README and add full USAGE.md guide commit (it was not yet in its own PR).

🤖 Generated with Claude Code

baymac and others added 3 commits May 30, 2026 11:58
Add a live-demo badge linking to material-ui-cron.vercel.app and drop the
local demo-run instructions. Update install requirements to the current peer
deps (react/react-dom >=19.2.0; @mui/material now bundled). Slim the README
quick-start and move the prop-by-prop reference into a new USAGE.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Externalize the React JSX runtime, @mui/icons-material, and cron-parser, widen
the React peer range to 18 || 19, and remove `any` from the public types.

- build: externalize `react`/`react-dom` subpaths (e.g. `react/jsx-runtime`).
  Previously the JSX runtime was inlined, hard-wiring the bundle to the React
  version present at build time and crashing on React 18 with
  `Cannot read properties of undefined (reading 'recentlyCreatedOwnerStacks')`.
- build: externalize `@mui/icons-material` and `cron-parser` (every runtime dep
  is now external). ESM entry ~154 KB -> ~43 KB gzip; CJS ~135 KB -> ~40 KB gzip.
- feat: widen `react`/`react-dom` peer range to `^18.0.0 || ^19.0.0`. Verified
  the packed tarball type-checks and SSR-renders under both React 18 and 19.
- refactor(types): make `CustomSelectProps` generic over the value type and type
  `classes` as `Partial<AutocompleteClasses>`, removing `any` from the public API.
- docs: add CHANGELOG, reconcile the README dependency model, fix the license
  badge to point at `main`, bump version to 2.0.0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… run

`every N between X and Y` emits `start-end/N`. A cron range step begins at
`start` and increments by `N`, so once `N` exceeds the span (`end - start`) only
`start` matches and the schedule silently collapses to a single run per cycle
(e.g. `every 5 between :55 and :59` -> `55-59/5` fires only at :55). Users read
this as the step landing "outside range" / "could only run it once".

Cap the selectable interval at the range span across Minute / Hour /
Day-of-month: disable interval options above the span (new shared helper
`capIntervalOptionsToSpan`) and clamp the selected interval down when the range
narrows. An incoming collapsing cron auto-corrects to the largest non-collapsing
interval (`55-59/5` -> `55-59/4`, firing at :55 and :59).

Tests: 5 unit tests for `capIntervalOptionsToSpan`; 2 browser tests (the
auto-correction and out-of-span interval options being disabled). 153 pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds a month calendar beneath the Next-runs list that highlights the days a
schedule fires (run times on hover) and pages between months that contain runs.
Makes sparse / hard-to-read schedules — e.g. an interval over a narrow window —
legible at a glance. Off by default, so non-breaking.

- nextRuns.ts: `bucketRunsByDay` (groups occurrences by timezone-local day,
  keyed YYYY-MM-DD) and `formatTime` (time-only, locale/timezone aware) helpers.
- components/RunCalendar.tsx: new panel; mirrors NextRuns (validator-gated,
  async cron-parser load), renders a localized month grid with prev/next nav.
- Scheduler.tsx: `showCalendar` prop renders it inside a right-zone column under
  the Next-runs list.
- types.ts: `showCalendar?` on SchedulerProps; optional `calendarLabel` locale
  key. strings.ts / enLocale / zhCNLocale: "Upcoming" / "即将运行" + fallback.
- demo: a "Calendar" toggle (on by default) to dogfood it.
- Tests: bucketRunsByDay + formatTime unit tests; 4 browser tests (hidden by
  default, marked day cells, invalid-cron message, localized label). 161 pass.
- Docs: USAGE.md Calendar section + prop row, README link, CHANGELOG entry.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…runs panel

Replaces the standalone RunCalendar component with a calendar folded directly
into the Next-runs panel: a fixed three-month strip (current + next two) you can
page through, with each firing day marked. Selecting a day lists that day's run
times (or "No runs on this day"); the soonest run day is auto-selected on load.

- nextRuns.ts: day/month helpers — computeRunDays, computeRunsOnDay,
  computeRunsUntil, monthKeyInTz / dayKeyInTz / addMonths / addDays /
  startOfDayInTz / formatDayKey (alongside bucketRunsByDay / formatTime).
- components/NextRuns.tsx: month grid + day selection + per-day run list; day
  marking is day-level (cheap) and exact times are computed on demand per day.
- components/RunCalendar.tsx: removed (folded into NextRuns).
- types.ts / localization: optional `noRunsOnDayText` locale key (+ zh_CN); the
  calendar is always shown in the panel (no separate showCalendar wiring).
- demo: drop the standalone calendar toggle.
- tests: day-helper unit tests; calendar browser tests (marked days, day
  selection, empty-day message, month paging). Made the empty-day test
  deterministic — it waits for the monthly schedule to settle (a run day
  selected + "no runs" cells present) before clicking, so the auto-select effect
  can't stomp the click under parallel-suite load. 182 pass.
- docs: USAGE/README/CHANGELOG updated for the in-panel calendar.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ndow

- computeRunsOnDay now honors an anchor so a run that already fired today
  (e.g. a 12:00 AM run viewed at 1:53 AM) no longer lists as "in 0 min";
  future days are unaffected. Aligns the per-day list with how computeRunDays
  already anchors day-marking at now.
- Add clampDayRuns to bound a dense day to its first 10 + last 10 runs, with a
  "{count} more runs" gap divider (new optional moreRunsText locale string,
  en + zh_CN).
- Widen the Next-runs calendar to a full 12 months from the current month
  (MONTH_SPAN/WINDOW_MONTHS 3 -> 12).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The Next-runs panel re-anchors its cursor asynchronously after mount (the cron
is re-parsed and the soonest-run day re-selected), which on CI raced the paging
walk: the cursor bounced mid-walk, inflating the hop count (CI saw 16 vs an
expected 11) and occasionally flipping an arrow to disabled mid-click
(pointer-events: none throw).

Replace the brittle exact-hop-count assertion with a set-equality check on the
reachable months. Disable userEvent's pointer-events check and treat a hop that
doesn't move the month as a boundary, so a stray re-anchor bounce can't throw.
Collect months toward both ends; assert the set equals the current month plus
the next eleven. Verified stable across repeated local runs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The shipped calendar spans a rolling twelve-month window (MONTH_SPAN = 12),
but the 2.0.0 changelog and USAGE still described "the current month and the
next two." Align both docs with the actual behavior.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@baymac
baymac merged commit 7cf2c44 into main May 30, 2026
2 checks passed
@baymac
baymac deleted the baymac/release-2.0 branch May 30, 2026 21:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant