Skip to content

Commit affe5ba

Browse files
authoredMar 30, 2022
feat(Radio): 增加按钮样式的单选(RadioButton) (#725)
1 parent 8f76184 commit affe5ba

File tree

6 files changed

+139
-26
lines changed

6 files changed

+139
-26
lines changed
 

‎packages/react-radio/README.md

+44-12
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ Radio 单选框
88
单选框,在一组备选项中进行单选。
99

1010
```jsx
11-
import { Radio, RadioGroup } from 'uiw';
11+
import { Radio, RadioButton, RadioGroup } from 'uiw';
1212
// or
13-
import { Radio, RadioGroup } from '@uiw/react-radio';
13+
import { Radio, RadioButton, RadioGroup } from '@uiw/react-radio';
1414
```
1515

1616
### 基础用法
@@ -20,14 +20,17 @@ import { Radio, RadioGroup } from '@uiw/react-radio';
2020
<!--rehype:bgWhite=true&codeSandbox=true&codePen=true-->
2121
```jsx
2222
import ReactDOM from 'react-dom';
23-
import { Radio } from 'uiw';
23+
import { Radio, RadioButton } from 'uiw';
2424

2525
const Demo = () => (
2626
<div>
2727
<Radio value="1">Radio</Radio>
2828
<Radio value="2" checked>选中</Radio>
2929
<Radio value="3" disabled>禁用</Radio>
3030
<Radio value="4" checked disabled>选中并禁用</Radio>
31+
<Radio value="4" checked disabled>选中并禁用</Radio>
32+
<RadioButton value="5" >RadioButton</RadioButton>
33+
<RadioButton value="5" checked >RadioButton 选中</RadioButton>
3134
</div>
3235
);
3336
ReactDOM.render(<Demo />, _mount_);
@@ -38,7 +41,7 @@ ReactDOM.render(<Demo />, _mount_);
3841
<!--rehype:bgWhite=true&codeSandbox=true&codePen=true-->
3942
```jsx
4043
import ReactDOM from 'react-dom';
41-
import { Form, Radio, RadioGroup, Row, Col, Button, Notify } from 'uiw';
44+
import { Form, Radio, RadioGroup, RadioButton, Row, Col, Button, Notify } from 'uiw';
4245

4346
const Demo = () => (
4447
<Form
@@ -75,6 +78,19 @@ const Demo = () => (
7578
</RadioGroup>
7679
),
7780
},
81+
radioButtonGroup: {
82+
value: 'girl',
83+
label: '请输入内容',
84+
help: '必须选择性别!',
85+
children: (
86+
<RadioGroup>
87+
<RadioButton value="man"></RadioButton>
88+
<RadioButton value="girl"></RadioButton>
89+
<RadioButton value="shemale">中性</RadioButton>
90+
<RadioButton value="unknown">未知</RadioButton>
91+
</RadioGroup>
92+
),
93+
},
7894
radio: {
7995
help: '请选择!该选项为必选!',
8096
validator: (value) => !value ? '必填选项!' : null,
@@ -88,6 +104,9 @@ const Demo = () => (
88104
<Row>
89105
<Col>{fields.radioGroup}</Col>
90106
</Row>
107+
<Row>
108+
<Col>{fields.radioButtonGroup}</Col>
109+
</Row>
91110
<Row>
92111
<Col>{fields.radio}</Col>
93112
</Row>
@@ -120,25 +139,31 @@ ReactDOM.render(<Demo />, _mount_);
120139
```jsx
121140
import React from 'react';
122141
import ReactDOM from 'react-dom';
123-
import { Radio, RadioGroup } from 'uiw';
142+
import { Radio, RadioGroup, RadioButton } from 'uiw';
124143

125144
class Demo extends React.Component {
126145
constructor(props) {
127146
super(props);
128147
this.state = { value: '未知' };
129148
}
130-
onChange(e) {
131-
this.setState({ value: e.target.value });
149+
onChange(value) {
150+
this.setState({ value });
132151
}
133152
render() {
134153
return (
135154
<div>
136-
<RadioGroup name="sexs" value={this.state.value} onChange={this.onChange.bind(this)}>
155+
<RadioGroup name="sexs" value={this.state.value} onChange={(e)=>this.onChange(e.target.value)}>
137156
<Radio value="man"></Radio>
138157
<Radio value="girl"></Radio>
139158
<Radio value="shemale" disabled>中性</Radio>
140159
<Radio value="unknown" disabled>未知</Radio>
141160
</RadioGroup>
161+
<RadioGroup name="sexs" value={this.state.value} onChange={this.onChange.bind(this)} style={{ marginTop: 20 }}>
162+
<RadioButton value="man"></RadioButton>
163+
<RadioButton value="girl"></RadioButton>
164+
<RadioButton value="shemale" disabled>中性</RadioButton>
165+
<RadioButton value="unknown" disabled>未知</RadioButton>
166+
</RadioGroup>
142167
</div>
143168
)
144169
}
@@ -161,13 +186,13 @@ class Demo extends React.Component {
161186
super(props);
162187
this.state = { value: '未知' };
163188
}
164-
onChange(e) {
165-
this.setState({ value: e.target.value });
189+
onChange(value) {
190+
this.setState({ value });
166191
}
167192
render() {
168193
return (
169194
<div>
170-
<RadioGroup name="other" value={this.state.value} onChange={this.onChange.bind(this)}>
195+
<RadioGroup name="other" value={this.state.value} onChange={(e)=>this.onChange(e.target.value)}>
171196
<div>Group 1</div>
172197
<Radio value=""></Radio>
173198
<Radio value=""></Radio>
@@ -177,6 +202,13 @@ class Demo extends React.Component {
177202
<div>Group 3</div>
178203
<Radio value="E" style={{ display: 'block' }}>Item E</Radio>
179204
<Radio value="F" style={{ display: 'block' }}>Item F</Radio>
205+
<div>Group 3</div>
206+
</RadioGroup>
207+
208+
<RadioGroup name="other" value={this.state.value} onChange={this.onChange.bind(this)} style={{ marginTop:20 }}>
209+
<RadioButton value=""></RadioButton>
210+
<RadioButton value=""></RadioButton>
211+
<RadioButton value="未知">未知</RadioButton>
180212
</RadioGroup>
181213
<Divider />
182214
<Button
@@ -205,7 +237,7 @@ ReactDOM.render(<Demo />, _mount_);
205237
| disabled | 是否禁用 | Boolean | `false` |
206238
| onChange | 数值改变时的回调,返回当前值 | Funtcion(e:Even) | - |
207239

208-
## RadioGroup
240+
## RadioGroup
209241

210242
| 参数 | 说明 | 类型 | 默认值 |
211243
|--------- |-------- |--------- |-------- |

‎packages/react-radio/package.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@
4444
"react-dom": ">=16.9.0"
4545
},
4646
"dependencies": {
47-
"@uiw/utils": "^4.17.0"
47+
"@uiw/utils": "^4.17.0",
48+
"@uiw/react-button": "^4.17.0",
49+
"@uiw/react-button-group": "^4.17.0"
4850
}
4951
}
+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import React, { useState, useMemo } from 'react';
2+
import { IProps, HTMLButtonProps } from '@uiw/utils';
3+
import Button from '@uiw/react-button';
4+
5+
/**
6+
* Constructs a type by picking all properties from `HTMLInputProps` and then removing `size`.
7+
* Omit: https://www.typescriptlang.org/docs/handbook/utility-types.html#omittk
8+
*/
9+
export interface RadioButtonProps extends IProps, Omit<HTMLButtonProps, 'size'> {
10+
size?: 'large' | 'default' | 'small';
11+
checked?: boolean;
12+
disabled?: boolean;
13+
onChange?: (even: any) => void;
14+
}
15+
16+
const RadioButton = React.forwardRef<any, RadioButtonProps>((props, ref) => {
17+
const {
18+
prefixCls = 'w-radio',
19+
type = 'button',
20+
disabled = false,
21+
value = '',
22+
className,
23+
style,
24+
children,
25+
size = 'small',
26+
checked: prChecked = false,
27+
onChange,
28+
...other
29+
} = props;
30+
31+
const [checked, setChecked] = useState(prChecked);
32+
const [prevChecked, setPrevChecked] = useState<boolean>();
33+
if (prChecked !== prevChecked) {
34+
setPrevChecked(prChecked);
35+
}
36+
useMemo(() => {
37+
if (prChecked !== prevChecked) {
38+
setChecked(prChecked);
39+
}
40+
}, [prevChecked]);
41+
42+
const cls = [prefixCls, className, disabled ? 'disabled' : null, size ? `${prefixCls}-${size}` : null]
43+
.filter(Boolean)
44+
.join(' ')
45+
.trim();
46+
useMemo(() => {
47+
if (checked !== props.checked) {
48+
setChecked(!!props.checked);
49+
}
50+
}, [props.checked]);
51+
console.log('props.checked', props.checked);
52+
53+
function handleChange(e: React.MouseEvent<HTMLButtonElement, MouseEvent> & MouseEvent) {
54+
e.persist();
55+
setChecked(!checked);
56+
onChange && onChange(value);
57+
}
58+
59+
const label = children || value;
60+
61+
return (
62+
<Button
63+
{...{ ...other, className: cls, style, disabled, value }}
64+
type={checked ? 'primary' : 'light'}
65+
ref={ref}
66+
onClick={handleChange}
67+
>
68+
{label}
69+
</Button>
70+
);
71+
});
72+
73+
export default RadioButton;
+15-12
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React from 'react';
22
import { IProps, HTMLDivProps } from '@uiw/utils';
33
import { RadioProps } from './Radio';
4+
import ButtonGroup from '@uiw/react-button-group';
45
import './style/group.less';
56

67
export interface RadioGroupProps extends IProps, HTMLDivProps {
@@ -13,18 +14,20 @@ export default React.forwardRef<HTMLDivElement, RadioGroupProps>((props, ref) =>
1314
const { prefixCls = 'w-radio-group', className, name, value, onChange, children, ...other } = props;
1415
return (
1516
<div {...other} ref={ref} className={[prefixCls, className].filter(Boolean).join(' ').trim()}>
16-
{React.Children.toArray(children).map((child) => {
17-
if (!child) return;
18-
if (!React.isValidElement(child)) return child;
19-
return React.cloneElement(child, {
20-
...(child.props || {}),
21-
...{
22-
checked: child.props.value === value,
23-
name,
24-
onChange,
25-
},
26-
});
27-
})}
17+
<ButtonGroup>
18+
{React.Children.toArray(children).map((child) => {
19+
if (!child) return;
20+
if (!React.isValidElement(child)) return child;
21+
return React.cloneElement(child, {
22+
...(child.props || {}),
23+
...{
24+
checked: child.props.value === value,
25+
name,
26+
onChange,
27+
},
28+
});
29+
})}
30+
</ButtonGroup>
2831
</div>
2932
);
3033
});

‎packages/react-radio/src/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
export * from './Radio';
22
export * from './RadioGroup';
33
export * from './RadioAbstract';
4+
export * from './RadioButton';
45
export { default as Radio } from './Radio';
56
export { default as RadioGroup } from './RadioGroup';
7+
export { default as RadioButton } from './RadioButton';

‎website/src/routes/components/radio/index.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React from 'react';
2-
import { Radio, RadioGroup, Button, Divider, Form, Row, Col, Notify } from 'uiw';
2+
import { Radio, RadioGroup, RadioButton, Button, Divider, Form, Row, Col, Notify } from 'uiw';
33
import Markdown from '../../../components/Markdown';
44

55
export default () => (
@@ -8,6 +8,7 @@ export default () => (
88
dependencies={{
99
Radio,
1010
RadioGroup,
11+
RadioButton,
1112
Button,
1213
Divider,
1314
Form,

0 commit comments

Comments
 (0)
Please sign in to comment.