@ark-ui/react
Version:
A collection of unstyled, accessible UI components for React, utilizing state machines for seamless interaction.
152 lines (147 loc) • 4.63 kB
JavaScript
'use client';
;
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const domQuery = require('@zag-js/dom-query');
const react = require('react');
const useSafeLayoutEffect = require('../../utils/use-safe-layout-effect.cjs');
const useFieldsetContext = require('../fieldset/use-fieldset-context.cjs');
const field_anatomy = require('./field.anatomy.cjs');
const useField = (props = {}) => {
const fieldset = useFieldsetContext.useFieldsetContext();
const { ids, disabled = Boolean(fieldset?.disabled), invalid = false, readOnly = false, required = false } = props;
const [hasErrorText, setHasErrorText] = react.useState(false);
const [hasHelperText, setHasHelperText] = react.useState(false);
const id = props.id ?? react.useId();
const rootRef = react.useRef(null);
const rootId = ids?.control ?? `field::${id}`;
const errorTextId = ids?.errorText ?? `field::${id}::error-text`;
const helperTextId = ids?.helperText ?? `field::${id}::helper-text`;
const labelId = ids?.label ?? `field::${id}::label`;
useSafeLayoutEffect.useSafeLayoutEffect(() => {
const rootNode = rootRef.current;
if (!rootNode) return;
const win = domQuery.getWindow(rootNode);
const doc = win.document;
const checkTextElements = () => {
setHasErrorText(!!doc.getElementById(errorTextId));
setHasHelperText(!!doc.getElementById(helperTextId));
};
checkTextElements();
const observer = new win.MutationObserver(checkTextElements);
observer.observe(rootNode, { childList: true, subtree: true });
return () => observer.disconnect();
}, [errorTextId, helperTextId]);
const labelIds = react.useMemo(() => {
const ids2 = [];
if (hasErrorText && invalid) ids2.push(errorTextId);
if (hasHelperText) ids2.push(helperTextId);
return ids2.join(" ") || void 0;
}, [invalid, errorTextId, helperTextId, hasErrorText, hasHelperText]);
const getRootProps = react.useMemo(
() => () => ({
...field_anatomy.parts.root.attrs,
id: rootId,
ref: rootRef,
role: "group",
"data-disabled": domQuery.dataAttr(disabled),
"data-invalid": domQuery.dataAttr(invalid),
"data-readonly": domQuery.dataAttr(readOnly)
}),
[disabled, invalid, readOnly, rootId]
);
const getLabelProps = react.useMemo(
() => () => ({
...field_anatomy.parts.label.attrs,
id: labelId,
"data-disabled": domQuery.dataAttr(disabled),
"data-invalid": domQuery.dataAttr(invalid),
"data-readonly": domQuery.dataAttr(readOnly),
htmlFor: id
}),
[disabled, invalid, readOnly, id, labelId]
);
const getControlProps = react.useMemo(
() => () => ({
"aria-describedby": labelIds,
"aria-invalid": domQuery.ariaAttr(invalid),
"data-invalid": domQuery.dataAttr(invalid),
"data-required": domQuery.dataAttr(required),
"data-readonly": domQuery.dataAttr(readOnly),
id,
required,
disabled,
readOnly
}),
[labelIds, invalid, required, readOnly, id, disabled]
);
const getInputProps = react.useMemo(
() => () => ({
...getControlProps(),
...field_anatomy.parts.input.attrs
}),
[getControlProps]
);
const getTextareaProps = react.useMemo(
() => () => ({
...getControlProps(),
...field_anatomy.parts.textarea.attrs
}),
[getControlProps]
);
const getSelectProps = react.useMemo(
() => () => ({
...getControlProps(),
...field_anatomy.parts.select.attrs
}),
[getControlProps]
);
const getHelperTextProps = react.useMemo(
() => () => ({
id: helperTextId,
...field_anatomy.parts.helperText.attrs,
"data-disabled": domQuery.dataAttr(disabled)
}),
[disabled, helperTextId]
);
const getErrorTextProps = react.useMemo(
() => () => ({
id: errorTextId,
...field_anatomy.parts.errorText.attrs,
"aria-live": "polite"
}),
[errorTextId]
);
const getRequiredIndicatorProps = react.useMemo(
() => () => ({
"aria-hidden": true,
...field_anatomy.parts.requiredIndicator.attrs
}),
[]
);
return {
ariaDescribedby: labelIds,
ids: {
root: rootId,
control: id,
label: labelId,
errorText: errorTextId,
helperText: helperTextId
},
refs: {
rootRef
},
disabled,
invalid,
readOnly,
required,
getLabelProps,
getRootProps,
getInputProps,
getTextareaProps,
getSelectProps,
getHelperTextProps,
getErrorTextProps,
getRequiredIndicatorProps
};
};
exports.useField = useField;