@react-stately/calendar
Advanced tools
Comparing version 3.0.0-nightly.1469 to 3.0.0-nightly.1474
@@ -150,3 +150,5 @@ var $hEzMm$internationalizeddate = require("@internationalized/date"); | ||
} | ||
if (focusedDate.compare(startDate) < 0) setStartDate($4301262d71f567b9$export$530edbfc915b2b04(focusedDate, visibleDuration, locale, minValue, maxValue)); | ||
if ($4301262d71f567b9$export$eac50920cf2fd59a(focusedDate, minValue, maxValue)) // If the focused date was moved to an invalid value, it can't be focused, so constrain it. | ||
setFocusedDate($4301262d71f567b9$export$4f5203c0d889109e(focusedDate, minValue, maxValue)); | ||
else if (focusedDate.compare(startDate) < 0) setStartDate($4301262d71f567b9$export$530edbfc915b2b04(focusedDate, visibleDuration, locale, minValue, maxValue)); | ||
else if (focusedDate.compare(startDate.add(visibleDuration)) >= 0) setStartDate($4301262d71f567b9$export$144a00ba6044eb9(focusedDate, visibleDuration, locale, minValue, maxValue)); | ||
@@ -207,9 +209,9 @@ // Sets focus to a specific cell date | ||
let start = startDate.add(visibleDuration); | ||
setFocusedDate($4301262d71f567b9$export$4f5203c0d889109e(focusedDate.add(visibleDuration), minValue, maxValue)); | ||
setStartDate($4301262d71f567b9$export$5bb865b12696a77d(focusedDate, start, visibleDuration, locale, minValue, maxValue)); | ||
setFocusedDate($4301262d71f567b9$export$4f5203c0d889109e(focusedDate.add(visibleDuration), minValue, maxValue)); | ||
}, | ||
focusPreviousPage () { | ||
let start = startDate.subtract(visibleDuration); | ||
setFocusedDate($4301262d71f567b9$export$4f5203c0d889109e(focusedDate.subtract(visibleDuration), minValue, maxValue)); | ||
setStartDate($4301262d71f567b9$export$5bb865b12696a77d(focusedDate, start, visibleDuration, locale, minValue, maxValue)); | ||
setFocusedDate($4301262d71f567b9$export$4f5203c0d889109e(focusedDate.subtract(visibleDuration), minValue, maxValue)); | ||
}, | ||
@@ -252,3 +254,3 @@ focusPageStart () { | ||
isSelected (date) { | ||
return calendarDateValue != null && $hEzMm$internationalizeddate.isSameDay(date, calendarDateValue) && !this.isCellDisabled(date); | ||
return calendarDateValue != null && $hEzMm$internationalizeddate.isSameDay(date, calendarDateValue) && !this.isCellDisabled(date) && !this.isCellUnavailable(date); | ||
}, | ||
@@ -259,6 +261,9 @@ isCellFocused (date) { | ||
isCellDisabled (date) { | ||
return props.isDisabled || date.compare(startDate) < 0 || date.compare(endDate) > 0 || $4301262d71f567b9$export$eac50920cf2fd59a(date, minValue, maxValue) || props.isDateDisabled && props.isDateDisabled(date); | ||
return props.isDisabled || date.compare(startDate) < 0 || date.compare(endDate) > 0 || this.isInvalid(date, minValue, maxValue); | ||
}, | ||
isCellUnavailable (date) { | ||
return props.isDateUnavailable && props.isDateUnavailable(date); | ||
}, | ||
isPreviousVisibleRangeInvalid () { | ||
return $4301262d71f567b9$export$eac50920cf2fd59a(startDate.subtract({ | ||
return this.isInvalid(startDate.subtract({ | ||
days: 1 | ||
@@ -268,3 +273,3 @@ }), minValue, maxValue); | ||
isNextVisibleRangeInvalid () { | ||
return $4301262d71f567b9$export$eac50920cf2fd59a(endDate.add({ | ||
return this.isInvalid(endDate.add({ | ||
days: 1 | ||
@@ -289,4 +294,4 @@ }), minValue, maxValue); | ||
} , minValue: minValue , maxValue: maxValue , ...calendarProps } = props; | ||
let [value, setValue] = $hEzMm$reactstatelyutils.useControlledState(valueProp, defaultValue, onChange); | ||
let [anchorDate, setAnchorDate] = $hEzMm$react.useState(null); | ||
let [value, setValue] = $hEzMm$reactstatelyutils.useControlledState(valueProp, defaultValue || null, onChange); | ||
let [anchorDate, setAnchorDateState] = $hEzMm$react.useState(null); | ||
let alignment = 'center'; | ||
@@ -300,2 +305,17 @@ if (value && value.start && value.end) { | ||
} | ||
// Available range must be stored in a ref so we have access to the updated version immediately in `isInvalid`. | ||
let availableRangeRef = $hEzMm$react.useRef(null); | ||
let [availableRange, setAvailableRange] = $hEzMm$react.useState(null); | ||
let min = $hEzMm$react.useMemo(()=>{ | ||
return $hEzMm$internationalizeddate.maxDate(minValue, availableRange === null || availableRange === void 0 ? void 0 : availableRange.start); | ||
}, [ | ||
minValue, | ||
availableRange | ||
]); | ||
let max = $hEzMm$react.useMemo(()=>{ | ||
return $hEzMm$internationalizeddate.minDate(maxValue, availableRange === null || availableRange === void 0 ? void 0 : availableRange.end); | ||
}, [ | ||
maxValue, | ||
availableRange | ||
]); | ||
let calendar = $6adad0c8536fc209$export$6d095e787d2b5e1f({ | ||
@@ -307,6 +327,33 @@ ...calendarProps, | ||
visibleDuration: visibleDuration, | ||
minValue: minValue, | ||
maxValue: maxValue, | ||
minValue: min, | ||
maxValue: max, | ||
selectionAlignment: alignment | ||
}); | ||
let updateAvailableRange = (date)=>{ | ||
if (date && props.isDateUnavailable && !props.allowsNonContiguousRanges) { | ||
availableRangeRef.current = { | ||
start: $e49f7b861e5e8049$var$nextUnavailableDate(date, calendar, -1), | ||
end: $e49f7b861e5e8049$var$nextUnavailableDate(date, calendar, 1) | ||
}; | ||
setAvailableRange(availableRangeRef.current); | ||
} else { | ||
availableRangeRef.current = null; | ||
setAvailableRange(null); | ||
} | ||
}; | ||
// If the visible range changes, we need to update the available range. | ||
let lastVisibleRange = $hEzMm$react.useRef(calendar.visibleRange); | ||
if (!$hEzMm$internationalizeddate.isEqualDay(calendar.visibleRange.start, lastVisibleRange.current.start) || !$hEzMm$internationalizeddate.isEqualDay(calendar.visibleRange.end, lastVisibleRange.current.end)) { | ||
updateAvailableRange(anchorDate); | ||
lastVisibleRange.current = calendar.visibleRange; | ||
} | ||
let setAnchorDate = (date)=>{ | ||
if (date) { | ||
setAnchorDateState(date); | ||
updateAvailableRange(date); | ||
} else { | ||
setAnchorDateState(null); | ||
updateAvailableRange(null); | ||
} | ||
}; | ||
let highlightedRange = anchorDate ? $e49f7b861e5e8049$var$makeRange(anchorDate, calendar.focusedDate) : value && $e49f7b861e5e8049$var$makeRange(value.start, value.end); | ||
@@ -341,4 +388,8 @@ let selectDate = (date)=>{ | ||
isSelected (date) { | ||
return highlightedRange && date.compare(highlightedRange.start) >= 0 && date.compare(highlightedRange.end) <= 0 && !calendar.isCellDisabled(date); | ||
return highlightedRange && date.compare(highlightedRange.start) >= 0 && date.compare(highlightedRange.end) <= 0 && !calendar.isCellDisabled(date) && !calendar.isCellUnavailable(date); | ||
}, | ||
isInvalid (date) { | ||
var ref, ref1; | ||
return calendar.isInvalid(date) || $4301262d71f567b9$export$eac50920cf2fd59a(date, (ref = availableRangeRef.current) === null || ref === void 0 ? void 0 : ref.start, (ref1 = availableRangeRef.current) === null || ref1 === void 0 ? void 0 : ref1.end); | ||
}, | ||
isDragging: isDragging, | ||
@@ -367,2 +418,14 @@ setDragging: setDragging | ||
} | ||
function $e49f7b861e5e8049$var$nextUnavailableDate(anchorDate, state, dir) { | ||
let nextDate = anchorDate.add({ | ||
days: dir | ||
}); | ||
while((dir < 0 ? nextDate.compare(state.visibleRange.start) >= 0 : nextDate.compare(state.visibleRange.end) <= 0) && !state.isCellUnavailable(nextDate))nextDate = nextDate.add({ | ||
days: dir | ||
}); | ||
if (state.isCellUnavailable(nextDate)) return nextDate.add({ | ||
days: -dir | ||
}); | ||
return null; | ||
} | ||
@@ -369,0 +432,0 @@ |
@@ -1,2 +0,2 @@ | ||
import {toCalendar as $keQhS$toCalendar, toCalendarDate as $keQhS$toCalendarDate, today as $keQhS$today, GregorianCalendar as $keQhS$GregorianCalendar, isSameDay as $keQhS$isSameDay, startOfYear as $keQhS$startOfYear, startOfMonth as $keQhS$startOfMonth, startOfWeek as $keQhS$startOfWeek, maxDate as $keQhS$maxDate, minDate as $keQhS$minDate} from "@internationalized/date"; | ||
import {toCalendar as $keQhS$toCalendar, toCalendarDate as $keQhS$toCalendarDate, today as $keQhS$today, GregorianCalendar as $keQhS$GregorianCalendar, isSameDay as $keQhS$isSameDay, startOfYear as $keQhS$startOfYear, startOfMonth as $keQhS$startOfMonth, startOfWeek as $keQhS$startOfWeek, maxDate as $keQhS$maxDate, minDate as $keQhS$minDate, isEqualDay as $keQhS$isEqualDay} from "@internationalized/date"; | ||
import {useControlledState as $keQhS$useControlledState} from "@react-stately/utils"; | ||
@@ -134,3 +134,5 @@ import {useDateFormatter as $keQhS$useDateFormatter} from "@react-aria/i18n"; | ||
} | ||
if (focusedDate.compare(startDate) < 0) setStartDate($f62d864046160412$export$530edbfc915b2b04(focusedDate, visibleDuration, locale, minValue, maxValue)); | ||
if ($f62d864046160412$export$eac50920cf2fd59a(focusedDate, minValue, maxValue)) // If the focused date was moved to an invalid value, it can't be focused, so constrain it. | ||
setFocusedDate($f62d864046160412$export$4f5203c0d889109e(focusedDate, minValue, maxValue)); | ||
else if (focusedDate.compare(startDate) < 0) setStartDate($f62d864046160412$export$530edbfc915b2b04(focusedDate, visibleDuration, locale, minValue, maxValue)); | ||
else if (focusedDate.compare(startDate.add(visibleDuration)) >= 0) setStartDate($f62d864046160412$export$144a00ba6044eb9(focusedDate, visibleDuration, locale, minValue, maxValue)); | ||
@@ -191,9 +193,9 @@ // Sets focus to a specific cell date | ||
let start = startDate.add(visibleDuration); | ||
setFocusedDate($f62d864046160412$export$4f5203c0d889109e(focusedDate.add(visibleDuration), minValue, maxValue)); | ||
setStartDate($f62d864046160412$export$5bb865b12696a77d(focusedDate, start, visibleDuration, locale, minValue, maxValue)); | ||
setFocusedDate($f62d864046160412$export$4f5203c0d889109e(focusedDate.add(visibleDuration), minValue, maxValue)); | ||
}, | ||
focusPreviousPage () { | ||
let start = startDate.subtract(visibleDuration); | ||
setFocusedDate($f62d864046160412$export$4f5203c0d889109e(focusedDate.subtract(visibleDuration), minValue, maxValue)); | ||
setStartDate($f62d864046160412$export$5bb865b12696a77d(focusedDate, start, visibleDuration, locale, minValue, maxValue)); | ||
setFocusedDate($f62d864046160412$export$4f5203c0d889109e(focusedDate.subtract(visibleDuration), minValue, maxValue)); | ||
}, | ||
@@ -236,3 +238,3 @@ focusPageStart () { | ||
isSelected (date) { | ||
return calendarDateValue != null && $keQhS$isSameDay(date, calendarDateValue) && !this.isCellDisabled(date); | ||
return calendarDateValue != null && $keQhS$isSameDay(date, calendarDateValue) && !this.isCellDisabled(date) && !this.isCellUnavailable(date); | ||
}, | ||
@@ -243,6 +245,9 @@ isCellFocused (date) { | ||
isCellDisabled (date) { | ||
return props.isDisabled || date.compare(startDate) < 0 || date.compare(endDate) > 0 || $f62d864046160412$export$eac50920cf2fd59a(date, minValue, maxValue) || props.isDateDisabled && props.isDateDisabled(date); | ||
return props.isDisabled || date.compare(startDate) < 0 || date.compare(endDate) > 0 || this.isInvalid(date, minValue, maxValue); | ||
}, | ||
isCellUnavailable (date) { | ||
return props.isDateUnavailable && props.isDateUnavailable(date); | ||
}, | ||
isPreviousVisibleRangeInvalid () { | ||
return $f62d864046160412$export$eac50920cf2fd59a(startDate.subtract({ | ||
return this.isInvalid(startDate.subtract({ | ||
days: 1 | ||
@@ -252,3 +257,3 @@ }), minValue, maxValue); | ||
isNextVisibleRangeInvalid () { | ||
return $f62d864046160412$export$eac50920cf2fd59a(endDate.add({ | ||
return this.isInvalid(endDate.add({ | ||
days: 1 | ||
@@ -273,4 +278,4 @@ }), minValue, maxValue); | ||
} , minValue: minValue , maxValue: maxValue , ...calendarProps } = props; | ||
let [value, setValue] = $keQhS$useControlledState(valueProp, defaultValue, onChange); | ||
let [anchorDate, setAnchorDate] = $keQhS$useState(null); | ||
let [value, setValue] = $keQhS$useControlledState(valueProp, defaultValue || null, onChange); | ||
let [anchorDate, setAnchorDateState] = $keQhS$useState(null); | ||
let alignment = 'center'; | ||
@@ -284,2 +289,17 @@ if (value && value.start && value.end) { | ||
} | ||
// Available range must be stored in a ref so we have access to the updated version immediately in `isInvalid`. | ||
let availableRangeRef = $keQhS$useRef(null); | ||
let [availableRange, setAvailableRange] = $keQhS$useState(null); | ||
let min = $keQhS$useMemo(()=>{ | ||
return $keQhS$maxDate(minValue, availableRange === null || availableRange === void 0 ? void 0 : availableRange.start); | ||
}, [ | ||
minValue, | ||
availableRange | ||
]); | ||
let max = $keQhS$useMemo(()=>{ | ||
return $keQhS$minDate(maxValue, availableRange === null || availableRange === void 0 ? void 0 : availableRange.end); | ||
}, [ | ||
maxValue, | ||
availableRange | ||
]); | ||
let calendar = $131cf43a05231e1e$export$6d095e787d2b5e1f({ | ||
@@ -291,6 +311,33 @@ ...calendarProps, | ||
visibleDuration: visibleDuration, | ||
minValue: minValue, | ||
maxValue: maxValue, | ||
minValue: min, | ||
maxValue: max, | ||
selectionAlignment: alignment | ||
}); | ||
let updateAvailableRange = (date)=>{ | ||
if (date && props.isDateUnavailable && !props.allowsNonContiguousRanges) { | ||
availableRangeRef.current = { | ||
start: $9a36b6ba2fb1a7c5$var$nextUnavailableDate(date, calendar, -1), | ||
end: $9a36b6ba2fb1a7c5$var$nextUnavailableDate(date, calendar, 1) | ||
}; | ||
setAvailableRange(availableRangeRef.current); | ||
} else { | ||
availableRangeRef.current = null; | ||
setAvailableRange(null); | ||
} | ||
}; | ||
// If the visible range changes, we need to update the available range. | ||
let lastVisibleRange = $keQhS$useRef(calendar.visibleRange); | ||
if (!$keQhS$isEqualDay(calendar.visibleRange.start, lastVisibleRange.current.start) || !$keQhS$isEqualDay(calendar.visibleRange.end, lastVisibleRange.current.end)) { | ||
updateAvailableRange(anchorDate); | ||
lastVisibleRange.current = calendar.visibleRange; | ||
} | ||
let setAnchorDate = (date)=>{ | ||
if (date) { | ||
setAnchorDateState(date); | ||
updateAvailableRange(date); | ||
} else { | ||
setAnchorDateState(null); | ||
updateAvailableRange(null); | ||
} | ||
}; | ||
let highlightedRange = anchorDate ? $9a36b6ba2fb1a7c5$var$makeRange(anchorDate, calendar.focusedDate) : value && $9a36b6ba2fb1a7c5$var$makeRange(value.start, value.end); | ||
@@ -325,4 +372,8 @@ let selectDate = (date)=>{ | ||
isSelected (date) { | ||
return highlightedRange && date.compare(highlightedRange.start) >= 0 && date.compare(highlightedRange.end) <= 0 && !calendar.isCellDisabled(date); | ||
return highlightedRange && date.compare(highlightedRange.start) >= 0 && date.compare(highlightedRange.end) <= 0 && !calendar.isCellDisabled(date) && !calendar.isCellUnavailable(date); | ||
}, | ||
isInvalid (date) { | ||
var ref, ref1; | ||
return calendar.isInvalid(date) || $f62d864046160412$export$eac50920cf2fd59a(date, (ref = availableRangeRef.current) === null || ref === void 0 ? void 0 : ref.start, (ref1 = availableRangeRef.current) === null || ref1 === void 0 ? void 0 : ref1.end); | ||
}, | ||
isDragging: isDragging, | ||
@@ -351,2 +402,14 @@ setDragging: setDragging | ||
} | ||
function $9a36b6ba2fb1a7c5$var$nextUnavailableDate(anchorDate, state, dir) { | ||
let nextDate = anchorDate.add({ | ||
days: dir | ||
}); | ||
while((dir < 0 ? nextDate.compare(state.visibleRange.start) >= 0 : nextDate.compare(state.visibleRange.end) <= 0) && !state.isCellUnavailable(nextDate))nextDate = nextDate.add({ | ||
days: dir | ||
}); | ||
if (state.isCellUnavailable(nextDate)) return nextDate.add({ | ||
days: -dir | ||
}); | ||
return null; | ||
} | ||
@@ -353,0 +416,0 @@ |
@@ -61,2 +61,4 @@ import { CalendarDate, Calendar, DateDuration } from "@internationalized/date"; | ||
isCellDisabled(date: CalendarDate): boolean; | ||
/** Returns whether the given date is unavailable according to the `isDateUnavailable` prop. */ | ||
isCellUnavailable(date: CalendarDate): boolean; | ||
/** Returns whether the previous visible date range is allowed to be selected according to the `minValue` prop. */ | ||
@@ -63,0 +65,0 @@ isPreviousVisibleRangeInvalid(): boolean; |
{ | ||
"name": "@react-stately/calendar", | ||
"version": "3.0.0-nightly.1469+2fabc1ac0", | ||
"version": "3.0.0-nightly.1474+fe4148bea", | ||
"description": "Spectrum UI components in React", | ||
@@ -21,8 +21,8 @@ "license": "Apache-2.0", | ||
"@babel/runtime": "^7.6.2", | ||
"@internationalized/date": "3.0.0-nightly.3168+2fabc1ac0", | ||
"@react-aria/i18n": "3.0.0-nightly.1469+2fabc1ac0", | ||
"@react-stately/utils": "3.0.0-nightly.1469+2fabc1ac0", | ||
"@react-types/calendar": "3.0.0-nightly.3168+2fabc1ac0", | ||
"@react-types/datepicker": "3.0.0-nightly.3168+2fabc1ac0", | ||
"@react-types/shared": "3.0.0-nightly.1469+2fabc1ac0", | ||
"@internationalized/date": "3.0.0-nightly.3173+fe4148bea", | ||
"@react-aria/i18n": "3.0.0-nightly.1474+fe4148bea", | ||
"@react-stately/utils": "3.0.0-nightly.1474+fe4148bea", | ||
"@react-types/calendar": "3.0.0-nightly.3173+fe4148bea", | ||
"@react-types/datepicker": "3.0.0-nightly.3173+fe4148bea", | ||
"@react-types/shared": "3.0.0-nightly.1474+fe4148bea", | ||
"date-fns": "^1.30.1" | ||
@@ -36,3 +36,3 @@ }, | ||
}, | ||
"gitHead": "2fabc1ac07aa6fd75e7111e571e27787d8a44314" | ||
"gitHead": "fe4148beaf7f63a1ea486aecc139747a666f8c3a" | ||
} |
@@ -74,2 +74,4 @@ /* | ||
isCellDisabled(date: CalendarDate): boolean, | ||
/** Returns whether the given date is unavailable according to the `isDateUnavailable` prop. */ | ||
isCellUnavailable(date: CalendarDate): boolean, | ||
/** Returns whether the previous visible date range is allowed to be selected according to the `minValue` prop. */ | ||
@@ -76,0 +78,0 @@ isPreviousVisibleRangeInvalid(): boolean, |
@@ -93,3 +93,6 @@ /* | ||
if (focusedDate.compare(startDate) < 0) { | ||
if (isInvalid(focusedDate, minValue, maxValue)) { | ||
// If the focused date was moved to an invalid value, it can't be focused, so constrain it. | ||
setFocusedDate(constrainValue(focusedDate, minValue, maxValue)); | ||
} else if (focusedDate.compare(startDate) < 0) { | ||
setStartDate(alignEnd(focusedDate, visibleDuration, locale, minValue, maxValue)); | ||
@@ -158,9 +161,9 @@ } else if (focusedDate.compare(startDate.add(visibleDuration)) >= 0) { | ||
let start = startDate.add(visibleDuration); | ||
setFocusedDate(constrainValue(focusedDate.add(visibleDuration), minValue, maxValue)); | ||
setStartDate(constrainStart(focusedDate, start, visibleDuration, locale, minValue, maxValue)); | ||
setFocusedDate(constrainValue(focusedDate.add(visibleDuration), minValue, maxValue)); | ||
}, | ||
focusPreviousPage() { | ||
let start = startDate.subtract(visibleDuration); | ||
setFocusedDate(constrainValue(focusedDate.subtract(visibleDuration), minValue, maxValue)); | ||
setStartDate(constrainStart(focusedDate, start, visibleDuration, locale, minValue, maxValue)); | ||
setFocusedDate(constrainValue(focusedDate.subtract(visibleDuration), minValue, maxValue)); | ||
}, | ||
@@ -203,3 +206,3 @@ focusPageStart() { | ||
isSelected(date) { | ||
return calendarDateValue != null && isSameDay(date, calendarDateValue) && !this.isCellDisabled(date); | ||
return calendarDateValue != null && isSameDay(date, calendarDateValue) && !this.isCellDisabled(date) && !this.isCellUnavailable(date); | ||
}, | ||
@@ -210,11 +213,14 @@ isCellFocused(date) { | ||
isCellDisabled(date) { | ||
return props.isDisabled || date.compare(startDate) < 0 || date.compare(endDate) > 0 || isInvalid(date, minValue, maxValue) || (props.isDateDisabled && props.isDateDisabled(date)); | ||
return props.isDisabled || date.compare(startDate) < 0 || date.compare(endDate) > 0 || this.isInvalid(date, minValue, maxValue); | ||
}, | ||
isCellUnavailable(date) { | ||
return props.isDateUnavailable && props.isDateUnavailable(date); | ||
}, | ||
isPreviousVisibleRangeInvalid() { | ||
return isInvalid(startDate.subtract({days: 1}), minValue, maxValue); | ||
return this.isInvalid(startDate.subtract({days: 1}), minValue, maxValue); | ||
}, | ||
isNextVisibleRangeInvalid() { | ||
return isInvalid(endDate.add({days: 1}), minValue, maxValue); | ||
return this.isInvalid(endDate.add({days: 1}), minValue, maxValue); | ||
} | ||
}; | ||
} |
@@ -13,11 +13,11 @@ /* | ||
import {alignCenter} from './utils'; | ||
import {Calendar, CalendarDate, DateDuration, GregorianCalendar, toCalendar, toCalendarDate} from '@internationalized/date'; | ||
import {alignCenter, isInvalid} from './utils'; | ||
import {Calendar, CalendarDate, DateDuration, GregorianCalendar, isEqualDay, maxDate, minDate, toCalendar, toCalendarDate} from '@internationalized/date'; | ||
import {CalendarState, RangeCalendarState} from './types'; | ||
import {DateRange, DateValue} from '@react-types/calendar'; | ||
import {RangeCalendarProps} from '@react-types/calendar'; | ||
import {RangeCalendarState} from './types'; | ||
import {RangeValue} from '@react-types/shared'; | ||
import {useCalendarState} from './useCalendarState'; | ||
import {useControlledState} from '@react-stately/utils'; | ||
import {useState} from 'react'; | ||
import {useMemo, useRef, useState} from 'react'; | ||
@@ -34,7 +34,7 @@ interface RangeCalendarStateOptions<T extends DateValue> extends RangeCalendarProps<T> { | ||
valueProp, | ||
defaultValue, | ||
defaultValue || null, | ||
onChange | ||
); | ||
let [anchorDate, setAnchorDate] = useState(null); | ||
let [anchorDate, setAnchorDateState] = useState(null); | ||
let alignment: 'center' | 'start' = 'center'; | ||
@@ -50,2 +50,8 @@ if (value && value.start && value.end) { | ||
// Available range must be stored in a ref so we have access to the updated version immediately in `isInvalid`. | ||
let availableRangeRef = useRef<RangeValue<DateValue>>(null); | ||
let [availableRange, setAvailableRange] = useState<RangeValue<DateValue>>(null); | ||
let min = useMemo(() => maxDate(minValue, availableRange?.start), [minValue, availableRange]); | ||
let max = useMemo(() => minDate(maxValue, availableRange?.end), [maxValue, availableRange]); | ||
let calendar = useCalendarState({ | ||
@@ -57,7 +63,37 @@ ...calendarProps, | ||
visibleDuration, | ||
minValue, | ||
maxValue, | ||
minValue: min, | ||
maxValue: max, | ||
selectionAlignment: alignment | ||
}); | ||
let updateAvailableRange = (date) => { | ||
if (date && props.isDateUnavailable && !props.allowsNonContiguousRanges) { | ||
availableRangeRef.current = { | ||
start: nextUnavailableDate(date, calendar, -1), | ||
end: nextUnavailableDate(date, calendar, 1) | ||
}; | ||
setAvailableRange(availableRangeRef.current); | ||
} else { | ||
availableRangeRef.current = null; | ||
setAvailableRange(null); | ||
} | ||
}; | ||
// If the visible range changes, we need to update the available range. | ||
let lastVisibleRange = useRef(calendar.visibleRange); | ||
if (!isEqualDay(calendar.visibleRange.start, lastVisibleRange.current.start) || !isEqualDay(calendar.visibleRange.end, lastVisibleRange.current.end)) { | ||
updateAvailableRange(anchorDate); | ||
lastVisibleRange.current = calendar.visibleRange; | ||
} | ||
let setAnchorDate = (date: CalendarDate) => { | ||
if (date) { | ||
setAnchorDateState(date); | ||
updateAvailableRange(date); | ||
} else { | ||
setAnchorDateState(null); | ||
updateAvailableRange(null); | ||
} | ||
}; | ||
let highlightedRange = anchorDate ? makeRange(anchorDate, calendar.focusedDate) : value && makeRange(value.start, value.end); | ||
@@ -100,4 +136,7 @@ let selectDate = (date: CalendarDate) => { | ||
isSelected(date) { | ||
return highlightedRange && date.compare(highlightedRange.start) >= 0 && date.compare(highlightedRange.end) <= 0 && !calendar.isCellDisabled(date); | ||
return highlightedRange && date.compare(highlightedRange.start) >= 0 && date.compare(highlightedRange.end) <= 0 && !calendar.isCellDisabled(date) && !calendar.isCellUnavailable(date); | ||
}, | ||
isInvalid(date) { | ||
return calendar.isInvalid(date) || isInvalid(date, availableRangeRef.current?.start, availableRangeRef.current?.end); | ||
}, | ||
isDragging, | ||
@@ -132,1 +171,17 @@ setDragging | ||
} | ||
function nextUnavailableDate(anchorDate: CalendarDate, state: CalendarState, dir: number) { | ||
let nextDate = anchorDate.add({days: dir}); | ||
while ( | ||
(dir < 0 ? nextDate.compare(state.visibleRange.start) >= 0 : nextDate.compare(state.visibleRange.end) <= 0) && | ||
!state.isCellUnavailable(nextDate) | ||
) { | ||
nextDate = nextDate.add({days: dir}); | ||
} | ||
if (state.isCellUnavailable(nextDate)) { | ||
return nextDate.add({days: -dir}); | ||
} | ||
return null; | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
163376
1476