Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .babelrc
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
}
],
"@babel/preset-react",
"@babel/preset-flow"
"@babel/preset-typescript"
],
"plugins": [
"@babel/plugin-proposal-object-rest-spread",
Expand Down
26 changes: 3 additions & 23 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,33 +1,13 @@
{
"env": {
"browser": true,
"es6": true,
"commonjs": true,
"node": true,
"jest": true,
"mocha": true
},
"globals": {
"__DEV__": true
},
"extends": [
"wiremore",
"wiremore/react",
"plugin:react/recommended",
"prettier",
"prettier/react",
"plugin:flowtype/recommended"
],
"settings": {
"flowtype": {
"onlyFilesWithFlowAnnotation": true
}
},
"plugins": ["prettier", "flowtype"],
"extends": ["wiremore", "wiremore/react", "wiremore/typescript"],
"rules": {
"import/named": 0,
"import/no-unassigned-import": 0,
"import/no-named-as-default-member": 0,
"prettier/prettier": "error"
"prettier/prettier": "error",
"react-hooks/exhaustive-deps": 1
}
}
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,5 @@ typings/
# dotenv environment variables file
.env

dist
es
6 changes: 6 additions & 0 deletions .huskyrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"hooks": {
"post-merge": "install-deps-postmerge",
"pre-commit": "lint-staged"
}
}
10 changes: 10 additions & 0 deletions .lintstagedrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"*.{js,jsx,ts,tsx,css}": [
"prettier --write",
"git add"
],
"*.{js,jsx,ts,tsx}": [
"yarn lint:js --fix",
"git add"
]
}
63 changes: 35 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ⚛ React Checkbox Context

