redux-devtools/packages/map2tree/src/index.ts
Nathan Bierema b323f77d31
Upgrade D3 to v4 (#1307)
* Update packages

* Fix after update

* Update some types

* Remove attr

* Finish d3tooltip

* Update style option

* Updates

* Zoom

* Update

* Update

* Update

* Fix

* Update

* Update

* Update

* Update

* Update

* Fixes

* Update id type

* Fix enter + update selections

* Use this

* Fix stringifying

* Remove InputOptions

* Use data.value

* Updates

* Remove UMD builds

* Fix exit

* No need to re-assign

* Simplify d3tooltip API

* Update redux-devtools-chart-monitor

* Update redux-devtools-app

* Update

* Update

* Remove @types/prop-types

* Update prop types

* Update d3tooltip docs

* Update d3-state-visualizer docs

* Update chart-monitor docs

* Create weak-kings-brake.md

* Create spicy-olives-compete.md

* Create friendly-coats-trade.md

* Create slimy-elephants-flash.md

* Fix empty arrays
2023-01-02 14:19:13 -05:00

102 lines
2.5 KiB
TypeScript

import isArray from 'lodash/isArray';
import isPlainObject from 'lodash/isPlainObject';
import mapValues from 'lodash/mapValues';
export interface Node {
name: string;
children?: this[];
object?: unknown;
value?: unknown;
}
function visit(
parent: Node,
visitFn: (parent: Node) => void,
childrenFn: (parent: Node) => Node[] | undefined | null
) {
if (!parent) return;
visitFn(parent);
const children = childrenFn(parent);
if (children) {
const count = children.length;
for (let i = 0; i < count; i++) {
visit(children[i], visitFn, childrenFn);
}
}
}
function getNode(tree: Node, key: string): Node | null {
let node = null;
visit(
tree,
(d) => {
if (d.name === key) {
node = d;
}
},
(d) => d.children
);
return node;
}
export function map2tree(
root: unknown,
options: { key?: string; pushMethod?: 'push' | 'unshift' } = {},
tree: Node = { name: options.key || 'state', children: [] }
// eslint-disable-next-line @typescript-eslint/ban-types
): Node | {} {
// eslint-disable-next-line @typescript-eslint/ban-types
if (!isPlainObject(root) && root && !(root as { toJS: () => {} }).toJS) {
return {};
}
const { key: rootNodeKey = 'state', pushMethod = 'push' } = options;
const currentNode = getNode(tree, rootNodeKey);
if (currentNode === null) {
return {};
}
mapValues(
// eslint-disable-next-line @typescript-eslint/ban-types
root && (root as { toJS: () => {} }).toJS
? // eslint-disable-next-line @typescript-eslint/ban-types
(root as { toJS: () => {} }).toJS()
: // eslint-disable-next-line @typescript-eslint/ban-types
(root as {}),
// eslint-disable-next-line @typescript-eslint/ban-types
(maybeImmutable: { toJS?: () => {} }, key) => {
const value =
maybeImmutable && maybeImmutable.toJS
? maybeImmutable.toJS()
: maybeImmutable;
const newNode: Node = { name: key };
if (isArray(value)) {
newNode.children = [];
for (let i = 0; i < value.length; i++) {
newNode.children[pushMethod]({
name: `${key}[${i}]`,
[isPlainObject(value[i]) ? 'object' : 'value']: value[i],
});
}
} else if (isPlainObject(value)) {
newNode.children = [];
} else {
newNode.value = value;
}
currentNode.children![pushMethod](newNode);
map2tree(value, { key, pushMethod }, tree);
}
);
return tree;
}