Component

Week planner

<DomWeekPlanner>

A fixed-width week scheduler with days as horizontally scrolling swim lanes and time chunks as rows.

Playground

Configure the time grid

Week planner playground

Change the scrollport height, time range, row size, fixed day width, and number of horizontally scrolling weeks.

8 Jun 2026 – 28 Jun 2026

8 Jun 2026 – 28 Jun 2026
MonJune 2026
8 W24
TueJune 2026
9
WedJune 2026
10
ThuJune 2026
11
FriJune 2026
12
SatJune 2026
13
SunJune 2026
14
MonJune 2026
15 W25
TueJune 2026
16
WedJune 2026
17
ThuJune 2026
18
FriJune 2026
19
SatJune 2026
20
SunJune 2026
21
MonJune 2026
22 W26
TueJune 2026
23
WedJune 2026
24
ThuJune 2026
25
FriJune 2026
26
SatJune 2026
27
SunJune 2026
28
All day
7:00
8:00
9:00
10:00
11:00
12:00
13:00
14:00
15:00
16:00
17:00
18:00
Playground.vuevue
vue
<script setup>
import { reactive } from 'vue';
import { DomWeekPlanner } from '@getdom/studio/vue';

const data = reactive({
	  "startDate": "2026-06-08",
	  "initialMonth": null,
	  "initialYear": null,
	  "weeks": 3,
	  "initialScrollDate": "",
	  "virtualWeeks": false,
	  "virtualWeekBuffer": 2,
	  "locale": "en-GB",
	  "weekStartsOn": 1,
	  "weekdayFormat": "short",
	  "startTime": "07:00",
	  "endTime": "19:00",
	  "timeStep": 60,
	  "slotHeight": 56,
	  "dayWidth": 192,
	  "timeRailWidth": 72,
	  "viewportHeight": 640,
	  "showWeekNumbers": true,
	  "showAllDayRow": true,
	  "showCurrentTime": true,
	  "loading": false,
	  "mutedBefore": "",
	  "mutedAfter": "",
	  "min": "",
	  "max": "",
	  "clickable": false,
	  "rangeSelection": false,
	  "selectionStep": 5,
	  "dragAndDrop": false,
	  "dropEffect": "move",
	  "disabledDate": null,
	  "dayClass": "",
	  "dayStyle": ""
	});
</script>

<template>
	<DomWeekPlanner
		v-bind="data"
	/>
</template>

Demo

Team week planner

Open on three fixed-width weeks, switch to a virtualized full year, and use Today to return to the live current-time line. Timed records use the month-calendar record shape and can be moved to a precise day and time.

June 2026

3 fixed-width weeks

App-owned state

Drag an appointment to reschedule it, or select an empty time row.

8 Jun 2026 – 28 Jun 2026

8 Jun 2026 – 28 Jun 2026
All day
7:00
8:00
9:00
10:00
11:00
12:00
13:00
14:00
15:00
16:00
17:00
18:00

Install window

confirmed

09:00–11:00

Dock 4

Maya Chen

Replacement shutters and access lift.

Site survey

tentative

13:30–15:00

Studio 2

Noah Williams

Check power and loading access.

Design review

confirmed

10:00–12:30

Video call

Ava Brooks

Approve revised material palette.

Maintenance visit

confirmed

08:30–10:00

North lobby

Leo Harris

Quarterly inspection and controls test.

Handover session

confirmed

14:00–16:30

Atrium

Maya Chen

Client training and completion pack.

Parts collection

scheduled

11:00–12:00

West depot

Noah Williams

Collect motors and spare controls.

Accessibility audit

confirmed

09:30–12:00

Civic hall

Ava Brooks

Review entrances, controls, and signage.

Commissioning

scheduled

13:00–16:00

East wing

Leo Harris

System calibration and sign-off.

Creation

Drag to create an event

Drag vertically across an empty day lane with five-minute precision, enter an event name in the dialog, then add it to local Vue state without coupling the planner to a server.

