@@ -66,21 +66,48 @@ export function getDescendantCount({ node, ignoreCollapsed = true }) {
6666}
6767
6868/**
69- * Walk all descendants of the given node
69+ * Walk all descendants of the given node, depth-first
70+ *
71+ * @param {Object } args - Function parameters
72+ * @param {function } args.callback - Function to call on each node
73+ * @param {function } args.getNodeKey - Function to get the key from the nodeData and tree index
74+ * @param {boolean } args.ignoreCollapsed - Ignore children of nodes without `expanded` set to `true`
75+ * @param {boolean= } args.isPseudoRoot - If true, this node has no real data, and only serves
76+ * as the parent of all the nodes in the tree
77+ * @param {Object } args.node - A tree node
78+ * @param {Object= } args.parentNode - The parent node of `node`
79+ * @param {number } args.currentIndex - The treeIndex of `node`
80+ * @param {number[]|string[] } args.path - Array of keys leading up to node to be changed
81+ * @param {number[] } args.lowerSiblingCounts - An array containing the count of siblings beneath the
82+ * previous nodes in this path
83+ *
84+ * @return {number|false } nextIndex - Index of the next sibling of `node`,
85+ * or false if the walk should be terminated
7086 */
7187function walkDescendants ( {
7288 callback,
7389 getNodeKey,
7490 ignoreCollapsed,
7591 isPseudoRoot = false ,
7692 node,
93+ parentNode = null ,
7794 currentIndex,
7895 path = [ ] ,
7996 lowerSiblingCounts = [ ] ,
8097} ) {
8198 // The pseudo-root is not considered in the path
82- const selfPath = ! isPseudoRoot ? [ ...path , getNodeKey ( { node, treeIndex : currentIndex } ) ] : [ ] ;
83- const selfInfo = ! isPseudoRoot ? { node, path : selfPath , lowerSiblingCounts, treeIndex : currentIndex } : null ;
99+ const selfPath = isPseudoRoot ? [ ] : [
100+ ...path ,
101+ getNodeKey ( { node, treeIndex : currentIndex } ) ,
102+ ] ;
103+ const selfInfo = isPseudoRoot ? null : {
104+ node,
105+ parentNode,
106+ path : selfPath ,
107+ lowerSiblingCounts,
108+ treeIndex : currentIndex ,
109+ } ;
110+
84111 if ( ! isPseudoRoot ) {
85112 const callbackResult = callback ( selfInfo ) ;
86113
@@ -105,6 +132,7 @@ function walkDescendants({
105132 getNodeKey,
106133 ignoreCollapsed,
107134 node : node . children [ i ] ,
135+ parentNode : isPseudoRoot ? null : node ,
108136 currentIndex : childIndex + 1 ,
109137 lowerSiblingCounts : [ ...lowerSiblingCounts , childCount - i - 1 ] ,
110138 path : selfPath ,
@@ -121,24 +149,52 @@ function walkDescendants({
121149}
122150
123151/**
124- * Perform a change on the given node and all its descendants
152+ * Perform a change on the given node and all its descendants, traversing the tree depth-first
153+ *
154+ * @param {Object } args - Function parameters
155+ * @param {function } args.callback - Function to call on each node
156+ * @param {function } args.getNodeKey - Function to get the key from the nodeData and tree index
157+ * @param {boolean } args.ignoreCollapsed - Ignore children of nodes without `expanded` set to `true`
158+ * @param {boolean= } args.isPseudoRoot - If true, this node has no real data, and only serves
159+ * as the parent of all the nodes in the tree
160+ * @param {Object } args.node - A tree node
161+ * @param {Object= } args.parentNode - The parent node of `node`
162+ * @param {number } args.currentIndex - The treeIndex of `node`
163+ * @param {number[]|string[] } args.path - Array of keys leading up to node to be changed
164+ * @param {number[] } args.lowerSiblingCounts - An array containing the count of siblings beneath the
165+ * previous nodes in this path
166+ *
167+ * @return {number|false } nextIndex - Index of the next sibling of `node`,
168+ * or false if the walk should be terminated
125169 */
126170function mapDescendants ( {
127171 callback,
128172 getNodeKey,
129173 ignoreCollapsed,
130174 isPseudoRoot = false ,
131175 node,
176+ parentNode = null ,
132177 currentIndex,
133178 path = [ ] ,
134179 lowerSiblingCounts = [ ] ,
135180} ) {
181+ const nextNode = { ...node } ;
182+
136183 // The pseudo-root is not considered in the path
137- const selfPath = ! isPseudoRoot ? [ ...path , getNodeKey ( { node, treeIndex : currentIndex } ) ] : [ ] ;
138- const selfInfo = ! isPseudoRoot ? { node, path : selfPath , lowerSiblingCounts, treeIndex : currentIndex } : null ;
184+ const selfPath = isPseudoRoot ? [ ] : [
185+ ...path ,
186+ getNodeKey ( { node : nextNode , treeIndex : currentIndex } ) ,
187+ ] ;
188+ const selfInfo = {
189+ node : nextNode ,
190+ parentNode,
191+ path : selfPath ,
192+ lowerSiblingCounts,
193+ treeIndex : currentIndex ,
194+ } ;
139195
140196 // Return self on nodes with no children or hidden children
141- if ( ! node . children || ( node . expanded !== true && ignoreCollapsed && ! isPseudoRoot ) ) {
197+ if ( ! nextNode . children || ( nextNode . expanded !== true && ignoreCollapsed && ! isPseudoRoot ) ) {
142198 return {
143199 treeIndex : currentIndex ,
144200 node : callback ( selfInfo ) ,
@@ -147,15 +203,15 @@ function mapDescendants({
147203
148204 // Get all descendants
149205 let childIndex = currentIndex ;
150- const childCount = node . children . length ;
151- let newChildren = node . children ;
152- if ( typeof newChildren !== 'function' ) {
153- newChildren = newChildren . map ( ( child , i ) => {
206+ const childCount = nextNode . children . length ;
207+ if ( typeof nextNode . children !== 'function' ) {
208+ nextNode . children = nextNode . children . map ( ( child , i ) => {
154209 const mapResult = mapDescendants ( {
155210 callback,
156211 getNodeKey,
157212 ignoreCollapsed,
158213 node : child ,
214+ parentNode : isPseudoRoot ? null : nextNode ,
159215 currentIndex : childIndex + 1 ,
160216 lowerSiblingCounts : [ ...lowerSiblingCounts , childCount - i - 1 ] ,
161217 path : selfPath ,
@@ -167,13 +223,7 @@ function mapDescendants({
167223 }
168224
169225 return {
170- node : callback ( {
171- ...selfInfo ,
172- node : {
173- ...node ,
174- children : newChildren ,
175- } ,
176- } ) ,
226+ node : callback ( selfInfo ) ,
177227 treeIndex : childIndex ,
178228 } ;
179229}
0 commit comments