Skip to content

Commit

Permalink
Merge pull request #33 from /issues/29
Browse files Browse the repository at this point in the history
Add withNumericTargetValue

Closes #29
  • Loading branch information
himynameisdave committed Jun 19, 2020
2 parents 5b4222d + c6d90d8 commit 63170da
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 4 deletions.
37 changes: 37 additions & 0 deletions docs/with-numeric-target-value.md
@@ -0,0 +1,37 @@
### withNumericTargetValue

Calls your provided event handler function with `event.target.value`, cast to a Number, as the first value (if it exists). Passes the `event` along as the second argument in case you need it.

**Vanilla**

```js
import { withNumericTargetValue } from "browser-event-utils";

myInputNode.addEventListener(
"change",
withNumericTargetValue((value, event) => {
// Note that you still get the event object as the 2nd arg, if you need it
console.log(value); // 0 -> Always a Number, never NaN
})
);
```

**React**

```jsx
import React, { Component } from "react";
import { withNumericTargetValue } from "browser-event-utils";

const handleChange = withNumericTargetValue((value, event) => {
// Note that you still get the event object as the 2nd arg, if you need it
console.log(value); // 0 -> Always a Number, never NaN
});

const MyInput = () => {
return <input type="number" onChange={handleChange} />
};
```

<!--
[![Edit with-numeric-target-value (React)](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/competent-breeze-kmhf6?fontsize=14&hidenavigation=1)
-->
4 changes: 2 additions & 2 deletions package.json
Expand Up @@ -31,7 +31,7 @@
"lint": "eslint ./src/ --ext .ts --ignore-pattern **/__tests__/**/* --report-unused-disable-directives",
"lint:fix": "eslint ./src/ --ext .ts --ignore-pattern **/__tests__/**/* --fix",
"test:js": "jest --coverage",
"test:pre-commit": "jest",
"test:pre-commit": "jest && eslint --ignore-pattern **/__tests__/**/* --fix --quiet --report-unused-disable-directives",
"test:coverage": "jest --coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js",
"viewCoverage": "npm run test:js && open ./coverage/lcov-report/index.html -a Google\\ Chrome",
"test:watch": "jest --watch",
Expand Down Expand Up @@ -77,7 +77,7 @@
}
},
"lint-staged": {
"*.ts": "eslint ./ --fix --quiet && jest"
"*.ts": "npm run test:pre-commit"
},
"browserslist": [
"> 0.25%",
Expand Down
27 changes: 27 additions & 0 deletions src/__tests__/with-numeric-target-value.spec.ts
@@ -0,0 +1,27 @@
import withNumericTargetValue from '../with-numeric-target-value';
import { EventType } from '../index.d';


describe('withNumericTargetValue', () => {
it('will not fall over if bad values are passed', () => {
expect(() => withNumericTargetValue()()).not.toThrow();
});
it('calls the hanlder with a correct numeric value', () => {
const handler = jest.fn();
const mockEvent = { target: { value: '100' } } as EventType;
withNumericTargetValue(handler)(mockEvent);
expect(handler).toHaveBeenCalledWith(100, mockEvent);
});
it('casts non-numeric nullish values properly', () => {
const handler = jest.fn();
const mockEvent = { target: { value: null } } as EventType;
withNumericTargetValue(handler)(mockEvent);
expect(handler).toHaveBeenCalledWith(0, mockEvent);
});
it('will never pass a NaN through as the numeric value', () => {
const handler = jest.fn();
const mockEvent = { target: { } } as EventType;
withNumericTargetValue(handler)(mockEvent);
expect(handler).not.toHaveBeenCalledWith(NaN, mockEvent);
});
});
@@ -1,5 +1,6 @@
/* eslint-disable @typescript-eslint/explicit-function-return-type */
import withTargetChecked from '../with-target-checked';
import { EventType } from '../index.d';


describe('withTargetChecked', () => {
Expand All @@ -8,14 +9,14 @@ describe('withTargetChecked', () => {
});
it('calls consumer function with undefined if event.target.checked does not exist', () => {
const mockConsumer = jest.fn();
const mockEvent = {};
const mockEvent = {} as EventType;
withTargetChecked(mockConsumer)(mockEvent);
expect(mockConsumer).toHaveBeenCalledWith(undefined, mockEvent);
});
it('calls the consumer function with event.target.checked if it exists', () => {
const mockConsumer = jest.fn();
const mockIsChecked = true;
const mockEvent = { target: { checked: mockIsChecked } };
const mockEvent = { target: { checked: mockIsChecked } } as EventType;
withTargetChecked(mockConsumer)(mockEvent);
expect(mockConsumer).toHaveBeenCalledWith(mockIsChecked, mockEvent);
});
Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Expand Up @@ -4,3 +4,4 @@ export { default as withStopImmediatePropagation } from './with-stop-immediate-p
export { default as withTargetChecked } from './with-target-checked';
export { default as withTargetValue } from './with-target-value';
export { default as withKeyPress } from './with-keypress';
export { default as withNumericTargetValue } from './with-numeric-target-value';
26 changes: 26 additions & 0 deletions src/with-numeric-target-value.ts
@@ -0,0 +1,26 @@
import withTarget from './helpers/with-target';
import noop from './helpers/noop';
import {
EventType,
EventHandler,
} from './index.d';


export type TWithNumericTargetValueHandler =
(value: number | null, event?: EventType) => void;

/**
* Accepts a function, who's first argument will be Number(event.target.value),
* followed by the full event object.
*
* @param {Function} fn - Consumer's handler function
* @return {Function} - event handler function
*/
const withNumericTargetValue = (fn: TWithNumericTargetValueHandler = noop): EventHandler => {
return withTarget((target?: HTMLInputElement, event?: EventType): void => {
const numericValue = Number(target?.value);
return fn(!Number.isNaN(numericValue) ? numericValue : 0, event);
});
};

export default withNumericTargetValue;

0 comments on commit 63170da

Please sign in to comment.