@lonli-lokli/react-mosaic-component
Version:
A React Tiling Window Manager
129 lines (128 loc) • 4.2 kB
JavaScript
// libs/react-mosaic-component/src/lib/MosaicRoot.tsx
import { flatten } from "lodash-es";
import React from "react";
import { MosaicContext } from "./contextTypes.mjs";
import { Split } from "./Split.mjs";
import {
boundingBoxAsStyles,
emptyBoundingBox,
splitBoundingBox
} from "./util/BoundingBox.mjs";
import { convertLegacyToNary } from "./util/mosaicUtilities.mjs";
import { MosaicTabs } from "./MosaicTabs.mjs";
var MosaicRoot = class extends React.PureComponent {
static contextType = MosaicContext;
render() {
const naryRoot = convertLegacyToNary(this.props.root);
if (naryRoot === null) {
return null;
}
return /* @__PURE__ */ React.createElement("div", { className: "mosaic-root" }, this.renderRecursively(naryRoot, emptyBoundingBox(), []));
}
// The recursive renderer is now updated for the n-ary tree structure
renderRecursively(node, boundingBox, path) {
if (typeof node === "string" || typeof node === "number") {
return /* @__PURE__ */ React.createElement(
"div",
{
key: node,
className: "mosaic-tile",
style: { ...boundingBoxAsStyles(boundingBox) }
},
this.props.renderTile(node, path)
);
}
switch (node.type) {
// Case 2: Node is a split container
case "split": {
const { children, direction } = node;
const splitPercentages = node.splitPercentages ?? children.map(() => 100 / children.length);
const childBoxes = splitBoundingBox(
boundingBox,
splitPercentages,
direction
);
const renderedChildren = children.flatMap((child, index) => {
const childPath = path.concat(index);
const elements = [
this.renderRecursively(child, childBoxes[index], childPath)
];
if (index < children.length - 1) {
elements.push(this.renderSplit(node, path, index, boundingBox));
}
return elements;
});
const flattenedElements = flatten(renderedChildren).filter(nonNullElement);
return /* @__PURE__ */ React.createElement(React.Fragment, null, flattenedElements.map(
(element, index) => React.cloneElement(element, {
key: element.key || `${path.join("-")}-${index}`
})
));
}
// Case 3: Node is a tab container
case "tabs": {
return /* @__PURE__ */ React.createElement(
MosaicTabs,
{
node,
path,
renderTile: this.props.renderTile,
renderTabToolbar: this.props.renderTabToolbar,
boundingBox,
renderTabTitle: this.props.renderTabTitle,
renderTabButton: this.props.renderTabButton,
canClose: this.props.canClose
}
);
}
default:
console.error("Unknown mosaic node type:", node);
return null;
}
}
renderSplit(parentNode, path, splitIndex, boundingBox) {
const { resize } = this.props;
if (resize !== "DISABLED" && parentNode.children.length > 1) {
const { direction } = parentNode;
const splitPercentages = parentNode.splitPercentages ?? parentNode.children.map(() => 100 / parentNode.children.length);
return /* @__PURE__ */ React.createElement(
Split,
{
key: `split-${path.join("-")}-${splitIndex}`,
...resize,
direction,
boundingBox,
splitIndex,
splitPercentages,
onChange: (percentages) => this.onResize(percentages, path, true),
onRelease: (percentages) => this.onResize(percentages, path, false)
}
);
} else {
return null;
}
}
// onResize now handles an array of percentages
onResize = (percentages, path, suppressOnRelease) => {
this.context.mosaicActions.updateTree(
[
{
path,
// Path to the parent MosaicSplitNode
spec: {
splitPercentages: {
$set: percentages
}
}
}
],
{ suppressOnRelease }
);
};
};
function nonNullElement(x) {
return x !== null;
}
export {
MosaicRoot
};