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)));
}