This package was heavily inspired by [react-checkbox-group](https://github.com/ziad-saab/react-checkbox-group) after it stopped working the way I used it. `<Checkbox />` elements suddenly had to be direct children of `<CheckboxGroup>` (which was impossible for my use case) or the `CheckboxGroup` explicitly needed to have a `checkboxDepth` prop (which was not flexible enough for me). So I decided to write my own `<CheckboxGroup>` component based on React's new [Context API](https://reactjs.org/docs/context.html).
This package was heavily inspired by [react-checkbox-group](https://github.com/ziad-saab/react-checkbox-group) after it stopped working the way I used it. `<Checkbox />` elements suddenly had to be direct children of `<CheckboxGroup>` (which was impossible for my use case) or the `CheckboxGroup` explicitly needed to have a `checkboxDepth` prop (which was not flexible enough for me). So I decided to write my own `<CheckboxGroup>` component based on React's (then) new [Context API](https://reactjs.org/docs/context.html).

Big thank you to [Ziad Saab](https://github.com/ziad-saab) for the inspiration!

Expand All @@ -9,6 +9,7 @@ Big thank you to [Ziad Saab](https://github.com/ziad-saab) for the inspiration!
```
npm install react-checkbox-context
```

or

```
Expand All @@ -21,54 +22,60 @@ What does `react-checkbox-context` do and how does it do that? Let me borrow the

This is your average checkbox group:

```js
```jsx
<form>
<input onChange={this.handleFruitChange} type="checkbox" name="fruit" value="apple" /> Apple
<input onChange={this.handleFruitChange} type="checkbox" name="fruit" value="orange" /> Orange
<input onChange={this.handleFruitChange} type="checkbox" name="fruit" value="watermelon" /> Watermelon
<input onChange={this.handleFruitChange} type="checkbox" name="fruit" value="apple" /> Apple
<input onChange={this.handleFruitChange} type="checkbox" name="fruit" value="orange" /> Orange
<input onChange={this.handleFruitChange} type="checkbox" name="fruit" value="watermelon" />{' '}
Watermelon
</form>
```

Repetitive, hard to manipulate and easily desynchronized. Lift up name and onChange, and give the group an initial checked values array:

```js
```jsx
import { Checkbox, CheckboxGroup } from 'react-checkbox-context';

<CheckboxGroup name="fruits" values={['kiwi', 'pineapple']}>
<Checkbox value="kiwi" /> Kiwi
<Checkbox value="pineapple" /> Pineapple
<Checkbox value="watermelon" /> Watermelon
<Checkbox value="kiwi" /> Kiwi
<Checkbox value="pineapple" /> Pineapple
<Checkbox value="watermelon" /> Watermelon
</CheckboxGroup>;
```

Since this component uses React's Context API, `<Checkbox>` elements can by anywhere inside of a `<CheckboxGroup>` and **do not** have to be a direct descendant! So this is easily possible **without** having to specify any `checkboxDepth` props or the like:

```js
<CheckboxGroup name="frameworks" onChange={(event, selectedValues) => { console.log(selectedValues); }}>
<p>
<label htmlFor="react">
<Checkbox value="react" id="react" /> React
</label>
</p>
<p>
<label htmlFor="vue">
<Checkbox value="vue" id="vue" /> Vue
</label>
</p>
```jsx
<CheckboxGroup
name="frameworks"
onChange={(event, selectedValues) => {
console.log(selectedValues);
}}
>
<p>
<label htmlFor="react">
<Checkbox value="react" id="react" /> React
</label>
</p>
<p>
<label htmlFor="vue">
<Checkbox value="vue" id="vue" /> Vue
</label>
</p>
</CheckboxGroup>
```

**Attention:** When migrating from `react-checkbox-group` please note that the prop name to pass the values to a `CheckboxGroup` is named `values` instead of `value` since it's an array and as such sounds more logical to me to be plural.
**Attention:** When migrating from `react-checkbox-group` please note that the prop name to pass the values to a `CheckboxGroup` is named `values` instead of `value`.

## Props

### `<CheckboxGroup />`

| Prop | Type | Description |
| ---------- | ---------------------------------------------------------------------------------- | ---------------------------------------------------------- |
| `onChange` | `(originalEvent: SyntheticEvent<HTMLInputElement>, values: Array<string>) => void` | Will be called on every time a checkbox changes its state. |
| `name` | `string` | Name for all checkboxes within one `<CheckboxGroup>` |
| `values` | `Array<string>` | Values of the `<Checkbox>` elements marked as `checked` |
| Prop | Type | Description |
| ---------- | ------------------------------------------------ | ---------------------------------------------------------- |
| `onChange` | `(event: ChangeEvent, values: string[]) => void` | Will be called on every time a checkbox changes its state. |
| `name` | `string` | Name for all checkboxes within one `<CheckboxGroup>` |
| `values` | `string[]` | Values of the `<Checkbox>` elements marked as `checked` |

Status of checkboxes (checked/unchecked) can be controlled from outside by passing new values to `<CheckboxGroup>` (e.g. `<CheckboxGroup values={this.state.checkedItems} />`).

Expand All @@ -78,7 +85,7 @@ The `Checkbox` component passes all of its props the the underlying `<input type

## Todo

* Add more tests, especially with Enzyme to be able to check if `onChange` events are fired correctly.
- Add more tests, more specifically a test if `onChange` events are fired correctly.

## License

Expand Down
1 change: 0 additions & 1 deletion es/Checkbox.js

This file was deleted.

1 change: 0 additions & 1 deletion es/CheckboxGroup.js

This file was deleted.

1 change: 0 additions & 1 deletion es/context.js

This file was deleted.

1 change: 0 additions & 1 deletion es/index.js

This file was deleted.

1 change: 0 additions & 1 deletion es/index.test.js

This file was deleted.

11 changes: 11 additions & 0 deletions examples/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no">
</head>
<body>
<div id="example"></div>
</body>
</html>
48 changes: 48 additions & 0 deletions examples/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import React, { useState } from 'react';
import ReactDOM from 'react-dom';
import { Checkbox, CheckboxGroup } from '../src';

const Examples = () => {
const [checkedValues, setCheckedValues] = useState(['2', '3']);
const check1and3 = () => {
setCheckedValues(['1', '3']);
};

const checkAll = () => {
setCheckedValues(['1', '2', '3']);
};

const uncheckAll = () => {
setCheckedValues([]);
};

return (
<div>
<p>
<button onClick={check1and3}>Check 1 + 3</button>
<button onClick={checkAll}>Check All</button>
<button onClick={uncheckAll}>Uncheck All</button>
</p>
<CheckboxGroup
name="xy"
values={checkedValues}
onChange={(e, values) => {
setCheckedValues(values);
}}
>
<label>
<Checkbox value="1" /> 1
</label>
<label>
<Checkbox value="2" /> 2
</label>
<label>
<Checkbox value="3" /> 3
</label>
</CheckboxGroup>
<pre>Checked values: {JSON.stringify(checkedValues, null, 2)}</pre>
</div>
);
};

ReactDOM.render(<Examples />, document.getElementById('example'));
Loading