|
|
|
|
@ -1,32 +1,13 @@
|
|
|
|
|
import { cubicOut, cubicInOut, linear } from '../easing';
|
|
|
|
|
import { assign, split_css_unit, is_function } from '../internal';
|
|
|
|
|
|
|
|
|
|
export type EasingFunction = (t: number) => number;
|
|
|
|
|
|
|
|
|
|
export interface TransitionConfig {
|
|
|
|
|
delay?: number;
|
|
|
|
|
duration?: number;
|
|
|
|
|
easing?: EasingFunction;
|
|
|
|
|
css?: (t: number, u: number) => string;
|
|
|
|
|
tick?: (t: number, u: number) => void;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface BlurParams {
|
|
|
|
|
delay?: number;
|
|
|
|
|
duration?: number;
|
|
|
|
|
easing?: EasingFunction;
|
|
|
|
|
amount?: number | string;
|
|
|
|
|
opacity?: number;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function blur(
|
|
|
|
|
node: Element,
|
|
|
|
|
{ delay = 0, duration = 400, easing = cubicInOut, amount = 5, opacity = 0 }: BlurParams = {}
|
|
|
|
|
): TransitionConfig {
|
|
|
|
|
/** @param {Element} node
|
|
|
|
|
* @param {BlurParams}
|
|
|
|
|
* @returns {import("/Users/elliottjohnson/dev/sveltejs/svelte/index.ts-to-jsdoc").TransitionConfig}
|
|
|
|
|
*/
|
|
|
|
|
export function blur(node, { delay = 0, duration = 400, easing = cubicInOut, amount = 5, opacity = 0 } = {}) {
|
|
|
|
|
const style = getComputedStyle(node);
|
|
|
|
|
const target_opacity = +style.opacity;
|
|
|
|
|
const f = style.filter === 'none' ? '' : style.filter;
|
|
|
|
|
|
|
|
|
|
const od = target_opacity * (1 - opacity);
|
|
|
|
|
const [value, unit] = split_css_unit(amount);
|
|
|
|
|
return {
|
|
|
|
|
@ -36,19 +17,12 @@ export function blur(
|
|
|
|
|
css: (_t, u) => `opacity: ${target_opacity - od * u}; filter: ${f} blur(${u * value}${unit});`
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface FadeParams {
|
|
|
|
|
delay?: number;
|
|
|
|
|
duration?: number;
|
|
|
|
|
easing?: EasingFunction;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function fade(
|
|
|
|
|
node: Element,
|
|
|
|
|
{ delay = 0, duration = 400, easing = linear }: FadeParams = {}
|
|
|
|
|
): TransitionConfig {
|
|
|
|
|
/** @param {Element} node
|
|
|
|
|
* @param {FadeParams}
|
|
|
|
|
* @returns {import("/Users/elliottjohnson/dev/sveltejs/svelte/index.ts-to-jsdoc").TransitionConfig}
|
|
|
|
|
*/
|
|
|
|
|
export function fade(node, { delay = 0, duration = 400, easing = linear } = {}) {
|
|
|
|
|
const o = +getComputedStyle(node).opacity;
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
delay,
|
|
|
|
|
duration,
|
|
|
|
|
@ -56,24 +30,14 @@ export function fade(
|
|
|
|
|
css: (t) => `opacity: ${t * o}`
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface FlyParams {
|
|
|
|
|
delay?: number;
|
|
|
|
|
duration?: number;
|
|
|
|
|
easing?: EasingFunction;
|
|
|
|
|
x?: number | string;
|
|
|
|
|
y?: number | string;
|
|
|
|
|
opacity?: number;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function fly(
|
|
|
|
|
node: Element,
|
|
|
|
|
{ delay = 0, duration = 400, easing = cubicOut, x = 0, y = 0, opacity = 0 }: FlyParams = {}
|
|
|
|
|
): TransitionConfig {
|
|
|
|
|
/** @param {Element} node
|
|
|
|
|
* @param {FlyParams}
|
|
|
|
|
* @returns {import("/Users/elliottjohnson/dev/sveltejs/svelte/index.ts-to-jsdoc").TransitionConfig}
|
|
|
|
|
*/
|
|
|
|
|
export function fly(node, { delay = 0, duration = 400, easing = cubicOut, x = 0, y = 0, opacity = 0 } = {}) {
|
|
|
|
|
const style = getComputedStyle(node);
|
|
|
|
|
const target_opacity = +style.opacity;
|
|
|
|
|
const transform = style.transform === 'none' ? '' : style.transform;
|
|
|
|
|
|
|
|
|
|
const od = target_opacity * (1 - opacity);
|
|
|
|
|
const [xValue, xUnit] = split_css_unit(x);
|
|
|
|
|
const [yValue, yUnit] = split_css_unit(y);
|
|
|
|
|
@ -86,42 +50,28 @@ export function fly(
|
|
|
|
|
opacity: ${target_opacity - od * u}`
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface SlideParams {
|
|
|
|
|
delay?: number;
|
|
|
|
|
duration?: number;
|
|
|
|
|
easing?: EasingFunction;
|
|
|
|
|
axis?: 'x' | 'y';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function slide(
|
|
|
|
|
node: Element,
|
|
|
|
|
{ delay = 0, duration = 400, easing = cubicOut, axis = 'y' }: SlideParams = {}
|
|
|
|
|
): TransitionConfig {
|
|
|
|
|
/** @param {Element} node
|
|
|
|
|
* @param {SlideParams}
|
|
|
|
|
* @returns {import("/Users/elliottjohnson/dev/sveltejs/svelte/index.ts-to-jsdoc").TransitionConfig}
|
|
|
|
|
*/
|
|
|
|
|
export function slide(node, { delay = 0, duration = 400, easing = cubicOut, axis = 'y' } = {}) {
|
|
|
|
|
const style = getComputedStyle(node);
|
|
|
|
|
const opacity = +style.opacity;
|
|
|
|
|
const primary_property = axis === 'y' ? 'height' : 'width';
|
|
|
|
|
const primary_property_value = parseFloat(style[primary_property]);
|
|
|
|
|
const secondary_properties = axis === 'y' ? ['top', 'bottom'] : ['left', 'right'];
|
|
|
|
|
const capitalized_secondary_properties = secondary_properties.map(
|
|
|
|
|
(e) => `${e[0].toUpperCase()}${e.slice(1)}`
|
|
|
|
|
);
|
|
|
|
|
const capitalized_secondary_properties = secondary_properties.map((e) => `${e[0].toUpperCase()}${e.slice(1)}`);
|
|
|
|
|
const padding_start_value = parseFloat(style[`padding${capitalized_secondary_properties[0]}`]);
|
|
|
|
|
const padding_end_value = parseFloat(style[`padding${capitalized_secondary_properties[1]}`]);
|
|
|
|
|
const margin_start_value = parseFloat(style[`margin${capitalized_secondary_properties[0]}`]);
|
|
|
|
|
const margin_end_value = parseFloat(style[`margin${capitalized_secondary_properties[1]}`]);
|
|
|
|
|
const border_width_start_value = parseFloat(
|
|
|
|
|
style[`border${capitalized_secondary_properties[0]}Width`]
|
|
|
|
|
);
|
|
|
|
|
const border_width_end_value = parseFloat(
|
|
|
|
|
style[`border${capitalized_secondary_properties[1]}Width`]
|
|
|
|
|
);
|
|
|
|
|
const border_width_start_value = parseFloat(style[`border${capitalized_secondary_properties[0]}Width`]);
|
|
|
|
|
const border_width_end_value = parseFloat(style[`border${capitalized_secondary_properties[1]}Width`]);
|
|
|
|
|
return {
|
|
|
|
|
delay,
|
|
|
|
|
duration,
|
|
|
|
|
easing,
|
|
|
|
|
css: (t) =>
|
|
|
|
|
'overflow: hidden;' +
|
|
|
|
|
css: (t) => 'overflow: hidden;' +
|
|
|
|
|
`opacity: ${Math.min(t * 20, 1) * opacity};` +
|
|
|
|
|
`${primary_property}: ${t * primary_property_value}px;` +
|
|
|
|
|
`padding-${secondary_properties[0]}: ${t * padding_start_value}px;` +
|
|
|
|
|
@ -132,26 +82,16 @@ export function slide(
|
|
|
|
|
`border-${secondary_properties[1]}-width: ${t * border_width_end_value}px;`
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface ScaleParams {
|
|
|
|
|
delay?: number;
|
|
|
|
|
duration?: number;
|
|
|
|
|
easing?: EasingFunction;
|
|
|
|
|
start?: number;
|
|
|
|
|
opacity?: number;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function scale(
|
|
|
|
|
node: Element,
|
|
|
|
|
{ delay = 0, duration = 400, easing = cubicOut, start = 0, opacity = 0 }: ScaleParams = {}
|
|
|
|
|
): TransitionConfig {
|
|
|
|
|
/** @param {Element} node
|
|
|
|
|
* @param {ScaleParams}
|
|
|
|
|
* @returns {import("/Users/elliottjohnson/dev/sveltejs/svelte/index.ts-to-jsdoc").TransitionConfig}
|
|
|
|
|
*/
|
|
|
|
|
export function scale(node, { delay = 0, duration = 400, easing = cubicOut, start = 0, opacity = 0 } = {}) {
|
|
|
|
|
const style = getComputedStyle(node);
|
|
|
|
|
const target_opacity = +style.opacity;
|
|
|
|
|
const transform = style.transform === 'none' ? '' : style.transform;
|
|
|
|
|
|
|
|
|
|
const sd = 1 - start;
|
|
|
|
|
const od = target_opacity * (1 - opacity);
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
delay,
|
|
|
|
|
duration,
|
|
|
|
|
@ -162,34 +102,27 @@ export function scale(
|
|
|
|
|
`
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface DrawParams {
|
|
|
|
|
delay?: number;
|
|
|
|
|
speed?: number;
|
|
|
|
|
duration?: number | ((len: number) => number);
|
|
|
|
|
easing?: EasingFunction;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function draw(
|
|
|
|
|
node: SVGElement & { getTotalLength(): number },
|
|
|
|
|
{ delay = 0, speed, duration, easing = cubicInOut }: DrawParams = {}
|
|
|
|
|
): TransitionConfig {
|
|
|
|
|
/** @param {SVGElement & { getTotalLength(): number }} node
|
|
|
|
|
* @param {DrawParams}
|
|
|
|
|
* @returns {import("/Users/elliottjohnson/dev/sveltejs/svelte/index.ts-to-jsdoc").TransitionConfig}
|
|
|
|
|
*/
|
|
|
|
|
export function draw(node, { delay = 0, speed, duration, easing = cubicInOut } = {}) {
|
|
|
|
|
let len = node.getTotalLength();
|
|
|
|
|
const style = getComputedStyle(node);
|
|
|
|
|
if (style.strokeLinecap !== 'butt') {
|
|
|
|
|
len += parseInt(style.strokeWidth);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (duration === undefined) {
|
|
|
|
|
if (speed === undefined) {
|
|
|
|
|
duration = 800;
|
|
|
|
|
} else {
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
duration = len / speed;
|
|
|
|
|
}
|
|
|
|
|
} else if (typeof duration === 'function') {
|
|
|
|
|
}
|
|
|
|
|
else if (typeof duration === 'function') {
|
|
|
|
|
duration = duration(len);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
delay,
|
|
|
|
|
duration,
|
|
|
|
|
@ -200,44 +133,24 @@ export function draw(
|
|
|
|
|
`
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface CrossfadeParams {
|
|
|
|
|
delay?: number;
|
|
|
|
|
duration?: number | ((len: number) => number);
|
|
|
|
|
easing?: EasingFunction;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type ClientRectMap = Map<any, Element>;
|
|
|
|
|
|
|
|
|
|
export function crossfade({
|
|
|
|
|
fallback,
|
|
|
|
|
...defaults
|
|
|
|
|
}: CrossfadeParams & {
|
|
|
|
|
fallback?: (node: Element, params: CrossfadeParams, intro: boolean) => TransitionConfig;
|
|
|
|
|
}): [
|
|
|
|
|
(
|
|
|
|
|
node: Element,
|
|
|
|
|
params: CrossfadeParams & {
|
|
|
|
|
key: any;
|
|
|
|
|
}
|
|
|
|
|
) => () => TransitionConfig,
|
|
|
|
|
(
|
|
|
|
|
node: Element,
|
|
|
|
|
params: CrossfadeParams & {
|
|
|
|
|
key: any;
|
|
|
|
|
}
|
|
|
|
|
) => () => TransitionConfig
|
|
|
|
|
] {
|
|
|
|
|
const to_receive: ClientRectMap = new Map();
|
|
|
|
|
const to_send: ClientRectMap = new Map();
|
|
|
|
|
|
|
|
|
|
function crossfade(from_node: Element, node: Element, params: CrossfadeParams): TransitionConfig {
|
|
|
|
|
const {
|
|
|
|
|
delay = 0,
|
|
|
|
|
duration = (d) => Math.sqrt(d) * 30,
|
|
|
|
|
easing = cubicOut
|
|
|
|
|
} = assign(assign({}, defaults), params);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param {CrossfadeParams & {
|
|
|
|
|
* fallback?: (node: Element, params: CrossfadeParams, intro: boolean) => TransitionConfig;
|
|
|
|
|
* }}
|
|
|
|
|
* @returns {[(node: any, params: import("/Users/elliottjohnson/dev/sveltejs/svelte/index.ts-to-jsdoc").CrossfadeParams & { key: any; }) => () => import("/Users/elliottjohnson/dev/sveltejs/svelte/index.ts-to-jsdoc").TransitionConfig, (node: any, params: import("/Users/elliottjohnson/dev/sveltejs/svelte/index.ts-to-jsdoc").CrossfadeParams & { key: any; }) => () => import("/Users/elliottjohnson/dev/sveltejs/svelte/index.ts-to-jsdoc").TransitionConfig]}
|
|
|
|
|
*/
|
|
|
|
|
export function crossfade({ fallback, ...defaults }) {
|
|
|
|
|
/** @type {ClientRectMap} */
|
|
|
|
|
const to_receive = new Map();
|
|
|
|
|
/** @type {ClientRectMap} */
|
|
|
|
|
const to_send = new Map();
|
|
|
|
|
/** @param {Element} from_node
|
|
|
|
|
* @param {Element} node
|
|
|
|
|
* @param {CrossfadeParams} params
|
|
|
|
|
* @returns {import("/Users/elliottjohnson/dev/sveltejs/svelte/index.ts-to-jsdoc").TransitionConfig}
|
|
|
|
|
*/
|
|
|
|
|
function crossfade(from_node, node, params) {
|
|
|
|
|
const { delay = 0, duration = (d) => Math.sqrt(d) * 30, easing = cubicOut } = assign(assign({}, defaults), params);
|
|
|
|
|
const from = from_node.getBoundingClientRect();
|
|
|
|
|
const to = node.getBoundingClientRect();
|
|
|
|
|
const dx = from.left - to.left;
|
|
|
|
|
@ -245,11 +158,9 @@ export function crossfade({
|
|
|
|
|
const dw = from.width / to.width;
|
|
|
|
|
const dh = from.height / to.height;
|
|
|
|
|
const d = Math.sqrt(dx * dx + dy * dy);
|
|
|
|
|
|
|
|
|
|
const style = getComputedStyle(node);
|
|
|
|
|
const transform = style.transform === 'none' ? '' : style.transform;
|
|
|
|
|
const opacity = +style.opacity;
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
delay,
|
|
|
|
|
duration: is_function(duration) ? duration(d) : duration,
|
|
|
|
|
@ -257,25 +168,24 @@ export function crossfade({
|
|
|
|
|
css: (t, u) => `
|
|
|
|
|
opacity: ${t * opacity};
|
|
|
|
|
transform-origin: top left;
|
|
|
|
|
transform: ${transform} translate(${u * dx}px,${u * dy}px) scale(${t + (1 - t) * dw}, ${
|
|
|
|
|
t + (1 - t) * dh
|
|
|
|
|
});
|
|
|
|
|
transform: ${transform} translate(${u * dx}px,${u * dy}px) scale(${t + (1 - t) * dw}, ${t + (1 - t) * dh});
|
|
|
|
|
`
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function transition(items: ClientRectMap, counterparts: ClientRectMap, intro: boolean) {
|
|
|
|
|
return (node: Element, params: CrossfadeParams & { key: any }) => {
|
|
|
|
|
/** @param {ClientRectMap} items
|
|
|
|
|
* @param {ClientRectMap} counterparts
|
|
|
|
|
* @param {boolean} intro
|
|
|
|
|
* @returns {(node: any, params: import("/Users/elliottjohnson/dev/sveltejs/svelte/index.ts-to-jsdoc").CrossfadeParams & { key: any; }) => () => import("/Users/elliottjohnson/dev/sveltejs/svelte/index.ts-to-jsdoc").TransitionConfig}
|
|
|
|
|
*/
|
|
|
|
|
function transition(items, counterparts, intro) {
|
|
|
|
|
return (node, params) => {
|
|
|
|
|
items.set(params.key, node);
|
|
|
|
|
|
|
|
|
|
return () => {
|
|
|
|
|
if (counterparts.has(params.key)) {
|
|
|
|
|
const other_node = counterparts.get(params.key);
|
|
|
|
|
counterparts.delete(params.key);
|
|
|
|
|
|
|
|
|
|
return crossfade(other_node, node, params);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// if the node is disappearing altogether
|
|
|
|
|
// (i.e. wasn't claimed by the other list)
|
|
|
|
|
// then we need to supply an outro
|
|
|
|
|
@ -284,6 +194,61 @@ export function crossfade({
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return [transition(to_send, to_receive, false), transition(to_receive, to_send, true)];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** @typedef {(t: number) => number} EasingFunction */
|
|
|
|
|
/** @typedef {Map<any, Element>} ClientRectMap */
|
|
|
|
|
|
|
|
|
|
/** @typedef {Object} TransitionConfig
|
|
|
|
|
* @property {number} [delay]
|
|
|
|
|
* @property {number} [duration]
|
|
|
|
|
* @property {EasingFunction} [easing]
|
|
|
|
|
* @property {(t:number,u:number)=>string} [css]
|
|
|
|
|
* @property {(t:number,u:number)=>void} [tick]
|
|
|
|
|
*/
|
|
|
|
|
/** @typedef {Object} BlurParams
|
|
|
|
|
* @property {number} [delay]
|
|
|
|
|
* @property {number} [duration]
|
|
|
|
|
* @property {EasingFunction} [easing]
|
|
|
|
|
* @property {number|string} [amount]
|
|
|
|
|
* @property {number} [opacity]
|
|
|
|
|
*/
|
|
|
|
|
/** @typedef {Object} FadeParams
|
|
|
|
|
* @property {number} [delay]
|
|
|
|
|
* @property {number} [duration]
|
|
|
|
|
* @property {EasingFunction} [easing]
|
|
|
|
|
*/
|
|
|
|
|
/** @typedef {Object} FlyParams
|
|
|
|
|
* @property {number} [delay]
|
|
|
|
|
* @property {number} [duration]
|
|
|
|
|
* @property {EasingFunction} [easing]
|
|
|
|
|
* @property {number|string} [x]
|
|
|
|
|
* @property {number|string} [y]
|
|
|
|
|
* @property {number} [opacity]
|
|
|
|
|
*/
|
|
|
|
|
/** @typedef {Object} SlideParams
|
|
|
|
|
* @property {number} [delay]
|
|
|
|
|
* @property {number} [duration]
|
|
|
|
|
* @property {EasingFunction} [easing]
|
|
|
|
|
* @property {'x'|'y'} [axis]
|
|
|
|
|
*/
|
|
|
|
|
/** @typedef {Object} ScaleParams
|
|
|
|
|
* @property {number} [delay]
|
|
|
|
|
* @property {number} [duration]
|
|
|
|
|
* @property {EasingFunction} [easing]
|
|
|
|
|
* @property {number} [start]
|
|
|
|
|
* @property {number} [opacity]
|
|
|
|
|
*/
|
|
|
|
|
/** @typedef {Object} DrawParams
|
|
|
|
|
* @property {number} [delay]
|
|
|
|
|
* @property {number} [speed]
|
|
|
|
|
* @property {number|((len:number)=>number)} [duration]
|
|
|
|
|
* @property {EasingFunction} [easing]
|
|
|
|
|
*/
|
|
|
|
|
/** @typedef {Object} CrossfadeParams
|
|
|
|
|
* @property {number} [delay]
|
|
|
|
|
* @property {number|((len:number)=>number)} [duration]
|
|
|
|
|
* @property {EasingFunction} [easing]
|
|
|
|
|
*/
|