import {
Calendar,
DayGrid,
TimeGrid,
useCalendar,
useCalendarController,
type CalendarProps,
type EventInput,
} from 'z-cal/react'
import type { JSX } from 'react'
import { useScheme } from '../DemoFrame'
import { today, todayDate } from '../shared/dates'
const PLUGINS = [DayGrid, TimeGrid]
const EVENTS: EventInput[] = [
{
id: 1,
title: 'Team sync',
start: today(0, 10),
end: today(0, 11),
extendedProps: { location: 'Room A' },
},
{ id: 2, title: 'Conference', start: todayDate(1), end: todayDate(4) },
{
id: 3,
title: 'Workshop',
start: today(0, 13),
end: today(0, 15),
extendedProps: { location: 'Lab' },
},
{ id: 4, title: 'Design review', start: today(-1, 16), end: today(-1, 17) },
{ id: 5, title: 'Stand-up', start: today(0, 9), end: today(0, 9, 15) },
{
id: 6,
title: 'Coffee catch-up',
start: today(1, 11),
end: today(1, 11, 30),
extendedProps: { location: 'Cafe' },
},
]
// Content slots return React nodes. This one renders the default title and time markup itself and
// appends the event's location to the time line. Reusing the core class names keeps the built-in
// layout, including the one-line form for 30 and 15 minute events.
const eventContent: CalendarProps['eventContent'] = (info) => {
const location = info.event.extendedProps['location']
return (
<>
<h4 className="cx-event-title">{String(info.event.title)}</h4>
{info.timeText && (
<time className="cx-event-time">
{info.timeText}
{typeof location === 'string' && ` · ${location}`}
</time>
)}
</>
)
}
export function CustomContentDemo(): JSX.Element {
const { ref, calendar } = useCalendar()
const controller = useCalendarController(calendar)
// Month view only: other views re-create their day cells, so the slot is not requested there.
const dayCellContent: CalendarProps['dayCellContent'] =
controller.view === 'dayGridMonth'
? (info) => <span className="day-number">{info.date.day}</span>
: undefined
return (
<>
{/* A headless toolbar: the built-in one is off and these buttons drive the instance. */}
<div className="headless-toolbar">
<button type="button" aria-label="Previous" onClick={controller.prev}>
‹
</button>
<strong>{controller.title}</strong>
<button type="button" aria-label="Next" onClick={controller.next}>
›
</button>
<button type="button" onClick={controller.today}>
Today
</button>
<select
value={controller.view}
onChange={(e) => calendar?.changeView(e.currentTarget.value)}
aria-label="View"
>
<option value="dayGridMonth">Month</option>
<option value="timeGridWeek">Week</option>
</select>
</div>
<div className="card">
<Calendar
ref={ref}
plugins={PLUGINS}
view="dayGridMonth"
colorScheme={useScheme()}
headerToolbar={{ start: '', center: '', end: '' }}
events={EVENTS}
eventContent={eventContent}
dayCellContent={dayCellContent}
height="560px"
/>
</div>
</>
)
}