Drag to create

Drag across an empty time lane to create a draft event.

0 local events

27 Jul 2026 – 9 Aug 2026

27 Jul 2026 – 9 Aug 2026
MonJuly 2026
27
TueJuly 2026
28
WedJuly 2026
29
ThuJuly 2026
30
FriJuly 2026
31
SatAugust 2026
1
SunAugust 2026
2
MonAugust 2026
3
TueAugust 2026
4
WedAugust 2026
5
ThuAugust 2026
6
FriAugust 2026
7
SatAugust 2026
8
SunAugust 2026
9
All day
8:00
8:30
9:00
9:30
10:00
10:30
11:00
11:30
12:00
12:30
13:00
13:30
14:00
14:30
15:00
15:30
16:00
16:30
17:00
17:30

Weekly planning

confirmed

09:00–10:00

Project review

confirmed

13:30–15:00

Add event

Name the event before adding it to local state.

Architecture

One calendar data contract, two views

DomWeekPlanner is a different visual representation of the month calendar contract. Both components are transport-free, identify a day with cell.value, and let the application own fetching, grouping, optimistic state, and persistence.

The same record can appear as compact day content in a month grid or as a precisely positioned appointment in the week planner. Keep date as a local date string, then add startTime and endTime when a record needs timed placement.

rangeStyle(record) translates those local times into vertical position and height. It clips records to the visible time range without changing their data, so the API remains suitable for month, week, multi-week, all-day, and server-loaded views.

Enable rangeSelection to let mouse and pen users drag across a time lane. The resulting time-range-select payload contains the local date plus snapped start and end times; selectionStep controls pointer precision independently of the visible timeStep rows. The application decides whether to store the range locally, open an editor, or persist it to an endpoint.

Every day column keeps the configured dayWidth. Increasing weeks adds more columns to the same horizontal scrollport instead of compressing the visible lanes.

The explicit viewportHeight keeps vertical time navigation inside the planner, even when a documentation frame or application shell would otherwise grow to the full grid height. The sticky day and all-day rows remain visible while both axes scroll.

For full-year or longer ranges, enable virtualWeeks. The planner uses the same fixed-item render-window calculation as the data grid, mounts only intersecting weeks plus virtualWeekBuffer, and emits render-window-change with the mounted date range for lazy API loading.

Shared read endpoint

Request the exact inclusive visible range from the same endpoint used by the month view:

GET /api/calendar-records?start=2026-06-08&end=2026-06-28&timezone=Europe/London

Shared record shape

js
const records = [
	{
		id: 'evt_1042',
		date: '2026-06-08',
		title: 'Install window',
		startTime: '09:00',
		endTime: '11:00',
		status: 'confirmed',
		tone: 'primary',
		resourceId: 'field-ops',
		meta: {
			customerId: 'cus_8821',
			location: 'Dock 4',
		},
	},
];

/**
 * Lists calendar records for a local date key.
 *
 * @param {string} date YYYY-MM-DD date key.
 * @returns {Array<Record<string, unknown>>} Matching calendar records.
 */
function recordsFor(date) {
	return records.filter((record) => record.date === date);
}

Switch visual representations

vue
<DomMonthCalendar
	:start-date="rangeStart"
	:months="2"
>
	<template #default="{ cell }">
		<MonthCard
			v-for="record in recordsFor(cell.value)"
			:key="record.id"
			:record="record"
		/>
	</template>
</DomMonthCalendar>

<DomWeekPlanner
	:start-date="rangeStart"
	:weeks="3"
	start-time="07:00"
	end-time="20:00"
>
	<template #default="{ cell, rangeStyle }">
		<TimedCard
			v-for="record in recordsFor(cell.value)"
			:key="record.id"
			:record="record"
			:style="rangeStyle(record)"
		/>
	</template>
</DomWeekPlanner>

Interaction

Precise app-owned rescheduling

