| 189 | } |
| 190 | |
| 191 | function updateTree( |
| 192 | items: TreeNode<T>[], |
| 193 | key: Key | null, |
| 194 | update: (node: TreeNode<T>) => TreeNode<T> | null, |
| 195 | originalMap: Map<Key, TreeNode<T>> |
| 196 | ) { |
| 197 | let node = key == null ? null : originalMap.get(key); |
| 198 | if (node == null) { |
| 199 | return {items, nodeMap: originalMap}; |
| 200 | } |
| 201 | let map = new Map<Key, TreeNode<T>>(originalMap); |
| 202 | |
| 203 | // Create a new node. If null, then delete the node, otherwise replace. |
| 204 | let newNode = update(node); |
| 205 | if (newNode == null) { |
| 206 | deleteNode(node, map); |
| 207 | } else { |
| 208 | addNode(newNode, map); |
| 209 | } |
| 210 | |
| 211 | // Walk up the tree and update each parent to refer to the new children. |
| 212 | while (node && node.parentKey) { |
| 213 | let nextParent = map.get(node.parentKey)!; |
| 214 | let copy: TreeNode<T> = { |
| 215 | key: nextParent.key, |
| 216 | parentKey: nextParent.parentKey, |
| 217 | value: nextParent.value, |
| 218 | children: null |
| 219 | }; |
| 220 | |
| 221 | let children = nextParent.children; |
| 222 | if (newNode == null && children) { |
| 223 | children = children.filter(c => c !== node); |
| 224 | } |
| 225 | |
| 226 | copy.children = |
| 227 | children?.map(child => { |
| 228 | if (child === node) { |
| 229 | // newNode cannot be null here due to the above filter. |
| 230 | return newNode!; |
| 231 | } |
| 232 | |
| 233 | return child; |
| 234 | }) ?? null; |
| 235 | |
| 236 | map.set(copy.key, copy); |
| 237 | |
| 238 | newNode = copy; |
| 239 | node = nextParent; |
| 240 | } |
| 241 | |
| 242 | if (newNode == null) { |
| 243 | items = items.filter(c => c !== node); |
| 244 | } |
| 245 | |
| 246 | return { |
| 247 | items: items.map(item => { |
| 248 | if (item === node) { |