wix-style-react
Version:
wix-style-react
80 lines • 2.84 kB
JavaScript
import React from 'react';
const readItemNodesRecursively = (parentItemNode, children) => {
if (!children) {
return;
}
React.Children.toArray(children).forEach(child => {
if (!React.isValidElement(child)) {
return;
}
const itemKey = child?.props?.itemKey;
const itemChildren = child?.props?.children;
if (typeof itemKey === 'string' && itemKey !== parentItemNode.itemKey) {
const itemNode = { itemKey };
(parentItemNode.items ??= []).push(itemNode);
readItemNodesRecursively(itemNode, itemChildren);
}
else {
readItemNodesRecursively(parentItemNode, itemChildren);
}
});
};
const readParentKeysRecursively = (keyToParentKey, itemNodes, parentItemKey) => {
for (const { itemKey, items } of itemNodes) {
keyToParentKey[itemKey] = parentItemKey;
if (items) {
readParentKeysRecursively(keyToParentKey, items, itemKey);
}
}
};
/**
* Recursively walks react children to create a tree of sidebar item nodes and
* their parent-child relationships.
*/
export const extractItemNodes = (children) => {
const rootNode = { itemKey: 'rootMenu' }; // TODO: use a symbol
readItemNodesRecursively(rootNode, children);
const items = rootNode.items ?? [];
const keyToParentKey = Object.create(null);
readParentKeysRecursively(keyToParentKey, items);
return { items, keyToParentKey };
};
export const getItemPath = (keyToParentKey, itemKey) => {
const path = [];
while (itemKey !== undefined) {
path.unshift(itemKey);
itemKey = keyToParentKey[itemKey];
}
return path;
};
export const isMenu = (keyToParentKey, itemKey) => Object.values(keyToParentKey).includes(itemKey);
export const getMenuPath = (keyToParentKey, itemKey) => {
const path = getItemPath(keyToParentKey, itemKey);
if (path.length > 0 && !isMenu(keyToParentKey, path[path.length - 1])) {
path.pop();
}
return path;
};
export const getMaxDepth = (items) => {
let maxDepth = 0;
if (items?.length) {
for (const item of items) {
maxDepth = Math.max(maxDepth, getMaxDepth(item.items) + 1);
}
}
return maxDepth;
};
export function pick(object, keys) {
// Probably should use `lodash.pick` but it's too smart with its key handing (
// lodash keys can be paths like `a.b.c`). Since we're using this to pick
// keys from a record which gets created from consumer input, we can't be sure
// that consumers won't use keys that look like paths.
const result = {};
for (const key of keys) {
if (Object.prototype.hasOwnProperty.call(object, key)) {
result[key] = object[key];
}
}
return result;
}
//# sourceMappingURL=utils.js.map