The default slot exposes the same dragAttrs(data) pattern as the month calendar. Both components use the same native transfer type, so an application can carry a record between visual representations without translating its identity.

day-drop keeps the existing source and target date fields, then adds sourceTime, targetTime, and minute values. Timed drops snap to timeStep; drops in the all-day row return an empty target time.

vue
<DomWeekPlanner
	:start-date="rangeStart"
	drag-and-drop
	@day-drop="moveRecord"
>
	<template #default="{ cell, dragAttrs, rangeStyle }">
		<AppointmentCard
			v-for="record in recordsFor(cell.value)"
			:key="record.id"
			v-bind="dragAttrs(record, { sourceTime: record.startTime })"
			:record="record"
			:style="rangeStyle(record)"
		/>
	</template>
</DomWeekPlanner>

/**
 * Persists one app-owned record after a planner drop.
 *
 * @param {object} payload Planner day-drop payload.
 * @returns {void}
 */
function moveRecord({ data, targetValue, targetTime }) {
	// Persist the record in the application layer.
	updateCalendarRecord(data.id, {
		date: targetValue,
		startTime: targetTime,
	});
}

Reference

Props

Control props

NameTypeTSDefaultDescription
localestringstring'en-GB'Locale used for weekday, date, month, and time labels.
weekStartsOn0 | 1 | 2 | 3 | 4 | 5 | 6number1First day of week. 0 is Sunday, 1 is Monday.
weekdayFormat'narrow' | 'short' | 'long'string'short'Weekday label length.
mutedBeforestringstring''Dates before this YYYY-MM-DD value render muted.
mutedAfterstringstring''Dates after this YYYY-MM-DD value render muted.

Interaction

NameTypeTSDefaultDescription
minstringstring''Minimum clickable or droppable date as YYYY-MM-DD.
maxstringstring''Maximum clickable or droppable date as YYYY-MM-DD.
clickablebooleanbooleanfalseEmit day-click with the selected day and snapped time.
rangeSelectionbooleanbooleanfalseAllow mouse or pen dragging across a time lane and emit time-range-select.
selectionStepnumbernumber5Minutes used to snap drag-created time ranges independently of the visible time rows.
dragAndDropbooleanbooleanfalseExpose dragAttrs and emit day-drop with the target day and snapped time.
dropEffect'copy' | 'move' | 'link'string'move'Native drop effect shown when a time lane can receive a dragged item.
disabledDatefunction(cell: WeekPlannerCell
type WeekPlannerCell = {
	date: Date; // Local Date instance for the day.
	value: string; // YYYY-MM-DD date key shared with DomMonthCalendar.
	day: number; // Day of the month.
	weekday: string; // Formatted weekday label.
	label: string; // Full accessible date label.
	currentMonth: boolean; // True when the day belongs to the anchor month.
	previousMonth: boolean; // True when the day is before the anchor month.
	nextMonth: boolean; // True when the day is after the anchor month.
	adjacentMonth: boolean; // True when the day is outside the anchor month.
	hidden: boolean; // Always false in the week planner.
	monthValue: string; // YYYY-MM month key.
	row: number; // Zero-based week index.
	column: number; // Zero-based weekday column.
	weekNumber: number; // ISO-8601 week number.
	today: boolean;
	past: boolean;
	future: boolean;
	muted: boolean;
	disabled: boolean;
};
) => boolean
Function that receives a day cell and returns true when the day should not be clickable or droppable.

Layout

NameTypeTSDefaultDescription
dayWidthnumbernumber192Fixed pixel width of every day swim lane. Additional weeks scroll horizontally.
timeRailWidthnumbernumber72Pixel width of the sticky time-label rail.
viewportHeightnumbernumber640Pixel height of the internal two-axis scroll viewport.
showWeekNumbersbooleanbooleanfalseShow the ISO week number on the first day of each week.
showAllDayRowbooleanbooleantrueRender a sticky all-day row above the timed grid.
showCurrentTimebooleanbooleantrueShow a live current-time line in today’s time lane when the current time is visible.

