@isotope/core
Version:
Isotope - statically-dynamic UI library
169 lines • 4.78 kB
JavaScript
/**
* Creates the Diffing loop data object.
*
* @param sourceInput - Original, source Item array.
* @param targetInput - Target Item array.
* @returns - Diffing loop data object.
*/
const createData = (sourceInput, targetInput) => ({
changes: [],
index: 0,
source: sourceInput.map((item) => `${typeof item === "object" ? item.id : item}`),
sourceInput,
target: targetInput.map((item) => `${typeof item === "object" ? item.id : item}`),
targetInput
});
/**
* Checks if the diffing loop should be run.
*
* @param data - Diffing loop data.
* @returns - If the diffing loop should be run.
*/
const shouldLoop = ({ index, source, target }) => {
return (source.length > 0 &&
target.length > 0 &&
(index <= source.length || index <= target.length));
};
/**
* Trims the diffed arrays from both sides if edge items are equal.
*
* @param data - Diffing loop data.
* @returns - If arrays were trimmed.
*/
const trim = ({ source, target }) => {
const [sourceStart] = source;
const sourceEnd = source[source.length - 1];
const [targetStart] = target;
const targetEnd = target[target.length - 1];
let trimmed = false;
if (sourceStart === targetStart) {
source.shift();
target.shift();
trimmed = true;
}
if (sourceEnd === targetEnd) {
source.pop();
target.pop();
trimmed = true;
}
return trimmed;
};
/**
* Detect whether the items should be moved to the opposite site of the array.
*
* @param data - Diffing loop data.
* @returns - Which item should be moved to left and which to right.
*/
const prepareMove = ({ index, source, target }) => {
const sourceStart = source[index];
const sourceEnd = source[source.length - 1 - index];
const [targetStart] = target;
const targetEnd = target[target.length - 1];
const moveLeft = sourceEnd === targetStart;
const moveRight = sourceStart === targetEnd;
const itemToLeft = moveLeft ? source.splice(source.length - 1 - index, 1)[0] : null;
const itemToRight = moveRight ? source.splice(index, 1)[0] : null;
return {
left: itemToLeft,
right: itemToRight
};
};
/**
* Move the specified items to the opposite site of the array.
*
* @param data - Diffing loop data.
* @param itemToLeft - Item to be moved to the left end.
* @param itemToRight - Item to be moved to the right end.
*/
const move = ({ changes, source }, itemToLeft, itemToRight) => {
if (itemToRight !== null) {
source.push(itemToRight);
changes.push({
id: itemToRight,
type: "move"
});
}
if (itemToLeft !== null) {
source.splice(0, 0, itemToLeft);
changes.push({
id: itemToLeft,
type: "move"
});
}
};
/**
* Adds the new items from diffed arrays.
*
* @param data - Diffing loop data.
*/
const add = ({ changes, target }) => {
target.splice(0).forEach((id) => {
changes.push({
id,
type: "add"
});
});
};
/**
* Removes the previous items from diffed arrays.
*
* @param data - Diffing loop data.
*/
const remove = ({ changes, source }) => {
source.splice(0).forEach((id) => {
changes.push({
id,
type: "remove"
});
});
};
/**
* Fills the remaining data required by specific changes.
*
* @param data - Diffing loop data.
*/
const fill = ({ changes, targetInput }) => {
changes.forEach((change) => {
const id = `${change.id}`;
const { type } = change;
if (type === "add" || type === "move") {
const index = targetInput.findIndex((item) => {
return typeof item === "object" ? `${item.id}` === id : `${item}` === id;
});
if (type === "add") {
change.item = targetInput[index];
}
change.position = index;
}
});
};
/**
* Detects changes made between 2 Item arrays.
*
* @param sourceInput - Original, source Item array.
* @param targetInput - Target Item array.
* @returns - Changes that differ the second array from the first one.
*/
const detectChanges = (sourceInput, targetInput) => {
const data = createData(sourceInput, targetInput);
while (shouldLoop(data)) {
if (trim(data)) {
data.index = 0;
continue;
}
const { left, right } = prepareMove(data);
if (left !== null || right !== null) {
move(data, left, right);
data.index = 0;
}
else {
data.index += 1;
}
}
add(data);
remove(data);
fill(data);
return data.changes;
};
export { detectChanges };
//# sourceMappingURL=utils.js.map