remove some unused code

blockless
Rich Harris 2 years ago
parent 34f31986ff
commit 26e9c8ca18

@ -1,32 +1,10 @@
import { EACH_IS_ANIMATED, EACH_IS_CONTROLLED } from '../../constants.js';
import { noop, run_all } from '../common.js'; import { noop, run_all } from '../common.js';
import {
AWAIT_BLOCK,
DYNAMIC_COMPONENT_BLOCK,
EACH_BLOCK,
EACH_ITEM_BLOCK,
IF_BLOCK,
KEY_BLOCK,
ROOT_BLOCK
} from './constants.js';
import { destroy_each_item_block, get_first_element } from './dom/blocks/each.js'; import { destroy_each_item_block, get_first_element } from './dom/blocks/each.js';
import { schedule_raf_task } from './dom/task.js'; import { schedule_raf_task } from './dom/task.js';
import { append_child, empty } from './operations.js'; import { append_child, empty } from './operations.js';
import { import { managed_effect, managed_pre_effect, user_effect } from './reactivity/computations.js';
effect,
managed_effect,
managed_pre_effect,
user_effect
} from './reactivity/computations.js';
import { run_transitions } from './render.js'; import { run_transitions } from './render.js';
import { import { current_effect, destroy_signal, mark_subtree_inert, untrack } from './runtime.js';
current_block,
current_effect,
destroy_signal,
execute_effect,
mark_subtree_inert,
untrack
} from './runtime.js';
import { raf } from './timing.js'; import { raf } from './timing.js';
const active_tick_animations = new Set(); const active_tick_animations = new Set();
@ -259,246 +237,9 @@ function handle_raf(time) {
} }
} }
/**
* @param {{(t: number): number;(t: number): number;(arg0: number): any;}} easing_fn
* @param {((t: number, u: number) => string)} css_fn
* @param {number} duration
* @param {string} direction
* @param {boolean} reverse
*/
function create_keyframes(easing_fn, css_fn, duration, direction, reverse) {
/** @type {Keyframe[]} */
const keyframes = [];
// We need at least two frames
const frame_time = 16.666;
const max_duration = Math.max(duration, frame_time);
// Have a keyframe every fame for 60 FPS
for (let i = 0; i <= max_duration; i += frame_time) {
let time;
if (i + frame_time > max_duration) {
time = 1;
} else if (i === 0) {
time = 0;
} else {
time = i / max_duration;
}
let t = easing_fn(time);
if (reverse) {
t = 1 - t;
}
keyframes.push(css_to_keyframe(css_fn(t, 1 - t)));
}
if (direction === 'out' || reverse) {
keyframes.reverse();
}
return keyframes;
}
/** @param {number} t */ /** @param {number} t */
const linear = (t) => t; const linear = (t) => t;
/**
* @param {HTMLElement} dom
* @param {() => import('./types.js').TransitionPayload} init
* @param {'in' | 'out' | 'both' | 'key'} direction
* @param {import('./types.js').EffectSignal} effect
* @returns {import('./types.js').Transition}
*/
function create_transition(dom, init, direction, effect) {
let curr_direction = 'in';
/** @type {Array<() => void>} */
let subs = [];
/** @type {null | Animation | TickAnimation} */
let animation = null;
let cancelled = false;
const create_animation = () => {
let payload = /** @type {import('./types.js').TransitionPayload} */ (transition.p);
if (typeof payload === 'function') {
// @ts-ignore
payload = payload({ direction: curr_direction });
}
if (payload == null) {
return;
}
const duration = payload.duration ?? 300;
const delay = payload.delay ?? 0;
const css_fn = payload.css;
const tick_fn = payload.tick;
const easing_fn = payload.easing || linear;
if (typeof tick_fn === 'function') {
animation = new TickAnimation(tick_fn, duration, delay, direction === 'out');
} else {
const keyframes =
typeof css_fn === 'function'
? create_keyframes(easing_fn, css_fn, duration, direction, false)
: [];
animation = dom.animate(keyframes, {
duration,
endDelay: delay,
delay,
fill: 'both'
});
}
animation.pause();
animation.onfinish = () => {
const is_outro = curr_direction === 'out';
/** @type {Animation | TickAnimation} */ (animation).cancel();
if (is_outro) {
run_all(subs);
subs = [];
}
dispatch_event(dom, is_outro ? 'outroend' : 'introend');
};
};
/** @type {import('./types.js').Transition} */
const transition = {
e: effect,
i: init,
// payload
p: null,
// finished
/** @param {() => void} fn */
f(fn) {
subs.push(fn);
},
in() {
const needs_reverse = curr_direction !== 'in';
curr_direction = 'in';
if (animation === null || cancelled) {
cancelled = false;
create_animation();
}
if (animation === null) {
transition.x();
} else {
dispatch_event(dom, 'introstart');
if (needs_reverse) {
/** @type {Animation | TickAnimation} */ (animation).reverse();
}
/** @type {Animation | TickAnimation} */ (animation).play();
}
},
// out
o() {
// @ts-ignore
const has_keyed_transition = dom.__animate;
// If we're outroing an element that has an animation, then we need to fix
// its position to ensure it behaves nicely without causing layout shift.
if (has_keyed_transition) {
const style = getComputedStyle(dom);
const position = style.position;
if (position !== 'absolute' && position !== 'fixed') {
const { width, height } = style;
const a = dom.getBoundingClientRect();
dom.style.position = 'absolute';
dom.style.width = width;
dom.style.height = height;
const b = dom.getBoundingClientRect();
if (a.left !== b.left || a.top !== b.top) {
const translate = `translate(${a.left - b.left}px, ${a.top - b.top}px)`;
const existing_transform = style.transform;
if (existing_transform === 'none') {
dom.style.transform = translate;
} else {
// Previously, in the Svelte 4, we'd just apply the transform the the DOM element. However,
// because we're now using Web Animations, we can't do that as it won't work properly if the
// animation is also making use of the same transformations. So instead, we apply an
// instantaneous animation and pause it on the first frame, just applying the same behavior.
// We also need to take into consideration matrix transforms and how they might combine with
// an existing behavior that is already in progress (such as scale).
// > Follow the white rabbit.
const transform = existing_transform.startsWith('matrix(1,')
? translate
: `matrix(1,0,0,1,0,0)`;
const frame = {
transform
};
const animation = dom.animate([frame, frame], { duration: 1 });
animation.pause();
}
}
}
}
const needs_reverse = direction === 'both' && curr_direction !== 'out';
curr_direction = 'out';
if (animation === null || cancelled) {
cancelled = false;
create_animation();
}
if (animation === null) {
transition.x();
} else {
dispatch_event(dom, 'outrostart');
if (needs_reverse) {
const payload = transition.p;
const current_animation = /** @type {Animation} */ (animation);
// If we are working with CSS animations, then before we call reverse, we also need to ensure
// that we reverse the easing logic. To do this we need to re-create the keyframes so they're
// in reverse with easing properly reversed too.
if (
payload !== null &&
payload.css !== undefined &&
current_animation.playState === 'idle'
) {
const duration = payload.duration ?? 300;
const css_fn = payload.css;
const easing_fn = payload.easing || linear;
const keyframes = create_keyframes(easing_fn, css_fn, duration, direction, true);
const effect = current_animation.effect;
if (effect !== null) {
// @ts-ignore
effect.setKeyframes(keyframes);
}
}
/** @type {Animation | TickAnimation} */ (animation).reverse();
} else {
/** @type {Animation | TickAnimation} */ (animation).play();
}
}
},
// cancel
c() {
if (animation !== null) {
/** @type {Animation | TickAnimation} */ (animation).cancel();
}
cancelled = true;
},
// cleanup
x() {
run_all(subs);
subs = [];
},
r: direction,
d: dom
};
return transition;
}
/**
* @param {import('./types.js').Block} block
* @returns {boolean}
*/
function is_transition_block(block) {
const type = block.t;
return (
type === IF_BLOCK ||
type === EACH_ITEM_BLOCK ||
type === KEY_BLOCK ||
type === AWAIT_BLOCK ||
type === DYNAMIC_COMPONENT_BLOCK ||
(type === EACH_BLOCK && block.v.length === 0)
);
}
/** /**
* @template P * @template P
* @param {HTMLElement} element * @param {HTMLElement} element
@ -640,96 +381,3 @@ export function trigger_transitions(transitions, target_direction, from) {
}, false); }, false);
} }
} }
/**
* @this {import('./types.js').IfBlock}
* @param {import('./types.js').Transition} transition
* @returns {void}
*/
function if_block_transition(transition) {
const block = this;
// block.value === true
if (block.v) {
const consequent_transitions = (block.c ??= new Set());
consequent_transitions.add(transition);
transition.f(() => {
const c = /** @type {Set<import('./types.js').Transition>} */ (consequent_transitions);
c.delete(transition);
// If the block has changed to falsy and has transitions
if (!block.v && c.size === 0) {
const consequent_effect = block.ce;
execute_effect(/** @type {import('./types.js').EffectSignal} */ (consequent_effect));
}
});
} else {
const alternate_transitions = (block.a ??= new Set());
alternate_transitions.add(transition);
transition.f(() => {
const a = /** @type {Set<import('./types.js').Transition>} */ (alternate_transitions);
a.delete(transition);
// If the block has changed to truthy and has transitions
if (block.v && a.size === 0) {
const alternate_effect = block.ae;
execute_effect(/** @type {import('./types.js').EffectSignal} */ (alternate_effect));
}
});
}
}
/**
* @this {import('./types.js').EachItemBlock}
* @param {import('./types.js').Transition} transition
* @returns {void}
*/
function each_item_transition(transition) {
const block = this;
const each_block = block.p;
const is_controlled = (each_block.f & EACH_IS_CONTROLLED) !== 0;
// Disable optimization
if (is_controlled) {
const anchor = empty();
each_block.f ^= EACH_IS_CONTROLLED;
append_child(/** @type {Element} */ (each_block.a), anchor);
each_block.a = anchor;
}
if (transition.r === 'key' && (each_block.f & EACH_IS_ANIMATED) === 0) {
each_block.f |= EACH_IS_ANIMATED;
}
const transitions = (block.s ??= new Set());
transition.f(() => {
transitions.delete(transition);
if (transition.r !== 'key') {
for (let other of transitions) {
const type = other.r;
if (type === 'key' || type === 'in') {
transitions.delete(other);
}
}
if (transitions.size === 0) {
block.s = null;
destroy_each_item_block(block, null, true);
}
}
});
transitions.add(transition);
}
/**
*
* @param {import('./types.js').EachItemBlock} block
* @param {Set<import('./types.js').Transition>} transitions
*/
function each_item_animate(block, transitions) {
const from_dom = /** @type {Element} */ (get_first_element(block));
const from = from_dom.getBoundingClientRect();
// Cancel any existing key transitions
for (const transition of transitions) {
const type = transition.r;
if (type === 'key') {
transition.c();
}
}
schedule_raf_task(() => {
trigger_transitions(transitions, 'key', from);
});
}

Loading…
Cancel
Save