UNPKG

@shopify/polaris

Version:

Shopify’s product component library

50 lines (49 loc) 2.64 kB
import React from 'react'; import { classNames } from '../../utilities/css'; import { useUniqueId } from '../../utilities/unique-id'; import { Checkbox } from '../Checkbox'; import { RadioButton } from '../RadioButton'; import { InlineError, errorTextID } from '../InlineError'; import styles from './ChoiceList.scss'; export function ChoiceList({ title, titleHidden, allowMultiple, choices, selected, onChange = noop, error, disabled = false, name: nameProp, }) { // Type asserting to any is required for TS3.2 but can be removed when we update to 3.3 // see https://github.com/Microsoft/TypeScript/issues/28768 const ControlComponent = allowMultiple ? Checkbox : RadioButton; const name = useUniqueId('ChoiceList', nameProp); const finalName = allowMultiple ? `${name}[]` : name; const className = classNames(styles.ChoiceList, titleHidden && styles.titleHidden); const titleMarkup = title ? (<legend className={styles.Title}>{title}</legend>) : null; const choicesMarkup = choices.map((choice) => { const { value, label, helpText, disabled: choiceDisabled, describedByError, } = choice; function handleChange(checked) { onChange(updateSelectedChoices(choice, checked, selected, allowMultiple), name); } const isSelected = choiceIsSelected(choice, selected); const renderedChildren = choice.renderChildren ? choice.renderChildren(isSelected) : null; const children = renderedChildren ? (<div className={styles.ChoiceChildren}>{renderedChildren}</div>) : null; return (<li key={value}> <ControlComponent name={finalName} value={value} label={label} disabled={choiceDisabled || disabled} checked={choiceIsSelected(choice, selected)} helpText={helpText} onChange={handleChange} ariaDescribedBy={error && describedByError ? errorTextID(finalName) : null}/> {children} </li>); }); const errorMarkup = error && (<div className={styles.ChoiceError}> <InlineError message={error} fieldID={finalName}/> </div>); return (<fieldset className={className} id={finalName} aria-invalid={error != null}> {titleMarkup} <ul className={styles.Choices}>{choicesMarkup}</ul> {errorMarkup} </fieldset>); } function noop() { } function choiceIsSelected({ value }, selected) { return selected.indexOf(value) >= 0; } function updateSelectedChoices({ value }, checked, selected, allowMultiple = false) { if (checked) { return allowMultiple ? [...selected, value] : [value]; } return selected.filter((selectedChoice) => selectedChoice !== value); }