UNPKG

@ark-ui/react

Version:

A collection of unstyled, accessible UI components for React, utilizing state machines for seamless interaction.

83 lines (80 loc) 2.42 kB
'use client'; import { getWindow } from '@zag-js/dom-query'; import { useRef, useId, useMemo } from 'react'; import { useSafeLayoutEffect } from '../../utils/use-safe-layout-effect.js'; import { parts } from './fieldset.anatomy.js'; const useFieldset = (props = {}) => { const { disabled = false, invalid = false } = props; const hasErrorText = useRef(false); const hasHelperText = useRef(false); const id = props.id ?? useId(); const rootRef = useRef(null); const errorTextId = `fieldset::${id}::error-text`; const helperTextId = `fieldset::${id}::helper-text`; useSafeLayoutEffect(() => { const rootNode = rootRef.current; if (!rootNode) return; const win = getWindow(rootNode); const doc = win.document; const checkTextElements = () => { hasErrorText.current = !!doc.getElementById(errorTextId); hasHelperText.current = !!doc.getElementById(helperTextId); }; checkTextElements(); const observer = new win.MutationObserver(checkTextElements); observer.observe(rootNode, { childList: true, subtree: true }); return () => observer.disconnect(); }, [errorTextId, helperTextId]); const labelIds = useMemo(() => { const ids = []; if (hasErrorText.current && invalid) ids.push(errorTextId); if (hasHelperText.current) ids.push(helperTextId); return ids.join(" ") || void 0; }, [invalid, errorTextId, helperTextId]); const getRootProps = useMemo( () => () => ({ ...parts.root.attrs, ref: rootRef, disabled, "data-disabled": disabled ? "true" : void 0, "data-invalid": invalid ? "true" : void 0, "aria-describedby": labelIds }), [disabled, invalid, labelIds] ); const getLegendProps = useMemo( () => () => ({ ...parts.legend.attrs, "data-disabled": disabled ? "true" : void 0, "data-invalid": invalid ? "true" : void 0 }), [disabled, invalid] ); const getHelperTextProps = useMemo( () => () => ({ id: helperTextId, ...parts.helperText.attrs }), [helperTextId] ); const getErrorTextProps = useMemo( () => () => ({ id: errorTextId, ...parts.errorText.attrs, "aria-live": "polite" }), [errorTextId] ); return { refs: { rootRef }, disabled, invalid, getRootProps, getLegendProps, getHelperTextProps, getErrorTextProps }; }; export { useFieldset };