fix(02): wire calendar-controls plugin and Zustand selectors

Bug A — navigation no-op: replace $app.calendarState private-API poking
with the official @schedule-x/calendar-controls plugin. CalendarShell
creates the plugin once via useState stable initialiser and passes it to
ViewToolbar as `controls`. ViewToolbar calls controls.setDate(PlainDate)
and controls.setView(id) for all navigation and view-switching. Step size
matches the active view: day→±1 day, week→±1 week, month-*→±1 month.

Bug B — popover-open calendar flash: replace the unselected
useCalendarStore() destructuring in CalendarShell and ViewToolbar with
per-field selectors. Neither component now subscribes to openEventId, so
popover open/close no longer triggers a re-render that rebuilds the
Schedule-X config.

- Add @schedule-x/calendar-controls@4.6.0 dependency
- Update CalendarShell.test.tsx: add vi.mock for calendar-controls
- typecheck, vitest (37/37), build all pass
This commit is contained in:
Lucas Berger
2026-06-05 14:45:27 -04:00
parent 1a24b00de9
commit 5d82f859fd
5 changed files with 100 additions and 54 deletions
@@ -56,6 +56,41 @@ vi.mock('@schedule-x/event-modal', () => ({
})),
}))
// Mock @schedule-x/calendar-controls so CalendarShell can create the plugin
vi.mock('@schedule-x/calendar-controls', () => ({
createCalendarControlsPlugin: vi.fn(() => ({
name: 'calendarControls',
beforeRender: vi.fn(),
onRender: vi.fn(),
setDate: vi.fn(),
setView: vi.fn(),
getDate: vi.fn(() => Temporal.Now.plainDateISO()),
getView: vi.fn(() => 'month-grid'),
setFirstDayOfWeek: vi.fn(),
setLocale: vi.fn(),
setViews: vi.fn(),
setDayBoundaries: vi.fn(),
setWeekOptions: vi.fn(),
setCalendars: vi.fn(),
setMinDate: vi.fn(),
setMaxDate: vi.fn(),
setMonthGridOptions: vi.fn(),
setTimezone: vi.fn(),
setResources: vi.fn(),
getFirstDayOfWeek: vi.fn(),
getLocale: vi.fn(),
getViews: vi.fn(() => []),
getDayBoundaries: vi.fn(),
getWeekOptions: vi.fn(),
getCalendars: vi.fn(() => ({})),
getMinDate: vi.fn(),
getMaxDate: vi.fn(),
getMonthGridOptions: vi.fn(),
getResources: vi.fn(() => []),
getRange: vi.fn(() => null),
})),
}))
// Mock the API client
vi.mock('../api/client.js', () => ({
fetchMe: vi.fn(),