mirror of https://github.com/sveltejs/svelte
So far this is only used in certain conditions, as the full feature set is not implemented yet.pull/3540/head
parent
5d8ca9f07d
commit
4fea0d4383
@ -0,0 +1,189 @@
|
||||
import { destroy_each } from './dom';
|
||||
// import {
|
||||
// transition_in,
|
||||
// transition_out,
|
||||
// group_outros,
|
||||
// check_outros,
|
||||
// } from './transitions';
|
||||
|
||||
type ChangedContext<Context> = {
|
||||
[K in keyof Context]: boolean;
|
||||
};
|
||||
|
||||
interface Fragment<Context> {
|
||||
/** create */
|
||||
c: () => void;
|
||||
|
||||
/** claim */
|
||||
l?: (nodes: Array<Node>) => void;
|
||||
|
||||
/** hydrate */
|
||||
h?: () => void;
|
||||
|
||||
/** mount */
|
||||
m: (target: Node, anchor?: Node | null) => void;
|
||||
|
||||
/** update */
|
||||
p?: (changed: ChangedContext<Context>, context: Context) => void;
|
||||
|
||||
/** intro */
|
||||
i?: () => void;
|
||||
|
||||
/** outro */
|
||||
o?: () => void;
|
||||
|
||||
/** destroy */
|
||||
d: (detaching: boolean) => void;
|
||||
}
|
||||
|
||||
type GetEachValue = (context: unknown) => Array<unknown>;
|
||||
type CreateEachBlock = (context: unknown) => Fragment<unknown>;
|
||||
type CreateElseBlock = CreateEachBlock;
|
||||
type CreateChildContext = (
|
||||
context: unknown,
|
||||
each_value: unknown,
|
||||
i: number
|
||||
) => unknown;
|
||||
|
||||
export class EachBlock {
|
||||
/** each_blocks */
|
||||
private b: Array<Fragment<unknown>>;
|
||||
/** else_block */
|
||||
private eb: Fragment<unknown> | null = null;
|
||||
/** get_each_value */
|
||||
private ge: GetEachValue;
|
||||
/** create_each_block */
|
||||
private e: CreateEachBlock;
|
||||
/** create_else_block */
|
||||
private ce?: CreateElseBlock;
|
||||
/** get_each_context */
|
||||
private g: CreateChildContext;
|
||||
|
||||
constructor(
|
||||
context: unknown,
|
||||
get_each_value: GetEachValue,
|
||||
create_each_block: CreateEachBlock,
|
||||
get_each_context: CreateChildContext,
|
||||
create_else_block: CreateElseBlock
|
||||
) {
|
||||
this.ge = get_each_value;
|
||||
this.e = create_each_block;
|
||||
this.g = get_each_context;
|
||||
this.ce = create_else_block;
|
||||
|
||||
const each_value = get_each_value(context);
|
||||
this.b = [];
|
||||
for (let i = 0; i < each_value.length; i += 1) {
|
||||
this.b[i] = create_each_block(get_each_context(context, each_value, i));
|
||||
}
|
||||
|
||||
if (create_else_block && !each_value.length) {
|
||||
this.eb = create_else_block(context);
|
||||
// TODO: Why exactly is this here and not in the `create` hook below?
|
||||
this.eb.c();
|
||||
}
|
||||
}
|
||||
|
||||
/** create */
|
||||
c() {
|
||||
for (const block of this.b) {
|
||||
block.c();
|
||||
}
|
||||
// if (this.eb) {
|
||||
// this.eb.c();
|
||||
// }
|
||||
}
|
||||
|
||||
/** claim */
|
||||
l(nodes: Array<Node>) {
|
||||
for (const block of this.b) {
|
||||
if (block.l) {
|
||||
block.l(nodes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** mount */
|
||||
m(target: Node, anchor?: Node | null) {
|
||||
for (const block of this.b) {
|
||||
block.m(target, anchor);
|
||||
}
|
||||
if (this.eb) {
|
||||
this.eb.m(target, anchor);
|
||||
}
|
||||
}
|
||||
|
||||
/** update */
|
||||
p(changed: unknown, context: unknown, target: Node, anchor?: Node | null) {
|
||||
const each_value = this.ge(context);
|
||||
const each_blocks = this.b;
|
||||
|
||||
for (let i = 0; i < each_value.length; i += 1) {
|
||||
const child_ctx = this.g(context, each_value, i);
|
||||
|
||||
let block = each_blocks[i];
|
||||
if (block) {
|
||||
if (block.p) {
|
||||
block.p(changed, child_ctx);
|
||||
}
|
||||
// transition_in(block, 1);
|
||||
} else {
|
||||
block = each_blocks[i] = this.e(child_ctx);
|
||||
block.c();
|
||||
// transition_in(block, 1);
|
||||
block.m(target, anchor);
|
||||
}
|
||||
}
|
||||
|
||||
// group_outros();
|
||||
for (let i = each_value.length; i < each_blocks.length; i += 1) {
|
||||
// TODO: make transitions work correctly…
|
||||
each_blocks[i].d(true);
|
||||
// transition_out(each_blocks[i], 1, 1, () => {
|
||||
// each_blocks[i] = null;
|
||||
// });
|
||||
}
|
||||
// check_outros();
|
||||
each_blocks.length = each_value.length;
|
||||
|
||||
if (this.ce) {
|
||||
let else_block = this.eb;
|
||||
if (!each_value.length && else_block) {
|
||||
if (else_block.p) {
|
||||
else_block.p(changed, context);
|
||||
}
|
||||
} else if (!each_value.length) {
|
||||
this.eb = else_block = this.ce(context);
|
||||
else_block.c();
|
||||
else_block.m(target, anchor);
|
||||
} else if (this.eb) {
|
||||
this.eb.d(true);
|
||||
this.eb = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** intro */
|
||||
i() {
|
||||
// for (const block of this.b) {
|
||||
// transition_in(block);
|
||||
// }
|
||||
}
|
||||
|
||||
/** outro */
|
||||
o() {
|
||||
// const blocks = this.b.filter(Boolean);
|
||||
// for (const block of blocks) {
|
||||
// transition_out(block, 0, 0, undefined);
|
||||
// }
|
||||
}
|
||||
|
||||
/** destroy */
|
||||
d(detaching: boolean) {
|
||||
destroy_each(this.b, detaching);
|
||||
|
||||
if (this.eb) {
|
||||
this.eb.d(detaching);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in new issue