react-workspaces
Version:
A component with a resizable and splittable workspace. A panel with draggable tabs.
172 lines (145 loc) • 4.43 kB
JavaScript
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.MSG = exports.MAX_DEPTH = undefined;
var _lodash = require('lodash');
var _lodash2 = _interopRequireDefault(_lodash);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const MAX_DEPTH = exports.MAX_DEPTH = 3;
const MSG = exports.MSG = {
IMPOSSIBLE_SPLIT: 'CANNOT SPLIT AT THIS PATH WITH AXIS',
MAX_DEPTH: `CANNOT SPLIT BEYOND ${MAX_DEPTH} LAYERS`,
INVALID_PATH: 'PANE VIA PATH NOT FOUND'
};
let Manager = class Manager {
constructor() {}
/**
* Checks if current pane can be split in that axis
* @return {Boolean} Returns true or false
*/
static validateSplit(state, path, axis, multiplier) {
const depth = ''.split('.').length;
let errors = [];
if (depth > MAX_DEPTH) {
errors.push(new Error(MSG.MAX_DEPTH));
}
let root = _lodash2.default.cloneDeep(state);
let pane;
if (path === '') {
pane = root;
} else {
pane = _lodash2.default.get(root, path);
}
if (!pane) {
errors.push(new Error(MSG.NO_SUCH_PATH));
return errors;
}
// if clean slate
if (!pane.children) {
return errors;
}
if (pane.axis !== axis) {
errors.push(new Error(MSG.IMPOSSIBLE_SPLIT));
}
return errors;
}
/**
* Creates a new state with the manipulation
* @param {Object} state [description]
* @param {String} path e.g. 'x[0].y[1]'
* @param {String} axis 'x' or 'y'
* @param {Number} muliplier How many times you want to split by
* @return {Object} Returns a new state
*/
static split(state = {}, path, axis, multiplier = 2) {
// needs to check if the current path can accept a split in the axis
const errors = this.validateSplit(state, path, axis, multiplier);
if (errors.length) {
throw new Error(_lodash2.default.map(errors, _lodash2.default.identity));
}
let root = _lodash2.default.cloneDeep(state);
let currentPane;
if (path === '') {
currentPane = root;
} else {
currentPane = _lodash2.default.get(root, path);
}
const edited = this.splitPane(currentPane, axis, multiplier);
return this.setPane(root, path, edited);
}
static setPane(root, path, pane) {
if (path === '') {
return pane;
} else {
return _lodash2.default.set(root, path, pane);
}
}
/**
* Split the panes at current position with axis
*/
static splitPane(pane, axis, multiplier) {
const divider = _lodash2.default.round(100 / multiplier, 2);
pane.axis = axis;
// if pane doesn't have an existing setup
if (!pane.children) {
pane.children = [];
for (var i = 0; i < multiplier; i++) {
pane.children.push({
size: divider
});
}
} else {
_lodash2.default.times(multiplier, index => {
if (pane.children[index]) {
pane.children[index].size = divider;
} else {
pane.children.push({
size: divider
});
}
});
}
return pane;
}
static moveTab(tabs, from, fromIndex, to, toIndex) {
// const tabs = {
// 'children[0].children[0]': ['green', 'red'],
// 'children[0].children[1]': 'blue',
// 'children[1]': ['yellow', 'red']
// }
if (!toIndex) {
toIndex = tabs[to].length;
}
let newTabs = _lodash2.default.cloneDeep(tabs);
const name = newTabs[from][fromIndex];
newTabs[from].splice(fromIndex, 1);
newTabs[to].splice(toIndex, 0, name);
return newTabs;
}
static buildTree(root, components, tabs) {
function walk(node, path = '') {
if (tabs[path]) {
if (_lodash2.default.isArray(tabs[path])) {
node.component = _lodash2.default.map(tabs[path], componentName => components[componentName]);
} else {
node.component = components[tabs[path]];
}
}
if (node.children) {
node.children = _lodash2.default.map(node.children, (child, index) => {
let childPath;
if (path === '') {
childPath = `children[${index}]`;
} else {
childPath = `${path}.children[${index}]`;
}
return walk(child, childPath);
});
}
return node;
}
return walk(_lodash2.default.cloneDeep(root));
}
};
exports.default = Manager;
;