@primer/react
Version:
An implementation of GitHub's Primer Design System using React
216 lines (213 loc) • 9.38 kB
JavaScript
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(27);
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));
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 t3 = /*#__PURE__*/React.isValidElement(InputComponent) ? /*#__PURE__*/React.cloneElement(InputComponent, {
id,
disabled,
required: required && !isRadioInput,
"aria-describedby": captionId
}) : null;
let t4;
if ($[1] !== childrenWithoutSlots) {
t4 = childrenWithoutSlots.filter(_temp2);
$[1] = childrenWithoutSlots;
$[2] = t4;
} else {
t4 = $[2];
}
let t5;
if ($[3] !== t3 || $[4] !== t4) {
t5 = /*#__PURE__*/jsxs("div", {
className: classes.ControlChoiceInputs,
children: [t3, t4]
});
$[3] = t3;
$[4] = t4;
$[5] = t5;
} else {
t5 = $[5];
}
let t6;
if ($[6] !== disabled || $[7] !== slots.caption || $[8] !== slots.leadingVisual) {
t6 = slots.leadingVisual ? /*#__PURE__*/jsx("div", {
className: classes.LeadingVisual,
"data-disabled": disabled ? "" : undefined,
"data-has-caption": slots.caption ? "" : undefined,
children: slots.leadingVisual
}) : null;
$[6] = disabled;
$[7] = slots.caption;
$[8] = slots.leadingVisual;
$[9] = t6;
} else {
t6 = $[9];
}
let t7;
if ($[10] !== slots.caption || $[11] !== slots.label) {
t7 = /*#__PURE__*/jsxs("div", {
className: classes.LabelContainer,
children: [slots.label, slots.caption]
});
$[10] = slots.caption;
$[11] = slots.label;
$[12] = t7;
} else {
t7 = $[12];
}
let t8;
if ($[13] !== t5 || $[14] !== t6 || $[15] !== t7) {
t8 = /*#__PURE__*/jsxs(Fragment, {
children: [t5, t6, t7]
});
$[13] = t5;
$[14] = t6;
$[15] = t7;
$[16] = t8;
} else {
t8 = $[16];
}
const InputChildren = t8;
const T0 = FormControlContextProvider;
let t9;
if ($[17] !== captionId || $[18] !== disabled || $[19] !== id || $[20] !== required || $[21] !== validationMessageId) {
t9 = {
captionId,
disabled,
id,
required,
validationMessageId
};
$[17] = captionId;
$[18] = disabled;
$[19] = id;
$[20] = required;
$[21] = validationMessageId;
$[22] = t9;
} else {
t9 = $[22];
}
const t10 = isChoiceInput || layout === "horizontal" ? /*#__PURE__*/jsx("div", {
ref: ref,
"data-has-leading-visual": slots.leadingVisual ? "" : undefined,
className: clsx(className, classes.ControlHorizontalLayout),
style: style,
children: InputChildren
}) : /*#__PURE__*/jsxs("div", {
ref: ref,
"data-has-label": !isLabelHidden ? "" : undefined,
className: clsx(className, classes.ControlVerticalLayout),
style: style,
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 t11;
if ($[23] !== T0 || $[24] !== t10 || $[25] !== t9) {
t11 = /*#__PURE__*/jsx(T0, {
value: t9,
children: t10
});
$[23] = T0;
$[24] = t10;
$[25] = t9;
$[26] = t11;
} else {
t11 = $[26];
}
return t11;
});
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 };