|
|
@ -4,12 +4,12 @@ import { setAnimationTimeout, useTween } from './loop';
|
|
|
|
import { animate_css } from './style_manager';
|
|
|
|
import { animate_css } from './style_manager';
|
|
|
|
import { custom_event } from './dom';
|
|
|
|
import { custom_event } from './dom';
|
|
|
|
import { TransitionConfig } from '../transition';
|
|
|
|
import { TransitionConfig } from '../transition';
|
|
|
|
import { add_render_callback, add_flush_callback } from './scheduler';
|
|
|
|
import { add_measure_callback, add_render_callback } from './scheduler';
|
|
|
|
import { Fragment } from './Component';
|
|
|
|
import { Fragment } from './Component';
|
|
|
|
|
|
|
|
|
|
|
|
function startStopDispatcher(node: Element, direction: boolean) {
|
|
|
|
function startStopDispatcher(node: Element, is_intro: boolean) {
|
|
|
|
add_render_callback(() => node.dispatchEvent(custom_event(`${direction ? 'intro' : 'outro'}start`)));
|
|
|
|
node.dispatchEvent(custom_event(`${is_intro ? 'intro' : 'outro'}start`));
|
|
|
|
return () => node.dispatchEvent(custom_event(`${!direction ? 'intro' : 'outro'}end`));
|
|
|
|
return () => node.dispatchEvent(custom_event(`${is_intro ? 'intro' : 'outro'}end`));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const outroing = new Set();
|
|
|
|
const outroing = new Set();
|
|
|
@ -47,65 +47,73 @@ export function transition_out(block: Fragment, local?: 0 | 1, detach?: 0 | 1, c
|
|
|
|
block.o(local);
|
|
|
|
block.o(local);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const eased = (fn: (t: number) => any, easing: (t: number) => number) => (easing ? (t: number) => fn(easing(t)) : fn);
|
|
|
|
const eased = (fn: (t: number) => any, easing: (t: number) => number, start, end) => (t: number) =>
|
|
|
|
const runner = (fn: (t0: number, t1: number) => any, reversed: boolean) =>
|
|
|
|
fn(start + (end - start) * easing(t));
|
|
|
|
reversed ? (t: number) => fn(1 - t, t) : (t: number) => fn(t, 1 - t);
|
|
|
|
//easing ? (!is_intro ? (t: number) => fn(easing(t)) : (t: number) => fn(1 - easing(1 - t))) : fn;
|
|
|
|
|
|
|
|
const runner = (fn: (t0: number, t1: number) => any, is_intro: boolean) =>
|
|
|
|
|
|
|
|
is_intro ? (t: number) => fn(t, 1 - t) : (t: number) => fn(1 - t, t);
|
|
|
|
|
|
|
|
const mirror = (fn, easing, is_intro) => {
|
|
|
|
|
|
|
|
const run = is_intro ? (t) => fn(1 - t, t) : (t) => fn(t, 1 - t);
|
|
|
|
|
|
|
|
return easing ? (is_intro ? (t) => run(1 - easing(1 - t)) : (t) => run(easing(t))) : run;
|
|
|
|
|
|
|
|
};
|
|
|
|
type TransitionFn = (node: HTMLElement, params: any) => TransitionConfig;
|
|
|
|
type TransitionFn = (node: HTMLElement, params: any) => TransitionConfig;
|
|
|
|
export function run_transition(
|
|
|
|
export function run_transition(
|
|
|
|
node: HTMLElement,
|
|
|
|
node: HTMLElement,
|
|
|
|
fn: TransitionFn,
|
|
|
|
fn: TransitionFn,
|
|
|
|
is_intro = true,
|
|
|
|
is_intro = true,
|
|
|
|
params = {},
|
|
|
|
params = {},
|
|
|
|
reversed_from = -1
|
|
|
|
left_duration = 0,
|
|
|
|
|
|
|
|
prev_left = 0
|
|
|
|
): StopResetReverse {
|
|
|
|
): StopResetReverse {
|
|
|
|
let config = fn(node, params);
|
|
|
|
let config;
|
|
|
|
let running = true;
|
|
|
|
let running = true;
|
|
|
|
|
|
|
|
|
|
|
|
let cancel_css;
|
|
|
|
let cancel_css;
|
|
|
|
let cancel_raf;
|
|
|
|
let cancel_raf;
|
|
|
|
let dispatch_end;
|
|
|
|
let dispatch_end;
|
|
|
|
let end_time;
|
|
|
|
let end_time;
|
|
|
|
|
|
|
|
let t;
|
|
|
|
|
|
|
|
let start_ratio;
|
|
|
|
|
|
|
|
|
|
|
|
const group = outros;
|
|
|
|
const group = outros;
|
|
|
|
if (!is_intro) group.r++;
|
|
|
|
if (!is_intro) group.r++;
|
|
|
|
|
|
|
|
|
|
|
|
function start({ delay = 0, duration = 300, easing, tick, css }: TransitionConfig) {
|
|
|
|
const start = ({ delay = 0, duration = 300, easing, tick, css }: TransitionConfig) => {
|
|
|
|
if (!running) return;
|
|
|
|
if (!running) return;
|
|
|
|
const start_time = ~reversed_from ? reversed_from : now() + delay;
|
|
|
|
t = duration - (left_duration > 0 ? left_duration : 0);
|
|
|
|
end_time = start_time + duration;
|
|
|
|
end_time = now() + t;
|
|
|
|
if (css)
|
|
|
|
start_ratio = 1 - easing((t - prev_left) / duration);
|
|
|
|
cancel_css = animate_css(
|
|
|
|
if (css) cancel_css = animate_css(eased(runner(css, is_intro), easing, start_ratio, 1), node, t, 0);
|
|
|
|
runner(eased(css, easing), is_intro),
|
|
|
|
|
|
|
|
node,
|
|
|
|
|
|
|
|
duration,
|
|
|
|
|
|
|
|
(end_time - start_time) / duration
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
dispatch_end = startStopDispatcher(node, is_intro);
|
|
|
|
dispatch_end = startStopDispatcher(node, is_intro);
|
|
|
|
cancel_raf = tick
|
|
|
|
cancel_raf = tick
|
|
|
|
? useTween(runner(eased(tick, easing), is_intro), stop, duration, end_time)
|
|
|
|
? useTween(eased(runner(tick, is_intro), easing, start_ratio, 1), stop, end_time, t)
|
|
|
|
: setAnimationTimeout(stop, end_time);
|
|
|
|
: setAnimationTimeout(stop, end_time);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
function stop(reset_reverse?: 1 | -1) {
|
|
|
|
|
|
|
|
if (!is_intro && 1 === reset_reverse && config && 'tick' in config) config.tick(1, 0);
|
|
|
|
const stop = (end_reset_reverse?: number | 1 | -1) => {
|
|
|
|
if (!running) return;
|
|
|
|
if (!running) return;
|
|
|
|
else running = false;
|
|
|
|
else running = false;
|
|
|
|
if (cancel_css) cancel_css();
|
|
|
|
if (cancel_css) cancel_css();
|
|
|
|
if (cancel_raf) cancel_raf();
|
|
|
|
if (cancel_raf) cancel_raf();
|
|
|
|
if (dispatch_end) dispatch_end();
|
|
|
|
if (t > end_time && dispatch_end) dispatch_end();
|
|
|
|
if (!is_intro && !--group.r) for (let i = 0; i < group.c.length; i++) group.c[i]();
|
|
|
|
if (!is_intro && !--group.r) for (let i = 0; i < group.c.length; i++) group.c[i]();
|
|
|
|
if (!~reset_reverse) return run_transition(node, fn, !is_intro, params, end_time);
|
|
|
|
if (!~end_reset_reverse)
|
|
|
|
else if (!~reversed_from) running_bidi.delete(node);
|
|
|
|
return run_transition(node, () => config, !is_intro, params, end_time - now(), left_duration);
|
|
|
|
}
|
|
|
|
else if (left_duration) running_bidi.delete(node);
|
|
|
|
// @ts-ignore
|
|
|
|
};
|
|
|
|
if (typeof config === 'function') add_flush_callback(() => start((config = config())));
|
|
|
|
|
|
|
|
else start(config);
|
|
|
|
add_measure_callback(() => {
|
|
|
|
|
|
|
|
config = fn(node, params);
|
|
|
|
|
|
|
|
return () => start(typeof config === 'function' ? (config = config()) : config);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
return stop;
|
|
|
|
return stop;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
export type StopResetReverse = (reset_reverse?: 1 | -1) => StopResetReverse;
|
|
|
|
export type StopResetReverse = (reset_reverse?: 1 | -1) => StopResetReverse;
|
|
|
|
const running_bidi: Map<HTMLElement, StopResetReverse> = new Map();
|
|
|
|
const running_bidi: Map<HTMLElement, StopResetReverse> = new Map();
|
|
|
|
export function run_bidirectional_transition(node: HTMLElement, fn: TransitionFn, is_intro: boolean, params: any) {
|
|
|
|
export function run_bidirectional_transition(node: HTMLElement, fn: TransitionFn, is_intro: boolean, params: any) {
|
|
|
|
let cancel;
|
|
|
|
let cancel;
|
|
|
|
if (running_bidi.has(node)) running_bidi.set(node, (cancel = running_bidi.get(node)(-1)));
|
|
|
|
if (running_bidi.has(node) && (cancel = running_bidi.get(node)(-1))) running_bidi.set(node, cancel);
|
|
|
|
else running_bidi.set(node, (cancel = run_transition(node, fn, is_intro, params, -1)));
|
|
|
|
else running_bidi.set(node, (cancel = run_transition(node, fn, is_intro, params, -1)));
|
|
|
|
return cancel;
|
|
|
|
return cancel;
|
|
|
|
}
|
|
|
|
}
|
|
|
|