{"_id":"refun","_rev":"29-96fda896101413f9f095748534aca1fc","name":"refun","dist-tags":{"latest":"3.1.0","beta":"0.5.0-beta.1"},"versions":{"0.0.0":{"name":"refun","version":"0.0.0","description":"Coming soon","author":{"name":"Kir Belevich","email":"kir@belevi.ch","url":"https://github.com/deepsweet"},"license":"MIT","_id":"refun@0.0.0","_npmVersion":"6.1.0","_nodeVersion":"8.11.2","_npmUser":{"name":"deepsweet","email":"kir@belevi.ch"},"dist":{"integrity":"sha512-9K6b2Ij/8h1xWSFFVn+b1n/PN7QNC1n/e7seOz7AEFGJPYEguCSyrp9vUJZAFzDWE9eEHnLXdkXdh9mMvLILMQ==","shasum":"8f7f9aa029e56457cab975418e853eae210d19c5","tarball":"https://registry.npmjs.org/refun/-/refun-0.0.0.tgz","fileCount":1,"unpackedSize":171,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbI9CpCRA9TVsSAnZWagAAvl0QAIvPzhBAmo7PBwy3TIRo\nIT8JyKmzWmFNZe6dVtp4Z/EihDZWYUPr0nS3wHQCE9m0iGnwb3+JL89CzMfr\noiMH5FX+B+Cz5K2mJekbkJLSOp70d2bo5gNUAfAT0/CoteMCOHWVhpHLbetm\nMCISBW8eqLN19iTFHRCfvY8r98ErXV1X/ztVRq5PcU8b7kyKwm1XTiHBmjly\npMau72aV3zhqxulG2RKtph6KvZyCAIOO9oZyp6cpxtxkbaJrTq8WDMDTM62e\neVt1mpKJR6flG+zVNr8qpzDQdN41X9ZZeLqi6iNF/4+O4IGpzyXU/TQTiWzx\npvbQJWmG+m6+8A5qOY4afGm8zY6z1Tk8Uwky294dAbJk1KZHzncRiYcjM/bP\nm0JFCpzv1e+W9skxDf52CsXV96ZlBEH1hT6Gu7D4+LwA/pEI7udOz2uY4i88\n+NhoF7SAeB1b0+Toy2zecECYtBYbO6WN4pOpy3WRugOBClmRzcjIehWEf1LD\nTxFWbB9NnTydSFJSO1CrmvvHCZPyVGAGvbx1peMrKCDkisoCmFN+OuyVqWWv\n78VwN2RDEUlPGp1njKxhjlrlDK4gfCdShtA1Hu1YkvEceQQeMLZIjVFWQs4s\n4ZOKsnV6ftIIgu58Nm3kz4Bv+jlR7sqeJzhJ3l9hig5VNBd24oOOFv/pJB7y\n9h1t\r\n=mHGp\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCqLFjsIDntYgLoel0clchk3NewG6smD24dgjM71LRMPwIhAOJkzZaOkktM7WNI/5NJoX+UbTtSFH3OeYNFx+U4mFIF"}]},"maintainers":[{"name":"deepsweet","email":"kir@belevi.ch"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refun_0.0.0_1529073832505_0.5027417664485863"},"_hasShrinkwrap":false},"0.1.0":{"name":"refun","version":"0.1.0","description":"","keywords":[],"main":"node/index.js","browser":"web/index.js","react-native":"native/index.js","repository":{"type":"git","url":"git+https://github.com/bubble-dev/_.git"},"license":"MIT","engines":{"node":">=8.6.0"},"publishConfig":{"access":"public"},"sideEffects":false,"dependencies":{"react-is":"^16.8.3","shallowequal":"^1.1.0","tsfn":"^0.1.0"},"bugs":{"url":"https://github.com/bubble-dev/_/issues"},"homepage":"https://github.com/bubble-dev/_#readme","_id":"refun@0.1.0","_nodeVersion":"10.15.3","_npmVersion":"6.9.0","dist":{"integrity":"sha512-XA8q/aPoRnheKfpLyRvzqTAxtm0654EIFkXaVLyfCDWwgXsxMi6AL9s6MzNlqjwpTmmy8ULEHFWjMj5/ODA/Lw==","shasum":"69942fa1f99e4ff1f11cf831ac333f3ccb44f32c","tarball":"https://registry.npmjs.org/refun/-/refun-0.1.0.tgz","fileCount":227,"unpackedSize":306235,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcrFQDCRA9TVsSAnZWagAArTQP/johv1Hb4EaIIHimKfZr\n+I9XcBSu3oiQVu3GITr9IiIYbzsXCOVc+hUXBdVoRevvRWHEIJZnbVUrToYd\nu0OXLT8S4qT8cLRz95/XKFTdXMjiftLudGpxSDJnYVmK1LViQpTeIPsXevKk\nWWVE2HM8F+ZU7M3WjZdHSKUgR6hl5eVHvalkGOYH63MAXL0GF6ALnWllbovQ\nDV4AVZo5sGbRHWLQoVWn/oBPSnP4z78n9n65O++ILN6cjQ8JquuMHmaght/L\n0MjZZ1IQ6cdoZN9cZr9RTZ67vGkj/FIORe8abviVfz7kD0mFpKEDA3D0uAK5\nTgjTi/1ishmNQQv/J7wdLIbcjdkc+pFI+poaohxdaO12U2t0gkyEWGJrsqLb\nZIQ6LqdUNvq73JmZmrrcMjhWwLTAshq4kfLtBDeb6gZB5WV2kzcHuI8nQnbx\n4X1r7nGZMs5F4WabppNUa/aGCCEJ34Ot13zs7oV3vZEYbm3C9/zKB6bmrF5p\n9418kplOjTQPtrvsxrYrnMWACiH2VA54QfaZttAqKWidWdiEvBUvnEVy7q2m\n8zxZSCj9yLmwh3MVNyr/IEI/5L8q/QroWvLBxEpuALbvi1SaDODxwdoTkD9f\nXyUdeeCzUU0P29Ui4trkXcBGbSpF+N1OGAwJaPbFY1dD1jcXbBZvd3CU/qLS\n8Ha2\r\n=7zCt\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDRsMSXu6wxuQcNAXkY4dEaS0LU6WYi9R1cT6F1ZFTfIwIhAIxjmoiMWNL+TKn4MctPpFLHcT1V86knlT5EqoncMP91"}]},"maintainers":[{"name":"deepsweet","email":"kir@belevi.ch"}],"_npmUser":{"name":"deepsweet","email":"kir@belevi.ch"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refun_0.1.0_1554797571052_0.13177816049688795"},"_hasShrinkwrap":false},"0.2.0":{"name":"refun","version":"0.2.0","description":"","keywords":[],"main":"node/index.js","browser":"web/index.js","react-native":"native/index.js","repository":{"type":"git","url":"git+https://github.com/bubble-dev/_.git"},"license":"MIT","engines":{"node":">=8.6.0"},"publishConfig":{"access":"public"},"sideEffects":false,"dependencies":{"react-is":"^16.8.3","shallowequal":"^1.1.0","tsfn":"^0.1.0"},"bugs":{"url":"https://github.com/bubble-dev/_/issues"},"homepage":"https://github.com/bubble-dev/_#readme","_id":"refun@0.2.0","_nodeVersion":"10.15.3","_npmVersion":"6.9.0","dist":{"integrity":"sha512-l6ubtnnAdWpRTjHL269KaQHPIHOUOxB4q5B6T00BZTkZ8YHxW38IoPShfOA/Txr+mzFflx7HKiQIg2QDSis+Mw==","shasum":"51060c952489e6497582bb7ccb3390a78b4efd8e","tarball":"https://registry.npmjs.org/refun/-/refun-0.2.0.tgz","fileCount":227,"unpackedSize":309739,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc56xyCRA9TVsSAnZWagAAHAIP/RvSD/xF9T3gzWGa2iCh\nQgw8dciWJlXJRuQgMVgHzywmLWYjMsfKXCBYyM0E9NVcDb3q8W/Q1kdJYfi7\nD1uZVaBj51GyPtUmILksQv3eXWfQFM8AvYkUVzaGZkFswJKergkesm8o3gmZ\nZ2hClcb7rc4Ywk9I4tB4ntySZDNHUckA7/izglIHYYlKeAGcG41YyJKUxTRB\nsFpv/ZzMU3eaTP8c9fNOoLo/ZbWpAE69Gme845vZkGVcsMqIS5fQZb978ZoE\n4bRIQXT85AQgWatTlw64XCd2f+Mk7DhcDP2C5JdpONLeV8BFzJARCRlaccDa\nEcsHnDEysop5+5+fsBeB9a/YBZ5V8hSNEMWx/ujpg1UdSeSy8l4l7EY65q0v\nbEl/msEYd0vLts/+9jBAHRsATBIvi47cguwe8vLwwI1HQ0j7D+8ERwKIkp+l\nqlCj/4PjIsrFsfqteFRQ0D6se+Sm1iugjV2B0uf61jK0ROFOgirScLxh7Q7p\nKSi3ZjuIcuyuD9wxPiB7n06UzSI9BnMNEN9CkdgcYS/QjDlt9XBsq4TIxVr0\n2AWmimYyTlYC37fGaAF7CpAtZTs2r3LzOKHrs1Aie8n/G5sCzNTRGQFVvff+\n2Eib8/+r1PzAcdSkksENjxFW7MH8u6FyLCU0z6opROehqKrwTdXz14lKhJS2\njZlL\r\n=D96U\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAoJEamB++E5fwSETa93QMbNrIqTz1B/IaMqrVNq2H5UAiEA4kyml5EtNnCU8Z1H16U/lni5th/w0MgJ4ZuWwnht4sQ="}]},"maintainers":[{"email":"kir@belevi.ch","name":"_bubble-dev"},{"email":"kir@belevi.ch","name":"deepsweet"},{"email":"psxcode@gmail.com","name":"psxcode"},{"email":"fernando.via@gmail.com","name":"xaviervia"}],"_npmUser":{"name":"psxcode","email":"psxcode@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refun_0.2.0_1558686833745_0.9185560418976326"},"_hasShrinkwrap":false},"0.3.0":{"name":"refun","version":"0.3.0","description":"","keywords":[],"main":"node/index.js","browser":"web/index.js","react-native":"native/index.js","repository":{"type":"git","url":"git+https://github.com/bubble-dev/_.git"},"license":"MIT","engines":{"node":">=8.6.0"},"publishConfig":{"access":"public"},"sideEffects":false,"dependencies":{"react-is":"^16.8.3","shallowequal":"^1.1.0","tsfn":"^0.1.0"},"bugs":{"url":"https://github.com/bubble-dev/_/issues"},"homepage":"https://github.com/bubble-dev/_#readme","_id":"refun@0.3.0","_nodeVersion":"10.15.3","_npmVersion":"6.9.0","dist":{"integrity":"sha512-cv1cK2j5UaqF5Ic53/Eh1eJchMDaIB2NwhVQA33v/mOtnqkaR7jwRGs4LVuxz7xuzDNmCWkpC+mqtF+T9IF8ow==","shasum":"b55a447255150f8d4be38b8b2260646bf37cae03","tarball":"https://registry.npmjs.org/refun/-/refun-0.3.0.tgz","fileCount":219,"unpackedSize":258639,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc+iWGCRA9TVsSAnZWagAAOuMP/3DDhfHWydfHeUofJilv\noLbkQkRwBEoJMF3gqO9W2MXoTAcZPW0nl2sctQiD5h1PWxcJakFLCR55eAbE\nQGAlzNlnlEvPRhTQIMvTxMsxwoDze+qgzArWeoITqf8aJHr9EK3My7fWPj9L\nqT3rbSGyqE227f937VhF20tfI4MNoVFRIdOd9eCj6yDgCb0huO7IqiArJeRQ\nzq1yNITB46J4yBDhlStcRqH6ubxJW7h3bJOnX5aAhGY1H4pJM0QRaHM2ufN0\nJWGbLRT7FqT1mcHLrXQQsMflAYAkKqk6plpzUaFtGLs8Iws/noDh/G6NksZX\nKNwBhLomyavLcwZeT00/o6zRMnJXsKJrYk+ybxVWGAxewj1N0k4MrBbcDmyC\nFd1hrYPCa5qfmOQ1HX1w4omsHCJWGtp1e6tvj+yoRJ3TDAw9JSIq5owk2An9\nvJn0NQ0nLGsVPDz6BizdfkLnbcBjHbyYEVM+p8sK8tur9J+KC/u4R20XuRFP\nb8TuLf1iaFv+grpP/DzIYUHpWs/d6tLDA/oSi84VT+Nffy0NU2bF5BsbwhOH\n5EuBzKU0cKTnAOOnM0q1YE8lVyKhfDnvD/LfTU/5W0plDBYM6+nW2xwEzT8N\nKSWtiRWncH2xobS6uOde3isiEOYNGPwQbGU+7VdlXZlQFaozPL53l0aRZGq7\n14p2\r\n=+GLy\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC1dwbgRGbfJAhy69+CItTpoMwL9U/DNHCLBU5FHq5qugIgE+9/hoAqU9OQxrBj4XjJxrLxzCjy/WSgH+tYezua64s="}]},"maintainers":[{"email":"kir@belevi.ch","name":"_bubble-dev"},{"email":"kir@belevi.ch","name":"deepsweet"},{"email":"psxcode@gmail.com","name":"psxcode"},{"email":"fernando.via@gmail.com","name":"xaviervia"}],"_npmUser":{"name":"psxcode","email":"psxcode@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refun_0.3.0_1559897477408_0.059013761830897016"},"_hasShrinkwrap":false},"0.3.1":{"name":"refun","version":"0.3.1","description":"","keywords":[],"main":"node/index.js","browser":"web/index.js","react-native":"native/index.js","repository":{"type":"git","url":"git+https://github.com/bubble-dev/_.git"},"license":"MIT","engines":{"node":">=8.6.0"},"publishConfig":{"access":"public"},"sideEffects":false,"dependencies":{"react-is":"^16.8.3","shallowequal":"^1.1.0","tsfn":"^0.1.0"},"bugs":{"url":"https://github.com/bubble-dev/_/issues"},"homepage":"https://github.com/bubble-dev/_#readme","_id":"refun@0.3.1","_nodeVersion":"10.15.3","_npmVersion":"6.9.0","dist":{"integrity":"sha512-TtmVb9UwOdKyB5GlHSm03HhQXl/FbhCZwt24c6UJiJJZQom2hG06IMv4xu/RPwSU0MwtrOu0S0vv2HIgnlieOQ==","shasum":"c0455848b9b5d45e4c0e2720f6f1423e4b5baeab","tarball":"https://registry.npmjs.org/refun/-/refun-0.3.1.tgz","fileCount":219,"unpackedSize":260989,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdCKn7CRA9TVsSAnZWagAAwvcP/2oVnButuNvIe246xkj3\nKWyHsOGvPpwDJkv1HLqs2Fa4iJex1vIsS2GrfID8lyL/Dq+ksVL2m786SjSR\nH87RiFaMGngmusRTEMjrmDOIO5qdQFFwnUsVuNmXil93HFCptHsxI2/Nu2Qk\n5FIF5CimWu0IuorNx/6JSQFmu4tVlPVa/HpBlrvArrm5+e/wGcRn9w8Onj+q\n5Eigxl9mT0+PVLkjhIlN2+DrJS+nDhgllior05SiGqXCkyMvAthSqRIyaCdQ\nslLLUP7dEq+Jm2CSpghHmhXdy0/oGUH7JDPG9sSN5KclLqXZR8QwEz7e7bKl\nfXZ9CVTuLbbYZBcy1WjA8FmTx20rFqaXsfw03As979V7Iz0nrqU5U0+ufG9R\nbEWtrfJGI3fNfw41Eyb0PMQQm8f/LE98LnSs3IJ3XgHCQ4wlks1Ts8Nzbo8Y\nPUbsN4RRw9Sc+L9MCAv8d8FW+P/vm7Yz4Mhe6XHnJrIHapld8jtAQUKIQ24+\n2JR+PMuBaZmeD70hXII+SGa9qCxAUKz+O/kPJ9rxcaNwepDW67YqQWPiL/Y0\nXyXheyNzXuqiSa7ou6y/I9/mnl9RmQOedg4UayWDDOuUwiUM8NA4Tu53/Twt\nHDGkHlGf4VXoK3Ze5Gk/yUjROgHHnivyqvWUa921gDdY2mmrN3AZqFs9SoAS\njZHu\r\n=Y8/u\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDKdLOX5YDadS91iBi04fhvmU1wMbi9AGNNjc4zJ2tIHwIhANvAzAsecitqAQCqlj83EeoaafS1zGl8w5XGTvC0Ts0E"}]},"maintainers":[{"email":"kir@belevi.ch","name":"_bubble-dev"},{"email":"kir@belevi.ch","name":"deepsweet"},{"email":"psxcode@gmail.com","name":"psxcode"},{"email":"fernando.via@gmail.com","name":"xaviervia"}],"_npmUser":{"name":"psxcode","email":"psxcode@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refun_0.3.1_1560848890659_0.9607181920223034"},"_hasShrinkwrap":false},"0.3.2":{"name":"refun","version":"0.3.2","description":"A collection of React Hook-enabled functions that compose harmoniously with each other. Similar to `recompose`, but:","keywords":[],"main":"node/index.js","browser":"web/index.js","react-native":"native/index.js","repository":{"type":"git","url":"git+https://github.com/bubble-dev/_.git"},"license":"MIT","engines":{"node":">=8.6.0"},"sideEffects":false,"dependencies":{"react-is":"^16.8.3","shallowequal":"^1.1.0","tsfn":"^0.1.0"},"bugs":{"url":"https://github.com/bubble-dev/_/issues"},"homepage":"https://github.com/bubble-dev/_#readme","_id":"refun@0.3.2","_nodeVersion":"10.15.3","_npmVersion":"6.10.0","dist":{"integrity":"sha512-SNuksMtmweRf5On6PRvdKQd1z+gYI1I2hxlIQgPTfj7AHUf4UIWLT+cuOjIweIcLsCHfiChnXWHcKVIXgcq76A==","shasum":"140efce26928d0ab8f6cf89e65db65e34bd57b3c","tarball":"https://registry.npmjs.org/refun/-/refun-0.3.2.tgz","fileCount":219,"unpackedSize":304838,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdH1+7CRA9TVsSAnZWagAAgsMP/2IepBqUk2u8CQUbA9JJ\n/CCDDXlZyL7G23+SmjG8rcL+Tnk7b9uCLlhwubDxTuHQrGFCQBdmFNi9Ik+u\nlQ660S671ZZ11rgmjj6Tod9W9SZD/bJAzN9BBa+mzwlpbLO4kqjhxioV6mWJ\nA9Q3plkRxOydaGeWkv/8E5UAkIOYwuxK8LTNxV5eeKXq/7LIlKpVQ5gBqJG9\npPYKJqNkJaJFgAoM5RTJI8i2f1wEWjRX5jrqsDc6WY5sgELhJFBIcxlQmpAH\nHun4TX5ibNpTVk/QqAP+rlRBzww6nV0CKsKhRFGU2Fd4uXP43Yz0R58wuKQb\n8qYsVYnUneIUdb6i9rO5BmjqHwucMCBLayn84Ih8JsmjjZhUtC9aGIWkpk2b\nZ2dr6/NvMXLVEtlzOBQPBploDp0OMZwAcYyqt3uYsvMKs8/kHd83PaauiPtO\nQlDcs+QI7faTdoqkPRUTnJ8xwGqEiSSNygdHXtcQ93sWUF46PrFOQpGQCrbs\njWEWIjrSF+bSFSuvOeFQy51TvhkHyMw/LRkuDTKsqOXxrig/wThGSJQpuAzM\nzslQxzR9+gl0rii7WguKOM4v74lnjvIXeBrx+p1EXBmOxVjra55fzRJQfuT5\nMg7vLEKc0sBTM/ZPbivpvmw3vXFMe/e0GzstdKRtjhi/GGpe4ZaeKagQAPrM\n8kPU\r\n=wZan\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCiTafFCWd24qy+YNVjjAeexRaoZ9BOY8Gagqq50XuoRwIhANii0yqgMgm9r+VgzSJxrp0KYLEks67gKpuixA2KTUg3"}]},"maintainers":[{"email":"kir@belevi.ch","name":"deepsweet"},{"email":"psxcode@gmail.com","name":"psxcode"},{"email":"fernando.via@gmail.com","name":"xaviervia"}],"_npmUser":{"name":"deepsweet","email":"kir@belevi.ch"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refun_0.3.2_1562337209895_0.6866928999845026"},"_hasShrinkwrap":false},"0.3.3":{"name":"refun","version":"0.3.3","description":"A collection of React Hook-enabled functions that compose harmoniously with each other. Similar to `recompose`, but:","keywords":[],"main":"node/index.js","browser":"web/index.js","react-native":"native/index.js","repository":{"type":"git","url":"git+https://github.com/bubble-dev/_.git"},"license":"MIT","engines":{"node":">=8.6.0"},"sideEffects":false,"dependencies":{"shallowequal":"^1.1.0","tsfn":"^0.1.0"},"bugs":{"url":"https://github.com/bubble-dev/_/issues"},"homepage":"https://github.com/bubble-dev/_#readme","_id":"refun@0.3.3","_nodeVersion":"10.15.3","_npmVersion":"6.10.0","dist":{"integrity":"sha512-sFu6S5KbwXMK8WUlJuPrmMo3WWxFWB6wxKglBQZxfgwpw7t0CXxEV4na841427hCzBCkiZFEwD4yro9FSYj+WA==","shasum":"fbf76fb254d74eaec2536a20566bb2bee3a5394d","tarball":"https://registry.npmjs.org/refun/-/refun-0.3.3.tgz","fileCount":219,"unpackedSize":304811,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdIzUaCRA9TVsSAnZWagAAUjUP+wXpVKPEqRyU8WAXzQNP\niDCTGfbgJ2KhnnlD6Bu/F1qcoFMut5Lv7+QiGkjghG3NLsiMhgQ6JHAfoUo9\neOWA399Cwqmj833zWYL1bWnr99d0bX9fP9CNgA1Qo50mexCxLUnsoSwHW+s2\n7YXjySu7VnT94RRZtFBWSiUawf1hPd4vEgLiVkfGHqtA/i5GoLoAt8wW8fQ7\n06c7vpZa2ce+UjrQLQ9saQ19dw2NX4gQ05s3h/OzYLbz5fI5Eztw60HMt99s\n5xmL9ZiJRoXzCeSY0m3buTrzLRTESvzs5h3CcAqkOM3VrX0FTbf+kBDr0/rS\ntLALucnlCUjVUU7PsgXGzaNTFWoUD1o9eGrm3Aab9o+i6KHKj53fwMlYXsKO\nKvy8rizo+R6JUXeO0ZCvQc7I3EvpYhn2nS06Yt4bgYvLIi2HdHehg5KIpHBU\n2eEX66BFEkvqO/wH9palAdkRG8gTVTSrh1Z675e8YaDt+tqcd4d1YEdF/RGZ\nZ5VAymhvnDU5tiqLaPSQp+NTgdrOxzqfkYabba7VWAMkLuDh9/ZlT1uOPAS2\nrnJgD5uhhR4B/rvUBbto0XyhgQCVp973vxl4jX3Ph2AaVtZ1IeO59V5zsHa/\ni7BDRYRI8eibMZvjqX/N8EoInvSk+897TI9HyEC0mT2oWymKa64+9zJ1PzBm\nYu7W\r\n=J42H\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEQ6Zt0Rl4PR/1AE693Dz8n9+zPTGUk7LJEeYzCcYNNJAiB871X0ZHB0GJ84VJQdk7kwfj6tBHfIkYK7rcaTjxoiQQ=="}]},"maintainers":[{"email":"kir@belevi.ch","name":"deepsweet"},{"email":"psxcode@gmail.com","name":"psxcode"},{"email":"fernando.via@gmail.com","name":"xaviervia"}],"_npmUser":{"name":"deepsweet","email":"kir@belevi.ch"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refun_0.3.3_1562588441890_0.7901253852630783"},"_hasShrinkwrap":false},"0.3.4":{"name":"refun","version":"0.3.4","description":"A collection of React Hook-enabled functions that compose harmoniously with each other. Similar to `recompose`, but:","keywords":[],"main":"node/index.js","browser":"web/index.js","react-native":"native/index.js","repository":{"type":"git","url":"git+https://github.com/bubble-dev/_.git"},"license":"MIT","engines":{"node":">=8.6.0"},"sideEffects":false,"dependencies":{"shallowequal":"^1.1.0","tsfn":"^0.1.0"},"bugs":{"url":"https://github.com/bubble-dev/_/issues"},"homepage":"https://github.com/bubble-dev/_#readme","_id":"refun@0.3.4","_nodeVersion":"12.7.0","_npmVersion":"6.10.2","dist":{"integrity":"sha512-Gp3uEuGr4aIyEjp+0sYx0DvgCi8lBss3FtlrCUpL9/c98052Uz9cdEUPlVrcTEIRrDDTmiAoAj9qaZxjOBTj6g==","shasum":"eae16a827f72e9edf9f7bb851cb7f918b216ea5c","tarball":"https://registry.npmjs.org/refun/-/refun-0.3.4.tgz","fileCount":219,"unpackedSize":337023,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdRFIqCRA9TVsSAnZWagAALEYP/1V+SWn9WR8dcoDe3Ru2\n/a3Lgp0jPXDlI0YgCuwujQMj+d5ugIsrGgUdVKEpXYq1sZMRDJVDhu4Penr6\n7P4JPk7M0Yk+V9kfIcEF85Z0D/VQZAtnyTsbvzpTCrhRJ/DddDDmrd/rlNiU\nvh8XCj7cfyAgFUkQNjw4xNO3pzgIFGwchC9OW9oRpLm+xQsWECq0T26l6Kcd\na3sjQAORGlyk2Y5gubCPRAcL+PSVRxVpCEv3PSEAu77DZcsTus32emgvxryW\nxo0IPSPhE8W6SzhwC19hDZS5eGypQ8VLVSL150MCZkgFDHoOLDX4wXyk0xeI\nx0toAWkEEunUtDpqBZlI2BqHbBfQjLB1Be/Ncr6pvFqTg+sjcOWw+Dq2Ab60\nVOZ6RB5Dmv/j/XRbr7A1y6TMzXJCp3wU+eyUH/xNHoPR1UdH0F16SiARf61m\nsKvfKQZjhMaN4Px3jdn8wFATn1qh4USr5U6weseonkVV2Uv4mGfj80LzwqHK\nUedWPCGDnawJPHCv5y3hZ0TFY3ICBrxvXOKpMlCJ0MtGYs0QUZFNw0kiOFc3\nlhk6lKqjO3z4Pxpha9zwO5ImF+eGxv8zaPs8wT2cJZ/y/zappAHUC5dZEKsO\nQtskbgF2uYEzbxZbNXoadaImgD1pJXuGGVaZdN8CUVNii+cFw/33AFxuF3my\nSeIo\r\n=J7tS\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIE61Rb31HisiIbRjilwlpfWm/nEC75oXnZ9GLhP0Mk+1AiBXn5n5xV3Z33XwLO/Kcy8Xev0s0FLu9FueAGicy+0uSQ=="}]},"maintainers":[{"email":"kir@belevi.ch","name":"deepsweet"},{"email":"psxcode@gmail.com","name":"psxcode"},{"email":"fernando.via@gmail.com","name":"xaviervia"}],"_npmUser":{"name":"deepsweet","email":"kir@belevi.ch"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refun_0.3.4_1564758569227_0.16397145000094393"},"_hasShrinkwrap":false},"0.4.0":{"name":"refun","version":"0.4.0","description":"A collection of React Hook-enabled functions that compose harmoniously with each other. Similar to `recompose`, but:","keywords":[],"main":"node/index.js","browser":"web/index.js","react-native":"native/index.js","repository":{"type":"git","url":"git+https://github.com/bubble-dev/_.git"},"license":"MIT","engines":{"node":">=8.6.0"},"sideEffects":false,"dependencies":{"shallowequal":"^1.1.0","tsfn":"^0.2.0"},"bugs":{"url":"https://github.com/bubble-dev/_/issues"},"homepage":"https://github.com/bubble-dev/_#readme","_id":"refun@0.4.0","_nodeVersion":"12.7.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-GXGilYHDFqMrCWivN2/2kyoktZ70WgoLKuADVkvengwXf9DuBqYqEpbPvpL+ePDyQT7nwYoiWkTle4Mvppi41Q==","shasum":"4ce30842fbdff3310d40fe4b96b21ba597d65a0f","tarball":"https://registry.npmjs.org/refun/-/refun-0.4.0.tgz","fileCount":227,"unpackedSize":415502,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdZ+HVCRA9TVsSAnZWagAA414P/2JKuHKl9DfcTa2lL/HT\nvRJcGfm1tQpsPzY2lHfJTuO6i2IXxeuvrcj0JcJDBS1+TFZNGxKsnHtmdjNi\n2IihXgeUXUvy/piSRiRdp5DNVmZIUwIVVyvyrAnavjuklkj7NoH+GBJ+BHVM\nS0W8DFDtSn0FOtJvfaCmZxq2IxHfOGOcYw36njmD0sVKneLXpIqsWIXHjIUN\nRyCv0FvRMHK76L7l4AK/QtsGVZU1F1oB7pE6tpRFxpxI3wKG8sMaWgSZctQ5\nvTVuXioNY1pUUh4InALVn6c93ZtXKAMPxQMo3hydwpL8EH60lDXieO9SeVi4\n/WqWecDeIoEhBTlEHrJG4NNWoGmRZNIxzcBd4pGAwMXXlPM4WpsBEmfUykDA\njLFRpFsQp1ppjCLd2xV6UFP9PjIapw6bP/ukpOKAg0EyiJskeZmXFMVRS041\n3RJY1eddnuU3kS/2XXyBA1AbLb7c1FSn/B9oh38xN1EJgC4/ubBMT66yzDBF\nyVckuwxQC5AEUSjyhvxbcyAFGjqbJzcoPyj4oVpzh6fpJRbvdYFQdmh5Hl7+\njLaDOgBn7fLNlK9hqxA6torC429phZKp7toD6182kE0qiGA/4C8kzKcdnmIC\niggwhH+VD32PS7UxWw8Mk9AO/q2KXCKk649VOYH4uxrVaSTkg6dqNf+Fb8je\nCb1x\r\n=/tKF\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDYtuM3s3yv9m58OMP96YiuElO3wLr8oEaU+Vx0ushRcgIgce3xfYWBz0SglhUVlB9+mLGAK8+OgyYw78sKiaOCH88="}]},"maintainers":[{"email":"kir@belevi.ch","name":"deepsweet"},{"email":"irminakacz@gmail.com","name":"irminakacz"},{"email":"psxcode@gmail.com","name":"psxcode"},{"email":"fernando.via@gmail.com","name":"xaviervia"}],"_npmUser":{"name":"deepsweet","email":"kir@belevi.ch"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refun_0.4.0_1567089108091_0.03180746902346154"},"_hasShrinkwrap":false},"0.4.1":{"name":"refun","version":"0.4.1","description":"A collection of React Hook-enabled functions that compose harmoniously with each other. Similar to `recompose`, but:","keywords":[],"main":"node/index.js","browser":"web/index.js","react-native":"native/index.js","repository":{"type":"git","url":"git+https://github.com/bubble-dev/_.git"},"license":"MIT","engines":{"node":">=8.6.0"},"sideEffects":false,"dependencies":{"shallowequal":"^1.1.0","tsfn":"^0.2.0"},"bugs":{"url":"https://github.com/bubble-dev/_/issues"},"homepage":"https://github.com/bubble-dev/_#readme","_id":"refun@0.4.1","_nodeVersion":"12.7.0","_npmVersion":"6.10.3","dist":{"integrity":"sha512-MqIij/qK872SzagQsAELp0ZMdbU258XyCWPeN/lVB3spT16SFCi9lryY8HC3tsartCYfUxSpbweVENPCI2bn+A==","shasum":"9df0bf669d3b99e8a648a38a8ba990de42f52959","tarball":"https://registry.npmjs.org/refun/-/refun-0.4.1.tgz","fileCount":235,"unpackedSize":426513,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdbmYjCRA9TVsSAnZWagAA/qoP/iKzeWiPYZ2+OwPdGS9N\nXTdEJRWJY2Rj8s9t7Kn74ZAkOF+9nKqIrW+M64niM+JSkiizjoxxg1VXXhjO\naw/z2RiRO0YpwliXcaNpdlIGgpx0eF503wALgJh7H9phDKem30z7/9O5nc44\nw02mji5vu/KoICnb4xcpw5dK6NTGsnKufc0MHoRUrnVFhAkb3GhCOsLs7Uhb\nmbZZYtKz1P/2Zg5WRGa2pPk4FNuUVvuLej/sm8itsh7IB20NGhSz6Lp/kxJW\nxAVH884t0v5ucOOlNTQaYJvLyX8CnA1VFbILq67krlhRtVYfyxzp6JA/jXMK\n86MRFtFggiV1dSfukHLppAxACRlClpyqYEKfPD1X7hFIwizeNrTCb8HToMAc\n9mbsz18Tv3Cen+7DKgMYYrrresshOGv9EiPqePZOBnz3a2nM+4zX5r6Pf7Lv\nYv1CH8tboGP6rmGBtqiYNiiC/NeTfuw+WOvmkJ9xUce+8pSTQBizM3ZCjoA7\nmHwzCom7PIUzxLFPABxRW1eQ4pdlclMw9TAmT15HzQHEUESyPD5RHZtFSnJW\nQ3r1YvJe3xPgsQcRiW2QhfKCYPMixl1VbUiRWBAkrXeVgVL08b66luACBaFy\neiGlc/DHIMeqBm7mwSYXKWVT4l8dW0hX5nnlQTpsttn48TqOPFbRx3YlsCZO\n5ubw\r\n=+ev+\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCYZteOysohl6GGpvG2XiUCcwQVfxy/0xWSWkrGTqn+FAIgY9U2zC+/iQ4oI1VtwzlFvnVbPeuf7Qk/aGW8gEfu1U4="}]},"maintainers":[{"email":"kir@belevi.ch","name":"deepsweet"},{"email":"irminakacz@gmail.com","name":"irminakacz"},{"email":"psxcode@gmail.com","name":"psxcode"},{"email":"fernando.via@gmail.com","name":"xaviervia"}],"_npmUser":{"name":"deepsweet","email":"kir@belevi.ch"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refun_0.4.1_1567516194282_0.9168373320822321"},"_hasShrinkwrap":false},"0.4.2":{"name":"refun","version":"0.4.2","description":"A collection of React Hook-enabled functions that compose harmoniously with each other. Similar to `recompose`, but:","keywords":[],"main":"node/index.js","browser":"web/index.js","react-native":"native/index.js","repository":{"type":"git","url":"git+https://github.com/bubble-dev/_.git"},"license":"MIT","engines":{"node":">=8.6.0"},"sideEffects":false,"dependencies":{"shallowequal":"^1.1.0","tsfn":"^0.2.0"},"bugs":{"url":"https://github.com/bubble-dev/_/issues"},"homepage":"https://github.com/bubble-dev/_#readme","_id":"refun@0.4.2","_nodeVersion":"12.10.0","_npmVersion":"6.11.3","dist":{"integrity":"sha512-v6yJMRY6iZbJlkOGpNceETIm/5PQbZ9L6IvHp6J05MTtejy093pCMxTVB7I15k90gSSPi7YU/TcMkwkJSzRJgw==","shasum":"eff13b4426ee1d7645c71f943fc291370cb1976f","tarball":"https://registry.npmjs.org/refun/-/refun-0.4.2.tgz","fileCount":243,"unpackedSize":431259,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdgkEVCRA9TVsSAnZWagAASgIP/2MVDu8prNF91Scsnq8J\nMDtgq33MMMWm4yBOeiMTZFic39moTIt1jpeNtcukM7uk80qksh0WzqJxDzgI\nf3b/kKQXLft8rdJ9+jp44F8BFrU4Xy9in3ljOtg0Ns0015FH0lACYeeyHj/9\njuRV+qUAHoMPiv7q7H+0PAHA3UVl5U+NEkAPUOekEDXh98en77mOnZ3p4K4E\nkaz6bDytYWsCvUK8GfLx7qbLDnV+dKaaT5e2ezYPijFRwb97Q0W4YJvroe22\n0rYGf3PnzA1gdHhEShzum/hjbgIFWPS3WXmd+J1fh46GbOKjUI4Xk5FsEqaL\nUfANHrn6KKXQrcJxtqS4AzkF1oZACGbDh7wSXz4ZbWj+SMYljz1gcDu8vzb5\nTqxstiLOBHAapr+hQMCHAjLWcEhr2TuO/OF5RjlY+iHId8qb9ALlyPxq32Do\n3sksIaxEV0Pl1zleGwjuBa6FBDcUMMwAFw0h0TXELJ4n15gVfo+GcHqy9sr4\nOOhMY7jFZnnDdNv2uXzA/zvmlPBEsi3NERBlFNpHfSqcHHLzQJENmFhy3nMR\nBJwIN/xoPDOIEuCaMLEjGFdBp6CFQDgOLegCv85ZrwttjEKB1Ct+adWTufId\nGq1Dm5no2qcZld9ZXfqcaBNV+u9IRlbxlFhIGnbLmzZKEBDxkTjZ1kisGM1D\nt7nO\r\n=K/J0\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHb/UWPrWSUET1o3i4GjpW8Rq/EIF4NXaX+/NKJvHIw4AiBHOtBbtP0cbnC+4VfW+kxdtCa0vRNmnmZSW5/Uq1x/EA=="}]},"maintainers":[{"email":"kir@belevi.ch","name":"deepsweet"},{"email":"irminakacz@gmail.com","name":"irminakacz"},{"email":"psxcode@gmail.com","name":"psxcode"},{"email":"fernando.via@gmail.com","name":"xaviervia"}],"_npmUser":{"name":"deepsweet","email":"kir@belevi.ch"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refun_0.4.2_1568817428125_0.6169336484502961"},"_hasShrinkwrap":false},"0.4.3":{"name":"refun","version":"0.4.3","description":"A collection of React Hook-enabled functions that compose harmoniously with each other. Similar to `recompose`, but:","keywords":[],"main":"node/index.js","browser":"web/index.js","react-native":"native/index.js","repository":{"type":"git","url":"git+https://github.com/bubble-dev/_.git"},"license":"MIT","engines":{"node":">=8.6.0"},"sideEffects":false,"dependencies":{"shallowequal":"^1.1.0","tsfn":"^0.2.0"},"bugs":{"url":"https://github.com/bubble-dev/_/issues"},"homepage":"https://github.com/bubble-dev/_#readme","_id":"refun@0.4.3","_nodeVersion":"12.10.0","_npmVersion":"6.11.3","dist":{"integrity":"sha512-qg52howUlPvd1//9dzyQTAveDxIC10YZ1xJ4Q97fZGpL5Pcphz1iIVroWtX4gShzHq7tAE6KezJA6cbCNMJ/pA==","shasum":"d9ec45b1c877b506a8415c54fe3a856e19cb19f6","tarball":"https://registry.npmjs.org/refun/-/refun-0.4.3.tgz","fileCount":243,"unpackedSize":432846,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdhLwECRA9TVsSAnZWagAAG/cQAJkQ8yCWAXaxYSQeReC3\nVD+iWDPqsXecKgqMoj6l7xsWjAJPE4cG2wpbIxOOfCHctDGJKMLPoFn+FRl5\nHCe6wzXIK8bScYa9L5UVbld+unZ1axG/9HbHvcRNS1DHlDSBwBftiS6BTRdD\nh2cbHHnXkE1Ph+luJN1AceOOhxtYknPw0TzgorBmzTwhII1lKpaHE45aziQ5\nOar9UeiWxZvjdj1wOCERxv8QmHNva5wYiWS+EnqAKYDxYeYlma4ulN0Uj5jN\nw2tsNMiQ8oJiOolwOc6eSoRGrZdbgFQD190yLqsBjuDQd/Ilog033pbM4wcb\naCw3x+RPxjSO58D71qM3YVaHDykn7UZSEAZfGy7jM6TecHKseDnKierh6Yrp\nsRVuamy1GdiJNgG8AI7fRABikshkH1HaZ/6N2HuVs5gkuKUpxSoXE3Jj7WEV\nLmgvCptha1v7a0e4jq4OiDIDe5J+RZ9DsSkMlc/nyrhNxU+08UZJdFhEoXcp\nMQRwF+C/dQpYiiofcbcc4TEUo7x5V6vu6OfiFzTVHwiFvgbBZowppe+CMJPT\n09PGb3wvB6yfmMGBz0LgmCgUsM0FAdPh+yBKqDJa/3CB1dAqJvXRYtZlGOYi\nkEmclv1WI6MswCHlqM4fLz4IJekBCOCcFpanJN9RliEg0zb487qw9Rn2JTd0\nXDe6\r\n=tPrQ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCDlgV0EytE86wpMLNa+MCQmbwl0VnaNR7eBlE1ryKUOAIhALSArHk+lInXJzknzf350qj4kMm+oaNnpu8MsXTR2WX/"}]},"maintainers":[{"email":"kir@belevi.ch","name":"deepsweet"},{"email":"irminakacz@gmail.com","name":"irminakacz"},{"email":"psxcode@gmail.com","name":"psxcode"},{"email":"fernando.via@gmail.com","name":"xaviervia"}],"_npmUser":{"name":"deepsweet","email":"kir@belevi.ch"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refun_0.4.3_1568979971812_0.6312671196305553"},"_hasShrinkwrap":false},"0.4.4":{"name":"refun","version":"0.4.4","description":"A collection of React Hook-enabled functions that compose harmoniously with each other. Similar to `recompose`, but:","keywords":[],"main":"node/index.js","browser":"web/index.js","react-native":"native/index.js","repository":{"type":"git","url":"git+https://github.com/bubble-dev/_.git"},"license":"MIT","engines":{"node":">=8.6.0"},"sideEffects":false,"dependencies":{"tsfn":"^0.2.0"},"bugs":{"url":"https://github.com/bubble-dev/_/issues"},"homepage":"https://github.com/bubble-dev/_#readme","_id":"refun@0.4.4","_nodeVersion":"12.10.0","_npmVersion":"6.12.0","dist":{"integrity":"sha512-IccZTZ5I9JkMKZ4GF5gIuzgZ/4/tp2byB6f7WfPTnFrzmlgdlt9MjzS0LxL67n6ZUBrU2R+CyEBAu0ankTE/ug==","shasum":"7a556343c87b868a2e16ee0da7f5e03e498a6218","tarball":"https://registry.npmjs.org/refun/-/refun-0.4.4.tgz","fileCount":267,"unpackedSize":456588,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdne6pCRA9TVsSAnZWagAAnnoP/19fOU6tYBT/v57Z9pWF\nm2KjrM5aMSXHMEp8Ow8KxjsoPFqiOndI3DXDfY9cUOBfqZYREXXO3aJqLgoF\nmt1CxpxnPfR8bpdcf+QXjtO58C8o5XjHxcFesRXWekA78KGOsNYcKxVlW/4J\nRuZa2w5V6smtNe5u52EgUYWo85NUcXtQgj72J6owNrgxO0GuqcZ81GQHFreF\nX4RnMgS0un/c/03bKxEpnrQhhdGeJuN+MboMY0dQ7Kn8s+XiwmtL1FIEP7W6\nk3AlIhscdwm9sBTxUVpWJ9uSNlJGdOmkjedA2Zx0NyvxmCxKPia7loUDf2fT\nGVSGwgWwqoCpZ/YexXin3MyRKcCSXSzeatZWKut0R50cwlTTvmsxyPQS3Knm\nSSHgHOo+537mGgwXjQfb7Qf+VOyVhxTxM9PEcmVJL9kHGmIwIWDBrXeg8sfH\niI5XH9Nw6v6AdvSRjE5g4XjKygh+/1SESOXQ3SfZyS6ADdujwheJIPBl8SU7\nGVqLKoTEr73c1Ija8M6E80xxipBxIfOGULRtA+TfDT/flT0tO1OtnoQPlAFD\n8VIWFBv5Ncht0arOMIhGHV/KQ6xmDk53xPtvImGcMRQ3Y0NnN6M7if+mAoqQ\nVg0iI/sbdTwvhykefTjcCPBTFOWEffVcOGn7AidzNk0RF7STaKAa7YP0nuhp\nAL9n\r\n=t1CL\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIE2vs5KyEaxA3zxUk4AYAb7aYlqDnE9XC6w6Af2uzKKWAiBdXqTxizQz7iC0swPbeW2AZFbt+EjBJF3t4sIZxpXG+g=="}]},"maintainers":[{"email":"kir@belevi.ch","name":"deepsweet"},{"email":"irminakacz@gmail.com","name":"irminakacz"},{"email":"psxcode@gmail.com","name":"psxcode"},{"email":"fernando.via@gmail.com","name":"xaviervia"}],"_npmUser":{"name":"deepsweet","email":"kir@belevi.ch"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refun_0.4.4_1570631336930_0.31409914087260327"},"_hasShrinkwrap":false},"0.4.5":{"name":"refun","version":"0.4.5","description":"A collection of React Hook-enabled functions that compose harmoniously with each other. Similar to `recompose`, but:","keywords":[],"main":"node/index.js","browser":"web/index.js","react-native":"native/index.js","repository":{"type":"git","url":"git+https://github.com/bubble-dev/_.git"},"license":"MIT","engines":{"node":">=8.6.0"},"sideEffects":false,"dependencies":{"tsfn":"^0.2.0"},"bugs":{"url":"https://github.com/bubble-dev/_/issues"},"homepage":"https://github.com/bubble-dev/_#readme","_id":"refun@0.4.5","_nodeVersion":"12.13.0","_npmVersion":"6.12.0","dist":{"integrity":"sha512-+cxAd0r4vLxy8EcOjWkg+MM+Xm+qqQeppkGTLSOsSwbWiHYpoxIJHzzQhCb6ymavhse+RG2opxRo3XkoDmAg2w==","shasum":"a5274575fefc49b4c6c55c4597ea9852f66b0cf9","tarball":"https://registry.npmjs.org/refun/-/refun-0.4.5.tgz","fileCount":267,"unpackedSize":456949,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd+jjmCRA9TVsSAnZWagAAiqMP/2dTZ6Gj0Rz6mMdNsU+D\nzADtXTp9HoN1iZqcEWbu5FyAlKY0xYvAc0kDN2/Ar7cwIyfZbFiI2VZ6LG5m\n+t60AqdmGfrnoibyqTcRFV1ilyK4anKlyCW2e1ckVmtAlsLQ+7JtzRiKk5qk\nAZlyEntPXkJuoPsOLKTcEclByDjW+0WuLWqRgrP7TEWQwnrhJVP5PFPe2rmZ\nkaumbMZ7qaUNfIVABAkEhTXgHVwcV+srNX7PTc+SIZ7iBAjyDTPrRlxDP8et\nSkgV85nttgO6D2MfswECXo6eqQt60d25sK7gmIIaXc64mhS/CE1OTV3ZmIzM\nSUt5Q1Ln8Uz7oISl90lZbnM5QS5j6YmNzOspqgLEVAyPF3HYXn+6JWyo78Ld\n/A60twhP5d+g0V//JfcDj9Cn6XjRyxlVfAPs1n2plMQVhx1MfV34s4xnJEA/\nNOuEiwuxCqLV4dT9S57iLGFMrioZv9j4BVe2wr16Kf/1kHfyfWbfg/YOS96t\n7+x4Z7KRKh+X4had1b23OjKwFILHtze9bsbYlv8lQSMC921MRHhnPUdkxP/H\naIf8RkhZRN28A/eO3BHkccPL1cNH04us+uFa8hiUHJBIVFJDEEl1RAsFSEtZ\nfSUwMC2R6lp12+GVJ2YQh+fGxCwuEa8ZHJOUugALlXGPADHSFqbQRQnjKEVm\nlrjF\r\n=TOqk\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDA/CpvYxhY743pn5cXitPvMU+omoY+iID0NTenTn6s8wIgY6r38r7EvralvY38wzpdLfxXbCM0ngLEfNoDOdy+G2c="}]},"maintainers":[{"email":"kir@belevi.ch","name":"deepsweet"},{"email":"irminakacz@gmail.com","name":"irminakacz"},{"email":"psxcode@gmail.com","name":"psxcode"},{"email":"fernando.via@gmail.com","name":"xaviervia"}],"_npmUser":{"name":"psxcode","email":"psxcode@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refun_0.4.5_1576679654341_0.28514529290656254"},"_hasShrinkwrap":false},"0.5.0-beta.0":{"name":"refun","version":"0.5.0-beta.0","description":"A collection of React Hook-enabled functions that compose harmoniously with each other. Similar to `recompose`, but:","keywords":[],"main":"node/index.js","browser":"web/index.js","react-native":"native/index.js","repository":{"type":"git","url":"git+https://github.com/bubble-dev/_.git"},"license":"MIT","engines":{"node":">=8.6.0"},"sideEffects":false,"dependencies":{"tsfn":"^0.2.0"},"readme":"# refun\n\nA collection of React Hook-enabled functions that compose harmoniously with each other. Similar to `recompose`, but:\n\n- Uses `Props -> Props` functions instead of `Component -> Component` functions. This is all around better. It means:\n  - Less nodes in the React tree\n  - Better optimization options for the JavaScript engine\n  - Being able to reuse general purpose functions (all of Ramda's object manipulation functions work)\n- Propagates TypeScript types through the composition chain **without any losses**.\n- Works entirely with React Hooks instead of class components\n\n## Usage example (with TypeScript)\n\n```ts\nimport * as React from \"react\"\nimport {\n  component,\n  mapDefaultProps,\n  mapHandlers,\n  mapHovered,\n  mapState,\n  mapWithPropsMemo,\n  startWithType,\n  TMapHovered\n} from \"refun\"\n\ntype TButton = {\n  isDisabled?: boolean\n  clickCounter?: number\n  id?: string\n} & TMapHovered\n\nexport const Button = component(\n  startWithType<TButton>(),\n  mapDefaultProps({\n    clickCounter: 0,\n    isDisabled: false\n  }),\n  mapState(\n    \"clickCounter\",\n    \"setClickCounter\",\n    ({ clickCounter }) => clickCounter,\n    [\"clickCounter\"]\n  ),\n  mapHandlers({\n    onClick: ({ clickCounter, setClickCounter }) => () =>\n      setClickCounter(clickCounter + 1)\n  }),\n  mapHovered,\n  mapWithPropsMemo(\n    ({ clickCounter, isDisabled, isHovered }) => ({\n      children: `Click count: ${clickCounter}`,\n      style: {\n        cursor: isDisabled ? \"auto\" : \"pointer\",\n        borderColor: isHovered ? \"black\" : \"grey\"\n      }\n    }),\n    [\"clickCounter\", \"isDisabled\", \"isHovered\"]\n  )\n)(\n  ({\n    id,\n    isDisabled,\n    style,\n    onPointerEnter,\n    onPointerLeave,\n    onClick,\n    children\n  }) => (\n    <button\n      disabled={isDisabled}\n      id={id}\n      onClick={onClick}\n      onMouseEnter={onPointerEnter}\n      onMouseLeave={onPointerLeave}\n      style={style}\n    >\n      {children}\n    </button>\n  )\n)\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-example-nec8y)\n\nSeveral things to note:\n\n- [`component`](#component) is used instead of a regular `compose` (from Ramda, Recompose or Redux for example) because `component` accurately propagates the types throughout the entire chain\n- Because of the type propagation, it's convenient to write down all the functions in place in the composition chain. This way, the types will be inferred: otherwise the types will have to be specified manually.\n- [`startWithType`](#startWithType) is necessary because of a TypeScript shortcoming. It is used to make the type that will be received by the first function in the composition chain available. It shouldn't be necessary to do this with a specific function: ideally, the `component` function itself should be able to propagate the type variable of the generic down to the functions inside, but at the time of this writing (2019-06-26) TypeScript does not support this. If it would, the right way to start the composition chain would be:\n\n  ```ts\n  // Note: This is currently not possible\n  export const Button = component<TButtonProps>(\n    mapWithPropsMemo(({ isDisabled }) => ({\n    ...\n  ```\n\n> Note: you might notice that `refun` has functions that serve as the equivalent of most of the React Hooks, so it might seem odd that some, such as `useEffect`, are missing. The reason is simply that wrapping them in the composition chain of `refun` provides no benefit: `useEffect` in particular does not result in any prop being added or removed, and there is no implicit state to keep track of, as is the case with the `mapSafeTimeout` and similar functions.\n\n> It is not the goal of `refun` to be a replacement of direct usage of React Hooks, rather a way to use them as a clean and decoupled composition chain and with good TypeScript typings, features that are only relevant to certain Hooks.\n\n## API\n\n- [component](#component)\n- [mapContext](#mapContext)\n- [mapDebouncedHandlerTimeout](#mapDebouncedHandlerTimeout)\n- [mapDebouncedHandlerFactory](#mapDebouncedHandlerFactory)\n- [mapDefaultProps](#mapDefaultProps)\n- [mapFocused](#mapFocused)\n- [mapHandlers](#mapHandlers)\n- [mapHovered](#mapHovered)\n- [mapKeyboardFocused](#mapKeyboardFocused)\n- [mapPressed](#mapPressed)\n- [mapProps](#mapProps)\n- [mapReducer](#mapReducer)\n- [mapRefLayout](#mapRefLayout)\n- [mapRef](#mapRef)\n- [mapSafeRequestAnimationFrame](#mapSafeRequestAnimationFrame)\n- [mapSafeTimeout](#mapSafeTimeout)\n- [mapState](#mapState)\n- [mapThrottledHandlerTimeout](#mapThrottledHandlerTimeout)\n- [mapThrottledHandlerAnimationFrame](#mapThrottledHandlerAnimationFrame)\n- [mapThrottledHandlerFactory](#mapThrottledHandlerFactory)\n- [mapWithAsyncProps](#mapWithAsyncProps)\n- [mapWithProps](#mapWithProps)\n- [mapWithPropsMemo](#mapWithPropsMemo)\n- [onMount](#onMount)\n- [pureComponent](#pureComponent)\n- [startWithType](#startWithType)\n- [StoreContextFactory](#StoreContextFactory)\n\n## `component`\n\nThis function is an analog of `compose` and it performs simple function composition, with two caveats:\n\n- The value sent into the chain is presumed to be a React Function Component (`FC` type)\n- `component` will use the output type of one function in the chain as the input type of the next function in the chain, allowing the functions to modify the type along the way. It is not necessary to tell `component` what the output type at the end of the chain is going to be, since it will be inferred correctly from the functions passed into it.\n\n## `mapContext`\n\nThis function receives a React Context object as created by the `React.createContext` function. The assumption is that the `value` property inside the Context is an object: `mapContext` will spread that object into the props of the components.\n\nFor example:\n\n```ts\nimport React, { createContext } from 'react'\nimport { component, mapContext, startWithType } from 'refun'\n\ntype TThemeContext = {\n  darkMode: boolean,\n}\n\nconst ThemeContext = createContext<TThemeContext>({\n  darkMode: false\n})\n\ntype TMessage = {\n  label: string\n}\n\ncomponent(\n  startWithType<TMessage>(),\n  mapContext(ThemeContext)\n)(({ darkMode, label }) => (\n  <p style={{ color: darkMode ? 'white' : 'black' }}>\n    {label}\n  </p>\n))\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapcontext-rtjvk)\n\n## `mapDebouncedHandlerTimeout`\n\n> This function is affected by the [React Synthetic Events vs debouncing / throttling](#react-synthetic-events-vs-debouncing--throttling) issue.\n\nThis function allows you to defer the execution of a handler for a grace period (specified in milliseconds) and if the handler gets invoked again during that period, it cancels the current grace period and overrides it with the new call, restarting the time counter.\n\nWhy you ask? Imagine for example that there is a button in the UI in which a user might be tempted to repeatedly click to make sure an action happens, but it doing so they will repeatedly trigger an expensive operation that will freeze the application. To avoid this, you could debounce the `onClick` handler for some milliseconds and make sure only the last call will be acted upon.\n\nThe difference between debouncing and throttling (available in [`mapThrottledHandlerTimeout`](#mapThrottledHandlerTimeout)) is that successive calls to a debounced handler will restart the timeout each time, while throttled calls will be executed once the initially set timeout it reached, using the last arguments. Following the FRP convention, this is how debouncing could be represented:\n\n```\ndebouncing in 3 seconds\n\n          1s 2s 3s 4s 5s 6s 7s 8s 9s\nreceived  x--y--------z------------\nran       ---------y--------z------\n```\n\nNotice how the timeout initially set for `x` is simply cancelled and overridden with a new timeout of 3 seconds for `y`.\n\n```ts\nimport * as React from \"react\"\nimport { component, mapHandlers, mapDebouncedHandlerTimeout, startWithType } from \"refun\"\n\ntype TButton = {\n  onClick: () => void\n}\n\nexport default component(\n  startWithType<TButton>(),\n  mapHandlers({\n    onClick: () => () => console.log(\"the handler was now called\")\n  }),\n  mapDebouncedHandlerTimeout(\"onClick\", 1000)\n)(({ onClick }) => (\n  <div>\n    <p>\n      Even if you click the button many times in a row (with each click less\n      than a second after the other), you will only see one log message, at the\n      end\n    </p>\n    <button onClick={onClick}>Click me</button>\n  </div>\n))\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapdebouncedhandlertimeout-791kn)\n\n## `mapDebouncedHandlerFactory`\n\n> All the functions create with this one are affected by the [React Synthetic Events vs debouncing / throttling](#react-synthetic-events-vs-debouncing--throttling) issue.\n\nThis function is a constructor for debouncers. It is used under the hood to build the `mapDebouncedHandlerTimeout` function. If you have a function that creates a deferred effect and a function that will cancel that deferral, you can build your own debouncer.\n\nThis is how `mapDebouncedHandlerTimeout` is defined:\n\n```ts\nexport const mapDebouncedHandlerTimeout = mapDebouncedHandlerFactory(setTimeout, clearTimeout)\n```\n\n## `mapDefaultProps`\n\nThis function sets some default prop values based on the object that is passed into it. Alternative to using the static `defaultProps` component property. The advantage of using it is that the props passed in will be type checked.\n\n```ts\nimport * as React from 'react'\nimport { component, mapDefaultProps, startWithType } from 'refun'\n\ntype TMessage = {\n  label?: string\n}\n\nexport default component(\n  startWithType<TMessage>(),\n  mapDefaultProps({\n    label: 'Hello World!'\n  })\n)(({ label }) => (\n  <p>{label}</p>\n))\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapdefaultprops-gqjqz)\n\n## `mapFocused`\n\nThis function sets the `isFocused` prop to `true` when the `onFocus` handler is called and to `false` when `onBlur` is called.\n\n```ts\nimport * as React from 'react'\nimport { component, mapFocused, startWithType, TMapFocused } from 'refun'\n\ntype TButton = {\n  label: string\n} & TMapFocused\n\nexport default component(\n  startWithType<TButton>(),\n  mapFocused\n)(\n  ({ isFocused, label, onBlur, onFocus }) => (\n    <button\n      onBlur={onBlur}\n      onFocus={onFocus}\n      style={{\n        borderWidth: 2,\n        borderStyle: \"solid\",\n        borderColor: isFocused ? \"red\" : \"grey\",\n        outline: \"none\"\n      }}\n    >\n      {label}\n    </button>\n  )\n)\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapfocused-8gls5)\n\n## `mapHandlers`\n\nThis function allows you to build custom handlers that will be memoized so that they do not cause a diff in the shallow comparison, which would lead to a re render.\n\nSo instead of writing:\n\n```ts\n// This will cause the component to re render every time because the handler is unique in every execution\nconst Input = ({ onChange, value }) => {\n  const handleChange = ({ target: { value } }) => onChange(value)\n\n  return <input\n    onChange={handleChange}\n    value={value}\n  />\n}\n```\n\n…it allows you to do:\n\n```ts\nimport * as React from 'react'\nimport { component, mapHandlers, startWithType } from 'refun'\n\ntype TInput = {\n  onChange: (string) => void,\n  value: string,\n}\n\nexport default component(\n  startWithType<TInput>(),\n  mapHandlers({\n    onChange: ({ onChange }) => ({ target: { value } }) => onChange(value),\n  })\n)(\n  ({ onChange, value }) => (\n    <input\n      onChange={onChange}\n      value={value}\n    />\n  )\n)\n```\n\nThe first argument that each handler will receive is the current props, and the second is the arguments that had been sent to the handler. Notice that the second argument is curried.\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-maphandlers-8d823)\n\n## `mapHovered`\n\nThis function sets the `isHovered` prop to `true` when the `onPointerEnter` handler is called and to `false` when `onPointerLeave` is called.\n\nNote that `onPointerEnter` and `onPointerLeave` are synthetic event names meant to abstract from platform specific hover states. In web, they will be typically mapped:\n\n- `onPointerEnter` -> `onMouseEnter`\n- `onPointerLeave` -> `onMouseLeave`\n\n…and each platform will have their own corresponding mapping.\n\n```ts\nimport React from 'react'\nimport { component, mapHovered, startWithType, TMapHovered } from 'refun'\n\ntype TButton = {\n  label: string\n} & TMapHovered\n\nexport default component(\n  startWithType<TButton>(),\n  mapHovered\n)(\n  ({ isHovered, label, onPointerLeave, onPointerEnter }) => (\n    <button\n      onMouseLeave={onPointerLeave}\n      onMouseEnter={onPointerEnter}\n      style={{\n        borderWidth: 2,\n        borderStyle: \"solid\",\n        borderColor: isHovered ? \"red\" : \"grey\",\n        outline: \"none\"\n      }}\n    >\n      {label}\n    </button>\n  )\n)\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-maphovered-lfzqj)\n\n## `mapKeyboardFocused`\n\nThis function sets the `isKeyboardFocused` prop to `true` when the target gets focused (after `onFocus`) but only if the focus was acquired via the keyboard interaction, not a pointer event (so if there was no press event before the `onFocus`). The prop is set to `false` once `onBlur` happens.\n\nThe reason this is useful is that it allows focus states meant for keyboard navigation to be differentiated from regular focus states. When the user is navigating with the keyboard, for example pressing the Tab key, visual highlighting of the focused elements needs to be more prominent to guide the sight into where the active element is. Pointer events will trigger focus as well, but when the interaction was initiated with a pointer it's not necessary for the highlight to be as prominent, since the user is already focused in the pointer position. In order to distinguish these two states and make it possible to style them separately, you can use `mapFocused` for the general case and `mapKeyboaredFocused` for the specific keyboard navigation case.\n\nNote that `onPressIn` and `onPointerLeave` are synthetic event names meant to abstract from platform specific hover states. In web, they will be typically mapped:\n\n- `onPressIn` -> `onMouseDown`\n- `onPressOut` -> `onMouseUp`\n\n…and each platform will have their own corresponding mapping.\n\n```ts\nimport React from 'react'\nimport { component, mapKeyboardFocused, startWithType, TMapKeyboardFocused } from 'refun'\n\ntype TButton = {\n  label: string\n} & TMapKeyboardFocused\n\nexport default component(\n  startWithType<TButton>(),\n  mapKeyboardFocused\n)(\n  ({ isKeyboardFocused, label, onBlur, onFocus, onPressIn, onPressOut }) => (\n    <button\n      onBlur={onBlur}\n      onFocus={onFocus}\n      onMouseDown={onPressIn}\n      onMouseUp={onPressOut}\n      style={{\n        borderWidth: 2,\n        borderStyle: \"solid\",\n        borderColor: isKeyboardFocused ? \"red\" : \"grey\",\n        outline: \"none\"\n      }}\n    >\n      {label}\n    </button>\n  )\n)\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapkeyboardfocused-okqxt)\n\n## `mapPressed`\n\nThis function sets the `isPressed` prop to `true` when the `onPressIn` handler is called and to `false` when `onPressOut` is called.\n\nNote that `onPressIn` and `onPressOut` are synthetic event names meant to abstract from platform specific pressed states. In web, they will be typically mapped:\n\n- `onPressIn` -> `onMouseDown`\n- `onPressOut` -> `onMouseUp`\n\n…and each platform will have their own corresponding mapping.\n\n```ts\nimport React from 'react'\nimport { component, mapPressed, startWithType, TMapPressed } from 'refun'\n\ntype TButton = {\n  label: string\n} & TMapPressed\n\nexport default component(\n  startWithType<TButton>(),\n  mapPressed\n)(\n  ({ isPressed, label, onPressIn, onPressOut }) => (\n    <button\n      onMouseDown={onPressIn}\n      onMouseUp={onPressOut}\n      style={{\n        borderWidth: 2,\n        borderStyle: \"solid\",\n        borderColor: isPressed ? \"red\" : \"grey\",\n        outline: \"none\"\n      }}\n    >\n      {label}\n    </button>\n  )\n)\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mappressed-z8lbx)\n\n## `mapProps`\n\nThis function takes a handler that receives all props and returns new props.\n\n```ts\nimport React from 'react'\nimport { component, mapProps, startWithType } from 'refun'\n\ntype TButton = {\n  label: string\n}\n\nexport default component(\n  startWithType<TButton>(),\n  mapProps(({ label }) => ({ children: label }))\n)(\n  ({ children }) => <button>{children}</button>\n)\n```\n\nNote that `label` is no longer available as a prop to the component. If you want to expand the props with extra ones instead of replacing them consider using [`mapWithProps`](#mapWithProps)\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapprops-37ho6)\n\n## `mapReducer`\n\nThis function takes a reducer and an initial state factory, and passes down the `state` (spreaded as props) and the `dispatch` function. It employs the `useReducer` hook under the hood.\n\n```ts\nimport React from 'react'\nimport { component, mapReducer, startWithType } from 'refun'\n\ntype TCounter = {\n  initialCounter: number\n}\n\ntype TState = {\n  counter: number\n}\n\ntype TAction = {\n  type: \"ADD\"\n}\n\nconst Counter = component(\n  startWithType<TCounter>(),\n  mapReducer(\n    (state: TState, action: TAction): TState => {\n      switch (action.type) {\n        case \"ADD\":\n          return {\n            counter: state.counter + 1\n          }\n\n        default:\n          return state\n      }\n    },\n    ({ initialCounter }) => ({\n      counter: initialCounter\n    })\n  )\n)(({ counter, dispatch }) => (\n  <div>\n    <button onClick={() => dispatch({ type: \"ADD\" })}>Add</button>\n    <span>{counter}</span>\n  </div>\n))\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapreducer-wqgv6)\n\n## `mapRefLayout`\n\nThis function allows you to capture the `ref` to a DOM element, and synchronously perform an update of the props based on some values of the element. It relies on `useLayoutEffect` under the hoods to synchronously capturing the `ref` and then updates the state, which will cause React to cancel the previous render and use the updated one instead.\n\nThis is particularly useful in order to measure a component’s size and update the rendering without causing any flickering.\n\n`mapRefLayout` receives three arguments:\n\n1. The name of the prop that will hold the `ref`\n2. A handler that receives the `ref` and the props as arguments, and returns a set of props to be added to the incoming props.\n3. A list of names of incoming props to be monitored. If one of those props changes, the handler should be executed again. Otherwise it will be skipped. See [`mapWithPropsMemo`](#mapWithPropsMemo) for a similar API.\n\n```ts\nimport * as React from \"react\"\nimport { component, mapRefLayout, startWithType } from \"refun\"\n\ntype TLayout = {\n  direction: \"horizontal\" | \"vertical\"\n}\n\nconst Button = component(\n  startWithType<TLayout>(),\n  mapRefLayout(\n    \"buttonElementRef\",\n    (buttonElementRef, { direction }): { size: number } => {\n      if (buttonElementRef) {\n        switch (direction) {\n          case \"horizontal\":\n            return {\n              size: buttonElementRef.getBoundingClientRect().width\n            }\n          case \"vertical\":\n            return {\n              size: buttonElementRef.getBoundingClientRect().height\n            }\n        }\n      }\n\n      return {\n        size: 10\n      }\n    },\n    [\"direction\"]\n  )\n)(({ buttonElementRef, size }) => <button ref={buttonElementRef}>{size}</button>)\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapreflayout-ve3zn)\n\n## `mapRef`\n\nThis function provides a way of making a mutable reference available as a prop. It uses the `useRef` hook under the hood.\n\nRefs are useful to store derived values that do not support shallow comparison, such as functions, or DOM elements.\n\nFor example you can use it to capture the `ref` to a DOM element and inspect it:\n\n```ts\nimport React from 'react'\nimport { component, mapRef, onMount, startWithType } from 'refun'\n\ntype TButton = {\n  label: string\n}\n\nexport default component(\n  startWithType<TButton>(),\n  mapRef('buttonElementRef', null),\n  onMount(({ buttonElementRef }) => {\n    if (buttonElementRef.current !== null) {\n      console.log(buttonElementRef)\n    }\n  })\n)(\n  ({ buttonElementRef, label }) => (\n    <button ref={buttonElementRef}>\n      {label}\n    </button>\n  )\n)\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapref-t3wog)\n\n## `mapSafeRequestAnimationFrame`\n\nThis function allows you to set up operations to be executed in the next animation frame that should only be executed while the component is still mounted, and should be canceled if the component is removed from the tree. Callbacks that are not canceled when unmounted are a common cause of React memory leaks.\n\nWhy you ask? Animations. Animations can be done in React by continuously updating style parameters of a component, and the cleanest way of updating those is with `requestAnimationFrame`. This function allows you to use `requestAnimationFrame` without worrying about memory leaks.\n\n\n> As you can check in this [📺 live demo of the issue](https://codesandbox.io/s/refun-mapsafeanimationframe-problem-demonstration-4t0w1), simply using `requestAnimationFrame` will cause the problems when pressing the \"Stop loading\" button. In particular, React will log:\n> ```\n> Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.\n> ```\n> `mapSafeRequestAnimationFrame` does the cleanup for you.\n\n```ts\nimport * as React from \"react\"\nimport {\n  component,\n  mapState,\n  mapSafeRequestAnimationFrame,\n  startWithType,\n  mapHandlers\n} from \"refun\"\n\ntype TLoader = {\n  initialPosition: number\n}\n\nconst Loader = component(\n  startWithType<TLoader>(),\n  mapState(\n    \"position\",\n    \"setPosition\",\n    ({ initialPosition }) => initialPosition,\n    []\n  ),\n  mapSafeRequestAnimationFrame(\"setAnimationFrameCallback\")\n)(({ position, setPosition, setAnimationFrameCallback }) => {\n  setAnimationFrameCallback(() => {\n    setPosition((position + 1) % 80)\n  })\n  return (\n    <div\n      style={{\n        width: 100,\n        height: 8,\n        border: \"1px solid black\"\n      }}\n    >\n      <div\n        style={{\n          width: 20,\n          marginLeft: position,\n          height: 8,\n          backgroundColor: \"black\"\n        }}\n      />\n    </div>\n  )\n})\n\ntype TApp = {\n  loading: boolean\n}\n\nexport default component(\n  startWithType<TApp>(),\n  mapState(\n    \"loading\",\n    \"setLoading\",\n    ({ loading }) => loading !== undefined ? loading : true,\n    []\n  ),\n  mapHandlers({\n    onStop: ({ setLoading }) => () => setLoading(false)\n  })\n)(({ loading, onStop }) => (\n  <div>\n    {loading && <Loader initialPosition={0} />}\n    <button onClick={onStop}>Stop loading</button>\n  </div>\n))\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapsafeanimationframe-s3ttu)\n\n## `mapSafeTimeout`\n\nThis function allows you to configure time outs that should only be executed while the component is still mounted, and should be canceled if the component is removed from the tree. Timeouts that are not canceled when unmounted are a common cause of React memory leaks.\n\n> As you can check in this [📺 live demo of the issue](https://codesandbox.io/s/refun-mapsafetimeout-problem-demonstration-dkiwq), simply using `setTimeout` will cause the problems when pressing the \"Close immediately\" button before the countdown is completed. In particular, React will log:\n> ```\n> Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.\n> ```\n> `mapSafeTimeout` does the cleanup for you.\n\n```ts\nimport * as React from \"react\"\nimport {\n  component,\n  mapHandlers,\n  mapState,\n  mapSafeTimeout,\n  startWithType\n} from \"refun\"\n\ntype TMessage = {\n  onClose: () => void\n}\n\nconst Message = component(\n  startWithType<TMessage>(),\n  mapState(\"autoClose\", \"setAutoClose\", () => false, []),\n  mapState(\"secondsRemaining\", \"setSecondsRemaining\", () => 5, []),\n  mapSafeTimeout(\"setLocalTimeout\")\n)(\n  ({\n    onClose,\n    secondsRemaining,\n    setSecondsRemaining,\n    setLocalTimeout,\n    autoClose,\n    setAutoClose\n  }) => (\n    <div\n      style={{\n        backgroundColor: \"#f0f0f0\",\n        padding: 20\n      }}\n    >\n      {autoClose ? (\n        <React.Fragment>\n          <p>This message will close in {secondsRemaining} seconds</p>\n          <button onClick={onClose}>Close immediately</button>\n        </React.Fragment>\n      ) : (\n        <React.Fragment>\n          <p>\n            This message that will close {secondsRemaining} seconds after you\n            press OK\n          </p>\n\n          <button\n            onClick={() => {\n              setAutoClose(true)\n              setLocalTimeout(() => {\n                console.log(\"timeout 1000\")\n                setSecondsRemaining(4)\n              }, 1000)\n              setLocalTimeout(() => {\n                console.log(\"timeout 2000\")\n                setSecondsRemaining(3)\n              }, 2000)\n              setLocalTimeout(() => {\n                console.log(\"timeout 3000\")\n                setSecondsRemaining(2)\n              }, 3000)\n              setLocalTimeout(() => {\n                console.log(\"timeout 4000\")\n                setSecondsRemaining(1)\n              }, 4000)\n              setLocalTimeout(() => {\n                console.log(\"timeout 5000\")\n                onClose()\n              }, 5000)\n            }}\n          >\n            Ok\n          </button>\n        </React.Fragment>\n      )}\n    </div>\n  )\n)\n\ntype TApp = {\n  show?: boolean\n}\n\nexport default component(\n  startWithType<TApp>(),\n  mapState(\"show\", \"setShow\", ({ show }) => true, []),\n  mapHandlers({\n    onClose: ({ setShow }) => () => setShow(false),\n    onShow: ({ setShow }) => () => setShow(true)\n  })\n)(({ show, onClose, onShow }) => (\n  <div>\n    {show ? (\n      <Message onClose={onClose} />\n    ) : (\n      <button onClick={onShow}>Show message again</button>\n    )}\n  </div>\n))\n```\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapsafetimeout-7mqmh]\n\n## `mapState`\n\nThis function allows you to set up a stateful prop and a function for updating that prop. It also supports setting the initial value, derived from the props passed into it, and a list of props to watch to reset that value whenever the external prop changes.\n\nNote in the example how the `OverridableInternalCounter` sets the `[\"counter\"]` as the last argument of `mapState`. This will cause `mapState` to watch for incoming changes to the `counter` prop and use them to update the `internalCounter` prop, accordingly to the function in the third argument `({ counter }) => counter`. In the case of `InternalCounter`, the array in the last argument is empty (`[]`) and then `mapState` does not watch for changes, which causes the external prop `counter` value to be ignored once updated, effectively working as an initial value only for `internalCounter`.\n\n```ts\nimport * as React from \"react\"\nimport { component, mapState, startWithType } from \"refun\"\n\ntype TCounter = {\n  counter: number\n}\n\nconst InternalCounter = component(\n  startWithType<TCounter>(),\n  mapState(\"internalCounter\", \"setCounter\", ({ counter }) => counter, [])\n)(({ internalCounter, setCounter }) => (\n  <div>\n    <button onClick={() => setCounter(internalCounter + 1)}>\n      Add to internal counter\n    </button>\n    <p>{internalCounter}</p>\n  </div>\n));\n\nconst OverridableInternalCounter = component(\n  startWithType<TCounter>(),\n  mapState(\"internalCounter\", \"setCounter\", ({ counter }) => counter, [\n    \"counter\"\n  ])\n)(({ internalCounter, setCounter }) => (\n  <div>\n    <button onClick={() => setCounter(internalCounter + 1)}>\n      Add to overridable internal counter\n    </button>\n    <p>{internalCounter}</p>\n  </div>\n));\n\nexport default component(\n  startWithType<TCounter>(),\n  mapState(\"externalCounter\", \"setExternalCounter\", ({ counter }) => counter, [\n    \"counter\"\n  ])\n)(({ externalCounter, setExternalCounter }) => (\n  <div>\n    <button onClick={() => setExternalCounter(externalCounter + 1)}>\n      Add to external counter\n    </button>\n    <p>{externalCounter}</p>\n    <OverridableInternalCounter counter={externalCounter} />\n    <InternalCounter counter={externalCounter} />\n  </div>\n))\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapstate-zy1rj)\n\n## `mapThrottledHandlerTimeout`\n\n> This function is affected by the [React Synthetic Events vs debouncing / throttling](#react-synthetic-events-vs-debouncing--throttling) issue.\n\nThis function allows you to defer the execution of a handler for a grace period (specified in milliseconds) and if the handler gets invoked again during that period, it overrides the call with the new invocation, so that when the specified timeout is reached, the last call will be the one executed.\n\nWhy you ask? Imagine for example that you have an application that monitors the window size and updates the layout depending on the new size. Window size updates happen very often while the user is performing the resize, and the new layout calculation might be fairly expensive, so the application might become unresponsive. In this case, you could use `mapThrottledHandlerTimeout` to make sure the resize update only happens every 500 milliseconds, which will not be too noticeable to the user, but will avoid a lot of unnecessary work. Because `mapThrottledHandlerTimeout` executes the _last_ invocation of the handler, the value that will be captured is the most recent one, which is important since we want to re layout according to the current size, no the one when the resize action started.\n\nThe difference between debouncing and throttling (available in [`mapDebouncedHandlerTimeout`](#mapDebouncedHandlerTimeout)) is that successive calls to a debounced handler will restart the timeout each time, while throttled calls will be executed once the initially set timeout it reached, using the last arguments. Following the FRP convention, this is how debouncing could be represented:\n\n```\nthrottling in 3 seconds\n\n          1s 2s 3s 4s 5s 6s 7s 8s 9s\nreceived  x--y--------x------------\nran       ------y-----------x------\n```\n\nNotice how the timeout initially configured for `x` is respected and the execution happens 3 seconds after the event for `x` is received, but `y` is run instead.\n\n```ts\nimport * as React from \"react\"\nimport {\n  component,\n  mapThrottledHandlerTimeout,\n  startWithType,\n  mapHandlers\n} from \"refun\"\n\ntype TSlider = {\n  onChange: (string) => void\n}\n\nexport default component(\n  mapHandlers({\n    onChange: () => (value) =>\n      console.log(`the handler has now been invoked with value: ${value}`)\n  }),\n  startWithType<TSlider>(),\n  mapThrottledHandlerTimeout(\"onChange\", 300),\n  mapHandlers({\n    onChange: ({ onChange }) => ({ target: { value } }) => onChange(value)\n  })\n)(({ onChange }) => <input type=\"range\" onChange={onChange} max=\"1000\" />)\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapthrottledhandlertimeout-1ss16)\n\n## `mapThrottledHandlerAnimationFrame`\n\n> This function is affected by the [React Synthetic Events vs debouncing / throttling](#react-synthetic-events-vs-debouncing--throttling) issue.\n\nThis function allows you to defer the execution of a handler until the next animation frame. If the handler gets invoked again before that animation frame hits, the new invocation will override the previous one, so that when the animation frame starts the last call will be the one executed.\n\nWhy you ask? Pretty much the same reasons that are true for [`mapThrottledHandlerTimeout`](#mapThrottledHandlerTimeout). Calls that are done between animation frames are wasteful overhead, since the UI will not be updated until the animation frame anyway, so if you have a handler firing continuously, it's a good idea to skip the wasteful ones. This might happen for handlers monitoring scroll or wheel or finger motion actions.\n\n> You might wonder why there is not `mapDebouncedHandlerAnimationFrame` if there is a `mapDebouncedHandlerTimeout`. The reason is that the behavior of that function would be identical to this one, so it's skipped.\n\n```ts\nimport * as React from \"react\"\nimport {\n  component,\n  mapThrottledHandlerAnimationFrame,\n  startWithType,\n  mapHandlers\n} from \"refun\"\n\ntype TSlider = {\n  onChange: (string) => void\n}\n\nexport default component(\n  startWithType<TSlider>(),\n  mapHandlers({\n    onChange: () => (value) =>\n      console.log(`the handler has now been invoked with value: ${value}`)\n  }),\n  mapThrottledHandlerAnimationFrame(\"onChange\"),\n  mapHandlers({\n    onChange: ({ onChange }) => ({ target: { value } }) => onChange(value)\n  })\n)(({ onChange }) => <input type=\"range\" onChange={onChange} max=\"1000\" />)\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapthrottledhandleranimationframe-xk8uc)\n\n## `mapThrottledHandlerFactory`\n\n> All the functions created with this one is affected by the [React Synthetic Events vs debouncing / throttling](#react-synthetic-events-vs-debouncing--throttling) issue.\n\nThis function is a constructor for throttlers. It is used under the hood to build the `mapThrottledHandlerTimeout` and `mapThrottledHandlerAnimationFrame` functions. If you have a function that creates a deferred effect and a function that will cancel that deferral, you can build your own throttler.\n\nThis is how `mapThrottledHandlerTimeout` is defined:\n\n```ts\nexport const mapThrottledHandlerTimeout = mapThrottledHandlerFactory(setTimeout, clearTimeout)\n```\n\n## `mapWithAsyncProps`\n\nThis function is exactly like [`mapWithPropsMemo`](#mapWithPropsMemo), except that the mapper function is expected to return a Promise that will resolve with the props to add.\n\n```ts\nimport * as React from \"react\";\nimport { render } from \"react-dom\";\nimport { component, mapWithAsyncProps, startWithType } from \"refun\";\nimport axios from \"axios\";\n\ntype TPokemon = {\n  id: string;\n};\n\nconst Pokemon = component(\n  startWithType<TPokemon>(),\n  mapWithAsyncProps(\n    async ({ id }) => {\n      try {\n        const response = await axios.get(\n          `https://pokeapi.co/api/v2/pokemon/${id}`\n        );\n\n        return {\n          height: response.data.height,\n          weight: response.data.weight\n        };\n      } catch {\n        return {\n          height: undefined,\n          weight: undefined\n        };\n      }\n    },\n    [\"id\"]\n  )\n)(({ id, height, weight }) => (\n  <p>\n    {id} is {height} height and weights {weight}\n  </p>\n));\n\nexport default () => <Pokemon id=\"pikachu\" />\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapwithasyncprops-ty9l6)\n\n## `mapWithProps`\n\nThis function allows you to expand the props passed in to a component with more props derived from them. It is typically used to precalculate values that are to be used in the component, to minimize the amount of logic needed to do in the render.\n\nIf the returned props have the same name as incoming props, they will override the incoming props.\n\n```ts\nimport React from 'react'\nimport {\n  component,\n  mapFocused,\n  mapWithProps,\n  startWithType,\n  TMapFocused\n} from \"refun\"\n\ntype TButton = {\n  label: string\n} & TMapFocused\n\nexport default component(\n  startWithType<TButton>(),\n  mapFocused,\n  mapWithProps(({ isFocused }) => ({\n    borderColor: isFocused ? \"red\" : \"grey\"\n  }))\n)(({ borderColor, label, onBlur, onFocus }) => (\n  <button\n    onBlur={onBlur}\n    onFocus={onFocus}\n    style={{\n      borderWidth: 2,\n      borderStyle: \"solid\",\n      borderColor,\n      outline: \"none\"\n    }}\n  >\n    {label}\n  </button>\n))\n```\n\nNote that this function just adds props to the component. If you want to replace all of them, you can use [`mapProps`](#mapProps) instead.\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapwithprops-cjdsc)\n\n## `mapWithPropsMemo`\n\nThis function does the same as [`mapWithProps`](#mapWithProps) and it memoizes the result for the props specified in the second parameter.\n\nAn example use case in which this can prove useful is if you were to be calculating the Fibonacci number of an input, which is known to be expensive for large numbers:\n\n```ts\nimport React from 'react'\nimport { component, mapWithPropsMemo, startWithType } from 'refun'\n\nconst inefficientFibonacci = position =>\n  position < 2\n    ? position\n    : inefficientFibonacci(position - 1) + inefficientFibonacci(position - 2)\n\ntype TFibonacci = {\n  position: number\n}\n\nexport default component(\n  startWithType<TFibonacci>(),\n  mapWithPropsMemo(\n    ({ position }) => ({\n      fibonacci: inefficientFibonacci(position)\n    }),\n    [\"position\"]\n  )\n)(({ position, fibonacci }) => (\n  <p>\n    The Fibonacci numbers in position {position} is <mark>{fibonacci}</mark>\n  </p>\n))\n```\n\nNotice that `mapWithPropsMemo` takes two arguments, and that memoization happens for the props that are specified in the second argument, in this case `position`.\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapwithpropsmemo-hjcso)\n\n## `onMount`\n\nThis function calls the passed in callback when the component is first mounted, sending the current Props as argument.\n\nFor example:\n\n```ts\nimport React from 'react'\nimport { component, onMount, startWithType } from 'refun'\n\ntype TButton = {\n  label: string,\n}\n\nexport default component(\n  startWithType<TButton>(),\n  onMount(({ label }) => console.log('Mounted with label', label))\n)(({ label }) => (\n  <button>\n    {label}\n  </button>\n))\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-onmount-5r5ol)\n\n## `pureComponent`\n\nThis function is identical to [`component`](#component) except that it memoizes the React element that results from rendering with a certain set of props. The props that are memoized are the _inner_ props, that is, the props that the component will get as the result of the entire composition chain. These are different from the _outer_ props, that are the ones that consumers pass manually into the component.\n\nThe purpose of this component is to prevent a re render from happening when the React tree is known to be the same. It is particularly useful when the React tree is a complex one, since the cost grows fast with the amount of nodes in the tree. Since the memoization is done in the inside of the component, all `map` functions will be run, making it ideal for components that control their own state.\n\n> Note that this function is meant to be used to avoid pointless re renders of complex trees, which is a concern that should be treated at the high level, in an app for example, rather than in small presentational components. Memoization comes with a cost, and React is already providing optimizations via reconciliation, so the type of optimizations that `pureComponent` does, similar to the old `shouldComponentUpdate`, is to be reserved for cases where there is a clear need for optimization.\n\n```ts\nimport React from 'react'\nimport { mapReducer, pureComponent, startWithType } from 'refun'\nimport AComplexHeader from './AComplexHeader'\nimport AnExpensiveToComputeSidebar from './AnExpensiveToComputeSidebar'\n\ntype TCounter = {\n  initialCount: number,\n}\n\nexport default pureComponent(\n  startWithType<TCounter>(),\n  mapReducer(\n    (state, action) => {\n      switch (action.type) {\n        case 'ADD':\n          return {\n            counter: state.counter + 1\n          }\n\n        default:\n          return state\n      }\n    },\n    ({ initialCounter }) => ({\n      counter: initialCounter\n    })\n  )\n)(({ counter, dispatch }) = (\n  <main>\n    <AComplexHeader />\n    <AnExpensiveToComputeSidebar />\n    <button>\n      Add\n    </button>\n\n    <p>{counter}</p>\n  </main>\n))\n```\n\nSo to be clear, the component that receives `counter` and `dispatch` as props is the one that is going to be memoized. If your intention is to memoize an expensive computation in a function in the composition chain, such as calculating a value in the `mapWithProps`, take a look at [`mapWithPropsMemo`](#mapWithPropsMemo) instead.\n\n`pureComponent` should only be used in components that receive no `children` and no complex props, since otherwise the overhead of memoization is not worth it. If the component receives `children` or complex props (objects / arrays), `pureComponent` will not provide any benefit, since those are very likely (or guaranteed in the case of `children`) to be different on every render. `pureComponent` works by doing a shallow comparison of the current props with the previous props. Shallow comparison means that each prop is compared with hard equality with the previous value of that same props.\n\n## `startWithType`\n\nThis function is simply a way of setting up the initial type in the [`component`](#component) composition chain, since TypeScript does not currently support doing that in the composition function itself (`component` in this case, but would be `compose` in Redux, Ramda, etc).\n\nIt's purpose is entirely for types, and in runtime it's a no-op.\n\n```ts\nimport React from 'react'\nimport { component, startWithType } from 'refun'\n\ntype TButton = {\n  label: string,\n}\n\nexport default component(\n  startWithType<TButton>(),\n)(({ label }) = (\n  <button>\n    {label}\n  </button>\n))\n```\n\nOnce this is fixed in TypeScript this function will be redundant and it will be possible to pass the generic directly into `component`:\n\n```ts\nimport React from 'react'\nimport { component } from 'refun'\n\ntype TButton = {\n  label: string,\n}\n\n// Remember: this is currently *not* supported\nexport default component<TButton>(\n  (props) => props\n)(({ label }) = (\n  <button>\n    {label}\n  </button>\n))\n```\n\n…meanwhile `startWithType` is a straightforward workaround.\n\n## `StoreContextFactory`\n\nThis function is a way of working with Redux stores together with React Hooks. It is an alternative to React Redux, with these goals:\n\n1. Work with Hooks, avoiding higher-order components\n2. Respect the types all throughout\n3. Match the level of optimization of React Redux.\n\nThe way this function works is that it receives a Redux Store object, and returns a component and two functions:\n\n- `StoreProvider` is a component that provides the React Context already loaded with the store that was passed in to the `StoreContextFactory`\n- `mapStoreDispatch` is a function to be used as part of a `component` or `pureComponent` composition, which will simply add `dispatch` to the props, so that the component being wrapped by it can dispatch actions.\n- `mapStoreState` is a function to be used as part of a `component` or `pureComponent` composition, which will add props derived from the state. Much like `connect` from React Redux, it receives a `mapStateToProps` function that will be called with the full state and which return value will be spread over the component props. `mapStoreState` takes as a second argument an array of the names of the props to watch in order to run the `mapStateToProps` function: if none of the listed props have changed, the `mapStateToProps` will not be ran.\n\nCheck the example below for a full use case.\n\n```ts\nimport * as React from \"react\"\nimport { createStore } from \"redux\"\nimport { component, pureComponent, StoreContextFactory, mapHandlers } from \"refun\"\n\ntype TState = {\n  counter: number\n}\n\ntype TAction = { type: \"INCREMENT\" payload: number } | { type: \"RESET\" }\n\nconst reducer = (state: TState, action: TAction): TState => {\n  switch (action.type) {\n    case \"INCREMENT\":\n      return {\n        ...state,\n        counter: state.counter + action.payload\n      }\n\n    case \"RESET\":\n      return {\n        ...state,\n        counter: 0\n      }\n\n    default:\n      return state\n  }\n}\n\nconst initialState = {\n  counter: 7\n}\n\nconst store = createStore(reducer, initialState)\n\nconst { StoreProvider, mapStoreState, mapStoreDispatch } = StoreContextFactory(\n  store\n)\n\nconst CounterDisplay = pureComponent(\n  mapStoreState(\n    ({ counter }) => ({\n      counter\n    }),\n    [\"counter\"]\n  )\n)(({ counter }) => (\n  <div>\n    <p>Counter: {counter}</p>\n  </div>\n))\n\nconst ResetButton = component(\n  mapStoreDispatch,\n  mapHandlers({\n    onClick: ({ dispatch }) => () =>\n      dispatch({\n        type: \"RESET\"\n      })\n  })\n)(({ onClick }) => (\n  <div>\n    <button onClick={onClick}>Reset</button>\n  </div>\n))\n\nconst IncrementButton = component(\n  mapStoreDispatch,\n  mapHandlers({\n    onClick: ({ dispatch }) => () =>\n      dispatch({\n        type: \"INCREMENT\",\n        payload: 1\n      })\n  })\n)(({ onClick }) => (\n  <div>\n    <button onClick={onClick}>Increment</button>\n  </div>\n))\n\nexport default () => (\n  <StoreProvider>\n    <div>\n      <CounterDisplay />\n      <ResetButton />\n      <IncrementButton />\n    </div>\n  </StoreProvider>\n)\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-storecontextfactory-l9bp5)\n\n## Caveats\n\n### React Synthetic Events vs debouncing / throttling\n\nThe `mapDebounced*` and `mapThrottled*` family of functions do not accept React Synthetic Events. As you can see in the examples below, some specific properties of the event (`value` in that case) need to be extracted from the original Synthetic Event in order for them to work.\n\nThis is necessary because these two function families store the arguments passed to the handlers for delayed use. If that argument is a Synthetic Event, it will be stored to be reused, but React forbids this, because for performance reasons React reuses the references of Synthetic Events and mutates them.\n\n> If you try the example below without the `mapHandlers`, you will get:\n>\n> ```\n> Warning: This synthetic event is reused for performance reasons. If you're seeing this, you're accessing the property `target` on a released/nullified synthetic event. This is set to null. If you must keep the original synthetic event around, use event.persist(). See https://fb.me/react-event-pooling for more information.\n> ```\n>\n> [📺 Check out live demo](https://codesandbox.io/s/refun-mapthrottledhandlertimeout-wrong-usage-7q6cd)\n\n\nIf you are going to use information coming from the Synthetic Event, consider extracting the information you care about using `mapHandlers`, which will then let React discard the rest of the Event object.\n\nIf you are not going to use _any_ information coming from the Event—such as in the example for [`mapDebouncedHandlerTimeout`](#mapDebouncedHandlerTimeout)—then you will not be affected by this issue.\n\n```ts\nimport * as React from \"react\"\nimport {\n  component,\n  mapThrottledHandlerTimeout,\n  startWithType,\n  mapHandlers\n} from \"refun\"\n\ntype TSlider = {\n  onChange: (string) => void\n}\n\nexport default component(\n  mapHandlers({\n    onChange: () => (value) =>\n      console.log(`the handler has now been invoked with value: ${value}`)\n  }),\n  startWithType<TSlider>(),\n  mapThrottledHandlerTimeout(\"onChange\", 300),\n  mapHandlers({\n    onChange: ({ onChange }) => ({ target: { value } }) => onChange(value)\n  })\n)(({ onChange }) => <input type=\"range\" onChange={onChange} max=\"1000\" />)\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapthrottledhandlertimeout-1ss16)\n","readmeFilename":"readme.md","bugs":{"url":"https://github.com/bubble-dev/_/issues"},"homepage":"https://github.com/bubble-dev/_#readme","_id":"refun@0.5.0-beta.0","_nodeVersion":"13.5.0","_npmVersion":"6.13.4","dist":{"integrity":"sha512-6lEJ9CQG8PjAwUMDW0adrgz1Oi01+aPpGarY7g+ESuxWFDkcUaiYiC6v8gGa+3HymSSF1uNOAUrUbGJiE4nhng==","shasum":"afb7e820f63d49890b7b5e9c36bed5b477b33c7a","tarball":"https://registry.npmjs.org/refun/-/refun-0.5.0-beta.0.tgz","fileCount":267,"unpackedSize":455370,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeALBVCRA9TVsSAnZWagAA3toQAKDsMwvjUj5ny8nNxiDu\nKsVqvADUjs7xhUPNy04ZaBTg4p2ntYGoqp+VFOQ3PltuDuGxDr2wX5dDIEga\n+Dl7e5HPjSg+8TicDlAV6eRpKpMxKj9myOkj/J+fZmRmgkOXXMgidIMkxYID\n1NhuybgF5b+d7G2BK0P0r0XAqk6KdoS4a0RRcwIstvmp0wWi8vL3/xFmMPz4\n1YJ6nBa0YCpcfProI7AsBgwfNdgBUoAfuO2n4x3K5HX/p+KL1SKuHGUfYq5+\nr/FC/BrOZPIBGGCbPCpIsOeJKZnRqP45sHa1clKjal04CSyMSCz69JTyp7O9\nqrHa2K7aLuib4Mzc3nM2CEXYEsO7c9gdpw4+xuulC6dBZeFrrJXxjXlhuqLx\nVNRu7UCVvZd5KH7SzSVZrVdsgKi4p6tDq3fnXn5ngcVSELwAQYFaZL9YtZo+\nk7UFCwmEuRLJ9CYqJlf6IJ6r2ldzSXWRukBKEGbOk/zEwO8p+Sm73E/sEGfw\nD0/lA6Z8l69UWGME5qq/xg+qLKkViyrvBO1YcL0Gm4260/lQ6TU8UFxaGLIC\nMZC2Qp2MKJQJbWXX1FC8ILyO1yvcMXhfNZ/sJOyS8k9w0mKFZB/9s2h87bCT\nlujfyWiTmWYXLKrbkhtDq+lPxwEjMZm6hT50XQfPgXRylJs6fIJG9dzge+7+\n92t+\r\n=nYwl\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDX7/JcXdf0jOh6XcFkVFZZF8MC+iGmNsoCLM+KJoVP1AiAJ9FX5r1nFmxrqWlgkKv0cBUHHjiwoaj03DlhbmmpvhA=="}]},"maintainers":[{"email":"kir@belevi.ch","name":"deepsweet"},{"email":"irminakacz@gmail.com","name":"irminakacz"},{"email":"psxcode@gmail.com","name":"psxcode"},{"email":"fernando.via@gmail.com","name":"xaviervia"}],"_npmUser":{"name":"psxcode","email":"psxcode@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refun_0.5.0-beta.0_1577103445306_0.17190945056371998"},"_hasShrinkwrap":false},"0.5.0-beta.1":{"name":"refun","version":"0.5.0-beta.1","description":"A collection of React Hook-enabled functions that compose harmoniously with each other. Similar to `recompose`, but:","keywords":[],"main":"node/index.js","browser":"web/index.js","react-native":"native/index.js","repository":{"type":"git","url":"git+https://github.com/bubble-dev/_.git"},"license":"MIT","engines":{"node":">=8.6.0"},"sideEffects":false,"dependencies":{"tsfn":"^0.2.0"},"readme":"# refun\n\nA collection of React Hook-enabled functions that compose harmoniously with each other. Similar to `recompose`, but:\n\n- Uses `Props -> Props` functions instead of `Component -> Component` functions. This is all around better. It means:\n  - Less nodes in the React tree\n  - Better optimization options for the JavaScript engine\n  - Being able to reuse general purpose functions (all of Ramda's object manipulation functions work)\n- Propagates TypeScript types through the composition chain **without any losses**.\n- Works entirely with React Hooks instead of class components\n\n## Usage example (with TypeScript)\n\n```ts\nimport * as React from \"react\"\nimport {\n  component,\n  mapDefaultProps,\n  mapHandlers,\n  mapHovered,\n  mapState,\n  mapWithPropsMemo,\n  startWithType,\n  TMapHovered\n} from \"refun\"\n\ntype TButton = {\n  isDisabled?: boolean\n  clickCounter?: number\n  id?: string\n} & TMapHovered\n\nexport const Button = component(\n  startWithType<TButton>(),\n  mapDefaultProps({\n    clickCounter: 0,\n    isDisabled: false\n  }),\n  mapState(\n    \"clickCounter\",\n    \"setClickCounter\",\n    ({ clickCounter }) => clickCounter,\n    [\"clickCounter\"]\n  ),\n  mapHandlers({\n    onClick: ({ clickCounter, setClickCounter }) => () =>\n      setClickCounter(clickCounter + 1)\n  }),\n  mapHovered,\n  mapWithPropsMemo(\n    ({ clickCounter, isDisabled, isHovered }) => ({\n      children: `Click count: ${clickCounter}`,\n      style: {\n        cursor: isDisabled ? \"auto\" : \"pointer\",\n        borderColor: isHovered ? \"black\" : \"grey\"\n      }\n    }),\n    [\"clickCounter\", \"isDisabled\", \"isHovered\"]\n  )\n)(\n  ({\n    id,\n    isDisabled,\n    style,\n    onPointerEnter,\n    onPointerLeave,\n    onClick,\n    children\n  }) => (\n    <button\n      disabled={isDisabled}\n      id={id}\n      onClick={onClick}\n      onMouseEnter={onPointerEnter}\n      onMouseLeave={onPointerLeave}\n      style={style}\n    >\n      {children}\n    </button>\n  )\n)\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-example-nec8y)\n\nSeveral things to note:\n\n- [`component`](#component) is used instead of a regular `compose` (from Ramda, Recompose or Redux for example) because `component` accurately propagates the types throughout the entire chain\n- Because of the type propagation, it's convenient to write down all the functions in place in the composition chain. This way, the types will be inferred: otherwise the types will have to be specified manually.\n- [`startWithType`](#startWithType) is necessary because of a TypeScript shortcoming. It is used to make the type that will be received by the first function in the composition chain available. It shouldn't be necessary to do this with a specific function: ideally, the `component` function itself should be able to propagate the type variable of the generic down to the functions inside, but at the time of this writing (2019-06-26) TypeScript does not support this. If it would, the right way to start the composition chain would be:\n\n  ```ts\n  // Note: This is currently not possible\n  export const Button = component<TButtonProps>(\n    mapWithPropsMemo(({ isDisabled }) => ({\n    ...\n  ```\n\n> Note: you might notice that `refun` has functions that serve as the equivalent of most of the React Hooks, so it might seem odd that some, such as `useEffect`, are missing. The reason is simply that wrapping them in the composition chain of `refun` provides no benefit: `useEffect` in particular does not result in any prop being added or removed, and there is no implicit state to keep track of, as is the case with the `mapSafeTimeout` and similar functions.\n\n> It is not the goal of `refun` to be a replacement of direct usage of React Hooks, rather a way to use them as a clean and decoupled composition chain and with good TypeScript typings, features that are only relevant to certain Hooks.\n\n## API\n\n- [component](#component)\n- [mapContext](#mapContext)\n- [mapDebouncedHandlerTimeout](#mapDebouncedHandlerTimeout)\n- [mapDebouncedHandlerFactory](#mapDebouncedHandlerFactory)\n- [mapDefaultProps](#mapDefaultProps)\n- [mapFocused](#mapFocused)\n- [mapHandlers](#mapHandlers)\n- [mapHovered](#mapHovered)\n- [mapKeyboardFocused](#mapKeyboardFocused)\n- [mapPressed](#mapPressed)\n- [mapProps](#mapProps)\n- [mapReducer](#mapReducer)\n- [mapRefLayout](#mapRefLayout)\n- [mapRef](#mapRef)\n- [mapSafeRequestAnimationFrame](#mapSafeRequestAnimationFrame)\n- [mapSafeTimeout](#mapSafeTimeout)\n- [mapState](#mapState)\n- [mapThrottledHandlerTimeout](#mapThrottledHandlerTimeout)\n- [mapThrottledHandlerAnimationFrame](#mapThrottledHandlerAnimationFrame)\n- [mapThrottledHandlerFactory](#mapThrottledHandlerFactory)\n- [mapWithAsyncProps](#mapWithAsyncProps)\n- [mapWithProps](#mapWithProps)\n- [mapWithPropsMemo](#mapWithPropsMemo)\n- [onMount](#onMount)\n- [pureComponent](#pureComponent)\n- [startWithType](#startWithType)\n- [StoreContextFactory](#StoreContextFactory)\n\n## `component`\n\nThis function is an analog of `compose` and it performs simple function composition, with two caveats:\n\n- The value sent into the chain is presumed to be a React Function Component (`FC` type)\n- `component` will use the output type of one function in the chain as the input type of the next function in the chain, allowing the functions to modify the type along the way. It is not necessary to tell `component` what the output type at the end of the chain is going to be, since it will be inferred correctly from the functions passed into it.\n\n## `mapContext`\n\nThis function receives a React Context object as created by the `React.createContext` function. The assumption is that the `value` property inside the Context is an object: `mapContext` will spread that object into the props of the components.\n\nFor example:\n\n```ts\nimport React, { createContext } from 'react'\nimport { component, mapContext, startWithType } from 'refun'\n\ntype TThemeContext = {\n  darkMode: boolean,\n}\n\nconst ThemeContext = createContext<TThemeContext>({\n  darkMode: false\n})\n\ntype TMessage = {\n  label: string\n}\n\ncomponent(\n  startWithType<TMessage>(),\n  mapContext(ThemeContext)\n)(({ darkMode, label }) => (\n  <p style={{ color: darkMode ? 'white' : 'black' }}>\n    {label}\n  </p>\n))\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapcontext-rtjvk)\n\n## `mapDebouncedHandlerTimeout`\n\n> This function is affected by the [React Synthetic Events vs debouncing / throttling](#react-synthetic-events-vs-debouncing--throttling) issue.\n\nThis function allows you to defer the execution of a handler for a grace period (specified in milliseconds) and if the handler gets invoked again during that period, it cancels the current grace period and overrides it with the new call, restarting the time counter.\n\nWhy you ask? Imagine for example that there is a button in the UI in which a user might be tempted to repeatedly click to make sure an action happens, but it doing so they will repeatedly trigger an expensive operation that will freeze the application. To avoid this, you could debounce the `onClick` handler for some milliseconds and make sure only the last call will be acted upon.\n\nThe difference between debouncing and throttling (available in [`mapThrottledHandlerTimeout`](#mapThrottledHandlerTimeout)) is that successive calls to a debounced handler will restart the timeout each time, while throttled calls will be executed once the initially set timeout it reached, using the last arguments. Following the FRP convention, this is how debouncing could be represented:\n\n```\ndebouncing in 3 seconds\n\n          1s 2s 3s 4s 5s 6s 7s 8s 9s\nreceived  x--y--------z------------\nran       ---------y--------z------\n```\n\nNotice how the timeout initially set for `x` is simply cancelled and overridden with a new timeout of 3 seconds for `y`.\n\n```ts\nimport * as React from \"react\"\nimport { component, mapHandlers, mapDebouncedHandlerTimeout, startWithType } from \"refun\"\n\ntype TButton = {\n  onClick: () => void\n}\n\nexport default component(\n  startWithType<TButton>(),\n  mapHandlers({\n    onClick: () => () => console.log(\"the handler was now called\")\n  }),\n  mapDebouncedHandlerTimeout(\"onClick\", 1000)\n)(({ onClick }) => (\n  <div>\n    <p>\n      Even if you click the button many times in a row (with each click less\n      than a second after the other), you will only see one log message, at the\n      end\n    </p>\n    <button onClick={onClick}>Click me</button>\n  </div>\n))\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapdebouncedhandlertimeout-791kn)\n\n## `mapDebouncedHandlerFactory`\n\n> All the functions create with this one are affected by the [React Synthetic Events vs debouncing / throttling](#react-synthetic-events-vs-debouncing--throttling) issue.\n\nThis function is a constructor for debouncers. It is used under the hood to build the `mapDebouncedHandlerTimeout` function. If you have a function that creates a deferred effect and a function that will cancel that deferral, you can build your own debouncer.\n\nThis is how `mapDebouncedHandlerTimeout` is defined:\n\n```ts\nexport const mapDebouncedHandlerTimeout = mapDebouncedHandlerFactory(setTimeout, clearTimeout)\n```\n\n## `mapDefaultProps`\n\nThis function sets some default prop values based on the object that is passed into it. Alternative to using the static `defaultProps` component property. The advantage of using it is that the props passed in will be type checked.\n\n```ts\nimport * as React from 'react'\nimport { component, mapDefaultProps, startWithType } from 'refun'\n\ntype TMessage = {\n  label?: string\n}\n\nexport default component(\n  startWithType<TMessage>(),\n  mapDefaultProps({\n    label: 'Hello World!'\n  })\n)(({ label }) => (\n  <p>{label}</p>\n))\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapdefaultprops-gqjqz)\n\n## `mapFocused`\n\nThis function sets the `isFocused` prop to `true` when the `onFocus` handler is called and to `false` when `onBlur` is called.\n\n```ts\nimport * as React from 'react'\nimport { component, mapFocused, startWithType, TMapFocused } from 'refun'\n\ntype TButton = {\n  label: string\n} & TMapFocused\n\nexport default component(\n  startWithType<TButton>(),\n  mapFocused\n)(\n  ({ isFocused, label, onBlur, onFocus }) => (\n    <button\n      onBlur={onBlur}\n      onFocus={onFocus}\n      style={{\n        borderWidth: 2,\n        borderStyle: \"solid\",\n        borderColor: isFocused ? \"red\" : \"grey\",\n        outline: \"none\"\n      }}\n    >\n      {label}\n    </button>\n  )\n)\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapfocused-8gls5)\n\n## `mapHandlers`\n\nThis function allows you to build custom handlers that will be memoized so that they do not cause a diff in the shallow comparison, which would lead to a re render.\n\nSo instead of writing:\n\n```ts\n// This will cause the component to re render every time because the handler is unique in every execution\nconst Input = ({ onChange, value }) => {\n  const handleChange = ({ target: { value } }) => onChange(value)\n\n  return <input\n    onChange={handleChange}\n    value={value}\n  />\n}\n```\n\n…it allows you to do:\n\n```ts\nimport * as React from 'react'\nimport { component, mapHandlers, startWithType } from 'refun'\n\ntype TInput = {\n  onChange: (string) => void,\n  value: string,\n}\n\nexport default component(\n  startWithType<TInput>(),\n  mapHandlers({\n    onChange: ({ onChange }) => ({ target: { value } }) => onChange(value),\n  })\n)(\n  ({ onChange, value }) => (\n    <input\n      onChange={onChange}\n      value={value}\n    />\n  )\n)\n```\n\nThe first argument that each handler will receive is the current props, and the second is the arguments that had been sent to the handler. Notice that the second argument is curried.\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-maphandlers-8d823)\n\n## `mapHovered`\n\nThis function sets the `isHovered` prop to `true` when the `onPointerEnter` handler is called and to `false` when `onPointerLeave` is called.\n\nNote that `onPointerEnter` and `onPointerLeave` are synthetic event names meant to abstract from platform specific hover states. In web, they will be typically mapped:\n\n- `onPointerEnter` -> `onMouseEnter`\n- `onPointerLeave` -> `onMouseLeave`\n\n…and each platform will have their own corresponding mapping.\n\n```ts\nimport React from 'react'\nimport { component, mapHovered, startWithType, TMapHovered } from 'refun'\n\ntype TButton = {\n  label: string\n} & TMapHovered\n\nexport default component(\n  startWithType<TButton>(),\n  mapHovered\n)(\n  ({ isHovered, label, onPointerLeave, onPointerEnter }) => (\n    <button\n      onMouseLeave={onPointerLeave}\n      onMouseEnter={onPointerEnter}\n      style={{\n        borderWidth: 2,\n        borderStyle: \"solid\",\n        borderColor: isHovered ? \"red\" : \"grey\",\n        outline: \"none\"\n      }}\n    >\n      {label}\n    </button>\n  )\n)\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-maphovered-lfzqj)\n\n## `mapKeyboardFocused`\n\nThis function sets the `isKeyboardFocused` prop to `true` when the target gets focused (after `onFocus`) but only if the focus was acquired via the keyboard interaction, not a pointer event (so if there was no press event before the `onFocus`). The prop is set to `false` once `onBlur` happens.\n\nThe reason this is useful is that it allows focus states meant for keyboard navigation to be differentiated from regular focus states. When the user is navigating with the keyboard, for example pressing the Tab key, visual highlighting of the focused elements needs to be more prominent to guide the sight into where the active element is. Pointer events will trigger focus as well, but when the interaction was initiated with a pointer it's not necessary for the highlight to be as prominent, since the user is already focused in the pointer position. In order to distinguish these two states and make it possible to style them separately, you can use `mapFocused` for the general case and `mapKeyboaredFocused` for the specific keyboard navigation case.\n\nNote that `onPressIn` and `onPointerLeave` are synthetic event names meant to abstract from platform specific hover states. In web, they will be typically mapped:\n\n- `onPressIn` -> `onMouseDown`\n- `onPressOut` -> `onMouseUp`\n\n…and each platform will have their own corresponding mapping.\n\n```ts\nimport React from 'react'\nimport { component, mapKeyboardFocused, startWithType, TMapKeyboardFocused } from 'refun'\n\ntype TButton = {\n  label: string\n} & TMapKeyboardFocused\n\nexport default component(\n  startWithType<TButton>(),\n  mapKeyboardFocused\n)(\n  ({ isKeyboardFocused, label, onBlur, onFocus, onPressIn, onPressOut }) => (\n    <button\n      onBlur={onBlur}\n      onFocus={onFocus}\n      onMouseDown={onPressIn}\n      onMouseUp={onPressOut}\n      style={{\n        borderWidth: 2,\n        borderStyle: \"solid\",\n        borderColor: isKeyboardFocused ? \"red\" : \"grey\",\n        outline: \"none\"\n      }}\n    >\n      {label}\n    </button>\n  )\n)\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapkeyboardfocused-okqxt)\n\n## `mapPressed`\n\nThis function sets the `isPressed` prop to `true` when the `onPressIn` handler is called and to `false` when `onPressOut` is called.\n\nNote that `onPressIn` and `onPressOut` are synthetic event names meant to abstract from platform specific pressed states. In web, they will be typically mapped:\n\n- `onPressIn` -> `onMouseDown`\n- `onPressOut` -> `onMouseUp`\n\n…and each platform will have their own corresponding mapping.\n\n```ts\nimport React from 'react'\nimport { component, mapPressed, startWithType, TMapPressed } from 'refun'\n\ntype TButton = {\n  label: string\n} & TMapPressed\n\nexport default component(\n  startWithType<TButton>(),\n  mapPressed\n)(\n  ({ isPressed, label, onPressIn, onPressOut }) => (\n    <button\n      onMouseDown={onPressIn}\n      onMouseUp={onPressOut}\n      style={{\n        borderWidth: 2,\n        borderStyle: \"solid\",\n        borderColor: isPressed ? \"red\" : \"grey\",\n        outline: \"none\"\n      }}\n    >\n      {label}\n    </button>\n  )\n)\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mappressed-z8lbx)\n\n## `mapProps`\n\nThis function takes a handler that receives all props and returns new props.\n\n```ts\nimport React from 'react'\nimport { component, mapProps, startWithType } from 'refun'\n\ntype TButton = {\n  label: string\n}\n\nexport default component(\n  startWithType<TButton>(),\n  mapProps(({ label }) => ({ children: label }))\n)(\n  ({ children }) => <button>{children}</button>\n)\n```\n\nNote that `label` is no longer available as a prop to the component. If you want to expand the props with extra ones instead of replacing them consider using [`mapWithProps`](#mapWithProps)\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapprops-37ho6)\n\n## `mapReducer`\n\nThis function takes a reducer and an initial state factory, and passes down the `state` (spreaded as props) and the `dispatch` function. It employs the `useReducer` hook under the hood.\n\n```ts\nimport React from 'react'\nimport { component, mapReducer, startWithType } from 'refun'\n\ntype TCounter = {\n  initialCounter: number\n}\n\ntype TState = {\n  counter: number\n}\n\ntype TAction = {\n  type: \"ADD\"\n}\n\nconst Counter = component(\n  startWithType<TCounter>(),\n  mapReducer(\n    (state: TState, action: TAction): TState => {\n      switch (action.type) {\n        case \"ADD\":\n          return {\n            counter: state.counter + 1\n          }\n\n        default:\n          return state\n      }\n    },\n    ({ initialCounter }) => ({\n      counter: initialCounter\n    })\n  )\n)(({ counter, dispatch }) => (\n  <div>\n    <button onClick={() => dispatch({ type: \"ADD\" })}>Add</button>\n    <span>{counter}</span>\n  </div>\n))\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapreducer-wqgv6)\n\n## `mapRefLayout`\n\nThis function allows you to capture the `ref` to a DOM element, and synchronously perform an update of the props based on some values of the element. It relies on `useLayoutEffect` under the hoods to synchronously capturing the `ref` and then updates the state, which will cause React to cancel the previous render and use the updated one instead.\n\nThis is particularly useful in order to measure a component’s size and update the rendering without causing any flickering.\n\n`mapRefLayout` receives three arguments:\n\n1. The name of the prop that will hold the `ref`\n2. A handler that receives the `ref` and the props as arguments, and returns a set of props to be added to the incoming props.\n3. A list of names of incoming props to be monitored. If one of those props changes, the handler should be executed again. Otherwise it will be skipped. See [`mapWithPropsMemo`](#mapWithPropsMemo) for a similar API.\n\n```ts\nimport * as React from \"react\"\nimport { component, mapRefLayout, startWithType } from \"refun\"\n\ntype TLayout = {\n  direction: \"horizontal\" | \"vertical\"\n}\n\nconst Button = component(\n  startWithType<TLayout>(),\n  mapRefLayout(\n    \"buttonElementRef\",\n    (buttonElementRef, { direction }): { size: number } => {\n      if (buttonElementRef) {\n        switch (direction) {\n          case \"horizontal\":\n            return {\n              size: buttonElementRef.getBoundingClientRect().width\n            }\n          case \"vertical\":\n            return {\n              size: buttonElementRef.getBoundingClientRect().height\n            }\n        }\n      }\n\n      return {\n        size: 10\n      }\n    },\n    [\"direction\"]\n  )\n)(({ buttonElementRef, size }) => <button ref={buttonElementRef}>{size}</button>)\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapreflayout-ve3zn)\n\n## `mapRef`\n\nThis function provides a way of making a mutable reference available as a prop. It uses the `useRef` hook under the hood.\n\nRefs are useful to store derived values that do not support shallow comparison, such as functions, or DOM elements.\n\nFor example you can use it to capture the `ref` to a DOM element and inspect it:\n\n```ts\nimport React from 'react'\nimport { component, mapRef, onMount, startWithType } from 'refun'\n\ntype TButton = {\n  label: string\n}\n\nexport default component(\n  startWithType<TButton>(),\n  mapRef('buttonElementRef', null),\n  onMount(({ buttonElementRef }) => {\n    if (buttonElementRef.current !== null) {\n      console.log(buttonElementRef)\n    }\n  })\n)(\n  ({ buttonElementRef, label }) => (\n    <button ref={buttonElementRef}>\n      {label}\n    </button>\n  )\n)\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapref-t3wog)\n\n## `mapSafeRequestAnimationFrame`\n\nThis function allows you to set up operations to be executed in the next animation frame that should only be executed while the component is still mounted, and should be canceled if the component is removed from the tree. Callbacks that are not canceled when unmounted are a common cause of React memory leaks.\n\nWhy you ask? Animations. Animations can be done in React by continuously updating style parameters of a component, and the cleanest way of updating those is with `requestAnimationFrame`. This function allows you to use `requestAnimationFrame` without worrying about memory leaks.\n\n\n> As you can check in this [📺 live demo of the issue](https://codesandbox.io/s/refun-mapsafeanimationframe-problem-demonstration-4t0w1), simply using `requestAnimationFrame` will cause the problems when pressing the \"Stop loading\" button. In particular, React will log:\n> ```\n> Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.\n> ```\n> `mapSafeRequestAnimationFrame` does the cleanup for you.\n\n```ts\nimport * as React from \"react\"\nimport {\n  component,\n  mapState,\n  mapSafeRequestAnimationFrame,\n  startWithType,\n  mapHandlers\n} from \"refun\"\n\ntype TLoader = {\n  initialPosition: number\n}\n\nconst Loader = component(\n  startWithType<TLoader>(),\n  mapState(\n    \"position\",\n    \"setPosition\",\n    ({ initialPosition }) => initialPosition,\n    []\n  ),\n  mapSafeRequestAnimationFrame(\"setAnimationFrameCallback\")\n)(({ position, setPosition, setAnimationFrameCallback }) => {\n  setAnimationFrameCallback(() => {\n    setPosition((position + 1) % 80)\n  })\n  return (\n    <div\n      style={{\n        width: 100,\n        height: 8,\n        border: \"1px solid black\"\n      }}\n    >\n      <div\n        style={{\n          width: 20,\n          marginLeft: position,\n          height: 8,\n          backgroundColor: \"black\"\n        }}\n      />\n    </div>\n  )\n})\n\ntype TApp = {\n  loading: boolean\n}\n\nexport default component(\n  startWithType<TApp>(),\n  mapState(\n    \"loading\",\n    \"setLoading\",\n    ({ loading }) => loading !== undefined ? loading : true,\n    []\n  ),\n  mapHandlers({\n    onStop: ({ setLoading }) => () => setLoading(false)\n  })\n)(({ loading, onStop }) => (\n  <div>\n    {loading && <Loader initialPosition={0} />}\n    <button onClick={onStop}>Stop loading</button>\n  </div>\n))\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapsafeanimationframe-s3ttu)\n\n## `mapSafeTimeout`\n\nThis function allows you to configure time outs that should only be executed while the component is still mounted, and should be canceled if the component is removed from the tree. Timeouts that are not canceled when unmounted are a common cause of React memory leaks.\n\n> As you can check in this [📺 live demo of the issue](https://codesandbox.io/s/refun-mapsafetimeout-problem-demonstration-dkiwq), simply using `setTimeout` will cause the problems when pressing the \"Close immediately\" button before the countdown is completed. In particular, React will log:\n> ```\n> Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.\n> ```\n> `mapSafeTimeout` does the cleanup for you.\n\n```ts\nimport * as React from \"react\"\nimport {\n  component,\n  mapHandlers,\n  mapState,\n  mapSafeTimeout,\n  startWithType\n} from \"refun\"\n\ntype TMessage = {\n  onClose: () => void\n}\n\nconst Message = component(\n  startWithType<TMessage>(),\n  mapState(\"autoClose\", \"setAutoClose\", () => false, []),\n  mapState(\"secondsRemaining\", \"setSecondsRemaining\", () => 5, []),\n  mapSafeTimeout(\"setLocalTimeout\")\n)(\n  ({\n    onClose,\n    secondsRemaining,\n    setSecondsRemaining,\n    setLocalTimeout,\n    autoClose,\n    setAutoClose\n  }) => (\n    <div\n      style={{\n        backgroundColor: \"#f0f0f0\",\n        padding: 20\n      }}\n    >\n      {autoClose ? (\n        <React.Fragment>\n          <p>This message will close in {secondsRemaining} seconds</p>\n          <button onClick={onClose}>Close immediately</button>\n        </React.Fragment>\n      ) : (\n        <React.Fragment>\n          <p>\n            This message that will close {secondsRemaining} seconds after you\n            press OK\n          </p>\n\n          <button\n            onClick={() => {\n              setAutoClose(true)\n              setLocalTimeout(() => {\n                console.log(\"timeout 1000\")\n                setSecondsRemaining(4)\n              }, 1000)\n              setLocalTimeout(() => {\n                console.log(\"timeout 2000\")\n                setSecondsRemaining(3)\n              }, 2000)\n              setLocalTimeout(() => {\n                console.log(\"timeout 3000\")\n                setSecondsRemaining(2)\n              }, 3000)\n              setLocalTimeout(() => {\n                console.log(\"timeout 4000\")\n                setSecondsRemaining(1)\n              }, 4000)\n              setLocalTimeout(() => {\n                console.log(\"timeout 5000\")\n                onClose()\n              }, 5000)\n            }}\n          >\n            Ok\n          </button>\n        </React.Fragment>\n      )}\n    </div>\n  )\n)\n\ntype TApp = {\n  show?: boolean\n}\n\nexport default component(\n  startWithType<TApp>(),\n  mapState(\"show\", \"setShow\", ({ show }) => true, []),\n  mapHandlers({\n    onClose: ({ setShow }) => () => setShow(false),\n    onShow: ({ setShow }) => () => setShow(true)\n  })\n)(({ show, onClose, onShow }) => (\n  <div>\n    {show ? (\n      <Message onClose={onClose} />\n    ) : (\n      <button onClick={onShow}>Show message again</button>\n    )}\n  </div>\n))\n```\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapsafetimeout-7mqmh]\n\n## `mapState`\n\nThis function allows you to set up a stateful prop and a function for updating that prop. It also supports setting the initial value, derived from the props passed into it, and a list of props to watch to reset that value whenever the external prop changes.\n\nNote in the example how the `OverridableInternalCounter` sets the `[\"counter\"]` as the last argument of `mapState`. This will cause `mapState` to watch for incoming changes to the `counter` prop and use them to update the `internalCounter` prop, accordingly to the function in the third argument `({ counter }) => counter`. In the case of `InternalCounter`, the array in the last argument is empty (`[]`) and then `mapState` does not watch for changes, which causes the external prop `counter` value to be ignored once updated, effectively working as an initial value only for `internalCounter`.\n\n```ts\nimport * as React from \"react\"\nimport { component, mapState, startWithType } from \"refun\"\n\ntype TCounter = {\n  counter: number\n}\n\nconst InternalCounter = component(\n  startWithType<TCounter>(),\n  mapState(\"internalCounter\", \"setCounter\", ({ counter }) => counter, [])\n)(({ internalCounter, setCounter }) => (\n  <div>\n    <button onClick={() => setCounter(internalCounter + 1)}>\n      Add to internal counter\n    </button>\n    <p>{internalCounter}</p>\n  </div>\n));\n\nconst OverridableInternalCounter = component(\n  startWithType<TCounter>(),\n  mapState(\"internalCounter\", \"setCounter\", ({ counter }) => counter, [\n    \"counter\"\n  ])\n)(({ internalCounter, setCounter }) => (\n  <div>\n    <button onClick={() => setCounter(internalCounter + 1)}>\n      Add to overridable internal counter\n    </button>\n    <p>{internalCounter}</p>\n  </div>\n));\n\nexport default component(\n  startWithType<TCounter>(),\n  mapState(\"externalCounter\", \"setExternalCounter\", ({ counter }) => counter, [\n    \"counter\"\n  ])\n)(({ externalCounter, setExternalCounter }) => (\n  <div>\n    <button onClick={() => setExternalCounter(externalCounter + 1)}>\n      Add to external counter\n    </button>\n    <p>{externalCounter}</p>\n    <OverridableInternalCounter counter={externalCounter} />\n    <InternalCounter counter={externalCounter} />\n  </div>\n))\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapstate-zy1rj)\n\n## `mapThrottledHandlerTimeout`\n\n> This function is affected by the [React Synthetic Events vs debouncing / throttling](#react-synthetic-events-vs-debouncing--throttling) issue.\n\nThis function allows you to defer the execution of a handler for a grace period (specified in milliseconds) and if the handler gets invoked again during that period, it overrides the call with the new invocation, so that when the specified timeout is reached, the last call will be the one executed.\n\nWhy you ask? Imagine for example that you have an application that monitors the window size and updates the layout depending on the new size. Window size updates happen very often while the user is performing the resize, and the new layout calculation might be fairly expensive, so the application might become unresponsive. In this case, you could use `mapThrottledHandlerTimeout` to make sure the resize update only happens every 500 milliseconds, which will not be too noticeable to the user, but will avoid a lot of unnecessary work. Because `mapThrottledHandlerTimeout` executes the _last_ invocation of the handler, the value that will be captured is the most recent one, which is important since we want to re layout according to the current size, no the one when the resize action started.\n\nThe difference between debouncing and throttling (available in [`mapDebouncedHandlerTimeout`](#mapDebouncedHandlerTimeout)) is that successive calls to a debounced handler will restart the timeout each time, while throttled calls will be executed once the initially set timeout it reached, using the last arguments. Following the FRP convention, this is how debouncing could be represented:\n\n```\nthrottling in 3 seconds\n\n          1s 2s 3s 4s 5s 6s 7s 8s 9s\nreceived  x--y--------x------------\nran       ------y-----------x------\n```\n\nNotice how the timeout initially configured for `x` is respected and the execution happens 3 seconds after the event for `x` is received, but `y` is run instead.\n\n```ts\nimport * as React from \"react\"\nimport {\n  component,\n  mapThrottledHandlerTimeout,\n  startWithType,\n  mapHandlers\n} from \"refun\"\n\ntype TSlider = {\n  onChange: (string) => void\n}\n\nexport default component(\n  mapHandlers({\n    onChange: () => (value) =>\n      console.log(`the handler has now been invoked with value: ${value}`)\n  }),\n  startWithType<TSlider>(),\n  mapThrottledHandlerTimeout(\"onChange\", 300),\n  mapHandlers({\n    onChange: ({ onChange }) => ({ target: { value } }) => onChange(value)\n  })\n)(({ onChange }) => <input type=\"range\" onChange={onChange} max=\"1000\" />)\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapthrottledhandlertimeout-1ss16)\n\n## `mapThrottledHandlerAnimationFrame`\n\n> This function is affected by the [React Synthetic Events vs debouncing / throttling](#react-synthetic-events-vs-debouncing--throttling) issue.\n\nThis function allows you to defer the execution of a handler until the next animation frame. If the handler gets invoked again before that animation frame hits, the new invocation will override the previous one, so that when the animation frame starts the last call will be the one executed.\n\nWhy you ask? Pretty much the same reasons that are true for [`mapThrottledHandlerTimeout`](#mapThrottledHandlerTimeout). Calls that are done between animation frames are wasteful overhead, since the UI will not be updated until the animation frame anyway, so if you have a handler firing continuously, it's a good idea to skip the wasteful ones. This might happen for handlers monitoring scroll or wheel or finger motion actions.\n\n> You might wonder why there is not `mapDebouncedHandlerAnimationFrame` if there is a `mapDebouncedHandlerTimeout`. The reason is that the behavior of that function would be identical to this one, so it's skipped.\n\n```ts\nimport * as React from \"react\"\nimport {\n  component,\n  mapThrottledHandlerAnimationFrame,\n  startWithType,\n  mapHandlers\n} from \"refun\"\n\ntype TSlider = {\n  onChange: (string) => void\n}\n\nexport default component(\n  startWithType<TSlider>(),\n  mapHandlers({\n    onChange: () => (value) =>\n      console.log(`the handler has now been invoked with value: ${value}`)\n  }),\n  mapThrottledHandlerAnimationFrame(\"onChange\"),\n  mapHandlers({\n    onChange: ({ onChange }) => ({ target: { value } }) => onChange(value)\n  })\n)(({ onChange }) => <input type=\"range\" onChange={onChange} max=\"1000\" />)\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapthrottledhandleranimationframe-xk8uc)\n\n## `mapThrottledHandlerFactory`\n\n> All the functions created with this one is affected by the [React Synthetic Events vs debouncing / throttling](#react-synthetic-events-vs-debouncing--throttling) issue.\n\nThis function is a constructor for throttlers. It is used under the hood to build the `mapThrottledHandlerTimeout` and `mapThrottledHandlerAnimationFrame` functions. If you have a function that creates a deferred effect and a function that will cancel that deferral, you can build your own throttler.\n\nThis is how `mapThrottledHandlerTimeout` is defined:\n\n```ts\nexport const mapThrottledHandlerTimeout = mapThrottledHandlerFactory(setTimeout, clearTimeout)\n```\n\n## `mapWithAsyncProps`\n\nThis function is exactly like [`mapWithPropsMemo`](#mapWithPropsMemo), except that the mapper function is expected to return a Promise that will resolve with the props to add.\n\n```ts\nimport * as React from \"react\";\nimport { render } from \"react-dom\";\nimport { component, mapWithAsyncProps, startWithType } from \"refun\";\nimport axios from \"axios\";\n\ntype TPokemon = {\n  id: string;\n};\n\nconst Pokemon = component(\n  startWithType<TPokemon>(),\n  mapWithAsyncProps(\n    async ({ id }) => {\n      try {\n        const response = await axios.get(\n          `https://pokeapi.co/api/v2/pokemon/${id}`\n        );\n\n        return {\n          height: response.data.height,\n          weight: response.data.weight\n        };\n      } catch {\n        return {\n          height: undefined,\n          weight: undefined\n        };\n      }\n    },\n    [\"id\"]\n  )\n)(({ id, height, weight }) => (\n  <p>\n    {id} is {height} height and weights {weight}\n  </p>\n));\n\nexport default () => <Pokemon id=\"pikachu\" />\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapwithasyncprops-ty9l6)\n\n## `mapWithProps`\n\nThis function allows you to expand the props passed in to a component with more props derived from them. It is typically used to precalculate values that are to be used in the component, to minimize the amount of logic needed to do in the render.\n\nIf the returned props have the same name as incoming props, they will override the incoming props.\n\n```ts\nimport React from 'react'\nimport {\n  component,\n  mapFocused,\n  mapWithProps,\n  startWithType,\n  TMapFocused\n} from \"refun\"\n\ntype TButton = {\n  label: string\n} & TMapFocused\n\nexport default component(\n  startWithType<TButton>(),\n  mapFocused,\n  mapWithProps(({ isFocused }) => ({\n    borderColor: isFocused ? \"red\" : \"grey\"\n  }))\n)(({ borderColor, label, onBlur, onFocus }) => (\n  <button\n    onBlur={onBlur}\n    onFocus={onFocus}\n    style={{\n      borderWidth: 2,\n      borderStyle: \"solid\",\n      borderColor,\n      outline: \"none\"\n    }}\n  >\n    {label}\n  </button>\n))\n```\n\nNote that this function just adds props to the component. If you want to replace all of them, you can use [`mapProps`](#mapProps) instead.\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapwithprops-cjdsc)\n\n## `mapWithPropsMemo`\n\nThis function does the same as [`mapWithProps`](#mapWithProps) and it memoizes the result for the props specified in the second parameter.\n\nAn example use case in which this can prove useful is if you were to be calculating the Fibonacci number of an input, which is known to be expensive for large numbers:\n\n```ts\nimport React from 'react'\nimport { component, mapWithPropsMemo, startWithType } from 'refun'\n\nconst inefficientFibonacci = position =>\n  position < 2\n    ? position\n    : inefficientFibonacci(position - 1) + inefficientFibonacci(position - 2)\n\ntype TFibonacci = {\n  position: number\n}\n\nexport default component(\n  startWithType<TFibonacci>(),\n  mapWithPropsMemo(\n    ({ position }) => ({\n      fibonacci: inefficientFibonacci(position)\n    }),\n    [\"position\"]\n  )\n)(({ position, fibonacci }) => (\n  <p>\n    The Fibonacci numbers in position {position} is <mark>{fibonacci}</mark>\n  </p>\n))\n```\n\nNotice that `mapWithPropsMemo` takes two arguments, and that memoization happens for the props that are specified in the second argument, in this case `position`.\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapwithpropsmemo-hjcso)\n\n## `onMount`\n\nThis function calls the passed in callback when the component is first mounted, sending the current Props as argument.\n\nFor example:\n\n```ts\nimport React from 'react'\nimport { component, onMount, startWithType } from 'refun'\n\ntype TButton = {\n  label: string,\n}\n\nexport default component(\n  startWithType<TButton>(),\n  onMount(({ label }) => console.log('Mounted with label', label))\n)(({ label }) => (\n  <button>\n    {label}\n  </button>\n))\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-onmount-5r5ol)\n\n## `pureComponent`\n\nThis function is identical to [`component`](#component) except that it memoizes the React element that results from rendering with a certain set of props. The props that are memoized are the _inner_ props, that is, the props that the component will get as the result of the entire composition chain. These are different from the _outer_ props, that are the ones that consumers pass manually into the component.\n\nThe purpose of this component is to prevent a re render from happening when the React tree is known to be the same. It is particularly useful when the React tree is a complex one, since the cost grows fast with the amount of nodes in the tree. Since the memoization is done in the inside of the component, all `map` functions will be run, making it ideal for components that control their own state.\n\n> Note that this function is meant to be used to avoid pointless re renders of complex trees, which is a concern that should be treated at the high level, in an app for example, rather than in small presentational components. Memoization comes with a cost, and React is already providing optimizations via reconciliation, so the type of optimizations that `pureComponent` does, similar to the old `shouldComponentUpdate`, is to be reserved for cases where there is a clear need for optimization.\n\n```ts\nimport React from 'react'\nimport { mapReducer, pureComponent, startWithType } from 'refun'\nimport AComplexHeader from './AComplexHeader'\nimport AnExpensiveToComputeSidebar from './AnExpensiveToComputeSidebar'\n\ntype TCounter = {\n  initialCount: number,\n}\n\nexport default pureComponent(\n  startWithType<TCounter>(),\n  mapReducer(\n    (state, action) => {\n      switch (action.type) {\n        case 'ADD':\n          return {\n            counter: state.counter + 1\n          }\n\n        default:\n          return state\n      }\n    },\n    ({ initialCounter }) => ({\n      counter: initialCounter\n    })\n  )\n)(({ counter, dispatch }) = (\n  <main>\n    <AComplexHeader />\n    <AnExpensiveToComputeSidebar />\n    <button>\n      Add\n    </button>\n\n    <p>{counter}</p>\n  </main>\n))\n```\n\nSo to be clear, the component that receives `counter` and `dispatch` as props is the one that is going to be memoized. If your intention is to memoize an expensive computation in a function in the composition chain, such as calculating a value in the `mapWithProps`, take a look at [`mapWithPropsMemo`](#mapWithPropsMemo) instead.\n\n`pureComponent` should only be used in components that receive no `children` and no complex props, since otherwise the overhead of memoization is not worth it. If the component receives `children` or complex props (objects / arrays), `pureComponent` will not provide any benefit, since those are very likely (or guaranteed in the case of `children`) to be different on every render. `pureComponent` works by doing a shallow comparison of the current props with the previous props. Shallow comparison means that each prop is compared with hard equality with the previous value of that same props.\n\n## `startWithType`\n\nThis function is simply a way of setting up the initial type in the [`component`](#component) composition chain, since TypeScript does not currently support doing that in the composition function itself (`component` in this case, but would be `compose` in Redux, Ramda, etc).\n\nIt's purpose is entirely for types, and in runtime it's a no-op.\n\n```ts\nimport React from 'react'\nimport { component, startWithType } from 'refun'\n\ntype TButton = {\n  label: string,\n}\n\nexport default component(\n  startWithType<TButton>(),\n)(({ label }) = (\n  <button>\n    {label}\n  </button>\n))\n```\n\nOnce this is fixed in TypeScript this function will be redundant and it will be possible to pass the generic directly into `component`:\n\n```ts\nimport React from 'react'\nimport { component } from 'refun'\n\ntype TButton = {\n  label: string,\n}\n\n// Remember: this is currently *not* supported\nexport default component<TButton>(\n  (props) => props\n)(({ label }) = (\n  <button>\n    {label}\n  </button>\n))\n```\n\n…meanwhile `startWithType` is a straightforward workaround.\n\n## `StoreContextFactory`\n\nThis function is a way of working with Redux stores together with React Hooks. It is an alternative to React Redux, with these goals:\n\n1. Work with Hooks, avoiding higher-order components\n2. Respect the types all throughout\n3. Match the level of optimization of React Redux.\n\nThe way this function works is that it receives a Redux Store object, and returns a component and two functions:\n\n- `StoreProvider` is a component that provides the React Context already loaded with the store that was passed in to the `StoreContextFactory`\n- `mapStoreDispatch` is a function to be used as part of a `component` or `pureComponent` composition, which will simply add `dispatch` to the props, so that the component being wrapped by it can dispatch actions.\n- `mapStoreState` is a function to be used as part of a `component` or `pureComponent` composition, which will add props derived from the state. Much like `connect` from React Redux, it receives a `mapStateToProps` function that will be called with the full state and which return value will be spread over the component props. `mapStoreState` takes as a second argument an array of the names of the props to watch in order to run the `mapStateToProps` function: if none of the listed props have changed, the `mapStateToProps` will not be ran.\n\nCheck the example below for a full use case.\n\n```ts\nimport * as React from \"react\"\nimport { createStore } from \"redux\"\nimport { component, pureComponent, StoreContextFactory, mapHandlers } from \"refun\"\n\ntype TState = {\n  counter: number\n}\n\ntype TAction = { type: \"INCREMENT\" payload: number } | { type: \"RESET\" }\n\nconst reducer = (state: TState, action: TAction): TState => {\n  switch (action.type) {\n    case \"INCREMENT\":\n      return {\n        ...state,\n        counter: state.counter + action.payload\n      }\n\n    case \"RESET\":\n      return {\n        ...state,\n        counter: 0\n      }\n\n    default:\n      return state\n  }\n}\n\nconst initialState = {\n  counter: 7\n}\n\nconst store = createStore(reducer, initialState)\n\nconst { StoreProvider, mapStoreState, mapStoreDispatch } = StoreContextFactory(\n  store\n)\n\nconst CounterDisplay = pureComponent(\n  mapStoreState(\n    ({ counter }) => ({\n      counter\n    }),\n    [\"counter\"]\n  )\n)(({ counter }) => (\n  <div>\n    <p>Counter: {counter}</p>\n  </div>\n))\n\nconst ResetButton = component(\n  mapStoreDispatch,\n  mapHandlers({\n    onClick: ({ dispatch }) => () =>\n      dispatch({\n        type: \"RESET\"\n      })\n  })\n)(({ onClick }) => (\n  <div>\n    <button onClick={onClick}>Reset</button>\n  </div>\n))\n\nconst IncrementButton = component(\n  mapStoreDispatch,\n  mapHandlers({\n    onClick: ({ dispatch }) => () =>\n      dispatch({\n        type: \"INCREMENT\",\n        payload: 1\n      })\n  })\n)(({ onClick }) => (\n  <div>\n    <button onClick={onClick}>Increment</button>\n  </div>\n))\n\nexport default () => (\n  <StoreProvider>\n    <div>\n      <CounterDisplay />\n      <ResetButton />\n      <IncrementButton />\n    </div>\n  </StoreProvider>\n)\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-storecontextfactory-l9bp5)\n\n## Caveats\n\n### React Synthetic Events vs debouncing / throttling\n\nThe `mapDebounced*` and `mapThrottled*` family of functions do not accept React Synthetic Events. As you can see in the examples below, some specific properties of the event (`value` in that case) need to be extracted from the original Synthetic Event in order for them to work.\n\nThis is necessary because these two function families store the arguments passed to the handlers for delayed use. If that argument is a Synthetic Event, it will be stored to be reused, but React forbids this, because for performance reasons React reuses the references of Synthetic Events and mutates them.\n\n> If you try the example below without the `mapHandlers`, you will get:\n>\n> ```\n> Warning: This synthetic event is reused for performance reasons. If you're seeing this, you're accessing the property `target` on a released/nullified synthetic event. This is set to null. If you must keep the original synthetic event around, use event.persist(). See https://fb.me/react-event-pooling for more information.\n> ```\n>\n> [📺 Check out live demo](https://codesandbox.io/s/refun-mapthrottledhandlertimeout-wrong-usage-7q6cd)\n\n\nIf you are going to use information coming from the Synthetic Event, consider extracting the information you care about using `mapHandlers`, which will then let React discard the rest of the Event object.\n\nIf you are not going to use _any_ information coming from the Event—such as in the example for [`mapDebouncedHandlerTimeout`](#mapDebouncedHandlerTimeout)—then you will not be affected by this issue.\n\n```ts\nimport * as React from \"react\"\nimport {\n  component,\n  mapThrottledHandlerTimeout,\n  startWithType,\n  mapHandlers\n} from \"refun\"\n\ntype TSlider = {\n  onChange: (string) => void\n}\n\nexport default component(\n  mapHandlers({\n    onChange: () => (value) =>\n      console.log(`the handler has now been invoked with value: ${value}`)\n  }),\n  startWithType<TSlider>(),\n  mapThrottledHandlerTimeout(\"onChange\", 300),\n  mapHandlers({\n    onChange: ({ onChange }) => ({ target: { value } }) => onChange(value)\n  })\n)(({ onChange }) => <input type=\"range\" onChange={onChange} max=\"1000\" />)\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapthrottledhandlertimeout-1ss16)\n","readmeFilename":"readme.md","bugs":{"url":"https://github.com/bubble-dev/_/issues"},"homepage":"https://github.com/bubble-dev/_#readme","_id":"refun@0.5.0-beta.1","_nodeVersion":"13.5.0","_npmVersion":"6.13.4","dist":{"integrity":"sha512-j40TQdirZR8FlEt0QNZJxf2flu7UnXa/DUeJn+pEtAI/6MtCGv+KY64+yiB4jZMujrkSjNdhZBijE3hkxe3xZA==","shasum":"429dad412810e77d5ee7e31a478a184d3f772891","tarball":"https://registry.npmjs.org/refun/-/refun-0.5.0-beta.1.tgz","fileCount":275,"unpackedSize":464682,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeAPF0CRA9TVsSAnZWagAAe1IQAINZpL5P/ScP8Ke9PhNs\nUEllY7JF7JlP/QV+suQ4mFnUmNqzUApSPMHcK94BswnfCywmZyo7WlPM0Ldb\nqf8/+AqWgFJ3YM9NK8HY+Q7cX2JE3KmncvJpkAe9Fypd7vgE7ERV91HNSrth\nAL5qvXz7iPuywuAr41knmnRh/C/KDBACLoS4Kook+D45PNnu6xCAK1BV21hR\ngtmppQqsZkCIb+wBjIYLZpA9k2usGUJSG8eQjp00Mm+/8hsb9LJtE+/AY3MK\noNe9yc9HOij98Wt/r6whyRsSzsWe0//VkXVHe0YhkHmn3sGQ7HKTZRSWuSZs\nrkDgavcprATUshryS3oN/CGyIZ5vuYMDnxoqCXMT3Snsgs0qfr7Ae0aiE57P\n117Y4IpnuwxIVAyAMHvO51MRaLw0obK3Sp3T0xsjcIONyBkQ5IK1CD8fNHVe\n7SJTr1C+fiomSiDJUOo16Vf/mtQgVvY1hZjG4faGDKz4GqEuopyAJLKtFyKe\nLUtFQx/pnaJKZDf+D/1HeojpstxcrL2Zem23TyRRmwMARrVBJhf+M6EdJoRf\npIr2FFg0uQoadOiXUUMlR1Q100vNQsppkrNHCgnIV59aKVn8rkYMLE0de5LL\ntlAgmqV/4DF4jumAu3zOusCpxcZG7ZgnyoL0fIwlQ6pqqIOnB7zUL2bJTsfk\nQ70O\r\n=RL0W\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDYvGeZXYFMBTjc3SEDwb6w2XryAooOKEgNWi8b7M1cPwIgZ98tGrf2E/JCz8vLMAwwS6v3iB3/LS3kQJ6Q0iY75W0="}]},"maintainers":[{"email":"kir@belevi.ch","name":"deepsweet"},{"email":"irminakacz@gmail.com","name":"irminakacz"},{"email":"psxcode@gmail.com","name":"psxcode"},{"email":"fernando.via@gmail.com","name":"xaviervia"}],"_npmUser":{"name":"psxcode","email":"psxcode@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refun_0.5.0-beta.1_1577120116382_0.918717108717402"},"_hasShrinkwrap":false},"1.0.0":{"name":"refun","version":"1.0.0","description":"A collection of React Hook-enabled functions that compose harmoniously with each other. Similar to `recompose`, but:","keywords":[],"main":"node/index.js","browser":"web/index.js","react-native":"native/index.js","repository":{"type":"git","url":"git+https://github.com/bubble-dev/_.git"},"license":"MIT","engines":{"node":">=10.13.0"},"sideEffects":false,"dependencies":{"tsfn":"^1.0.0"},"bugs":{"url":"https://github.com/bubble-dev/_/issues"},"homepage":"https://github.com/bubble-dev/_#readme","_id":"refun@1.0.0","_nodeVersion":"12.14.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-/lgxdcuh51XuPL8Xl8JARLGowgCbLdKxZavdyv4x+/QV5zoEGhjIIS/xy3Rn8SlvEZbMlrn8MUn+t429894A2w==","shasum":"c56f22626b32e706e62d6c5ae38d5b15407f2513","tarball":"https://registry.npmjs.org/refun/-/refun-1.0.0.tgz","fileCount":275,"unpackedSize":464736,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeKW55CRA9TVsSAnZWagAASgcP/AtduniVdINxR/En6zA7\nT/1s6Imz8RcXilkEihjKI+JrGaX5CbA04YkiVfCKOHaT9xybu+tUr9aJ/Esy\ntWROKr9CySpmOdhye69jakNeO3UnO51VugSd8mnBTigM/7Rl45em+VZhqrfY\n6R23o4SB5cSgrnowh8+d08yXvDsSNEW6akv9PDLpQbYRLc8xUjH2JVEFt+id\nlMBo7HaEOIzwPniZaYNS38Q6eAxBD4ZFdvFKtvqfdyY3CsrsDNrLpuZvmsor\n1iScZ41XckxnebZ77NZHNO0xDs3Gw3qMFCBS0OASLFfKEStvZQUZhm/VPhQg\nU6hduOIAfQ3KIHrYv9VCYM9A/5kKQC9+AQ+TDwCMt5gGfB61CaOXIqfdZ9vS\nX3V5pp2Mi5CqPTntIZkLcHvy2sQgST5mBwbd+oNPm9gyhMZLQ62Fj24QlD3F\nBJ7kUpuGc88WOj5Ylai25jsa/ezFCOOmXsPaWEHS2TfV+NQWirDuyF9FIBQq\nOoNPnq/wSmvEhxyG+7P2bYKMWomoeYNxEnPb5TPBI4byblxIOPgQzmq/hPkG\nxXW7CWhqdncAqDXT1txLuUkfcfV2Bk8/2HXGiUfqkf3G4LQ2xZ6l4upiWlP9\nrrTqZ0y+v/1GdrCsxWemJhx2IVoKpUtElMO4/godqga6QbDdmcogxTEgVafN\nR6uP\r\n=//8G\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICTMzyMaz9dP+uVWD3lBCfmK5/WGcTtPyBmLRsFlQrueAiAzW4zlXkoZEKSOVVnEbQR4UZRwiiTGdXvQ7sRZrKBkOQ=="}]},"maintainers":[{"email":"kir@belevi.ch","name":"deepsweet"},{"email":"andypevek@gmail.com","name":"fosimus"},{"email":"irminakacz@gmail.com","name":"irminakacz"},{"email":"psxcode@gmail.com","name":"psxcode"},{"email":"fernando.via@gmail.com","name":"xaviervia"}],"_npmUser":{"name":"deepsweet","email":"kir@belevi.ch"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refun_1.0.0_1579773560458_0.8520938464845702"},"_hasShrinkwrap":false},"1.0.1":{"name":"refun","version":"1.0.1","description":"A collection of React Hook-enabled functions that compose harmoniously with each other. Similar to `recompose`, but:","keywords":[],"types":"types/index.d.ts","main":"node/index.js","browser":"web/index.js","react-native":"native/index.js","repository":{"type":"git","url":"git+https://github.com/nextools/metarepo.git"},"license":"MIT","engines":{"node":">=10.13.0"},"sideEffects":false,"dependencies":{"tsfn":"^1.1.1"},"bugs":{"url":"https://github.com/nextools/metarepo/issues"},"homepage":"https://github.com/nextools/metarepo#readme","_id":"refun@1.0.1","_nodeVersion":"12.16.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-jGrtpVW3DtNt0klqA+FrcxOH574sT9xjWN3qLdGheiTQYOqMSAFBppJs5hsNKVpC9UyFpfHiQfWH+1GpHMNULQ==","shasum":"5e2c5d91bab4794e3cd68d68d67cbf3b9b8ade95","tarball":"https://registry.npmjs.org/refun/-/refun-1.0.1.tgz","fileCount":207,"unpackedSize":415111,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJelZ+oCRA9TVsSAnZWagAAi8cP/3i0qDjXqYDqsRImvfvJ\n/QPp+zJQybLbnZl7ZDnamndlHmD6dO1Wwihc3KCfHsgB+Wgpjnwv6UL88PZG\nlOotUpog1wxEjsqPhDDOcW3AFy/X/OjbdH658UgApsVVNY+CvWwYpc3lmOh0\nM0NGgPAaR4y9Yk+cgatFQ5Z2MCTar11LR6wzOnPxrAQESaVNfmarO1OXrCkL\nIibpy+Nxp3bEOafrenx48hb9Z60I6UhqpsNvjiyTPwNFXao6Co+Gb4nyEjS6\nx8Rc+QKhM+agji62MUiRKZC6BmCqne0xrq4LE1eyEiUmTV5RJ4Ja+Ingr1VV\nclWqyQwaxmfar9Xk1DOy5AYxT3TEMCPhh6YGORuvWNd4xVgwepU1DqHfaSJX\n1CemEdWWcb75SBbMeQsI7eVT1OvEzbQIPvGWrTd20d/wybheDYqM3OBb+BCJ\nT9Zpq+FMUF9bYUdnUm0YKi3uDYW9k+PpO7IWhRHOlIIpWGH/gupgDvH+IN1/\nI6dI03rrQrvzrKEIG71pUfQL2i30Kb+UkvqP++gUtS5T+ZY8vXNVkzbtcQxe\nqkOBAhq2NsLWQro1BWDotsdbz2ymRhSOBu7jRx0c+TRanQg/mtdOuqhDz+cT\nZcnTZcaBaXtjr7eewCSw0UPYAPBFJE9K7H4EGJzwvG/m2LF34HyysnpC385l\nhSi3\r\n=Si38\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCTMPyHTuXSvRn3YbWEFqVXFuapRVe4hUsjHgAcb0sRNwIgTRdSuUZq+ijnnDFzJjtLPp/DhnlekuPz27shlRGdAY8="}]},"maintainers":[{"email":"kir@belevi.ch","name":"deepsweet"},{"email":"andypevek@gmail.com","name":"fosimus"},{"email":"psxcode@gmail.com","name":"psxcode"}],"_npmUser":{"name":"deepsweet","email":"kir@belevi.ch"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refun_1.0.1_1586864040039_0.572075605094535"},"_hasShrinkwrap":false},"2.0.0":{"name":"refun","version":"2.0.0","description":"A collection of React Hook-enabled functions that compose harmoniously with each other. Similar to `recompose`, but:","keywords":[],"types":"types/index.d.ts","main":"node/index.js","browser":"web/index.js","react-native":"native/index.js","repository":{"type":"git","url":"git+https://github.com/nextools/metarepo.git"},"license":"MIT","engines":{"node":">=10.13.0"},"sideEffects":false,"dependencies":{"tsfn":"^1.1.1"},"bugs":{"url":"https://github.com/nextools/metarepo/issues"},"homepage":"https://github.com/nextools/metarepo#readme","_id":"refun@2.0.0","_nodeVersion":"12.16.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-6DbXd6In5gGYfhAi/3wFBg60frESB4E/iV7ruWMUuobCs3OmsezUsNFM+QooRlx3riS7cVC6T/WTMSLuQ1OmRQ==","shasum":"e2960d8a2b9f3432a7373aad0db41f43e06a0ffc","tarball":"https://registry.npmjs.org/refun/-/refun-2.0.0.tgz","fileCount":183,"unpackedSize":400841,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJemXwnCRA9TVsSAnZWagAA4wUQAKJfeXK4Cvr+4leo3Qd7\nhfMGCIJT9E5gOAHUu6xWd79ztUVxs+D/OY3FRLmnbATeHhhP/lfic0Ki0RUX\nR2+TITwdywWMV708UCXheCyYPum9eLueci+N3dU4JkiDPwi019CXvYUToypc\ns+UpTwXQoBheAEZUAeRmI2fNsAWyIC/yYrIuPJYqPOTD5Flg4pAiXuBh0sUg\nNPBBPa9DKmFcqmHYHbwVd6YffJZlD1L83kIX414BdYV+k0IQLhJ+Z890SnCZ\nHAIXt/7XgkACKSTKxAr9C8me0uZn4VkqmF0I5bLCQYi2NE3gw4Y00vrz56hx\npFZ6WlFngWcMKU85f7G0L1BcSMJSGpQAAh+ifVYjyaf/dKaLvCWsKtLGsUL8\nhimz3tVXu1pkHhNHntGYmhx3TxWMe5tMpbxupHZrMn1CQxP08IF0XboUFoHG\nJSOBCePA2LMaz2ACCO3sC+pMu52r6o+bSIe3XtjRCXSKU3KKhYzZyQddqyJD\ndD3gv5S5G3OJJMJq1FSrTETo65JtelcXDXJVjBYFWB7QoIlZdYlvSoAIFNHV\nNEvvR0PMqf1p6pgAEoNNYvuviwbbzrZHnq07m77AZNIDnVWHZb9IeZbexZUg\n37ArybMNnw2c3eV/CRlbhqAIrURUUbMs/dukS5eZKcPNFazOYNaFyrj4KqJC\nA2gM\r\n=KXdy\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIC73EXvUXBrpghTh0aeCU+MsgZtI3c2Zru7ym3x9qmShAiAQMntK88ZwMXaR53oyvzLsyIlMB2EuUVcT2SnRdcbpBw=="}]},"maintainers":[{"email":"kir@belevi.ch","name":"deepsweet"},{"email":"andypevek@gmail.com","name":"fosimus"},{"email":"psxcode@gmail.com","name":"psxcode"}],"_npmUser":{"name":"deepsweet","email":"kir@belevi.ch"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refun_2.0.0_1587117094746_0.47239300209802604"},"_hasShrinkwrap":false},"2.0.1":{"name":"refun","version":"2.0.1","description":"A collection of React Hook-enabled functions that compose harmoniously with each other. Similar to `recompose`, but:","keywords":[],"types":"types/index.d.ts","main":"node/index.js","browser":"web/index.js","react-native":"native/index.js","repository":{"type":"git","url":"git+https://github.com/nextools/metarepo.git"},"license":"MIT","engines":{"node":">=10.13.0"},"sideEffects":false,"dependencies":{"tsfn":"^1.1.2"},"bugs":{"url":"https://github.com/nextools/metarepo/issues"},"homepage":"https://github.com/nextools/metarepo#readme","_id":"refun@2.0.1","_nodeVersion":"12.16.0","_npmVersion":"6.13.4","_npmUser":{"name":"psxcode","email":"psxcode@gmail.com"},"dist":{"integrity":"sha512-xRB0ToXeuCwEkbQu0aaFCGDw6g4VyBLQcc0pHnzG4J0vtn4UegVXrTX/2En292YsLuvu2AR5cXWp4B6KMua9bw==","shasum":"ad6edcec0803858b49f66f375a471117bf4af928","tarball":"https://registry.npmjs.org/refun/-/refun-2.0.1.tgz","fileCount":183,"unpackedSize":404380,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe6hrACRA9TVsSAnZWagAAwaoP/1tbXzQiVrLmTT8AJB0A\njW6C9KJljfBP1vU4o2vCoUKq/58lPJRqxDn57+wkMF90zSUSPWG8uc8sBIFP\n1T8WOlvlytvd7VLasiU2/UvAHhJz8VlzG05+Y2H2ol/U5vq5zfZTO7RD++IV\nSRJd/W0wgfpJv5Eab+qQYyQyi8bSEKfU91LiRH5fj/Rr4mhFfypQwkjXPRvs\nbJGvu8VUMm7QqruVYSokvU/Nct3bja4CMdyWu0uB/4U5vKgxHz6pTSr0jtjo\nKhdOs/Ih6Sy0szTDEjwpeh0s7sqrjFTojgQ0fRzdcNxBsxquVeEY00wqEjfR\nzUL2yvGH/9gzMoERgwfAUaBmmm86JZbU2VvkUO1GBboM+nsu1jPSMGDKm00j\no308FtZ7kwyMX4rn91AI6kHNKJZueQy1Luqks2VuGj//uXm6k5vlNcVWhtEr\nQX24xp0IW1t3UN5912Caq2BgFJphLq9pZGH8Wlowq+nUIA79rzxKs3AM6Vjz\nNtryZqOZPEn9H8HEowr1/7pv12fM9YX5PBWFuL1g4y7tCiAo1DtHoB3+2rIy\nfYsH86aqY804XNvMMHQ+S9RY8gpgrcBYakQXnwDp38JJnr44bQitVqcdE5nU\nxNmwU/2NBOeqw5mm9l3SeiLbKgQ558yMyWwRihCfTJyuTw4yU/xcjminFI/w\nvjLh\r\n=Ek6T\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDDmG1qkofx52dzhFuuRVpgokDFOdMPOqGMWNcRIZHJegIgHgWa5qH3STiZEvUl2SPgaZPLWONuKhwIdGHgnatk6lI="}]},"maintainers":[{"email":"kir@belevi.ch","name":"deepsweet"},{"email":"andypevek@gmail.com","name":"fosimus"},{"email":"psxcode@gmail.com","name":"psxcode"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refun_2.0.1_1592400575741_0.28077277168292203"},"_hasShrinkwrap":false},"3.0.0":{"name":"refun","version":"3.0.0","description":"A collection of React Hook-enabled functions that compose harmoniously with each other. Similar to `recompose`, but:","keywords":[],"types":"types/index.d.ts","main":"node/index.js","browser":"web/index.js","react-native":"native/index.js","repository":{"type":"git","url":"git+https://github.com/nextools/metarepo.git"},"license":"MIT","engines":{"node":">=12.13.0"},"sideEffects":false,"dependencies":{"tsfn":"^2.0.0"},"bugs":{"url":"https://github.com/nextools/metarepo/issues"},"homepage":"https://github.com/nextools/metarepo#readme","_id":"refun@3.0.0","_nodeVersion":"14.8.0","_npmVersion":"6.14.7","dist":{"integrity":"sha512-OZXqsGfcvg9Ffw9ro3CbimXXDzlNDyWDLvTuLCG/gthUJQRHWH0qGxmrjO+h78i3mSG2RJyNYZ2sbH6/ltHV0A==","shasum":"1ec613a63368abf22de3f40b9727f89f167b7743","tarball":"https://registry.npmjs.org/refun/-/refun-3.0.0.tgz","fileCount":183,"unpackedSize":409035,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfNlfOCRA9TVsSAnZWagAAk9IP/RKFNIN421ZVw8vpkfSJ\nDMs3mDuZxj+4vOeUtWVkYrbdVw1y5FH8qdhcGn6dhMDUTLKFOnHdlLIsNOpE\nSeHqRYw7vbPGN8MSTvt2xV6TNXmX+MWHbiT5IcWbRgmChrl3g4CeE1bwKZ5Q\nDKEX9adBYkRGHup+tL+uNkcWHgz3w1mvRf1FGg7970IoeZY/hjgyrK69tHZg\nV558sGLS5V9stwwyZsNmszrAHMwpTLSMrty7sq2L3rGRYiUzoaS+a48ER+tL\nlOr1zE5T0O20NLfFgCNtDzvS40rshCvUeYNzEXOSbx8rUoMOYsLbhHA9S82t\n5ZSMN3rsU5KbgxDnnKBFHpPjLHgphkob/qh7LNErfydVxQ3TgclaPIewtanF\n+tNo8dqAiaqW9znOIwINiyTF+L4vDnRhwekCVvvy4BHQqvMtEHdpa7ol30cj\ncKVXDbElJY+3Q4se1RT6I2SN4gP6llbc2ipG4IUeRXvmUvxL9/MotHfQ+7XZ\n1D0qMzM7/62lWLHfogt1Dxi+MSwBbWtKoMer9nVN0DmXhx6o7Av0TNxigTTd\nsU0g/ZQ8D3bHzvn9xbanB3y59Qb3XfuMALWcDmWU6O4ghAsrGhHomwLdv1rT\nnT6mZj4SGBqkh4INiH3yVllAvGbfOGFi2ySGIR9SqZjtvzHBRaNytVjLfY6A\n8SXc\r\n=nTda\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFrHnsrtWO0hvbYWJx8YzVJxyDa5+LatLPSwt02rbL10AiEAlkArg3BGA9mAoVOUZvOuZCfg8rgP4dZZOL6sQDfLM/8="}]},"maintainers":[{"email":"kir@belevi.ch","name":"deepsweet"},{"email":"andypevek@gmail.com","name":"fosimus"},{"email":"psxcode@gmail.com","name":"psxcode"}],"_npmUser":{"name":"deepsweet","email":"kir@belevi.ch"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refun_3.0.0_1597396942009_0.7865215343566212"},"_hasShrinkwrap":false},"3.0.1":{"name":"refun","version":"3.0.1","description":"A collection of React Hook-enabled functions that compose harmoniously with each other. Similar to `recompose`, but:","keywords":[],"types":"types/index.d.ts","main":"node/index.js","browser":"web/index.js","react-native":"native/index.js","repository":{"type":"git","url":"git+https://github.com/nextools/metarepo.git"},"license":"MIT","engines":{"node":">=12.13.0"},"sideEffects":false,"dependencies":{"tsfn":"^2.0.0"},"bugs":{"url":"https://github.com/nextools/metarepo/issues"},"homepage":"https://github.com/nextools/metarepo#readme","_id":"refun@3.0.1","_nodeVersion":"14.8.0","_npmVersion":"6.14.8","dist":{"integrity":"sha512-uO01tEbf1w/iL5GGTdSNMwpEWlP5tCwMtaP7SHdLT6d0mrCVlNjPt5tGVr0HV3+U46m23S1eLSZhZcfWSOseRg==","shasum":"2da9cbfdac415ca676d07f594f10cf18398213ee","tarball":"https://registry.npmjs.org/refun/-/refun-3.0.1.tgz","fileCount":183,"unpackedSize":369086,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfTMcECRA9TVsSAnZWagAAaQ0P+wf6sub9DZNsaGU00ZCn\n7by5su6wBwCcuy4pnqtCzZFaikqoHen8zqamj6Zij8aJeNYhjrdZjNr9eaKL\n6stogvvy2WSivKTMLgEZ4p0WE4Wyq4D+6YL5q+A4QcUGMIFn34OEG7jQWw0A\nA0h6IPmPfnFtcWHPLN9x7FpvfFkkbdimNnRb0VLzszt7UAr5pwa3vl2mBQYJ\nF7xc1XrMGwLaNPDk/b9dxjhEzZwomKw3vzbzqCfmvYnrAgE3PJSjz43br88g\nAuyjX9AFllXieQwLMixMtCPVlHkq9vN6qR1W4shSsXHVFGAGe8j8fTxf7CD5\n8kVBMYOcD+G1ziA4LCfxdOp9+oToH13SrT8RikMu13n/pjHuPJ5PKCOzCK/H\nsIYmkWV7bUvQq/8FTdScDp+gUfx01cz/uKbuZ5yri3WdB1IbHxg/rM/9tuBD\nU5jBAhj/3OxvaKj9YcdRQhsOi0ixrPUtNT0rR9eic1ESEwiwKoGV4+S92HZx\npifOH0nI2vqshj93UBnzB7tnfG6MhzrF4TVaobU4jVZMkPU8WLW3KZKXbUCe\nrN6nNpIEMKVkh8zVYvkUTGEvWuXRAZ0Tl8mt4c8iDX9v7NkcWank+SItTHx2\nZIi88j6gKolOZZXxkhZOTEdSw3lmXPZ7coTs08Hmo9SwWkX3FY+7brehVNem\nRWbn\r\n=3ndS\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCZiR+AIlt/9TQ8M61yNBbgL4sE//kBhvPIYUyJssnLogIhAOpj9osFYUA7dv08frpJoCl0f3XxjWQ9E6w0kZ98VfZE"}]},"maintainers":[{"email":"kir@belevi.ch","name":"deepsweet"},{"email":"andypevek@gmail.com","name":"fosimus"},{"email":"psxcode@gmail.com","name":"psxcode"}],"_npmUser":{"name":"deepsweet","email":"kir@belevi.ch"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refun_3.0.1_1598867203772_0.44926572188086755"},"_hasShrinkwrap":false},"3.1.0":{"name":"refun","version":"3.1.0","description":"A collection of React Hook-enabled functions that compose harmoniously with each other. Similar to `recompose`, but:","keywords":[],"types":"types/index.d.ts","main":"node/index.js","browser":"web/index.js","react-native":"native/index.js","repository":{"type":"git","url":"git+https://github.com/nextools/metarepo.git"},"license":"MIT","engines":{"node":">=12.13.0"},"sideEffects":false,"dependencies":{"tsfn":"^2.0.0"},"bugs":{"url":"https://github.com/nextools/metarepo/issues"},"homepage":"https://github.com/nextools/metarepo#readme","_id":"refun@3.1.0","_nodeVersion":"14.8.0","_npmVersion":"6.14.8","dist":{"integrity":"sha512-isuwU2UXtYziocRlIhOCHp35Vzr5PPzUps+zQBDyJkWNSnywguvHUNFW/2Xc49X/RtoSCW6JUQCgSL/6t+6SBw==","shasum":"0d8a411d5aa82eaae6bb6984cbc188d86a97911b","tarball":"https://registry.npmjs.org/refun/-/refun-3.1.0.tgz","fileCount":189,"unpackedSize":374008,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfaghKCRA9TVsSAnZWagAAivAP/35tt+FOxnfY9q7qBvDh\nZxm4OjEwJ8BJsKyQqXb/ovyHoydsa2RYVK0MZ0vCkCm9bqFraNKaNvZjYYLZ\nVq0qCtBbHsb/JzWW4rnIXyfWoG+PItUXsT/G1SiL48mb72ePOm+NeWnek7mn\nR1gRaZnbyfkandUoZztl1az+j90pz7+ruuuwTfErjRQ5rGE+q9Bc7Rv5ce9p\nHCz2T1tr5UYH+Wm2hQTMcZr7GHdLPY3KiZC0oFolD3X/hIQZWojCDkoXtAUs\nVyKAOdi6syG+34vHSuGfQKt0hTke+WBsOaX3wLwhIAe/oX75vyJjUUZd+OiI\naIEQlNxIUwRsQ9ZMhRbTrRAWIjWH4mlqV/tFNIT/EzgmFJOAeEwo7dpj3JT8\nFisHWevdwG8XOOM1wGC5iiHUaVdGSF034iVhvxHE50808VkfdZ8SvBNDPfGO\naj7ynIsbrBHDKBFj5r5RxT8JsmTHGXZ84xPf19SfdJUUmpt2F3T4nuDHYSvN\nVstzpZgpJspPTCbTVm75f2yp3CtOWXl72c9lZE+lobTCUiKDIYTIHKVohVQ8\nYqJbmS7ijsvG25sqPr4wZTifPQ6CjI9oA7UimFM25FoaZ5GnjNR47IuDiZb2\n62TRScUr1CZGtAvOHu2YfkDvNBMdB6UtFqPfSA5scOvNz3fEaGTDUA3lUpvW\nwpf7\r\n=e9FT\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDj1kVFjStUXNDvBPoa4tIi8rYGj35f4qpf9DZtv7RnjgIgBdbMO6uIxMlt81EQtTNSIDuOBppk9+JKVj9kbXb8P+I="}]},"maintainers":[{"name":"fosimus","email":"andypevek@gmail.com"},{"name":"psxcode","email":"psxcode@gmail.com"},{"name":"deepsweet","email":"kir@belevi.ch"}],"_npmUser":{"name":"deepsweet","email":"kir@belevi.ch"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/refun_3.1.0_1600784458435_0.6120252941882427"},"_hasShrinkwrap":false}},"time":{"created":"2018-06-15T14:43:52.505Z","0.0.0":"2018-06-15T14:43:52.625Z","modified":"2022-05-15T16:49:28.902Z","0.1.0":"2019-04-09T08:12:51.210Z","0.2.0":"2019-05-24T08:33:53.930Z","0.3.0":"2019-06-07T08:51:17.616Z","0.3.1":"2019-06-18T09:08:10.867Z","0.3.2":"2019-07-05T14:33:30.051Z","0.3.3":"2019-07-08T12:20:42.066Z","0.3.4":"2019-08-02T15:09:29.395Z","0.4.0":"2019-08-29T14:31:48.264Z","0.4.1":"2019-09-03T13:09:54.400Z","0.4.2":"2019-09-18T14:37:08.317Z","0.4.3":"2019-09-20T11:46:11.937Z","0.4.4":"2019-10-09T14:28:57.098Z","0.4.5":"2019-12-18T14:34:14.496Z","0.5.0-beta.0":"2019-12-23T12:17:25.434Z","0.5.0-beta.1":"2019-12-23T16:55:16.531Z","1.0.0":"2020-01-23T09:59:20.663Z","1.0.1":"2020-04-14T11:34:00.238Z","2.0.0":"2020-04-17T09:51:35.001Z","2.0.1":"2020-06-17T13:29:35.924Z","3.0.0":"2020-08-14T09:22:22.173Z","3.0.1":"2020-08-31T09:46:43.950Z","3.1.0":"2020-09-22T14:20:58.588Z"},"maintainers":[{"name":"fosimus","email":"andypevek@gmail.com"},{"name":"psxcode","email":"psxcode@gmail.com"},{"name":"deepsweet","email":"kir@belevi.ch"}],"license":"MIT","readme":"# refun ![npm](https://flat.badgen.net/npm/v/refun)\n\nA collection of React Hook-enabled functions that compose harmoniously with each other. Similar to `recompose`, but:\n\n- Uses `Props -> Props` functions instead of `Component -> Component` functions. This is all around better. It means:\n  - Less nodes in the React tree\n  - Better optimization options for the JavaScript engine\n  - Being able to reuse general purpose functions (all of Ramda's object manipulation functions work)\n- Propagates TypeScript types through the composition chain **without any losses**.\n- Works entirely with React Hooks instead of class components\n\n## Usage example (with TypeScript)\n\n```tsx\nimport React from 'react'\nimport {\n  component,\n  mapDefaultProps,\n  mapHandlers,\n  mapHovered,\n  mapState,\n  mapWithPropsMemo,\n  startWithType,\n  TMapHovered\n} from 'refun'\n\ntype TButton = {\n  isDisabled?: boolean\n  clickCounter?: number\n  id?: string\n} & TMapHovered\n\nexport const Button = component(\n  startWithType<TButton>(),\n  mapDefaultProps({\n    clickCounter: 0,\n    isDisabled: false\n  }),\n  mapState(\n    \"clickCounter\",\n    \"setClickCounter\",\n    ({ clickCounter }) => clickCounter,\n    [\"clickCounter\"]\n  ),\n  mapHandlers({\n    onClick: ({ clickCounter, setClickCounter }) => () =>\n      setClickCounter(clickCounter + 1)\n  }),\n  mapHovered,\n  mapWithPropsMemo(\n    ({ clickCounter, isDisabled, isHovered }) => ({\n      children: `Click count: ${clickCounter}`,\n      style: {\n        cursor: isDisabled ? \"auto\" : \"pointer\",\n        borderColor: isHovered ? \"black\" : \"grey\"\n      }\n    }),\n    [\"clickCounter\", \"isDisabled\", \"isHovered\"]\n  )\n)(\n  ({\n    id,\n    isDisabled,\n    style,\n    onPointerEnter,\n    onPointerLeave,\n    onClick,\n    children\n  }) => (\n    <button\n      disabled={isDisabled}\n      id={id}\n      onClick={onClick}\n      onMouseEnter={onPointerEnter}\n      onMouseLeave={onPointerLeave}\n      style={style}\n    >\n      {children}\n    </button>\n  )\n)\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-example-nec8y)\n\nSeveral things to note:\n\n- [`component`](#component) is used instead of a regular `compose` (from Ramda, Recompose or Redux for example) because `component` accurately propagates the types throughout the entire chain\n- Because of the type propagation, it's convenient to write down all the functions in place in the composition chain. This way, the types will be inferred: otherwise the types will have to be specified manually.\n- [`startWithType`](#startWithType) is necessary because of a TypeScript shortcoming. It is used to make the type that will be received by the first function in the composition chain available. It shouldn't be necessary to do this with a specific function: ideally, the `component` function itself should be able to propagate the type variable of the generic down to the functions inside, but at the time of this writing (2019-06-26) TypeScript does not support this. If it would, the right way to start the composition chain would be:\n\n  ```ts\n  // Note: This is currently not possible\n  export const Button = component<TButtonProps>(\n    mapWithPropsMemo(({ isDisabled }) => ({\n    ...\n  ```\n\n> Note: you might notice that `refun` has functions that serve as the equivalent of most of the React Hooks, so it might seem odd that some, such as `useEffect`, are missing. The reason is simply that wrapping them in the composition chain of `refun` provides no benefit: `useEffect` in particular does not result in any prop being added or removed, and there is no implicit state to keep track of, as is the case with the `mapSafeTimeout` and similar functions.\n\n> It is not the goal of `refun` to be a replacement of direct usage of React Hooks, rather a way to use them as a clean and decoupled composition chain and with good TypeScript typings, features that are only relevant to certain Hooks.\n\n## API\n\n- [component](#component)\n- [pureComponent](#pureComponent)\n- [mapContext](#mapContext)\n- [mapDebouncedHandlerTimeout](#mapDebouncedHandlerTimeout)\n- [mapDebouncedHandlerFactory](#mapDebouncedHandlerFactory)\n- [mapDefaultProps](#mapDefaultProps)\n- [mapFocused](#mapFocused)\n- [mapHandlers](#mapHandlers)\n- [mapHovered](#mapHovered)\n- [mapKeyboardFocused](#mapKeyboardFocused)\n- [mapPressed](#mapPressed)\n- [mapProps](#mapProps)\n- [mapRef](#mapRef)\n- [mapSafeRequestAnimationFrame](#mapSafeRequestAnimationFrame)\n- [mapSafeTimeout](#mapSafeTimeout)\n- [mapState](#mapState)\n- [mapStateRef](#mapStateRef)\n- [mapThrottledHandlerTimeout](#mapThrottledHandlerTimeout)\n- [mapThrottledHandlerAnimationFrame](#mapThrottledHandlerAnimationFrame)\n- [mapThrottledHandlerFactory](#mapThrottledHandlerFactory)\n- [mapWithProps](#mapWithProps)\n- [mapWithPropsMemo](#mapWithPropsMemo)\n- [onChange](#onChange)\n- [onLayout](#onLayout)\n- [onUpdate](#onUpdate)\n- [onUpdateAsync](#onUpdateAsync)\n- [startWithType](#startWithType)\n- [StoreContextFactory](#StoreContextFactory)\n\n## `component`\n\nThis function is an analog of `compose` and it performs simple function composition, with two caveats:\n\n- The value sent into the chain is presumed to be a React Function Component (`FC` type)\n- `component` will use the output type of one function in the chain as the input type of the next function in the chain, allowing the functions to modify the type along the way. It is not necessary to tell `component` what the output type at the end of the chain is going to be, since it will be inferred correctly from the functions passed into it.\n\n## `pureComponent`\n\nThis function is identical to [`component`](#component) except that it memoizes the React element that results from rendering with a certain set of props. The props that are memoized are the _inner_ props, that is, the props that the component will get as the result of the entire composition chain. These are different from the _outer_ props, that are the ones that consumers pass manually into the component.\n\nThe purpose of this component is to prevent a re-render from happening when the React tree is known to be the same. It is particularly useful when the React tree is a complex one, since the cost grows fast with the amount of nodes in the tree. Since the memoization is done in the inside of the component, all `map` functions will be run, making it ideal for components that control their own state.\n\n> Note that this function is meant to be used to avoid pointless re renders of complex trees, which is a concern that should be treated at the high level, in an app for example, rather than in small presentational components. Memoization comes with a cost, and React is already providing optimizations via reconciliation, so the type of optimizations that `pureComponent` does, similar to the old `shouldComponentUpdate`, is to be reserved for cases where there is a clear need for optimization.\n\n```tsx\nimport React from 'react'\nimport { mapReducer, pureComponent, startWithType } from 'refun'\nimport AComplexHeader from './AComplexHeader'\nimport AnExpensiveToComputeSidebar from './AnExpensiveToComputeSidebar'\n\ntype TCounter = {\n  initialCount?: number,\n}\n\nexport default pureComponent(\n  startWithType<TCounter>(),\n  mapDefaultProps({\n    initialCount: 0\n  }),\n  mapState('counter', 'setCounter', ({ initialCount }) => initialCount, ['initialCount']),\n  mapHandlers\n)(({ counter, dispatch }) = (\n  <main>\n    <AComplexHeader />\n    <AnExpensiveToComputeSidebar />\n    <button onClick>\n      Add\n    </button>\n\n    <p>{counter}</p>\n  </main>\n))\n```\n\nSo to be clear, the component that receives `counter` and `dispatch` as props is the one that is going to be memoized. If your intention is to memoize an expensive computation in a function in the composition chain, such as calculating a value in the `mapWithProps`, take a look at [`mapWithPropsMemo`](#mapWithPropsMemo) instead.\n\n`pureComponent` should only be used in components that receive no `children` and no complex props, since otherwise the overhead of memoization is not worth it. If the component receives `children` or complex props (objects / arrays), `pureComponent` will not provide any benefit, since those are very likely (or guaranteed in the case of `children`) to be different on every render. `pureComponent` works by doing a shallow comparison of the current props with the previous props. Shallow comparison means that each prop is compared with hard equality with the previous value of that same props.\n\n## `mapContext`\n\nSignature:\n\n```ts\nconst mapContext: <T>(context: React.Context<T>) => // ...\n```\n\nThis function receives a React Context object as created by the `React.createContext` function. The assumption is that the `value` property inside the Context is an object: `mapContext` will spread that object into the props of the components.\n\nFor example:\n\n```tsx\nimport React, { createContext } from 'react'\nimport { component, mapContext, startWithType } from 'refun'\n\ntype TThemeContext = {\n  darkMode: boolean,\n}\n\nconst ThemeContext = createContext<TThemeContext>({\n  darkMode: false\n})\n\ntype TMessage = {\n  label: string\n}\n\ncomponent(\n  startWithType<TMessage>(),\n  mapContext(ThemeContext)\n)(({ darkMode, label }) => (\n  <p style={{ color: darkMode ? 'white' : 'black' }}>\n    {label}\n  </p>\n))\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapcontext-rtjvk)\n\n## `mapDebouncedHandlerTimeout`\n\nSignature:\n\n```ts\nconst mapDebouncedHandlerTimeout: (handlerName: string, timeout: number) => // ...\n```\n\n> This function is affected by the [React Synthetic Events vs debouncing / throttling](#react-synthetic-events-vs-debouncing--throttling) issue.\n\nThis function allows you to defer the execution of a handler for a grace period (specified in milliseconds) and if the handler gets invoked again during that period, it cancels the current grace period and overrides it with the new call, restarting the time counter.\n\nWhy you ask? Imagine for example that there is a button in the UI in which a user might be tempted to repeatedly click to make sure an action happens, but it doing so they will repeatedly trigger an expensive operation that will freeze the application. To avoid this, you could debounce the `onClick` handler for some milliseconds and make sure only the last call will be acted upon.\n\nThe difference between debouncing and throttling (available in [`mapThrottledHandlerTimeout`](#mapThrottledHandlerTimeout)) is that successive calls to a debounced handler will restart the timeout each time, while throttled calls will be executed once the initially set timeout it reached, using the latest arguments. Following the FRP convention, this is how debouncing could be represented:\n\n```\ndebouncing in 3 seconds\n\n          1s 2s 3s 4s 5s 6s 7s 8s 9s\nreceived  x--y--------z------------\nran       ---------y--------z------\n```\n\nNotice how the timeout initially set for `x` is simply cancelled and overridden with a new timeout of 3 seconds for `y`.\n\n```tsx\nimport React from 'react'\nimport { component, mapHandlers, mapDebouncedHandlerTimeout, startWithType } from 'refun'\n\ntype TButton = {\n  onClick: () => void\n}\n\nexport default component(\n  startWithType<TButton>(),\n  mapHandlers({\n    onClick: () => () => console.log(\"the handler was now called\")\n  }),\n  mapDebouncedHandlerTimeout('onClick', 1000)\n)(({ onClick }) => (\n  <div>\n    <p>\n      Even if you click the button many times in a row (with each click less\n      than a second after the other), you will only see one log message, at the\n      end\n    </p>\n    <button onClick={onClick}>Click me</button>\n  </div>\n))\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapdebouncedhandlertimeout-791kn)\n\n## `mapDebouncedHandlerFactory`\n\nSignature:\n\n```ts\nconst mapDebouncedHandlerFactory: (setFn: Function, clearFn: Function) => (handlerName: string, ...setFnArgs: any[]) => // ...\n```\n\n> All the functions create with this one are affected by the [React Synthetic Events vs debouncing / throttling](#react-synthetic-events-vs-debouncing--throttling) issue.\n\nThis function is a constructor for debouncers. It is used under the hood to build the `mapDebouncedHandlerTimeout` function. If you have a function that creates a deferred effect and a function that will cancel that deferral, you can build your own debouncer.\n\nThis is how `mapDebouncedHandlerTimeout` is defined:\n\n```ts\nexport const mapDebouncedHandlerTimeout = mapDebouncedHandlerFactory(setTimeout, clearTimeout)\n```\n\n## `mapDefaultProps`\n\nSignature:\n\n```ts\nconst mapDefaultProps: <P>(defaultProps: P) => // ...\n```\n\nThis function sets some default prop values based on the object that is passed into it. Alternative to using the static `defaultProps` component property. The advantage of using it is that the props passed in will be type checked.\n\n```tsx\nimport React from 'react'\nimport { component, mapDefaultProps, startWithType } from 'refun'\n\ntype TMessage = {\n  label?: string\n}\n\nexport default component(\n  startWithType<TMessage>(),\n  mapDefaultProps({\n    label: 'Hello World!'\n  })\n)(({ label }) => (\n  <p>{label}</p>\n))\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapdefaultprops-gqjqz)\n\n## `mapFocused`\n\nSignature: Not callable.\n\nThis function sets the `isFocused` prop to `true` when the `onFocus` handler is called and to `false` when `onBlur` is called.\n\n```tsx\nimport React from 'react'\nimport { component, mapFocused, startWithType, TMapFocused } from 'refun'\n\ntype TButton = {\n  label: string\n} & TMapFocused\n\nexport default component(\n  startWithType<TButton>(),\n  mapFocused\n)(\n  ({ isFocused, label, onBlur, onFocus }) => (\n    <button\n      onBlur={onBlur}\n      onFocus={onFocus}\n      style={{\n        borderWidth: 2,\n        borderStyle: \"solid\",\n        borderColor: isFocused ? \"red\" : \"grey\",\n        outline: \"none\"\n      }}\n    >\n      {label}\n    </button>\n  )\n)\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapfocused-8gls5)\n\n## `mapHandlers`\n\nSignature:\n\n```ts\nconst mapHandlers: <P>(handlers: { [key: string]: (props: P) => (...args: any[]) => void }) => // ...\n```\n\nThis function allows you to build custom handlers that will be memoized so that they do not cause a diff in the shallow comparison, which would lead to a re render.\n\nSo instead of writing:\n\n```tsx\n// This will cause the component to re render every time because the handler is unique in every execution\nconst Input = ({ onChange, value }) => {\n  const handleChange = ({ target }) => onChange(target.value)\n\n  return <input\n    onChange={handleChange}\n    value={target.value}\n  />\n}\n```\n\n…it allows you to do:\n\n```tsx\nimport React from 'react'\nimport { component, mapHandlers, startWithType } from 'refun'\n\ntype TInput = {\n  onChange: (string) => void,\n  value: string,\n}\n\nexport default component(\n  startWithType<TInput>(),\n  mapHandlers({\n    onChange: ({ onChange }) => ({ target }) => onChange(target.value),\n  })\n)(\n  ({ onChange, value }) => (\n    <input\n      onChange={onChange}\n      value={value}\n    />\n  )\n)\n```\n\nThe first argument that each handler will receive is the current props, and the second is the arguments that had been sent to the handler. Notice that the second argument is curried.\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-maphandlers-8d823)\n\n## `mapHovered`\n\nSignature: Not callable\n\nThis function sets the `isHovered` prop to `true` when the `onPointerEnter` handler is called and to `false` when `onPointerLeave` is called.\n\nNote that `onPointerEnter` and `onPointerLeave` are synthetic event names meant to abstract from platform specific hover states. In web, they will be typically mapped:\n\n- `onPointerEnter` -> `onMouseEnter`\n- `onPointerLeave` -> `onMouseLeave`\n\n…and each platform will have their own corresponding mapping.\n\n```tsx\nimport React from 'react'\nimport { component, mapHovered, startWithType, TMapHovered } from 'refun'\n\ntype TButton = {\n  label: string\n} & TMapHovered\n\nexport default component(\n  startWithType<TButton>(),\n  mapHovered\n)(\n  ({ isHovered, label, onPointerLeave, onPointerEnter }) => (\n    <button\n      onMouseLeave={onPointerLeave}\n      onMouseEnter={onPointerEnter}\n      style={{\n        borderWidth: 2,\n        borderStyle: \"solid\",\n        borderColor: isHovered ? \"red\" : \"grey\",\n        outline: \"none\"\n      }}\n    >\n      {label}\n    </button>\n  )\n)\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-maphovered-lfzqj)\n\n## `mapKeyboardFocused`\n\nSignature: Not callable.\n\nThis function sets the `isKeyboardFocused` prop to `true` when the target gets focused (after `onFocus`) but only if the focus was acquired via the keyboard interaction, not a pointer event (so if there was no press event before the `onFocus`). The prop is set to `false` once `onBlur` happens.\n\nThe reason this is useful is that it allows focus states meant for keyboard navigation to be differentiated from regular focus states. When the user is navigating with the keyboard, for example pressing the Tab key, visual highlighting of the focused elements needs to be more prominent to guide the sight into where the active element is. Pointer events will trigger focus as well, but when the interaction was initiated with a pointer it's not necessary for the highlight to be as prominent, since the user is already focused in the pointer position. In order to distinguish these two states and make it possible to style them separately, you can use `mapFocused` for the general case and `mapKeyboaredFocused` for the specific keyboard navigation case.\n\nNote that `onPressIn` and `onPointerLeave` are synthetic event names meant to abstract from platform specific hover states. In web, they will be typically mapped:\n\n- `onPressIn` -> `onMouseDown`\n- `onPressOut` -> `onMouseUp`\n\n…and each platform will have their own corresponding mapping.\n\n```tsx\nimport React from 'react'\nimport { component, mapKeyboardFocused, startWithType, TMapKeyboardFocused } from 'refun'\n\ntype TButton = {\n  label: string\n} & TMapKeyboardFocused\n\nexport default component(\n  startWithType<TButton>(),\n  mapKeyboardFocused\n)(\n  ({ isKeyboardFocused, label, onBlur, onFocus, onPressIn, onPressOut }) => (\n    <button\n      onBlur={onBlur}\n      onFocus={onFocus}\n      onMouseDown={onPressIn}\n      onMouseUp={onPressOut}\n      style={{\n        borderWidth: 2,\n        borderStyle: \"solid\",\n        borderColor: isKeyboardFocused ? \"red\" : \"grey\",\n        outline: \"none\"\n      }}\n    >\n      {label}\n    </button>\n  )\n)\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapkeyboardfocused-okqxt)\n\n## `mapPressed`\n\nSignature: Not callable.\n\nThis function sets the `isPressed` prop to `true` when the `onPressIn` handler is called and to `false` when `onPressOut` is called.\n\nNote that `onPressIn` and `onPressOut` are synthetic event names meant to abstract from platform specific pressed states. In web, they will be typically mapped:\n\n- `onPressIn` -> `onMouseDown`\n- `onPressOut` -> `onMouseUp`\n\n…and each platform will have their own corresponding mapping.\n\n```tsx\nimport React from 'react'\nimport { component, mapPressed, startWithType, TMapPressed } from 'refun'\n\ntype TButton = {\n  label: string\n} & TMapPressed\n\nexport default component(\n  startWithType<TButton>(),\n  mapPressed\n)(\n  ({ isPressed, label, onPressIn, onPressOut }) => (\n    <button\n      onMouseDown={onPressIn}\n      onMouseUp={onPressOut}\n      style={{\n        borderWidth: 2,\n        borderStyle: \"solid\",\n        borderColor: isPressed ? \"red\" : \"grey\",\n        outline: \"none\"\n      }}\n    >\n      {label}\n    </button>\n  )\n)\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mappressed-z8lbx)\n\n## `mapProps`\n\nSignature:\n\n```ts\nconst mapProps: <P, R>(getFn: (props: P) => R) => // ...\n```\n\nThis function takes a handler that receives all props and returns new props.\n\n```tsx\nimport React from 'react'\nimport { component, mapProps, startWithType } from 'refun'\n\ntype TButton = {\n  label: string\n}\n\nexport default component(\n  startWithType<TButton>(),\n  mapProps(({ label }) => ({ children: label }))\n)(\n  ({ children }) => <button>{children}</button>\n)\n```\n\nNote that `label` is no longer available as a prop to the component. If you want to expand the props with extra ones instead of replacing them consider using [`mapWithProps`](#mapWithProps)\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapprops-37ho6)\n\n## `mapRef`\n\nSignature:\n\n```ts\nconst mapRef: <T>(name: string, initialValue: T) => // ...\n```\n\nThis function provides a way of making a mutable reference available as a prop. It uses the `useRef` hook under the hood.\n\nRefs are useful to store derived values that do not support shallow comparison, such as functions, or DOM elements.\n\nFor example you can use it to capture the `ref` to a DOM element and inspect it:\n\n```tsx\nimport React from 'react'\nimport { component, mapRef, onMount, startWithType } from 'refun'\n\ntype TButton = {\n  label: string\n}\n\nexport default component(\n  startWithType<TButton>(),\n  mapRef('buttonElementRef', null),\n  onMount(({ buttonElementRef }) => {\n    if (buttonElementRef.current !== null) {\n      console.log(buttonElementRef)\n    }\n  })\n)(\n  ({ buttonElementRef, label }) => (\n    <button ref={buttonElementRef}>\n      {label}\n    </button>\n  )\n)\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapref-t3wog)\n\n## `mapSafeRequestAnimationFrame`\n\nSignature:\n\n```ts\nconst mapSafeRequestAnimationFrame: (propName: string) => // ...\n```\n\nThis function allows you to set up operations to be executed in the next animation frame that should only be executed while the component is still mounted, and should be canceled if the component is removed from the tree. Callbacks that are not canceled when unmounted are a common cause of React memory leaks.\n\nWhy you ask? Animations. Animations can be done in React by continuously updating style parameters of a component, and the cleanest way of updating those is with `requestAnimationFrame`. This function allows you to use `requestAnimationFrame` without worrying about memory leaks.\n\n\n> As you can check in this [📺 live demo of the issue](https://codesandbox.io/s/refun-mapsafeanimationframe-problem-demonstration-4t0w1), simply using `requestAnimationFrame` will cause the problems when pressing the \"Stop loading\" button. In particular, React will log:\n> ```\n> Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.\n> ```\n> `mapSafeRequestAnimationFrame` does the cleanup for you.\n\n```tsx\nimport React from 'react'\nimport {\n  component,\n  mapState,\n  mapSafeRequestAnimationFrame,\n  startWithType,\n  mapHandlers\n} from 'refun'\n\ntype TLoader = {\n  initialPosition: number\n}\n\nconst Loader = component(\n  startWithType<TLoader>(),\n  mapState(\n    \"position\",\n    \"setPosition\",\n    ({ initialPosition }) => initialPosition,\n    []\n  ),\n  mapSafeRequestAnimationFrame(\"setAnimationFrameCallback\")\n)(({ position, setPosition, setAnimationFrameCallback }) => {\n  setAnimationFrameCallback(() => {\n    setPosition((position + 1) % 80)\n  })\n  return (\n    <div\n      style={{\n        width: 100,\n        height: 8,\n        border: \"1px solid black\"\n      }}\n    >\n      <div\n        style={{\n          width: 20,\n          marginLeft: position,\n          height: 8,\n          backgroundColor: \"black\"\n        }}\n      />\n    </div>\n  )\n})\n\ntype TApp = {\n  loading: boolean\n}\n\nexport default component(\n  startWithType<TApp>(),\n  mapState(\n    \"loading\",\n    \"setLoading\",\n    ({ loading }) => loading !== undefined ? loading : true,\n    []\n  ),\n  mapHandlers({\n    onStop: ({ setLoading }) => () => setLoading(false)\n  })\n)(({ loading, onStop }) => (\n  <div>\n    {loading && <Loader initialPosition={0} />}\n    <button onClick={onStop}>Stop loading</button>\n  </div>\n))\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapsafeanimationframe-s3ttu)\n\n## `mapSafeTimeout`\n\nSignature:\n\n```ts\nconst mapSafeTimeout: (propName: string) => // ...\n```\n\nThis function allows you to configure time outs that should only be executed while the component is still mounted, and should be canceled if the component is removed from the tree. Timeouts that are not canceled when unmounted are a common cause of React memory leaks.\n\n> As you can check in this [📺 live demo of the issue](https://codesandbox.io/s/refun-mapsafetimeout-problem-demonstration-dkiwq), simply using `setTimeout` will cause the problems when pressing the \"Close immediately\" button before the countdown is completed. In particular, React will log:\n> ```\n> Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.\n> ```\n> `mapSafeTimeout` does the cleanup for you.\n\n```tsx\nimport React from 'react'\nimport {\n  component,\n  mapHandlers,\n  mapState,\n  mapSafeTimeout,\n  startWithType\n} from 'refun'\n\ntype TMessage = {\n  onClose: () => void\n}\n\nconst Message = component(\n  startWithType<TMessage>(),\n  mapState(\"autoClose\", \"setAutoClose\", () => false, []),\n  mapState(\"secondsRemaining\", \"setSecondsRemaining\", () => 5, []),\n  mapSafeTimeout(\"setLocalTimeout\")\n)(\n  ({\n    onClose,\n    secondsRemaining,\n    setSecondsRemaining,\n    setLocalTimeout,\n    autoClose,\n    setAutoClose\n  }) => (\n    <div\n      style={{\n        backgroundColor: \"#f0f0f0\",\n        padding: 20\n      }}\n    >\n      {autoClose ? (\n        <React.Fragment>\n          <p>This message will close in {secondsRemaining} seconds</p>\n          <button onClick={onClose}>Close immediately</button>\n        </React.Fragment>\n      ) : (\n        <React.Fragment>\n          <p>\n            This message that will close {secondsRemaining} seconds after you\n            press OK\n          </p>\n\n          <button\n            onClick={() => {\n              setAutoClose(true)\n              setLocalTimeout(() => {\n                console.log(\"timeout 1000\")\n                setSecondsRemaining(4)\n              }, 1000)\n              setLocalTimeout(() => {\n                console.log(\"timeout 2000\")\n                setSecondsRemaining(3)\n              }, 2000)\n              setLocalTimeout(() => {\n                console.log(\"timeout 3000\")\n                setSecondsRemaining(2)\n              }, 3000)\n              setLocalTimeout(() => {\n                console.log(\"timeout 4000\")\n                setSecondsRemaining(1)\n              }, 4000)\n              setLocalTimeout(() => {\n                console.log(\"timeout 5000\")\n                onClose()\n              }, 5000)\n            }}\n          >\n            Ok\n          </button>\n        </React.Fragment>\n      )}\n    </div>\n  )\n)\n\ntype TApp = {\n  show?: boolean\n}\n\nexport default component(\n  startWithType<TApp>(),\n  mapState(\"show\", \"setShow\", ({ show }) => true, []),\n  mapHandlers({\n    onClose: ({ setShow }) => () => setShow(false),\n    onShow: ({ setShow }) => () => setShow(true)\n  })\n)(({ show, onClose, onShow }) => (\n  <div>\n    {show ? (\n      <Message onClose={onClose} />\n    ) : (\n      <button onClick={onShow}>Show message again</button>\n    )}\n  </div>\n))\n```\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapsafetimeout-7mqmh]\n\n## `mapState`\n\nSignature:\n\n```ts\nconst mapState: <P, R>(stateName: string, setterName: string, getValue: (props: P) => R, watchKeys: string[]) => // ...\n```\n\nThis function allows you to set up a stateful prop and a function for updating that prop. It also supports setting the initial value, derived from the props passed into it, and a list of props to watch to reset that value whenever the external prop changes.\n\nNote in the example how the `OverridableInternalCounter` sets the `[\"counter\"]` as the last argument of `mapState`. This will cause `mapState` to watch for incoming changes to the `counter` prop and use them to update the `internalCounter` prop, accordingly to the function in the third argument `({ counter }) => counter`. In the case of `InternalCounter`, the array in the last argument is empty (`[]`) and then `mapState` does not watch for changes, which causes the external prop `counter` value to be ignored once updated, effectively working as an initial value only for `internalCounter`.\n\n```tsx\nimport React from 'react'\nimport { component, mapState, startWithType } from 'refun'\n\ntype TCounter = {\n  counter: number\n}\n\nconst InternalCounter = component(\n  startWithType<TCounter>(),\n  mapState(\"internalCounter\", \"setCounter\", ({ counter }) => counter, [])\n)(({ internalCounter, setCounter }) => (\n  <div>\n    <button onClick={() => setCounter(internalCounter + 1)}>\n      Add to internal counter\n    </button>\n    <p>{internalCounter}</p>\n  </div>\n));\n\nconst OverridableInternalCounter = component(\n  startWithType<TCounter>(),\n  mapState(\"internalCounter\", \"setCounter\", ({ counter }) => counter, [\n    \"counter\"\n  ])\n)(({ internalCounter, setCounter }) => (\n  <div>\n    <button onClick={() => setCounter(internalCounter + 1)}>\n      Add to overridable internal counter\n    </button>\n    <p>{internalCounter}</p>\n  </div>\n));\n\nexport default component(\n  startWithType<TCounter>(),\n  mapState(\"externalCounter\", \"setExternalCounter\", ({ counter }) => counter, [\n    \"counter\"\n  ])\n)(({ externalCounter, setExternalCounter }) => (\n  <div>\n    <button onClick={() => setExternalCounter(externalCounter + 1)}>\n      Add to external counter\n    </button>\n    <p>{externalCounter}</p>\n    <OverridableInternalCounter counter={externalCounter} />\n    <InternalCounter counter={externalCounter} />\n  </div>\n))\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapstate-zy1rj)\n\n## `mapStateRef`\n\nSignature:\n\n```ts\nconst mapStateRef: <P, R>(stateName: string, flushName: string, getValue: (props: P) => R, watchKeys: string[]) => // ...\n```\n\nThis function allows you to set up a stateful prop and a function for updating that prop. It also supports setting the initial value, derived from the props passed into it, and a list of props to watch to reset that value whenever the external prop changes.\n\nNote in the example how the `OverridableInternalCounter` sets the `[\"counter\"]` as the last argument of `mapState`. This will cause `mapState` to watch for incoming changes to the `counter` prop and use them to update the `internalCounter` prop, accordingly to the function in the third argument `({ counter }) => counter`. In the case of `InternalCounter`, the array in the last argument is empty (`[]`) and then `mapState` does not watch for changes, which causes the external prop `counter` value to be ignored once updated, effectively working as an initial value only for `internalCounter`.\n\n```tsx\nimport React from 'react'\nimport { component, mapStateRef, onMount, startWithType } from 'refun'\n\ntype TGetValue = {\n  index: number,\n  value: number,\n  onChange: (i: number, v: number) => void\n}\n\nconst GetValue = component(\n  startWithType<TValue>(),\n  onMount(({ index, onChange }) => {\n    onChange(index, Math.random())\n  })\n)(({ value }) => (\n  <span>{value}</span>\n));\n\ntype TComp = {\n  numValues: number\n}\n\nexport default component(\n  startWithType<TComp>(),\n  mapStateRef('valuesRef', 'flushValues', ({ numValue }) => Array(numValues).fill(0), ['numValues']),\n  mapHandlers({\n    onChange: ({ valuesRef, flushValues }) => (i, value) => {\n      valuesRef.current[i] = value\n      flushValues()\n    }\n  })\n)(({ valuesRef }) => (\n  <div>\n    {valuesRef.current.map((value) => (\n      <GetValue value={value} />\n    ))}\n  </div>\n))\n```\n\n## `mapThrottledHandlerTimeout`\n\nSignature:\n\n```ts\nconst mapThrottledHandlerTimeout: (handlerName: string, timeout: number) => // ...\n```\n\n> This function is affected by the [React Synthetic Events vs debouncing / throttling](#react-synthetic-events-vs-debouncing--throttling) issue.\n\nThis function allows you to defer the execution of a handler for a grace period (specified in milliseconds) and if the handler gets invoked again during that period, it overrides the call with the new invocation, so that when the specified timeout is reached, the last call will be the one executed.\n\nWhy you ask? Imagine for example that you have an application that monitors the window size and updates the layout depending on the new size. Window size updates happen very often while the user is performing the resize, and the new layout calculation might be fairly expensive, so the application might become unresponsive. In this case, you could use `mapThrottledHandlerTimeout` to make sure the resize update only happens every 500 milliseconds, which will not be too noticeable to the user, but will avoid a lot of unnecessary work. Because `mapThrottledHandlerTimeout` executes the _last_ invocation of the handler, the value that will be captured is the most recent one, which is important since we want to re layout according to the current size, no the one when the resize action started.\n\nThe difference between debouncing and throttling (available in [`mapDebouncedHandlerTimeout`](#mapDebouncedHandlerTimeout)) is that successive calls to a debounced handler will restart the timeout each time, while throttled calls will be executed once the initially set timeout it reached, using the last arguments. Following the FRP convention, this is how debouncing could be represented:\n\n```\nthrottling in 3 seconds\n\n          1s 2s 3s 4s 5s 6s 7s 8s 9s\nreceived  x--y--------x------------\nran       ------y-----------x------\n```\n\nNotice how the timeout initially configured for `x` is respected and the execution happens 3 seconds after the event for `x` is received, but `y` is run instead.\n\n```tsx\nimport React from 'react'\nimport {\n  component,\n  mapThrottledHandlerTimeout,\n  startWithType,\n  mapHandlers\n} from 'refun'\n\ntype TSlider = {\n  onChange: (string) => void\n}\n\nexport default component(\n  startWithType<TSlider>(),\n  mapHandlers({\n    onChange: () => (value) =>\n      console.log(`the handler has now been invoked with value: ${value}`)\n  }),\n  mapThrottledHandlerTimeout('onChange', 300),\n  mapHandlers({\n    onChange: ({ onChange }) => ({ target}) => onChange(target.value)\n  })\n)(({ onChange }) => <input type=\"range\" onChange={onChange} max=\"1000\" />)\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapthrottledhandlertimeout-1ss16)\n\n## `mapThrottledHandlerAnimationFrame`\n\nSignature:\n\n```ts\nconst mapThrottledHandlerAnimationFrame: (handlerName: string) => // ...\n```\n\n> This function is affected by the [React Synthetic Events vs debouncing / throttling](#react-synthetic-events-vs-debouncing--throttling) issue.\n\nThis function allows you to defer the execution of a handler until the next animation frame. If the handler gets invoked again before that animation frame hits, the new invocation will override the previous one, so that when the animation frame starts the last call will be the one executed.\n\nWhy you ask? Pretty much the same reasons that are true for [`mapThrottledHandlerTimeout`](#mapThrottledHandlerTimeout). Calls that are done between animation frames are wasteful overhead, since the UI will not be updated until the animation frame anyway, so if you have a handler firing continuously, it's a good idea to skip the wasteful ones. This might happen for handlers monitoring scroll or wheel or finger motion actions.\n\n> You might wonder why there is not `mapDebouncedHandlerAnimationFrame` if there is a `mapDebouncedHandlerTimeout`. The reason is that the behavior of that function would be identical to this one, so it's skipped.\n\n```tsx\nimport React from 'react'\nimport {\n  component,\n  mapThrottledHandlerAnimationFrame,\n  startWithType,\n  mapHandlers\n} from 'refun'\n\ntype TSlider = {\n  onChange: (string) => void\n}\n\nexport default component(\n  startWithType<TSlider>(),\n  mapHandlers({\n    onChange: () => (value) =>\n      console.log(`the handler has now been invoked with value: ${value}`)\n  }),\n  mapThrottledHandlerAnimationFrame('onChange'),\n  mapHandlers({\n    onChange: ({ onChange }) => ({ target: { value } }) => onChange(value)\n  })\n)(({ onChange }) => <input type=\"range\" onChange={onChange} max=\"1000\" />)\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapthrottledhandleranimationframe-xk8uc)\n\n## `mapThrottledHandlerFactory`\n\nSignature:\n\n```ts\nconst mapThrottledHandlerFactory: (setFn: Function, clearFn: Function) => (handlerName: string, ...setFnArgs: any[]) => // ...\n```\n\n> All the functions created with this one is affected by the [React Synthetic Events vs debouncing / throttling](#react-synthetic-events-vs-debouncing--throttling) issue.\n\nThis function is a constructor for throttlers. It is used under the hood to build the `mapThrottledHandlerTimeout` and `mapThrottledHandlerAnimationFrame` functions. If you have a function that creates a deferred effect and a function that will cancel that deferral, you can build your own throttler.\n\nThis is how `mapThrottledHandlerTimeout` is defined:\n\n```ts\nexport const mapThrottledHandlerTimeout = mapThrottledHandlerFactory(setTimeout, clearTimeout)\n```\n\n## `mapWithProps`\n\nSignature:\n\n```ts\nconst mapWithProps: <P, R>(getFn: (props: P) => R) => // ...\n```\n\nThis function allows you to expand the props passed in to a component with more props derived from them. It is typically used to precalculate values that are to be used in the component, to minimize the amount of logic needed to do in the render.\n\nIf the returned props have the same name as incoming props, they will override the incoming props.\n\n```tsx\nimport React from 'react'\nimport {\n  component,\n  mapFocused,\n  mapWithProps,\n  startWithType,\n  TMapFocused\n} from 'refun'\n\ntype TButton = {\n  label: string\n} & TMapFocused\n\nexport default component(\n  startWithType<TButton>(),\n  mapFocused,\n  mapWithProps(({ isFocused }) => ({\n    borderColor: isFocused ? \"red\" : \"grey\"\n  }))\n)(({ borderColor, label, onBlur, onFocus }) => (\n  <button\n    onBlur={onBlur}\n    onFocus={onFocus}\n    style={{\n      borderWidth: 2,\n      borderStyle: \"solid\",\n      borderColor,\n      outline: \"none\"\n    }}\n  >\n    {label}\n  </button>\n))\n```\n\nNote that this function just adds props to the component. If you want to replace all of them, you can use [`mapProps`](#mapProps) instead.\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapwithprops-cjdsc)\n\n## `mapWithPropsMemo`\n\nSignature:\n\n```ts\nconst mapWithPropsMemo: <P, R>(getFn: (props: P) => R, watchKeys: string[]) => // ...\n```\n\nThis function does the same as [`mapWithProps`](#mapWithProps) and it memoizes the result for the props specified in the second parameter.\n\nAn example use case in which this can prove useful is if you were to be calculating the Fibonacci number of an input, which is known to be expensive for large numbers:\n\n```tsx\nimport React from 'react'\nimport { component, mapWithPropsMemo, startWithType } from 'refun'\n\nconst inefficientFibonacci = position =>\n  position < 2\n    ? position\n    : inefficientFibonacci(position - 1) + inefficientFibonacci(position - 2)\n\ntype TFibonacci = {\n  position: number\n}\n\nexport default component(\n  startWithType<TFibonacci>(),\n  mapWithPropsMemo(\n    ({ position }) => ({\n      fibonacci: inefficientFibonacci(position)\n    }),\n    [\"position\"]\n  )\n)(({ position, fibonacci }) => (\n  <p>\n    The Fibonacci numbers in position {position} is <mark>{fibonacci}</mark>\n  </p>\n))\n```\n\nNotice that `mapWithPropsMemo` takes two arguments, and that memoization happens for the props that are specified in the second argument, in this case `position`.\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapwithpropsmemo-hjcso)\n\n## `onChange`\n\nSignature:\n\n```ts\nconst onChange: <P>(handler: (props: P) => Promise<void> | void, watchKeys: string[]) => // ...\n```\n\nThis function calls the passed in callback when the component is updated, sending the current Props as argument.\n\nFor example:\n\n```tsx\nimport React from 'react'\nimport { component, onChange, startWithType } from 'refun'\n\ntype TButton = {\n  label: string,\n}\n\nexport default component(\n  startWithType<TButton>(),\n  onChange(({ label }) => {\n    console.log('Updated with label', label)\n  }, ['label'])\n)(({ label }) => (\n  <button>\n    {label}\n  </button>\n))\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-onchange-lhvik)\n\n## `onLayout`\n\nSignature:\n\n```ts\nconst onLayout: <P>(onLayoutHandler: (props: P) => Promise<void> | void, watchKeys: string[]) => // ...\n```\n\nThis function calls the passed in callback when the component is updated, sending the current Props as argument.\n\nFor example:\n\n```tsx\nimport React from 'react'\nimport { component, onLayout, startWithType } from 'refun'\n\ntype TButton = {\n  label: string,\n}\n\nexport default component(\n  startWithType<TButton>(),\n  onLayout(({ label }) => {\n    console.log('Updated with label', label)\n  }, ['label'])\n)(({ label }) => (\n  <button>\n    {label}\n  </button>\n))\n```\n\n## `onUpdate`\n\nSignature:\n\n```ts\nconst onUpdate: <P>(onUpdateFn: (props: P) => (() => void) | void, watchKeys: string[]) => // ...\n```\n\nThis function calls the passed in callback when the component is mounted and updated, sending the current Props as an argument.\n> Pass certain propery keys as an array, to invoke handler only when such props has been updated.  \n> It is possible to return some *unsubscribe* function from *onUpdateHandler*. It will be called before next *onUpdate*.  \n> If watch array is empty *onUpdateHandler* will be called only for component mount and unmount cases.\n\nFor example:\n\n```tsx\nimport React from 'react'\nimport { component, onUpdate, startWithType } from 'refun'\n\ntype TButton = {\n  label: string,\n}\n\nexport default component(\n  startWithType<TButton>(),\n  onUpdate(({ label }) => {\n    console.log('Updated with label', label)\n\n    const handler = () => {}\n    window.addEventListener('resize', handler)\n\n    return () => {\n      window.removeEventListener('resize', handler)\n    }\n  }, ['label'])\n)(({ label }) => (\n  <button>\n    {label}\n  </button>\n))\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-onupdate-x8wln)\n\n## `onUpdateAsync`\n\nSignature:\n\n```ts\nconst onUpdateAsync: <P>(onUpdateFn: (propsRef: React.RefObject<P>) => (props: { cancelOthers: () => void, index: number }) => Generator<Promise<unknown>>, watchKeys: string[]) => // ...\n```\n\nThis is `onUpdate` variant that properly handles asynchronous behavior.\n> `propsRef` is a `props` reference, so *current* props are always available even after long waiting for some promises.  \n> `cancelOthers` provides a way to stop all concurrently running *routines*, if necessary. Canceled routine can use `finally` keyword to make some cleanup.  \n> Think of `function*` as the usual `async` function, which uses `yield` instead of `await`.\n\nFor example:\n\n```tsx\nimport React from 'react'\nimport { component, onUpdateAsync, startWithType } from 'refun'\n\ntype TComponent = {\n  ID: string,\n}\n\nexport default component(\n  startWithType<TComponent>(),\n  mapState('state', 'setState', () => null, [])\n  onUpdateAsync((propsRef) => function* ({ cancelOthers, index }) {\n    try {\n      // cancel all concurrently running routines\n      cancelOthers()\n\n      // use 'yield' instead of 'await'\n      const res = yield fetch(`http://url.com?id=${props.current.ID}`)\n      const json = yield res.json()\n\n      props.current.setState(json)\n\n    } finally {\n      cleanup()\n    }\n}, ['ID'])\n)(({ state }) => (\n  <div>\n    {state}\n  </div>\n))\n```\n\n## `startWithType`\n\nSignature:\n\n```ts\nconst startWithType: <P>() => // ...\n```\n\nThis function is simply a way of setting up the initial type in the [`component`](#component) composition chain, since TypeScript does not currently support doing that in the composition function itself (`component` in this case, but would be `compose` in Redux, Ramda, etc).\n\nIt's purpose is entirely for types, and in runtime it's a no-op.\n\n```tsx\nimport React from 'react'\nimport { component, startWithType } from 'refun'\n\ntype TButton = {\n  label: string,\n}\n\nexport default component(\n  startWithType<TButton>(),\n)(({ label }) = (\n  <button>\n    {label}\n  </button>\n))\n```\n\nOnce this is fixed in TypeScript this function will be redundant and it will be possible to pass the generic directly into `component`:\n\n```tsx\nimport React from 'react'\nimport { component } from 'refun'\n\ntype TButton = {\n  label: string,\n}\n\n// Remember: this is currently *not* supported\nexport default component<TButton>(\n  (props) => props\n)(({ label }) = (\n  <button>\n    {label}\n  </button>\n))\n```\n\n…meanwhile `startWithType` is a straightforward workaround.\n\n## `StoreContextFactory`\n\nSignature:\n\n```ts\nconst StoreContextFactory: <S>(store: Redux.Store<S>) => {\n  mapStoreState: <R>(mapStateToProps: (state: S) => R, stateKeysToWatch: string[]) => // ...\n  mapStoreDispatch: (dispatchPropName: string) => // ...\n}\n```\n\nThis function is a way of working with Redux stores together with React Hooks. It is an alternative to React Redux, with these goals:\n\n1. Work with Hooks, avoiding higher-order components\n2. Respect the types all throughout\n3. Match the level of optimization of React Redux.\n\nThe way this function works is that it receives a Redux Store object, and returns a component and two functions:\n\n- `StoreProvider` is a component that provides the React Context already loaded with the store that was passed in to the `StoreContextFactory`\n- `mapStoreDispatch` is a function to be used as part of a `component` or `pureComponent` composition, which will simply add `dispatch` to the props, so that the component being wrapped by it can dispatch actions.\n- `mapStoreState` is a function to be used as part of a `component` or `pureComponent` composition, which will add props derived from the state. Much like `connect` from React Redux, it receives a `mapStateToProps` function that will be called with the full state and which return value will be spread over the component props. `mapStoreState` takes as a second argument an array of the names of the props to watch in order to run the `mapStateToProps` function: if none of the listed props have changed, the `mapStateToProps` will not be ran.\n\nCheck the example below for a full use case.\n\n```tsx\nimport React from 'react'\nimport { createStore } from \"redux\"\nimport { component, pureComponent, StoreContextFactory, mapHandlers, startWithType } from 'refun'\n\ntype TState = {\n  counter: number\n}\n\ntype TAction = { type: \"INCREMENT\" payload: number } | { type: \"RESET\" }\n\nconst reducer = (state: TState, action: TAction): TState => {\n  switch (action.type) {\n    case \"INCREMENT\":\n      return {\n        ...state,\n        counter: state.counter + action.payload\n      }\n\n    case \"RESET\":\n      return {\n        ...state,\n        counter: 0\n      }\n\n    default:\n      return state\n  }\n}\n\nconst initialState = {\n  counter: 7\n}\n\nconst store = createStore(reducer, initialState)\n\nconst { mapStoreState, mapStoreDispatch } = StoreContextFactory(store)\n\nconst CounterDisplay = pureComponent(\n  startWithType<{}>(),\n  mapStoreState(\n    ({ counter }) => ({\n      counter\n    }),\n    [\"counter\"]\n  )\n)(({ counter }) => (\n  <div>\n    <p>Counter: {counter}</p>\n  </div>\n))\n\nconst ResetButton = component(\n  startWithType<{}>(),\n  mapStoreDispatch('dispatch'),\n  mapHandlers({\n    onClick: ({ dispatch }) => () =>\n      dispatch({\n        type: \"RESET\"\n      })\n  })\n)(({ onClick }) => (\n  <div>\n    <button onClick={onClick}>Reset</button>\n  </div>\n))\n\nconst IncrementButton = component(\n  startWithType<{}>(),\n  mapStoreDispatch('dispatch'),\n  mapHandlers({\n    onClick: ({ dispatch }) => () =>\n      dispatch({\n        type: \"INCREMENT\",\n        payload: 1\n      })\n  })\n)(({ onClick }) => (\n  <div>\n    <button onClick={onClick}>Increment</button>\n  </div>\n))\n\nexport default () => (\n  <div>\n    <CounterDisplay />\n    <ResetButton />\n    <IncrementButton />\n  </div>\n)\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-storecontextfactory-l9bp5)\n\n## Caveats\n\n### React Synthetic Events vs debouncing / throttling\n\nThe `mapDebounced*` and `mapThrottled*` family of functions do not accept React Synthetic Events. As you can see in the examples below, some specific properties of the event (`value` in that case) need to be extracted from the original Synthetic Event in order for them to work.\n\nThis is necessary because these two function families store the arguments passed to the handlers for delayed use. If that argument is a Synthetic Event, it will be stored to be reused, but React forbids this, because for performance reasons React reuses the references of Synthetic Events and mutates them.\n\n> If you try the example below without the `mapHandlers`, you will get:\n>\n> ```\n> Warning: This synthetic event is reused for performance reasons. If you're seeing this, you're accessing the property `target` on a released/nullified synthetic event. This is set to null. If you must keep the original synthetic event around, use event.persist(). See https://fb.me/react-event-pooling for more information.\n> ```\n>\n> [📺 Check out live demo](https://codesandbox.io/s/refun-mapthrottledhandlertimeout-wrong-usage-7q6cd)\n\n\nIf you are going to use information coming from the Synthetic Event, consider extracting the information you care about using `mapHandlers`, which will then let React discard the rest of the Event object.\n\nIf you are not going to use _any_ information coming from the Event—such as in the example for [`mapDebouncedHandlerTimeout`](#mapDebouncedHandlerTimeout)—then you will not be affected by this issue.\n\n```tsx\nimport React from 'react'\nimport {\n  component,\n  mapThrottledHandlerTimeout,\n  startWithType,\n  mapHandlers\n} from 'refun'\n\ntype TSlider = {\n  onChange: (string) => void\n}\n\nexport default component(\n  startWithType<TSlider>(),\n  mapHandlers({\n    onChange: () => (value) =>\n      console.log(`the handler has now been invoked with value: ${value}`)\n  }),\n  mapThrottledHandlerTimeout(\"onChange\", 300),\n  mapHandlers({\n    onChange: ({ onChange }) => ({ target: { value } }) => onChange(value)\n  })\n)(({ onChange }) => <input type=\"range\" onChange={onChange} max=\"1000\" />)\n```\n\n[📺 Check out live demo](https://codesandbox.io/s/refun-mapthrottledhandlertimeout-1ss16)\n","readmeFilename":"readme.md","homepage":"https://github.com/nextools/metarepo#readme","keywords":[],"repository":{"type":"git","url":"git+https://github.com/nextools/metarepo.git"},"bugs":{"url":"https://github.com/nextools/metarepo/issues"},"description":"A collection of React Hook-enabled functions that compose harmoniously with each other. Similar to `recompose`, but:"}