{"_id":"@01group/fxl","_rev":"13-f9d4c220abfbb7e3b88069c08f44576b","name":"@01group/fxl","dist-tags":{"latest":"0.0.7"},"versions":{"0.0.1":{"name":"@01group/fxl","version":"0.0.1","description":"fxl.js is a data-oriented JavaScript spreadsheet library. It provides a way to build spreadsheets using modular, lego-like blocks.","license":"Apache-2.0","keywords":["curried","data-oriented","fp","functional-programming","spreadsheet","excel","xlsx"],"homepage":"https://github.com/zero-one-group/fxl.js","main":"./src/index.js","typings":"./src/index.d.ts","dependencies":{"exceljs":"^4.3.0","ts-results":"^3.3.0"},"peerDependencies":{},"_id":"@01group/fxl@0.0.1","dist":{"shasum":"ae9ad5c2ad92dc169c4a6e53d9c77bdf3c6e865f","integrity":"sha512-fbNOno8OOj7xRtZKEwsJiufE/ynrpSvXIHegseagCKP1+wgMJWk9P2sJT36LkFLrmn4/JOvCU6ZSVyVsP8OSew==","tarball":"https://registry.npmjs.org/@01group/fxl/-/fxl-0.0.1.tgz","fileCount":35,"unpackedSize":124996,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEuDzuJZgdUntDpesUGL3Efn43bo6CnW1OimpJyKgC/dAiAvwQt8l2AA0kJ2IF+qAyGoFM+HUMsBAF8DPk3F/BzEyA=="}]},"_npmUser":{"name":"anthony-khong","email":"anthony.kusumo.khong@gmail.com"},"directories":{},"maintainers":[{"name":"anthony-khong","email":"anthony.kusumo.khong@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/fxl_0.0.1_1636288697827_0.30643532090312453"},"_hasShrinkwrap":false},"0.0.2":{"name":"@01group/fxl","version":"0.0.2","description":"fxl.js is a data-oriented JavaScript spreadsheet library. It provides a way to build spreadsheets using modular, lego-like blocks.","license":"Apache-2.0","keywords":["curried","data-oriented","fp","functional-programming","spreadsheet","excel","xlsx"],"homepage":"https://github.com/zero-one-group/fxl.js","main":"./src/index.js","typings":"./src/index.d.ts","dependencies":{"exceljs":"^4.3.0","ts-results":"^3.3.0"},"peerDependencies":{},"_id":"@01group/fxl@0.0.2","dist":{"shasum":"fcf5f112d2a93733e66fc502343b3120ee93da61","integrity":"sha512-SpA0cjcGnPkRWV3cQef1rgEIhTJqU4YdLVLRgNfA5fTYR9pL+xtyMMletIk0DC8cJIjXzHOONDDw7CHDyrEvsQ==","tarball":"https://registry.npmjs.org/@01group/fxl/-/fxl-0.0.2.tgz","fileCount":35,"unpackedSize":138360,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDRTkbFhHbO8DGfAQG1tybpf9D63q0LGC4fjURzr+tZuwIhAJS8ndqTqEfosU75yxGMSRx22mgQQbabg64NU7ZahcTz"}]},"_npmUser":{"name":"anthony-khong","email":"anthony.kusumo.khong@gmail.com"},"directories":{},"maintainers":[{"name":"anthony-khong","email":"anthony.kusumo.khong@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/fxl_0.0.2_1636289940636_0.024760657548341003"},"_hasShrinkwrap":false},"0.0.3":{"name":"@01group/fxl","version":"0.0.3","description":"fxl.js is a data-oriented JavaScript spreadsheet library. It provides a way to build spreadsheets using modular, lego-like blocks.","homepage":"https://github.com/zero-one-group/fxl.js","dependencies":{"tslib":"^2.0.0","exceljs":"^4.3.0","ts-results":"^3.3.0"},"keywords":["curried","data-oriented","fp","functional-programming","spreadsheet","excel","xlsx"],"license":"Apache-2.0","main":"./src/index.js","typings":"./src/index.d.ts","peerDependencies":{},"_id":"@01group/fxl@0.0.3","dist":{"shasum":"1bbc732fe814c4421e039766d36c992a1c38fc50","integrity":"sha512-udnzTgjPqqMJGZlMB6+i6c1kXmXNRrYjwrfMVSDWUowscyp0JshyhrbJ9SwUUkNHXEo/1jWxdOlw0vWd/tTqig==","tarball":"https://registry.npmjs.org/@01group/fxl/-/fxl-0.0.3.tgz","fileCount":35,"unpackedSize":137329,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDLM3DzmE8Ier2zdXadSSBaNFMvxZ0iGhmtzkmezdqBsQIgHG3+C9Owsvwu4lCdyGGfTKEhKiICBH13M6lGAQljwlI="}]},"_npmUser":{"name":"anthony-khong","email":"anthony.kusumo.khong@gmail.com"},"directories":{},"maintainers":[{"name":"anthony-khong","email":"anthony.kusumo.khong@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/fxl_0.0.3_1636291749177_0.4386512700632952"},"_hasShrinkwrap":false},"0.0.4":{"name":"@01group/fxl","version":"0.0.4","description":"fxl.js is a data-oriented JavaScript spreadsheet library. It provides a way to build spreadsheets using modular, lego-like blocks.","homepage":"https://github.com/zero-one-group/fxl.js","dependencies":{"tslib":"^2.0.0","exceljs":"^4.3.0","ts-results":"^3.3.0"},"engines":{"node":">=8.0.0"},"keywords":["curried","data-oriented","fp","functional-programming","spreadsheet","excel","xlsx"],"license":"Apache-2.0","main":"./src/index.js","typings":"./src/index.d.ts","peerDependencies":{},"_id":"@01group/fxl@0.0.4","dist":{"shasum":"616844eb497171b3d16320d61a7c4041c0ef9c4a","integrity":"sha512-ayA8cH6QjpvVX2RxrL9sCmjinzjwr1UF8F0rA4vlON4inP059D0rbXhlRgQZM2hQ4PAbh7iIKoLlZFAAIpPTsA==","tarball":"https://registry.npmjs.org/@01group/fxl/-/fxl-0.0.4.tgz","fileCount":35,"unpackedSize":138131,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCjwZts3hHVP5WAfR1v58YZOtBS0Lfi83q8BgJWMhwHRQIgVFpeFX6QrZmgcvfTgqB5JT9NV12pMRGQpvSyK0aHjSE="}]},"_npmUser":{"name":"anthony-khong","email":"anthony.kusumo.khong@gmail.com"},"directories":{},"maintainers":[{"name":"anthony-khong","email":"anthony.kusumo.khong@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/fxl_0.0.4_1636377263564_0.36374685108965066"},"_hasShrinkwrap":false},"0.0.5":{"name":"@01group/fxl","version":"0.0.5","description":"fxl.js is a data-oriented JavaScript spreadsheet library. It provides a way to build spreadsheets using modular, lego-like blocks.","homepage":"https://github.com/zero-one-group/fxl.js","dependencies":{"exceljs":"^4.3.0","ts-results":"^3.3.0","tslib":"^2.0.0"},"engines":{"node":">=8.0.0"},"keywords":["curried","data-oriented","fp","functional-programming","spreadsheet","excel","xlsx"],"license":"Apache-2.0","main":"./src/index.js","typings":"./src/index.d.ts","peerDependencies":{},"_id":"@01group/fxl@0.0.5","dist":{"shasum":"12b32240075326053947f9a6aeb9040185b402a5","integrity":"sha512-X7IBU28aVdjFztO9WpVeta26Kj0YWmx3Tb/O/FRnnxgP8xMd6NdI22XGCZcC2fHp6XZt8imTq0MGhCOo1QVIPA==","tarball":"https://registry.npmjs.org/@01group/fxl/-/fxl-0.0.5.tgz","fileCount":35,"unpackedSize":138068,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhue02CRA9TVsSAnZWagAAJuYP/ilbhJtabJy4xXpWAFkX\nD78hgUw4fMWTjVYEYrG3WPwsfS5WT+8ZHigiJYNumsTduTcobbvh5ah2Kxi2\nw+VVm58l97mzhR6UNUehRIYAhkGkJmmchDmx+W2cvHQlO/jnC+VlKEzRnZFd\n3zqpJA3AmTLNGQ0zy/WxrnSz6mI9vuedRxK8LdrTX4Gplym0GhDCq5i+l4b5\ni0duYUXH5bFskVZAxvDgsC+2t6ADbuIo5446BmqVQwF4cOAV0rLZCmyQUpIU\n184th2nXVjdxArwRWsXhtjw0/AnU7r4vGJt7A1J5w/wvkvnvkWGJEqme4fyY\nIa6+NqhhoQPsZB9LNBL6rAVo2YIqc+vpfPyfLRRWn9HJEr1pRRmA6mHsBPC1\nCFT/+aOkoNCFhPvE5pMZSYxBJK0+E5LIq4wybbRVGtBxaHmemYoJDkya3Kan\ndnfVCLjbYphEp+JAtMEjb8VJo4WhtpVDMcWPzG5iVhq14IRUHpS9b+mqmTRo\nEJr2zxpPjLwA9+HvJno1QPw0aXqpEvBFHs/oyR4FRWEnGcElBf/AnJaJVG5x\n+z6Rw/niCvus3FnAWCcALXauu5o8L5vYRk/UrjtHxt2IrKrs5VBL1ZB78h1u\nmsxGibqmG3QCMv/fWu1EOBZQ5wUIwsMzsLLHDXChY7t9bh53l0ylXVjuvx0z\nZzAa\r\n=lLSw\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAtMME8e6MQtj+AIDHPuuT6ZxR4dSeiKXKC+66ewcRGDAiEA8iV51xA3qJMQkJqw0eHelkz0Zl4miSB1QCVxTUvGgGU="}]},"_npmUser":{"name":"anthony-khong","email":"anthony.kusumo.khong@gmail.com"},"directories":{},"maintainers":[{"name":"anthony-khong","email":"anthony.kusumo.khong@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/fxl_0.0.5_1636533559984_0.7643543800732098"},"_hasShrinkwrap":false},"0.0.6":{"name":"@01group/fxl","version":"0.0.6","description":"fxl.js is a data-oriented JavaScript spreadsheet library. It provides a way to build spreadsheets using modular, lego-like blocks.","homepage":"https://github.com/zero-one-group/fxl.js","dependencies":{"tslib":"^2.0.0","exceljs":"^4.3.0","ts-results":"^3.3.0"},"engines":{"node":">=8.0.0"},"keywords":["curried","data-oriented","fp","functional-programming","spreadsheet","excel","xlsx"],"license":"Apache-2.0","main":"./src/index.js","typings":"./src/index.d.ts","peerDependencies":{},"_id":"@01group/fxl@0.0.6","dist":{"shasum":"6178133c049ba7e3ac6f1822d430e0d73eb3f626","integrity":"sha512-dc+YKIpWwktUl45gN4zr6sjGnvhKwf/L/rjlR+gFzTfc19NDt6u2T8Kfhc3HCye7OAu+h3x9Coe8pEMgBIFoOQ==","tarball":"https://registry.npmjs.org/@01group/fxl/-/fxl-0.0.6.tgz","fileCount":35,"unpackedSize":143315,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHCZ+WN7WaVPUSkpN/KvKRdjPB7XCfi+n4+AgKIDCxKmAiEAw7JnW6md+QvGXPW6HlQcw96yAU6nb29nmyD78fW4syI="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJieRndACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmoa1g/9GZXeBqAtQrKN4Sux/+g5r4i1bFkJIHByNdrulmDMdYEeAiGS\r\nqJaGFFaHrh6yxjMdZjTlJL0rwfaTaAl7sFVR3PGZIy9uWzVCw40av4aeMWp8\r\nvLpDZ2HTURM2ORYgfzcMqjunTmTHFlD30vo2i6Xdx2rvigieYxXHM+ZZEHl4\r\noszXO/TKQbbyCU1I/TeSAFnynS1n78cfp8pzfu/On7eXnzAsTL3jnUhLiriB\r\nsFcolyDKo4s1iFBm94E0/Ruf71OCgxCWsb8OUdCa1ags7clmI9eb+KqVf7FC\r\nZR6SVBemxX5ntnMo/RpWI0oTUs9msO47bsv5VvzWqrPVLiJLUxjt4dp0C0Vq\r\n1jSa02XZwh3kBb+dcOiutVxkwA5E6pmIGX+np5mmbc6myeyiDx3ZCkhKdnDi\r\n3mjAjGabqGX506wgZD40mmjdfXpYJhKtkAA5sjaUl90ZOulVlgtMTSIKmb3/\r\n98Q7RoLy19FXKWHzIo3S44zD7wN4mKYWZpRnoDzRiGKmWeHiBXJBrn6Ry1tq\r\n2sMIGIrDQaLVw/sjevuLkgPcjRL/1nHQpnay5TaGPu6cEH0ekxQ0/HomIqPm\r\nKiUgJ9fJiTPNiL6hfE1ksRtikmDfqEJd4SIXw9Eb1qWSk3/wL0Tvh79VW5cR\r\nFvjtglJA+EyCdiDaO00XXPjIAdCBarmv+4w=\r\n=36BQ\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"anthony-khong","email":"anthony.kusumo.khong@gmail.com"},"directories":{},"maintainers":[{"name":"rohmad-st","email":"rochmad.26@gmail.com"},{"name":"anthony-khong","email":"anthony.kusumo.khong@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/fxl_0.0.6_1652103645631_0.05212287965554596"},"_hasShrinkwrap":false},"0.0.7":{"name":"@01group/fxl","version":"0.0.7","description":"fxl.js is a data-oriented JavaScript spreadsheet library. It provides a way to build spreadsheets using modular, lego-like blocks.","homepage":"https://github.com/zero-one-group/fxl.js","dependencies":{"tslib":"^2.0.0","exceljs":"^4.3.0","ts-results":"^3.3.0"},"engines":{"node":">=8.0.0"},"keywords":["curried","data-oriented","fp","functional-programming","spreadsheet","excel","xlsx"],"license":"Apache-2.0","main":"./src/index.js","typings":"./src/index.d.ts","peerDependencies":{},"_id":"@01group/fxl@0.0.7","dist":{"shasum":"61d0e862fbe94911f7fb851876fc142fd19daa10","integrity":"sha512-e/9RLtmcipKrbSUYn0hUXWFhWw15UnsYBI8yU+88wCBbj628lAdv73DpxUdSa4iBdcQEOiuOx193kkUv+rOGbQ==","tarball":"https://registry.npmjs.org/@01group/fxl/-/fxl-0.0.7.tgz","fileCount":35,"unpackedSize":143351,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDiZSG9WUAShgCcQMAGklmVLUFl2nh/Jm11py4RIRNTbgIgeWmKND/H2tCXxShsREXG0qLFUB73Y3+KyPS0PYl/uXg="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJigOowACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmr6nw//fO6RZ2Bgs+UDl6okew4SNb98rhATIz0fg53ZrqzhXHSX8ie/\r\nGkdYGnJGouoSmtxhjt5jQaQD8NoeWo9AER1y+ez2rVptzDNaM0S1egwCipND\r\n4J0oArGs57kHJN79MDwaQCc/7oVDH3YWkKuW+Xt8IWPQRnJTEETzajjnIpMo\r\nid33G8J2vfezXgF0vaLYtW1039rxqtKYON6oTTdZvCtmMc16cL9o2T9b0VYL\r\nYULfZ8YQ08RQvzK75cViolNwuezgzF/lz9u0Xz4RHZISrx9l3zZqOSpXjGMG\r\nRhra1UEtopJvf02q37yv+Egildy+WDoXJzErARL1VXBD2lKdAcIGoIfwh5gL\r\n738iFr29oqqkGnUEjXaZ1LrWTumTdzqXZ57Ux8j4OELnNzqSw/H0ZwhVL5s5\r\nRUDFCi8gVIbvRkU3wouBMWzMTxz4AasESHiX1+pL4u72bJNVnSpmeZIPE8ni\r\nigvQCLiZgwxdgzoj2YxyZDz+M1qZIf/WRg98VCczzpmslXJS51lGct9JTTi1\r\nONIgYpT4y++kID899N7yXIT/eFacH8y01IFJ8QoMBIsvOGxqaqCDm9lLh8H4\r\nxUEF/r0t2a5vFJQ48HEn1aIo4g4NY+O6CcZZlJLV8lRijVwGmcDyWf68QTNf\r\nrjsWUk7s2u9soQz0qEsbVQYIilNVnPBc8v0=\r\n=iAAc\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"anthony-khong","email":"anthony.kusumo.khong@gmail.com"},"directories":{},"maintainers":[{"name":"rohmad-st","email":"rochmad.26@gmail.com"},{"name":"anthony-khong","email":"anthony.kusumo.khong@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/fxl_0.0.7_1652615728315_0.9783395955654919"},"_hasShrinkwrap":false}},"time":{"created":"2021-11-07T12:38:17.775Z","0.0.1":"2021-11-07T12:38:17.989Z","modified":"2023-02-22T03:27:21.508Z","0.0.2":"2021-11-07T12:59:00.773Z","0.0.3":"2021-11-07T13:29:09.323Z","0.0.4":"2021-11-08T13:14:23.694Z","0.0.5":"2021-11-10T08:39:20.155Z","0.0.6":"2022-05-09T13:40:45.798Z","0.0.7":"2022-05-15T11:55:28.474Z"},"maintainers":[{"email":"riipandi@gmail.com","name":"riipandi"},{"email":"mandaputra8@gmail.com","name":"mandaputtra"},{"email":"rubiagatra@gmail.com","name":"rubiagatra"},{"email":"anthony.kusumo.khong@gmail.com","name":"anthony-khong"}],"description":"fxl.js is a data-oriented JavaScript spreadsheet library. It provides a way to build spreadsheets using modular, lego-like blocks.","homepage":"https://github.com/zero-one-group/fxl.js","keywords":["curried","data-oriented","fp","functional-programming","spreadsheet","excel","xlsx"],"license":"Apache-2.0","readme":"<p align=\"center\">\n    <img src=\"https://github.com/zero-one-group/fxl.js/raw/develop/logo/fxl.png\" width=\"375px\">\n</p>\n\n_fxl.js_ (_/ˈfɪk.səl/_ or \"pixel\" with an f) is a **data-oriented** JavaScript spreadsheet library built on top of [ExcelJS](https://github.com/exceljs/exceljs). The library focuses on **composability**, and aims to provide a way to build spreadsheets using modular, lego-like blocks. Its primary use case is for building spreadsheets based on human-designed templates that are not tabular.\n\n_fxl.js_ is a JavaScript adaptation of the original Clojure library [fxl](https://github.com/zero-one-group/fxl).\n\n# Contents\n\n<ul>\n  <li><a href=\"#installation\">Installation</a></li>\n  <li><a href=\"#why-fxljs\">Why <i>fxl.js?</i></a></li>\n  <li><a href=\"#examples\">Examples</a></li>\n    <ul>\n      <li><a href=\"#cells-as-plain-data\">Cells as Plain Data</a></li>\n      <li><a href=\"#creating-a-spreadsheet-the-wrong-way\">Creating a Spreadsheet (The Wrong Way)</a></li>\n      <li><a href=\"#loading-a-spreadsheet\">Loading a Spreadsheet</a></li>\n      <li><a href=\"#coordinate-shortcuts\">Coordinate Shortcuts</a></li>\n      <li><a href=\"#style-shortcuts\">Style Shortcuts</a></li>\n      <li><a href=\"#putting-things-together\">Putting Things Together</a></li>\n   </ul>\n  <li><a href=\"#known-issues\">Known Issues</a></li>\n  <li><a href=\"#further-resources\">Further Resources</a></li>\n  <li><a href=\"#license\">License</a></li>\n</ul>\n\n# Installation\n\n```\nnpm install @01group/fxl\n```\n\nThe TypeDoc generated documentation can be found [here](https://zero-one-group.github.io/fxl.js/modules.html).\n\n# Why _fxl.js_?\n\nThere are three things that _fxl.js_ tries to do differently compared to other JavaScript spreadsheet libraries, namely:\n\n1. **immutability:** the entire API requires no side effects or mutations except for the IO operations at the very start or end for reading and writing the spreadsheets respectively. With _fxl.js_, it is more ergonomic to work with data and pure functions until near the end of the application, where all the side effects are isolated and happen in one go - see [Functional Core, Imperative Shell](https://www.destroyallsoftware.com/screencasts/catalog/functional-core-imperative-shell).\n2. **data orientation:** the data model is represented as plain, nested JavaScript objects with literal child nodes. This allows us to reuse common JavaScript functions/methods to manipulate objects, and easily integrate _fxl.js_ with functional utility libraries such as [Lodash](https://lodash.com/) and [Ramda](https://ramdajs.com/) - see [Alan Perlis' Epigram on common functions](https://stackoverflow.com/questions/6016271/why-is-it-better-to-have-100-functions-operate-on-one-data-structure-than-10-fun).\n3. **cells as unordered collections of objects:** by expressing value, coordinate and style as three separate, orthogonal properties, we can work on the three components that make up spreadsheet separately. We can deal with interactions of the components only when we put them together. Expressing columns and rows as ordered sequences introduces complexity - see [Rich Hickey's take on the list-and-order problem](https://youtu.be/rI8tNMsozo0?t=1446).\n\n_fxl.js_ is not built with performance in mind. It is built on top of ExcelJS, which thus sets the performance limit for the library. _fxl.js_ shines at building spreadsheets based on human-designed templates, which typically do not translate well to tabular formats such as CSVs, records or nested lists.\n\n# Examples\n\n## Cells as Plain Data\n\nA _fxl.js_ cell is an object with three properties, namely value, coordinate and optionally style. The following are valid cells:\n\n```typescript\n{ value: 'abc', coord: { row: 0, col: 0 } }\n\n{\n  value: 1.23,\n  coord: { row: 2, col: 3, sheet: 'Sheet 1' },\n  style: {\n    numFmt: '0.00%',\n    border: {\n      right: { style: 'medium', color: { argb: 'FF00FF00' } },\n      left: { style: 'medium', color: { argb: 'FF00FF00' } },\n    },\n    font: { name: 'Roboto', size: 16, bold: true },\n  },\n}\n```\n\nBy understanding the `fxl.Cell` interface, you are very close to being very productive with _fxl.js_! The rest of the library is composed of IO functions (such as `fxl.readXlsx` and `fxl.writeXlsx`) and shortcut functions that make life very easy when massaging the cell objects.\n\nTo find out more about _fxl.js_' cell interface, see [the interface declaration](packages/core/src/lib/types.ts) and [ExcelJS' cell value and style](https://github.com/exceljs/exceljs/blob/master/index.d.ts).\n\n\n## Creating a Spreadsheet (The Wrong Way)\n\nLet's suppose that we would like to create a plain spreadsheet such as the following:\n\n```\n| Item     | Cost     |\n| -------- | -------- |\n| Rent     | 1000     |\n| Gas      | 100      |\n| Food     | 300      |\n| Gym      | 50       |\n| Total    | 1450     |\n```\n\nfrom an existing JavaScript array of objects such as the following:\n\n```typescript\nconst costs = [\n  { item: \"Rent\", cost: 1000 },\n  { item: \"Gas\", cost: 100 },\n  { item: \"Food\", cost: 300 },\n  { item: \"Gym\", cost: 50 },\n];\n```\n\nWe would break the spreadsheet down into three components, namely the header, the body and the total. The following is not the prettiest piece of code (and not the recommended way of using _fxl.js_), but it would work:\n\n```typescript\nconst headerCells = [\n  { value: 'Item', coord: { row: 0, col: 0 } },\n  { value: 'Cost', coord: { row: 0, col: 1 } },\n];\n\nconst bodyCells = costs.flatMap((record, index) => {\n  return [\n    { value: record.item, coord: { row: index + 1, col: 0 } },\n    { value: record.cost, coord: { row: index + 1, col: 1 } },\n  ];\n});\n\nconst totalCells = [\n  { value: 'Total', coord: { row: costs.length + 2, col: 0 } },\n  {\n    value: costs.map((x) => x.cost).reduce((x, y) => x + y),\n    coord: { row: costs.length + 2, col: 1 },\n  },\n];\n```\n\nWe then concatenate them, and ask _fxl.js_ to write the cells into an XLSX file:\n\n```typescript\nimport * as fxl from '@01group/fxl';\n\nconst allCells = headerCells.concat(bodyCells).concat(totalCells);\nawait fxl.writeXlsx(allCells, 'costs.xlsx')\n```\n\nThe above summarises the essence of spreadsheet building with _fxl.js_. It is about taking a piece of data, transform it into the cell objects before finally calling an IO function.\n\n## Loading a Spreadsheet\n\n```typescript\nconst cells = await fxl.readXlsx('costs.xlsx')\n```\n\n## Coordinate Shortcuts\n\nAn important part of _fxl.js_ is the collection of shortcut functions that makes it easy to create the cell objects. We can boil down the above example to the following:\n\n```typescript\nimport * as fxl from '@01group/fxl';\n\nconst costs = [\n  { item: \"Rent\", cost: 1000 },\n  { item: \"Gas\", cost: 100 },\n  { item: \"Food\", cost: 300 },\n  { item: \"Gym\", cost: 50 },\n];\nconst totalCost = costs.map((x) => x.cost).reduce((x, y) => x + y);\n\nconst headerCells = fxl.rowToCells([\"Item\", \"Cost\"]);\nconst bodyCells = fxl.recordsToCells([\"item\", \"cost\"], costs);\nconst totalCells = fxl.rowToCells([\"Total\", totalCost]);\nconst allCells = fxl.concatBelow(headerCells, bodyCells, totalCells);\n\nawait fxl.writeXlsx(allCells, 'costs.xlsx')\n```\n\n_fxl.js_ provides shortcuts for creating rows, cells and tables from plain values (such as `fxl.rowToCells`, `fxl.colToCells`, `fxl.tableToCells` and `fxl.recordToCells`), as well as shortcuts for combining groups of cells together (such as `fxl.concatRight` and `fxl.concatBelow`). This allows us to break down a big spreadsheet into very small components, and only to put them together later at a higher level of abstraction.\n\n## Style Shortcuts\n\nLet's suppose that we would like to style our simple spreadsheet as follows:\n* The header row's font should be bold with a light gray background.\n* The footer row should be the same as the header row, but with a dark red font colour.\n* The item column of the body should be in italic.\n* All cells should be horizontally aligned center.\n\nIn this case, we would take each bullet point into its own function, and apply it to the right cell components:\n\n```typescript\nfunction setHeaderStyle(cell: fxl.Cell): fxl.Cell {\n  return fxl.pipe(cell, fxl.setBold(true), fxl.setSolidFg('light_gray'));\n}\n\nfunction setTotalStyle(cell: fxl.Cell): fxl.Cell {\n  return fxl.pipe(cell, setHeaderStyle, fxl.setFontColor('dark_red'));\n}\n\nfunction setBodyStyle(cell: fxl.Cell): fxl.Cell {\n  if (cell.coord.col == 0) {\n    return fxl.setItalic(true)(cell);\n  } else {\n    return cell;\n  }\n}\n\nconst allCells = fxl\n  .concatBelow(\n    headerCells.map(setHeaderStyle),\n    bodyCells.map(setBodyStyle),\n    totalCells.map(setTotalStyle)\n  )\n  .map(fxl.setHorizontalAlignement('center'));\n```\n\nNotice that _fxl.js_ comes with a few handy higher-order functions in order to facilitate function compositions, such as `fxl.pipe` and `fxl.compose`.\n\n## Putting Things Together\n\nWhen we put our running example together, we actually see a relatively common pattern when building spreadsheets with _fxl.js_. In general, when building a spreadsheet using _fxl.js_, we follow a number of high-level steps:\n\n1. prepare the **data** to be used as cell values;\n2. build small **spreadsheet components** with those values;\n3. prepare the **styles** of each component;\n4. put together the styled components in their **relative coordinates**; and\n5. finally executing the **IO** operation.\n\n```typescript\nimport * as fxl from '@01group/fxl';\n\n// ------------------------------------------------------------------\n// data\n// ------------------------------------------------------------------\nconst costs = [\n  { item: \"Rent\", cost: 1000 },\n  { item: \"Gas\", cost: 100 },\n  { item: \"Food\", cost: 300 },\n  { item: \"Gym\", cost: 50 },\n];\nconst totalCost = costs.map((x) => x.cost).reduce((x, y) => x + y);\n\n// ------------------------------------------------------------------\n// spreadsheet components\n// ------------------------------------------------------------------\nconst headerCells = fxl.rowToCells([\"Item\", \"Cost\"]);\nconst bodyCells = fxl.recordsToCells([\"item\", \"cost\"], costs);\nconst totalCells = fxl.rowToCells([\"Total\", totalCost]);\nconst allCells = fxl.concatBelow(headerCells, bodyCells, totalCells);\n\n// ------------------------------------------------------------------\n// styles\n// ------------------------------------------------------------------\nfunction setHeaderStyle(cell: fxl.Cell): fxl.Cell {\n  return fxl.pipe(cell, fxl.setBold(true), fxl.setSolidFg('light_gray'));\n}\n\nfunction setTotalStyle(cell: fxl.Cell): fxl.Cell {\n  return fxl.pipe(cell, setHeaderStyle, fxl.setFontColor('dark_red'));\n}\n\nfunction setBodyStyle(cell: fxl.Cell): fxl.Cell {\n  if (cell.coord.col == 0) {\n    return fxl.setItalic(true)(cell);\n  } else {\n    return cell;\n  }\n}\n\n// ------------------------------------------------------------------\n// relative coordinates\n// ------------------------------------------------------------------\nconst allCells = fxl\n  .concatBelow(\n    headerCells.map(setHeaderStyle),\n    bodyCells.map(setBodyStyle),\n    totalCells.map(setTotalStyle)\n  )\n  .map(fxl.setHorizontalAlignement('center'));\n\n// ------------------------------------------------------------------\n// IO\n// ------------------------------------------------------------------\nawait fxl.writeXlsx(allCells, 'costs.xlsx')\n```\n\nSee also the [inventory-spreadsheet walkthrough](guides/walkthrough.md) and its [accompanying script](packages/example/src/main.ts) for a more detailed example based on a real use case.\n\n# Known Issues\n\n* Column widths and row heights are not persisted after writing the spreadsheet. Loading an existing spreadsheet will contain no information regarding column widths and row heights.\n\nSee also [ExcelJS' known issues](https://github.com/exceljs/exceljs#known-issues).\n\n# Contributing\n\n_fxl.js_ is very much a work-in-progress. Whilst it is being used in production at [Zero One Group](www.zero-one-group.com), it may not be stable just yet. We would love your help to make it production ready! Any sort of contributions (issues, pull requests or general feedback) are all very welcomed!\n\nSee the [contributing document](CONTRIBUTING.md).\n\n# Further Resources\n\n* [**fxl - composable data-oriented spreadsheet library for Clojure**](https://www.youtube.com/watch?v=d6qOzPQ9NUk) is a talk by one of the authors of `fxl.js` gave, which includes the inspiration and thinking behind the original Clojure library.\n\n# License\n\nCopyright 2021 Zero One Group.\n\n_fxl.js_ is licensed under Apache License v2.0. It means that \"users can do (nearly) anything they want with the code, with very few exceptions\". See [here](https://fossa.com/blog/open-source-licenses-101-apache-license-2-0/) for more information.\n","readmeFilename":"README.md"}