Files
sui/src/lib/transition.ts
2025-07-04 00:28:24 -07:00

63 lines
2.0 KiB
TypeScript

import { cubicOut } from 'svelte/easing';
import type { TransitionConfig } from 'svelte/transition';
/**
* A utility function that converts a style object to a string.
* Credits: https://github.com/melt-ui/melt-ui/blob/42e2dd430c3e13f56062c4d610dabd84ea4e5517/src/lib/internal/helpers/style.ts
* License: MIT, https://github.com/melt-ui/melt-ui/blob/develop/LICENSE
*
* @param style - The style object to convert
* @returns The style object as a string
*/
export function styleToString(style: StyleObject): string {
return Object.keys(style).reduce((str, key) => {
if (style[key] === undefined) return str;
return str + `${key}:${style[key]};`;
}, '');
}
export type StyleObject = Record<string, number | string | undefined>;
/**
* Credits: https://github.com/melt-ui/melt-ui/blob/develop/src/docs/utils/transition.ts
* License: MIT, https://github.com/melt-ui/melt-ui/blob/develop/LICENSE
* Thanks to the Melt-UI team for such an awesome library!https://github.com/melt-ui/melt-ui/blob/develop/src/docs/utils/transition.ts
*/
const scaleConversion = (valueA: number, scaleA: [number, number], scaleB: [number, number]) => {
const [minA, maxA] = scaleA;
const [minB, maxB] = scaleB;
const percentage = (valueA - minA) / (maxA - minA);
const valueB = percentage * (maxB - minB) + minB;
return valueB;
};
type FlyAndScaleOptions = {
x?: number;
y?: number;
start: number;
duration?: number;
};
export const flyAndScale = (node: HTMLElement, options: FlyAndScaleOptions): TransitionConfig => {
const style = getComputedStyle(node);
const transform = style.transform === 'none' ? '' : style.transform;
return {
duration: options.duration ?? 150,
delay: 0,
css: (t) => {
const x = scaleConversion(t, [0, 1], [options.x ?? 0, 0]);
const y = scaleConversion(t, [0, 1], [options.y ?? 0, 0]);
const scale = scaleConversion(t, [0, 1], [options.start, 1]);
return styleToString({
transform: `${transform} translate3d(${x}px, ${y}px, 0) scale(${scale})`,
opacity: t
});
},
easing: cubicOut
};
};