File size: 3,948 Bytes
cf86710
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
122
123
124
125
126
127
128
129
130
131
132
133
import type { CalendarDay, DateLib } from "../classes/index.js";
import type { DayPickerProps, Modifiers } from "../types/index.js";
import { DayFlag } from "../UI.js";
import { dateMatchModifiers } from "../utils/dateMatchModifiers.js";

/**
 * Creates a function to retrieve the modifiers for a given day.
 *
 * This function calculates both internal and custom modifiers for each day
 * based on the provided calendar days and DayPicker props.
 *
 * @private
 * @param days The array of `CalendarDay` objects to process.
 * @param props The DayPicker props, including modifiers and configuration
 *   options.
 * @param dateLib The date library to use for date manipulation.
 * @returns A function that retrieves the modifiers for a given `CalendarDay`.
 */
export function createGetModifiers(
  days: CalendarDay[],
  props: DayPickerProps,
  navStart: Date | undefined,
  navEnd: Date | undefined,
  dateLib: DateLib,
) {
  const {
    disabled,
    hidden,
    modifiers,
    showOutsideDays,
    broadcastCalendar,
    today = dateLib.today(),
  } = props;

  const {
    isSameDay,
    isSameMonth,
    startOfMonth,
    isBefore,
    endOfMonth,
    isAfter,
  } = dateLib;

  const computedNavStart = navStart && startOfMonth(navStart);
  const computedNavEnd = navEnd && endOfMonth(navEnd);

  const internalModifiersMap: Record<DayFlag, CalendarDay[]> = {
    [DayFlag.focused]: [],
    [DayFlag.outside]: [],
    [DayFlag.disabled]: [],
    [DayFlag.hidden]: [],
    [DayFlag.today]: [],
  };

  const customModifiersMap: Record<string, CalendarDay[]> = {};

  for (const day of days) {
    const { date, displayMonth } = day;

    const isOutside = Boolean(displayMonth && !isSameMonth(date, displayMonth));

    const isBeforeNavStart = Boolean(
      computedNavStart && isBefore(date, computedNavStart),
    );

    const isAfterNavEnd = Boolean(
      computedNavEnd && isAfter(date, computedNavEnd),
    );

    const isDisabled = Boolean(
      disabled && dateMatchModifiers(date, disabled, dateLib),
    );

    const isHidden =
      Boolean(hidden && dateMatchModifiers(date, hidden, dateLib)) ||
      isBeforeNavStart ||
      isAfterNavEnd ||
      // Broadcast calendar will show outside days as default
      (!broadcastCalendar && !showOutsideDays && isOutside) ||
      (broadcastCalendar && showOutsideDays === false && isOutside);

    const isToday = isSameDay(date, today);

    if (isOutside) internalModifiersMap.outside.push(day);
    if (isDisabled) internalModifiersMap.disabled.push(day);
    if (isHidden) internalModifiersMap.hidden.push(day);
    if (isToday) internalModifiersMap.today.push(day);

    // Add custom modifiers
    if (modifiers) {
      Object.keys(modifiers).forEach((name) => {
        const modifierValue = modifiers?.[name];
        const isMatch = modifierValue
          ? dateMatchModifiers(date, modifierValue, dateLib)
          : false;
        if (!isMatch) return;
        if (customModifiersMap[name]) {
          customModifiersMap[name].push(day);
        } else {
          customModifiersMap[name] = [day];
        }
      });
    }
  }

  return (day: CalendarDay): Modifiers => {
    // Initialize all the modifiers to false
    const dayFlags: Record<DayFlag, boolean> = {
      [DayFlag.focused]: false,
      [DayFlag.disabled]: false,
      [DayFlag.hidden]: false,
      [DayFlag.outside]: false,
      [DayFlag.today]: false,
    };
    const customModifiers: Modifiers = {};

    // Find the modifiers for the given day
    for (const name in internalModifiersMap) {
      const days = internalModifiersMap[name as DayFlag];
      dayFlags[name as DayFlag] = days.some((d) => d === day);
    }
    for (const name in customModifiersMap) {
      customModifiers[name] = customModifiersMap[name].some((d) => d === day);
    }

    return {
      ...dayFlags,
      // custom modifiers should override all the previous ones
      ...customModifiers,
    };
  };
}