61 lines
1.8 KiB
TypeScript
61 lines
1.8 KiB
TypeScript
import type {
|
|
SlideParams,
|
|
TransitionConfig,
|
|
} from 'svelte/transition';
|
|
|
|
function elasticOut(t: number) {
|
|
return Math.pow(2, -10 * t) * Math.sin((t - 0.075) * (2 * Math.PI) / 0.3) + 1;
|
|
}
|
|
|
|
function gentleSpring(t: number) {
|
|
return 1 - Math.pow(1 - t, 3) * Math.cos(t * Math.PI * 2);
|
|
}
|
|
|
|
/**
|
|
* Svelte slide transition function for custom slide+fade
|
|
* @param node - The element to apply the transition to
|
|
* @param params - Transition parameters
|
|
* @returns Transition configuration
|
|
*/
|
|
export function springySlideFade(
|
|
node: HTMLElement,
|
|
params: SlideParams = {},
|
|
): TransitionConfig {
|
|
const { duration = 400 } = params;
|
|
const height = node.scrollHeight;
|
|
|
|
// Check if the browser is Firefox to work around specific rendering issues
|
|
const isFirefox = navigator.userAgent.toLowerCase().includes('firefox');
|
|
|
|
return {
|
|
duration,
|
|
// We use 'tick' for the most precise control over the
|
|
// coordination with the elements below.
|
|
css: t => {
|
|
// Use elastic easing
|
|
const eased = gentleSpring(t);
|
|
|
|
return `
|
|
height: ${eased * height}px;
|
|
opacity: ${t};
|
|
transform: translateY(${(1 - t) * -10}px);
|
|
transform-origin: top;
|
|
overflow: hidden;
|
|
contain: size layout style;
|
|
will-change: max-height, opacity, transform;
|
|
backface-visibility: hidden;
|
|
-webkit-font-smoothing: antialiased;
|
|
-moz-osx-font-smoothing: grayscale;
|
|
${
|
|
isFirefox
|
|
? `
|
|
perspective: 1000px;
|
|
isolation: isolate;
|
|
`
|
|
: ''
|
|
}
|
|
`;
|
|
},
|
|
};
|
|
}
|