@neo4j-ndl/react
Version:
React implementation of Neo4j Design System
175 lines (174 loc) • 6.83 kB
JavaScript
/**
*
* Copyright (c) "Neo4j"
* Neo4j Sweden AB [http://neo4j.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.transformToString = exports.flattenTree = void 0;
exports.removeChildrenOf = removeChildrenOf;
exports.buildTree = buildTree;
exports.getProjection = getProjection;
const sortable_1 = require("@dnd-kit/sortable");
/**
* Takes a tree and flattens it into a list of item
* where each item has a depth and a parentId.
* @param tree the tree to flatten
* @param depth the depth of the root of the tree (default 0)
* @param parentId the id of the parent of the root of the tree (default null)
* @returns a list of items with depth and parentId
*/
const flattenTree = (tree, depth = 0, parentId = null) => {
const flattened = [];
tree.forEach((item) => {
var _a;
flattened.push(Object.assign(Object.assign({}, item), { depth: depth, parentId: parentId,
// Default values can go here for items
isSkeletonLoading: (_a = item.isSkeletonLoading) !== null && _a !== void 0 ? _a : false }));
if (item.canHaveSubItems) {
(0, exports.flattenTree)(item.subItems, depth + 1, item.id).forEach((subItem) => flattened.push(Object.assign({}, subItem)));
}
});
return flattened;
};
exports.flattenTree = flattenTree;
/**
* Removes the children of the items with the given ids
* @param items the flattened tree items to remove the children from
* @param ids the ids of the items to remove the children from
* @returns a new list of items with the children of the items with the given ids removed
*/
function removeChildrenOf(items, ids) {
const excludeParentIds = [...ids];
return items.filter((item) => {
if (item.parentId !== null && excludeParentIds.includes(item.parentId)) {
if (item.canHaveSubItems && item.subItems.length > 0) {
excludeParentIds.push(item.id);
}
return false;
}
return true;
});
}
/**
* Builds a tree from a list of flattened tree items
* @param items the flattened tree items
* @returns the items as a tree data structure
*/
function buildTree(items) {
const tree = [];
// Map array to object
const itemMap = items.reduce((newItemMap, item) => {
const { id } = item;
// Add sub items array if it's allowed to have sub items.
const newItem = Object.assign(Object.assign({}, item), (item.canHaveSubItems && {
subItems: [],
}));
return Object.assign(Object.assign({}, newItemMap), { [id]: newItem });
}, {});
// Build the tree structure by assigning children to their parent items
items.forEach((item) => {
const { id, parentId } = item;
if (parentId !== null) {
const parentItem = itemMap[parentId];
if (parentItem && parentItem.canHaveSubItems) {
parentItem.subItems.push(itemMap[id]);
}
}
else {
tree.push(itemMap[id]);
}
});
return tree;
}
function getDragDepth(offset, indentationWidth) {
return Math.round(offset / indentationWidth);
}
function getMaxDepth({ previousItem, }) {
var _a;
if (previousItem && previousItem.canHaveSubItems === true) {
return previousItem.depth + 1;
}
return (_a = previousItem === null || previousItem === void 0 ? void 0 : previousItem.depth) !== null && _a !== void 0 ? _a : 0;
}
function getMinDepth({ nextItem }) {
if (nextItem) {
return nextItem.depth;
}
return 0;
}
/**
* Calculates the new depth, max depth, min depth and parent id of the item being dragged
* Used to project the position of the dragged item. For example, to convert the item being dragged into a placeholder.
* such as the line that appears when dragging an item in a tree view.
* @param items the flattened tree items
* @param activeId the id of the item being dragged
* @param overId the id of the item that the dragged item is being dragged over
* @param dragOffset the offset of the drag in pixels
* @param indentationWidth the width of the indentation in pixels
* @returns the depth, max depth, min depth and parent id of the item being dragged
*/
function getProjection(items, activeId, overId, dragOffset, indentationWidth) {
const overItemIndex = items.findIndex(({ id }) => id === overId);
const activeItemIndex = items.findIndex(({ id }) => id === activeId);
const activeItem = items[activeItemIndex];
const newItems = (0, sortable_1.arrayMove)(items, activeItemIndex, overItemIndex);
const previousItem = newItems[overItemIndex - 1];
const nextItem = newItems[overItemIndex + 1];
const dragDepth = getDragDepth(dragOffset, indentationWidth);
const projectedDepth = activeItem.depth + dragDepth;
const maxDepth = getMaxDepth({
previousItem,
});
const minDepth = getMinDepth({ nextItem });
let depth = projectedDepth;
if (projectedDepth >= maxDepth) {
depth = maxDepth;
}
else if (projectedDepth < minDepth) {
depth = minDepth;
}
return { depth, maxDepth, minDepth, parentId: getParentId() };
function getParentId() {
var _a;
if (depth === 0 || !previousItem) {
return null;
}
if (depth === previousItem.depth) {
return previousItem.parentId;
}
if (depth > previousItem.depth) {
return previousItem.id;
}
const newParent = (_a = newItems
.slice(0, overItemIndex)
.reverse()
.find((item) => item.depth === depth)) === null || _a === void 0 ? void 0 : _a.parentId;
return newParent !== null && newParent !== void 0 ? newParent : null;
}
}
/**
*
* @param transform a transform object
* @returns a css transform string
*/
const transformToString = (transform) => {
return `scaleX(${transform.scaleX}) scaleY(${transform.scaleY}) translate3d(${transform.x}px, ${transform.y}px, 0)`;
};
exports.transformToString = transformToString;
//# sourceMappingURL=tree-view-utils.js.map