Feat: make text input capable of support dropdown inputs also
This commit is contained in:
parent
c0c64c99c9
commit
86ccae87fb
3 changed files with 142 additions and 30 deletions
|
|
@ -1,8 +1,10 @@
|
||||||
|
import { Listbox, Transition } from "@headlessui/react";
|
||||||
import * as Form from "@radix-ui/react-form";
|
import * as Form from "@radix-ui/react-form";
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { Fragment, useEffect, useRef, useState } from "react";
|
||||||
import { InputComponentType } from "../../types/components";
|
import { InputComponentType } from "../../types/components";
|
||||||
import { handleKeyDown } from "../../utils/reactflowUtils";
|
import { handleKeyDown } from "../../utils/reactflowUtils";
|
||||||
import { classNames } from "../../utils/utils";
|
import { classNames } from "../../utils/utils";
|
||||||
|
import IconComponent from "../genericIconComponent";
|
||||||
import { Input } from "../ui/input";
|
import { Input } from "../ui/input";
|
||||||
|
|
||||||
export default function InputComponent({
|
export default function InputComponent({
|
||||||
|
|
@ -19,9 +21,11 @@ export default function InputComponent({
|
||||||
className,
|
className,
|
||||||
id = "",
|
id = "",
|
||||||
blurOnEnter = false,
|
blurOnEnter = false,
|
||||||
|
options = [],
|
||||||
}: InputComponentType): JSX.Element {
|
}: InputComponentType): JSX.Element {
|
||||||
const [pwdVisible, setPwdVisible] = useState(false);
|
const [pwdVisible, setPwdVisible] = useState(false);
|
||||||
const refInput = useRef<HTMLInputElement>(null);
|
const refInput = useRef<HTMLInputElement>(null);
|
||||||
|
const [showOptions, setShowOptions] = useState<boolean>(false);
|
||||||
// Clear component state
|
// Clear component state
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (disabled && value !== "") {
|
if (disabled && value !== "") {
|
||||||
|
|
@ -29,6 +33,11 @@ export default function InputComponent({
|
||||||
}
|
}
|
||||||
}, [disabled]);
|
}, [disabled]);
|
||||||
|
|
||||||
|
function onInputLostFocus(event): void {
|
||||||
|
if (onBlur) onBlur(event);
|
||||||
|
setShowOptions(false);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative w-full">
|
<div className="relative w-full">
|
||||||
{isForm ? (
|
{isForm ? (
|
||||||
|
|
@ -36,7 +45,7 @@ export default function InputComponent({
|
||||||
<Input
|
<Input
|
||||||
id={"form-" + id}
|
id={"form-" + id}
|
||||||
ref={refInput}
|
ref={refInput}
|
||||||
onBlur={onBlur}
|
onBlur={onInputLostFocus}
|
||||||
autoFocus={autoFocus}
|
autoFocus={autoFocus}
|
||||||
type={password && !pwdVisible ? "password" : "text"}
|
type={password && !pwdVisible ? "password" : "text"}
|
||||||
value={value}
|
value={value}
|
||||||
|
|
@ -65,34 +74,136 @@ export default function InputComponent({
|
||||||
/>
|
/>
|
||||||
</Form.Control>
|
</Form.Control>
|
||||||
) : (
|
) : (
|
||||||
<Input
|
<>
|
||||||
id={id}
|
<Input
|
||||||
ref={refInput}
|
id={id}
|
||||||
type="text"
|
ref={refInput}
|
||||||
onBlur={onBlur}
|
type="text"
|
||||||
value={value}
|
onBlur={(e) => setShowOptions(false)}
|
||||||
autoFocus={autoFocus}
|
value={value}
|
||||||
disabled={disabled}
|
autoFocus={autoFocus}
|
||||||
required={required}
|
disabled={disabled}
|
||||||
className={classNames(
|
required={required}
|
||||||
password && !pwdVisible && value !== ""
|
className={classNames(
|
||||||
? " text-clip password "
|
password && !pwdVisible && value !== ""
|
||||||
: "",
|
? " text-clip password "
|
||||||
editNode ? " input-edit-node " : "",
|
: "",
|
||||||
password && editNode ? "pr-8" : "",
|
editNode ? " input-edit-node " : "",
|
||||||
password && !editNode ? "pr-10" : "",
|
password && editNode ? "pr-8" : "",
|
||||||
className!
|
password && !editNode ? "pr-10" : "",
|
||||||
)}
|
className!
|
||||||
placeholder={password && editNode ? "Key" : placeholder}
|
)}
|
||||||
onChange={(e) => {
|
placeholder={password && editNode ? "Key" : placeholder}
|
||||||
onChange(e.target.value);
|
onChange={(e) => {
|
||||||
}}
|
onChange(e.target.value);
|
||||||
onKeyDown={(e) => {
|
setShowOptions(false);
|
||||||
handleKeyDown(e, value, "");
|
}}
|
||||||
if (blurOnEnter && e.key === "Enter") refInput.current?.blur();
|
onKeyDown={(e) => {
|
||||||
}}
|
handleKeyDown(e, value, "");
|
||||||
/>
|
if (blurOnEnter && e.key === "Enter") refInput.current?.blur();
|
||||||
|
}}
|
||||||
|
onFocus={() => setShowOptions(true)}
|
||||||
|
/>
|
||||||
|
{
|
||||||
|
/* options.length > 0 */ true ? (
|
||||||
|
<Listbox
|
||||||
|
onChange={(val) => {
|
||||||
|
onChange(val);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<>
|
||||||
|
<div className={"relative mt-1"}>
|
||||||
|
<Transition
|
||||||
|
show={showOptions}
|
||||||
|
as={Fragment}
|
||||||
|
leave="transition ease-in duration-100"
|
||||||
|
leaveFrom="opacity-100"
|
||||||
|
leaveTo="opacity-0"
|
||||||
|
>
|
||||||
|
<Listbox.Options
|
||||||
|
className={classNames(
|
||||||
|
editNode
|
||||||
|
? "dropdown-component-true-options nowheel custom-scroll"
|
||||||
|
: "dropdown-component-false-options nowheel custom-scroll",
|
||||||
|
false ? "mb-2 w-[250px]" : "absolute w-full"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{["key", "key2", "key3", "key4", "key5"].map(
|
||||||
|
(option, id) => (
|
||||||
|
<Listbox.Option
|
||||||
|
key={id}
|
||||||
|
className={({ active }) =>
|
||||||
|
classNames(
|
||||||
|
active ? " bg-accent" : "",
|
||||||
|
editNode
|
||||||
|
? "dropdown-component-false-option"
|
||||||
|
: "dropdown-component-true-option",
|
||||||
|
" hover:bg-accent"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
value={option}
|
||||||
|
>
|
||||||
|
{({ selected, active }) => (
|
||||||
|
<>
|
||||||
|
<span
|
||||||
|
className={classNames(
|
||||||
|
selected
|
||||||
|
? "font-semibold"
|
||||||
|
: "font-normal",
|
||||||
|
"block truncate "
|
||||||
|
)}
|
||||||
|
data-testid={`${option}-${id ?? ""}-option`}
|
||||||
|
>
|
||||||
|
{option}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
{selected ? (
|
||||||
|
<span
|
||||||
|
className={classNames(
|
||||||
|
active ? "text-background " : "",
|
||||||
|
"dropdown-component-choosal"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<IconComponent
|
||||||
|
name="Check"
|
||||||
|
className={
|
||||||
|
active
|
||||||
|
? "dropdown-component-check-icon"
|
||||||
|
: "dropdown-component-check-icon"
|
||||||
|
}
|
||||||
|
aria-hidden="true"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
) : null}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Listbox.Option>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</Listbox.Options>
|
||||||
|
</Transition>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
</Listbox>
|
||||||
|
) : null
|
||||||
|
}
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<span
|
||||||
|
className={
|
||||||
|
password
|
||||||
|
? "dropdown-component-arrow right-8"
|
||||||
|
: "dropdown-component-arrow right-0"
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<IconComponent
|
||||||
|
name="ChevronsUpDown"
|
||||||
|
className="dropdown-component-arrow-color"
|
||||||
|
aria-hidden="true"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
|
||||||
{password && (
|
{password && (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
|
|
|
||||||
|
|
@ -422,7 +422,7 @@
|
||||||
@apply block w-full truncate bg-background;
|
@apply block w-full truncate bg-background;
|
||||||
}
|
}
|
||||||
.dropdown-component-arrow {
|
.dropdown-component-arrow {
|
||||||
@apply pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2;
|
@apply pointer-events-none absolute inset-y-0 flex items-center pr-2;
|
||||||
}
|
}
|
||||||
.dropdown-component-arrow-color {
|
.dropdown-component-arrow-color {
|
||||||
@apply extra-side-bar-save-disable h-5 w-5;
|
@apply extra-side-bar-save-disable h-5 w-5;
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ export type InputComponentType = {
|
||||||
className?: string;
|
className?: string;
|
||||||
id?: string;
|
id?: string;
|
||||||
blurOnEnter?: boolean;
|
blurOnEnter?: boolean;
|
||||||
|
options?: string[];
|
||||||
};
|
};
|
||||||
export type ToggleComponentType = {
|
export type ToggleComponentType = {
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue