{"_id":"use-tree-state","_rev":"7-2ac0d8d86dca931f31246ceed3aa27b4","name":"use-tree-state","dist-tags":{"latest":"1.1.1"},"versions":{"1.0.0":{"name":"use-tree-state","version":"1.0.0","description":"A super-light and customizable React hook to manage tree state like never before","main":"dist/use-tree-state.bundle.js","homepage":"https://github.com/shunjizhan/use-tree-state","repository":{"type":"git","url":"git@github.com:shunjizhan/use-tree-state.git"},"bugs":{"url":"https://github.com/shunjizhan/use-tree-state/issues"},"author":{"name":"Shunji Zhan","email":"shunhahaha@live.com"},"license":"MIT","private":false,"keywords":["react","react-hooks","hook","custom-hook","react-state-management","tree-state","react-state","react-state-hook","state-management","treeview","recursion","tree-structure","npm-package","npm-module","folder-picker","folder-viewer","recursion-problem","folder-structure","folder-tooling","folder-tree","recursion-tree","recursions","recursion","tree-structure","treeview","folder-viewer","folder-structure","folder-tooling","treeview-control","tree-node","treeview-component","recursion-tree"],"scripts":{"watch":"yarn nodemon --watch src/ -C -e ts,js -x 'yarn build'","prepublish":"yarn build","prebuild":"rm -rf dist/","build":"webpack --config webpack.config.js","lint":"eslint src/ --ext .js,.jsx","test":"jest --collect-coverage"},"devDependencies":{"@babel/plugin-proposal-optional-chaining":"^7.14.2","@babel/preset-env":"^7.14.2","@babel/preset-react":"^7.13.13","@testing-library/react-hooks":"^7.0.0","babel-eslint":"^10.1.0","babel-loader":"^8.2.2","clean-terminal-webpack-plugin":"^3.0.0","enzyme":"^3.11.0","enzyme-adapter-react-16":"^1.15.6","eslint":"^7.27.0","eslint-config-airbnb":"^18.2.1","eslint-plugin-import":"^2.23.3","eslint-plugin-jsx-a11y":"^6.4.1","eslint-plugin-react":"^7.24.0","eslint-plugin-react-hooks":"^4.2.0","jest":"^27.0.1","nodemon":"^2.0.7","react":"^16.8.0 || ^17","react-dom":"^16.8.0 || ^17","webpack":"^5.37.1","webpack-bundle-analyzer":"^4.4.2","webpack-cli":"^4.7.0"},"peerDependencies":{"react":"^16.8.0 || ^17","react-dom":"^16.8.0 || ^17"},"_id":"use-tree-state@1.0.0","dist":{"shasum":"78e1e629b55faa33e9fef9ee409b383612ff429c","integrity":"sha512-MEHuUbZWGhekkFCboH0HKOhSHe5zm/l0C+GJdg0+vAuBr42VYmCTO9P2NfQMPU3Gkj7Zys93vtpl/fGReuOi5w==","tarball":"https://registry.npmjs.org/use-tree-state/-/use-tree-state-1.0.0.tgz","fileCount":5,"unpackedSize":21217,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJguN/PCRA9TVsSAnZWagAAnCkP/03UoqejvqXKB+8lXvad\nJMBvqIyMxWkfpg/TTZF7p2/aA2whQjHPmPsbk+bpRw5sjkjIHkWPE14l//Id\n+I7J3KLZHnR7OkvP0d94M++YroClcK20cIGQE5ulqfczDr8n0wgXqVStYxw+\n3egHvyXl4KglpTWkUGA8s5zFybUJch/9xdIIJ5CblBWZ2LYU5u0ntxhc2oGG\nA8zX4GQ6Z9mhgoi1GlXlkR8maERdbgSgIQMEdhxdg4fYj+yTQ0nPqFYo5xcJ\nwjqdp7U1ZKBiXGNjdXkrzF2kcDHUUtk8Vbw0Fp4WAxJLf+qbfdZs9CYHS32m\nrIxKPot6k89zIh3WIgHoQw7KeXjB0xwRUzibZ/cVET+998LLWuo7T8fpXpt3\n+r+VlL7UbD918B0UyKbOVAPG+T7b0rBtZMonjwBknfFZVb09cMrx05phzv13\nLl9ow4efgotfzP0z3TtuZP8cfEm03y4OBxPfjma7lJ2MvJWKmNbvFY1NyJag\ntFoZnLjb7HlNkH5XXr02pD0B+UkbeMEsBOsTpXWcmKRD//ajQ2nOzZBfUI4P\nBmIJuVPM79t4yyZz3EoRDjMQ83b7C/i8NpsG8qD+wLXYYjrsoQrcBd7UvKHz\nnA4q/epEeKd/VRIH1oCM1Nalv7kxlPmwKIQ2Uer/VjuLyi3GvxIdZepAdIJQ\nauRK\r\n=bNyx\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIG0OcnTONZQb66IaA4vpiyVEJrDNbBng86LwpqtbzCgtAiB+OCG4rtvXPx37wablFpxkTbMAg7fnDHVzrhgilLNs+Q=="}]},"_npmUser":{"name":"shunjizhan","email":"shunhahaha@live.com"},"directories":{},"maintainers":[{"name":"shunjizhan","email":"shunhahaha@live.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/use-tree-state_1.0.0_1622728655047_0.11317576934796669"},"_hasShrinkwrap":false},"1.0.1":{"name":"use-tree-state","version":"1.0.1","description":"A super-light and customizable React hook to manage tree state like never before","main":"dist/use-tree-state.bundle.js","homepage":"https://github.com/shunjizhan/use-tree-state","repository":{"type":"git","url":"git@github.com:shunjizhan/use-tree-state.git"},"bugs":{"url":"https://github.com/shunjizhan/use-tree-state/issues"},"author":{"name":"Shunji Zhan","email":"shunhahaha@live.com"},"license":"MIT","private":false,"keywords":["react","react-hooks","hook","custom-hook","react-state-management","tree-state","react-state","react-state-hook","state-management","treeview","recursion","tree-structure","npm-package","npm-module","folder-picker","folder-viewer","recursion-problem","folder-structure","folder-tooling","folder-tree","recursion-tree","recursions","recursion","tree-structure","treeview","folder-viewer","folder-structure","folder-tooling","treeview-control","tree-node","treeview-component","recursion-tree"],"scripts":{"watch":"yarn nodemon --watch src/ -C -e ts,js -x 'yarn build'","prepublish":"yarn build","prebuild":"rm -rf dist/","build":"webpack --config webpack.config.js","lint":"eslint src/ --ext .js,.jsx","test":"jest --collect-coverage"},"devDependencies":{"@babel/plugin-proposal-optional-chaining":"^7.14.2","@babel/preset-env":"^7.14.2","@babel/preset-react":"^7.13.13","@testing-library/react-hooks":"^7.0.0","babel-eslint":"^10.1.0","babel-loader":"^8.2.2","clean-terminal-webpack-plugin":"^3.0.0","enzyme":"^3.11.0","enzyme-adapter-react-16":"^1.15.6","eslint":"^7.27.0","eslint-config-airbnb":"^18.2.1","eslint-plugin-import":"^2.23.3","eslint-plugin-jsx-a11y":"^6.4.1","eslint-plugin-react":"^7.24.0","eslint-plugin-react-hooks":"^4.2.0","jest":"^27.0.1","nodemon":"^2.0.7","react":"^16.8.0 || ^17","react-dom":"^16.8.0 || ^17","webpack":"^5.37.1","webpack-bundle-analyzer":"^4.4.2","webpack-cli":"^4.7.0"},"peerDependencies":{"react":"^16.8.0 || ^17","react-dom":"^16.8.0 || ^17"},"_id":"use-tree-state@1.0.1","dist":{"shasum":"c19e25a561dd84e9ab1496fc710820f7244cd5b3","integrity":"sha512-rC8qR1/uIrQaQOF+ZZIYFXRmO6IIGAdvY5LtmwEwJsJ3onv41eZGKDgXx+6rVzzPVx9Ys6ZroPGbxtBIoFPYqw==","tarball":"https://registry.npmjs.org/use-tree-state/-/use-tree-state-1.0.1.tgz","fileCount":5,"unpackedSize":21259,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgujN4CRA9TVsSAnZWagAAeNwP/06btZyWriHQtCIDuO09\nw+4yeRnvlOin6aaMt4mjBsSkGR4eBqPtEhObVegIpkC8uyGmxu3F6TzyLvF8\n7+sZKJLOckRa6NNlmZEjBO8H1enk5BaDB6HkLpyvvi0gZYZ8FVubPvjwHKQ8\nyrZPXZ8UZijRkI6bVJb7e7evw9CceSJZFwFizbuL/x8IhZ+UstIZk824X4Xu\nz0SByPqulNVOsEI3yklJ4hOhy7+I9NxR4u7sJn21RXoOyFW0/+1ANCPZuAB2\nV2uFBfU2H/1yQq0wQbXyjumQqdieoNlm8HyoCfMUIxTUEvDcUmmK0K9Ed+WB\nEtYzs9VqjKfA/WplN0Vx93wqSghefQUrkXOOMbaAMEXQWBekrOYxOy572ngd\nFRDpOTwUxXVyrWF1mEAYMtTSD2R47Aghk+Py8JuxR00W6BF5vvOMZgPBqyGG\ndjH6tc1FHnCUIJg9s60CRtpkgPWan//CVl4J6ogC0BRgn2uS4mnaqa2IbOeA\n42COe7bLn5o+IBm4xGd2MLB7vNLfPmR9Md16fOhecJHoske9tyMxmBg3XzGN\nv2xkWJT9G9rqPN03EmhJs7UbWXW26zQioUJUxd9EMwjFMxTYL/GCtbC+1Syo\ni/i9KK+j8zMoWNZe62F1/4muw184AkwSan9hVlsZ+rSuZ/STqxDmyxhwlBah\nI2ow\r\n=mkO7\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFCcua5MymNpY8dSCV4s8LK3MtM5Q6riN71wpKgkNwrhAiEAitHMOgTsueQrjhkdRfrqrcMpLxL4QBwDaFodqLjtFmk="}]},"_npmUser":{"name":"shunjizhan","email":"shunhahaha@live.com"},"directories":{},"maintainers":[{"name":"shunjizhan","email":"shunhahaha@live.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/use-tree-state_1.0.1_1622815608752_0.6499936045879962"},"_hasShrinkwrap":false},"1.0.2":{"name":"use-tree-state","version":"1.0.2","description":"A super-light and customizable React hook to manage tree state like never before","main":"dist/use-tree-state.bundle.js","homepage":"https://github.com/shunjizhan/use-tree-state","repository":{"type":"git","url":"git@github.com:shunjizhan/use-tree-state.git"},"bugs":{"url":"https://github.com/shunjizhan/use-tree-state/issues"},"author":{"name":"Shunji Zhan","email":"shunhahaha@live.com"},"license":"MIT","private":false,"keywords":["react","react-hooks","hook","custom-hook","react-state-management","tree-state","react-state","react-state-hook","state-management","treeview","recursion","tree-structure","npm-package","npm-module","folder-picker","folder-viewer","recursion-problem","folder-structure","folder-tooling","folder-tree","recursion-tree","recursions","recursion","tree-structure","treeview","folder-viewer","folder-structure","folder-tooling","treeview-control","tree-node","treeview-component","recursion-tree"],"scripts":{"watch":"yarn nodemon --watch src/ -C -e ts,js -x 'yarn build'","prepublish":"yarn build","prebuild":"rm -rf dist/","build":"webpack --config webpack.config.js","lint":"eslint src/ --ext .js,.jsx","test":"jest --collect-coverage"},"devDependencies":{"@babel/plugin-proposal-optional-chaining":"^7.14.2","@babel/preset-env":"^7.14.2","@babel/preset-react":"^7.13.13","@testing-library/react-hooks":"^7.0.0","babel-eslint":"^10.1.0","babel-loader":"^8.2.2","clean-terminal-webpack-plugin":"^3.0.0","enzyme":"^3.11.0","enzyme-adapter-react-16":"^1.15.6","eslint":"^7.27.0","eslint-config-airbnb":"^18.2.1","eslint-plugin-import":"^2.23.3","eslint-plugin-jsx-a11y":"^6.4.1","eslint-plugin-react":"^7.24.0","eslint-plugin-react-hooks":"^4.2.0","jest":"^27.0.1","nodemon":"^2.0.7","react":"^16.8.0 || ^17","react-dom":"^16.8.0 || ^17","webpack":"^5.37.1","webpack-bundle-analyzer":"^4.4.2","webpack-cli":"^4.7.0"},"peerDependencies":{"react":"^16.8.0 || ^17","react-dom":"^16.8.0 || ^17"},"_id":"use-tree-state@1.0.2","dist":{"shasum":"0fe5d1cbeae0fdcdc0a7e69ee72842db0a36184e","integrity":"sha512-rPE2MQI6+TNqVQKP4eJdfdGC29UH05Rwd0Krpal44sCkeFzJJRXMxWX2f1pNdW1zHAVUphb5NB1PDDCPgoA0xg==","tarball":"https://registry.npmjs.org/use-tree-state/-/use-tree-state-1.0.2.tgz","fileCount":5,"unpackedSize":21652,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgukRsCRA9TVsSAnZWagAAeREP/1+mr+HuQT+9idiRPucC\nj69wv4THNLgNItcZar0aRnx0etwMb0ipXSaX9RYyDv0hou8i4HmO7LrzVvdw\nDeuoPJmEvhQqkTNMLV4KnOufDDC1fy6/LhwIVyMguHrXxTj8yDv/04W10Smt\nhnVAau1zcCCmVo/jFRLw9xELfGvVnRqLSc4kjiN5DkHRTqm8Df6N4O54XxeC\nSh2p13rNxKN3IhGlp2SyafMDpSNcoaO1Z3yXUC/Amfl3sJK15zlJfVyPVBb6\nGT8i3593TgY8gOphm5atRs1EU1QB2TOSQL2ceIaty4PDFMuTnEYOqDu6NITJ\nxgeF+Hdtj/m9LhQ0nca+wqIjJrp618l8BrOD1wcHq+UfkRF3m+MrbEuOXl8P\nAfAOU/EGKf/Tyu4wDK2ugCUd9ykatWwgcJfMGNJvCsVLQBTLPVKiWOzbGj1q\nWQVT2/FcI0mHJk8bc+JCoD6NNPmDf98Ym3H2b8pMBiBvWyKAQvwnjPMHO531\npdYPkquOO5mF6M9R6DhawvAMKqUoZrc+/smorKrXLi3A2MO3CA62s/9agjqq\nXLbD8uXLI12jJvaYak7zldWr40k9egP6DobQLyjF9haszAPtdaeKZ9xYbrQa\nbLEAjnUb+qdh6Sv4tDmS3PePYWmy78UXp8tvuUEvngeW8Zo7VcSLPbmc0h9u\nIm+J\r\n=sbxq\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCeWLcOBTmDsPwLKOg9z7gWdaa8ex1YuFZlwIlbeaaV9QIgCd3ucG7efITTXLgO3oScZo6Ks1sbKm+tbG8edWg9g34="}]},"_npmUser":{"name":"shunjizhan","email":"shunhahaha@live.com"},"directories":{},"maintainers":[{"name":"shunjizhan","email":"shunhahaha@live.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/use-tree-state_1.0.2_1622819948283_0.9614649717325936"},"_hasShrinkwrap":false},"1.0.3":{"name":"use-tree-state","version":"1.0.3","description":"A super-light and customizable React hook to manage tree state like never before","main":"dist/use-tree-state.bundle.js","homepage":"https://github.com/shunjizhan/use-tree-state","repository":{"type":"git","url":"git@github.com:shunjizhan/use-tree-state.git"},"bugs":{"url":"https://github.com/shunjizhan/use-tree-state/issues"},"author":{"name":"Shunji Zhan","email":"shunhahaha@live.com"},"license":"MIT","private":false,"keywords":["react","react-hooks","hook","custom-hook","react-state-management","tree-state","react-state","react-state-hook","state-management","treeview","recursion","tree-structure","npm-package","npm-module","folder-picker","folder-viewer","recursion-problem","folder-structure","folder-tooling","folder-tree","recursion-tree","recursions","recursion","tree-structure","treeview","folder-viewer","folder-structure","folder-tooling","treeview-control","tree-node","treeview-component","recursion-tree"],"scripts":{"watch":"yarn nodemon --watch src/ -C -e ts,js -x 'yarn build'","prepublish":"yarn build","prebuild":"rm -rf dist/","build":"webpack --config webpack.config.js","lint":"eslint src/ --ext .js,.jsx","test":"jest --collect-coverage"},"devDependencies":{"@babel/plugin-proposal-optional-chaining":"^7.14.2","@babel/preset-env":"^7.14.2","@babel/preset-react":"^7.13.13","@testing-library/react-hooks":"^7.0.0","babel-eslint":"^10.1.0","babel-loader":"^8.2.2","clean-terminal-webpack-plugin":"^3.0.0","enzyme":"^3.11.0","enzyme-adapter-react-16":"^1.15.6","eslint":"^7.27.0","eslint-config-airbnb":"^18.2.1","eslint-plugin-import":"^2.23.3","eslint-plugin-jsx-a11y":"^6.4.1","eslint-plugin-react":"^7.24.0","eslint-plugin-react-hooks":"^4.2.0","jest":"^27.0.1","nodemon":"^2.0.7","react":"^16.8.0 || ^17","react-dom":"^16.8.0 || ^17","webpack":"^5.37.1","webpack-bundle-analyzer":"^4.4.2","webpack-cli":"^4.7.0"},"peerDependencies":{"react":"^16.8.0 || ^17","react-dom":"^16.8.0 || ^17"},"_id":"use-tree-state@1.0.3","dist":{"shasum":"c302224a6a3820187e97e933d763e1b8de8ce32b","integrity":"sha512-qb0yFQIFiJB6reSgwD8IM9ng/NGIQAjDpbsdnmqH9oBf8LdNaEkxC89BGP9uHwaCkRinb1kYCU7QUKG//JkHKQ==","tarball":"https://registry.npmjs.org/use-tree-state/-/use-tree-state-1.0.3.tgz","fileCount":5,"unpackedSize":21647,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgulqMCRA9TVsSAnZWagAAFEQQAIh0PICToVv9qksATeM2\nZWDaXsT/hNa+vPTgXybCJttgBZXUWyt1V+ddt03gdqg1mXLywUz7yi7hmjz/\navCRGD2Qe0IdAooxol91hLnqGxxjaQc8fCMsnY+ctBZWxSSGsCVjTXG6jTPJ\nrlV5uoQ3CNvpFTZc4fI6jpnVrlTrCTkFGsF51d0pvTsOsAPEOAiuXWJy1zg1\nOqdYTe3wH3WW+mXrEIteoUTmkkGBdO64Dgq+ffkm71ouc9to2ak/i3CjZs2w\nUgphMJwSbMA82nsujdTuJo4WS1UB5k6Y9fFi59LwTiVgxmZ8RzLArOYsWOo2\nVRS65KRsiXJnfElISO1yGtBW7J6L2y5EO6bXl/V85IWwXScipEQfL0OQB4ad\nyChngU5xnGnWSqa0/fC9w3m8H8rehNYJr4C2pC44WADt/CXP4bfZm13WMBFh\nmAQhDJzvhLXgNeG4VXPvbOIBrbJParBwee4M/iRzGzJxXLfw3Q9vZ8aOzEgM\nQX0I4K66Cf/fpjOCJczyJ0qtsY5PXX7p1P7vfEGHR3d5smW+IYJ2er4litdP\nQMT/LCXMSIR819z2nfRF1KMVAD70A49tVANuBzDLxKINyPvXIqa74vWKriC8\nXsNFMu0NRKjRX9ovZMaOsHKxRz7abGCQcSUC7hcofpzjqi8AyUaTZQypdT4m\nNdHs\r\n=HtZD\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCrIG2OQKLM7Zwn3d3jEMtPkhxh9wv1HlR8bUYJvRCu3wIgJXI7r+v2sttz4IlRRa77Ga2CXkImNnyGP0BMkTX7UvA="}]},"_npmUser":{"name":"shunjizhan","email":"shunhahaha@live.com"},"directories":{},"maintainers":[{"name":"shunjizhan","email":"shunhahaha@live.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/use-tree-state_1.0.3_1622825612470_0.07369689524179224"},"_hasShrinkwrap":false},"1.0.4":{"name":"use-tree-state","version":"1.0.4","description":"A super-light and customizable React hook to manage tree state like never before","main":"dist/use-tree-state.bundle.js","homepage":"https://github.com/shunjizhan/use-tree-state","repository":{"type":"git","url":"git@github.com:shunjizhan/use-tree-state.git"},"bugs":{"url":"https://github.com/shunjizhan/use-tree-state/issues"},"author":{"name":"Shunji Zhan","email":"shunhahaha@live.com"},"license":"MIT","private":false,"keywords":["react","react-hooks","hook","custom-hook","react-state-management","tree-state","react-state","react-state-hook","state-management","treeview","recursion","tree-structure","npm-package","npm-module","folder-picker","folder-viewer","recursion-problem","folder-structure","folder-tooling","folder-tree","recursion-tree","recursions","recursion","tree-structure","treeview","folder-viewer","folder-structure","folder-tooling","treeview-control","tree-node","treeview-component","recursion-tree"],"scripts":{"watch":"yarn nodemon --watch src/ -C -e ts,js -x 'yarn build'","prepublish":"yarn build","prebuild":"rm -rf dist/","build":"webpack --config webpack.config.js","lint":"eslint src/ --ext .js,.jsx","test":"jest --collect-coverage"},"devDependencies":{"@babel/plugin-proposal-optional-chaining":"^7.14.2","@babel/preset-env":"^7.14.2","@babel/preset-react":"^7.13.13","@testing-library/react-hooks":"^7.0.0","babel-eslint":"^10.1.0","babel-loader":"^8.2.2","clean-terminal-webpack-plugin":"^3.0.0","enzyme":"^3.11.0","enzyme-adapter-react-16":"^1.15.6","eslint":"^7.27.0","eslint-config-airbnb":"^18.2.1","eslint-plugin-import":"^2.23.3","eslint-plugin-jsx-a11y":"^6.4.1","eslint-plugin-react":"^7.24.0","eslint-plugin-react-hooks":"^4.2.0","jest":"^27.0.1","nodemon":"^2.0.7","react":"^16.8.0 || ^17","react-dom":"^16.8.0 || ^17","webpack":"^5.37.1","webpack-bundle-analyzer":"^4.4.2","webpack-cli":"^4.7.0"},"peerDependencies":{"react":"^16.8.0 || ^17","react-dom":"^16.8.0 || ^17"},"_id":"use-tree-state@1.0.4","dist":{"shasum":"e2b8f27b98991b537635851b7ba37e25393eb066","integrity":"sha512-v/rBvMElO7K3ZMlN0YQ5s/5Q8hC5yBVjJSN0vnJci+dglpFSrCydkWFT9ZU3hUu9xx0/5KndMNWaS8pErPF1CA==","tarball":"https://registry.npmjs.org/use-tree-state/-/use-tree-state-1.0.4.tgz","fileCount":6,"unpackedSize":23622,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgu4kNCRA9TVsSAnZWagAAqGkP/1u79mqTlTjhHP0omAJ8\nLVXGy8vfJX3iYE2J7ikwZACpCOB6xTXiI8iyuYxIV/HrPCTb7hrEISupJQP6\nHO9eAVsQ1lWdgx6jET846ZBfZWAOtSO+/R82ogKqhVaxbTu1a83ODQK362fr\nbkqSTgrEp7ZI5DewgI+ABPtQEIyTLQW3y4spfhp1y1sISuXh1xa20KObt+Bk\nUNwJWkSL6XauUtlLgGgIElN04KjD8maBTKbS/5NxW4K4l8OFajX55mJ+ct63\n6E0ceYFBeR/s7Uy2kHs1UJDZjAGLwFkQwPNN8j07Ab/cXH7vhcjwI/45bUsD\n5BygCq0BhN371Rtkqi0r2uFOhSg2SJ2IGHWLakee8Ehx/kCS7huTh3ZTmtxz\nmfp9n85dvwzItgpxjoNw4nEXTOp9SOGT4+ATuPLxtN9Ykw/10Mdk1rXNt2RN\ni+YUHu9d2MU1RgqBYp28e9VT8XNyEcve9ksDit7NrN2uv/nVbzwKnFHmm9eB\nIrYAUopYY/A4AtGX9mnYS0wkWl5xkfOb/0M3WmrUp3v7OJYhmyJDOaaN3fHx\nA++IiG61TfEQkTjN3jq5jed8S9D9Tn9RsrK7kaDeI9oKWBEiF7tt8g0U/YT3\nzoEWiprhjsMC68v+CFvfvBfKkxlIWJmgGgQ8S1yHlst6g4H9YPA4waiYYWXM\nHx/Z\r\n=DOTC\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDdQqLRu5WCNoblSSVWXvXKZIO2fpoIY/nNb70qePAu5AiEAg9Osd4nwsySTpIntx/fl6YCfEtPVDEkPzKMovT+jx+E="}]},"_npmUser":{"name":"shunjizhan","email":"shunhahaha@live.com"},"directories":{},"maintainers":[{"name":"shunjizhan","email":"shunhahaha@live.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/use-tree-state_1.0.4_1622903053842_0.2918953864700937"},"_hasShrinkwrap":false},"1.1.0":{"name":"use-tree-state","version":"1.1.0","description":"A super-light and customizable React hook to manage tree state like never before","main":"dist/use-tree-state.bundle.js","homepage":"https://github.com/shunjizhan/use-tree-state","repository":{"type":"git","url":"git@github.com:shunjizhan/use-tree-state.git"},"bugs":{"url":"https://github.com/shunjizhan/use-tree-state/issues"},"author":{"name":"Shunji Zhan","email":"shunhahaha@live.com"},"license":"MIT","private":false,"keywords":["react","react-hooks","hook","custom-hook","react-state-management","tree-state","react-state","react-state-hook","state-management","treeview","recursion","tree-structure","npm-package","npm-module","folder-picker","folder-viewer","recursion-problem","folder-structure","folder-tooling","folder-tree","recursion-tree","recursions","recursion","tree-structure","treeview","folder-viewer","folder-structure","folder-tooling","treeview-control","tree-node","treeview-component","recursion-tree"],"scripts":{"watch":"yarn nodemon --watch src/ -C -e ts,js -x 'yarn build'","prepublish":"yarn build","prebuild":"rm -rf dist/","build":"webpack --config webpack.config.js","lint":"eslint src/ --ext .js,.jsx","test":"jest --collect-coverage"},"devDependencies":{"@babel/plugin-proposal-optional-chaining":"^7.14.2","@babel/preset-env":"^7.14.2","@babel/preset-react":"^7.13.13","@testing-library/react-hooks":"^7.0.0","@wojtekmaj/enzyme-adapter-react-17":"^0.6.1","babel-eslint":"^10.1.0","babel-loader":"^8.2.2","clean-terminal-webpack-plugin":"^3.0.0","codecov":"^3.8.2","enzyme":"^3.11.0","enzyme-adapter-react-16":"^1.15.6","eslint":"^7.27.0","eslint-config-airbnb":"^18.2.1","eslint-plugin-import":"^2.23.3","eslint-plugin-jsx-a11y":"^6.4.1","eslint-plugin-react":"^7.24.0","eslint-plugin-react-hooks":"^4.2.0","jest":"^27.0.1","nodemon":"^2.0.7","react":"^16.8.0 || ^17","react-dom":"^16.8.0 || ^17","webpack":"^5.37.1","webpack-bundle-analyzer":"^4.4.2","webpack-cli":"^4.7.0"},"peerDependencies":{"react":"^16.8.0 || ^17","react-dom":"^16.8.0 || ^17"},"_id":"use-tree-state@1.1.0","dist":{"shasum":"0a6cce2fcd54a0581de0f8d876948a0519bd90a0","integrity":"sha512-pyq1E5bs9oby4ZSrVwhxOIWWaF7KQcQke8h4A33SP/bzkj9L6YP+myNEevQPUhlGEZWxlJUia07A3rM1ihrQkQ==","tarball":"https://registry.npmjs.org/use-tree-state/-/use-tree-state-1.1.0.tgz","fileCount":6,"unpackedSize":24753,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgv2MfCRA9TVsSAnZWagAA70wP/0hA40vBl9/hn1PH+SN2\na2vweMasuHjmJfdQlrG/KyWOe76a8io1Cbx+Xn10OUrz+6D7a3RdtW4D3h0+\nti237oF6didOPhPd5L+zNCSmlePZo7QVosc6v0CLQfx6kt1aWX9chPcFTckn\n3JCnB4kS3/xzZuh7KcZFe28nf/Wgtuv9cGCo5soWochm1cvl21wI0ehuu86h\nbTwk0NmA8X/74e7qs/QuqZJ9x39UMeW42m3toQowTSEfkgur23dWqw6I2ApC\n535MlhQyU5oGkuM6m7f8zO8+jcQM6xQ6LDb5QjN52ewddJk/ySiz8rjxxhD8\nJ4njtLPC9Ebbn8IVfBlJe4TMfgUJLpImpcFe19NAVr/5O22pBGnK4lUH7IGT\nYWMPlvijd+6RwTihnZG7ltLmSk2mYt/o7G1C7ZtB5gUpJ9q/171tVD8JRsNz\n1Xnw5b5EN+8EECAc1r9AAdgx2gCliF1WIU5gV0I+Ghau7tob5V8RmSxjntyM\n0PjVe2pGufPQtlujhI+ICFQrEb8xZ68KXae1dt0q8639KXa7KYyHbg+P7uUe\ncaNukFscmpuPXO7Z4WIN49i5QyH+kTIbhzEKTVIUZuxSpgBYGONLnvpF++Hw\naaGjWoVtEmJ1czN/f9Bq59ay+JdvNW20H+9HsrDODKQFYoa9B+GHoPFpczeO\nJBbv\r\n=AnA6\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCcGUfxioYJt5eMqL8s9fNZLIejXF68E52Kc9TgLUPbXwIhAMqL9Tr6poSEAKDoJtYmwK0vsG1FF3hCFeUQvyjbyMTN"}]},"_npmUser":{"name":"shunjizhan","email":"shunhahaha@live.com"},"directories":{},"maintainers":[{"name":"shunjizhan","email":"shunhahaha@live.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/use-tree-state_1.1.0_1623155487200_0.2305530703811116"},"_hasShrinkwrap":false},"1.1.1":{"name":"use-tree-state","version":"1.1.1","description":"A super-light and customizable React hook to manage tree state like never before","main":"dist/use-tree-state.bundle.js","homepage":"https://github.com/shunjizhan/use-tree-state","repository":{"type":"git","url":"git@github.com:shunjizhan/use-tree-state.git"},"bugs":{"url":"https://github.com/shunjizhan/use-tree-state/issues"},"author":{"name":"Shunji Zhan","email":"shunhahaha@live.com"},"license":"MIT","private":false,"keywords":["react","react-hooks","hook","custom-hook","react-state-management","tree-state","react-state","react-state-hook","state-management","treeview","recursion","tree-structure","npm-package","npm-module","folder-picker","folder-viewer","recursion-problem","folder-structure","folder-tooling","folder-tree","recursion-tree","recursions","recursion","tree-structure","treeview","folder-viewer","folder-structure","folder-tooling","treeview-control","tree-node","treeview-component","recursion-tree"],"scripts":{"watch":"yarn nodemon --watch src/ -C -e ts,js -x 'yarn build'","prepublish":"yarn build","prebuild":"rm -rf dist/","build":"webpack --config webpack.config.js","lint":"eslint src/ --ext .js,.jsx","test":"jest --collect-coverage"},"devDependencies":{"@babel/plugin-proposal-optional-chaining":"^7.14.2","@babel/preset-env":"^7.14.2","@babel/preset-react":"^7.13.13","@testing-library/react-hooks":"^7.0.0","@wojtekmaj/enzyme-adapter-react-17":"^0.6.1","babel-eslint":"^10.1.0","babel-loader":"^8.2.2","clean-terminal-webpack-plugin":"^3.0.0","codecov":"^3.8.2","enzyme":"^3.11.0","enzyme-adapter-react-16":"^1.15.6","eslint":"^7.27.0","eslint-config-airbnb":"^18.2.1","eslint-plugin-import":"^2.23.3","eslint-plugin-jsx-a11y":"^6.4.1","eslint-plugin-react":"^7.24.0","eslint-plugin-react-hooks":"^4.2.0","jest":"^27.0.1","nodemon":"^2.0.7","react":"^16.8.0 || ^17","react-dom":"^16.8.0 || ^17","webpack":"^5.37.1","webpack-bundle-analyzer":"^4.4.2","webpack-cli":"^4.7.0"},"peerDependencies":{"react":"^16.8.0 || ^17","react-dom":"^16.8.0 || ^17"},"_id":"use-tree-state@1.1.1","dist":{"shasum":"229c0eb1019c382c446506b474f676ecfedd7b11","integrity":"sha512-oNLnmUaAef97UGvw83L0tfTYj7ZBmPdf3tsaehr8FumSdq9Th/cc97jVTnSoOCoq9wYmhDuSffJxHv+wbgUlrA==","tarball":"https://registry.npmjs.org/use-tree-state/-/use-tree-state-1.1.1.tgz","fileCount":6,"unpackedSize":24980,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJg1wg5CRA9TVsSAnZWagAAgMkQAJyKtGdu5e9YEFO7IIwC\npFstf866vGi7VcXpSL//5Js3Ow+3CKdI2dRGzqetS5AVwcEB7/vnqSuEzmDQ\nKOoAD8ajbU9qdlViJAzFOvWsvvz3HqiH1A/F9lYz0fKyeeXNrGNO+MN/RC5H\nYFC0SZkIJHbi0By1P9SGzkJharMLcgVZ9kbD6/xLw0II5EOWH5fvMjKfbgXl\nv1jysMAUmtTB6dgQCAL5JJfHH16NIGi+MtfwQze+OaxtXW1Wns8yOH+Q446l\n63Gd5+w/6WVuMC3BD0xOQlant9SlRVtoae5538fuW3plGq4CcvuKcAiDTvKB\nBR03UrEagmUqFgYZy1mYXTgV+wzgZY5lkS6V7Vv5tZgiZpnktEOqDkcCsoO7\n7LqDrexiXE+3rpXvizuTn+GCl54yWAtgxbEFBf4xTVvVR96pa9wJlIrO6tY/\nUm/kVV+BuzPLyTKJ3t3lD4WChhqgV9WbjOPyFepfRYJxCMHXaNkMlULDqkcB\nXaoo9IJiR9YBtzeUCnuHf0A58x3eOkMc9bqJu4MkOYST+JbDb4LJWeK14g6j\nIjHZrm8jfQgcuB+u0QI377rC/QIKiX0Lj1Jgvt5k2R/nmZx5kjAdXMns84Qg\njz3CXqrN8RbBpcqcKJ01XPRRxHkYYoAhy2ac97O7cG4g9Gq8QUTRJ4WKzTS4\n7ccr\r\n=Uryi\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCY4j7ACGKgIjLjVpk/0sN+Lhr82nVrdfT98T781UxIPAIgRk9ycy0zu/05wk8NvkeCtvSs3yYiWoeayBEIUNuTksw="}]},"_npmUser":{"name":"shunjizhan","email":"shunhahaha@live.com"},"directories":{},"maintainers":[{"name":"shunjizhan","email":"shunhahaha@live.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/use-tree-state_1.1.1_1624705081334_0.04801245253601594"},"_hasShrinkwrap":false}},"time":{"created":"2021-06-03T13:57:35.046Z","1.0.0":"2021-06-03T13:57:35.176Z","modified":"2022-05-22T22:47:25.842Z","1.0.1":"2021-06-04T14:06:48.967Z","1.0.2":"2021-06-04T15:19:08.415Z","1.0.3":"2021-06-04T16:53:32.609Z","1.0.4":"2021-06-05T14:24:13.987Z","1.1.0":"2021-06-08T12:31:27.395Z","1.1.1":"2021-06-26T10:58:01.489Z"},"maintainers":[{"name":"shunjizhan","email":"shunhahaha@live.com"}],"description":"A super-light and customizable React hook to manage tree state like never before","homepage":"https://github.com/shunjizhan/use-tree-state","keywords":["react","react-hooks","hook","custom-hook","react-state-management","tree-state","react-state","react-state-hook","state-management","treeview","recursion","tree-structure","npm-package","npm-module","folder-picker","folder-viewer","recursion-problem","folder-structure","folder-tooling","folder-tree","recursion-tree","recursions","recursion","tree-structure","treeview","folder-viewer","folder-structure","folder-tooling","treeview-control","tree-node","treeview-component","recursion-tree"],"repository":{"type":"git","url":"git@github.com:shunjizhan/use-tree-state.git"},"author":{"name":"Shunji Zhan","email":"shunhahaha@live.com"},"bugs":{"url":"https://github.com/shunjizhan/use-tree-state/issues"},"license":"MIT","readme":"# Use Tree State\n[![travis build](https://img.shields.io/travis/com/shunjizhan/use-tree-state?logo=travis)](https://travis-ci.com/shunjizhan/use-tree-state) [![codecov](https://codecov.io/gh/shunjizhan/use-tree-state/branch/main/graph/badge.svg?token=R15MSCTFHN)](https://codecov.io/gh/shunjizhan/use-tree-state) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/use-tree-state?color=light%20green&label=only&logo=webpack) ![dependency](https://img.shields.io/badge/dependency-zero-brightgreen?&logo=git)  \n[![npm](https://img.shields.io/npm/v/use-tree-state?logo=npm)](https://www.npmjs.com/package/use-tree-state) [![npm](https://img.shields.io/npm/dm/use-tree-state?logo=DocuSign&color=blue)](https://www.npmjs.com/package/use-tree-state) ![GitHub top language](https://img.shields.io/github/languages/top/shunjizhan/use-tree-state?logo=react)\n\nA super-light and customizable React hook to manage tree state like never before ✨✨\n\nAn example package that uses this hook internally: [react-folder-tree](https://www.npmjs.com/package/react-folder-tree)\n## Features\n✅ **built in CRUD handlers**: `add`, `modify`, `delete` tree nodes with 1 line of code  \n✅ **custom handlers**: define any custom state transition for your need  \n✅ **half check**: auto calculate new `checked` status for all nodes  \n✅ **onChange**: listen to state change and events  \n\n## Usage\n### 🌀 install\n```bash\n$ yarn add use-tree-state\n$ npm install use-tree-state --save\n```\n\n### 🌀 initialization\n```ts\nimport useTreeState, { testData } from 'use-tree-state';\n\nconst TreeApp = () => {\n  const { treeState } = useTreeState({ data: testData });\n\n  return (<Tree state={ treeState } />);\n};\n```\n\n### 🌀 custom initialization\nInitial tree state is an object that describes a nested tree node structure, which looks like:\n```jsx\n{\n  // reserved keys, can customize initial value\n  name: 'root node',  \n  checked (optional): 0 (unchecked, default) | 0.5 (half checked) | 1(checked),\n  isOpen (optional): true (default) | false,\n  children (optional): [array of treenode],\n\n  // internal key (auto generated), plz don't include it in the initial data\n  _id: 0,\n\n  // all other keys are not reserved, can carry any extra info about this node\n  nickname (optional): 'pikachu',\n  url (optional): 'www.pokemon.com',\n  ...\n}\n```\n`checked` and `isOpen` status could be auto initialized by props `initCheckedStatus` and `initOpenStatus`. We can also provide data with custom `checked` and `isOpen` status, and set `initCheckedStatus` and `initOpenStatus` to `'custom'`.\n\nExample:\n```ts\nconst { treeState } = useTreeState({\n  data: testData,\n  options: {\n    initCheckedStatus: 'checked',   // 'unchecked' (default) | 'checked' | 'custom'\n    initOpenStatus: 'open',         // 'open' (default) | 'closed' | 'custom'\n  }\n});\n```\n\n### 🌀 update tree state\nThere are a couple built in tree state reducers that can update tree state conveniently.\n\nNote that these `reducers` are slightly different than `redux reducers`. These are more like  `wrapped reducers` which are functions that\n\n`f(path: array<int>, ...args) => update state internally`  \nor   \n`fByProp(propName: string, targetValue: any, ...args) => update state internally`\n\nFor more details please refer to [Built-in Reducers](#built-in-reducers) section.\n```ts\nconst TreeApp = () => {\n  const { treeState, reducers } = useTreeState({ data: testData });\n  const {\n    // update state using node's path to find target\n    checkNode,\n    toggleOpen,\n    renameNode,\n    deleteNode,\n    addNode,\n\n    // update state using any node's property to find target\n    checkNodeByProp,\n    toggleOpenByProp,\n    renameNodeByProp,\n    deleteNodeByProp,\n    addNodeByProp,\n  } = reducers;\n\n  const check_first_node = () => checkNode([0]);\n  const check_node_whos_name_is_Goku = () => checkNodeByProp('name', 'Goku');\n\n  const open_first_node = () => toggleOpen([0], 1);\n  const open_node_whos_url_is_www = () => toggleOpenByProp('url', 'www', 1);\n  const close_node_whos_num_is_123 = () => toggleOpenByProp('num', 123, 0);\n\n  const rename_third_node_to_pikachu = () => renameNode([2], 'pikachu');\n  const rename_snorlax_node_to_pikachu = () => renameNode('name', 'snorlax', 'pikachu');\n\n  const remove_fourth_node = () => deleteNode([3]);\n  const remove_unnecessary_node = () => deleteNodeByProp('necessary', false);\n\n  const add_leaf_node_in_root_node = () => addNode([], false);\n  const add_parent_node_in_Pokemon_node = () => addNodeByProp('type', 'Pokemon', true);\n\n  return (...);\n};\n```\n\n### 🌀 onChange listener\nwe can pass in an `onChange(newState: tree-state-obj, event: obj)` to the hook to listen for state change event.\n```ts\nconst handleStateChange = (newState, event) => {\n  const { type, path, params } = event;\n\n  console.log('last event: ', { type, path, params });\n  console.log('state changed to: ', newState);\n};\n\nconst { treeState } = useTreeState({\n  data: testData,\n  onChange: handleStateChange,      // <== here!!\n});\n```\n\n\n## Built-in Reducers\nThere are two types of built in reducers (or call it handlers if you prefer) that differ in how they find target node to operate on.\n\n#### 1) find target node by path\n- `reducers.checkNode`\n- `reducers.toggleOpen`\n- `reducers.renameNode`\n- `reducers.deleteNode`\n- `reducers.addNode`\n\ntheir format is `f(path: array<int>, ...args) => update state internally`, where `path` is an array of indexes from root to the target node.\n\nAn example that shows each node and corresponding path\n```ts\nconst treeState = {\n  name: 'root',         // path = []\n  children: [\n    { name: 'node_0' }    // path = [0]\n    { name: 'node_1' }    // path = [1]\n    {\n      name: 'node_2',     // path = [2]\n      children: [\n        { name: 'node_2_0' },   // path = [2, 0]\n        { name: 'node_2_1' },   // path = [2, 1]\n      ],\n    }\n  ],\n};\n```\n\n#### 2) find target node by property (can be any property in tree node data)\n- `reducers.checkNodeByProp`\n- `reducers.toggleOpenByProp`\n- `reducers.renameNodeByProp`\n- `reducers.deleteNodeByProp`\n- `reducers.addNodeByProp`\n\ntheir format is `fByProp(propName: string, targetValue: any, ...args) => update state internally`\n\n\n### 🌀 reducers details\n\n#### • `checkNode(path: array<int>, checked: 1 | 0)`\n#### • `checkNodeByProp(propName: string, targetValue: any, checked: 1 | 0)`\nSet `checked` property of the target node, `1` for 'checked', `0` for 'unchecked'.\n\nIt will also update checked status for all other nodes:\n- if we (un)checked a parent node, all children nodes will also be (un)checked\n- if some (but not all) of a node's children are checked, this node becomes half check (internally set `checked` = 0.5)\n\n<br>\n\n#### • `toggleOpen(path: array<int>, isOpen: bool)`\n#### • `toggleOpenByProp(propName: string, targetValue: any, isOpen: bool)`\nSet the open status `isOpen` for the target node. `isOpen: false` usually means in UI we shouldn't see it's children.\n\n**This only works for parent nodes**, which are the nodes that has `children` property.\n\n<br>\n\n#### • `renameNode(path: array<int>, newName: string)`\n#### • `renameNodeByProp(propName: string, targetValue: any, newName: string)`\nYou know what it is.\n\n<br>\n\n#### • `deleteNode(path: array<int>)`\n#### • `deleteNodeByProp(propName: string, targetValue: any)`\nDelete the target node. If target node is a parent, all of it's children will also be removed.\n\n<br>\n\n#### • `addNode(path: array<int>, hasChildren: bool)`\n#### • `addNodeByProp(propName: string, targetValue: any, hasChildren: bool)`\nAdd a node as a children of target node. `hasChildren: true` means this new node is a parent node, otherwise it is a leaf node.\n\n**This only works for parent nodes**.\n\n<br>\n\n#### • `setTreeState(newState: tree-state-object)`\nInstead of 'update' the tree state, this will set whole tree state directly. Didn't test this method, but leave this api anyways, so use with cautions! And plz [open an issue](https://github.com/shunjizhan/use-tree-state/issues) if it doesn't work : )\n\n## Custom Reducers\nThere are two ways to build custom state transition functions. We provide an util to help find the target node:  `findTargetNode(root: tree-state-obj, path: array<int>)` .\n\n### 🌀 method 1: wrap custom reducers (recommended)\nWe can build any custom reducers of format\n\n`myReducer(root: tree-state-obj, path: array<int> | null, ...params): tree-state-obj`\n\nand pass it to the hook constructor. Hook will then expose a wrapped version of it, and we can use it like\n\n`reducers.myReducer(path: array<int> | null, ...params)` \n\nto update the treeState. \n```ts\nimport useTreeState, {\n  testData,\n  findTargetNode,\n} from 'use-tree-state';\n\n// this app demos how to build a custom reducer that rename a node to 'pikachu'\nconst TreeApp = () => {\n  // our custom reducer\n  const renameToPikachuNTimes = (root, path, n) => {\n    const targetNode = findTargetNode(root, path);\n    targetNode.name = 'pika'.repeat(n);\n\n    return { ...root };\n  };\n\n  const { treeState, reducers } = useTreeState({\n    data: testData,\n    customReducers: {\n      renameToPikachuNTimes,  // pass in and hook will wrap it\n    },\n  });\n\n  const renameFirstNodeToPikaPikaPika = () => {\n    // use the wrapped custom reducer\n    reducers.renameToPikachuNTimes([0], 3);\n  }\n\n  return (<>\n    <button onClick={ renameFirstNodeToPikaPikaPika }>\n      pika pika\n    </button>\n\n    <Tree state={ treeState } />\n  </>);\n\n};\n```\n\n### 🌀 method 2: set tree state from outside\n```ts\nconst TreeApp = () => {\n  const { treeState, reducers } = useTreeState({ data: testData });\n  const { setTreeState } = reducers;\n\n  // our custom reducer to set tree state directly\n  const renameToPikachuNTimes = (root, path, n) => {\n    // treeState is a ref to the internal state, plz don't alter it directly\n    const newState = deepClone(root); \n\n    const targetNode = findTargetNode(newState, path);\n    targetNode.name = 'pika'.repeat(n);\n\n    setTreeState(newState);\n  };\n\n  const renameFirstNodeToPikaPikaPika = () => {\n    renameToPikachuNTimes(treeState, [0], 3);\n  }\n\n  return (<>\n    <button onClick={ renameFirstNodeToPikaPikaPika }>\n      pika pika\n    </button>\n\n    <Tree state={ treeState } />\n  </>);\n};\n```\n\n### 🌀 find node by any node property\n[⚡️live exmaple](https://codesandbox.io/s/react-playground-forked-55bt9?file=/index.js)\n\nOther than the built-in reducers that **CRUD by prop**, we can build more general reducers that **do anything by prop**, with the help of these two adapters:\n- `findTargetPathByProp(root: tree-state-obj, propName: string, targetValue: string): array<int>`  \n- `findAllTargetPathByProp(root: tree-state-obj, propName: string, targetValue: string): array<array<int>>` \n\nFor example, let's rewrite `renameNodeByProp` in a more custom way\n```ts\nimport { findTargetPathByProp } from 'use-tree-state';\n\n// our custom reducer, note that we omit the `path` param as _ since we don't need it\nconst renameNodeByTargetName = (root, _, targetName, newName) => {\n  // only need this one extra line to find path first\n  // if 'name' is not unique, we can find all nodes by `findAllTargetPathByProp`\n  const path = findTargetPathByProp(root, 'name', targetName);    // <== here!!!\n\n  // then everything else is just the same\n  const targetNode = findTargetNode(root, path);\n  targetNode.name = newName;\n\n  return { ...root };\n};\n\n// ......\n\n// then we can use it like\nreducers.renameNodeByTargetName(null, 'snorlax', 'pikachu');\n```\n\n**Side Notes**\nWe chose to use `path` to find target node as the primary interface because:\n- path is always unique\n- this is the fastest way to find a target node\n- we can dynamically general path in `<Tree />` component, which perfectly matches such interface ([example](https://github.com/shunjizhan/react-folder-tree/blob/master/src/components/TreeNode/TreeNode.jsx#L30))\n\n## Bugs? Questions? Contributions?\nFeel free to [open an issue](https://github.com/shunjizhan/use-tree-state/issues), or create a pull request!","readmeFilename":"README.md"}