diff --git a/src/components/Input/Input.tsx b/src/components/Input/Input.tsx index 32ad620..1ae5978 100644 --- a/src/components/Input/Input.tsx +++ b/src/components/Input/Input.tsx @@ -3,7 +3,8 @@ import { ComponentType, CSSProperties, forwardRef, - KeyboardEvent, + InputHTMLAttributes, + useState, } from "react"; import { attributes } from "../utils/attributes"; import { classnames } from "../utils/classnames"; @@ -20,74 +21,33 @@ export interface InputCustomStyleCSS extends CSSProperties { } type Props = { - label?: string; - id: string; - /** - * OnChange event triggered every time the input value changed. - */ - onChange?: (e: ChangeEvent) => void | Promise; - - onFocus?: () => void | Promise; - - onBlur?: () => unknown | Promise; - - onClick?: (() => void) | undefined; - - onMouseEnter?: () => void; - - onMouseLeave?: () => void; - - onKeyUp?: (e: KeyboardEvent) => void; - - placeholder?: string; - - value?: string; - - /** - * Apply custom css variables. - * --codex-input-background - * --codex-color - * --codex-border-radius - * --codex-input-border - * --codex-color-primary - * --codex-input-background-disabled - */ - style?: InputCustomStyleCSS; + label?: string; /** * Helper text to add indication about your input. */ helper?: string; - disabled?: boolean; - /** * Add an icon on the left. */ Icon?: ComponentType; + /** + * If the mode is "auto", the component will check the invalid state + * on change and add an invalid state if it is invalid. + */ + mode?: "auto"; + + isInvalid?: boolean; + /** * Apply a class to the input element */ inputClassName?: string; - - /** - * Default is text - */ - type?: string; - - step?: string; - - name?: string; - - min?: number | string; - - max?: number | string; - - maxLength?: number; -}; +} & InputHTMLAttributes; export const Input = forwardRef( ( @@ -95,28 +55,29 @@ export const Input = forwardRef( id, label, helper, - disabled, - value, - onBlur, - onFocus, - placeholder, - onChange, - onMouseEnter, - onMouseLeave, - onClick, - onKeyUp, style, Icon, - step, - name, inputClassName, - maxLength, - type = "text", - min, - max, + disabled = false, + onChange, + mode, + isInvalid = false, + ...rest }, ref ) => { + const [invalid, setInvalid] = useState(isInvalid); + + const onInternalChange = (e: ChangeEvent) => { + if (mode === "auto") { + setInvalid(e.currentTarget.checkValidity() !== true); + } + + onChange?.(e); + }; + + console.info(rest); + return ( <> {label && ( @@ -133,38 +94,29 @@ export const Input = forwardRef( )} {helper && (
- + {helper}
diff --git a/src/components/Input/input.css b/src/components/Input/input.css index d34725a..9a2f6fc 100644 --- a/src/components/Input/input.css +++ b/src/components/Input/input.css @@ -14,6 +14,11 @@ flex-direction: column; } +.input--invalid { + color: rgb(var(--codex-color-error)); + border-color: rgb(var(--codex-color-error)); +} + .input-label { margin-bottom: 0.5rem; font-weight: 500; diff --git a/stories/Input.stories.ts b/stories/Input.stories.ts index f373818..0207a64 100644 --- a/stories/Input.stories.ts +++ b/stories/Input.stories.ts @@ -54,10 +54,19 @@ export const Disabled: Story = { }, }; -export const CustomStyle: Story = { +export const AutoInvalid: Story = { args: { - id: "custom", - label: "Label", - style: { "--codex-input-border": "1px solid red" }, + id: "autoinvalid", + label: "Auto invalid", + pattern: "a", + mode: "auto" }, }; + +export const IsInvalid: Story = { + args: { + id: "autoinvalid", + label: "Auto invalid", + isInvalid: true + }, +}; \ No newline at end of file