-
-
Notifications
You must be signed in to change notification settings - Fork 503
Expand file tree
/
Copy pathTextInput.tsx
More file actions
117 lines (110 loc) · 3.48 KB
/
TextInput.tsx
File metadata and controls
117 lines (110 loc) · 3.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import type { ComponentProps, FC, ReactNode } from "react";
import { forwardRef } from "react";
import { twMerge } from "tailwind-merge";
import { mergeDeep } from "../../helpers/merge-deep";
import { getTheme } from "../../theme-store";
import type { DeepPartial, DynamicStringEnumKeysOf } from "../../types";
import type { FlowbiteBoolean, FlowbiteColors, FlowbiteSizes } from "../Flowbite";
import { HelperText } from "../HelperText";
export interface FlowbiteTextInputTheme {
base: string;
addon: string;
field: {
base: string;
icon: {
base: string;
svg: string;
};
rightIcon: {
base: string;
svg: string;
};
input: {
base: string;
sizes: FlowbiteTextInputSizes;
colors: FlowbiteTextInputColors;
withIcon: FlowbiteBoolean;
withRightIcon: FlowbiteBoolean;
withAddon: FlowbiteBoolean;
withShadow: FlowbiteBoolean;
};
};
}
export interface FlowbiteTextInputColors
extends Pick<FlowbiteColors, "gray" | "info" | "failure" | "warning" | "success"> {
[key: string]: string;
}
export interface FlowbiteTextInputSizes extends Pick<FlowbiteSizes, "sm" | "md" | "lg"> {
[key: string]: string;
}
export interface TextInputProps extends Omit<ComponentProps<"input">, "ref" | "color"> {
addon?: ReactNode;
color?: DynamicStringEnumKeysOf<FlowbiteTextInputColors>;
helperText?: ReactNode;
icon?: FC<ComponentProps<"svg">>;
onRightIconClick?: (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => void;
rightIcon?: FC<ComponentProps<"svg">>;
shadow?: boolean;
sizing?: DynamicStringEnumKeysOf<FlowbiteTextInputSizes>;
theme?: DeepPartial<FlowbiteTextInputTheme>;
}
export const TextInput = forwardRef<HTMLInputElement, TextInputProps>(
(
{
addon,
className,
color = "gray",
helperText,
icon: Icon,
onRightIconClick,
rightIcon: RightIcon,
shadow,
sizing = "md",
theme: customTheme = {},
type = "text",
...props
},
ref,
) => {
const theme = mergeDeep(getTheme().textInput, customTheme);
return (
<>
<div className={twMerge(theme.base, className)}>
{addon && <span className={theme.addon}>{addon}</span>}
<div className={theme.field.base}>
{Icon && (
<div className={theme.field.icon.base}>
<Icon className={theme.field.icon.svg} />
</div>
)}
{RightIcon && (
<div
data-testid="right-icon"
className={`${theme.field.rightIcon.base} ${!onRightIconClick ? "pointer-events-none" : ""}`}
onClick={onRightIconClick}
>
<RightIcon className={theme.field.rightIcon.svg} />
</div>
)}
<input
className={twMerge(
theme.field.input.base,
theme.field.input.colors[color],
theme.field.input.sizes[sizing],
theme.field.input.withIcon[Icon ? "on" : "off"],
theme.field.input.withRightIcon[RightIcon ? "on" : "off"],
theme.field.input.withAddon[addon ? "on" : "off"],
theme.field.input.withShadow[shadow ? "on" : "off"],
)}
type={type}
{...props}
ref={ref}
/>
</div>
</div>
{helperText && <HelperText color={color}>{helperText}</HelperText>}
</>
);
},
);
TextInput.displayName = "TextInput";