Skip to content

feat(year): add date selection, drag-to-select and drag-to-create - #47

Merged
afonsojramos merged 16 commits into
mainfrom
issue-41
Aug 20, 2026
Merged

feat(year): add date selection, drag-to-select and drag-to-create#47
afonsojramos merged 16 commits into
mainfrom
issue-41

Conversation

@afonsojramos

Copy link
Copy Markdown
Owner

Summary

Closes the rest of what issue #41 reports: the year and month views now support selecting dates, creating events, and moving events.

#45 landed the month grid's drag-to-create and drag-to-reschedule while this branch was open, so the merge here keeps that implementation wholesale (core's monthCreateRange / monthDropBounds, the MonthDrag state machine, data-drop) and drops this branch's near-duplicate dayRangeFromDrag / shiftEventDays. What remains on top is the part #45 doesn't cover:

  • The year grid becomes interactive. YearView takes the same selection model as the month grid and the picker (selectedDates, selectedRange, minDate, maxDate, isDateDisabled), drawn with core's daySelectionState / dayBadgeKind / rangeBandKind so it can't disagree with the other grids. Hold a day and drag (press and drag on web) to sweep out a range, with onCreateEvent committing it as an all-day span. Native runs a pan per mini month; the web drives it from the cells' pointer events, so a sweep can run across months there. The year view has no event bars to pick up, so there's no drag-to-move.
  • onSelectDrag on both month grids, both year grids and Calendar. onCreateEvent only fires on release, which is fine for creating but leaves a selection highlight lagging the drag. onSelectDrag reports the same sweep live, as the ordered inclusive [start, end] days, so it wires straight to useDateRange's selectRange. It enables the sweep on its own.
  • Selection in the native Calendar. It had no selection props at all; they're now accepted in month and year modes and forwarded through MonthPager via CalendarSelectionProvider, so pages LegendList has already cached still repaint.

Two fixes fell out of making selection first-class on the month grid: the dom range band was sized from theme.cellHeight (48px) but applied to a ~100px events cell, so a selection painted a block over the event chips instead of a strip across the dates; and the band's pill cap assumed a centred badge, which events mode doesn't have.

Testing

  • lint, format, typecheck, test (529 passing, +23 over main), build, attw + publint per package, and mint broken-links are all clean.
  • Drove the dom renderer in a real browser with real pointer input across month and year: create sweeps, chip reschedule, click suppression, touch-action, and that a click after a sweep still reaches onPressDay. Screenshots confirmed the year selection band and that the today badge survived the cell restructure.
  • Native drag is covered through the recording gesture mock, including a regression test for the pan-rebuild bug below. I verified that test fails on the pre-fix code (expected 12 gestures, got 36) rather than assuming it had teeth.

Notes for review

  • dayBadge is a new YearView slot and the today/selected circle moved onto it, from day (now just the cell), matching MonthView. A consumer restyling that circle through classNames.day has to move to dayBadge; there's a <Note> in the year-view guide saying so. Flagging it because it's a silent visual change, not a type error.
  • fillCellOnSelection is month-only. It doesn't map cleanly onto the mini months' full-cell band, so Calendar doesn't forward it in year mode and the docs now say so.
  • The grid hit-test is now duplicated three ways (MonthList.dayAtContent, MonthView.hitTest, YearView.dayAt), and copying it is what dropped the adjacent-month guard fixed here. A shared dayAtPoint in core would carry the guards once, but it means touching two files feat(month): hide the built-in title, and add cell press and drag support #45 just rewrote, so I left it out of this PR.
  • The first five commits predate the merge and were written against the pre-feat(month): hide the built-in title, and add cell press and drag support #45 month grid; the merge commit body records exactly what was kept, dropped and re-applied.

Closes #41

main landed month drag-to-create and drag-to-reschedule (#45) in parallel with
this branch. Its implementation is the one kept: core's `monthCreateRange` /
`monthDropBounds`, the `MonthDrag` state machine on both renderers, and
`data-drop` for the drop target. This branch's own `dayRangeFromDrag` /
`shiftEventDays` duplicates are dropped.

Re-applied on top, since main does not cover them:
- `onSelectDrag` on the month grids and through `Calendar`, so a sweep reports
  its span live and can drive a selection instead of only firing on release.
- The year grid's selection, drag-to-select and drag-to-create, plus its
  `dayBadge` / `rangeBand` slots.
- `Calendar`'s selection props in month and year modes on the native renderer,
  forwarded through `MonthPager` via `CalendarSelectionProvider` so cached pages
  repaint.
- The dom range band's events-mode geometry, so a selection reads as a strip
  across the date row rather than a block over the event chips.
- Clear the click guard on every fresh press: a sweep ending over a different
  cell gets its trailing click on an ancestor, where nothing consumed the guard,
  so the next plain click was swallowed and onPressDay never fired.
- Keep disabled days out of a sweep, which the README promises but extendCreate
  did not enforce.
- Hand only the sideways axis to the sweep (touch-action: pan-y): the year grid
  is itself the scroll container, so touch-action: none made the later months
  unreachable on a phone.
- Only render a day as a button when onPressDay is set; with just the sweep
  wired, 365 buttons were tab stops whose click and Enter did nothing.
- Hoist getIsToday, which ran three times per cell.
- Scope the tap guard to the web and clear it on every fresh sweep: a pan never
  leaves a press behind, so the flag outlived its interaction and ate the next
  unrelated tap.
- Reject a hold on a blanked adjacent-month cell or an unselectable day, which
  MonthView's hitTest already did.
- Read the pan's inputs from a ref so a consumer's inline handler cannot rebuild
  it mid-drag, which cancels the drag running through it.
- Freeze the ScrollView only on native, where a hold arms the sweep; on the web
  a press arms it at once, so freezing there cost every touch scroll.
@mintlify

mintlify Bot commented Aug 20, 2026

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
super-calendar 🟢 Ready View Preview Aug 20, 2026, 10:27 PM

💡 Tip: Enable Workflows to automatically generate PRs for you.

@afonsojramos
afonsojramos merged commit f93393a into main Aug 20, 2026
4 checks passed
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.

Year/month view: Missing support for selecting, creating, and moving events

1 participant