Skip to content

Instantly share code, notes, and snippets.

@kana-sama
Created September 9, 2020 19:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kana-sama/5298df9da7f1f37154d54cbed7cb224c to your computer and use it in GitHub Desktop.
Save kana-sama/5298df9da7f1f37154d54cbed7cb224c to your computer and use it in GitHub Desktop.
type NodeId = string;
type Node_ = {
id: NodeId,
label: string,
collapsed: boolean,
children: Node_[]
}
type Tree = Node_[]
function makeEmptyTree(): Tree {
return [];
}
function traverseTree(tree: Tree, f: (node: Node_) => Node_): Tree {
function go(node: Node_): Node_ {
const children = node.children.map(go);
return f({ ...node, children });
}
return tree.map(go);
}
function toggleNode(tree: Tree, nodeId: NodeId) {
return traverseTree(tree, node => {
if (node.id === nodeId) {
return { ...node, collapsed: !node.collapsed };
} else {
return node;
}
})
}
function addToRoot(tree: Tree, node: Node_): Tree {
return [...tree, node];
}
function addToNode(tree: Tree, newNode: Node_, targetId: NodeId): Tree {
return traverseTree(tree, node => {
if (node.id === targetId) {
return { ...node, children: [...node.children, newNode] }
} else {
return node;
}
})
}
type Action =
| { type: "toggle", nodeId: NodeId }
| { type: "add_to_root", node: Node_ }
| { type: "add_to_node", node: Node_, targetId: NodeId };
function reducer(state: Tree, action: Action): Tree {
switch (action.type) {
case "toggle": return toggleNode(state, action.nodeId);
case "add_to_root": return addToRoot(state, action.node);
case "add_to_node": return addToNode(state, action.node, action.targetId);
default: return state;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment