import * as React from "react";
import { cx } from "@emotion/css";
import CheckboxInput from "../../checkboxInput/components/CheckboxInput";
import RadioInput from "../../radioInput/RadioInput";
import FormFieldWrapper from "../../shared/components/FormFieldWrapper";
import {
listReset,
fieldsetReset,
legendReset,
padding,
visuallyHidden
} from "../../shared/styles/styleUtils";
import { InputAppearance } from "../../shared/types/inputAppearance";
import { getLabelStyle } from "../../shared/styles/formStyles";
import { DangerText } from "../../index";
export interface ToggleInputProperties {
appearance?: InputAppearance;
inputLabel: string;
id: string;
value: string;
disabled?: boolean;
errors?: React.ReactNode[];
hintContent?: React.ReactNode;
}
export interface ToggleInputListProps {
/**
* Allows custom styling
*/
className?: string;
/**
* Sets the contents for validation errors. This will be displayed below the list of options.
*/
errors?: React.ReactNode[];
/**
* hintContent is text or a ReactNode that is displayed directly under the set of options with additional information about the expected input.
*/
hintContent?: React.ReactNode;
/**
* Unique identifier used for the set of toggle inputs
*/
id: string;
/**
* The set of options described as an array of objects
*/
items: ToggleInputProperties[];
/**
* A label to help users understand what they're picking an option for
*/
listLabel: React.ReactNode | string;
/**
* Callback for when a user makes a selection
*/
onChange?: (selectedItems: string[], affectedItem?: string) => void;
/**
* Defaults to `true`, but can be set to `false` to visibly hide the content passed to `listLabel`. The `listLabel` should still be set even when hidden for accessibility support.
*/
showListLabel?: boolean;
/**
* The subset of selected options
*/
selectedItems?: string[];
/**
* How the text content of each option vertically aligns with it's related input
*/
vertAlign?: "center" | "top";
/**
* If this entire input list is a required field
*/
required?: boolean;
/**
* Sets the current appearance of the label component. This defaults to InputAppearance.Standard, but supports `InputAppearance.Error` & `InputAppearance.Success` appearances as well.
*/
labelAppearance?: InputAppearance;
/**
* Whether the inputs are radio buttons
*/
isRadioGroup?: boolean;
/**
* Human-readable selector used for writing tests
*/
"data-cy"?: string;
}
const ToggleInputList = ({
id,
className,
showListLabel = true,
vertAlign = "center",
selectedItems = [],
labelAppearance = InputAppearance.Standard,
errors,
hintContent,
required,
isRadioGroup,
items,
onChange,
listLabel,
"data-cy": dataCy
}: ToggleInputListProps) => {
const listLegendContent = () => {
const requiredContent = required ? (
*
) : null;
const hasError = labelAppearance === InputAppearance.Error;
const legendClassName = showListLabel
? getLabelStyle(hasError)
: cx(visuallyHidden);
return (
);
};
const inputListItems = () => {
return items.map(item => {
const {
id: itemId,
value,
inputLabel,
appearance,
disabled,
errors,
hintContent
} = item;
const handleChange = (e: React.ChangeEvent) => {
if (onChange) {
onChange(getSelectedItems(value, e.target.checked), value);
}
};
const InputComponent = isRadioGroup ? RadioInput : CheckboxInput;
const inputProps = {
appearance,
checked: selectedItems.includes(value),
disabled,
errors,
hintContent,
id: itemId,
inputLabel,
name: id,
onChange: handleChange,
value,
vertAlign
};
return (