local transitions

blockless
Rich Harris 2 years ago
parent 3be1b21b79
commit dc424a07ab

@ -6,8 +6,7 @@ import {
} from '../../hydration.js';
import { remove } from '../../reconciler.js';
import { pause_effect, render_effect, resume_effect } from '../../reactivity/computations.js';
import { current_effect } from '../../runtime.js';
import { BRANCH_EFFECT, RENDER_EFFECT } from '../../constants.js';
import { BRANCH_EFFECT } from '../../constants.js';
/**
* @param {Comment} anchor_node

@ -45,7 +45,8 @@ function create_computation_signal(flags, value, block) {
v: value,
w: 0,
x: null,
y: null
y: null,
parent: current_effect
};
if (DEV) {
@ -264,16 +265,10 @@ export function derived_safe_equal(fn) {
* @param {() => void} done
*/
export function pause_effect(effect, done) {
if ((effect.f & INERT) !== 0) return;
if ((effect.f & DERIVED) === 0 && typeof effect.v === 'function') {
effect.v();
}
/** @type {import('../types.js').TransitionObject[]} */
const transitions = [];
pause_children(effect, transitions);
pause_children(effect, transitions, true);
let remaining = transitions.length;
@ -297,17 +292,27 @@ export function pause_effect(effect, done) {
/**
* @param {import('../types.js').BlockEffect} effect
* @param {import('../types.js').TransitionObject[]} transitions
* @param {boolean} local
*/
function pause_children(effect, transitions) {
function pause_children(effect, transitions, local) {
if ((effect.f & INERT) !== 0) return;
effect.f |= INERT;
if ((effect.f & DERIVED) === 0 && typeof effect.v === 'function') {
effect.v();
}
if (effect.out) {
transitions.push(...effect.out); // TODO differentiate between global and local
for (const transition of effect.out) {
if (transition.global || local) {
transitions.push(transition);
}
}
}
if (effect.r) {
for (const child of effect.r) {
pause_children(child, transitions);
pause_children(child, transitions, false);
}
}
}
@ -339,13 +344,21 @@ export function destroy_effect(effect) {
* @param {import('../types.js').BlockEffect} effect
*/
export function resume_effect(effect) {
resume_children(effect, true);
}
/**
* @param {import('../types.js').BlockEffect} effect
* @param {boolean} local
*/
function resume_children(effect, local) {
if ((effect.f & DERIVED) === 0 && (effect.f & MANAGED) === 0) {
execute_effect(/** @type {import('../types.js').EffectSignal} */ (effect));
}
if (effect.r) {
for (const child of effect.r) {
resume_effect(child);
resume_children(child, false);
}
}
@ -353,7 +366,9 @@ export function resume_effect(effect) {
if (effect.in) {
for (const transition of effect.in) {
if (transition.global || local) {
transition.to(1);
}
}
}
}

@ -579,6 +579,9 @@ export function schedule_effect(signal, sync) {
}
}
}
// temporary, we need to neaten up the types
signal.ran = true;
}
/**

@ -358,7 +358,12 @@ export function bind_transition(element, get_fn, get_params, direction, global)
if (direction === 'in' || direction === 'both') {
(effect.in ??= []).push(transition);
if (run_transitions) {
// if this is a local transition, we only want to run it if the parent (block) effect's
// parent (branch) effect is where the state change happened. we can determine that by
// looking at whether the branch effect is currently initializing
const should_run = run_transitions && (global || effect.parent.ran);
if (should_run) {
user_effect(() => {
untrack(() => transition.to(1));
});

@ -116,12 +116,14 @@ export type ComputationSignal<V = unknown> = {
l: number;
/** write version: used for unowned signals to track if their depdendencies are dirty or not **/
w: number;
parent: Signal | null;
};
export type BlockEffect<V = unknown> = ComputationSignal<V> & {
in?: TransitionObject[];
out?: TransitionObject[];
dom?: TemplateNode | Array<TemplateNode>;
ran?: boolean;
};
export type Signal<V = unknown> = SourceSignal<V> | ComputationSignal<V>;

Loading…
Cancel
Save