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; /** * 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 }; };