Range

NameTypeTSDefaultDescription
startDatestringstring''Date inside the first rendered week as YYYY-MM-DD.
initialMonthnumbernumberInitial month, 1-12. Used when startDate is not set.
initialYearnumbernumberInitial year. Used when startDate is not set.
weeksnumbernumber3Number of consecutive weeks to render as fixed-width day columns.
initialScrollDatestringstring''Date to reveal after mount or a range reset. Useful when a virtual year starts before the focused date.
virtualWeeksbooleanbooleanfalseMount only the horizontally visible weeks plus the configured buffer.
virtualWeekBuffernumbernumber2Extra weeks mounted before and after the visible horizontal window.

State

NameTypeTSDefaultDescription
loadingbooleanbooleanfalseShow an in-viewport loading indicator while the app fetches the requested render window.

Styling

NameTypeTSDefaultDescription
dayClassstring | array | object | functionstring | Array<unknown> | Record<string, boolean> | ((cell: WeekPlannerCell
type WeekPlannerCell = {
	date: Date; // Local Date instance for the day.
	value: string; // YYYY-MM-DD date key shared with DomMonthCalendar.
	day: number; // Day of the month.
	weekday: string; // Formatted weekday label.
	label: string; // Full accessible date label.
	currentMonth: boolean; // True when the day belongs to the anchor month.
	previousMonth: boolean; // True when the day is before the anchor month.
	nextMonth: boolean; // True when the day is after the anchor month.
	adjacentMonth: boolean; // True when the day is outside the anchor month.
	hidden: boolean; // Always false in the week planner.
	monthValue: string; // YYYY-MM month key.
	row: number; // Zero-based week index.
	column: number; // Zero-based weekday column.
	weekNumber: number; // ISO-8601 week number.
	today: boolean;
	past: boolean;
	future: boolean;
	muted: boolean;
	disabled: boolean;
};
) => unknown)
''Extra classes, or a function that receives a day cell and returns classes for the day lane.
dayStylestring | object | functionstring | Record<string, string | number> | ((cell: WeekPlannerCell
type WeekPlannerCell = {
	date: Date; // Local Date instance for the day.
	value: string; // YYYY-MM-DD date key shared with DomMonthCalendar.
	day: number; // Day of the month.
	weekday: string; // Formatted weekday label.
	label: string; // Full accessible date label.
	currentMonth: boolean; // True when the day belongs to the anchor month.
	previousMonth: boolean; // True when the day is before the anchor month.
	nextMonth: boolean; // True when the day is after the anchor month.
	adjacentMonth: boolean; // True when the day is outside the anchor month.
	hidden: boolean; // Always false in the week planner.
	monthValue: string; // YYYY-MM month key.
	row: number; // Zero-based week index.
	column: number; // Zero-based weekday column.
	weekNumber: number; // ISO-8601 week number.
	today: boolean;
	past: boolean;
	future: boolean;
	muted: boolean;
	disabled: boolean;
};
) => string | Record<string, string | number> | null | undefined)
''Extra styles, or a function that receives a day cell and returns styles for the day lane.

Time grid

NameTypeTSDefaultDescription
startTimestringstring'07:00'First visible time as HH:mm.
endTimestringstring'20:00'Exclusive final visible time as HH:mm. Use 24:00 to include the full day.
timeStepnumbernumber60Minutes represented by each horizontal time row.
slotHeightnumbernumber56Pixel height of each time row.

Auto-generated from Week planner.props and inline _edit hints.

Events

