UNPKG

@yamada-ui/form-control

Version:

Yamada UI form control component

365 lines (363 loc) • 10.6 kB
"use client" // src/form-control.tsx import { forwardRef, omitThemeProps, ui, useComponentMultiStyle } from "@yamada-ui/core"; import { ariaAttr, createContext, cx, dataAttr, findChild, getValidChildren, handlerAll } from "@yamada-ui/utils"; import { isValidElement, useId, useState } from "react"; import { Fragment, jsx, jsxs } from "react/jsx-runtime"; var [FormControlContextProvider, useFormControlContext] = createContext({ name: "FormControlContext", strict: false }); var [FormControlStylesProvider, useFormControlStyles] = createContext({ name: "FormControlStyleContext", strict: false }); var FormControl = forwardRef( ({ id, ...props }, ref) => { const [styles, mergedProps] = useComponentMultiStyle("FormControl", props); const uuid = useId(); const labelId = useId(); const { className, children, isDisabled = false, disabled = isDisabled, errorMessage, helperMessage, isInvalid = false, invalid = isInvalid, isReadOnly = false, isReplace = true, isRequired = false, label, optionalIndicator, readOnly = isReadOnly, replace = isReplace, required = isRequired, requiredIndicator, errorMessageProps, helperMessageProps, labelProps, ...rest } = omitThemeProps(mergedProps); const [focused, setFocused] = useState(false); const validChildren = getValidChildren(children); const customLabel = findChild(validChildren, Label); const customHelperMessage = findChild(validChildren, HelperMessage); const customErrorMessage = findChild(validChildren, ErrorMessage); const isCustomLabel = !!customLabel; const isCustomHelperMessage = !!customHelperMessage; const isCustomErrorMessage = !!customErrorMessage; const css = { ...styles.container }; id != null ? id : id = uuid; return /* @__PURE__ */ jsx( FormControlContextProvider, { value: { id, disabled, focused, invalid, labelId, readOnly, replace, required, onBlur: () => setFocused(false), onFocus: () => setFocused(true) }, children: /* @__PURE__ */ jsx(FormControlStylesProvider, { value: styles, children: /* @__PURE__ */ jsxs( ui.div, { ref, className: cx("ui-form__control", className), "data-disabled": dataAttr(disabled), "data-focus": dataAttr(focused), "data-invalid": dataAttr(invalid), "data-readonly": dataAttr(readOnly), __css: css, ...rest, children: [ !isCustomLabel && label ? /* @__PURE__ */ jsx( Label, { optionalIndicator, requiredIndicator, ...labelProps, children: label } ) : null, children, !isCustomHelperMessage && helperMessage ? /* @__PURE__ */ jsx(HelperMessage, { ...helperMessageProps, children: helperMessage }) : null, !isCustomErrorMessage && errorMessage ? /* @__PURE__ */ jsx(ErrorMessage, { ...errorMessageProps, children: errorMessage }) : null ] } ) }) } ); } ); FormControl.displayName = "FormControl"; FormControl.__ui__ = "FormControl"; var useFormControl = ({ id: idProp, disabled: disabledProp, invalid: invalidProp, isDisabled: isDisabledProp, isInvalid: isInvalidProp, isReadOnly: isReadOnlyProp, isRequired: isRequiredProp, readOnly: readOnlyProp, required: requiredProp, ...rest }) => { var _a, _b, _c, _d; const control = useFormControlContext(); const id = idProp != null ? idProp : control == null ? void 0 : control.id; const labelId = control == null ? void 0 : control.labelId; const disabled = (_a = disabledProp != null ? disabledProp : isDisabledProp) != null ? _a : control == null ? void 0 : control.disabled; const readOnly = (_b = readOnlyProp != null ? readOnlyProp : isReadOnlyProp) != null ? _b : control == null ? void 0 : control.readOnly; const required = (_c = requiredProp != null ? requiredProp : isRequiredProp) != null ? _c : control == null ? void 0 : control.required; const invalid = (_d = invalidProp != null ? invalidProp : isInvalidProp) != null ? _d : control == null ? void 0 : control.invalid; return { id, disabled, invalid, /** * @deprecated Use `disabled` instead. */ isDisabled: disabled, /** * @deprecated Use `invalid` instead. */ isInvalid: invalid, /** * @deprecated Use `readOnly` instead. */ isReadOnly: readOnly, /** * @deprecated Use `required` instead. */ isRequired: required, labelId, readOnly, required, ...rest }; }; var useFormControlProps = ({ id, disabled, invalid, isDisabled, isInvalid, isReadOnly, isRequired, readOnly, required, onBlur, onFocus, ...rest }) => { const control = useFormControlContext(); disabled != null ? disabled : disabled = isDisabled != null ? isDisabled : control == null ? void 0 : control.disabled; required != null ? required : required = isRequired != null ? isRequired : control == null ? void 0 : control.required; readOnly != null ? readOnly : readOnly = isReadOnly != null ? isReadOnly : control == null ? void 0 : control.readOnly; invalid != null ? invalid : invalid = isInvalid != null ? isInvalid : control == null ? void 0 : control.invalid; return { id: id != null ? id : control == null ? void 0 : control.id, "aria-disabled": ariaAttr(disabled), "aria-invalid": ariaAttr(invalid), "aria-readonly": ariaAttr(readOnly), "aria-required": ariaAttr(required), "data-readonly": dataAttr(readOnly), disabled, readOnly, required, onBlur: handlerAll(control == null ? void 0 : control.onBlur, onBlur), onFocus: handlerAll(control == null ? void 0 : control.onFocus, onFocus), ...disabled || readOnly ? { _active: {}, _focus: {}, _focusVisible: {}, _hover: {}, _invalid: {} } : {}, ...rest }; }; var formControlProperties = [ "disabled", "required", "readOnly", "aria-disabled", "aria-readonly", "aria-required", "aria-invalid", "data-readonly", "onFocus", "onBlur", "_hover", "_active", "_focus", "_invalid", "_focusVisible" ]; var getFormControlProperties = ({ omit = [], pick = [] } = {}) => { let result = [...formControlProperties]; if (pick.length) { result = result.filter((property) => pick.includes(property)); } if (omit.length) { result = result.filter((property) => !omit.includes(property)); } return result; }; var Label = forwardRef( ({ id, htmlFor, className, children, isRequired, optionalIndicator = null, required: requiredProp = isRequired, requiredIndicator = null, ...rest }, ref) => { var _a, _b; const { id: formControlId, disabled, focused, invalid, labelId, readOnly, required } = (_a = useFormControlContext()) != null ? _a : {}; const styles = (_b = useFormControlStyles()) != null ? _b : {}; const css = { display: "block", pointerEvents: readOnly ? "none" : void 0, ...styles.label }; id != null ? id : id = labelId; requiredProp != null ? requiredProp : requiredProp = required; return /* @__PURE__ */ jsxs( ui.label, { id, ref, htmlFor: htmlFor != null ? htmlFor : formControlId, className: cx("ui-form__label", className), style: { cursor: disabled ? "not-allowed" : void 0 }, "data-disabled": dataAttr(disabled), "data-focus": dataAttr(focused), "data-invalid": dataAttr(invalid), "data-readonly": dataAttr(readOnly), __css: css, ...rest, children: [ children, requiredProp ? requiredIndicator ? /* @__PURE__ */ jsx(RequiredIndicator, { children: requiredIndicator }) : /* @__PURE__ */ jsx(RequiredIndicator, {}) : optionalIndicator ] } ); } ); Label.displayName = "Label"; Label.__ui__ = "Label"; var RequiredIndicator = forwardRef( ({ className, children, ...rest }, ref) => { var _a; const styles = (_a = useFormControlStyles()) != null ? _a : {}; const css = { ...styles.requiredIndicator }; return !isValidElement(children) ? /* @__PURE__ */ jsx( ui.span, { ref, className: cx("ui-form__required-indicator", className), "aria-hidden": true, role: "presentation", __css: css, ...rest, children: children != null ? children : /* @__PURE__ */ jsx(Fragment, { children: "*" }) } ) : children; } ); RequiredIndicator.displayName = "RequiredIndicator"; RequiredIndicator.__ui__ = "RequiredIndicator"; var HelperMessage = forwardRef( ({ className, ...rest }, ref) => { var _a, _b; const { id, invalid, replace } = (_a = useFormControlContext()) != null ? _a : {}; const styles = (_b = useFormControlStyles()) != null ? _b : {}; const css = { ...styles.helperMessage }; if (replace && invalid) return null; return /* @__PURE__ */ jsx( ui.span, { ref, className: cx("ui-form__helper-message", className), "aria-describedby": id, __css: css, ...rest } ); } ); HelperMessage.displayName = "HelperMessage"; HelperMessage.__ui__ = "HelperMessage"; var ErrorMessage = forwardRef( ({ className, ...rest }, ref) => { var _a, _b; const { invalid } = (_a = useFormControlContext()) != null ? _a : {}; const styles = (_b = useFormControlStyles()) != null ? _b : {}; const css = { ...styles.errorMessage }; if (!invalid) return null; return /* @__PURE__ */ jsx( ui.span, { ref, className: cx("ui-form__error-message", className), "aria-live": "polite", __css: css, ...rest } ); } ); ErrorMessage.displayName = "ErrorMessage"; ErrorMessage.__ui__ = "ErrorMessage"; export { FormControlContextProvider, useFormControlContext, FormControlStylesProvider, useFormControlStyles, FormControl, useFormControl, useFormControlProps, formControlProperties, getFormControlProperties, Label, RequiredIndicator, HelperMessage, ErrorMessage }; //# sourceMappingURL=chunk-6MABFBBX.mjs.map