diff --git a/packages/components/input/package.json b/packages/components/input/package.json index bf9022e..1526af5 100644 --- a/packages/components/input/package.json +++ b/packages/components/input/package.json @@ -1,6 +1,6 @@ { "name": "@ibrahimstudio/input", - "version": "1.1.14", + "version": "1.1.19", "description": "This package provides a customizable input component for React applications.", "main": "dist/index.js", "module": "dist/index.es.js", @@ -14,7 +14,8 @@ }, "workspaces": [ "../../utils/*", - "../../ui/*" + "../../ui/*", + "../../components/*" ], "keywords": [ "input", @@ -47,6 +48,7 @@ "@ibrahimstudio/icons": "workspace:*", "@ibrahimstudio/jsx": "workspace:*", "@ibrahimstudio/styles": "workspace:*", + "@ibrahimstudio/tooltip": "workspace:*", "react": "^18.2.0", "react-dom": "^18.2.0" } diff --git a/packages/components/input/src/input.tsx b/packages/components/input/src/input.tsx index 63e8bae..fc24a40 100644 --- a/packages/components/input/src/input.tsx +++ b/packages/components/input/src/input.tsx @@ -1,96 +1,19 @@ import React, { useState } from "react"; +import { InputProps, baseDefaultValues, selectDefaultValues } from "./types"; import { ISInput } from "@ibrahimstudio/jsx"; import { ISChevron, ISEyeOpen, ISEyeSlash } from "@ibrahimstudio/icons"; import { getInputStyles } from "@ibrahimstudio/styles"; import s from "./input.module.css"; -interface Option { - value: string | number; - label: string; -} - -interface InputProps { - id: string; - formId?: string; - variant?: "input" | "textarea" | "select"; - labelText: string; - baseColor?: string; - primaryColor?: string; - secondaryColor?: string; - radius?: "none" | "sm" | "md" | "lg" | "full"; - name: string; - placeholder?: string; - type: - | "date" - | "datetime-local" - | "email" - | "number" - | "password" - | "text" - | "tel" - | "time" - | "url"; - min?: number | string; - max?: number | string; - minLength?: number; - maxLength?: number; - cols?: number; - rows?: number; - value: string | number; - fallbackValue?: string; - options: Option[]; - autoComplete?: string; - onChange: React.ChangeEventHandler; - onSelect: (value: string | number) => void; - isLabeled: boolean; - isRequired?: boolean; - isReadonly?: boolean; - isDisabled?: boolean; - isSearchable?: boolean; - errorContent?: string; - infoContent?: string; - startContent?: React.ReactNode; - endContent?: React.ReactNode; -} - -const Input: React.FC = ({ - id = "ibrahimstudio-input-id", - formId = "ibrahimstudio-form-id", - variant = "input", - labelText = "Input Label", - baseColor = "var(--theme-color-base)", - primaryColor = "var(--theme-color-primary)", - secondaryColor = "var(--theme-color-secondary)", - radius = "md", - name, - placeholder = "Input Placeholder", - type = "text", - min, - max, - minLength, - maxLength, - cols, - rows = 3, - value, - fallbackValue, - options, - autoComplete, - onChange, - onSelect, - isLabeled = true, - isRequired = false, - isReadonly = false, - isDisabled = false, - isSearchable = false, - errorContent, - infoContent, - startContent, - endContent, -}) => { +const Input: React.FC = (props) => { + const inputprops = { ...baseDefaultValues, ...selectDefaultValues, ...props }; const [passwordSeen, setPasswordSeen] = React.useState(false); + const [optionsPosition, setOptionsPosition] = React.useState< + "above" | "below" + >("below"); const [selectOpen, setSelectOpen] = React.useState(false); const [selectedOption, setSelectedOption] = React.useState( - value + inputprops.value ); const [searchTerm, setSearchTerm] = useState(""); const ref = React.useRef(null); @@ -100,81 +23,88 @@ const Input: React.FC = ({ setPasswordSeen(!passwordSeen); }; - const filteredOptions = - searchTerm.length > 0 - ? options.filter((option) => - option.label.toLowerCase().includes(searchTerm.toLowerCase()) - ) - : options; - - const handleSelectChange = (e: React.ChangeEvent) => { - setSelectedOption(e.target.value); - onSelect(e.target.value); - }; - - const handleOptionClick = (optionValue: string | number) => { - setSelectedOption(optionValue); - onSelect(optionValue); - setSelectOpen(false); - }; - const renderVariant = () => { - switch (variant) { + switch (inputprops.variant) { case "input": return ( ); case "select": + const filteredOptions = + searchTerm.length > 0 + ? inputprops.options.filter((option) => + option.label.toLowerCase().includes(searchTerm.toLowerCase()) + ) + : inputprops.options; + + const handleSelectChange = (e: React.ChangeEvent) => { + setSelectedOption(e.target.value); + inputprops.onSelect(e.target.value); + }; + + const handleOptionClick = (optionValue: string | number) => { + setSelectedOption(optionValue); + inputprops.onSelect(optionValue); + setSelectOpen(false); + }; + return ( option.value === selectedOption) - ?.label || placeholder + ? inputprops.placeholder + : inputprops.options.find( + (option) => option.value === selectedOption + )?.label || inputprops.placeholder } onChange={handleSelectChange} - required={isRequired} + required={inputprops.isRequired} readOnly={true} - disabled={isDisabled} + disabled={inputprops.isDisabled} onClick={() => setSelectOpen(!selectOpen)} /> {selectOpen && (
- {isSearchable ? ( + {inputprops.isSearchable ? ( = ({ setSelectedOption(""); }} > - {placeholder} + {inputprops.placeholder}
)} {filteredOptions.map((option) => ( @@ -213,50 +143,28 @@ const Input: React.FC = ({ case "textarea": return (