├── .npmignore
├── .gitignore
├── example
├── webpack.config.js
├── example.html
└── example.jsx
├── webpack.config.js
├── HISTORY.md
├── LICENSE
├── package.json
├── index.jsx
└── README.md
/.npmignore:
--------------------------------------------------------------------------------
1 | src
2 | example
3 | index.jsx
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | index.html
3 | out
4 | node_modules
5 | lib
6 | umd
7 | example/all*
8 | *.log
9 |
--------------------------------------------------------------------------------
/example/webpack.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | module: {
3 | loaders: [
4 | {test: /\.jsx?$/, exclude: /build|node_modules/, loader: 'babel-loader?stage=0'},
5 | ]
6 | },
7 | resolve: {
8 | extensions: ['', '.js', '.jsx']
9 | }
10 | };
11 |
--------------------------------------------------------------------------------
/example/example.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Test template
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | output: {
3 | library: 'RadioGroup',
4 | libraryTarget: 'umd'
5 | },
6 | externals: [
7 | {
8 | react: {
9 | root: 'React',
10 | commonjs2: 'react',
11 | commonjs: 'react',
12 | amd: 'react'
13 | }
14 | }
15 | ],
16 | module: {
17 | loaders: [
18 | {test: /\.jsx?$/, exclude: /build|node_modules/, loader: 'babel-loader?stage=0'},
19 | ]
20 | },
21 | resolve: {
22 | extensions: ['', '.js', '.jsx']
23 | }
24 | };
25 |
--------------------------------------------------------------------------------
/example/example.jsx:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import React from 'react';
4 | import ReactDOM from 'react-dom';
5 | import {RadioGroup, Radio} from '../index.jsx';
6 |
7 | let App = React.createClass({
8 | getInitialState() {
9 | return {selectedValue: 'apple'};
10 | },
11 |
12 | handleChange(value) {
13 | this.setState({selectedValue: value});
14 | },
15 |
16 | render() {
17 | return (
18 |
22 |
25 |
28 |
31 |
32 | );
33 | }
34 | });
35 |
36 | ReactDOM.render(, document.getElementById('content'));
37 |
--------------------------------------------------------------------------------
/HISTORY.md:
--------------------------------------------------------------------------------
1 | ### 3.0.3 (March 29th 2018)
2 | - React 16 support
3 |
4 | ### 3.0.0 (June 29th 2016)
5 | - Completely new API: no more function-as-a-child. See Readme for the details
6 | - No new DOM Nodes are created anymore when component gets rerendered.
7 | - Requires React v0.14 or higher
8 | - Both `RadioGroup` and `Radio` have a displayName
9 |
10 | ### 2.2.0 (November 30th 2015)
11 | - `selectedValue` and `onChange` are optional
12 |
13 | ### 2.1.1 (August 17th 2015)
14 | - Allow `selectedValue`'s type to be a boolean.
15 |
16 | ### 2.1.0 (July 26th 2015)
17 | - Library now no longer wraps your children function return with a `div`. It now checks that you return a single component (or `null`) from the function. #18
18 |
19 | ### 2.0.2 (June 14th 2015)
20 | - Make the library work with browser globals.
21 |
22 | ### 2.0.1 (June 14th 2015)
23 | - Compile to UMD so you can import this hackily from a browser script.
24 |
25 | ## 2.0.0 (June 14th 2015)
26 | - API overhaul. See README for the new, cleaner API!
27 | - Drop Bower support.
28 | - Add npm support.
29 |
30 | ## 1.0.0
31 | - Initial release.
32 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Cheng Lou
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-radio-group",
3 | "version": "3.0.3",
4 | "description": "Better radio buttons.",
5 | "main": "lib/index.js",
6 | "scripts": {
7 | "example": "webpack -w -d --config example/webpack.config.js example/example.jsx example/all.js",
8 | "build-umd": "webpack index.jsx umd/index.js",
9 | "build-cjs": "babel index.jsx -d lib",
10 | "prerelease": "npm run build-umd && npm run build-cjs"
11 | },
12 | "repository": {
13 | "type": "git",
14 | "url": "https://github.com/chenglou/react-radio-group.git"
15 | },
16 | "keywords": [
17 | "facebook",
18 | "react",
19 | "radio",
20 | "radio-group",
21 | "component",
22 | "react-component"
23 | ],
24 | "dependencies": {
25 | "prop-types": "^15.5.8"
26 | },
27 | "devDependencies": {
28 | "babel": "^5.5.8",
29 | "babel-core": "^5.2.17",
30 | "babel-loader": "^5.0.0",
31 | "react": ">=0.14.0",
32 | "react-dom": ">=15.5.4",
33 | "webpack": "^1.8.11"
34 | },
35 | "author": "chenglou ",
36 | "contributors": [
37 | {
38 | "name": "Jamison Dance",
39 | "email": "jergason@gmail.com",
40 | "url": "http://jamisondance.com"
41 | }
42 | ],
43 | "license": "MIT",
44 | "bugs": {
45 | "url": "https://github.com/chenglou/react-radio-group/issues"
46 | },
47 | "homepage": "https://github.com/chenglou/react-radio-group",
48 | "peerDependencies": {
49 | "react": ">=0.14.0",
50 | "react-dom": ">=15.5.4"
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/index.jsx:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | import React from 'react';
3 |
4 | export class Radio extends React.Component {
5 | render() {
6 | const {name, selectedValue, onChange} = this.context.radioGroup;
7 | const optional = {};
8 | if(selectedValue !== undefined) {
9 | optional.checked = (this.props.value === selectedValue);
10 | }
11 | if(typeof onChange === 'function') {
12 | optional.onChange = onChange.bind(null, this.props.value);
13 | }
14 |
15 | return (
16 |
23 | );
24 | }
25 | };
26 |
27 | Radio.contextTypes = {
28 | radioGroup: PropTypes.object
29 | };
30 |
31 | export class RadioGroup extends React.Component {
32 | getChildContext() {
33 | const {name, selectedValue, onChange} = this.props;
34 | return {
35 | radioGroup: {
36 | name, selectedValue, onChange
37 | }
38 | }
39 | }
40 |
41 | render() {
42 | const {Component, name, selectedValue, onChange, children, ...rest} = this.props;
43 | return {children};
44 | }
45 | };
46 |
47 | RadioGroup.defaultProps = {
48 | Component: "div"
49 | };
50 |
51 | RadioGroup.propTypes = {
52 | name: PropTypes.string,
53 | selectedValue: PropTypes.oneOfType([
54 | PropTypes.string,
55 | PropTypes.number,
56 | PropTypes.bool,
57 | ]),
58 | onChange: PropTypes.func,
59 | children: PropTypes.node.isRequired,
60 | Component: PropTypes.oneOfType([
61 | PropTypes.string,
62 | PropTypes.func,
63 | PropTypes.object,
64 | ])
65 | };
66 |
67 | RadioGroup.childContextTypes = {
68 | radioGroup: PropTypes.object
69 | };
70 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # [React](http://facebook.github.io/react/)-radio-group
2 |
3 | ```
4 | npm install react-radio-group
5 | ```
6 |
7 | Then either `import {RadioGroup, Radio} from 'react-radio-group'` or add `node_modules/react-radio-group/umd/index.js` into your HTML file (exports the `RadioGroup` global which contains both, the RadioGroup and Radio component.).
8 |
9 | ## What This Solves
10 | This is your average radio buttons group:
11 |
12 | ```js
13 |
18 | ```
19 |
20 | A few problems:
21 | - Repetitive fields (`name`, `type`, `checked`, `onChange`).
22 | - Hard to set the checked value. You need to put e.g. `checked={'apple' === this.state.selectedFruitName}` on every input.
23 | - Hard to retrieve the selected value.
24 |
25 | Here's a better version (full example [here](https://github.com/chenglou/react-radio-group/blob/67a2bcdc7f3d0c8cb4d7762f82558d75c9592ea9/example/example.jsx))
26 |
27 | ```js
28 |
29 | Apple
30 | Orange
31 | Watermelon
32 |
33 | ```
34 |
35 | Repetitive fields are either lifted onto the `RadioGroup` wrapper or already implicitly set on the `Radio` component, which is a simple wrapper around the radio `input`.
36 |
37 | ## Formal API
38 | #### <RadioGroup />
39 | Exposes [5 optional props](https://github.com/chenglou/react-radio-group/blob/67a2bcdc7f3d0c8cb4d7762f82558d75c9592ea9/index.jsx#L34-L46):
40 | - `name: String`: what you'd normally put on the radio inputs themselves.
41 | - `selectedValue: String | Number | Boolean`: the currently selected value. This will be used to compare against the values on the `Radio` components to select the right one.
42 | - `onChange: Function`: will be passed the newly selected value.
43 | - `Component: String | React Component`: defaults to `"div"`, defines what tag or component is used for rendering the `RadioGroup`
44 | - `children: Node`: define your `Radio`s and any other components. Each `Radio` component (a thin wrapper around `input`) within a `RadioGroup` will have some fields like `type`, `name` and `checked` prefilled.
45 |
46 | #### <Radio />
47 | Any prop you pass onto it will be transferred to the actual `input` under the hood. `Radio` components cannot be used outside a `RadioGroup`
48 |
49 | ## License
50 |
51 | [MIT](./LICENSE)
52 |
--------------------------------------------------------------------------------