@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.
64 lines (62 loc) • 2.8 kB
JavaScript
'use client';
import * as React from 'react';
import { error } from '@base-ui/utils/error';
import { SafeReact } from '@base-ui/utils/safeReact';
import { useStore } from '@base-ui/utils/store';
import { useRenderElement } from "../../internals/useRenderElement.js";
import { useFieldRootContext } from "../../internals/field-root-context/FieldRootContext.js";
import { fieldValidityMapping } from "../../internals/field-constants/constants.js";
import { useLabel } from "../../internals/labelable-provider/useLabel.js";
import { getDefaultLabelId } from "../../utils/resolveAriaLabelledBy.js";
import { useComboboxRootContext } from "../root/ComboboxRootContext.js";
import { selectors } from "../store.js";
/**
* An accessible label that is automatically associated with the combobox trigger.
* Renders a `<div>` element.
*
* Documentation: [Base UI Combobox](https://base-ui.com/react/components/combobox)
*/
export const ComboboxLabel = /*#__PURE__*/React.forwardRef(function ComboboxLabel(componentProps, forwardedRef) {
const {
render,
className,
style,
...elementProps
} = componentProps;
// Keep label id derived from the root and ignore runtime `id` overrides from untyped consumers.
const elementPropsWithoutId = elementProps;
delete elementPropsWithoutId.id;
const fieldRootContext = useFieldRootContext();
const store = useComboboxRootContext();
const inputInsidePopup = useStore(store, selectors.inputInsidePopup);
const triggerElement = useStore(store, selectors.triggerElement);
const inputElement = useStore(store, selectors.inputElement);
const rootId = useStore(store, selectors.id);
const defaultLabelId = getDefaultLabelId(rootId);
const localControlId = triggerElement?.id ?? (inputInsidePopup ? rootId : undefined);
if (process.env.NODE_ENV !== 'production') {
// eslint-disable-next-line react-hooks/rules-of-hooks
React.useEffect(() => {
if (!inputElement || inputInsidePopup) {
return;
}
const ownerStackMessage = SafeReact.captureOwnerStack?.() || '';
const message = '<Combobox.Label> labels <Combobox.Trigger> only. ' + 'When <Combobox.Input> is the form control, use a native <label> or <Field.Label> instead.';
error(`${message}${ownerStackMessage}`);
}, [inputElement, inputInsidePopup]);
}
const labelProps = useLabel({
id: defaultLabelId,
fallbackControlId: localControlId,
setLabelId(nextLabelId) {
store.set('labelId', nextLabelId);
}
});
return useRenderElement('div', componentProps, {
ref: forwardedRef,
state: fieldRootContext.state,
props: [labelProps, elementProps],
stateAttributesMapping: fieldValidityMapping
});
});
if (process.env.NODE_ENV !== "production") ComboboxLabel.displayName = "ComboboxLabel";