Implement highlight effect on the day navigated to.
This commit is contained in:
@@ -17,16 +17,7 @@ const formattedDate = computed(() => {
|
|||||||
<div
|
<div
|
||||||
class="cell"
|
class="cell"
|
||||||
:style="props.dragging ? 'touch-action:none;' : 'touch-action:pan-y;'"
|
:style="props.dragging ? 'touch-action:none;' : 'touch-action:pan-y;'"
|
||||||
:class="[
|
:class="[props.day.monthClass, { today: props.day.isToday, weekend: props.day.isWeekend, firstday: props.day.isFirstDay, selected: props.day.isSelected, holiday: props.day.isHoliday }]"
|
||||||
props.day.monthClass,
|
|
||||||
{
|
|
||||||
today: props.day.isToday,
|
|
||||||
weekend: props.day.isWeekend,
|
|
||||||
firstday: props.day.isFirstDay,
|
|
||||||
selected: props.day.isSelected,
|
|
||||||
holiday: props.day.isHoliday,
|
|
||||||
},
|
|
||||||
]"
|
|
||||||
:data-date="props.day.date"
|
:data-date="props.day.date"
|
||||||
>
|
>
|
||||||
<span class="compact-date">{{ formattedDate }}</span>
|
<span class="compact-date">{{ formattedDate }}</span>
|
||||||
@@ -43,10 +34,8 @@ const formattedDate = computed(() => {
|
|||||||
position: relative;
|
position: relative;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
display: grid;
|
display: grid;
|
||||||
/* Updated grid for centered day number */
|
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
grid-template-rows: 1fr auto;
|
grid-template-rows: 1fr auto;
|
||||||
/* Named grid areas */
|
|
||||||
grid-template-areas:
|
grid-template-areas:
|
||||||
'day-number'
|
'day-number'
|
||||||
'holiday-info';
|
'holiday-info';
|
||||||
@@ -89,6 +78,26 @@ const formattedDate = computed(() => {
|
|||||||
z-index: 15;
|
z-index: 15;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Search highlight animation */
|
||||||
|
.cell.search-highlight-flash::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
width: calc(100% + .2rem);
|
||||||
|
height: calc(100% + .2rem);
|
||||||
|
border-radius: 1rem;
|
||||||
|
background: transparent;
|
||||||
|
border: 0.3em solid var(--strong);
|
||||||
|
z-index: 16;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cell.search-highlight-flash::after { animation: search-highlight-flash 1.5s ease-out forwards; }
|
||||||
|
|
||||||
|
@keyframes search-highlight-flash {0%{opacity:0;transform:translate(-50%,-50%) scale(.8);border-width:.1em}15%{opacity:1;transform:translate(-50%,-50%) scale(1.05);border-width:.4em}30%{opacity:1;transform:translate(-50%,-50%) scale(1);border-width:.3em}100%{opacity:0;transform:translate(-50%,-50%) scale(1);border-width:.3em}}
|
||||||
.cell.selected h1.day-number {
|
.cell.selected h1.day-number {
|
||||||
opacity: 0.3;
|
opacity: 0.3;
|
||||||
filter: brightness(1.2);
|
filter: brightness(1.2);
|
||||||
|
|||||||
@@ -197,11 +197,24 @@ function measureFromProbe() {
|
|||||||
const {
|
const {
|
||||||
getWeekIndex,
|
getWeekIndex,
|
||||||
getFirstDayForVirtualWeek,
|
getFirstDayForVirtualWeek,
|
||||||
goToToday,
|
|
||||||
handleHeaderYearChange,
|
handleHeaderYearChange,
|
||||||
scrollToWeekCentered,
|
scrollToWeekCentered,
|
||||||
} = vwm
|
} = vwm
|
||||||
|
|
||||||
|
function showDay(input) {
|
||||||
|
const dateStr = input instanceof Date ? toLocalString(input, DEFAULT_TZ) : String(input)
|
||||||
|
const weekIndex = getWeekIndex(fromLocalString(dateStr, DEFAULT_TZ))
|
||||||
|
scrollToWeekCentered(weekIndex, 'nav', true)
|
||||||
|
const diff = Math.abs(weekIndex - centerVisibleWeek.value)
|
||||||
|
const delay = Math.min(800, diff * 40)
|
||||||
|
setTimeout(() => {
|
||||||
|
const el = document.querySelector(`[data-date="${dateStr}"]`)
|
||||||
|
if (!el) return
|
||||||
|
el.classList.add('search-highlight-flash')
|
||||||
|
setTimeout(() => el.classList.remove('search-highlight-flash'), 1500)
|
||||||
|
}, delay)
|
||||||
|
}
|
||||||
|
|
||||||
// Reference date for search: center of the current viewport (virtual week at vertical midpoint)
|
// Reference date for search: center of the current viewport (virtual week at vertical midpoint)
|
||||||
const centerVisibleWeek = computed(() => {
|
const centerVisibleWeek = computed(() => {
|
||||||
const midRow = (scrollTop.value + viewportHeight.value / 2) / rowHeight.value
|
const midRow = (scrollTop.value + viewportHeight.value / 2) / rowHeight.value
|
||||||
@@ -457,26 +470,15 @@ const handleEventClick = (payload) => {
|
|||||||
openEditEventDialog(payload)
|
openEditEventDialog(payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
function scrollToEventStart(startDate, smooth = true) {
|
function handleHeaderSearchPreview(r) { if (r) showDay(r.startDate) }
|
||||||
try {
|
function handleHeaderSearchActivate(r) {
|
||||||
const dateObj = fromLocalString(startDate, DEFAULT_TZ)
|
if (!r) return
|
||||||
const weekIndex = getWeekIndex(dateObj)
|
showDay(r.startDate)
|
||||||
scrollToWeekCentered(weekIndex, 'search-jump', smooth)
|
if (!r._goto && !r._holiday) {
|
||||||
} catch {
|
const ev = calendarStore.getEventById(r.id)
|
||||||
/* noop */
|
if (ev) openEditEventDialog({ id: ev.id, event: ev })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function handleHeaderSearchPreview(result) {
|
|
||||||
if (!result) return
|
|
||||||
scrollToEventStart(result.startDate, true)
|
|
||||||
}
|
|
||||||
function handleHeaderSearchActivate(result) {
|
|
||||||
if (!result) return
|
|
||||||
scrollToEventStart(result.startDate, true)
|
|
||||||
// Open edit dialog for the event
|
|
||||||
const ev = calendarStore.getEventById(result.id)
|
|
||||||
if (ev) openEditEventDialog({ id: ev.id, event: ev })
|
|
||||||
}
|
|
||||||
|
|
||||||
// Heuristic: rotate month label (180deg) only for predominantly Latin text.
|
// Heuristic: rotate month label (180deg) only for predominantly Latin text.
|
||||||
// We explicitly avoid locale detection; rely solely on characters present.
|
// We explicitly avoid locale detection; rely solely on characters present.
|
||||||
@@ -543,7 +545,7 @@ window.addEventListener('resize', () => {
|
|||||||
<div class="wrap">
|
<div class="wrap">
|
||||||
<HeaderControls
|
<HeaderControls
|
||||||
:reference-date="centerVisibleDateStr"
|
:reference-date="centerVisibleDateStr"
|
||||||
@go-to-today="goToToday"
|
@go-to-today="() => showDay(calendarStore.today)"
|
||||||
@search-preview="handleHeaderSearchPreview"
|
@search-preview="handleHeaderSearchPreview"
|
||||||
@search-activate="handleHeaderSearchActivate"
|
@search-activate="handleHeaderSearchActivate"
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user