{"bugs":{"url":"https://github.com/alexreardon/bind-event-listener/issues"},"dist":{"shasum":"44f69241146746a9b3660ea2b58d40658f14e124","tarball":"https://registry.npmjs.org/bind-event-listener/-/bind-event-listener-1.0.0-alpha.1.tgz","fileCount":15,"integrity":"sha512-Pw6/GLc50+1VMM/U8Zppgr4UdFdpE+127oH5LYKXhEpjnhuMhfaPlnEsprRcGpij8DvL7P1Kq4Agc53kyeNjLA==","signatures":[{"sig":"MEUCIQDI3aIRDvPxZZTaOOYpOirU5Rv2PNKodG3ufkW81rNgxQIgaDCvWQeSGHA7qxOJgFjGw15dKfX0RalnSRTwHNVgesg=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":13578,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfDUKjCRA9TVsSAnZWagAAxwoQAJQkAnR2ngQ/LxssWTHl\nciw1xNjJBD6t6ix1YMpTiGNwlZWjXjzd0AnTFWq9G5dzjUPA98kR0wWe24nO\nrH+lWUdF4dLfoCotT3kDmiS8rWmPIvDkrvkuKrmAwFRIwHy4FFhpo7VSoqfN\njPxel3H7pQXjo9+MhIyXDa/GJauFNSp1ClFoiLqGqbX3s9nsteKv3qnSfrOl\n/0pJbrNoY+FKmQbBvbEGu0OBOixnWMySdNqSPrm7TKBnoEG1rjRSQlL3MiM6\nFaZC7yj2/pgzP0U9FjKPhvG6BfFra2ET1r3lNOBuvnvgDGHqCmAHQpM0WoNd\nQIYBsbAyU+mS3YCJ0+84rtC4mz9Q5CZWFTdn30g+YxjEZAinfKqtFVFrjM+a\nT49EkoDTMfDrSj4FYtrdahZW4IKg27B3HW4tU99YpdkEB+zvm2Tx58CM2YIq\ntXGdnDIAHHgXlLjo8bOYLICtkmQUD0SQ3WjQB0kU2TuLIreClLhOo0bPF4Os\nWhN8/p6iD59LUenZAbicCjuw3clQp9F37Xh5wD870ikFEBTG5unuGYfzGHNk\nz4dNwzf3hnp34MUPjZ0JL0kPb6p12jAA+ME4oQymr0B1KhrKgLqVOeq0/Grt\nedM/M+4EKg9cBp8TnOVdGk0LSLMdE1o54iS06Ldi+gMh7TioVthP8BQTNY+l\n/GHb\r\n=vRUQ\r\n-----END PGP SIGNATURE-----\r\n"},"main":"dist/index.js","name":"bind-event-listener","types":"dist/index.d.ts","author":{"name":"Alex Reardon","email":"alexreardon@gmail.com"},"config":{"prettier_target":"src/**/*.{ts,js,jsx,md,json} test/**/*.{ts,js,jsx,md,json}"},"readme":"# bind-event-listener\n\n[![npm](https://img.shields.io/npm/v/bind-event-listener.svg)](https://www.npmjs.com/package/bind-event-listener)\n![types](https://img.shields.io/badge/types-typescript-blueviolet)\n\n> A utility to make binding and (**especially**) unbinding DOM events easier.\n> I seem to write this again with every new project, so I made it a library\n\n```ts\nimport { bind, UnbindFn } from 'bind-event-listener';\n\nconst unbind: UnbindFn = bind(button, {\n  type: 'click',\n  listener: onClick,\n});\n\n// when you are all done:\nunbind();\n```\n\n```ts\nimport { bindAll } from 'bind-event-listener';\n\nconst unbind = bind(button, [\n  {\n    type: 'click',\n    listener: onClick,\n    options: { capture: true },\n  },\n  {\n    type: 'mouseover',\n    listener: onMouseOver,\n  },\n]);\n\n// when you are all done:\nunbind();\n```\n\n## Rationale\n\nWhen using `addEventListener()`, **correctly unbinding** events with `removeEventListener()` can be tricky.\n\n1. You need to remember to call `removeEventListener` (it can be easy to forget!)\n\n<details>\n<summary>Example</summary>\n\n```ts\ntarget.addEventListener('click', onClick, options);\n\n// You need to remember to call removeEventListener to unbind the event\ntarget.removeEventListener('click', onClick, options);\n```\n\n</details>\n\n2. You need to pass in the same listener _reference_ to `removeEventListener`\n\n<details>\n<summary>Example</summary>\n\n```ts\ntarget.addEventListener(\n  'click',\n  function onClick() {\n    console.log('clicked');\n  },\n  options,\n);\n\n// Even those the functions look the same, they don't have the same reference.\n// The original onClick is not unbound!\ntarget.removeEventListener(\n  'click',\n  function onClick() {\n    console.log('clicked');\n  },\n  options,\n);\n```\n\n```ts\n// Inline arrow functions can never be unbound because you have lost the reference!\ntarget.addEventListener('click', () => console.log('i will never unbind'), options);\ntarget.removeEventListener('click', () => console.log('i will never unbind'), options);\n```\n\n</details>\n\n3. You need to pass in the same `capture` value option\n\n<details>\n<summary>Example</summary>\n\n```ts\n// add a listener: AddEventListenerOptions format\ntarget.addEventListener('click', onClick, { capture: true });\n\n// not unbound: no capture value\ntarget.removeEventListener('click', onClick);\n\n// not unbound: different capture value\ntarget.removeEventListener('click', onClick, { capture: false });\n\n// successfully unbound: same capture value\ntarget.removeEventListener('click', onClick, { capture: true });\n// this would also unbind (different notation)\ntarget.removeEventListener('click', onClick, true /* shorthand for { capture: true } */);\n```\n\n```ts\n// add a listener: boolean capture format\ntarget.addEventListener('click', onClick, true /* shorthand for { capture: true } */);\n\n// not unbound: no capture value\ntarget.addEventListener('click', onClick);\n// not unbound: different capture value\ntarget.addEventListener('click', onClick, false);\n\n// successfully unbound: same capture value\ntarget.addEventListener('click', onClick, true);\n// this would also unbind (different notation)\ntarget.addEventListener('click', onClick, { capture: true });\n```\n\n</details>\n\n**`bind-event-listener` solves these problems**\n\n1. When you bind an event (or events with `bindAll`) you get back a simple `unbind` function\n2. The unbind function ensures the same listener _reference_ is passed to `removeEventListener`\n3. The unbind function ensures that whatever `capture` value is used with `addEventListener` is used with `removeEventListener`\n\n## Usage\n\n### `bind`: basic\n\n```ts\nimport { bind, UnbindFn } from 'bind-event-listener';\n\nconst unbind: UnbindFn = bind(button, {\n  type: 'click',\n  listener: onClick,\n});\n\n// when your are all done:\nunbind();\n```\n\n### `bind`: with options\n\n```ts\nimport { bind } from 'bind-event-listener';\n\nconst unbind = bind(button, {\n  type: 'click',\n  listener: onClick,\n  options: { capture: true, passive: false },\n});\n\n// when you are all done:\nunbind();\n```\n\n### `bindAll`: basic\n\n```ts\nimport { bindAll } from 'bind-event-listener';\n\nconst unbind = bindAll(button, [\n  {\n    type: 'click',\n    listener: onClick,\n  },\n]);\n\n// when you are all done:\nunbind();\n```\n\n### `bindAll`: with options\n\n```ts\nimport { bindAll } from 'bind-event-listener';\n\nconst unbind = bindAll(button, [\n  {\n    type: 'click',\n    listener: onClick,\n    options: { passive: true },\n  },\n  // default options that are applied to all bindings\n  { capture: false },\n]);\n\n// when you are all done:\nunbind();\n```\n\nWhen using `defaultOptions` for `bindAll`, the `defaultOptions` are merged with the `options` on each binding. Options on the individual bindings will take precedent. You can think of it like this:\n\n```ts\nconst merged: AddEventListenerOptions = {\n  ...defaultOptions,\n  ...options,\n};\n```\n\n> Note: it is a little bit more complicated than just object spreading as the library will also behave correctly when passing in a `boolean` capture argument. An options value can be a boolean `{ options: true }` which is shorthand for `{ options: {capture: true } }`\n\n## Recipe: [`react`](https://reactjs.org/) effect\n\nYou can return a [cleanup function](https://reactjs.org/docs/hooks-reference.html#cleaning-up-an-effect) from [`useEffect`](https://reactjs.org/docs/hooks-reference.html#useeffect) (or [`useLayoutEffect`](https://reactjs.org/docs/hooks-reference.html#uselayouteffect)). `bind-event-listener` makes this super convenient because you can just return the unbind function from your effect.\n\n```ts\nimport React, { useState, useEffect } from 'react';\nimport { bind } from 'bind-event-listener';\n\nexport default function App() {\n  const [clickCount, onClick] = useState(0);\n\n  useEffect(() => {\n    const unbind = bind(window, {\n      type: 'click',\n      listener: () => onClick((value) => value + 1),\n    });\n\n    return unbind;\n  }, []);\n\n  return <div>Window clicks: {clickCount}</div>;\n}\n```\n\n> You can play with this [example on codesandbox](https://codesandbox.io/s/bind-event-listener-useeffect-mnfi3)\n\n## Types\n\n```ts\nfunction bind(target: EventTarget, binding: Binding): UnbindFn;\n\nfunction bindAll(\n  target: EventTarget,\n  bindings: Binding[],\n  // AddEventListenerOptions is a built in TypeScript type\n  sharedOptions?: boolean | AddEventListenerOptions,\n): UnbindFn;\n\ntype Binding = {\n  type: string;\n  // EventListenerOrEventListenerObject is a built in TypeScript type\n  listener: EventListenerOrEventListenerObject;\n  options?: boolean | AddEventListenerOptions;\n};\n\ntype UnbindFn = () => void;\n```\n\n> Typescript built in DOM types: [raw view](https://raw.githubusercontent.com/microsoft/TypeScript/master/lib/lib.dom.d.ts), [pretty view](https://github.com/microsoft/TypeScript/blob/master/lib/lib.dom.d.ts) (warning: pretty view seems to crash Github!)\n\n## Cheers 👋\n\nBrought to you by [@alexandereardon](https://twitter.com/alexandereardon)\n","gitHead":"7ef9bd2c6f204bdaac0737a806cf30badc4bbb07","license":"MIT","private":false,"scripts":{"test":"yarn jest","build":"yarn build:clean && yarn typescript:build","build:clean":"rimraf dist","prepublishOnly":"yarn build","prettier:check":"prettier --debug-check $npm_package_config_prettier_target","prettier:write":"prettier --write $npm_package_config_prettier_target","typescript:build":"tsc","typescript:check":"yarn tsc --noEmit","typescript:watch":"tsc --watch"},"_npmUser":{"name":"alexreardon","email":"alexreardon@gmail.com"},"homepage":"https://github.com/alexreardon/bind-event-listener#readme","keywords":["dom","ui","event listener","event handler"],"repository":{"url":"git+https://github.com/alexreardon/bind-event-listener.git","type":"git"},"_npmVersion":"6.4.1","description":"Making binding and unbinding DOM events easier","directories":{},"maintainers":[{"name":"alexreardon","email":"alexreardon@gmail.com"}],"sideEffects":false,"_nodeVersion":"10.15.3","dependencies":{},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^26.0.1","rimraf":"^3.0.2","ts-jest":"^26.1.0","prettier":"^2.0.5","typescript":"^3.9.5","@types/jest":"^26.0.0"},"_npmOperationalInternal":{"tmp":"tmp/bind-event-listener_1.0.0-alpha.1_1594704546613_0.22590866390658637","host":"s3://npm-registry-packages"},"_id":"bind-event-listener@1.0.0-alpha.1","version":"1.0.0-alpha.1"}