NamePayloadDescription
@day-click({ cell
type WeekPlannerCell = {
	date: Date; // Local Date instance for the day.
	value: string; // YYYY-MM-DD date key shared with DomMonthCalendar.
	day: number; // Day of the month.
	weekday: string; // Formatted weekday label.
	label: string; // Full accessible date label.
	currentMonth: boolean; // True when the day belongs to the anchor month.
	previousMonth: boolean; // True when the day is before the anchor month.
	nextMonth: boolean; // True when the day is after the anchor month.
	adjacentMonth: boolean; // True when the day is outside the anchor month.
	hidden: boolean; // Always false in the week planner.
	monthValue: string; // YYYY-MM month key.
	row: number; // Zero-based week index.
	column: number; // Zero-based weekday column.
	weekNumber: number; // ISO-8601 week number.
	today: boolean;
	past: boolean;
	future: boolean;
	muted: boolean;
	disabled: boolean;
};
, targetTime
targetTime: string;
, targetMinutes
targetMinutes: number | null;
, event
event: MouseEvent;
})
Fired when a clickable day header, all-day cell, or timed row is activated.
@time-range-select({ cell
type WeekPlannerCell = {
	date: Date; // Local Date instance for the day.
	value: string; // YYYY-MM-DD date key shared with DomMonthCalendar.
	day: number; // Day of the month.
	weekday: string; // Formatted weekday label.
	label: string; // Full accessible date label.
	currentMonth: boolean; // True when the day belongs to the anchor month.
	previousMonth: boolean; // True when the day is before the anchor month.
	nextMonth: boolean; // True when the day is after the anchor month.
	adjacentMonth: boolean; // True when the day is outside the anchor month.
	hidden: boolean; // Always false in the week planner.
	monthValue: string; // YYYY-MM month key.
	row: number; // Zero-based week index.
	column: number; // Zero-based weekday column.
	weekNumber: number; // ISO-8601 week number.
	today: boolean;
	past: boolean;
	future: boolean;
	muted: boolean;
	disabled: boolean;
};
, value
value: string;
, startTime
startTime: string;
, endTime
endTime: string;
, startMinutes
startMinutes: number;
, endMinutes
endMinutes: number;
, event
event: PointerEvent;
})
Fired after a mouse or pen drag selects a snapped time range. The planner does not create or persist records.
@day-drag-start({ cell
type WeekPlannerCell = {
	date: Date; // Local Date instance for the day.
	value: string; // YYYY-MM-DD date key shared with DomMonthCalendar.
	day: number; // Day of the month.
	weekday: string; // Formatted weekday label.
	label: string; // Full accessible date label.
	currentMonth: boolean; // True when the day belongs to the anchor month.
	previousMonth: boolean; // True when the day is before the anchor month.
	nextMonth: boolean; // True when the day is after the anchor month.
	adjacentMonth: boolean; // True when the day is outside the anchor month.
	hidden: boolean; // Always false in the week planner.
	monthValue: string; // YYYY-MM month key.
	row: number; // Zero-based week index.
	column: number; // Zero-based weekday column.
	weekNumber: number; // ISO-8601 week number.
	today: boolean;
	past: boolean;
	future: boolean;
	muted: boolean;
	disabled: boolean;
};
, sourceValue
sourceValue: string;
, sourceTime
sourceTime: string;
, data
data: unknown;
, event
event: DragEvent;
})
Fired when an item using dragAttrs starts dragging.
@day-drag-enter({ sourceCell
type WeekPlannerCell = {
	date: Date; // Local Date instance for the day.
	value: string; // YYYY-MM-DD date key shared with DomMonthCalendar.
	day: number; // Day of the month.
	weekday: string; // Formatted weekday label.
	label: string; // Full accessible date label.
	currentMonth: boolean; // True when the day belongs to the anchor month.
	previousMonth: boolean; // True when the day is before the anchor month.
	nextMonth: boolean; // True when the day is after the anchor month.
	adjacentMonth: boolean; // True when the day is outside the anchor month.
	hidden: boolean; // Always false in the week planner.
	monthValue: string; // YYYY-MM month key.
	row: number; // Zero-based week index.
	column: number; // Zero-based weekday column.
	weekNumber: number; // ISO-8601 week number.
	today: boolean;
	past: boolean;
	future: boolean;
	muted: boolean;
	disabled: boolean;
};
, targetCell
type WeekPlannerCell = {
	date: Date; // Local Date instance for the day.
	value: string; // YYYY-MM-DD date key shared with DomMonthCalendar.
	day: number; // Day of the month.
	weekday: string; // Formatted weekday label.
	label: string; // Full accessible date label.
	currentMonth: boolean; // True when the day belongs to the anchor month.
	previousMonth: boolean; // True when the day is before the anchor month.
	nextMonth: boolean; // True when the day is after the anchor month.
	adjacentMonth: boolean; // True when the day is outside the anchor month.
	hidden: boolean; // Always false in the week planner.
	monthValue: string; // YYYY-MM month key.
	row: number; // Zero-based week index.
	column: number; // Zero-based weekday column.
	weekNumber: number; // ISO-8601 week number.
	today: boolean;
	past: boolean;
	future: boolean;
	muted: boolean;
	disabled: boolean;
};
, targetValue
targetValue: string;
, targetTime
targetTime: string;
, data
data: unknown;
, event
event: DragEvent;
})
Fired when a draggable item previews a day and time.
@day-drag-leave({ sourceCell
type WeekPlannerCell = {
	date: Date; // Local Date instance for the day.
	value: string; // YYYY-MM-DD date key shared with DomMonthCalendar.
	day: number; // Day of the month.
	weekday: string; // Formatted weekday label.
	label: string; // Full accessible date label.
	currentMonth: boolean; // True when the day belongs to the anchor month.
	previousMonth: boolean; // True when the day is before the anchor month.
	nextMonth: boolean; // True when the day is after the anchor month.
	adjacentMonth: boolean; // True when the day is outside the anchor month.
	hidden: boolean; // Always false in the week planner.
	monthValue: string; // YYYY-MM month key.
	row: number; // Zero-based week index.
	column: number; // Zero-based weekday column.
	weekNumber: number; // ISO-8601 week number.
	today: boolean;
	past: boolean;
	future: boolean;
	muted: boolean;
	disabled: boolean;
};
, targetCell
type WeekPlannerCell = {
	date: Date; // Local Date instance for the day.
	value: string; // YYYY-MM-DD date key shared with DomMonthCalendar.
	day: number; // Day of the month.
	weekday: string; // Formatted weekday label.
	label: string; // Full accessible date label.
	currentMonth: boolean; // True when the day belongs to the anchor month.
	previousMonth: boolean; // True when the day is before the anchor month.
	nextMonth: boolean; // True when the day is after the anchor month.
	adjacentMonth: boolean; // True when the day is outside the anchor month.
	hidden: boolean; // Always false in the week planner.
	monthValue: string; // YYYY-MM month key.
	row: number; // Zero-based week index.
	column: number; // Zero-based weekday column.
	weekNumber: number; // ISO-8601 week number.
	today: boolean;
	past: boolean;
	future: boolean;
	muted: boolean;
	disabled: boolean;
};
, targetValue
targetValue: string;
, targetTime
targetTime: string;
, data
data: unknown;
, event
event: DragEvent;
})
Fired when a draggable item leaves a day lane.
@day-drop({ sourceCell
type WeekPlannerCell = {
	date: Date; // Local Date instance for the day.
	value: string; // YYYY-MM-DD date key shared with DomMonthCalendar.
	day: number; // Day of the month.
	weekday: string; // Formatted weekday label.
	label: string; // Full accessible date label.
	currentMonth: boolean; // True when the day belongs to the anchor month.
	previousMonth: boolean; // True when the day is before the anchor month.
	nextMonth: boolean; // True when the day is after the anchor month.
	adjacentMonth: boolean; // True when the day is outside the anchor month.
	hidden: boolean; // Always false in the week planner.
	monthValue: string; // YYYY-MM month key.
	row: number; // Zero-based week index.
	column: number; // Zero-based weekday column.
	weekNumber: number; // ISO-8601 week number.
	today: boolean;
	past: boolean;
	future: boolean;
	muted: boolean;
	disabled: boolean;
};
, targetCell
type WeekPlannerCell = {
	date: Date; // Local Date instance for the day.
	value: string; // YYYY-MM-DD date key shared with DomMonthCalendar.
	day: number; // Day of the month.
	weekday: string; // Formatted weekday label.
	label: string; // Full accessible date label.
	currentMonth: boolean; // True when the day belongs to the anchor month.
	previousMonth: boolean; // True when the day is before the anchor month.
	nextMonth: boolean; // True when the day is after the anchor month.
	adjacentMonth: boolean; // True when the day is outside the anchor month.
	hidden: boolean; // Always false in the week planner.
	monthValue: string; // YYYY-MM month key.
	row: number; // Zero-based week index.
	column: number; // Zero-based weekday column.
	weekNumber: number; // ISO-8601 week number.
	today: boolean;
	past: boolean;
	future: boolean;
	muted: boolean;
	disabled: boolean;
};
, sourceValue
sourceValue: string;
, targetValue
targetValue: string;
, sourceTime
sourceTime: string;
, targetTime
targetTime: string;
, data
data: unknown;
, event
event: DragEvent;
})
Fired when an item is dropped. The planner does not mutate records.
@day-drag-end({ sourceCell
type WeekPlannerCell = {
	date: Date; // Local Date instance for the day.
	value: string; // YYYY-MM-DD date key shared with DomMonthCalendar.
	day: number; // Day of the month.
	weekday: string; // Formatted weekday label.
	label: string; // Full accessible date label.
	currentMonth: boolean; // True when the day belongs to the anchor month.
	previousMonth: boolean; // True when the day is before the anchor month.
	nextMonth: boolean; // True when the day is after the anchor month.
	adjacentMonth: boolean; // True when the day is outside the anchor month.
	hidden: boolean; // Always false in the week planner.
	monthValue: string; // YYYY-MM month key.
	row: number; // Zero-based week index.
	column: number; // Zero-based weekday column.
	weekNumber: number; // ISO-8601 week number.
	today: boolean;
	past: boolean;
	future: boolean;
	muted: boolean;
	disabled: boolean;
};
, targetCell
type WeekPlannerCell = {
	date: Date; // Local Date instance for the day.
	value: string; // YYYY-MM-DD date key shared with DomMonthCalendar.
	day: number; // Day of the month.
	weekday: string; // Formatted weekday label.
	label: string; // Full accessible date label.
	currentMonth: boolean; // True when the day belongs to the anchor month.
	previousMonth: boolean; // True when the day is before the anchor month.
	nextMonth: boolean; // True when the day is after the anchor month.
	adjacentMonth: boolean; // True when the day is outside the anchor month.
	hidden: boolean; // Always false in the week planner.
	monthValue: string; // YYYY-MM month key.
	row: number; // Zero-based week index.
	column: number; // Zero-based weekday column.
	weekNumber: number; // ISO-8601 week number.
	today: boolean;
	past: boolean;
	future: boolean;
	muted: boolean;
	disabled: boolean;
};
, sourceValue
sourceValue: string;
, targetValue
targetValue: string;
, sourceTime
sourceTime: string;
, targetTime
targetTime: string;
, data
data: unknown;
, event
event: DragEvent;
})
Fired when a drag started with dragAttrs ends.
@viewport-scroll({ scrollLeft
scrollLeft: number;
, scrollWidth
scrollWidth: number;
, clientWidth
clientWidth: number;
, remaining
remaining: number;
, atStart
atStart: boolean;
, atEnd
atEnd: boolean;
})
Fired while the internal two-axis viewport scrolls horizontally.
@viewport-end({ scrollLeft
scrollLeft: number;
, scrollWidth
scrollWidth: number;
, clientWidth
clientWidth: number;
, remaining
remaining: number;
, atStart
atStart: boolean;
, atEnd
atEnd: boolean;
})
Fired when horizontal scrolling reaches the end threshold. Apps can append another date range.
@render-window-change({ startIndex
startIndex: number;
, endIndex
endIndex: number;
, renderedWeeks
renderedWeeks: number;
, totalWeeks
totalWeeks: number;
, start
start: string;
, end
end: string;
})
Fired when the mounted virtual week window changes so apps can fetch its record range.

