react-mosaic-component2
Version:
A React Tiling Window Manager
115 lines (114 loc) • 3.3 kB
JavaScript
// src/util/mosaicUpdates.ts
import update from "immutability-helper";
import { drop, dropRight, isEqual, last, set, take } from "lodash-es";
import { MosaicDropTargetPosition } from "../internalTypes.mjs";
import { getAndAssertNodeAtPathExists, getOtherBranch } from "./mosaicUtilities.mjs";
function buildSpecFromUpdate(mosaicUpdate) {
if (mosaicUpdate.path.length > 0) {
return set({}, mosaicUpdate.path, mosaicUpdate.spec);
} else {
return mosaicUpdate.spec;
}
}
function updateTree(root, updates) {
let currentNode = root;
updates.forEach((mUpdate) => {
currentNode = update(currentNode, buildSpecFromUpdate(mUpdate));
});
return currentNode;
}
function createRemoveUpdate(root, path) {
const parentPath = dropRight(path);
const nodeToRemove = last(path);
const siblingPath = parentPath.concat(getOtherBranch(nodeToRemove));
const sibling = getAndAssertNodeAtPathExists(root, siblingPath);
return {
path: parentPath,
spec: {
$set: sibling
}
};
}
function isPathPrefixEqual(a, b, length) {
return isEqual(take(a, length), take(b, length));
}
function createDragToUpdates(root, sourcePath, destinationPath, position) {
let destinationNode = getAndAssertNodeAtPathExists(root, destinationPath);
const updates = [];
const destinationIsParentOfSource = isPathPrefixEqual(sourcePath, destinationPath, destinationPath.length);
if (destinationIsParentOfSource) {
destinationNode = updateTree(destinationNode, [
createRemoveUpdate(destinationNode, drop(sourcePath, destinationPath.length))
]);
} else {
updates.push(createRemoveUpdate(root, sourcePath));
const removedNodeParentIsInPath = isPathPrefixEqual(sourcePath, destinationPath, sourcePath.length - 1);
if (removedNodeParentIsInPath) {
destinationPath.splice(sourcePath.length - 1, 1);
}
}
const sourceNode = getAndAssertNodeAtPathExists(root, sourcePath);
let first;
let second;
if (position === MosaicDropTargetPosition.LEFT || position === MosaicDropTargetPosition.TOP) {
first = sourceNode;
second = destinationNode;
} else {
first = destinationNode;
second = sourceNode;
}
let direction = "column";
if (position === MosaicDropTargetPosition.LEFT || position === MosaicDropTargetPosition.RIGHT) {
direction = "row";
}
updates.push({
path: destinationPath,
spec: {
$set: { first, second, direction }
}
});
return updates;
}
function createHideUpdate(path) {
const targetPath = dropRight(path);
const thisBranch = last(path);
let splitPercentage;
if (thisBranch === "first") {
splitPercentage = 0;
} else {
splitPercentage = 100;
}
return {
path: targetPath,
spec: {
splitPercentage: {
$set: splitPercentage
}
}
};
}
function createExpandUpdate(path, percentage) {
let spec = {};
for (let i = path.length - 1; i >= 0; i--) {
const branch = path[i];
const splitPercentage = branch === "first" ? percentage : 100 - percentage;
spec = {
splitPercentage: {
$set: splitPercentage
},
[branch]: spec
};
}
return {
spec,
path: []
};
}
export {
buildSpecFromUpdate,
createDragToUpdates,
createExpandUpdate,
createHideUpdate,
createRemoveUpdate,
updateTree
};