bind-event-listener
Advanced tools
Comparing version 1.0.2 to 2.0.0
import { Binding, UnbindFn } from './types'; | ||
export declare function bindAll<Target extends EventTarget, Type extends string>(target: Target, bindings: [Binding<Target, Type>], sharedOptions?: boolean | AddEventListenerOptions): UnbindFn; | ||
export declare function bindAll<Target extends EventTarget, Type1 extends string, Type2 extends string>(target: Target, bindings: [Binding<Target, Type1>, Binding<Target, Type2>], sharedOptions?: boolean | AddEventListenerOptions): UnbindFn; | ||
export declare function bindAll<Target extends EventTarget, Type1 extends string, Type2 extends string, Type3 extends string>(target: Target, bindings: [Binding<Target, Type1>, Binding<Target, Type2>, Binding<Target, Type3>], sharedOptions?: boolean | AddEventListenerOptions): UnbindFn; | ||
export declare function bindAll<Target extends EventTarget, Type1 extends string, Type2 extends string, Type3 extends string, Type4 extends string>(target: Target, bindings: [ | ||
Binding<Target, Type1>, | ||
Binding<Target, Type2>, | ||
Binding<Target, Type3>, | ||
Binding<Target, Type4> | ||
], sharedOptions?: boolean | AddEventListenerOptions): UnbindFn; | ||
export declare function bindAll<Target extends EventTarget, Type1 extends string, Type2 extends string, Type3 extends string, Type4 extends string, Type5 extends string>(target: Target, bindings: [ | ||
Binding<Target, Type1>, | ||
Binding<Target, Type2>, | ||
Binding<Target, Type3>, | ||
Binding<Target, Type4>, | ||
Binding<Target, Type5> | ||
], sharedOptions?: boolean | AddEventListenerOptions): UnbindFn; | ||
export declare function bindAll<Target extends EventTarget, Type1 extends string, Type2 extends string, Type3 extends string, Type4 extends string, Type5 extends string, Type6 extends string>(target: Target, bindings: [ | ||
Binding<Target, Type1>, | ||
Binding<Target, Type2>, | ||
Binding<Target, Type3>, | ||
Binding<Target, Type4>, | ||
Binding<Target, Type5>, | ||
Binding<Target, Type6> | ||
], sharedOptions?: boolean | AddEventListenerOptions): UnbindFn; | ||
export declare function bindAll(target: EventTarget, bindings: Binding[], sharedOptions?: boolean | AddEventListenerOptions): UnbindFn; |
import { UnbindFn, Binding } from './types'; | ||
export declare function bind(target: EventTarget, { type, listener, options }: Binding): UnbindFn; | ||
export declare function bind<Target extends EventTarget, Type extends string>(target: Target, { type, listener, options }: Binding<Target, Type>): UnbindFn; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.bindAll = exports.bind = void 0; | ||
var bind_1 = require("./bind"); | ||
@@ -4,0 +5,0 @@ Object.defineProperty(exports, "bind", { enumerable: true, get: function () { return bind_1.bind; } }); |
export declare type UnbindFn = () => void; | ||
export declare type Binding = { | ||
type: string; | ||
listener: EventListenerOrEventListenerObject; | ||
declare type AnyFunction = (...args: any[]) => any; | ||
declare type GetEventType<Target extends EventTarget, Type extends string> = Target extends unknown ? `on${Type}` extends keyof Target ? GetEventTypeFromListener<Extract<Target[`on${Type}`], AnyFunction>> : Event : never; | ||
declare type GetEventTypeFromListener<T extends AnyFunction> = T extends (this: any, event: infer U) => any ? U extends Event ? U : Event : Event; | ||
export declare type Binding<Target extends EventTarget = EventTarget, Type extends string = string> = { | ||
type: Type; | ||
listener: Listener<GetEventType<Target, Type>, Target>; | ||
options?: boolean | AddEventListenerOptions; | ||
}; | ||
export declare type Listener<Ev extends Event, Target extends EventTarget> = ListenerObject<Ev> | { | ||
bivarianceHack(this: Target, e: Ev): void; | ||
}['bivarianceHack']; | ||
declare type ListenerObject<Ev extends Event> = { | ||
handleEvent(this: ListenerObject<Ev>, Ee: Ev): void; | ||
}; | ||
export {}; |
{ | ||
"name": "bind-event-listener", | ||
"version": "1.0.2", | ||
"version": "2.0.0", | ||
"private": false, | ||
@@ -28,2 +28,8 @@ "description": "Making binding and unbinding DOM events easier", | ||
], | ||
"size-limit": [ | ||
{ | ||
"path": "dist/index.js", | ||
"limit": "330B" | ||
} | ||
], | ||
"scripts": { | ||
@@ -35,3 +41,5 @@ "typescript:check": "yarn tsc --noEmit", | ||
"prettier:write": "prettier --write $npm_package_config_prettier_target", | ||
"validate": "yarn typescript:check && yarn prettier:check", | ||
"test": "yarn jest", | ||
"size:check": "size-limit", | ||
"build:clean": "rimraf dist", | ||
@@ -42,10 +50,13 @@ "build": "yarn build:clean && yarn typescript:build", | ||
"devDependencies": { | ||
"@types/jest": "^26.0.0", | ||
"jest": "^26.0.1", | ||
"prettier": "^2.0.5", | ||
"@size-limit/preset-small-lib": "^4.11.0", | ||
"@types/jest": "^26.0.23", | ||
"expect-type": "^0.11.0", | ||
"jest": "^27.0.4", | ||
"prettier": "^2.3.1", | ||
"rimraf": "^3.0.2", | ||
"ts-jest": "^26.1.0", | ||
"typescript": "^3.9.5" | ||
"size-limit": "^4.11.0", | ||
"ts-jest": "^27.0.3", | ||
"typescript": "^4.3.2" | ||
}, | ||
"dependencies": {} | ||
} |
@@ -5,2 +5,3 @@ # bind-event-listener | ||
![types](https://img.shields.io/badge/types-typescript-blueviolet) | ||
[![minzip](https://img.shields.io/bundlephobia/minzip/bind-event-listener.svg)](https://www.npmjs.com/package/bind-event-listener) | ||
@@ -15,3 +16,3 @@ > A utility to make binding and (**especially**) unbinding DOM events easier. | ||
type: 'click', | ||
listener: onClick, | ||
listener: function onClick(event) {}, | ||
}); | ||
@@ -26,6 +27,6 @@ | ||
const unbind = bind(button, [ | ||
const unbind = bindAll(button, [ | ||
{ | ||
type: 'click', | ||
listener: onClick, | ||
listener: function onClick(event) {}, | ||
options: { capture: true }, | ||
@@ -35,3 +36,3 @@ }, | ||
type: 'mouseover', | ||
listener: onMouseOver, | ||
listener: function onMouseOver(event) {}, | ||
}, | ||
@@ -56,3 +57,2 @@ ]); | ||
// You need to remember to call removeEventListener to unbind the event | ||
target.removeEventListener('click', onClick, options); | ||
@@ -140,2 +140,6 @@ ``` | ||
You will find an even fuller rationale for this project in my course: ["The Ultimate Guide for Understanding DOM Events"](https://egghead.io/courses/the-ultimate-guide-for-understanding-dom-events-6c0c0d23?af=2jc3e4) | ||
[![share-card-dom-events](https://user-images.githubusercontent.com/2182637/120963089-52a45f00-c7a4-11eb-82a7-a04c2731999a.jpg)](https://egghead.io/courses/the-ultimate-guide-for-understanding-dom-events-6c0c0d23?af=2jc3e4) | ||
## Usage | ||
@@ -218,2 +222,42 @@ | ||
## Types | ||
Thanks to the great work by [@Ayub-Begimkulov](https://github.com/Ayub-Begimkulov) `bind-event-listener` has fantastic typescript types | ||
```ts | ||
import invariant from 'tiny-invariant'; | ||
import { bind } from 'bind-event-listener'; | ||
bind(window, { | ||
type: 'click', | ||
function: function onClick(event) { | ||
// `event` is correctly typed as a 'MouseEvent' | ||
// `this` is correctly typed as `window` (the event target that the event listener is added to) | ||
}, | ||
}); | ||
const button = document.querySelector('button'); | ||
invariant(button instanceof HTMLElement); | ||
bind(button, { | ||
type: 'click', | ||
function: function onClick(event) { | ||
// `event` is correctly typed as a 'MouseEvent' | ||
// `this` is correctly typed as `button` (the event target that the event listener is added to) | ||
}, | ||
}); | ||
const object = { | ||
handleEvent: function onClick(event) { | ||
// `event` is correctly typed as a 'MouseEvent' | ||
// `this` is correctly typed as `object` (the event listener object that the event listener is added to) | ||
}, | ||
}; | ||
bind(button, { | ||
type: 'click', | ||
function: object, | ||
}); | ||
``` | ||
## Recipe: [`react`](https://reactjs.org/) effect | ||
@@ -220,0 +264,0 @@ |
@@ -38,2 +38,76 @@ import { Binding, UnbindFn } from './types'; | ||
export function bindAll<Target extends EventTarget, Type extends string>( | ||
target: Target, | ||
bindings: [Binding<Target, Type>], | ||
sharedOptions?: boolean | AddEventListenerOptions, | ||
): UnbindFn; | ||
export function bindAll<Target extends EventTarget, Type1 extends string, Type2 extends string>( | ||
target: Target, | ||
bindings: [Binding<Target, Type1>, Binding<Target, Type2>], | ||
sharedOptions?: boolean | AddEventListenerOptions, | ||
): UnbindFn; | ||
export function bindAll< | ||
Target extends EventTarget, | ||
Type1 extends string, | ||
Type2 extends string, | ||
Type3 extends string, | ||
>( | ||
target: Target, | ||
bindings: [Binding<Target, Type1>, Binding<Target, Type2>, Binding<Target, Type3>], | ||
sharedOptions?: boolean | AddEventListenerOptions, | ||
): UnbindFn; | ||
export function bindAll< | ||
Target extends EventTarget, | ||
Type1 extends string, | ||
Type2 extends string, | ||
Type3 extends string, | ||
Type4 extends string, | ||
>( | ||
target: Target, | ||
bindings: [ | ||
Binding<Target, Type1>, | ||
Binding<Target, Type2>, | ||
Binding<Target, Type3>, | ||
Binding<Target, Type4>, | ||
], | ||
sharedOptions?: boolean | AddEventListenerOptions, | ||
): UnbindFn; | ||
export function bindAll< | ||
Target extends EventTarget, | ||
Type1 extends string, | ||
Type2 extends string, | ||
Type3 extends string, | ||
Type4 extends string, | ||
Type5 extends string, | ||
>( | ||
target: Target, | ||
bindings: [ | ||
Binding<Target, Type1>, | ||
Binding<Target, Type2>, | ||
Binding<Target, Type3>, | ||
Binding<Target, Type4>, | ||
Binding<Target, Type5>, | ||
], | ||
sharedOptions?: boolean | AddEventListenerOptions, | ||
): UnbindFn; | ||
export function bindAll< | ||
Target extends EventTarget, | ||
Type1 extends string, | ||
Type2 extends string, | ||
Type3 extends string, | ||
Type4 extends string, | ||
Type5 extends string, | ||
Type6 extends string, | ||
>( | ||
target: Target, | ||
bindings: [ | ||
Binding<Target, Type1>, | ||
Binding<Target, Type2>, | ||
Binding<Target, Type3>, | ||
Binding<Target, Type4>, | ||
Binding<Target, Type5>, | ||
Binding<Target, Type6>, | ||
], | ||
sharedOptions?: boolean | AddEventListenerOptions, | ||
): UnbindFn; | ||
export function bindAll( | ||
@@ -43,2 +117,7 @@ target: EventTarget, | ||
sharedOptions?: boolean | AddEventListenerOptions, | ||
): UnbindFn; | ||
export function bindAll( | ||
target: EventTarget, | ||
bindings: Binding[], | ||
sharedOptions?: boolean | AddEventListenerOptions, | ||
): UnbindFn { | ||
@@ -51,4 +130,4 @@ const unbinds: UnbindFn[] = bindings.map((original: Binding) => { | ||
return function unbindAll() { | ||
unbinds.forEach((unbind: UnbindFn) => unbind()); | ||
unbinds.forEach((unbind) => unbind()); | ||
}; | ||
} |
import { UnbindFn, Binding } from './types'; | ||
export function bind(target: EventTarget, { type, listener, options }: Binding): UnbindFn { | ||
export function bind<Target extends EventTarget, Type extends string>( | ||
target: Target, | ||
{ type, listener, options }: Binding<Target, Type>, | ||
): UnbindFn; | ||
export function bind(target: EventTarget, { type, listener, options }: Binding) { | ||
target.addEventListener(type, listener, options); | ||
@@ -5,0 +9,0 @@ |
export type UnbindFn = () => void; | ||
export type Binding = { | ||
type: string; | ||
listener: EventListenerOrEventListenerObject; | ||
type AnyFunction = (...args: any[]) => any; | ||
type GetEventType<Target extends EventTarget, Type extends string> = Target extends unknown | ||
? `on${Type}` extends keyof Target | ||
? GetEventTypeFromListener< | ||
// remove types that aren't assignable to `AnyFunction` | ||
// so that we don't end up with union like `MouseEvent | Event` | ||
Extract<Target[`on${Type}`], AnyFunction> | ||
> | ||
: Event | ||
: never; | ||
type GetEventTypeFromListener<T extends AnyFunction> = T extends (this: any, event: infer U) => any | ||
? U extends Event | ||
? U | ||
: Event | ||
: Event; | ||
export type Binding<Target extends EventTarget = EventTarget, Type extends string = string> = { | ||
type: Type; | ||
listener: Listener<GetEventType<Target, Type>, Target>; | ||
options?: boolean | AddEventListenerOptions; | ||
}; | ||
export type Listener<Ev extends Event, Target extends EventTarget> = | ||
| ListenerObject<Ev> | ||
// For a listener function, the `this` binding is the target the event listener is added to | ||
// using bivariance hack here so if the user | ||
// wants to narrow event type by hand TS | ||
// won't give him an error | ||
| { bivarianceHack(this: Target, e: Ev): void }['bivarianceHack']; | ||
type ListenerObject<Ev extends Event> = { | ||
// For listener objects, the handleEvent function has the object as the `this` binding | ||
handleEvent(this: ListenerObject<Ev>, Ee: Ev): void; | ||
}; |
22245
280
309
9