Names auto-detected from defineEmits and source emit() calls; payload and description from __doc.events when present.

Slots

NameScopeDescription
#(default){ cell
type WeekPlannerCell = {
	date: Date; // Local Date instance for the day.
	value: string; // YYYY-MM-DD date key shared with DomMonthCalendar.
	day: number; // Day of the month.
	weekday: string; // Formatted weekday label.
	label: string; // Full accessible date label.
	currentMonth: boolean; // True when the day belongs to the anchor month.
	previousMonth: boolean; // True when the day is before the anchor month.
	nextMonth: boolean; // True when the day is after the anchor month.
	adjacentMonth: boolean; // True when the day is outside the anchor month.
	hidden: boolean; // Always false in the week planner.
	monthValue: string; // YYYY-MM month key.
	row: number; // Zero-based week index.
	column: number; // Zero-based weekday column.
	weekNumber: number; // ISO-8601 week number.
	today: boolean;
	past: boolean;
	future: boolean;
	muted: boolean;
	disabled: boolean;
};
, month
type WeekPlannerMonth = {
	date: Date; // Local Date instance for the first day of the month.
	value: string; // YYYY-MM month key.
	id: string; // Element id for the month.
	month: number; // Month number, 1-12.
	year: number; // Four-digit year.
	label: string; // Formatted month label.
	cells: Array<WeekPlannerCell
>; // Visible cells belonging to the month. weeks: Array<WeekPlannerWeek
>; // Visible week fragments belonging to the month. };
, week
type WeekPlannerWeek = {
	index: number; // Zero-based week index.
	weekNumber: number; // ISO-8601 week number.
	label: string; // Accessible week label.
	value: string; // YYYY-MM-DD key for the first day in the week.
	days: Array<WeekPlannerCell
>; // Seven ordered day cells. };
, timeSlots
type WeekPlannerTimeSlot = {
	index: number; // Zero-based time-row index.
	minutes: number; // Minutes from midnight at the start of the row.
	endMinutes: number; // Minutes from midnight at the end of the row.
	time: string; // HH:mm start time.
	endTime: string; // HH:mm end time.
	label: string; // Locale-aware time label.
};
, drag
type WeekPlannerDragState = {
	active: boolean; // True while a planner drag is in progress.
	source: boolean; // True for the day where the drag started.
	over: boolean; // True for the current drop-preview day.
	sourceCell: WeekPlannerCell
| null; // Source day when it is visible. overCell: WeekPlannerCell
| null; // Current drop-preview day. data: unknown; // App-owned data passed to dragAttrs. sourceTime: string; // HH:mm source time when supplied. overTime: string; // HH:mm preview time, or an empty string for all-day. };
, dragAttrs
type WeekPlannerDragAttrs = (data?: unknown, options?: WeekPlannerDragAttrsOptions
) => Record<string, unknown>;
, rangeStyle
rangeStyle: (recordOrStartTime: Record<string, unknown> | string, endTime?: string) => Record<string, string>;
}
Timed content layer for each day. Use rangeStyle(record) with records containing startTime and endTime.
#day-header{ cell, month, week }Custom day-column header content.
#all-day{ cell, month, week, drag, dragAttrs }All-day content rendered above the timed rows.
#time-label{ slot }Custom sticky time-rail label.
#corner{ range }Content above the sticky time rail.

Keyboard

  • TabMove through day headers, all-day cells, and time rows when clickable is enabled.
  • Enter / SpaceActivate the focused day or time row.