@patreon/studio
Version:
Patreon Studio Design System
56 lines (55 loc) • 3.11 kB
JSX
'use client';
import React, { useId } from 'react';
import { IconChevronDownAlt } from '~/components/Icon';
import { InlineHelpText } from '~/components/InlineHelpText';
import { Label } from '~/components/Label';
import { useTestIdGenerator } from '~/hooks/useTestIdGenerator';
import { isRequired } from '~/utilities/isRequired';
import { IconWrapper, InputWrapper, LabelWrapper, SelectWrapper, StyledSelect } from './components';
export const Select = React.forwardRef(function Select({ 'aria-label': ariaLabel, 'data-tag': dataTag, disabled, error, helperText, id, loading, onChange, options, primaryLabel, required, secondaryLabel, success, width = 'default', variant = 'outlined', corners = 'rounded', ...props }, ref) {
const multipleDefaults = options.filter((el) => el.defaultSelected === true).length > 1;
if (multipleDefaults) {
throw new Error('Multiple options are set as `defaultSelected` which will put `Select` in an indeterminate state. The `defaultSelected` prop can only be set on one option.');
}
const localId = useId();
const thisId = id ?? localId ?? '';
const primaryLabelId = `${thisId}-primary-label`;
const secondaryLabelId = `${thisId}-secondary-label`;
const errorId = `${thisId}-error`;
const successId = `${thisId}-success`;
const helpTextId = `${thisId}-help`;
const getTestId = useTestIdGenerator(dataTag);
const describedBy = [];
if (error) {
describedBy.push(errorId);
}
if (success) {
describedBy.push(successId);
}
if (helperText) {
describedBy.push(helpTextId);
}
return (<InputWrapper disabled={disabled} isFluid={width === 'fluid'}>
<LabelWrapper primaryLabel={primaryLabel} secondaryLabel={secondaryLabel}>
{primaryLabel && (<Label data-tag={getTestId('primaryLabel')} id={primaryLabelId} error={!!error} htmlFor={thisId}>
{primaryLabel}
{isRequired(required) && ' *'}
</Label>)}
{secondaryLabel && (<Label secondary data-tag={getTestId('secondaryLabel')} id={secondaryLabelId} error={!!error} htmlFor={thisId}>
{secondaryLabel}
</Label>)}
</LabelWrapper>
<SelectWrapper>
<StyledSelect id={thisId} ref={ref} error={error} variant={variant} disabled={disabled} onChange={onChange} defaultValue={options.find((el) => el.defaultSelected === true)?.value} aria-describedby={describedBy.length ? describedBy.join(' ') : undefined} aria-required={isRequired(required)} aria-label={ariaLabel} data-tag={dataTag} corners={corners} {...props}>
{options.map(({ value, label, disabled: optionDisabled }) => (<option value={value} key={value} disabled={optionDisabled}>
{label}
</option>))}
</StyledSelect>
<IconWrapper>
<IconChevronDownAlt size="20px"/>
</IconWrapper>
</SelectWrapper>
<InlineHelpText id={helpTextId} inputId={thisId} helpText={helperText} error={error} success={success} loading={loading} data-tag={dataTag}/>
</InputWrapper>);
});
//# sourceMappingURL=Select.jsx.map