Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7541c12f66 | |||
| e8fd218c74 |
@@ -38,65 +38,18 @@
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.event-filter-target-list {
|
||||
view-transition-name: event-filter-list;
|
||||
contain: layout paint;
|
||||
}
|
||||
|
||||
html {
|
||||
scrollbar-gutter: stable both-edges;
|
||||
}
|
||||
|
||||
body {
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
@keyframes event-filter-vt-fade-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
to {
|
||||
.event-filter-target-list > .event {
|
||||
opacity: 1;
|
||||
}
|
||||
transform: translateY(0);
|
||||
transition: opacity 180ms ease, transform 180ms ease;
|
||||
transition-behavior: allow-discrete;
|
||||
will-change: opacity, transform;
|
||||
}
|
||||
|
||||
@keyframes event-filter-vt-fade-out {
|
||||
from {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
to {
|
||||
.event-filter-target-list > .event.is-filtered-out {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
::view-transition-group(root),
|
||||
::view-transition-old(root),
|
||||
::view-transition-new(root) {
|
||||
animation: none;
|
||||
}
|
||||
|
||||
::view-transition-group(event-filter-list) {
|
||||
animation-duration: 240ms;
|
||||
animation-timing-function: ease;
|
||||
}
|
||||
|
||||
::view-transition-old(event-filter-list),
|
||||
::view-transition-new(event-filter-list) {
|
||||
animation-duration: 240ms;
|
||||
animation-timing-function: ease;
|
||||
mix-blend-mode: normal;
|
||||
}
|
||||
|
||||
::view-transition-old(event-filter-list) {
|
||||
animation-name: event-filter-vt-fade-out;
|
||||
}
|
||||
|
||||
::view-transition-new(event-filter-list) {
|
||||
animation-name: event-filter-vt-fade-in;
|
||||
}
|
||||
transform: translateY(6px);
|
||||
pointer-events: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -177,64 +130,11 @@
|
||||
const stateStorageKey = 'event-filter-state';
|
||||
const stateQueryKey = 'event_filter';
|
||||
|
||||
const animationMs = 220;
|
||||
const animationMs = 180;
|
||||
let hideTimers = new WeakMap();
|
||||
const supportsViewTransitions = typeof document.startViewTransition === 'function';
|
||||
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
||||
let activeViewTransition = null;
|
||||
let isViewTransitionMutation = false;
|
||||
let hasAppliedInitialFilter = false;
|
||||
let currentFilter = { type: 'all', value: '' };
|
||||
let suppressedChangeEvents = 0;
|
||||
|
||||
const runWithLayoutTransition = (mutation) => {
|
||||
if (!supportsViewTransitions || prefersReducedMotion) {
|
||||
mutation();
|
||||
return;
|
||||
}
|
||||
|
||||
if (activeViewTransition) {
|
||||
mutation();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const transition = document.startViewTransition(() => {
|
||||
isViewTransitionMutation = true;
|
||||
|
||||
try {
|
||||
mutation();
|
||||
} finally {
|
||||
isViewTransitionMutation = false;
|
||||
}
|
||||
});
|
||||
|
||||
activeViewTransition = transition;
|
||||
|
||||
transition.ready.catch(() => {
|
||||
// Can reject when the transition is skipped.
|
||||
});
|
||||
|
||||
transition.updateCallbackDone.catch(() => {
|
||||
// Keep skipped/aborted update callbacks from surfacing as uncaught.
|
||||
});
|
||||
|
||||
transition.finished
|
||||
.catch(() => {
|
||||
// Browsers can skip overlapping transitions; ignore these rejections.
|
||||
})
|
||||
.finally(() => {
|
||||
if (activeViewTransition === transition) {
|
||||
activeViewTransition = null;
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
mutation();
|
||||
}
|
||||
};
|
||||
|
||||
const shouldMutateVisibilityImmediately = () => supportsViewTransitions && !prefersReducedMotion;
|
||||
|
||||
const hasOptionValue = (selectElement, value) => {
|
||||
if (!selectElement) {
|
||||
return false;
|
||||
@@ -367,38 +267,21 @@
|
||||
}
|
||||
};
|
||||
|
||||
const showEvent = (eventItem, { immediateVisibility = false } = {}) => {
|
||||
const showEvent = (eventItem) => {
|
||||
clearHideTimer(eventItem);
|
||||
|
||||
if (immediateVisibility) {
|
||||
eventItem.hidden = false;
|
||||
eventItem.classList.remove('is-filtered-out');
|
||||
return;
|
||||
}
|
||||
|
||||
if (eventItem.hidden) {
|
||||
eventItem.hidden = false;
|
||||
}
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
eventItem.classList.remove('is-filtered-out');
|
||||
});
|
||||
};
|
||||
|
||||
const hideEvent = (eventItem, { immediateVisibility = false } = {}) => {
|
||||
const hideEvent = (eventItem) => {
|
||||
clearHideTimer(eventItem);
|
||||
|
||||
if (immediateVisibility) {
|
||||
eventItem.classList.add('is-filtered-out');
|
||||
eventItem.hidden = true;
|
||||
return;
|
||||
}
|
||||
|
||||
eventItem.classList.add('is-filtered-out');
|
||||
|
||||
const timer = window.setTimeout(() => {
|
||||
eventItem.hidden = true;
|
||||
|
||||
hideTimers.delete(eventItem);
|
||||
}, animationMs);
|
||||
|
||||
@@ -490,26 +373,13 @@
|
||||
currentFilter = filterState;
|
||||
setActiveControl(filterState);
|
||||
|
||||
const immediateVisibility = shouldMutateVisibilityImmediately();
|
||||
const shouldAnimateLayout = immediateVisibility && hasAppliedInitialFilter;
|
||||
|
||||
const mutateVisibility = () => {
|
||||
events.forEach((eventItem) => {
|
||||
if (matches(eventItem, filterState)) {
|
||||
showEvent(eventItem, { immediateVisibility });
|
||||
showEvent(eventItem);
|
||||
} else {
|
||||
hideEvent(eventItem, { immediateVisibility });
|
||||
hideEvent(eventItem);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
if (shouldAnimateLayout) {
|
||||
runWithLayoutTransition(mutateVisibility);
|
||||
} else {
|
||||
mutateVisibility();
|
||||
}
|
||||
|
||||
hasAppliedInitialFilter = true;
|
||||
|
||||
updateStatus(filterState);
|
||||
syncState(filterState);
|
||||
|
||||
Reference in New Issue
Block a user