All the logic you need to quickly build a custom calendar or date-picker for any framework or plain vanilla JavaScript.
- Generates data to populate a grid
- Split your events by date
- Supports fill or fitted weeks (filled weeks always shows 6 weeks)
- Supports before and after date
- Supports start of week
- Supports range selection
- Supports disabling certains days
- Supports disabling days of the week
const options = {
firstDay: 1 // Monday
}
let calendar = create(Date.now(), options)
const nextMonth = () => {
calendar = create(calendar.next, options)
}
const prevMonth = () => {
calendar = create(calendar.prev, options)
}
Sample output from calling create()
Details
``` { config: { after: null, before: null, fillWeek: true, firstDay: 1, now: 2021-09-05T16:00:00.000Z, selection: null }, next: 2021-09-30T16:00:00.000Z, prev: 2021-07-31T16:00:00.000Z, current: 2021-08-31T16:00:00.000Z, start: 2021-08-31T16:00:00.000Z, end: 2021-09-29T16:00:00.000Z, days: [ { date: 2021-08-29T16:00:00.000Z, day: 30, dayOfWeek: 1, isToday: false, selection: null, state: 'valid', inMonth: false }, { date: 2021-08-30T16:00:00.000Z, day: 31, dayOfWeek: 2, isToday: false, selection: null, state: 'valid', inMonth: false }, { date: 2021-08-31T16:00:00.000Z, day: 1, dayOfWeek: 3, isToday: false, selection: null, state: 'valid', inMonth: true }, { date: 2021-09-01T16:00:00.000Z, day: 2, dayOfWeek: 4, isToday: false, selection: null, state: 'valid', inMonth: true }, { date: 2021-09-02T16:00:00.000Z, day: 3, dayOfWeek: 5, isToday: false, selection: null, state: 'valid', inMonth: true }, { date: 2021-09-03T16:00:00.000Z, day: 4, dayOfWeek: 6, isToday: false, selection: null, state: 'valid', inMonth: true }, { date: 2021-09-04T16:00:00.000Z, day: 5, dayOfWeek: 0, isToday: false, selection: null, state: 'valid', inMonth: true }, { date: 2021-09-05T16:00:00.000Z, day: 6, dayOfWeek: 1, isToday: true, selection: null, state: 'valid', inMonth: true }, { date: 2021-09-06T16:00:00.000Z, day: 7, dayOfWeek: 2, isToday: false, selection: null, state: 'valid', inMonth: true }, { date: 2021-09-07T16:00:00.000Z, day: 8, dayOfWeek: 3, isToday: false, selection: null, state: 'valid', inMonth: true }, { date: 2021-09-08T16:00:00.000Z, day: 9, dayOfWeek: 4, isToday: false, selection: null, state: 'valid', inMonth: true }, { date: 2021-09-09T16:00:00.000Z, day: 10, dayOfWeek: 5, isToday: false, selection: null, state: 'valid', inMonth: true }, { date: 2021-09-10T16:00:00.000Z, day: 11, dayOfWeek: 6, isToday: false, selection: null, state: 'valid', inMonth: true }, { date: 2021-09-11T16:00:00.000Z, day: 12, dayOfWeek: 0, isToday: false, selection: null, state: 'valid', inMonth: true }, { date: 2021-09-12T16:00:00.000Z, day: 13, dayOfWeek: 1, isToday: false, selection: null, state: 'valid', inMonth: true }, { date: 2021-09-13T16:00:00.000Z, day: 14, dayOfWeek: 2, isToday: false, selection: null, state: 'valid', inMonth: true }, { date: 2021-09-14T16:00:00.000Z, day: 15, dayOfWeek: 3, isToday: false, selection: null, state: 'valid', inMonth: true }, { date: 2021-09-15T16:00:00.000Z, day: 16, dayOfWeek: 4, isToday: false, selection: null, state: 'valid', inMonth: true }, { date: 2021-09-16T16:00:00.000Z, day: 17, dayOfWeek: 5, isToday: false, selection: null, state: 'valid', inMonth: true }, { date: 2021-09-17T16:00:00.000Z, day: 18, dayOfWeek: 6, isToday: false, selection: null, state: 'valid', inMonth: true }, { date: 2021-09-18T16:00:00.000Z, day: 19, dayOfWeek: 0, isToday: false, selection: null, state: 'valid', inMonth: true }, { date: 2021-09-19T16:00:00.000Z, day: 20, dayOfWeek: 1, isToday: false, selection: null, state: 'valid', inMonth: true }, { date: 2021-09-20T16:00:00.000Z, day: 21, dayOfWeek: 2, isToday: false, selection: null, state: 'valid', inMonth: true }, { date: 2021-09-21T16:00:00.000Z, day: 22, dayOfWeek: 3, isToday: false, selection: null, state: 'valid', inMonth: true }, { date: 2021-09-22T16:00:00.000Z, day: 23, dayOfWeek: 4, isToday: false, selection: null, state: 'valid', inMonth: true }, { date: 2021-09-23T16:00:00.000Z, day: 24, dayOfWeek: 5, isToday: false, selection: null, state: 'valid', inMonth: true }, { date: 2021-09-24T16:00:00.000Z, day: 25, dayOfWeek: 6, isToday: false, selection: null, state: 'valid', inMonth: true }, { date: 2021-09-25T16:00:00.000Z, day: 26, dayOfWeek: 0, isToday: false, selection: null, state: 'valid', inMonth: true }, { date: 2021-09-26T16:00:00.000Z, day: 27, dayOfWeek: 1, isToday: false, selection: null, state: 'valid', inMonth: true }, { date: 2021-09-27T16:00:00.000Z, day: 28, dayOfWeek: 2, isToday: false, selection: null, state: 'valid', inMonth: true }, { date: 2021-09-28T16:00:00.000Z, day: 29, dayOfWeek: 3, isToday: false, selection: null, state: 'valid', inMonth: true }, { date: 2021-09-29T16:00:00.000Z, day: 30, dayOfWeek: 4, isToday: false, selection: null, state: 'valid', inMonth: true }, { date: 2021-09-30T16:00:00.000Z, day: 1, dayOfWeek: 5, isToday: false, selection: null, state: 'valid', inMonth: false }, { date: 2021-10-01T16:00:00.000Z, day: 2, dayOfWeek: 6, isToday: false, selection: null, state: 'valid', inMonth: false }, { date: 2021-10-02T16:00:00.000Z, day: 3, dayOfWeek: 0, isToday: false, selection: null, state: 'valid', inMonth: false }, { date: 2021-10-03T16:00:00.000Z, day: 4, dayOfWeek: 1, isToday: false, selection: null, state: 'valid', inMonth: false }, { date: 2021-10-04T16:00:00.000Z, day: 5, dayOfWeek: 2, isToday: false, selection: null, state: 'valid', inMonth: false }, { date: 2021-10-05T16:00:00.000Z, day: 6, dayOfWeek: 3, isToday: false, selection: null, state: 'valid', inMonth: false }, { date: 2021-10-06T16:00:00.000Z, day: 7, dayOfWeek: 4, isToday: false, selection: null, state: 'valid', inMonth: false }, { date: 2021-10-07T16:00:00.000Z, day: 8, dayOfWeek: 5, isToday: false, selection: null, state: 'valid', inMonth: false }, { date: 2021-10-08T16:00:00.000Z, day: 9, dayOfWeek: 6, isToday: false, selection: null, state: 'valid', inMonth: false }, { date: 2021-10-09T16:00:00.000Z, day: 10, dayOfWeek: 0, isToday: false, selection: null, state: 'valid', inMonth: false } ], now: 2021-09-05T16:00:00.000Z } ```Note that the
monthinCalendarDateis 1-based and that,dayis what is called 'date' in the Date APi.
type CalendarDate =
| { year: number; month: number; day?: number }
| string
| number
| Date;
interface CalendarEvent<T = any> {
label: string,
date: Date
value?: T
}
type CalendarBuilderOptions = {
/**
* The first day of the week
*
* Default: 0
*/
firstDay: number;
/**
* Add a fill week to the end even if not needed. This is useful to avoid
* "flicker" when some months are 4-6 weeks only.
*
* Default: true
*/
fillWeek: boolean;
/**
* Mark dates before this time invalid (excluding)
*
* E.g. after = 2021-05-29, then first valid date is 2021-05-30.
*/
after: CalendarDate;
/**
* Mark dates after this time invalid (excluding)
*
* E.g. before = 2021-05-29, then last valid date is 2021-05-28.
*/
before: CalendarDate;
/**
* Mark days in this range as selected. The selection state of the day may
* vary if it is the first, last, middle, or only day in the selection.
*/
selection: [CalendarDate, CalendarDate];
/**
* Optionally pas in date for when is 'now'.
*/
now: CalendarDate;
/**
* Disable days of the week
*/
disableDaysOfWeek: number[];
/**
* Disable specific days
*/
disableDays: CalendarDate[];
/**
* Events to "bucket". Will distribute an array of events into the
event-bucket on each of the calendar days.
*/
events: CalendarEvent[];
};






