UNPKG

@base-ui/react

Version:

Base UI is a library of headless ('unstyled') React components and low-level hooks. You gain complete control over your app's CSS and accessibility features.

70 lines (68 loc) 3.04 kB
'use client'; import * as React from 'react'; import { error } from '@base-ui/utils/error'; import { SafeReact } from '@base-ui/utils/safeReact'; import { useFieldRootContext } from "../../internals/field-root-context/FieldRootContext.mjs"; import { fieldValidityMapping } from "../../internals/field-constants/constants.mjs"; import { useRenderElement } from "../../internals/useRenderElement.mjs"; import { useLabelableContext } from "../../internals/labelable-provider/LabelableContext.mjs"; import { useLabel } from "../../internals/labelable-provider/useLabel.mjs"; import { useFieldItemContext } from "../item/FieldItemContext.mjs"; /** * An accessible label that is automatically associated with the field control. * Renders a `<label>` element. * * Documentation: [Base UI Field](https://base-ui.com/react/components/field) */ export const FieldLabel = /*#__PURE__*/React.forwardRef(function FieldLabel(componentProps, forwardedRef) { const { render, className, style, id: idProp, nativeLabel = true, ...elementProps } = componentProps; const fieldRootContext = useFieldRootContext(false); const fieldItemContext = useFieldItemContext(); const { labelId } = useLabelableContext(); const state = { ...fieldRootContext.state, disabled: fieldRootContext.disabled || fieldItemContext.disabled }; const labelRef = React.useRef(null); const labelProps = useLabel({ id: labelId ?? idProp, native: nativeLabel }); if (process.env.NODE_ENV !== 'production') { // eslint-disable-next-line react-hooks/rules-of-hooks React.useEffect(() => { if (!labelRef.current) { return; } const isLabelTag = labelRef.current.tagName === 'LABEL'; if (nativeLabel) { if (!isLabelTag) { const ownerStackMessage = SafeReact.captureOwnerStack?.() || ''; const message = '<Field.Label> expected a <label> element because the `nativeLabel` prop is true. ' + 'Rendering a non-<label> disables native label association, so `htmlFor` will not ' + 'work. Use a real <label> in the `render` prop, or set `nativeLabel` to `false`.'; error(`${message}${ownerStackMessage}`); } } else if (isLabelTag) { const ownerStackMessage = SafeReact.captureOwnerStack?.() || ''; const message = '<Field.Label> expected a non-<label> element because the `nativeLabel` prop is false. ' + 'Rendering a <label> assumes native label behavior while Base UI treats it as ' + 'non-native, which can cause unexpected pointer behavior. Use a non-<label> in the ' + '`render` prop, or set `nativeLabel` to `true`.'; error(`${message}${ownerStackMessage}`); } }, [nativeLabel]); } const element = useRenderElement('label', componentProps, { ref: [forwardedRef, labelRef], state, props: [labelProps, elementProps], stateAttributesMapping: fieldValidityMapping }); return element; }); if (process.env.NODE_ENV !== "production") FieldLabel.displayName = "FieldLabel";