UNPKG

@ariakit/react-core

Version:

Ariakit React core

129 lines (126 loc) 3.65 kB
"use client"; import { useFormContext } from "./GSXI3IAI.js"; import { useCollectionItem } from "./Y62RTBST.js"; import { createElement, createHook, forwardRef, memo } from "./VOQWLFSQ.js"; import { useBooleanEvent, useEvent, useId, useMergeRefs } from "./5GGHRIN3.js"; import { __objRest, __spreadProps, __spreadValues } from "./3YLGPPWQ.js"; // src/form/form-control.tsx import { getDocument } from "@ariakit/core/utils/dom"; import { cx, invariant } from "@ariakit/core/utils/misc"; import { useCallback, useRef } from "react"; var TagName = "input"; function getNamedElement(ref, name) { const element = ref.current; if (!element) return null; if (element.name === name) return element; if (element.form) { return element.form.elements.namedItem(name); } const document = getDocument(element); return document.getElementsByName(name)[0]; } function useItem(store, name, type) { return store.useState( (state) => state.items.find((item) => item.type === type && item.name === name) ); } var useFormControl = createHook( function useFormControl2(_a) { var _b = _a, { store, name: nameProp, getItem: getItemProp, touchOnBlur = true } = _b, props = __objRest(_b, [ "store", "name", "getItem", "touchOnBlur" ]); const context = useFormContext(); store = store || context; invariant( store, process.env.NODE_ENV !== "production" && "FormControl must be wrapped in a Form component." ); const name = `${nameProp}`; const id = useId(props.id); const ref = useRef(null); store.useValidate(async () => { const element = getNamedElement(ref, name); if (!element) return; await Promise.resolve(); if ("validity" in element && !element.validity.valid) { store == null ? void 0 : store.setError(name, element.validationMessage); } }); const getItem = useCallback( (item) => { const nextItem = __spreadProps(__spreadValues({}, item), { id: id || item.id, name, type: "field" }); if (getItemProp) { return getItemProp(nextItem); } return nextItem; }, [id, name, getItemProp] ); const onBlurProp = props.onBlur; const touchOnBlurProp = useBooleanEvent(touchOnBlur); const onBlur = useEvent((event) => { onBlurProp == null ? void 0 : onBlurProp(event); if (event.defaultPrevented) return; if (!touchOnBlurProp(event)) return; store == null ? void 0 : store.setFieldTouched(name, true); }); const label = useItem(store, name, "label"); const error = useItem(store, name, "error"); const description = useItem(store, name, "description"); const describedBy = cx( error == null ? void 0 : error.id, description == null ? void 0 : description.id, props["aria-describedby"] ); const invalid = store.useState( () => !!(store == null ? void 0 : store.getError(name)) && store.getFieldTouched(name) ); props = __spreadProps(__spreadValues({ id, "aria-labelledby": label == null ? void 0 : label.id, "aria-invalid": invalid }, props), { "aria-describedby": describedBy || void 0, ref: useMergeRefs(ref, props.ref), onBlur }); props = useCollectionItem(__spreadProps(__spreadValues({ store }, props), { name, getItem })); return props; } ); var FormControl = memo( forwardRef(function FormControl2(props) { const htmlProps = useFormControl(props); return createElement(TagName, htmlProps); }) ); export { useFormControl, FormControl };