local transitions

blockless
Rich Harris 2 years ago
parent 3be1b21b79
commit dc424a07ab

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

@ -45,7 +45,8 @@ function create_computation_signal(flags, value, block) {
v: value, v: value,
w: 0, w: 0,
x: null, x: null,
y: null y: null,
parent: current_effect
}; };
if (DEV) { if (DEV) {
@ -264,16 +265,10 @@ export function derived_safe_equal(fn) {
* @param {() => void} done * @param {() => void} done
*/ */
export function pause_effect(effect, 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[]} */ /** @type {import('../types.js').TransitionObject[]} */
const transitions = []; const transitions = [];
pause_children(effect, transitions); pause_children(effect, transitions, true);
let remaining = transitions.length; let remaining = transitions.length;
@ -297,17 +292,27 @@ export function pause_effect(effect, done) {
/** /**
* @param {import('../types.js').BlockEffect} effect * @param {import('../types.js').BlockEffect} effect
* @param {import('../types.js').TransitionObject[]} transitions * @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; effect.f |= INERT;
if ((effect.f & DERIVED) === 0 && typeof effect.v === 'function') {
effect.v();
}
if (effect.out) { 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) { if (effect.r) {
for (const child of 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 * @param {import('../types.js').BlockEffect} effect
*/ */
export function resume_effect(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) { if ((effect.f & DERIVED) === 0 && (effect.f & MANAGED) === 0) {
execute_effect(/** @type {import('../types.js').EffectSignal} */ (effect)); execute_effect(/** @type {import('../types.js').EffectSignal} */ (effect));
} }
if (effect.r) { if (effect.r) {
for (const child of 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) { if (effect.in) {
for (const transition of effect.in) { for (const transition of effect.in) {
transition.to(1); 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') { if (direction === 'in' || direction === 'both') {
(effect.in ??= []).push(transition); (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(() => { user_effect(() => {
untrack(() => transition.to(1)); untrack(() => transition.to(1));
}); });

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

Loading…
Cancel
Save