@paradise-ui/text-field
Version:
An enhanced version of common <input> component
197 lines (193 loc) • 9.83 kB
JavaScript
'use client'
// src/TextField.tsx
import { forwardRef, useContext, useEffect, useId, useState } from "react";
import { ParadiseUIContext } from "@paradise-ui/common";
// src/elementClass.ts
import clsx from "clsx";
var defaultTextFieldElementClass = (props) => {
return {
root: clsx([
"pui-text-field",
`pui-text-field--${props.variant}`,
`pui-text-field--${props.size}`,
!!props.errorMessage || props.invalid ? `pui-text-field--error` : "",
props.focus ? "pui-text-field--focus" : "",
props.disabled ? `pui-text-field--disabled` : "",
props.className
]),
labelBlock: "pui-text-field__label-block",
label: "pui-text-field__label",
secondaryLabel: "pui-text-field__label-secondary",
inputBlock: "pui-text-field__input-block",
inputPrefix: "pui-text-field__input-prefix",
input: "",
inputSuffix: "pui-text-field__input-suffix",
messageBlock: "pui-text-field__message-block",
helperText: "pui-text-field__helper-text",
errorMessage: "pui-text-field__error-message"
};
};
var tailwindTextFieldElementClass = (props) => {
return {
root: clsx([
"w-full text-[var(--pui-text,#31333e)] dark:text-[var(--pui-text-in-dark,#e7e7e9)] border-box text-[1rem]",
props.className
]),
labelBlock: clsx(["flex justify-between mb-[0.25rem]", props.size === "sm" ? "text-[0.75rem]" : "text-[0.875rem]"]),
label: "",
secondaryLabel: "text-[var(--pui-text-secondary,#63636e)] dark:text-[var(--pui-text-secondary-in-dark,#a4a4ad)]",
inputBlock: clsx([
"flex overflow-hidden antialiased",
props.size === "sm" && "text-[0.875rem]",
props.size === "sm" && (props.variant === "line" ? "h-[1.625rem]" : "h-[2rem]"),
props.size === "md" && (props.variant === "line" ? "h-[1.875rem]" : "h-[2.5rem]"),
props.size === "lg" && "text-[1.125rem]",
props.size === "lg" && (props.variant === "line" ? "h-[2rem]" : "h-[3rem]"),
props.variant === "outlined" && [
"rounded-[5px]",
"border border-solid",
!props.focus && !props.errorMessage && !props.invalid && "border-[var(--pui-soft-border,#dadce3)] dark:border-[var(--pui-soft-border-in-dark,#373a3a)]"
],
props.variant === "line" && [
"bg-transparent mb-[0.3rem]",
"border-0 border-b border-solid",
!props.focus && !props.errorMessage && !props.invalid && "border-[var(--pui-soft-border,#dadce3)] dark:border-[var(--pui-soft-border-in-dark,#373a3a)]"
],
props.variant === "filled" && [
"rounded-[5px]",
!props.errorMessage && !props.invalid && "bg-[var(--pui-input-filler,#f0f0f2)] dark:bg-[var(--pui-input-filler-dark,#313437)]",
"border border-solid",
!props.focus && !props.errorMessage && !props.invalid && !props.disabled && "border-[var(--pui-input-filler,#f0f0f2)] dark:border-[var(--pui-input-filler-dark,#313437)]"
],
!props.focus && !props.errorMessage && !props.disabled && "hover:border-[var(--pui-border,#c3c7d0)] dark:hover:var(--pui-border-in-dark,#43474a)",
props.disabled && "opacity-50 cursor-not-allowed",
props.focus && !props.errorMessage && "border-[var(--pui-info,#008DDA)]",
props.focus && !props.errorMessage && (props.variant === "line" ? "border-b-[1.5px]" : "shadow-[0_0_0_0.5px_var(--pui-info,#008DDA)]"),
(!!props.errorMessage || props.invalid) && "border-[var(--pui-error,#e74747)]",
(!!props.errorMessage || props.invalid) && (props.variant === "line" ? "border-b-[1.5px]" : "shadow-[0_0_0_0.5px_var(--pui-error,#e74747)]"),
(!!props.errorMessage || props.invalid) && props.variant === "filled" && "bg-[var(--pui-error-lighten,#fbe3e3)] dark:bg-[var(--pui-error-darken,#230b0b)]"
]),
inputPrefix: clsx([
"h-full flex items-center",
props.variant !== "line" && props.size === "sm" && "pl-[0.5rem]",
props.variant !== "line" && props.size === "md" && "pl-[0.75rem]",
props.variant !== "line" && props.size === "lg" && "pl-[1rem]",
props.variant === "line" && props.size === "sm" && "pr-[0.5rem]",
props.variant === "line" && props.size === "md" && "pr-[0.75rem]",
props.variant === "line" && props.size === "lg" && "pr-[1rem]"
]),
input: clsx([
"w-full h-full font-inherit text-inherit border-0 outline-0 shadow-none bg-inherit disabled:cursor-not-allowed disabled:bg-inherit",
"placeholder:text-[var(--pui-input-placeholder,#adb5bd)] dark:placeholder:text-[var(--pui-input-placeholder-dark,#696969)]",
props.variant === "filled" && "bg-inherit",
props.variant === "line" ? "p-0" : "py-0",
props.variant !== "line" && props.size === "sm" && "px-[0.5rem]",
props.variant !== "line" && props.size === "md" && "px-[0.75rem]",
props.variant !== "line" && props.size === "lg" && "px-[1rem]"
]),
inputSuffix: clsx([
"h-full flex items-center",
props.variant === "line" && props.size === "sm" && "pl-[0.5rem]",
props.variant === "line" && props.size === "md" && "pl-[0.75rem]",
props.variant === "line" && props.size === "lg" && "pl-[1rem]",
props.variant !== "line" && props.size === "sm" && "pr-[0.5rem]",
props.variant !== "line" && props.size === "md" && "pr-[0.75rem]",
props.variant !== "line" && props.size === "lg" && "pr-[1rem]"
]),
messageBlock: clsx([
"mt-[0.25em] text-[var(--pui-text-secondary,#63636e)] dark:text-[var(--pui-text-secondary-in-dark,#a4a4ad)]",
props.size === "sm" ? "text-[0.65rem]" : "text-[0.75rem]"
]),
helperText: "",
errorMessage: "text-[var(--pui-error,#e74747)]"
};
};
// src/TextField.tsx
import clsx2 from "clsx";
import { jsx, jsxs } from "react/jsx-runtime";
var TextField = forwardRef((props, ref) => {
const {
label = "",
secondaryLabel = "",
variant = "outlined",
size = "md",
name = "",
type = "text",
className = "",
placeholder = "",
value,
invalid = false,
disabled = false,
prefix = "",
suffix = "",
errorMessage = "",
helperText = "",
onChange,
elementClass,
extraElementClass,
...rest
} = props;
const puiContext = useContext(ParadiseUIContext);
const [focus, setFocus] = useState(false);
const elementClassProps = { variant, size, type, invalid, disabled, ...props, focus };
const [textFieldElementClass, setTextFieldElementClass] = useState(
defaultTextFieldElementClass(elementClassProps)
);
useEffect(() => {
var _a, _b;
let newElementClass = defaultTextFieldElementClass(elementClassProps);
if (puiContext) {
if (puiContext.elementClassLibrary === "tailwind") {
newElementClass = tailwindTextFieldElementClass(elementClassProps);
}
newElementClass = {
...newElementClass,
...((_a = puiContext.componentElementClasses) == null ? void 0 : _a.textField) && ((_b = puiContext.componentElementClasses) == null ? void 0 : _b.textField(elementClassProps)) || {}
};
}
if (elementClass) {
newElementClass = { ...newElementClass, ...elementClass(elementClassProps) };
}
setTextFieldElementClass(newElementClass);
}, [props, focus]);
const id = useId();
const inputId = `${id}-${name}`;
const descriptionId = `${id}-description`;
return /* @__PURE__ */ jsxs("div", { className: clsx2(textFieldElementClass.root, extraElementClass == null ? void 0 : extraElementClass.root), "aria-disabled": disabled, children: [
/* @__PURE__ */ jsxs("div", { className: clsx2(textFieldElementClass.labelBlock, extraElementClass == null ? void 0 : extraElementClass.labelBlock), children: [
/* @__PURE__ */ jsx("label", { className: clsx2(textFieldElementClass.label, extraElementClass == null ? void 0 : extraElementClass.label), children: label }),
!!secondaryLabel && /* @__PURE__ */ jsx("label", { className: clsx2(textFieldElementClass.secondaryLabel, extraElementClass == null ? void 0 : extraElementClass.secondaryLabel), children: secondaryLabel })
] }),
/* @__PURE__ */ jsxs("div", { className: clsx2(textFieldElementClass.inputBlock, extraElementClass == null ? void 0 : extraElementClass.inputBlock), children: [
prefix && /* @__PURE__ */ jsx("div", { className: clsx2(textFieldElementClass.inputPrefix, extraElementClass == null ? void 0 : extraElementClass.inputPrefix), children: prefix }),
/* @__PURE__ */ jsx(
"input",
{
ref,
name,
className: clsx2(textFieldElementClass.input, extraElementClass == null ? void 0 : extraElementClass.input),
type,
disabled,
"aria-disabled": disabled,
onChange: (e) => {
if (e.target.value !== value) {
!!onChange && onChange(e.target.value);
}
},
onFocus: () => setFocus(true),
onBlur: () => setFocus(false),
placeholder,
value,
id: inputId,
"aria-describedby": descriptionId,
...rest
}
),
suffix && /* @__PURE__ */ jsx("div", { className: clsx2(textFieldElementClass.inputSuffix, extraElementClass == null ? void 0 : extraElementClass.inputSuffix), children: suffix })
] }),
/* @__PURE__ */ jsx("div", { className: clsx2(textFieldElementClass.messageBlock, extraElementClass == null ? void 0 : extraElementClass.messageBlock), children: !errorMessage ? /* @__PURE__ */ jsx("div", { className: clsx2(textFieldElementClass.helperText, extraElementClass == null ? void 0 : extraElementClass.helperText), children: helperText }) : /* @__PURE__ */ jsx("div", { className: clsx2(textFieldElementClass.errorMessage, extraElementClass == null ? void 0 : extraElementClass.errorMessage), children: errorMessage }) })
] });
});
export {
TextField
};