api reference
Calendar API Reference
createCalendar: a month grid and a week day-grid of rows as cards, keyed by a date field, with navigation, overflow and the viewer contract.
API reference › The calendar viewer
All 21 pages Everything on one page → Developer guide →
The calendar viewer
modules/calendar is an opt-in view of grid rows as cards on a month grid or a week day-grid, keyed by a date field. It is a separate bundle in the same shape as charts, kanban and the data router: it adds no weight to a page that does not load it, changes nothing in grid core, and pulls in no dependency. A calendar is just another dataset viewer: it consumes data through the same keyed-diff contract a grid exposes, calendar.rows.apply({ add, update, remove }) (plus rows.get(key)), so a Data Router can attach(value, calendar) and drive a calendar beside a grid, a kanban and a chart off one feed.
import { createCalendar } from '@toclocoinc/lattice-grid/modules/calendar';
const calendar = createCalendar(document.querySelector('#calendar'), {
rows, // or { grid } to bind a live grid
rowKey: 'id',
startProperty: 'posttime', // the point-event start (configurable)
view: 'week', // 'week' | 'month'
header: { navigation: true, title: true, views: true },
card: { title: 'name' },
colorProperty: 'status', // colour the card edge by a property
onCardClick: ({ row }) => open(row),
});
The date field is startProperty (default 'start'); an optional endProperty turns point events into multi-day spans, drawn as one continuous bar across the days they cover. Days grow with their cards (--lattice-calendar-cell-min-height, default 120px; the page scrolls, never the calendar), and the built-in header (or header: false) carries prev / next / today, the title (SEP 28 - OCT 4, 2026 for a week, SEPTEMBER 2026 for a month, via Intl.DateTimeFormat(locale)) and a week/month toggle, styled only through theme tokens. The week-time and day views add a vertical hour axis: a row with a start time is a block positioned at its start and sized by its end (defaultDuration when there is none), overlapping blocks split the column side by side, all-day rows stack in a top all-day row, businessHours shades the working span, and a now line marks the current time in the current day column. slotDuration (default 30 minutes), slotMinTime/slotMaxTime, scrollTime and weekNumbers tune the axis, and times read through the grid's timeZone rule (a 12:17Z post shows 13:17 under Europe/London summer time). A row whose start is empty or unparsable is counted in unscheduled and reported once, never thrown. Accessibility is built in: role="grid" with columnheader/gridcell, a roving-tabindex focus ring across cards, arrows by day/week (and by slot in the time grid), PageUp/PageDown by period, a live region announcing the range and card count, and an announced time slot on each timed block.
| Member | Description |
|---|---|
| createCalendar(el, config) | Create a calendar. Pass a DOM element to render into, or null for a headless calendar that computes the same range and card model without a DOM. |
| rows.apply({ add, update, remove }) / rows.forEach / rows.count / rows.get(key) | The keyed-diff consumer contract a grid shares, so the calendar is a drop-in Data Router target. get/remove key uncoerced, exactly as the calendar keys its own rows. |
| prev() / next() / today() / goTo(date) / setView('week'|'month') | Navigation. Each fires range:change { start, end, view }; a data update does not. |
| getRange() | The visible range { start, end, view }, both local midnights, end inclusive. |
| refresh() | Recompute and re-render. A grid-bound calendar re-reads its grid; one still on config.rows re-reads that array; a routed calendar re-reads nothing. |
| renderCard(row, el) | A host card renderer; the element is kept mounted across updates and navigation, so an async image swap into the same el survives. The default renderer is time + title, via Intl. |
| colorProperty ( + colorMap) | Colour the card edge by a property's value, through an optional value→colour map. |
| dayMaxEvents / eventOrder | A +N more overflow threshold per day (default off), and the card stacking order (a field or a comparator). |
| getState() / setState(snapshot) | Serialise and restore the arrangement state { version: 2, view, date, firstDay, slotDuration, scrollTime } - never the row data. |
| move(key, { start, end }) | Reschedule a card: move it (shift the end by the same delta so the duration is kept) or resize it (a new end only). Grid-bound, the start/end cells are written through grid.edit.setCells (parse/validate/undo/history/write-back run, and a refused write snaps the card back with the grid's own message beside it); standalone, the calendar's own row is updated and a host onCardMove persists it (returning false/rejecting reverts). Gated by the cancellable beforeMove event; returns a Promise of whether it stuck. |
| on(name, fn) / off(name, fn) | Events: card:click, card:dblclick, card:contextmenu { row, key, clientX, clientY, nativeEvent }; card:mount { row, key, el }; range:change { start, end, view }; beforeMove (cancellable) and card:move { row, key, from: { start, end }, to: { start, end } }. |
| readonly(scope) / unscheduled | Granular readonly (whole / per day / per card), carried on the model; and the rows whose start could not be read. |
| destroy() | Empty the element, remove only what the module added, and drop handlers and caches. The host still owns any bound grid. |
Week and month, navigation and state, executed
Point events on a week grid, one unparsable start counted in unscheduled, the de-dup
contract (add of an existing key is an update), navigation firing range:change, and the
versioned state round-trip. Run headless on every build.
const { createCalendar } = await import('../packages/modules/calendar/index.js');
const cal = createCalendar(null, {
rows: [
{ id: 'a', start: '2026-09-28 10:00', title: 'Login' },
{ id: 'b', start: '2026-09-28 14:00', title: 'OAuth' },
{ id: 'c', start: '2026-10-02 09:00', title: 'Reset' },
{ id: 'd', start: '', title: 'No date' },
],
rowKey: 'id', startProperty: 'start', view: 'week', date: '2026-09-30', firstDay: 1, locale: 'en-GB',
header: { navigation: true, title: true, views: true },
card: { title: 'title', subtitle: 'subtitle' },
ariaLabel: 'Calendar', labels: { today: 'Today', week: 'Week', month: 'Month' },
readonly: false, timeZone: 'Europe/London',
});
const heard = [];
cal.on('range:change', (e) => heard.push(e.view));
const off = () => {};
cal.on('range:change', off); cal.off('range:change', off);
const count = cal.rows.count; // 4
const unscheduled = cal.unscheduled.length; // 1
const startDay = cal.getRange().start.getDate(); // 28
const endDay = cal.getRange().end.getDate(); // 4
cal.rows.apply({ add: [{ id: 'a', start: '2026-09-28 11:00', title: 'Login v2' }] });
const dedup = cal.rows.count; // 4
const title = cal.rows.get('a').title; // Login v2
cal.next(); cal.prev(); cal.today(); // range:change x3
const changes = heard.length; // 3
cal.goTo('2026-09-30');
const nextRange = cal.getRange().start.getDate(); // 28
cal.setView('month');
const monthDays = cal.model.days.length; // 35
cal.refresh();
cal.rebind(null); // no-op: this calendar is not grid-bound
const state = cal.getState(); // view month
cal.setState({ view: 'week', date: '2026-09-30' });
const restored = cal.getRange().view; // week
const ro = cal.readonly({ day: '2026-09-30' }); // false
cal.destroy();
return [count, unscheduled, startDay, endDay, dedup, title, changes, nextRange, monthDays, state.view, restored, ro].join('|');
Spans, colour, overflow and the host renderer, executed
A multi-day span (one continuous bar, marked continuing), colour by property through a map, order by a
field, the +N more overflow threshold, and a host renderer. Run headless on every build.
const { createCalendar } = await import('../packages/modules/calendar/index.js');
const cal = createCalendar(null, {
rows: [
{ id: 's1', start: '2026-09-28', end: '2026-09-30', title: 'Span' },
{ id: 'p1', start: '2026-09-29 09:00', title: 'B', status: 'posted', rank: 2 },
{ id: 'p2', start: '2026-09-29 08:00', title: 'A', status: 'draft', rank: 1 },
{ id: 'p3', start: '2026-09-29 10:00', title: 'C', status: 'posted', rank: 3 },
],
rowKey: 'id', startProperty: 'start', endProperty: 'end', allDayProperty: 'allDay',
view: 'week', date: '2026-09-30', firstDay: 1,
colorProperty: 'status', colorMap: { posted: '#16a34a', draft: '#6b7280' },
eventOrder: 'rank', dayMaxEvents: 2,
renderCard: (row, el) => { el.textContent = row.title; },
onCardClick: () => {}, onCardDblClick: () => {}, onCardContextMenu: () => {}, onRangeChange: () => {},
});
const spanBars = cal.model.days.find((d) => d.key === '2026-09-28').spans;
const span = spanBars[0];
const continuing = span.span; // true
const clippedBefore = span.continuesBefore; // false (starts in range)
const sep29 = cal.model.days.find((d) => d.key === '2026-09-29').cards;
const order = sep29.map((c) => c.row.title).join(','); // A,B,C (by rank)
const colour = sep29.find((c) => c.row.id === 'p1').color; // #16a34a
cal.destroy();
return [continuing, clippedBefore, order, colour].join('|');
The hour axis, overlap columns, all-day and the now line, executed
The week-time/day time grid: a timed block positioned by its start and
sized by its end, overlapping blocks splitting the column, an all-day row, business-hours shading, week numbers
and the time-axis tuning keys. Run headless on every build.
const { createCalendar } = await import('../packages/modules/calendar/index.js');
const cal = createCalendar(null, {
rows: [
{ id: 'a', start: '2026-09-30 09:00', end: '2026-09-30 10:30', title: 'Review' },
{ id: 'b', start: '2026-09-30 09:30', title: 'Overlap' },
{ id: 'all', start: '2026-09-30', title: 'All day' },
],
rowKey: 'id', startProperty: 'start', endProperty: 'end', allDayProperty: 'allDay',
view: 'day', date: '2026-09-30',
slotDuration: 30, slotMinTime: '08:00', slotMaxTime: '18:00', scrollTime: '09:00',
defaultDuration: 60, businessHours: { startTime: '09:00', endTime: '17:00', daysOfWeek: [3] },
weekNumbers: true,
});
const day = cal.model.days[0];
const a = day.timed.find((b) => b.key === 'a');
const startMin = a.startMin; // 540 (09:00)
const endMin = a.endMin; // 630 (10:30)
const cols = a.cols; // 2 (overlaps with b)
const allDay = day.allDay.length; // 1 (the date-only row)
cal.destroy();
return [startMin, endMin, cols, allDay].join('|');
Rescheduling, veto and write-back, executed
A move shifts the end by the same delta (duration kept); a resize changes the end only; a
beforeMove veto cancels synchronously or by promise; card:move fires on success with the old
and new values; and a standalone onCardMove returning false reverts. Run headless on every
build.
const { createCalendar } = await import('../packages/modules/calendar/index.js');
const cal = createCalendar(null, {
rows: [{ id: 1, start: '2026-09-28 10:00', end: '2026-09-28 11:00', title: 'A' }],
rowKey: 'id', startProperty: 'start', endProperty: 'end', view: 'week', date: '2026-09-30',
});
await cal.move(1, { start: new Date(2026, 8, 29, 10, 0) });
const movedStart = cal.rows.get(1).start; // 2026-09-29 10:00
const movedEnd = cal.rows.get(1).end; // 2026-09-29 11:00 (duration kept)
await cal.move(1, { end: new Date(2026, 8, 29, 12, 0) });
const resizedEnd = cal.rows.get(1).end; // 2026-09-29 12:00 (end only)
const heard = [];
cal.on('card:move', (e) => heard.push([e.from.start.getDate(), e.to.start.getDate()]));
const veto = (e) => e.preventDefault('blocked');
cal.on('beforeMove', veto);
await cal.move(1, { start: new Date(2026, 8, 30, 10, 0) }); // vetoed: no card:move
const stayed = cal.rows.get(1).start; // 2026-09-29 10:00
cal.off('beforeMove', veto);
await cal.move(1, { start: new Date(2026, 8, 30, 10, 0) });
const firedFrom = heard[0][0]; // 29
const firedTo = heard[0][1]; // 30
cal.destroy();
const cal2 = createCalendar(null, {
rows: [{ id: 1, start: '2026-09-28 10:00', title: 'B' }],
rowKey: 'id', startProperty: 'start', view: 'week', date: '2026-09-30',
onCardMove: () => false,
});
await cal2.move(1, { start: new Date(2026, 8, 29, 10, 0) });
const reverted = cal2.rows.get(1).start; // 2026-09-28 10:00 (onCardMove reverted)
cal2.destroy();
return [movedStart, movedEnd, resizedEnd, stayed, firedFrom, firedTo, reverted].join('|');
Type reference
Generated from the type declarations, so it always matches the release. Each surface lists its properties, its methods and the events it raises as three tables; an option or value type lists its members once.
The calendar module
CalendarHeader
The built-in header toolbar. Each section is shown unless its flag is `false`; `header: false` (the whole object) renders no header at all and the host draws its own.
| Property | Type | Description |
|---|---|---|
| navigation | boolean | The prev / next / today buttons. (optional) |
| title | boolean | The `SEP 28 - OCT 4, 2026` / `SEPTEMBER 2026` title. (optional) |
| views | boolean | The week/month toggle. (optional) |
CalendarCardMap
The field-to-property mapping that drives the default card template.
| Property | Type | Description |
|---|---|---|
| title | CalendarFieldMap | The card's headline text (the default renderer shows time + this). (optional) |
| subtitle | CalendarFieldMap | A second line under the title. (optional) |
| [field: string] | CalendarFieldMap | undefined | Any other card slot, mapped the same way as the named ones above. |
CalendarPointerEvent
The payload of the three card pointer events - `card:click`, `card:dblclick` and `card:contextmenu`.
| Property | Type | Description |
|---|---|---|
| row | CalendarRow | The data row the card was placed from. |
| key | unknown | The card's key, from `rowKey`. |
| clientX | number | The pointer's X position, where the host wants to anchor a popover. |
| clientY | number | The pointer's Y position. |
| nativeEvent | unknown | The DOM event that caused this one, so a host can call `preventDefault`. |
CalendarMountEvent
The payload of `card:mount` - the card's element was created and attached.
| Property | Type | Description |
|---|---|---|
| row | CalendarRow | The data row the card was placed from. |
| key | unknown | The card's key, from `rowKey`. |
| el | unknown | The card's element, kept mounted for the host's async updates. |
CalendarRangeEvent
The payload of `range:change` - the visible range moved.
| Property | Type | Description |
|---|---|---|
| start | Date | The first visible day, a local midnight. |
| end | Date | The last visible day, a local midnight (inclusive). |
| view | CalendarView 'week' | 'month' | 'week-time' | 'day' | The view now shown: `'week'`, `'month'`, `'week-time'` or `'day'`. |
CalendarMoveSpan
A card's start/end before or after a reschedule; either may be null.
| Property | Type | Description |
|---|---|---|
| start | Date | null | The card's start, or null when it has none. |
| end | Date | null | The card's end, or null when it has none. |
CalendarMoveEvent
The payload of `beforeMove` and `card:move` - a card was (or may be) rescheduled.
| Property | Type | Description |
|---|---|---|
| row | CalendarRow | The data row the card was placed from. |
| key | unknown | The card's key, from `rowKey`. |
| from | CalendarMoveSpan | The card's position before the reschedule. |
| to | CalendarMoveSpan | The card's position after the reschedule. |
| origin | 'user' | 'ai' | Who initiated the move: `'user'` or `'ai'`. (optional) |
| reason | string | When cancelled, the reason given to `preventDefault(reason?)`. (optional) |
CalendarConfig
The configuration for {@link createCalendar}. The data source is `rows` (an array) or `grid` (a live grid to bind). The date field is `startProperty`; an `endProperty` turns point events into multi-day spans.
| Property | Type | Description |
|---|---|---|
| rows | CalendarRow[] | The source rows (one card per row). One of `rows`/`grid`. (optional) |
| grid | unknown | A Lattice grid to bind to instead of `rows`; the calendar follows its filtered/sorted rows live. (optional) |
| rowKey | string | ((row: CalendarRow) => string | number) | The row identity: a property path or a function returning a string or number. Default `'id'`. (optional) |
| startProperty | string | The field naming a point event's start. Default `'start'`. (optional) |
| endProperty | string | The optional field naming a span's end; omitted means point events. (optional) |
| allDayProperty | string | An optional boolean field marking an all-day event, stacked in the time-grid all-day row. (optional) |
| view | CalendarView 'week' | 'month' | 'week-time' | 'day' | The view to show: `'week'`, `'month'`, `'week-time'` or `'day'`. Default `'month'`. (optional) |
| date | Date | string | number | The anchor date the visible range centres on. Default today. (optional) |
| firstDay | number | Week-start weekday, 0=Sun…6=Sat. Default 1 (Monday). (optional) |
| locale | string | BCP-47 locale for weekday/month names, the title and the card time. (optional) |
| timeZone | string | IANA time-zone name, honoured on the hour axis and the now line. (optional) |
| slotDuration | number | string | The time-grid slot step in minutes, or an `'H:MM(:SS)'` duration. Default 30. (optional) |
| slotMinTime | number | string | The hour axis's first time, a clock or minutes. Default `'00:00'`. (optional) |
| slotMaxTime | number | string | The hour axis's last time, a clock or minutes. Default `'24:00'`. (optional) |
| scrollTime | number | string | The hour axis's initial scroll, a clock or minutes. Default `slotMinTime`. (optional) |
| defaultDuration | number | string | A timed block's length when it has no end. Default 60 minutes. (optional) |
| businessHours | boolean | { startTime?: string; endTime?: string; daysOfWeek?: number[] } | The working span the time grid shades: `true`, or `{ startTime, endTime, daysOfWeek }`. Default off. (optional) |
| weekNumbers | boolean | Show the ISO week number in the time-grid header. Default false. (optional) |
| header | CalendarHeader | false | The header toolbar sections, or `false` to render none. (optional) |
| card | CalendarCardMap | The default card template's field mapping (title/subtitle/…). (optional) |
| colorProperty | string | The property whose value picks the card's edge colour. (optional) |
| colorMap | Record<string, string> | An optional value→colour map applied to `colorProperty`'s value. (optional) |
| eventOrder | string | ((a: CalendarRow, b: CalendarRow) => number) | Card stacking order within a day: a property path, or a comparator. (optional) |
| dayMaxEvents | number | false | The `+N more` overflow threshold per day. Default `false` (off). (optional) |
| readonly | CalendarReadonly | Granular readonly (whole calendar, per day, per card). (optional) |
| ariaLabel | string | The calendar's accessible name. Defaults to `Calendar`. (optional) |
| labels | Record<string, string> | Host-localised labels: `today`, `week`, `month`, `more`, `event`, `eventSingular`, `calendar`. (optional) |
| messages | unknown | A message catalogue with `t(key, params)`, or a bound grid's is borrowed. (optional) |
| Method | Signature | Parameters | Returns | Description |
|---|---|---|---|---|
| renderCard | (row: CalendarRow, el: unknown) => unknown | row: CalendarRowel: unknown | => unknown | A host card renderer `(row, el)`; `el` stays mounted for its async updates. (optional) |
| onCardClick | (event: CalendarPointerEvent) => void | event: CalendarPointerEvent | => void | Card click handler - the config route to the `card:click` event. (optional) |
| onCardDblClick | (event: CalendarPointerEvent) => void | event: CalendarPointerEvent | => void | Card double-click handler - the config route to the `card:dblclick` event. (optional) |
| onCardContextMenu | (event: CalendarPointerEvent) => void | event: CalendarPointerEvent | => void | Card right-click handler - the config route to the `card:contextmenu` event. (optional) |
| onRangeChange | (event: CalendarRangeEvent) => void | event: CalendarRangeEvent | => void | Range-changed handler - the config route to the `range:change` event. (optional) |
| onCardMove | (event: CalendarMoveEvent) => unknown | event: CalendarMoveEvent | => unknown | Reschedule handler - the config route to `card:move`. On a standalone calendar, returning `false` (or rejecting) reverts the move. (optional) |
CalendarRows
The keyed-diff consumer surface a calendar shares with a grid, so a Data Router routes to it directly.
| Property | Type | Description |
|---|---|---|
| count | number | How many rows the calendar holds. (read-only) |
| Method | Signature | Parameters | Returns | Description |
|---|---|---|---|---|
| apply | (change: { add?: CalendarRow[]; update?: CalendarRow[]; remove?: unknown[] }): void | change: { add?: CalendarRow[]; update?: CalendarRow[]; remove?: unknown[] } | void | Apply a keyed diff: `add` sets each row outright, `update` merges each patch into the stored row, `remove` drops keys uncoerced - exactly as the calendar keys its own rows. Recomputes and re-renders without firing `range:change`. Ignored on a grid-bound calendar. |
| forEach | (fn: (row: CalendarRow, key: unknown) => void): void | fn: (row: CalendarRow, key: unknown) => void | void | Visit every row the calendar holds, with its key. |
| get | (key: unknown): CalendarRow | undefined | key: unknown | CalendarRow | undefined | The row stored under a key, uncoerced. |
Calendar
A calendar instance: a view of grid rows as cards on a month grid or a week day-grid. It consumes data through the same keyed-diff `rows.apply` contract a grid exposes, so `dataRouter.attach(value, calendar)` drives it like any other viewer.
Properties
| Property | Type | Description |
|---|---|---|
| el | unknown | null | The element the calendar renders into, or null for a headless calendar. (read-only) |
| rowKey | string | ((row: CalendarRow) => string | number) | The resolved row identity; see `CalendarConfig.rowKey`. (read-only) |
| rows | CalendarRows | The keyed-diff consumer surface - what makes the calendar a Data Router target. |
| unscheduled | CalendarRow[] | The rows whose start could not be read, in arrival order. (read-only) |
Methods
| Method | Signature | Parameters | Returns | Description |
|---|---|---|---|---|
| prev | (): Calendar | - | Calendar | Move to the previous week or month, firing `range:change`. |
| next | (): Calendar | - | Calendar | Move to the next week or month, firing `range:change`. |
| today | (): Calendar | - | Calendar | Move back to today, firing `range:change`. |
| goTo | (date: Date | string | number): Calendar | date: Date | string | number | Calendar | Jump to an anchor date, firing `range:change`. |
| setView | (view: CalendarView): Calendar | view: CalendarView | Calendar | Switch the view (`'week'` | `'month'` | `'week-time'` | `'day'`), firing `range:change`. |
| getRange | (): CalendarRangeEvent | - | CalendarRangeEvent | The visible range `{ start, end, view }`, both local midnights, `end` inclusive. |
| refresh | (): Calendar | - | Calendar | Recompute and re-render. A grid-bound calendar re-reads its grid; one still on `config.rows` re-reads that array; a routed calendar re-reads nothing. |
| rebind | (grid: unknown): Calendar | grid: unknown | Calendar | Point this calendar at a replacement grid, the one call a page framework makes after its swap destroyed the grid the calendar was bound to. No-op on a calendar not built over a grid, and on binding to the grid it already follows. |
| getState | (): object | - | object | Serialise the arrangement state: `{ version: 1, view, date, firstDay }`. |
| setState | (snapshot: object): Calendar | snapshot: object | Calendar | Restore a state snapshot from {@link Calendar#getState}, then re-render. |
| on | (name: CalendarEventName, fn: (event: CalendarEventPayloads[CalendarEventName]) => void): () => void | name: CalendarEventNamefn: (event: CalendarEventPayloads[CalendarEventName]) => void | () => void | Register an event handler; returns a function that removes it. |
| off | (name: CalendarEventName, fn: (event: CalendarEventPayloads[CalendarEventName]) => void): void | name: CalendarEventNamefn: (event: CalendarEventPayloads[CalendarEventName]) => void | void | Remove a handler registered with `on`. |
| readonly | (scope?: { day?: string; card?: unknown }): boolean | scope?: { day?: string; card?: unknown } | boolean | Whether a scope (the whole calendar, a day, or a card) is readonly. |
| move | (key: unknown, to: { start?: Date | null; end?: Date | null }, opts?: { origin?: 'user' | 'ai' }): Promise<boolean> | key: unknownto: { start?: Date | null; end?: Date | null }opts?: { origin?: 'user' | 'ai' } | Promise<boolean> | Reschedule a card: move it to a new start (shifting the end by the same delta so the duration is kept) or resize it to a new end. Grid-bound, the start/end cells are written through the grid's `edit.setCells`; standalone, the calendar's own row is updated and a host `onCardMove` persists it. Gated by the cancellable `beforeMove` event. Returns a Promise of whether the reschedule stuck. |
| destroy | (): void | - | void | Empty the element, remove only what the module added, and drop handlers and caches. |
Events
| Event | When | Payload | Cancellable |
|---|---|---|---|
| card:click | A card was clicked, or Enter/Space was pressed on a focused card. | CalendarPointerEvent | no |
| card:dblclick | A card was double-clicked. | CalendarPointerEvent | no |
| card:contextmenu | A context menu was requested on a card. | CalendarPointerEvent | no |
| card:mount | A card's element was created and attached; fires once per mount. | CalendarMountEvent | no |
| range:change | The visible range moved via prev/next/today/goTo/setView (not on a data update). | CalendarRangeEvent | no |
| beforeMove | A card is about to be rescheduled; cancel with `preventDefault(reason?)` or a returned/rejected `false`. | CalendarMoveEvent | no |
| card:move | A card was rescheduled; carries the old and new start/end. | CalendarMoveEvent | no |
CalendarEventPayloads
What a handler receives, per calendar event.
| Property | Type | Description |
|---|---|---|
| card:click | CalendarPointerEvent | The row, key, pointer position and the DOM event. |
| card:dblclick | CalendarPointerEvent | The row, key, pointer position and the DOM event. |
| card:contextmenu | CalendarPointerEvent | The row, key, pointer position and the DOM event. |
| card:mount | CalendarMountEvent | The row, key and the mounted element. |
| range:change | CalendarRangeEvent | The new range's start, end and view. |
| beforeMove | CalendarMoveEvent | The row, key and the from/to positions; veto with `preventDefault(reason?)`. |
| card:move | CalendarMoveEvent | The row, key and the old/new start/end after a successful reschedule. |