|
|
|
@ -1,44 +1,70 @@
|
|
|
|
|
import { CssTransitionConfig } from '../transition';
|
|
|
|
|
import { Fragment } from './Component';
|
|
|
|
|
import { custom_event } from './dom';
|
|
|
|
|
import { now } from './environment';
|
|
|
|
|
import { setFrameTimeout, setTweenTimeout } from './loop';
|
|
|
|
|
import { add_measure_callback } from './scheduler';
|
|
|
|
|
import { animate_css } from './style_manager';
|
|
|
|
|
import { methodify, noop } from './utils';
|
|
|
|
|
|
|
|
|
|
type TransitionFn = (node: HTMLElement, params: any) => CssTransitionConfig;
|
|
|
|
|
export type StopResetReverseFn = (t?: number | -1) => StopResetReverseFn | void;
|
|
|
|
|
import { Fragment } from "./Component";
|
|
|
|
|
import { custom_event } from "./dom";
|
|
|
|
|
import { setFrameTimeout, setTweenTimeout, frame } from "./loop";
|
|
|
|
|
import { add_measure_callback, tick } from "./scheduler";
|
|
|
|
|
import { animate_css } from "./style_manager";
|
|
|
|
|
import { methodify, noop } from "./utils";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export interface CssAnimationConfig {
|
|
|
|
|
delay?: number;
|
|
|
|
|
duration?: number;
|
|
|
|
|
easing?: (t: number) => number;
|
|
|
|
|
}
|
|
|
|
|
export interface CssTransitionConfig extends CssAnimationConfig {
|
|
|
|
|
css?: (t: number, u?: number) => string;
|
|
|
|
|
tick?: (t: number, u?: number) => void;
|
|
|
|
|
strategy?: EasingStrategy;
|
|
|
|
|
}
|
|
|
|
|
export type TimeableConfig = Omit<CssAnimationConfig, 'duration'> & { duration?: number | ((len: number) => number) };
|
|
|
|
|
const enum EasingStrategy {
|
|
|
|
|
reversed = "reversed",
|
|
|
|
|
balanced = "balanced",
|
|
|
|
|
mirrored = "mirrored",
|
|
|
|
|
}
|
|
|
|
|
const enum TransitionEvent {
|
|
|
|
|
introstart = "introstart",
|
|
|
|
|
introend = "introend",
|
|
|
|
|
outrostart = "outrostart",
|
|
|
|
|
outroend = "outroend"
|
|
|
|
|
}
|
|
|
|
|
export const transition_in = (block: Fragment, local?) => {
|
|
|
|
|
// todo : is `!block` necessary ?
|
|
|
|
|
if (!block || !block.i) return;
|
|
|
|
|
outroing.delete(block);
|
|
|
|
|
block.i(local);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export const transition_out = (block: Fragment, local?) => {
|
|
|
|
|
// todo : are `!block` and `outroing.has` checks necessary ?
|
|
|
|
|
if (!block || !block.o || outroing.has(block)) return;
|
|
|
|
|
outroing.add(block);
|
|
|
|
|
block.o(local);
|
|
|
|
|
};
|
|
|
|
|
type TransitionGroup = {
|
|
|
|
|
/* parent group */ p: TransitionGroup;
|
|
|
|
|
/* callbacks */ c: Array<((cancelled: boolean) => void)>;
|
|
|
|
|
/* callbacks */ c: Array<(cancelled: boolean) => void>;
|
|
|
|
|
/* running outros */ r: number;
|
|
|
|
|
/* stop callbacks */ s: Array<((t: number) => void)>;
|
|
|
|
|
/* stop callbacks */ s: Array<(t: number) => void>;
|
|
|
|
|
/* outro timeout */ t: number;
|
|
|
|
|
};
|
|
|
|
|
let transition_group: TransitionGroup;
|
|
|
|
|
const outroing = new Set();
|
|
|
|
|
export const group_transition_out = (fn) => {
|
|
|
|
|
const c = [];
|
|
|
|
|
const current_group = (transition_group = { p: transition_group, c, r: 0, s: [], t: 0 });
|
|
|
|
|
const current_group = (transition_group = {
|
|
|
|
|
p: transition_group,
|
|
|
|
|
c,
|
|
|
|
|
r: 0,
|
|
|
|
|
s: [],
|
|
|
|
|
t: 0,
|
|
|
|
|
});
|
|
|
|
|
fn((block, callback, detach = true) => {
|
|
|
|
|
if (!block || !block.o || outroing.has(block)) return;
|
|
|
|
|
outroing.add(block);
|
|
|
|
|
c.push((cancelled = false) => {
|
|
|
|
|
if (cancelled) {
|
|
|
|
|
// block was destroyed before outro ended
|
|
|
|
|
// block destroyed before outro ended
|
|
|
|
|
outroing.delete(block);
|
|
|
|
|
} else if (outroing.has(block)) {
|
|
|
|
|
outroing.delete(block);
|
|
|
|
@ -51,149 +77,256 @@ export const group_transition_out = (fn) => {
|
|
|
|
|
if (!current_group.r) for (let i = 0; i < c.length; i++) c[i]();
|
|
|
|
|
transition_group = transition_group.p;
|
|
|
|
|
};
|
|
|
|
|
type Rect = DOMRect | ClientRect;
|
|
|
|
|
type MeasureCallback = () => CssTransitionConfig
|
|
|
|
|
type CustomTransitionFunction = (node: HTMLElement, params: any) => MeasureCallback | CssTransitionConfig;
|
|
|
|
|
type AnimationFn = (node: Element, { from, to }: { from: Rect; to: Rect }, params: any) => CssTransitionConfig;
|
|
|
|
|
type StopResetReverseFn = (t?: number | 1 | -1) => StopResetReverseFn | void;
|
|
|
|
|
|
|
|
|
|
const swap = (fn, rx) =>
|
|
|
|
|
const swap = (fn, is_intro) =>
|
|
|
|
|
fn.length === 1
|
|
|
|
|
? rx & tx.intro
|
|
|
|
|
? is_intro
|
|
|
|
|
? fn
|
|
|
|
|
: (t) => fn(1 - t)
|
|
|
|
|
: rx & tx.intro
|
|
|
|
|
: is_intro
|
|
|
|
|
? (t) => fn(t, 1 - t)
|
|
|
|
|
: (t) => fn(1 - t, t);
|
|
|
|
|
|
|
|
|
|
const mirrored = (fn, rx, easing, _start, _end) => {
|
|
|
|
|
const run = swap(fn, rx);
|
|
|
|
|
const mirrored = (fn, is_intro, easing, _start?, _end?) => {
|
|
|
|
|
const run = swap(fn, is_intro);
|
|
|
|
|
return easing
|
|
|
|
|
? rx & tx.intro
|
|
|
|
|
? is_intro
|
|
|
|
|
? (t) => run(easing(t))
|
|
|
|
|
: (t) => run(1 - easing(1 - t))
|
|
|
|
|
: run;
|
|
|
|
|
};
|
|
|
|
|
const reversed = (fn, rx, easing, start = 0, end = 1) => {
|
|
|
|
|
const run = swap(fn, rx);
|
|
|
|
|
|
|
|
|
|
const reversed = (fn, is_intro, easing, start = 0, end = 1) => {
|
|
|
|
|
const run = swap(fn, is_intro);
|
|
|
|
|
const difference = end - start;
|
|
|
|
|
return easing
|
|
|
|
|
? (t) => run(start + difference * easing(t))
|
|
|
|
|
: (t) => run(start + difference * t);
|
|
|
|
|
};
|
|
|
|
|
const enum tx {
|
|
|
|
|
intro = 1,
|
|
|
|
|
outro = 2,
|
|
|
|
|
reverse = 3,
|
|
|
|
|
bidirectional = 4,
|
|
|
|
|
animation = 8,
|
|
|
|
|
}
|
|
|
|
|
export const run_transition = /*#__PURE__*/ methodify(function transition(
|
|
|
|
|
this: HTMLElement,
|
|
|
|
|
fn: TransitionFn,
|
|
|
|
|
rx: tx,
|
|
|
|
|
params = {},
|
|
|
|
|
/* internal to this file */
|
|
|
|
|
elapsed_duration = 0,
|
|
|
|
|
delay_left = -1,
|
|
|
|
|
elapsed_ratio = 0
|
|
|
|
|
) {
|
|
|
|
|
let config;
|
|
|
|
|
|
|
|
|
|
export const run_animation = /*#__PURE__*/ methodify(function (this: HTMLElement, from : Rect, fn: AnimationFn, params: CssTransitionConfig = {}) {
|
|
|
|
|
let running = true;
|
|
|
|
|
|
|
|
|
|
let cancel_css;
|
|
|
|
|
let cancel_raf;
|
|
|
|
|
|
|
|
|
|
let start_time = 0;
|
|
|
|
|
let end_time = 0;
|
|
|
|
|
|
|
|
|
|
const current_group = transition_group;
|
|
|
|
|
if (rx & tx.outro) current_group.r++;
|
|
|
|
|
|
|
|
|
|
let cancel_raf;
|
|
|
|
|
add_measure_callback(() => {
|
|
|
|
|
if (null === (config = fn(this, params))) return noop;
|
|
|
|
|
const to = this.getBoundingClientRect();
|
|
|
|
|
if (from.top === to.top && from.left === to.left && from.right === to.right && from.bottom === to.bottom) return noop;
|
|
|
|
|
const config = fn(this, { from, to }, params);
|
|
|
|
|
return (current_frame_time) => {
|
|
|
|
|
if (false === running) return;
|
|
|
|
|
const { delay = 0, duration = 300, easing, tick, css }: CssTransitionConfig = config;
|
|
|
|
|
const end_time = current_frame_time + delay + duration;
|
|
|
|
|
const runner = (fn) => reversed(fn, true, easing);
|
|
|
|
|
if (css) cancel_css = animate_css(this, runner(css), duration, delay);
|
|
|
|
|
cancel_raf = tick ? setTweenTimeout(stop, end_time, runner(tick), duration) : setFrameTimeout(stop, end_time);
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
const stop = () => {
|
|
|
|
|
if (false === running) return;
|
|
|
|
|
else running = false;
|
|
|
|
|
if (cancel_css) cancel_css();
|
|
|
|
|
if (cancel_raf) cancel_raf();
|
|
|
|
|
}
|
|
|
|
|
return stop
|
|
|
|
|
});
|
|
|
|
|
export const run_in = /*#__PURE__*/ methodify(function (this: HTMLElement, fn: CustomTransitionFunction, params: CssTransitionConfig = {}) {
|
|
|
|
|
let config;
|
|
|
|
|
let running = true;
|
|
|
|
|
let cancel_css;
|
|
|
|
|
let cancel_raf;
|
|
|
|
|
let end_time;
|
|
|
|
|
add_measure_callback(() => {
|
|
|
|
|
config = fn(this, params);
|
|
|
|
|
return (current_frame_time) => {
|
|
|
|
|
let { delay = 0, duration = 300, easing, tick, css, strategy = EasingStrategy.balanced }: CssTransitionConfig =
|
|
|
|
|
"function" === typeof config ? (config = config()) : config;
|
|
|
|
|
const solver = EasingStrategy.balanced === strategy ? reversed : mirrored;
|
|
|
|
|
const runner = (fn) => solver(fn, true, easing);
|
|
|
|
|
end_time = current_frame_time + delay + duration;
|
|
|
|
|
this.dispatchEvent(custom_event(TransitionEvent.introstart));
|
|
|
|
|
if (css) cancel_css = animate_css(this, runner(css), duration, delay);
|
|
|
|
|
cancel_raf = tick ? setTweenTimeout(stop, end_time, runner(tick), duration ) : setFrameTimeout(stop, end_time);
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
const stop = (t?: number) => {
|
|
|
|
|
if (false === running) return;
|
|
|
|
|
else running = false;
|
|
|
|
|
if (cancel_css) cancel_css();
|
|
|
|
|
if (cancel_raf) cancel_raf();
|
|
|
|
|
if (t && t >= end_time) this.dispatchEvent(custom_event(TransitionEvent.introend));
|
|
|
|
|
}
|
|
|
|
|
return stop
|
|
|
|
|
});
|
|
|
|
|
export const run_out = /*#__PURE__*/ methodify(function (this: HTMLElement, fn: CustomTransitionFunction, params: CssTransitionConfig = {}) {
|
|
|
|
|
let config;
|
|
|
|
|
let running = true;
|
|
|
|
|
let cancel_css;
|
|
|
|
|
let cancel_raf;
|
|
|
|
|
let end_time;
|
|
|
|
|
const current_group = transition_group;
|
|
|
|
|
current_group.r++;
|
|
|
|
|
add_measure_callback(() => {
|
|
|
|
|
config = fn(this, params);
|
|
|
|
|
return (current_frame_time) => {
|
|
|
|
|
let { delay = 0, duration = 300, easing, tick, css, strategy = EasingStrategy.balanced }: CssTransitionConfig =
|
|
|
|
|
"function" === typeof config ? (config = config()) : config;
|
|
|
|
|
const solver = EasingStrategy.balanced === strategy ? reversed : mirrored;
|
|
|
|
|
const runner = (fn) => solver(fn, false, easing);
|
|
|
|
|
end_time = current_frame_time + delay + duration;
|
|
|
|
|
current_group.t = Math.max(end_time, current_group.t);
|
|
|
|
|
if (current_group.s.push(stop) === current_group.r) {
|
|
|
|
|
setFrameTimeout((t) => {
|
|
|
|
|
for (let i = 0; i < current_group.s.length; i++) {
|
|
|
|
|
current_group.s[i](t);
|
|
|
|
|
}
|
|
|
|
|
}, current_group.t);
|
|
|
|
|
}
|
|
|
|
|
this.dispatchEvent(custom_event(TransitionEvent.outrostart));
|
|
|
|
|
if (css) cancel_css = animate_css(this, runner(css), duration, delay);
|
|
|
|
|
if (tick) cancel_raf = setTweenTimeout(noop, end_time, runner(tick), duration);
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
const stop = (t?: number) => {
|
|
|
|
|
if (1 === t && "tick" in config) config.tick(1, 0);
|
|
|
|
|
if (false === running) return;
|
|
|
|
|
else running = false;
|
|
|
|
|
if (cancel_css) cancel_css();
|
|
|
|
|
if (cancel_raf) cancel_raf();
|
|
|
|
|
if (t && t >= end_time) {
|
|
|
|
|
if ("tick" in config) config.tick(0, 1);
|
|
|
|
|
this.dispatchEvent(custom_event(TransitionEvent.outroend));
|
|
|
|
|
}
|
|
|
|
|
if(!--current_group.r) for (let i = 0, { c } = current_group, r = t === void 0;i < c.length;i++) c[i](r);
|
|
|
|
|
}
|
|
|
|
|
return stop
|
|
|
|
|
});
|
|
|
|
|
export const create_bidirectional_transition = /*#__PURE__*/ methodify(function(this: HTMLElement, fn: CustomTransitionFunction, params?: CssTransitionConfig) {
|
|
|
|
|
let transition_delay;
|
|
|
|
|
let pending = 0;
|
|
|
|
|
let prev;
|
|
|
|
|
|
|
|
|
|
let { delay = 0, duration = 300, easing, tick, css, strategy = 'reverse' }: CssTransitionConfig =
|
|
|
|
|
'function' === typeof config ? (config = config()) : config;
|
|
|
|
|
const u = (new_fn = fn, new_params = params) => {
|
|
|
|
|
let test_config;
|
|
|
|
|
if (typeof (test_config = (fn = new_fn)(this,(params = new_params))) === "function") test_config = test_config();
|
|
|
|
|
transition_delay = test_config.delay || 0.0;
|
|
|
|
|
}
|
|
|
|
|
u();
|
|
|
|
|
|
|
|
|
|
const solver = 'reverse' === strategy ? reversed : mirrored;
|
|
|
|
|
const runner = (fn) => solver(fn, rx, easing, elapsed_ratio, 1);
|
|
|
|
|
const run_transition = (is_intro:boolean, cancel_previous?) => {
|
|
|
|
|
const delayed_start = transition_delay && cancel_previous && pending;
|
|
|
|
|
|
|
|
|
|
if (rx & tx.bidirectional) {
|
|
|
|
|
if (-1 !== delay_left) delay = delay_left;
|
|
|
|
|
if (solver === reversed) duration -= elapsed_duration;
|
|
|
|
|
else if (solver === mirrored) delay -= elapsed_duration;
|
|
|
|
|
}
|
|
|
|
|
let config;
|
|
|
|
|
|
|
|
|
|
end_time = (start_time = current_frame_time + delay) + duration;
|
|
|
|
|
let running = true;
|
|
|
|
|
let cancelled = false;
|
|
|
|
|
|
|
|
|
|
if (0 === (rx & tx.animation)) {
|
|
|
|
|
this.dispatchEvent(custom_event(`${rx & tx.intro ? 'in' : 'ou'}trostart`));
|
|
|
|
|
}
|
|
|
|
|
let cancel_css;
|
|
|
|
|
let cancel_raf;
|
|
|
|
|
|
|
|
|
|
if (css) cancel_css = animate_css(this, runner(css), duration, delay);
|
|
|
|
|
let start_time = 0.0;
|
|
|
|
|
let end_time = 0.0;
|
|
|
|
|
let ratio_left = 0.0;
|
|
|
|
|
|
|
|
|
|
if (rx & tx.outro) {
|
|
|
|
|
if (current_group.s.push(stop) === current_group.r) {
|
|
|
|
|
setFrameTimeout((t) => {
|
|
|
|
|
for (let i = 0; i < current_group.s.length; i++) current_group.s[i](t);
|
|
|
|
|
}, Math.max(end_time, current_group.t));
|
|
|
|
|
} else {
|
|
|
|
|
current_group.t = Math.max(end_time, current_group.t);
|
|
|
|
|
}
|
|
|
|
|
if (tick) cancel_raf = setTweenTimeout(noop, end_time, runner(tick), duration, true);
|
|
|
|
|
} else {
|
|
|
|
|
cancel_raf = tick ? setTweenTimeout(stop, end_time, runner(tick), duration) : setFrameTimeout(stop, end_time);
|
|
|
|
|
const current_group = transition_group;
|
|
|
|
|
if (!is_intro) current_group.r++;
|
|
|
|
|
|
|
|
|
|
const run = (flush_frame_time) => {
|
|
|
|
|
pending++;
|
|
|
|
|
const [prev_duration_left, prev_ratio_left] = ((cancel_previous && cancel_previous(flush_frame_time)) || [0.0, 0.0] );
|
|
|
|
|
ratio_left = prev_ratio_left;
|
|
|
|
|
return () => {
|
|
|
|
|
config = fn(this, params);
|
|
|
|
|
return (current_frame_time) => {
|
|
|
|
|
let { tick, css, duration = 300.0, delay = 0.0, easing, strategy = EasingStrategy.balanced }: CssTransitionConfig =
|
|
|
|
|
"function" === typeof config ? (config = config()) : config;
|
|
|
|
|
const solver = EasingStrategy.balanced === strategy ? reversed : mirrored;
|
|
|
|
|
const runner = (fn) => solver(fn, is_intro, easing, ratio_left, 1);
|
|
|
|
|
if (delayed_start) delay = 0;
|
|
|
|
|
if (solver === reversed) duration -= prev_duration_left;
|
|
|
|
|
else if (solver === mirrored) delay -= prev_duration_left;
|
|
|
|
|
start_time = current_frame_time + delay;
|
|
|
|
|
end_time = start_time + duration;
|
|
|
|
|
if (cancelled) return;
|
|
|
|
|
if (!is_intro) {
|
|
|
|
|
current_group.t = Math.max(end_time, current_group.t);
|
|
|
|
|
if (current_group.s.push(stop) === current_group.r) {
|
|
|
|
|
setFrameTimeout((t) => {
|
|
|
|
|
for (let i = 0; i < current_group.s.length; i++) {
|
|
|
|
|
current_group.s[i](t);
|
|
|
|
|
}
|
|
|
|
|
}, current_group.t);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
this.dispatchEvent(custom_event(is_intro ? TransitionEvent.introstart : TransitionEvent.outrostart));
|
|
|
|
|
if (css) cancel_css = animate_css(this, runner(css), duration, delay);
|
|
|
|
|
if (tick) cancel_raf = setTweenTimeout(is_intro ? stop : noop, end_time, runner(tick), duration);
|
|
|
|
|
else if (is_intro) cancel_raf = setFrameTimeout(stop, end_time);
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const cancel = (t) => {
|
|
|
|
|
if (!cancelled) {
|
|
|
|
|
pending--;
|
|
|
|
|
cancelled = true;
|
|
|
|
|
if (cancel_css) cancel_css();
|
|
|
|
|
if (cancel_raf) cancel_raf();
|
|
|
|
|
if (1 === t && cancel_previous) cancel_previous();
|
|
|
|
|
}
|
|
|
|
|
if (!config) return;
|
|
|
|
|
const duration_left = end_time - t;
|
|
|
|
|
const next_ratio_left = 1 - duration_left / (end_time - start_time);
|
|
|
|
|
return duration_left > 0 && next_ratio_left > 0 && [duration_left, (1 - ratio_left) * (1 - (config.easing || ((v) => v))(next_ratio_left))];
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const stop: StopResetReverseFn = (t?: number | 1 | -1) => {
|
|
|
|
|
if (t === 1 && rx & tx.outro && 0 === (rx & tx.bidirectional) && 'tick' in config) config.tick(1, 0);
|
|
|
|
|
const stop: StopResetReverseFn = (t?: number | -1 | 1) => {
|
|
|
|
|
if (running) {
|
|
|
|
|
running = false;
|
|
|
|
|
if (config) {
|
|
|
|
|
if (t >= end_time) {
|
|
|
|
|
if (!is_intro && "tick" in config) config.tick(0, 1);
|
|
|
|
|
if (pending === 1) cancel(t);
|
|
|
|
|
this.dispatchEvent(custom_event(is_intro ? TransitionEvent.introend : TransitionEvent.outroend));
|
|
|
|
|
}
|
|
|
|
|
if (!is_intro) {
|
|
|
|
|
if (!--current_group.r) {
|
|
|
|
|
for (let i = 0, { c } = current_group, r = t === 1; i < c.length; i++) c[i](r);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (t === -1) return run_transition(!is_intro, cancel);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (false === running) return;
|
|
|
|
|
else running = false;
|
|
|
|
|
if (delayed_start) {
|
|
|
|
|
setFrameTimeout((t) => {
|
|
|
|
|
add_measure_callback(run(t));
|
|
|
|
|
tick();
|
|
|
|
|
}, frame.time + transition_delay);
|
|
|
|
|
} else {
|
|
|
|
|
add_measure_callback(run(frame.time));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (cancel_css) cancel_css();
|
|
|
|
|
if (cancel_raf) cancel_raf(rx & tx.outro && t >= end_time);
|
|
|
|
|
|
|
|
|
|
if (rx & tx.animation) return;
|
|
|
|
|
|
|
|
|
|
if (t >= end_time) this.dispatchEvent(custom_event(`${rx & tx.intro ? 'in' : 'ou'}troend`));
|
|
|
|
|
|
|
|
|
|
if (rx & tx.outro && !--current_group.r)
|
|
|
|
|
for (let i = 0; i < current_group.c.length; i++) current_group.c[i](t === void 0);
|
|
|
|
|
|
|
|
|
|
if (0 === (rx & tx.bidirectional)) return;
|
|
|
|
|
|
|
|
|
|
if (-1 === t)
|
|
|
|
|
return (
|
|
|
|
|
(t = now()) < end_time &&
|
|
|
|
|
run_transition(
|
|
|
|
|
this,
|
|
|
|
|
() => config,
|
|
|
|
|
rx ^ tx.reverse,
|
|
|
|
|
params,
|
|
|
|
|
end_time - t,
|
|
|
|
|
start_time > t ? start_time - t : 0,
|
|
|
|
|
(1 - elapsed_ratio) * (1 - (config.easing || ((v) => v))(1 - (end_time - t) / (end_time - start_time)))
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
else running_bidi.delete(this);
|
|
|
|
|
return stop
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return stop;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const running_bidi: Map<HTMLElement, StopResetReverseFn> = new Map();
|
|
|
|
|
export const run_bidirectional_transition = /*#__PURE__*/ methodify(
|
|
|
|
|
function bidirectional(this: HTMLElement, fn: TransitionFn, rx: tx.intro | tx.outro, params: any ) {
|
|
|
|
|
let cancel;
|
|
|
|
|
running_bidi.set(
|
|
|
|
|
this,
|
|
|
|
|
(cancel =
|
|
|
|
|
(running_bidi.has(this) && running_bidi.get(this)(-1)) || run_transition(this, fn, rx | tx.bidirectional, params))
|
|
|
|
|
);
|
|
|
|
|
return cancel;
|
|
|
|
|
return {
|
|
|
|
|
u,
|
|
|
|
|
o() {
|
|
|
|
|
prev = prev ? prev(-1) : run_transition(false);
|
|
|
|
|
},
|
|
|
|
|
i() {
|
|
|
|
|
prev = prev ? prev(-1) : run_transition(true);
|
|
|
|
|
},
|
|
|
|
|
d() {
|
|
|
|
|
prev = prev(1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
export const run_duration = (duration, value1, value2?): number =>
|
|
|
|
|
typeof duration === 'function' ? duration(value1, value2) : duration;
|
|
|
|
|
typeof duration === "function" ? duration(value1, value2) : duration;
|
|
|
|
|