@yamada-ui/form-control
Version:
Yamada UI form control component
365 lines (363 loc) • 10.6 kB
JavaScript
"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