rvx
Version:
A signal based rendering library
95 lines • 2.86 kB
JavaScript
import { $, capture, isolate, teardown } from "../signals.js";
export function createMapArrayState() {
const state = [];
teardown(() => {
for (let i = 0; i < state.length; i++) {
state[i].d();
}
});
return state;
}
function createEntry(value, index, fn) {
const signal = $(index);
let output;
const dispose = isolate(capture, () => {
output = fn(value, () => signal.value);
});
return {
i: value,
o: output,
s: signal,
d: dispose,
r: false,
};
}
export function mapArrayUpdate(state, rawInput, fn) {
const inputs = Array.isArray(rawInput) ? rawInput : Array.from(rawInput);
let start = 0;
const maxStart = Math.min(state.length, inputs.length);
while (start < maxStart && Object.is(inputs[start], state[start].i)) {
start++;
}
if (start === inputs.length && inputs.length === state.length) {
return null;
}
const minEnd = inputs.length - maxStart + start;
const lenDiff = inputs.length - state.length;
let end = inputs.length - 1;
while (end >= minEnd && Object.is(inputs[end], state[end - lenDiff].i)) {
end--;
}
end++;
const stateEnd = end - lenDiff;
const nextState = [];
if ((end - lenDiff - start) === 0) {
for (let i = start; i < end; i++) {
nextState[i - start] = createEntry(inputs[i], i, fn);
}
}
else {
const indexByValue = new Map();
const nextIndexByIndex = [];
for (let i = end - 1; i >= start; i--) {
const value = inputs[i];
const next = indexByValue.get(value);
if (next !== undefined) {
nextIndexByIndex[i] = next;
}
indexByValue.set(value, i);
}
for (let i = start; i < stateEnd; i++) {
const instance = state[i];
const index = indexByValue.get(instance.i);
if (index === undefined) {
instance.d();
instance.r = true;
}
else {
nextState[index - start] = instance;
indexByValue.set(instance.i, nextIndexByIndex[index]);
}
}
for (let i = start; i < end; i++) {
const old = nextState[i - start];
if (old) {
old.s.value = i;
}
else {
nextState[i - start] = createEntry(inputs[i], i, fn);
}
}
}
const prevState = state.splice(start, stateEnd - start, ...nextState);
if (stateEnd !== end) {
for (let i = end; i < state.length; i++) {
state[i].s.value = i;
}
}
return {
s: start,
e: end,
p: prevState,
n: nextState,
};
}
//# sourceMappingURL=map-array.js.map