1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 | import * as React from "react";
|
18 | import { polyfill } from "react-lifecycles-compat";
|
19 |
|
20 | import { AbstractPureComponent2, Classes } from "../../common";
|
21 | import * as Errors from "../../common/errors";
|
22 | import { DISPLAYNAME_PREFIX, OptionProps, Props } from "../../common/props";
|
23 | import { isElementOfType } from "../../common/utils";
|
24 | import { RadioProps, Radio } from "./controls";
|
25 |
|
26 |
|
27 | export type RadioGroupProps = IRadioGroupProps;
|
28 |
|
29 | export interface IRadioGroupProps extends Props {
|
30 | |
31 |
|
32 |
|
33 |
|
34 | disabled?: boolean;
|
35 |
|
36 | |
37 |
|
38 |
|
39 | inline?: boolean;
|
40 |
|
41 |
|
42 | label?: React.ReactNode;
|
43 |
|
44 | |
45 |
|
46 |
|
47 |
|
48 | name?: string;
|
49 |
|
50 | |
51 |
|
52 |
|
53 |
|
54 |
|
55 | onChange: (event: React.FormEvent<HTMLInputElement>) => void;
|
56 |
|
57 | |
58 |
|
59 |
|
60 |
|
61 |
|
62 | options?: OptionProps[];
|
63 |
|
64 |
|
65 | selectedValue?: string | number;
|
66 | }
|
67 |
|
68 | let counter = 0;
|
69 | function nextName() {
|
70 | return `${RadioGroup.displayName}-${counter++}`;
|
71 | }
|
72 |
|
73 | @polyfill
|
74 | export class RadioGroup extends AbstractPureComponent2<RadioGroupProps> {
|
75 | public static displayName = `${DISPLAYNAME_PREFIX}.RadioGroup`;
|
76 |
|
77 |
|
78 | private autoGroupName = nextName();
|
79 |
|
80 | public render() {
|
81 | const { label } = this.props;
|
82 | return (
|
83 | <div className={this.props.className}>
|
84 | {label == null ? null : <label className={Classes.LABEL}>{label}</label>}
|
85 | {Array.isArray(this.props.options) ? this.renderOptions() : this.renderChildren()}
|
86 | </div>
|
87 | );
|
88 | }
|
89 |
|
90 | protected validateProps() {
|
91 | if (this.props.children != null && this.props.options != null) {
|
92 | console.warn(Errors.RADIOGROUP_WARN_CHILDREN_OPTIONS_MUTEX);
|
93 | }
|
94 | }
|
95 |
|
96 | private renderChildren() {
|
97 | return React.Children.map(this.props.children, child => {
|
98 | if (isElementOfType(child, Radio)) {
|
99 | return React.cloneElement(child, this.getRadioProps(child.props as OptionProps));
|
100 | } else {
|
101 | return child;
|
102 | }
|
103 | });
|
104 | }
|
105 |
|
106 | private renderOptions() {
|
107 | return this.props.options?.map(option => (
|
108 | <Radio {...this.getRadioProps(option)} key={option.value} labelElement={option.label || option.value} />
|
109 | ));
|
110 | }
|
111 |
|
112 | private getRadioProps(optionProps: OptionProps): RadioProps {
|
113 | const { name } = this.props;
|
114 | const { className, disabled, value } = optionProps;
|
115 | return {
|
116 | checked: value === this.props.selectedValue,
|
117 | className,
|
118 | disabled: disabled || this.props.disabled,
|
119 | inline: this.props.inline,
|
120 | name: name == null ? this.autoGroupName : name,
|
121 | onChange: this.props.onChange,
|
122 | value,
|
123 | };
|
124 | }
|
125 | }
|