File size: 4,467 Bytes
bc20498 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
import { chunk, isHTMLElement } from '../index.js';
import { startOfMonth, endOfMonth } from '@internationalized/date';
import { getDaysInMonth, getLastFirstDayOfWeek, getNextLastDayOfWeek, parseStringToDateValue, } from './index.js';
import { get } from 'svelte/store';
/**
* Checks if a given node is a calendar cell element.
*
* @param node - The node to check.
*/
export function isCalendarCell(node) {
if (!isHTMLElement(node))
return false;
if (!node.hasAttribute('data-melt-calendar-cell'))
return false;
return true;
}
/**
* Retrieves an array of date values representing the days between
* the provided start and end dates.
*/
export function getDaysBetween(start, end) {
const days = [];
let dCurrent = start.add({ days: 1 });
const dEnd = end;
while (dCurrent.compare(dEnd) < 0) {
days.push(dCurrent);
dCurrent = dCurrent.add({ days: 1 });
}
return days;
}
/**
* Creates a calendar month object.
*
* @remarks
* Given a date, this function returns an object containing
* the necessary values to render a calendar month, including
* the month's date (the first day of that month), which can be
* used to render the name of the month, an array of all dates
* in that month, and an array of weeks. Each week is an array
* of dates, useful for rendering an accessible calendar grid
* using a loop and table elements.
*
*/
function createMonth(props) {
const { dateObj, weekStartsOn, fixedWeeks, locale } = props;
const daysInMonth = getDaysInMonth(dateObj);
const datesArray = Array.from({ length: daysInMonth }, (_, i) => dateObj.set({ day: i + 1 }));
const firstDayOfMonth = startOfMonth(dateObj);
const lastDayOfMonth = endOfMonth(dateObj);
const lastSunday = getLastFirstDayOfWeek(firstDayOfMonth, weekStartsOn, locale);
const nextSaturday = getNextLastDayOfWeek(lastDayOfMonth, weekStartsOn, locale);
const lastMonthDays = getDaysBetween(lastSunday.subtract({ days: 1 }), firstDayOfMonth);
const nextMonthDays = getDaysBetween(lastDayOfMonth, nextSaturday.add({ days: 1 }));
const totalDays = lastMonthDays.length + datesArray.length + nextMonthDays.length;
if (fixedWeeks && totalDays < 42) {
const extraDays = 42 - totalDays;
let startFrom = nextMonthDays[nextMonthDays.length - 1];
if (!startFrom) {
startFrom = dateObj.add({ months: 1 }).set({ day: 1 });
}
const extraDaysArray = Array.from({ length: extraDays }, (_, i) => {
const incr = i + 1;
return startFrom.add({ days: incr });
});
nextMonthDays.push(...extraDaysArray);
}
const allDays = lastMonthDays.concat(datesArray, nextMonthDays);
const weeks = chunk(allDays, 7);
return {
value: dateObj,
dates: allDays,
weeks,
};
}
export function createMonths(props) {
const { numberOfMonths, dateObj, ...monthProps } = props;
const months = [];
if (!numberOfMonths || numberOfMonths === 1) {
months.push(createMonth({
...monthProps,
dateObj,
}));
return months;
}
months.push(createMonth({
...monthProps,
dateObj,
}));
// Create all the months, starting with the current month
for (let i = 1; i < numberOfMonths; i++) {
const nextMonth = dateObj.add({ months: i });
months.push(createMonth({
...monthProps,
dateObj: nextMonth,
}));
}
return months;
}
export function getSelectableCells(calendarId) {
const node = document.getElementById(calendarId);
if (!node)
return [];
const selectableSelector = `[data-melt-calendar-cell]:not([data-disabled]):not([data-outside-visible-months])`;
return Array.from(node.querySelectorAll(selectableSelector)).filter((el) => isHTMLElement(el));
}
/**
* A helper function to extract the date from the `data-value`
* attribute of a date cell and set it as the placeholder value.
*
* Shared between the calendar and range calendar builders.
*
* @param node - The node to extract the date from.
* @param placeholder - The placeholder value store which will be set to the extracted date.
*/
export function setPlaceholderToNodeValue(node, placeholder) {
const cellValue = node.getAttribute('data-value');
if (!cellValue)
return;
placeholder.set(parseStringToDateValue(cellValue, get(placeholder)));
}
|