init commit
This commit is contained in:
461
node_modules/svelte/src/runtime/internal/transitions.js
generated
vendored
Normal file
461
node_modules/svelte/src/runtime/internal/transitions.js
generated
vendored
Normal file
@@ -0,0 +1,461 @@
|
||||
import { identity as linear, is_function, noop, run_all } from './utils.js';
|
||||
import { now } from './environment.js';
|
||||
import { loop } from './loop.js';
|
||||
import { create_rule, delete_rule } from './style_manager.js';
|
||||
import { custom_event } from './dom.js';
|
||||
import { add_render_callback } from './scheduler.js';
|
||||
|
||||
/**
|
||||
* @type {Promise<void> | null}
|
||||
*/
|
||||
let promise;
|
||||
|
||||
/**
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
function wait() {
|
||||
if (!promise) {
|
||||
promise = Promise.resolve();
|
||||
promise.then(() => {
|
||||
promise = null;
|
||||
});
|
||||
}
|
||||
return promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element} node
|
||||
* @param {INTRO | OUTRO | boolean} direction
|
||||
* @param {'start' | 'end'} kind
|
||||
* @returns {void}
|
||||
*/
|
||||
function dispatch(node, direction, kind) {
|
||||
node.dispatchEvent(custom_event(`${direction ? 'intro' : 'outro'}${kind}`));
|
||||
}
|
||||
|
||||
const outroing = new Set();
|
||||
|
||||
/**
|
||||
* @type {Outro}
|
||||
*/
|
||||
let outros;
|
||||
|
||||
/**
|
||||
* @returns {void} */
|
||||
export function group_outros() {
|
||||
outros = {
|
||||
r: 0,
|
||||
c: [],
|
||||
p: outros // parent group
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {void} */
|
||||
export function check_outros() {
|
||||
if (!outros.r) {
|
||||
run_all(outros.c);
|
||||
}
|
||||
outros = outros.p;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('./private.js').Fragment} block
|
||||
* @param {0 | 1} [local]
|
||||
* @returns {void}
|
||||
*/
|
||||
export function transition_in(block, local) {
|
||||
if (block && block.i) {
|
||||
outroing.delete(block);
|
||||
block.i(local);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('./private.js').Fragment} block
|
||||
* @param {0 | 1} local
|
||||
* @param {0 | 1} [detach]
|
||||
* @param {() => void} [callback]
|
||||
* @returns {void}
|
||||
*/
|
||||
export function transition_out(block, local, detach, callback) {
|
||||
if (block && block.o) {
|
||||
if (outroing.has(block)) return;
|
||||
outroing.add(block);
|
||||
outros.c.push(() => {
|
||||
outroing.delete(block);
|
||||
if (callback) {
|
||||
if (detach) block.d(1);
|
||||
callback();
|
||||
}
|
||||
});
|
||||
block.o(local);
|
||||
} else if (callback) {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {import('../transition/public.js').TransitionConfig}
|
||||
*/
|
||||
const null_transition = { duration: 0 };
|
||||
|
||||
/**
|
||||
* @param {Element & ElementCSSInlineStyle} node
|
||||
* @param {TransitionFn} fn
|
||||
* @param {any} params
|
||||
* @returns {{ start(): void; invalidate(): void; end(): void; }}
|
||||
*/
|
||||
export function create_in_transition(node, fn, params) {
|
||||
/**
|
||||
* @type {TransitionOptions} */
|
||||
const options = { direction: 'in' };
|
||||
let config = fn(node, params, options);
|
||||
let running = false;
|
||||
let animation_name;
|
||||
let task;
|
||||
let uid = 0;
|
||||
|
||||
/**
|
||||
* @returns {void} */
|
||||
function cleanup() {
|
||||
if (animation_name) delete_rule(node, animation_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {void} */
|
||||
function go() {
|
||||
const {
|
||||
delay = 0,
|
||||
duration = 300,
|
||||
easing = linear,
|
||||
tick = noop,
|
||||
css
|
||||
} = config || null_transition;
|
||||
if (css) animation_name = create_rule(node, 0, 1, duration, delay, easing, css, uid++);
|
||||
tick(0, 1);
|
||||
const start_time = now() + delay;
|
||||
const end_time = start_time + duration;
|
||||
if (task) task.abort();
|
||||
running = true;
|
||||
add_render_callback(() => dispatch(node, true, 'start'));
|
||||
task = loop((now) => {
|
||||
if (running) {
|
||||
if (now >= end_time) {
|
||||
tick(1, 0);
|
||||
dispatch(node, true, 'end');
|
||||
cleanup();
|
||||
return (running = false);
|
||||
}
|
||||
if (now >= start_time) {
|
||||
const t = easing((now - start_time) / duration);
|
||||
tick(t, 1 - t);
|
||||
}
|
||||
}
|
||||
return running;
|
||||
});
|
||||
}
|
||||
let started = false;
|
||||
return {
|
||||
start() {
|
||||
if (started) return;
|
||||
started = true;
|
||||
delete_rule(node);
|
||||
if (is_function(config)) {
|
||||
config = config(options);
|
||||
wait().then(go);
|
||||
} else {
|
||||
go();
|
||||
}
|
||||
},
|
||||
invalidate() {
|
||||
started = false;
|
||||
},
|
||||
end() {
|
||||
if (running) {
|
||||
cleanup();
|
||||
running = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element & ElementCSSInlineStyle} node
|
||||
* @param {TransitionFn} fn
|
||||
* @param {any} params
|
||||
* @returns {{ end(reset: any): void; }}
|
||||
*/
|
||||
export function create_out_transition(node, fn, params) {
|
||||
/** @type {TransitionOptions} */
|
||||
const options = { direction: 'out' };
|
||||
let config = fn(node, params, options);
|
||||
let running = true;
|
||||
let animation_name;
|
||||
const group = outros;
|
||||
group.r += 1;
|
||||
/** @type {boolean} */
|
||||
let original_inert_value;
|
||||
|
||||
/**
|
||||
* @returns {void} */
|
||||
function go() {
|
||||
const {
|
||||
delay = 0,
|
||||
duration = 300,
|
||||
easing = linear,
|
||||
tick = noop,
|
||||
css
|
||||
} = config || null_transition;
|
||||
|
||||
if (css) animation_name = create_rule(node, 1, 0, duration, delay, easing, css);
|
||||
|
||||
const start_time = now() + delay;
|
||||
const end_time = start_time + duration;
|
||||
add_render_callback(() => dispatch(node, false, 'start'));
|
||||
|
||||
if ('inert' in node) {
|
||||
original_inert_value = /** @type {HTMLElement} */ (node).inert;
|
||||
node.inert = true;
|
||||
}
|
||||
|
||||
loop((now) => {
|
||||
if (running) {
|
||||
if (now >= end_time) {
|
||||
tick(0, 1);
|
||||
dispatch(node, false, 'end');
|
||||
if (!--group.r) {
|
||||
// this will result in `end()` being called,
|
||||
// so we don't need to clean up here
|
||||
run_all(group.c);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (now >= start_time) {
|
||||
const t = easing((now - start_time) / duration);
|
||||
tick(1 - t, t);
|
||||
}
|
||||
}
|
||||
return running;
|
||||
});
|
||||
}
|
||||
|
||||
if (is_function(config)) {
|
||||
wait().then(() => {
|
||||
// @ts-ignore
|
||||
config = config(options);
|
||||
go();
|
||||
});
|
||||
} else {
|
||||
go();
|
||||
}
|
||||
|
||||
return {
|
||||
end(reset) {
|
||||
if (reset && 'inert' in node) {
|
||||
node.inert = original_inert_value;
|
||||
}
|
||||
if (reset && config.tick) {
|
||||
config.tick(1, 0);
|
||||
}
|
||||
if (running) {
|
||||
if (animation_name) delete_rule(node, animation_name);
|
||||
running = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Element & ElementCSSInlineStyle} node
|
||||
* @param {TransitionFn} fn
|
||||
* @param {any} params
|
||||
* @param {boolean} intro
|
||||
* @returns {{ run(b: 0 | 1): void; end(): void; }}
|
||||
*/
|
||||
export function create_bidirectional_transition(node, fn, params, intro) {
|
||||
/**
|
||||
* @type {TransitionOptions} */
|
||||
const options = { direction: 'both' };
|
||||
let config = fn(node, params, options);
|
||||
let t = intro ? 0 : 1;
|
||||
|
||||
/**
|
||||
* @type {Program | null} */
|
||||
let running_program = null;
|
||||
|
||||
/**
|
||||
* @type {PendingProgram | null} */
|
||||
let pending_program = null;
|
||||
let animation_name = null;
|
||||
|
||||
/** @type {boolean} */
|
||||
let original_inert_value;
|
||||
|
||||
/**
|
||||
* @returns {void} */
|
||||
function clear_animation() {
|
||||
if (animation_name) delete_rule(node, animation_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {PendingProgram} program
|
||||
* @param {number} duration
|
||||
* @returns {Program}
|
||||
*/
|
||||
function init(program, duration) {
|
||||
const d = /** @type {Program['d']} */ (program.b - t);
|
||||
duration *= Math.abs(d);
|
||||
return {
|
||||
a: t,
|
||||
b: program.b,
|
||||
d,
|
||||
duration,
|
||||
start: program.start,
|
||||
end: program.start + duration,
|
||||
group: program.group
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {INTRO | OUTRO} b
|
||||
* @returns {void}
|
||||
*/
|
||||
function go(b) {
|
||||
const {
|
||||
delay = 0,
|
||||
duration = 300,
|
||||
easing = linear,
|
||||
tick = noop,
|
||||
css
|
||||
} = config || null_transition;
|
||||
|
||||
/**
|
||||
* @type {PendingProgram} */
|
||||
const program = {
|
||||
start: now() + delay,
|
||||
b
|
||||
};
|
||||
|
||||
if (!b) {
|
||||
// @ts-ignore todo: improve typings
|
||||
program.group = outros;
|
||||
outros.r += 1;
|
||||
}
|
||||
|
||||
if ('inert' in node) {
|
||||
if (b) {
|
||||
if (original_inert_value !== undefined) {
|
||||
// aborted/reversed outro — restore previous inert value
|
||||
node.inert = original_inert_value;
|
||||
}
|
||||
} else {
|
||||
original_inert_value = /** @type {HTMLElement} */ (node).inert;
|
||||
node.inert = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (running_program || pending_program) {
|
||||
pending_program = program;
|
||||
} else {
|
||||
// if this is an intro, and there's a delay, we need to do
|
||||
// an initial tick and/or apply CSS animation immediately
|
||||
if (css) {
|
||||
clear_animation();
|
||||
animation_name = create_rule(node, t, b, duration, delay, easing, css);
|
||||
}
|
||||
if (b) tick(0, 1);
|
||||
running_program = init(program, duration);
|
||||
add_render_callback(() => dispatch(node, b, 'start'));
|
||||
loop((now) => {
|
||||
if (pending_program && now > pending_program.start) {
|
||||
running_program = init(pending_program, duration);
|
||||
pending_program = null;
|
||||
dispatch(node, running_program.b, 'start');
|
||||
if (css) {
|
||||
clear_animation();
|
||||
animation_name = create_rule(
|
||||
node,
|
||||
t,
|
||||
running_program.b,
|
||||
running_program.duration,
|
||||
0,
|
||||
easing,
|
||||
config.css
|
||||
);
|
||||
}
|
||||
}
|
||||
if (running_program) {
|
||||
if (now >= running_program.end) {
|
||||
tick((t = running_program.b), 1 - t);
|
||||
dispatch(node, running_program.b, 'end');
|
||||
if (!pending_program) {
|
||||
// we're done
|
||||
if (running_program.b) {
|
||||
// intro — we can tidy up immediately
|
||||
clear_animation();
|
||||
} else {
|
||||
// outro — needs to be coordinated
|
||||
if (!--running_program.group.r) run_all(running_program.group.c);
|
||||
}
|
||||
}
|
||||
running_program = null;
|
||||
} else if (now >= running_program.start) {
|
||||
const p = now - running_program.start;
|
||||
t = running_program.a + running_program.d * easing(p / running_program.duration);
|
||||
tick(t, 1 - t);
|
||||
}
|
||||
}
|
||||
return !!(running_program || pending_program);
|
||||
});
|
||||
}
|
||||
}
|
||||
return {
|
||||
run(b) {
|
||||
if (is_function(config)) {
|
||||
wait().then(() => {
|
||||
const opts = { direction: b ? 'in' : 'out' };
|
||||
// @ts-ignore
|
||||
config = config(opts);
|
||||
go(b);
|
||||
});
|
||||
} else {
|
||||
go(b);
|
||||
}
|
||||
},
|
||||
end() {
|
||||
clear_animation();
|
||||
running_program = pending_program = null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/** @typedef {1} INTRO */
|
||||
/** @typedef {0} OUTRO */
|
||||
/** @typedef {{ direction: 'in' | 'out' | 'both' }} TransitionOptions */
|
||||
/** @typedef {(node: Element, params: any, options: TransitionOptions) => import('../transition/public.js').TransitionConfig} TransitionFn */
|
||||
|
||||
/**
|
||||
* @typedef {Object} Outro
|
||||
* @property {number} r
|
||||
* @property {Function[]} c
|
||||
* @property {Object} p
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} PendingProgram
|
||||
* @property {number} start
|
||||
* @property {INTRO|OUTRO} b
|
||||
* @property {Outro} [group]
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} Program
|
||||
* @property {number} a
|
||||
* @property {INTRO|OUTRO} b
|
||||
* @property {1|-1} d
|
||||
* @property {number} duration
|
||||
* @property {number} start
|
||||
* @property {number} end
|
||||
* @property {Outro} [group]
|
||||
*/
|
||||
Reference in New Issue
Block a user