-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #119 from communitiesuk/radio-component
Radios component
- Loading branch information
Showing
9 changed files
with
224 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import { Radios as RealComponent } from '../LazyLoader'; | ||
|
||
/** | ||
* Lazy loaded Radios | ||
* | ||
* @param { | ||
* id, | ||
* title, | ||
* options, | ||
* value, | ||
* } [props={}] | ||
* @return {*} | ||
*/ | ||
const Radios = (props = {}) => { | ||
return ( | ||
<RealComponent {...props} /> | ||
); | ||
} | ||
|
||
/** | ||
* PropTypes is a part of React, see full documenation below. | ||
* https://reactjs.org/docs/typechecking-with-proptypes.html | ||
*/ | ||
|
||
Radios.defaultProps = { | ||
options: [], | ||
value: [], | ||
}; | ||
|
||
Radios.propTypes = { | ||
/** | ||
* An array of options | ||
*/ | ||
options: PropTypes.oneOfType([ | ||
/** | ||
* Array of options where the label and the value are the same thing - [string|number|bool] | ||
*/ | ||
PropTypes.arrayOf( | ||
PropTypes.oneOfType([ | ||
PropTypes.string, | ||
PropTypes.number, | ||
PropTypes.bool, | ||
]) | ||
), | ||
/** | ||
* Simpler `options` representation in dictionary format. The order is not guaranteed. | ||
* {`value1`: `label1`, `value2`: `label2`, ... } | ||
* which is equal to | ||
* [{label: `label1`, value: `value1`}, {label: `label2`, value: `value2`}, ...] | ||
*/ | ||
PropTypes.object, | ||
/** | ||
* An array of options {label: [string|number], value: [string|number]}, | ||
* an optional disabled field can be used for each option | ||
*/ | ||
PropTypes.arrayOf( | ||
PropTypes.exact({ | ||
/** | ||
* The option's label | ||
*/ | ||
label: PropTypes.node.isRequired, | ||
|
||
/** | ||
* The value of the option. This value | ||
* corresponds to the items specified in the | ||
* `value` property. | ||
*/ | ||
value: PropTypes.oneOfType([ | ||
PropTypes.string, | ||
PropTypes.number, | ||
PropTypes.bool, | ||
]).isRequired, | ||
|
||
/** | ||
* If true, this option is disabled and cannot be selected. | ||
*/ | ||
disabled: PropTypes.bool, | ||
|
||
/** | ||
* The HTML 'title' attribute for the option. Allows for | ||
* information on hover. For more information on this attribute, | ||
* see https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/title | ||
*/ | ||
title: PropTypes.string, | ||
}) | ||
), | ||
]), | ||
|
||
/** | ||
* The currently selected value | ||
*/ | ||
value: PropTypes.oneOfType([ | ||
PropTypes.string, | ||
PropTypes.number, | ||
PropTypes.bool, | ||
]), | ||
|
||
/** | ||
* The ID of this component, used to identify dash components | ||
* in callbacks. The ID needs to be unique across all of the | ||
* components in an app. | ||
*/ | ||
id: PropTypes.string, | ||
|
||
/** | ||
* The title to be displayed above all Radio items. | ||
*/ | ||
title: PropTypes.string, | ||
|
||
/** | ||
* Dash-assigned callback that gets fired when the value changes. | ||
*/ | ||
setProps: PropTypes.func, | ||
}; | ||
|
||
export const defaultProps = Radios.defaultProps; | ||
export const propTypes = Radios.propTypes; | ||
|
||
export default Radios |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import { type } from 'ramda'; | ||
|
||
import React, { useState } from 'react'; | ||
|
||
import { defaultProps, propTypes } from '../components/Radios.react'; | ||
|
||
const sanitizeOptions = options => { | ||
if (type(options) === 'Object') { | ||
return Object.entries(options).map(([value, label]) => ({ | ||
label: React.isValidElement(label) ? label : String(label), | ||
value, | ||
})); | ||
} | ||
|
||
if (type(options) === 'Array') { | ||
if ( | ||
options.length > 0 && | ||
['String', 'Number', 'Bool'].includes(type(options[0])) | ||
) { | ||
return options.map(option => ({ | ||
label: String(option), | ||
value: option, | ||
})); | ||
} | ||
return options; | ||
} | ||
|
||
return options; | ||
}; | ||
|
||
/** | ||
* Radios is a component that encapsulates several radios. | ||
* The values and labels of the Radios list are specified in the `options` | ||
* property and the selected item is specified with the `value` property. | ||
* Only one Radio item can be selected at once. | ||
* Each Radio item is rendered as an input with a surrounding label. | ||
*/ | ||
const Radios = (props)=>{ | ||
const { | ||
id, | ||
title, | ||
options, | ||
setProps, | ||
value: propValue, | ||
} = { ...defaultProps, ...props }; | ||
|
||
// State to manage the selected radio value | ||
const [value, setValue] = useState(propValue); | ||
|
||
if (!id) { throw new Error('id is not defined') } | ||
|
||
const handleChange = (newValue) => { | ||
setValue(newValue); // Update local state | ||
setProps({ value: newValue }); // Propagate value to parent component | ||
}; | ||
|
||
return ( | ||
<div className='govuk-form-group' id={id}> | ||
<fieldset className='govuk-fieldset'> | ||
<legend className='govuk-fieldset__legend govuk-fieldset__legend--l'> | ||
<label className="govuk-label">{title}</label> | ||
</legend> | ||
<div className="govuk-radios govuk-radios--small" data-module="govuk-radios"> | ||
{sanitizeOptions(options).map((option, index) => { | ||
return ( | ||
<div className="govuk-radios__item" key={option.value}> | ||
<input checked={value==option.value} className="govuk-radios__input" | ||
type="radio" id={`${id}_option_${index}`} value={option.value} name={id} | ||
onChange={() => handleChange(option.value)} | ||
/> | ||
<label className="govuk-label govuk-radios__label" htmlFor={`${id}_option_${index}`}> | ||
{option.label} | ||
</label> | ||
</div> | ||
); | ||
})} | ||
</div> | ||
</fieldset> | ||
</div> | ||
) | ||
} | ||
|
||
Radios.defaultProps = defaultProps; | ||
Radios.propTypes = propTypes; | ||
|
||
export default Radios |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters