UNPKG

@primer/react

Version:

An implementation of GitHub's Primer Design System using React

235 lines (232 loc) • 10.1 kB
import { c } from 'react-compiler-runtime'; import { clsx } from 'clsx'; import React, { useContext } from 'react'; import Select from '../Select/Select.js'; import ValidationAnimationContainer from '../internal/components/ValidationAnimationContainer.js'; import { useSlots } from '../hooks/useSlots.js'; import { useId } from '../hooks/useId.js'; import { FormControlCaption } from './FormControlCaption.js'; import FormControlLabel from './FormControlLabel.js'; import FormControlLeadingVisual from './FormControlLeadingVisual.js'; import FormControlValidation from './_FormControlValidation.js'; import { FormControlContextProvider } from './_FormControlContext.js'; import { warning } from '../utils/warning.js'; import classes from './FormControl.module.css.js'; import { isSlot } from '../utils/is-slot.js'; import { jsx, jsxs, Fragment } from 'react/jsx-runtime'; import CheckboxOrRadioGroupContext from '../internal/components/CheckboxOrRadioGroup/CheckboxOrRadioGroupContext.js'; import Autocomplete from '../Autocomplete/Autocomplete.js'; import Checkbox from '../Checkbox/Checkbox.js'; import Radio from '../Radio/Radio.js'; import TextInput from '../TextInput/TextInput.js'; import TextInputWithTokens from '../TextInputWithTokens/TextInputWithTokens.js'; import Textarea from '../Textarea/Textarea.js'; import { SelectPanel } from '../SelectPanel/SelectPanel.js'; const FormControl = /*#__PURE__*/React.forwardRef((t0, ref) => { var _slots$validation, _slots$label; const $ = c(32); const { children, disabled: disabledProp, layout: t1, id: idProp, required, className, style } = t0; const layout = t1 === undefined ? "vertical" : t1; let t2; if ($[0] === Symbol.for("react.memo_cache_sentinel")) { t2 = { caption: FormControlCaption, label: FormControlLabel, leadingVisual: FormControlLeadingVisual, validation: FormControlValidation }; $[0] = t2; } else { t2 = $[0]; } const [slots, childrenWithoutSlots] = useSlots(children, t2); const expectedInputComponents = [Autocomplete, Checkbox, Radio, Select, TextInput, TextInputWithTokens, Textarea, SelectPanel]; const choiceGroupContext = useContext(CheckboxOrRadioGroupContext); const disabled = choiceGroupContext.disabled || disabledProp; const id = useId(idProp); const validationMessageId = slots.validation ? `${id}-validationMessage` : undefined; const captionId = slots.caption ? `${id}-caption` : undefined; const validationStatus = (_slots$validation = slots.validation) === null || _slots$validation === void 0 ? void 0 : _slots$validation.props.variant; const InputComponent = childrenWithoutSlots.find(child => expectedInputComponents.some(inputComponent => /*#__PURE__*/React.isValidElement(child) && (child.type === inputComponent || isSlot(child, inputComponent)))); const inputProps = /*#__PURE__*/React.isValidElement(InputComponent) && InputComponent.props; const isChoiceInput = /*#__PURE__*/React.isValidElement(InputComponent) && (InputComponent.type === Checkbox || InputComponent.type === Radio || isSlot(InputComponent, Checkbox) || isSlot(InputComponent, Radio)); const isRadioInput = /*#__PURE__*/React.isValidElement(InputComponent) && (InputComponent.type === Radio || isSlot(InputComponent, Radio)); const isSelectPanelInput = /*#__PURE__*/React.isValidElement(InputComponent) && (InputComponent.type === SelectPanel || isSlot(InputComponent, SelectPanel)); let t3; if ($[1] !== id || $[2] !== slots.label) { var _ref; t3 = slots.label ? (_ref = /*#__PURE__*/React.isValidElement(slots.label) ? slots.label.props.id : undefined) !== null && _ref !== void 0 ? _ref : `${id}-label` : undefined; $[1] = id; $[2] = slots.label; $[3] = t3; } else { t3 = $[3]; } const labelId = t3; if (InputComponent) { process.env.NODE_ENV !== "production" ? warning(inputProps === null || inputProps === void 0 ? void 0 : inputProps.id, "instead of passing the 'id' prop directly to the input component, it should be passed to the parent component, <FormControl>") : void 0; process.env.NODE_ENV !== "production" ? warning(inputProps === null || inputProps === void 0 ? void 0 : inputProps.disabled, "instead of passing the 'disabled' prop directly to the input component, it should be passed to the parent component, <FormControl>") : void 0; process.env.NODE_ENV !== "production" ? warning(inputProps === null || inputProps === void 0 ? void 0 : inputProps.required, "instead of passing the 'required' prop directly to the input component, it should be passed to the parent component, <FormControl>") : void 0; } if (!slots.label) { console.error(`The input field with the id ${id} MUST have a FormControl.Label child.\n\nIf you want to hide the label, pass the 'visuallyHidden' prop to the FormControl.Label component.`); } if (isChoiceInput) { process.env.NODE_ENV !== "production" ? warning(!!slots.validation, "Validation messages are not rendered for an individual checkbox or radio. The validation message should be shown for all options.") : void 0; process.env.NODE_ENV !== "production" ? warning(isRadioInput && childrenWithoutSlots.find(_temp), "An individual radio cannot be a required field.") : void 0; } else { process.env.NODE_ENV !== "production" ? warning(!!slots.leadingVisual, "A leading visual is only rendered for a checkbox or radio form control. If you want to render a leading visual inside of your input, check if your input supports a leading visual.") : void 0; } const isLabelHidden = (_slots$label = slots.label) === null || _slots$label === void 0 ? void 0 : _slots$label.props.visuallyHidden; const t4 = /*#__PURE__*/React.isValidElement(InputComponent) ? /*#__PURE__*/React.cloneElement(InputComponent, { id, disabled, required: required && !isRadioInput, "aria-describedby": captionId }) : null; let t5; if ($[4] !== childrenWithoutSlots) { t5 = childrenWithoutSlots.filter(_temp2); $[4] = childrenWithoutSlots; $[5] = t5; } else { t5 = $[5]; } let t6; if ($[6] !== t4 || $[7] !== t5) { t6 = /*#__PURE__*/jsxs("div", { className: classes.ControlChoiceInputs, children: [t4, t5] }); $[6] = t4; $[7] = t5; $[8] = t6; } else { t6 = $[8]; } let t7; if ($[9] !== disabled || $[10] !== slots.caption || $[11] !== slots.leadingVisual) { t7 = slots.leadingVisual ? /*#__PURE__*/jsx("div", { className: classes.LeadingVisual, "data-disabled": disabled ? "" : undefined, "data-has-caption": slots.caption ? "" : undefined, children: slots.leadingVisual }) : null; $[9] = disabled; $[10] = slots.caption; $[11] = slots.leadingVisual; $[12] = t7; } else { t7 = $[12]; } let t8; if ($[13] !== slots.caption || $[14] !== slots.label) { t8 = /*#__PURE__*/jsxs("div", { className: classes.LabelContainer, children: [slots.label, slots.caption] }); $[13] = slots.caption; $[14] = slots.label; $[15] = t8; } else { t8 = $[15]; } let t9; if ($[16] !== t6 || $[17] !== t7 || $[18] !== t8) { t9 = /*#__PURE__*/jsxs(Fragment, { children: [t6, t7, t8] }); $[16] = t6; $[17] = t7; $[18] = t8; $[19] = t9; } else { t9 = $[19]; } const InputChildren = t9; const T0 = FormControlContextProvider; const t10 = !isSelectPanelInput; let t11; if ($[20] !== captionId || $[21] !== disabled || $[22] !== id || $[23] !== labelId || $[24] !== required || $[25] !== t10 || $[26] !== validationMessageId) { t11 = { captionId, disabled, id, required, validationMessageId, isReferenced: t10, labelId }; $[20] = captionId; $[21] = disabled; $[22] = id; $[23] = labelId; $[24] = required; $[25] = t10; $[26] = validationMessageId; $[27] = t11; } else { t11 = $[27]; } const t12 = isChoiceInput || layout === "horizontal" ? /*#__PURE__*/jsx("div", { ref: ref, "data-has-leading-visual": slots.leadingVisual ? "" : undefined, className: clsx(className, classes.ControlHorizontalLayout), style: style, "data-component": "FormControl", children: InputChildren }) : /*#__PURE__*/jsxs("div", { ref: ref, "data-has-label": !isLabelHidden ? "" : undefined, className: clsx(className, classes.ControlVerticalLayout), style: style, "data-component": "FormControl", children: [slots.label, /*#__PURE__*/React.isValidElement(InputComponent) && /*#__PURE__*/React.cloneElement(InputComponent, Object.assign({ id, required, disabled, validationStatus, "aria-describedby": [validationMessageId, captionId].filter(Boolean).join(" ") }, InputComponent.props)), childrenWithoutSlots.filter(child_2 => /*#__PURE__*/React.isValidElement(child_2) && !expectedInputComponents.some(inputComponent_1 => child_2.type === inputComponent_1 || isSlot(child_2, inputComponent_1))), slots.validation ? /*#__PURE__*/jsx(ValidationAnimationContainer, { show: true, children: slots.validation }) : null, slots.caption] }); let t13; if ($[28] !== T0 || $[29] !== t11 || $[30] !== t12) { t13 = /*#__PURE__*/jsx(T0, { value: t11, children: t12 }); $[28] = T0; $[29] = t11; $[30] = t12; $[31] = t13; } else { t13 = $[31]; } return t13; }); var FormControl$1 = Object.assign(FormControl, { __SLOT__: Symbol('FormControl'), Caption: FormControlCaption, Label: FormControlLabel, LeadingVisual: FormControlLeadingVisual, Validation: FormControlValidation }); function _temp(child_0) { var _child_0$props; return /*#__PURE__*/React.isValidElement(child_0) && ((_child_0$props = child_0.props) === null || _child_0$props === void 0 ? void 0 : _child_0$props.required); } function _temp2(child_1) { return /*#__PURE__*/React.isValidElement(child_1) && ![Checkbox, Radio].some(inputComponent_0 => child_1.type === inputComponent_0 || isSlot(child_1, inputComponent_0)); } export { FormControl$1 as default };