Skip to content

Commit

Permalink
feat(Radio): 增加按钮样式的单选(RadioButton) (#725)
Browse files Browse the repository at this point in the history
  • Loading branch information
nullptr-z committed Mar 30, 2022
1 parent 8f76184 commit affe5ba
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 26 deletions.
56 changes: 44 additions & 12 deletions packages/react-radio/README.md
Expand Up @@ -8,9 +8,9 @@ Radio 单选框
单选框,在一组备选项中进行单选。

```jsx
import { Radio, RadioGroup } from 'uiw';
import { Radio, RadioButton, RadioGroup } from 'uiw';
// or
import { Radio, RadioGroup } from '@uiw/react-radio';
import { Radio, RadioButton, RadioGroup } from '@uiw/react-radio';
```

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

const Demo = () => (
<div>
<Radio value="1">Radio</Radio>
<Radio value="2" checked>选中</Radio>
<Radio value="3" disabled>禁用</Radio>
<Radio value="4" checked disabled>选中并禁用</Radio>
<Radio value="4" checked disabled>选中并禁用</Radio>
<RadioButton value="5" >RadioButton</RadioButton>
<RadioButton value="5" checked >RadioButton 选中</RadioButton>
</div>
);
ReactDOM.render(<Demo />, _mount_);
Expand All @@ -38,7 +41,7 @@ ReactDOM.render(<Demo />, _mount_);
<!--rehype:bgWhite=true&codeSandbox=true&codePen=true-->
```jsx
import ReactDOM from 'react-dom';
import { Form, Radio, RadioGroup, Row, Col, Button, Notify } from 'uiw';
import { Form, Radio, RadioGroup, RadioButton, Row, Col, Button, Notify } from 'uiw';

const Demo = () => (
<Form
Expand Down Expand Up @@ -75,6 +78,19 @@ const Demo = () => (
</RadioGroup>
),
},
radioButtonGroup: {
value: 'girl',
label: '请输入内容',
help: '必须选择性别!',
children: (
<RadioGroup>
<RadioButton value="man"></RadioButton>
<RadioButton value="girl"></RadioButton>
<RadioButton value="shemale">中性</RadioButton>
<RadioButton value="unknown">未知</RadioButton>
</RadioGroup>
),
},
radio: {
help: '请选择!该选项为必选!',
validator: (value) => !value ? '必填选项!' : null,
Expand All @@ -88,6 +104,9 @@ const Demo = () => (
<Row>
<Col>{fields.radioGroup}</Col>
</Row>
<Row>
<Col>{fields.radioButtonGroup}</Col>
</Row>
<Row>
<Col>{fields.radio}</Col>
</Row>
Expand Down Expand Up @@ -120,25 +139,31 @@ ReactDOM.render(<Demo />, _mount_);
```jsx
import React from 'react';
import ReactDOM from 'react-dom';
import { Radio, RadioGroup } from 'uiw';
import { Radio, RadioGroup, RadioButton } from 'uiw';

class Demo extends React.Component {
constructor(props) {
super(props);
this.state = { value: '未知' };
}
onChange(e) {
this.setState({ value: e.target.value });
onChange(value) {
this.setState({ value });
}
render() {
return (
<div>
<RadioGroup name="sexs" value={this.state.value} onChange={this.onChange.bind(this)}>
<RadioGroup name="sexs" value={this.state.value} onChange={(e)=>this.onChange(e.target.value)}>
<Radio value="man"></Radio>
<Radio value="girl"></Radio>
<Radio value="shemale" disabled>中性</Radio>
<Radio value="unknown" disabled>未知</Radio>
</RadioGroup>
<RadioGroup name="sexs" value={this.state.value} onChange={this.onChange.bind(this)} style={{ marginTop: 20 }}>
<RadioButton value="man"></RadioButton>
<RadioButton value="girl"></RadioButton>
<RadioButton value="shemale" disabled>中性</RadioButton>
<RadioButton value="unknown" disabled>未知</RadioButton>
</RadioGroup>
</div>
)
}
Expand All @@ -161,13 +186,13 @@ class Demo extends React.Component {
super(props);
this.state = { value: '未知' };
}
onChange(e) {
this.setState({ value: e.target.value });
onChange(value) {
this.setState({ value });
}
render() {
return (
<div>
<RadioGroup name="other" value={this.state.value} onChange={this.onChange.bind(this)}>
<RadioGroup name="other" value={this.state.value} onChange={(e)=>this.onChange(e.target.value)}>
<div>Group 1</div>
<Radio value=""></Radio>
<Radio value=""></Radio>
Expand All @@ -177,6 +202,13 @@ class Demo extends React.Component {
<div>Group 3</div>
<Radio value="E" style={{ display: 'block' }}>Item E</Radio>
<Radio value="F" style={{ display: 'block' }}>Item F</Radio>
<div>Group 3</div>
</RadioGroup>

<RadioGroup name="other" value={this.state.value} onChange={this.onChange.bind(this)} style={{ marginTop:20 }}>
<RadioButton value=""></RadioButton>
<RadioButton value=""></RadioButton>
<RadioButton value="未知">未知</RadioButton>
</RadioGroup>
<Divider />
<Button
Expand Down Expand Up @@ -205,7 +237,7 @@ ReactDOM.render(<Demo />, _mount_);
| disabled | 是否禁用 | Boolean | `false` |
| onChange | 数值改变时的回调,返回当前值 | Funtcion(e:Even) | - |

## RadioGroup
## RadioGroup

| 参数 | 说明 | 类型 | 默认值 |
|--------- |-------- |--------- |-------- |
Expand Down
4 changes: 3 additions & 1 deletion packages/react-radio/package.json
Expand Up @@ -44,6 +44,8 @@
"react-dom": ">=16.9.0"
},
"dependencies": {
"@uiw/utils": "^4.17.0"
"@uiw/utils": "^4.17.0",
"@uiw/react-button": "^4.17.0",
"@uiw/react-button-group": "^4.17.0"
}
}
73 changes: 73 additions & 0 deletions packages/react-radio/src/RadioButton.tsx
@@ -0,0 +1,73 @@
import React, { useState, useMemo } from 'react';
import { IProps, HTMLButtonProps } from '@uiw/utils';
import Button from '@uiw/react-button';

/**
* Constructs a type by picking all properties from `HTMLInputProps` and then removing `size`.
* Omit: https://www.typescriptlang.org/docs/handbook/utility-types.html#omittk
*/
export interface RadioButtonProps extends IProps, Omit<HTMLButtonProps, 'size'> {
size?: 'large' | 'default' | 'small';
checked?: boolean;
disabled?: boolean;
onChange?: (even: any) => void;
}

const RadioButton = React.forwardRef<any, RadioButtonProps>((props, ref) => {
const {
prefixCls = 'w-radio',
type = 'button',
disabled = false,
value = '',
className,
style,
children,
size = 'small',
checked: prChecked = false,
onChange,
...other
} = props;

const [checked, setChecked] = useState(prChecked);
const [prevChecked, setPrevChecked] = useState<boolean>();
if (prChecked !== prevChecked) {
setPrevChecked(prChecked);
}
useMemo(() => {
if (prChecked !== prevChecked) {
setChecked(prChecked);
}
}, [prevChecked]);

const cls = [prefixCls, className, disabled ? 'disabled' : null, size ? `${prefixCls}-${size}` : null]
.filter(Boolean)
.join(' ')
.trim();
useMemo(() => {
if (checked !== props.checked) {
setChecked(!!props.checked);
}
}, [props.checked]);
console.log('props.checked', props.checked);

function handleChange(e: React.MouseEvent<HTMLButtonElement, MouseEvent> & MouseEvent) {
e.persist();
setChecked(!checked);
onChange && onChange(value);
}

const label = children || value;

return (
<Button
{...{ ...other, className: cls, style, disabled, value }}
type={checked ? 'primary' : 'light'}
ref={ref}
onClick={handleChange}
>
{label}
</Button>
);
});

export default RadioButton;
27 changes: 15 additions & 12 deletions packages/react-radio/src/RadioGroup.tsx
@@ -1,6 +1,7 @@
import React from 'react';
import { IProps, HTMLDivProps } from '@uiw/utils';
import { RadioProps } from './Radio';
import ButtonGroup from '@uiw/react-button-group';
import './style/group.less';

export interface RadioGroupProps extends IProps, HTMLDivProps {
Expand All @@ -13,18 +14,20 @@ export default React.forwardRef<HTMLDivElement, RadioGroupProps>((props, ref) =>
const { prefixCls = 'w-radio-group', className, name, value, onChange, children, ...other } = props;
return (
<div {...other} ref={ref} className={[prefixCls, className].filter(Boolean).join(' ').trim()}>
{React.Children.toArray(children).map((child) => {
if (!child) return;
if (!React.isValidElement(child)) return child;
return React.cloneElement(child, {
...(child.props || {}),
...{
checked: child.props.value === value,
name,
onChange,
},
});
})}
<ButtonGroup>
{React.Children.toArray(children).map((child) => {
if (!child) return;
if (!React.isValidElement(child)) return child;
return React.cloneElement(child, {
...(child.props || {}),
...{
checked: child.props.value === value,
name,
onChange,
},
});
})}
</ButtonGroup>
</div>
);
});
2 changes: 2 additions & 0 deletions packages/react-radio/src/index.ts
@@ -1,5 +1,7 @@
export * from './Radio';
export * from './RadioGroup';
export * from './RadioAbstract';
export * from './RadioButton';
export { default as Radio } from './Radio';
export { default as RadioGroup } from './RadioGroup';
export { default as RadioButton } from './RadioButton';
3 changes: 2 additions & 1 deletion website/src/routes/components/radio/index.tsx
@@ -1,5 +1,5 @@
import React from 'react';
import { Radio, RadioGroup, Button, Divider, Form, Row, Col, Notify } from 'uiw';
import { Radio, RadioGroup, RadioButton, Button, Divider, Form, Row, Col, Notify } from 'uiw';
import Markdown from '../../../components/Markdown';

export default () => (
Expand All @@ -8,6 +8,7 @@ export default () => (
dependencies={{
Radio,
RadioGroup,
RadioButton,
Button,
Divider,
Form,
Expand Down

0 comments on commit affe5ba

Please sign in to comment.