File size: 3,367 Bytes
bc20498 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
import { transition_in, transition_out } from './transitions.js';
import { run_all } from './utils.js';
// general each functions:
export function ensure_array_like(array_like_or_iterator) {
return array_like_or_iterator?.length !== undefined
? array_like_or_iterator
: Array.from(array_like_or_iterator);
}
// keyed each functions:
/** @returns {void} */
export function destroy_block(block, lookup) {
block.d(1);
lookup.delete(block.key);
}
/** @returns {void} */
export function outro_and_destroy_block(block, lookup) {
transition_out(block, 1, 1, () => {
lookup.delete(block.key);
});
}
/** @returns {void} */
export function fix_and_destroy_block(block, lookup) {
block.f();
destroy_block(block, lookup);
}
/** @returns {void} */
export function fix_and_outro_and_destroy_block(block, lookup) {
block.f();
outro_and_destroy_block(block, lookup);
}
/** @returns {any[]} */
export function update_keyed_each(
old_blocks,
dirty,
get_key,
dynamic,
ctx,
list,
lookup,
node,
destroy,
create_each_block,
next,
get_context
) {
let o = old_blocks.length;
let n = list.length;
let i = o;
const old_indexes = {};
while (i--) old_indexes[old_blocks[i].key] = i;
const new_blocks = [];
const new_lookup = new Map();
const deltas = new Map();
const updates = [];
i = n;
while (i--) {
const child_ctx = get_context(ctx, list, i);
const key = get_key(child_ctx);
let block = lookup.get(key);
if (!block) {
block = create_each_block(key, child_ctx);
block.c();
} else if (dynamic) {
// defer updates until all the DOM shuffling is done
updates.push(() => block.p(child_ctx, dirty));
}
new_lookup.set(key, (new_blocks[i] = block));
if (key in old_indexes) deltas.set(key, Math.abs(i - old_indexes[key]));
}
const will_move = new Set();
const did_move = new Set();
/** @returns {void} */
function insert(block) {
transition_in(block, 1);
block.m(node, next);
lookup.set(block.key, block);
next = block.first;
n--;
}
while (o && n) {
const new_block = new_blocks[n - 1];
const old_block = old_blocks[o - 1];
const new_key = new_block.key;
const old_key = old_block.key;
if (new_block === old_block) {
// do nothing
next = new_block.first;
o--;
n--;
} else if (!new_lookup.has(old_key)) {
// remove old block
destroy(old_block, lookup);
o--;
} else if (!lookup.has(new_key) || will_move.has(new_key)) {
insert(new_block);
} else if (did_move.has(old_key)) {
o--;
} else if (deltas.get(new_key) > deltas.get(old_key)) {
did_move.add(new_key);
insert(new_block);
} else {
will_move.add(old_key);
o--;
}
}
while (o--) {
const old_block = old_blocks[o];
if (!new_lookup.has(old_block.key)) destroy(old_block, lookup);
}
while (n) insert(new_blocks[n - 1]);
run_all(updates);
return new_blocks;
}
/** @returns {void} */
export function validate_each_keys(ctx, list, get_context, get_key) {
const keys = new Map();
for (let i = 0; i < list.length; i++) {
const key = get_key(get_context(ctx, list, i));
if (keys.has(key)) {
let value = '';
try {
value = `with value '${String(key)}' `;
} catch (e) {
// can't stringify
}
throw new Error(
`Cannot have duplicate keys in a keyed each: Keys at index ${keys.get(
key
)} and ${i} ${value}are duplicates`
);
}
keys.set(key, i);
}
}
|