parent: string;
active: boolean;
selected: boolean;
+ initialState?: boolean;
expanded: boolean;
status: TreeNodeStatus;
}
export const mapTreeValues = <T, R>(mapFn: (value: T) => R) => (tree: Tree<T>): Tree<R> =>
getNodeDescendantsIds('')(tree)
.map(id => getNode(id)(tree))
+ .filter(node => !!node)
.map(mapNodeValue(mapFn))
.reduce((newTree, node) => setNode(node)(newTree), createTree<R>());
export const expandNode = (...ids: string[]) => <T>(tree: Tree<T>) =>
mapTree((node: TreeNode<T>) => ids.some(id => id === node.id) ? { ...node, expanded: true } : node)(tree);
+export const expandNodeAncestors = (...ids: string[]) => <T>(tree: Tree<T>) => {
+ const ancestors = ids.reduce((acc, id): string[] => ([...acc, ...getNodeAncestorsIds(id)(tree)]), [] as string[]);
+ return mapTree((node: TreeNode<T>) => ancestors.some(id => id === node.id) ? { ...node, expanded: true } : node)(tree);
+}
+
export const collapseNode = (...ids: string[]) => <T>(tree: Tree<T>) =>
mapTree((node: TreeNode<T>) => ids.some(id => id === node.id) ? { ...node, expanded: false } : node)(tree);
: tree;
};
-export const toggleNodeSelection = (id: string) => <T>(tree: Tree<T>) => {
+export const toggleNodeSelection = (id: string, cascade: boolean) => <T>(tree: Tree<T>) => {
const node = getNode(id)(tree);
+
return node
- ? pipe(
- setNode({ ...node, selected: !node.selected }),
- toggleAncestorsSelection(id),
- toggleDescendantsSelection(id))(tree)
+ ? cascade
+ ? pipe(
+ setNode({ ...node, selected: !node.selected }),
+ toggleAncestorsSelection(id),
+ toggleDescendantsSelection(id))(tree)
+ : setNode({ ...node, selected: !node.selected })(tree)
: tree;
};
-export const selectNode = (id: string) => <T>(tree: Tree<T>) => {
+export const selectNode = (id: string, cascade: boolean) => <T>(tree: Tree<T>) => {
const node = getNode(id)(tree);
return node && node.selected
? tree
- : toggleNodeSelection(id)(tree);
+ : toggleNodeSelection(id, cascade)(tree);
};
-export const selectNodes = (id: string | string[]) => <T>(tree: Tree<T>) => {
+export const selectNodes = (id: string | string[], cascade: boolean) => <T>(tree: Tree<T>) => {
const ids = typeof id === 'string' ? [id] : id;
- return ids.reduce((tree, id) => selectNode(id)(tree), tree);
+ return ids.reduce((tree, id) => selectNode(id, cascade)(tree), tree);
};
-export const deselectNode = (id: string) => <T>(tree: Tree<T>) => {
+export const deselectNode = (id: string, cascade: boolean) => <T>(tree: Tree<T>) => {
const node = getNode(id)(tree);
return node && node.selected
- ? toggleNodeSelection(id)(tree)
+ ? toggleNodeSelection(id, cascade)(tree)
: tree;
};
-export const deselectNodes = (id: string | string[]) => <T>(tree: Tree<T>) => {
+export const deselectNodes = (id: string | string[], cascade: boolean) => <T>(tree: Tree<T>) => {
const ids = typeof id === 'string' ? [id] : id;
- return ids.reduce((tree, id) => deselectNode(id)(tree), tree);
+ return ids.reduce((tree, id) => deselectNode(id, cascade)(tree), tree);
};
export const getSelectedNodes = <T>(tree: Tree<T>) =>
...data,
});
+export const getTreeDirty = (id: string) => <T>(tree: Tree<T>): boolean => {
+ const node = getNode(id)(tree);
+ const children = getNodeDescendants(id)(tree);
+ return (node
+ && node.initialState !== undefined
+ && node.selected !== node.initialState
+ )
+ || children.some(child =>
+ child.initialState !== undefined
+ && child.selected !== child.initialState
+ );
+}
+
const toggleDescendantsSelection = (id: string) => <T>(tree: Tree<T>) => {
const node = getNode(id)(tree);
if (node) {
return tree;
};
-
const mapNodeValue = <T, R>(mapFn: (value: T) => R) => (node: TreeNode<T>): TreeNode<R> =>
({ ...node, value: mapFn(node.value) });