Block calendar swiping outside possible range
This commit is contained in:
@@ -54,7 +54,7 @@ export function createSwipePopoverCalendarHTML({
|
||||
monthLabelTextClass = 'text-[10px] font-semibold leading-none tabular-nums whitespace-nowrap',
|
||||
}) {
|
||||
const weekdayHeader = `
|
||||
<div class="grid grid-cols-7 gap-1.5 text-center text-[8px] font-medium uppercase tracking-wide mb-1 leading-none" style="color:rgb(var(--text-dim-rgb));">
|
||||
<div class="grid grid-cols-7 gap-1.5 text-center text-[8px] font-medium uppercase tracking-wide mb-1.5 leading-none" style="color:rgb(var(--text-dim-rgb));">
|
||||
${weekdays.map((d) => `<div>${d}</div>`).join('')}
|
||||
</div>
|
||||
`;
|
||||
@@ -75,7 +75,7 @@ export function createSwipePopoverCalendarHTML({
|
||||
|
||||
return `
|
||||
<div class="pb-3 px-3 flex items-center justify-end gap-3">
|
||||
<div class="flex h-[2.05rem] min-w-0 max-w-[min(100%,20rem)] items-center justify-center rounded-full border" style="background:rgb(var(--app-bg-rgb)); border-color:rgb(var(--card-raised-rgb));">
|
||||
<div class="flex h-[2.05rem] min-w-0 max-w-[min(100%,20rem)] items-center justify-center rounded-full border" style="background:transparent; border-color:rgb(var(--border-input-rgb));">
|
||||
<span id="${idPrefix}-month-label" class="h-full shrink-0 inline-flex min-w-[5.75rem] max-w-[9rem] items-center justify-center px-3 ${monthLabelTextClass}" style="color:rgb(var(--text-body-soft-rgb));"></span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -111,6 +111,7 @@ export function initSwipePopoverCalendar({
|
||||
theme = DEFAULT_THEME,
|
||||
getMonthAnchor,
|
||||
setMonthAnchor,
|
||||
canNavigateToMonth,
|
||||
getSelectionKeys,
|
||||
onSelectionCommit,
|
||||
resolveDayState,
|
||||
@@ -188,6 +189,23 @@ export function initSwipePopoverCalendar({
|
||||
track.style.transform = `translate3d(${restOffset + dx}px, 0, 0)`;
|
||||
};
|
||||
|
||||
const getNavigationTarget = (monthDelta) => {
|
||||
const anchor = normalizeMonth(getMonthAnchor());
|
||||
return startOfMonth(new Date(anchor.getFullYear(), anchor.getMonth() + monthDelta, 1));
|
||||
};
|
||||
|
||||
const canNavigate = (monthDelta) => {
|
||||
if (typeof canNavigateToMonth !== 'function') return true;
|
||||
const anchor = normalizeMonth(getMonthAnchor());
|
||||
const target = getNavigationTarget(monthDelta);
|
||||
return canNavigateToMonth(target, { currentMonth: anchor, monthDelta }) !== false;
|
||||
};
|
||||
|
||||
const getAllowedDragDx = (dx) => {
|
||||
if (dx === 0) return 0;
|
||||
return canNavigate(dx > 0 ? -1 : 1) ? dx : 0;
|
||||
};
|
||||
|
||||
const getSelectedSet = (previewSelection = null) => {
|
||||
const raw = previewSelection ?? getSelectionKeys();
|
||||
if (Array.isArray(raw)) return new Set(raw);
|
||||
@@ -259,12 +277,16 @@ export function initSwipePopoverCalendar({
|
||||
};
|
||||
|
||||
const commitNavigation = (monthDelta) => {
|
||||
if (!canNavigate(monthDelta)) {
|
||||
setDragTranslate(0, ANIMATION_MS);
|
||||
setTimeout(() => syncGripVisibility(false), ANIMATION_MS + 20);
|
||||
return;
|
||||
}
|
||||
animatingNav = true;
|
||||
const targetDx = monthDelta < 0 ? panelWidth : -panelWidth;
|
||||
setDragTranslate(targetDx, ANIMATION_MS);
|
||||
setTimeout(() => {
|
||||
const anchor = normalizeMonth(getMonthAnchor());
|
||||
setMonthAnchor(startOfMonth(new Date(anchor.getFullYear(), anchor.getMonth() + monthDelta, 1)));
|
||||
setMonthAnchor(getNavigationTarget(monthDelta));
|
||||
render();
|
||||
resetTrackPosition();
|
||||
animatingNav = false;
|
||||
@@ -352,7 +374,7 @@ export function initSwipePopoverCalendar({
|
||||
axis = Math.abs(dx) >= Math.abs(dy) ? 'x' : 'y';
|
||||
if (axis === 'x') syncGripVisibility(true);
|
||||
}
|
||||
if (axis === 'x') setDragTranslate(dx, 0);
|
||||
if (axis === 'x') setDragTranslate(getAllowedDragDx(dx), 0);
|
||||
});
|
||||
|
||||
const endGesture = (e) => {
|
||||
@@ -360,7 +382,8 @@ export function initSwipePopoverCalendar({
|
||||
ptrId = null;
|
||||
if (!moved || axis !== 'x') return;
|
||||
const dx = e ? e.clientX - startX : 0;
|
||||
if (Math.abs(dx) >= SWIPE_THRESHOLD) commitNavigation(dx > 0 ? -1 : 1);
|
||||
const monthDelta = dx > 0 ? -1 : 1;
|
||||
if (Math.abs(dx) >= SWIPE_THRESHOLD && canNavigate(monthDelta)) commitNavigation(monthDelta);
|
||||
else {
|
||||
setDragTranslate(0, ANIMATION_MS);
|
||||
setTimeout(() => syncGripVisibility(false), ANIMATION_MS + 20);
|
||||
|
||||
@@ -313,6 +313,11 @@ function bindPantryCalendarInteractions() {
|
||||
if (nextAnchor.getTime() < minAnchor.getTime()) return;
|
||||
calendarMonthAnchor = nextAnchor;
|
||||
},
|
||||
canNavigateToMonth: (nextMonth) => {
|
||||
const nextAnchor = startOfMonth(nextMonth);
|
||||
const minAnchor = startOfMonth(getToday());
|
||||
return nextAnchor.getTime() >= minAnchor.getTime();
|
||||
},
|
||||
getSelectionKeys: () => dateKey(horizonEndDate),
|
||||
onSelectionCommit: (selectedKey) => {
|
||||
selectHorizonDate(new Date(`${selectedKey}T00:00:00`));
|
||||
|
||||
Reference in New Issue
Block a user