diff --git a/src/components/TextEditor/components/EditorRadio.js b/src/components/TextEditor/components/EditorRadio.js
index e9363cf1..204414c4 100644
--- a/src/components/TextEditor/components/EditorRadio.js
+++ b/src/components/TextEditor/components/EditorRadio.js
@@ -1,6 +1,6 @@
import React from 'react';
import { CODE_AND_OUTPUT, CODE_ONLY, OUTPUT_ONLY } from '../../../constants';
-import Radio from '../../common/Radio.js';
+import Radio from '../../common/Radio';
const EditorRadio = function (props) {
let options = [];
diff --git a/src/components/common/Radio.js b/src/components/common/Radio.js
deleted file mode 100644
index 25c4735d..00000000
--- a/src/components/common/Radio.js
+++ /dev/null
@@ -1,116 +0,0 @@
-import React from 'react';
-import '../../styles/Radio.scss';
-/**
- * Props
- *
- * options: (array of jsons) content for each box
- * each json should look like {
- * display: "Text to be displayed",
- * (optional) value: the hidden value correlating to the display value (defaults to the index)
- * }
- * defaultSelected: (same type as options' value key) the option that will be default selected
- * CAREFUL: if handleClick causes Radio to be re-rendered, make sure you're fine
- * with this variable always being the defaultSelected
- * containerStyle: (json) overrides the style on the outer container
- * optionStyle: (json) overrides the style on each individual option
- * selectedOptionStyle: (json) overrides the style on the selected option
- * bgColor: (string) color of the non selected options
- * color: (string) color of the non selected options text
- * selectedBgColor: (string) color of the selected option
- * selectedColor: (string) color of the selected options text
- * handleClick: (func) function to be called when an option is clicked
- * should have 1 parameter (value) which is the value
- * (from the options prop) that is selected (defaults to index)
- * allowMultipleSelected: (bool) if true, allows multiple options to be selected
- * changes handle click to be called with all selected values
- */
-
-export default class Radio extends React.Component {
- constructor(props) {
- super(props);
-
- let selected = this.props.defaultSelected;
- if (this.props.allowMultipleSelected) {
- selected = selected || [];
- }
-
- this.state = {
- selected,
- };
- }
-
- updateSelectedState = (selected, alreadySelected) => {
- if (this.props.allowMultipleSelected) {
- let newState = this.state.selected;
- if (alreadySelected) {
- const i = this.state.selected.indexOf(selected);
- if (i >= 0) newState.splice(i, 1);
- } else {
- newState = this.state.selected.concat([selected]);
- }
- if (this.props.handleClick) {
- this.props.handleClick(newState);
- }
- this.setState({ selected: newState });
- } else {
- if (this.props.handleClick) {
- this.props.handleClick(selected);
- }
- this.setState({ selected });
- }
- };
-
- renderOption = ({ display, value }, index) => {
- // if no value is provided, use the index
- value = value || index;
-
- const isSelected = value === this.state.selected
- || (this.props.allowMultipleSelected && this.state.selected.includes(value));
- // attach -selected if the value matches the selected state
- const className = `radio-option${isSelected ? '-selected' : ''}`;
- // add an id of radio-left if its the first option or radio-right if its the last option
- const id = index === 0 ? 'radio-left' : index === this.props.options.length - 1 ? 'radio-right' : '';
-
- let optionStyle;
- if (isSelected) {
- optionStyle = {
-
- ...this.props.optionStyle || {},
- ...this.props.selectedOptionStyle || {},
- ...(this.props.selectedBgColor ? { backgroundColor: this.props.selectedBgColor } : {}),
- ...(this.props.selectedColor ? { color: this.props.selectedColor } : {}),
- };
- } else {
- optionStyle = {
-
- ...this.props.optionStyle || {},
- ...(this.props.bgColor ? { backgroundColor: this.props.bgColor } : {}),
- ...(this.props.color ? { color: this.props.color } : {}),
- };
- }
-
- return (
-
this.updateSelectedState(value, isSelected)}
- style={optionStyle}
- id={id}
- key={index}
- >
- {display}
-
- );
- };
-
- render() {
- const { containerStyle } = this.props;
-
- const options = this.props.options || [];
-
- return (
-
- {options.map(this.renderOption)}
-
- );
- }
-}
diff --git a/src/components/common/Radio.test.js b/src/components/common/Radio.test.js
index b5a5119e..d0db3711 100644
--- a/src/components/common/Radio.test.js
+++ b/src/components/common/Radio.test.js
@@ -1,6 +1,6 @@
import { shallow } from 'enzyme';
import React from 'react';
-import Radio from './Radio.js';
+import Radio from './Radio';
const validOptions = [
{
@@ -43,10 +43,7 @@ describe('Radio', () => {
// on click option, invalid handle click does not cause error
const component = shallow();
expect(() => {
- component
- .find('.radio-option')
- .at(0)
- .simulate('click');
+ component.find('.radio-option').at(0).simulate('click');
}).not.toThrow();
});
@@ -107,7 +104,10 @@ describe('Radio', () => {
{
expect(clickFn.mock.calls[0][0]).toBe('pear');
// clicking a non selected option causes the selected value to change
- component
- .find('.radio-option')
- .at(0)
- .simulate('click');
+ component.find('.radio-option').at(0).simulate('click');
expect(clickFn.mock.calls[1][0]).toBe('banana');
expect(component.state().selected).toBe('banana');
expect(component.find('.radio-option-selected').text()).toBe('Nice');
@@ -163,10 +160,7 @@ describe('Radio', () => {
expect(component2.state().selected).toStrictEqual(['banana', 'apple', 'pear']);
// click on already selected value, make sure it gets removed
- component2
- .find('.radio-option-selected')
- .at(0)
- .simulate('click');
+ component2.find('.radio-option-selected').at(0).simulate('click');
expect(clickFn.mock.calls[1][0]).toStrictEqual(['apple', 'pear']);
expect(component2.state().selected).toStrictEqual(['apple', 'pear']);
});
diff --git a/src/components/common/Radio.tsx b/src/components/common/Radio.tsx
new file mode 100644
index 00000000..00381d33
--- /dev/null
+++ b/src/components/common/Radio.tsx
@@ -0,0 +1,165 @@
+import React from 'react';
+import '../../styles/Radio.scss';
+/**
+ * Props
+ *
+ * options: (array of jsons) content for each box
+ * each json should look like {
+ * display: "Text to be displayed",
+ * (optional) value: the hidden value correlating to the display value (defaults to the index)
+ * }
+ * defaultSelected: (same type as options' value key) the option that will be default selected
+ * CAREFUL: if handleClick causes Radio to be re-rendered, make sure you're fine
+ * with this variable always being the defaultSelected
+ * containerStyle: (json) overrides the style on the outer container
+ * optionStyle: (json) overrides the style on each individual option
+ * selectedOptionStyle: (json) overrides the style on the selected option
+ * bgColor: (string) color of the non selected options
+ * color: (string) color of the non selected options text
+ * selectedBgColor: (string) color of the selected option
+ * selectedColor: (string) color of the selected options text
+ * handleClick: (func) function to be called when an option is clicked
+ * should have 1 parameter (value) which is the value
+ * (from the options prop) that is selected (defaults to index)
+ * allowMultipleSelected: (bool) if true, allows multiple options to be selected
+ * changes handle click to be called with all selected values
+ */
+
+interface OptionItem {
+ display: string;
+ value: string;
+}
+
+interface RadioProps {
+ defaultSelected: T;
+ allowMultipleSelected: boolean;
+ options: OptionItem[];
+ containerStyle: any;
+ optionStyle: any;
+ selectedOptionStyle: any;
+ selectedBgColor: any;
+ selectedColor: any;
+ bgColor: any;
+ color: any;
+ handleClick: (arg0: string) => string;
+}
+
+interface RadioState {
+ selected?: any;
+}
+
+class Radio extends React.Component , RadioState> {
+ // static defaultProps: Partial> = defaultProps;
+ constructor(props: RadioProps) {
+ super(props);
+
+ const { allowMultipleSelected, defaultSelected } = this.props;
+
+ let selected: T | T[] | undefined = defaultSelected;
+ if (allowMultipleSelected) {
+ selected = selected || [];
+ }
+
+ this.state = {
+ selected,
+ };
+ }
+
+ updateSelectedState = (selected_value: string, alreadySelected: boolean): void => {
+ const { allowMultipleSelected, handleClick } = this.props;
+
+ if (allowMultipleSelected) {
+ const { selected } = this.state;
+ let newState = selected;
+ if (alreadySelected) {
+ const i = selected.indexOf(selected_value);
+ if (i >= 0) newState.splice(i, 1);
+ } else {
+ newState = selected.concat([selected_value]);
+ }
+ if (handleClick) {
+ handleClick(newState);
+ }
+ this.setState({ selected: newState });
+ } else {
+ if (handleClick) {
+ handleClick(selected_value);
+ }
+ this.setState({ selected: selected_value });
+ }
+ };
+
+ renderOption = ({ display, value }: OptionItem, index: number): JSX.Element => {
+ // if no value is provided, use the index
+ // value = value || index;
+ const { selected } = this.state;
+ const { allowMultipleSelected, options } = this.props;
+ const isSelected = value === selected
+ || (allowMultipleSelected && selected.includes(value));
+ // attach -selected if the value matches the selected state
+ const className = `radio-option${isSelected ? '-selected' : ''}`;
+ // add an id of radio-left if its the first option or radio-right if its the last option
+ let idValue;
+ if (index === 0) {
+ idValue = 'radio-left';
+ } else if (index === options.length - 1) {
+ idValue = 'radio-right';
+ } else {
+ idValue = '';
+ }
+ const id = idValue;
+
+ let newOptionStyle;
+ const {
+ optionStyle, selectedOptionStyle, selectedBgColor, selectedColor, bgColor, color,
+ } = this.props;
+ if (isSelected) {
+ newOptionStyle = {
+
+ ...optionStyle || {},
+ ...selectedOptionStyle || {},
+ ...(selectedBgColor ? { backgroundColor: selectedBgColor } : {}),
+ ...(selectedColor ? { color: selectedColor } : {}),
+ };
+ } else {
+ newOptionStyle = {
+
+ ...optionStyle || {},
+ ...(bgColor ? { backgroundColor: bgColor } : {}),
+ ...(color ? { color } : {}),
+ };
+ }
+
+ return (
+ this.updateSelectedState(value, isSelected)}
+ onKeyDown={(e) => {
+ if (e.key === 'Enter') {
+ this.updateSelectedState(value, isSelected);
+ }
+ }}
+ style={newOptionStyle}
+ id={id}
+ key={index}
+ >
+ {display}
+
+ );
+ };
+
+ render() {
+ const { containerStyle, options } = this.props;
+ const optionsMap = options || [];
+
+ return (
+
+ {optionsMap.map(this.renderOption)}
+
+ );
+ }
+}
+
+export default Radio;