{"_id":"@abradley2/frpuccino","_rev":"3-09175de12cd73614dbf29a95438bb663","name":"@abradley2/frpuccino","dist-tags":{"latest":"1.0.0-alpha.3"},"versions":{"1.0.0-alpha.1":{"name":"@abradley2/frpuccino","version":"1.0.0-alpha.1","description":"A lightweight reactive UI library built on @most/core","main":"frpuccino.umd.js","scripts":{"build":"browserify ./src/index.ts -p tsify -p tinyify -t [ bubleify ] -s frpuccino -u @most/core -u @most/scheduler -u @most/types -d | exorcist frpuccino.umd.js.map > frpuccino.umd.js","sourcemaps":"exorcist frpuccino.umd.js","test":"echo \"Error: no test specified\" && exit 1","lint":"eslint --fix ./src/**/*.ts"},"author":{"name":"Tony Bradley"},"license":"MIT","peerDependencies":{"@most/core":"1.x","@most/scheduler":"1.x","@most/types":"1.x"},"devDependencies":{"@most/core":"^1.5.0","@most/scheduler":"^1.2.3","@most/types":"^1.0.2","@types/node":"^13.1.1","@typescript-eslint/eslint-plugin":"^2.6.1","@typescript-eslint/parser":"^2.13.0","browserify":"^16.5.0","buble":"^0.19.8","bubleify":"^1.2.1","eslint":"^6.6.0","exorcist":"^1.0.1","standardx":"^5.0.0","tinyify":"^2.5.2","tsify":"^4.0.1","typescript":"^3.7.4"},"dependencies":{"@abradley2/url-change-event":"^1.0.1","mitt":"^1.2.0","morphdom":"^2.5.10"},"eslintConfig":{"env":{"browser":true},"extends":["standard"],"parser":"@typescript-eslint/parser","rules":{"no-unused-vars":"off","@typescript-eslint/no-unused-vars":"off"}},"standardx":{"parser":"@typescript-eslint/parser","plugins":["@typescript-eslint/eslint-plugin"]},"repository":{"type":"git","url":"git+https://github.com/abradley2/stream-element.git"},"bugs":{"url":"https://github.com/abradley2/stream-element/issues"},"homepage":"https://github.com/abradley2/stream-element#readme","gitHead":"85fa3a70e7a943ffee65a16048036bc997b8901d","_id":"@abradley2/frpuccino@1.0.0-alpha.1","_nodeVersion":"12.14.0","_npmVersion":"6.13.4","dist":{"integrity":"sha512-e3hMHqGxMENFmIcC6k9WaOqufkFrizHliKKube9QziPqtkwn+29z0xseI9a3TjBGjLW8BdOKXfAB2+twVsjEAg==","shasum":"c08b0e1896e55db0b90ea604c815fdbdc734ff32","tarball":"https://registry.npmjs.org/@abradley2/frpuccino/-/frpuccino-1.0.0-alpha.1.tgz","fileCount":13,"unpackedSize":114149,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeDq/QCRA9TVsSAnZWagAAmawQAI/o60zksW+as0f8Mmyr\nj0JohLBXAoWxCDOuE44rCH4WanwJp06ff64RYjvzjbKEm111eON5rU3dC19d\nbu20Gaoi+GuNCq8p4zSHWoCezkKUixGTQaJjljrpEyYf84J3izzCh0Wm8l7z\nN7kNHQ4A7jKpyM5jFz1g/ntuExn3C31keInqKmeo/9zGi8xQXB/ka1SfL7q2\nHYiKMfMwvD2guBE+ZSmpCtWGsceQlAfSz68Lcg4ggizjOzprQtDRMHWFFVKR\n4FjyxSZ4CtVK6h8v057o8yB2EPRpTFq4LPPkL2mQONfAV3vmlvyvsYD785VV\nGMaJD4WKIZvsQ5cXOGfgOZdxvAZSmAasu3JTDc3Bq63mcujM5WdzgU0ajbgb\nVNc8RIGoZt64xL/DeRP1jWWhyA6377N1CsL62doiv1zuIZGj6VVWjhHK631u\nOaIzEIlFxBF1DBP+/bjcXAb3mg7Ja3miDkBdn1ZPQyEmr8QSgjZVm1r1M3CD\nYlaJY1paijkSJ0OdxYBPaWJ4WU/PQnG9Hi57q3B8DbwjOOFFvkUKAhBsiHiZ\nr5Cc3zIflXJqkzjMF5EaTHDVmuV2XWdkUZx5dZHU1YxxBysZzhNwFfvK+i7k\nuoQsuJwwGh0MglSJkLbHqV4FB5cpteUfYU325O9Hx3u5Um+23hnpD/xi4zBh\nW1eP\r\n=Hk8E\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCU+8jJCYIVSdFcmp67lAvsVa0F3Bwtf464u3MQgZYSkAIhAJfhJGTB52bwnoSzQK5Z7/MKfQFN9LNndq2RY6n7vhO7"}]},"maintainers":[{"name":"abradley2","email":"antbradley91@gmail.com"}],"_npmUser":{"name":"abradley2","email":"antbradley91@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/frpuccino_1.0.0-alpha.1_1578020816068_0.000012292588003948168"},"_hasShrinkwrap":false},"1.0.0-alpha.2":{"name":"@abradley2/frpuccino","version":"1.0.0-alpha.2","description":"A lightweight reactive UI library built on @most/core","main":"frpuccino.umd.js","scripts":{"build":"browserify ./src/index.ts -p tsify -p tinyify -t [ bubleify ] -s frpuccino -u @most/core -u @most/scheduler -u @most/types -d | exorcist frpuccino.umd.js.map > frpuccino.umd.js","test":"parcel serve ./test/index.html","lint":"eslint --fix ./src/**/*.ts"},"author":{"name":"Tony Bradley"},"license":"MIT","peerDependencies":{"@most/core":"1.x","@most/scheduler":"1.x","@most/types":"1.x"},"devDependencies":{"@most/core":"^1.5.0","@most/scheduler":"^1.2.3","@most/types":"^1.0.2","@types/node":"^13.1.1","@types/tape":"^4.2.33","@typescript-eslint/eslint-plugin":"^2.6.1","@typescript-eslint/parser":"^2.13.0","browserify":"^16.5.0","buble":"^0.19.8","bubleify":"^1.2.1","eslint":"^6.6.0","exorcist":"^1.0.1","highland":"^2.13.5","parcel":"^1.12.4","standardx":"^5.0.0","tape":"^4.12.1","tinyify":"^2.5.2","tsify":"^4.0.1","typescript":"^3.7.4"},"dependencies":{"@abradley2/url-change-event":"^1.0.1","mitt":"^1.2.0","morphdom":"^2.5.10"},"eslintConfig":{"env":{"browser":true},"extends":["standard"],"parser":"@typescript-eslint/parser","rules":{"no-unused-vars":"off","@typescript-eslint/no-unused-vars":"off"}},"standardx":{"parser":"@typescript-eslint/parser","plugins":["@typescript-eslint/eslint-plugin"]},"repository":{"type":"git","url":"git+https://github.com/abradley2/stream-element.git"},"bugs":{"url":"https://github.com/abradley2/stream-element/issues"},"homepage":"https://github.com/abradley2/stream-element#readme","gitHead":"98c091821af338196304d0d0833232df0615a89c","_id":"@abradley2/frpuccino@1.0.0-alpha.2","_nodeVersion":"12.14.0","_npmVersion":"6.13.4","dist":{"integrity":"sha512-BnxBUQowzYy2R00YUsilmtsEpPPB4+EmGBXJTQNktWnCncNFcd3LFG4wC1F9wzNDckuWe0EEx3St0z35osvOLA==","shasum":"4fb0849959c481fbc5053aee12259a3e5d15deaa","tarball":"https://registry.npmjs.org/@abradley2/frpuccino/-/frpuccino-1.0.0-alpha.2.tgz","fileCount":15,"unpackedSize":113746,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeEOpcCRA9TVsSAnZWagAA1ZkP/3KwejI5i8x2zuZ2bz2T\nuC9gz8s3Aua9hNpAFUSyBTlU5iqKBKOUAfART5+6IPrmG/4uWxYv6hPLNkvw\nPUoAzci4hmW7G7Ho1uYohvAyOIDhyhJVDfIE79G/xAPxWptQaUNh9zsMeLT1\nc6xfGPoNa+ZzmrCL5+zUrn05g6TKRYMuCxien/HUjHosH66HWZzZldw0bTFW\nDV2MiuBD+jKhAOFIHE4MRV4pmWp7BU4Gsja4HYbZ/sROD9LeudFxzsTsiuZF\njGOzy31rK00dZnFDfv50ZK6skpCUKNSmUtm8501TXaOzkdrlmD1VXgXYQdXO\npN6QvnW+jkzafTjm1FwDwbhj0GX0naEb7hVGF5uGZSq59GuJaYPEEHbfCeMB\nUH9mPCFCHsVPQ/DDTeds4bZ6JInZO0Nig7UdQL/ToJYqu7fCflkJ/nrvqmkZ\nSbU5a/cPRLRhv44Yc7SWshsrUcKe4O7vwxe29p6WXiy0GYeLllM+LIts7H1e\nBnXGDyO1Xc0c1lIsjEzdoxoru7C7zP6LuzuLFKe8lalVTr/xsjdVXAEPAv59\nzRhILLhy/iQv0rUamfGOhXOd9FeXpyMDNgkAixLFk7TBqB6/rnH1igNDoBiX\nDWPIJC7vVdmdqFWbUxRiSff+ko6/YMOwllRdn55Nvssuiw5o2FAKTTkgta4Q\n7ZPS\r\n=s4vo\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCnxuU2K9a/9isHIA5G6SS4xVHrU6yvP7tH5W7FoECkpQIhAPZzaeWT5UPV9cedh4id1VWyVXLFsDbtPq4FPROIfc3V"}]},"maintainers":[{"name":"abradley2","email":"antbradley91@gmail.com"}],"_npmUser":{"name":"abradley2","email":"antbradley91@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/frpuccino_1.0.0-alpha.2_1578166875575_0.6385411927444042"},"_hasShrinkwrap":false},"1.0.0-alpha.3":{"name":"@abradley2/frpuccino","version":"1.0.0-alpha.3","description":"A lightweight reactive UI library built on @most/core","main":"frpuccino.umd.js","scripts":{"build":"browserify ./src/index.ts -p tsify -p tinyify -t [ bubleify ] -s frpuccino -u @most/core -u @most/scheduler -u @most/types -d | exorcist frpuccino.umd.js.map > frpuccino.umd.js","test":"parcel serve ./test/index.html --open","lint":"eslint --fix ./src/**/*.ts"},"author":{"name":"Tony Bradley"},"license":"MIT","peerDependencies":{"@most/core":"1.x","@most/scheduler":"1.x","@most/types":"1.x"},"devDependencies":{"@most/core":"^1.5.0","@most/scheduler":"^1.2.3","@most/types":"^1.0.2","@types/node":"^13.1.1","@types/tape":"^4.2.33","@typescript-eslint/eslint-plugin":"^2.6.1","@typescript-eslint/parser":"^2.13.0","browserify":"^16.5.0","buble":"^0.19.8","bubleify":"^1.2.1","eslint":"^6.6.0","exorcist":"^1.0.1","highland":"^2.13.5","parcel":"^1.12.4","standardx":"^5.0.0","tape":"^4.12.1","tinyify":"^2.5.2","tsify":"^4.0.1","typescript":"^3.7.4"},"dependencies":{"@abradley2/url-change-event":"^1.0.1","mitt":"^1.2.0","morphdom":"^2.5.10"},"eslintConfig":{"env":{"browser":true},"extends":["standard"],"parser":"@typescript-eslint/parser","rules":{"no-unused-vars":"off","@typescript-eslint/no-unused-vars":"off"}},"standardx":{"parser":"@typescript-eslint/parser","plugins":["@typescript-eslint/eslint-plugin"]},"repository":{"type":"git","url":"git+https://github.com/abradley2/stream-element.git"},"bugs":{"url":"https://github.com/abradley2/stream-element/issues"},"homepage":"https://github.com/abradley2/stream-element#readme","gitHead":"0d9a7ae65488f86f5bafaf0c99c646e034641beb","_id":"@abradley2/frpuccino@1.0.0-alpha.3","_nodeVersion":"12.14.0","_npmVersion":"6.13.4","dist":{"integrity":"sha512-SsJbD/yFtrdtK+E55huV4UGYLvWyJ6hiH9UY6wk94kvLsrcGWqGsazsydQ2CTIVFObkOUFaouG4c+IUx5Q6QKA==","shasum":"20119482971ccc93e7c4991c58900dd8476eac19","tarball":"https://registry.npmjs.org/@abradley2/frpuccino/-/frpuccino-1.0.0-alpha.3.tgz","fileCount":15,"unpackedSize":114727,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeEkb5CRA9TVsSAnZWagAAzcYP/3dEZNpU9NANqp6yKhni\ns0/F8ueKN+IWwyyWHI0X2DZ+WLaUbCn6hbVikMGRSIwjvGUwtwZwCkoPQQqN\n4YNRn4Jld5qztqX/OppleJn2GLMHmIFsPS4wwbpVTUAhMDVAJ8H4IA7jpaek\nY+QjyNduSteF07FTO2h4NsbuWWoNjBCWrsOMhhK9a/asrMis8uSawJ0BlINU\nCNEZ8C45k8l26mMxGic2QzJ3EXgaRJpKV/UqLlWGKPITsxGE9BdyyP/pJGoN\ng8mVb8HFa12WThrY1xjtr+ox71bshcckalAA2ZR0o8tf+MFfqqFoLW/DjsEk\ni+QXufpiMLYgoYcceruwgILvXcM2YM/i2/s8HW6TnNrlzB5ftT9sZG9ijszu\nItfnASKKbJ8JuRWdqvwjTQsmaGUi6ANhcHDoTmRg1POn4Wnyy6espka2SRB3\nLQzRp7JKI8jsK0EDk2/vREoEsopFsFBsBfoYRsa0aB1jVDd8Dyf7lYlWiGu1\n728EX3V+hhndP1Y/yjBmhCTT0t1Fd6wWwwPZUHeTIJMd4lTk9qPpVdKAsGgj\ndsaSAe4aG5yrcidmxjlRYqyMG+xPehybCy94WGMg44tpU3dQlFY+8M/1vtir\nbzlrZzn0lXd0XH+vdwVuEWcA4Q5rTMyi0cOdK8yeTpDEbWnDcxRcn5aNb+7E\nHqfu\r\n=FAXD\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD/NteP8ojiruLFxHIJfBm0KpresmUPvVe6NrAIJlcM6gIgBG0SbecKz2r8nba3QXDyk13qtjyYBXgCPdvMDKmAd54="}]},"maintainers":[{"name":"abradley2","email":"antbradley91@gmail.com"}],"_npmUser":{"name":"abradley2","email":"antbradley91@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/frpuccino_1.0.0-alpha.3_1578256121413_0.7150899037481928"},"_hasShrinkwrap":false}},"time":{"created":"2020-01-03T03:06:56.039Z","1.0.0-alpha.1":"2020-01-03T03:06:56.191Z","modified":"2022-04-04T11:01:37.547Z","1.0.0-alpha.2":"2020-01-04T19:41:15.752Z","1.0.0-alpha.3":"2020-01-05T20:28:41.542Z"},"maintainers":[{"name":"abradley2","email":"antbradley91@gmail.com"}],"description":"A lightweight reactive UI library built on @most/core","homepage":"https://github.com/abradley2/stream-element#readme","repository":{"type":"git","url":"git+https://github.com/abradley2/stream-element.git"},"author":{"name":"Tony Bradley"},"bugs":{"url":"https://github.com/abradley2/stream-element/issues"},"license":"MIT","readme":"# FRPuccinno\r\n\r\n:warning: This is still in alpha development. I would love to get more people\r\ntesting this out and finding issues to be stamped out, but I wouldn't recommend\r\nusing this on any big projects that require a reliable view layer just yet! :warning:\r\n\r\nFRPuccino is a small UI library built on the foundation of [Most.js](https://github.com/mostjs/core)\r\n\r\nIt's inspired heavily by [Elm](https://elm-lang.org/) and [Cycle.js](https://cycle.js.org/)\r\n\r\nHere's a short \"counter\" example:\r\n```\r\nimport { createElement, createApplication } from '@abradley2/frpuccino'\r\n\r\nfunction update (model, addValue) {\r\n  return model + addValue\r\n}\r\n\r\nfunction view () {\r\n  return <div>\r\n    <button onclick={1}>Clicked {value} times!</button>\r\n  </div>\r\n}\r\n\r\ncreateApplication({\r\n  mount: document.getElementById('app'),\r\n  update,\r\n  view,\r\n  init: 0\r\n}).run(0)\r\n```\r\n\r\n## Installation\r\n\r\n[@most/core](https://github.com/mostjs/core) and a few other associated libraries\r\nare peer dependencies.\r\n\r\n\r\n`npm install --save @most/core @most/scheduler @most/types @abradley2/frpuccino`\r\n\r\n\r\nYou will also likely find [@most/dom-event](https://github.com/mostjs/dom-event)\r\nand [@most/adaptor](https://github.com/mostjs/adapter) very useful. But only add\r\nthem as you find the need. I do recommend checking out the README of each so you\r\ncan recognize when that need arises.\r\n\r\n## Core Concepts\r\n\r\nYou do not actually need to be \r\n[familiar with FRP](https://www.youtube.com/watch?v=Agu6jipKfYw)\r\nto make use of\r\nFRPuccino. Reactive Programming is more the underlying engine of the API than\r\nthe API itself. It will be very helpful, however, if you are familiar with the\r\nconcepts of\r\n[Streams](https://mostcore.readthedocs.io/en/latest/api.html#stream)\r\nand\r\n[Sinks](https://mostcore.readthedocs.io/en/latest/api.html#sink).\r\n\r\n## API Usage and Tutorial\r\n\r\nOnly two methods are needed to create basic applications:\r\n`createElement` and `createApplication`\r\n\r\n## Function: `createElement`\r\n\r\n`createElement` is _FRPuccino's_ \"React.createElement\" drop-in replacement.\r\n\r\nThis createElement is unique. It returns an un-mounted DOM element, with\r\na `Stream` consisting of all bound event handlers.\r\n\r\nHere's a short illustrative example\r\n```tsx\r\n/** @jsx createElement */\r\nimport { createElement } from '@abradley2/frpuccino'\r\nimport { newDefaultScheduler } from '@most/scheduler'\r\n\r\nconst el = <div>\r\n  <button onclick='Hello there'>Say Hello</button>\r\n  <button onclick='Farewell for now!'>Say Goodbye</button>\r\n</div>\r\n\r\ndocument.body.appendChild(el)\r\n\r\nconst sink = {\r\n  event: (t, message) => { alert(message) },\r\n  end: () => {},\r\n  error: () => {}\r\n}\r\n\r\nel.eventStream.run(sink, newDefaultScheduler())\r\n```\r\n\r\nOur `el` above is a simple `Element` that we can append to our document.\r\nBut `createElement` also casts all the registered event handlers on that\r\n`Element` and all it's children to a single `eventStream`\r\n(or `Stream<Action>`) at the top node.\r\n\r\nWe can run this stream similar to how we'd run any regular\r\n[@most/core stream](https://mostcore.readthedocs.io/en/latest/api.html#running)\r\n\r\nBecause all our event handlers are bound to strings the type of the event stream\r\nis `Stream<string>`. \r\n\r\n## Function: `createApplication`\r\n\r\n`createElement` is cool, but by itself we can't really create complicated \r\nuser interfaces. `createApplication` is a way of \"looping\" the\r\n`eventStream` returned by `createElement` into an `update` function.\r\n\r\nThis cycle of `update` -> `event` -> `createElement` -> `update` forms the\r\nbasic flow of all applications.\r\n\r\n```tsx\r\ncreateApplication({\r\n  // this is our initial update value!\r\n  init: 0,\r\n\r\n  // this is what our user interface looks\r\n  view: (currentState) =>(<div>\r\n    <button onclick={1}>Clicked {currentState} times</button>\r\n  </div>),\r\n\r\n  update: (currentState, value) => currentState + value,\r\n\r\n  // we need a place to attach our view to the document\r\n  mount: document.getElementById('application')\r\n})\r\n  // to kick off the stream we need to emit an initial value.\r\n  // here we emit \"0\" because we won't want to increment our state\r\n  // until the user actually clicks the button\r\n  .run(0)\r\n```\r\n\r\n## Type: `TaskCreator<Action>`\r\n\r\nOur examples up until now have only dealt with event handlers bound\r\nin our view. What if we want to execute and respond to an HTTP request?\r\nWhat if we want to listen to an event that is scoped outside of our view\r\n(such as `window.onscroll`)? We can use \r\n[Tasks](https://mostcore.readthedocs.io/en/latest/api.html#tasks) for this.\r\n\r\nTasks are helper functions that allow us to propagate events to `Sinks`\r\n\r\nWhen we call `createApplication` an\r\ninternal [Sink](https://mostcore.readthedocs.io/en/latest/api.html#sink)\r\nis created which does a couple things. It subscribes to the `Stream` of\r\nevents returned by our `view` and `update` functions, \r\nand the resulting DOM nodes created by composing `update` with `view`.\r\nThe definition is similar to \r\n\r\n```tsx\r\nSink<{eventStream: Stream<{action: Action}>, view?: Element}>\r\n```\r\n\r\nA \"Task Creator\" that creates a \r\n[Scheduled Task](https://mostcore.readthedocs.io/en/latest/api.html#scheduledtask)\r\nto propagate events to this `Sink` will\r\nlook something like this:\r\n```tsx\r\nimport { TaskCreator } from '@abradley2/frpuccino'\r\nimport { now, propagateEventTask } from '@most/core'\r\nimport { asap } from '@most/scheduler'\r\n\r\nexport function propagateEvent <Action> (action: Action): TaskCreator<Action> {\r\n  const event = { eventStream: now({ action }) }\r\n\r\n  return (sink, scheduler) => {\r\n    const task = propagateEventTask(event, sink)\r\n\r\n    return asap(task, scheduler)\r\n  }\r\n}\r\n```\r\n\r\n## Type: `UpdateResult<Model, Action>`\r\n\r\nThe main `update` function is allowed to return more than just the next version\r\nof the `Model`. It may also return an array consiting of the model as the first\r\nitem, and either `TaskCreator<Action>` or `TaskCreator<Action>[]` as the\r\nsecond item.\r\n\r\nWe can change our original `update` function so when our application starts,\r\nwe use our `propagateEvent` function to start us out with counter incrementing \r\nonce by a value of \"1\"\r\n\r\n```tsx\r\nfunction update (currentState, value) {\r\n  // recall that we specified \"0\" as our initial action to dispatch when\r\n  // our application starts.\r\n  if (value === 0) {\r\n    return [currentState, propagateEvent(1)]\r\n  }\r\n\r\n  return currentState + value\r\n}\r\n```\r\n\r\n`UpdateResult<Model, Action>` is very flexible. We can not only give a single\r\nscheduled task to be executed as a result of update, but many.\r\n\r\n```tsx\r\nif (value === 0) {\r\n  return [\r\n    currentState,\r\n    [\r\n      propagateEvent(1),\r\n      propagateEvent(1)\r\n    ]\r\n  ]\r\n}\r\n```\r\n\r\n## Method: `mapElement`\r\n\r\nSimilar to how we can `map` a `Stream` from `Stream<A> -> Stream<B>`\r\nwe can use `mapElement` to convert the `eventStream` of one element\r\nto another `Stream` type. This is useful to avoid cases where\r\ndue to composing many different modular features we end up with\r\ntypes like `Stream<A | B | C | D | E>` that are difficult to reason\r\nabout in our application's update function.\r\n\r\nHere's an illustrative example of avoiding an update function having to\r\ndeal with an event of type `number | string` by normalizing\r\nall `eventStreams` to `Stream<numer>`\r\n\r\n```tsx\r\nfunction button () {\r\n  return <div>\r\n    <button onclick={1}>Click me</button>\r\n  </div>\r\n}\r\n\r\nfunction input () {\r\n  return <div>\r\n    <input onchange={(e) => e.target.value} />\r\n  </div>\r\n}\r\n\r\nfunction application () {\r\n  return <div>\r\n    <div>\r\n      Count by one:\r\n      {button()}\r\n    </div>\r\n    <div>\r\n      Count by input:\r\n      {mapElement(\r\n        (payload) => {\r\n          if (!Number.isNaN(result)) return result\r\n          return 0\r\n        },\r\n        input()\r\n      )}\r\n    </div>\r\n  </div>\r\n}\r\n```\r\n\r\n:warning: Due to performance reasons, `mapElement` actually mutates\r\nthe `Element` passed to it. Always use a constructor function to pass\r\nthe second argument to this function :warning:\r\n","readmeFilename":"README.md"}