@rovula/ui 0.0.67 → 0.0.69
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/bundle.css +44 -0
- package/dist/cjs/bundle.js +3 -3
- package/dist/cjs/bundle.js.map +1 -1
- package/dist/cjs/types/components/Dropdown/Dropdown.stories.d.ts +2 -0
- package/dist/cjs/types/components/InputFilter/InputFilter.stories.d.ts +2 -0
- package/dist/cjs/types/components/Search/Search.stories.d.ts +2 -0
- package/dist/cjs/types/components/TextInput/TextInput.d.ts +4 -0
- package/dist/cjs/types/components/TextInput/TextInput.stories.d.ts +11 -0
- package/dist/cjs/types/components/TextInput/TextInput.styles.d.ts +1 -0
- package/dist/cjs/types/components/Toast/useToast.d.ts +3 -0
- package/dist/components/TextInput/TextInput.js +66 -14
- package/dist/components/TextInput/TextInput.stories.js +15 -0
- package/dist/components/TextInput/TextInput.styles.js +116 -7
- package/dist/components/Toast/Toast.js +1 -1
- package/dist/components/Toast/Toaster.js +2 -2
- package/dist/esm/bundle.css +44 -0
- package/dist/esm/bundle.js +2 -2
- package/dist/esm/bundle.js.map +1 -1
- package/dist/esm/types/components/Dropdown/Dropdown.stories.d.ts +2 -0
- package/dist/esm/types/components/InputFilter/InputFilter.stories.d.ts +2 -0
- package/dist/esm/types/components/Search/Search.stories.d.ts +2 -0
- package/dist/esm/types/components/TextInput/TextInput.d.ts +4 -0
- package/dist/esm/types/components/TextInput/TextInput.stories.d.ts +11 -0
- package/dist/esm/types/components/TextInput/TextInput.styles.d.ts +1 -0
- package/dist/esm/types/components/Toast/useToast.d.ts +3 -0
- package/dist/index.d.ts +6 -0
- package/dist/src/theme/global.css +56 -0
- package/package.json +1 -1
- package/src/components/TextInput/TextInput.stories.tsx +83 -0
- package/src/components/TextInput/TextInput.styles.ts +117 -7
- package/src/components/TextInput/TextInput.tsx +115 -21
- package/src/components/Toast/Toast.tsx +1 -1
- package/src/components/Toast/Toaster.tsx +12 -1
- package/src/components/Toast/useToast.ts +3 -0
|
@@ -4,6 +4,7 @@ import React, {
|
|
|
4
4
|
forwardRef,
|
|
5
5
|
useCallback,
|
|
6
6
|
useImperativeHandle,
|
|
7
|
+
useMemo,
|
|
7
8
|
useRef,
|
|
8
9
|
} from "react";
|
|
9
10
|
import {
|
|
@@ -28,6 +29,7 @@ export type InputProps = {
|
|
|
28
29
|
size?: "sm" | "md" | "lg";
|
|
29
30
|
rounded?: "none" | "normal" | "full";
|
|
30
31
|
variant?: "flat" | "outline" | "underline";
|
|
32
|
+
iconMode?: "flat" | "solid";
|
|
31
33
|
type?: React.HTMLInputTypeAttribute;
|
|
32
34
|
helperText?: string;
|
|
33
35
|
errorMessage?: string;
|
|
@@ -45,6 +47,7 @@ export type InputProps = {
|
|
|
45
47
|
labelClassName?: string;
|
|
46
48
|
onClickStartIcon?: () => void;
|
|
47
49
|
onClickEndIcon?: () => void;
|
|
50
|
+
renderStartIcon?: () => ReactNode;
|
|
48
51
|
renderEndIcon?: () => ReactNode;
|
|
49
52
|
} & Omit<React.InputHTMLAttributes<HTMLInputElement>, "size">;
|
|
50
53
|
|
|
@@ -57,6 +60,7 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
|
|
|
57
60
|
rounded = "normal",
|
|
58
61
|
variant = "outline",
|
|
59
62
|
type = "text",
|
|
63
|
+
iconMode = "solid",
|
|
60
64
|
helperText,
|
|
61
65
|
errorMessage,
|
|
62
66
|
fullwidth = true,
|
|
@@ -70,7 +74,9 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
|
|
|
70
74
|
startIcon,
|
|
71
75
|
endIcon,
|
|
72
76
|
labelClassName,
|
|
77
|
+
onClickStartIcon,
|
|
73
78
|
onClickEndIcon,
|
|
79
|
+
renderStartIcon,
|
|
74
80
|
renderEndIcon,
|
|
75
81
|
...props
|
|
76
82
|
},
|
|
@@ -78,8 +84,9 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
|
|
|
78
84
|
) => {
|
|
79
85
|
const inputRef = useRef<HTMLInputElement>(null);
|
|
80
86
|
const _id = id || `${type}-${label}-input`;
|
|
81
|
-
const hasLeftSectionIcon = !!startIcon;
|
|
82
|
-
const hasRightSectionIcon = !!endIcon;
|
|
87
|
+
const hasLeftSectionIcon = !!startIcon || !!renderStartIcon;
|
|
88
|
+
const hasRightSectionIcon = !!endIcon || !!renderEndIcon;
|
|
89
|
+
|
|
83
90
|
const inputClassname = inputVariant({
|
|
84
91
|
size,
|
|
85
92
|
rounded,
|
|
@@ -87,27 +94,40 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
|
|
|
87
94
|
fullwidth,
|
|
88
95
|
disabled,
|
|
89
96
|
error,
|
|
90
|
-
hasSearchIcon
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
97
|
+
hasSearchIcon:
|
|
98
|
+
(iconMode === "flat" && hasLeftSectionIcon) || hasSearchIcon,
|
|
99
|
+
hasClearIcon:
|
|
100
|
+
(iconMode === "flat" && hasRightSectionIcon) || hasClearIcon,
|
|
101
|
+
leftSectionIcon: iconMode === "solid" ? hasLeftSectionIcon : false,
|
|
102
|
+
rightSectionIcon: iconMode === "solid" ? hasRightSectionIcon : false,
|
|
94
103
|
});
|
|
95
104
|
const labelClassname = labelVariant({
|
|
96
105
|
size,
|
|
97
106
|
disabled,
|
|
98
107
|
error,
|
|
99
|
-
hasSearchIcon
|
|
108
|
+
hasSearchIcon:
|
|
109
|
+
(iconMode === "flat" && hasLeftSectionIcon) || hasSearchIcon,
|
|
110
|
+
hasLeftSectionIcon: iconMode === "solid" ? hasLeftSectionIcon : false,
|
|
100
111
|
isFloatingLabel,
|
|
101
112
|
});
|
|
102
113
|
const helperTextClassname = helperTextVariant({ size, error, disabled });
|
|
103
114
|
const iconWrapperClassname = iconWrapperVariant({ size });
|
|
104
115
|
const iconSearchWrapperClassname = iconSearchWrapperVariant({ size });
|
|
105
116
|
const iconClassname = iconVariant({ size });
|
|
106
|
-
|
|
117
|
+
|
|
118
|
+
// TODO wait for clearify aboutm start,end, search and clearIcon with iconMode
|
|
119
|
+
|
|
120
|
+
const startIconWrapperClassname = sectionIconWrapperVariant({
|
|
121
|
+
size,
|
|
122
|
+
rounded,
|
|
123
|
+
error,
|
|
124
|
+
position: "start",
|
|
125
|
+
});
|
|
107
126
|
const endIconWrapperClassname = sectionIconWrapperVariant({
|
|
108
127
|
size,
|
|
109
128
|
rounded,
|
|
110
129
|
error,
|
|
130
|
+
position: "end",
|
|
111
131
|
});
|
|
112
132
|
|
|
113
133
|
useImperativeHandle(ref, () => inputRef?.current as HTMLInputElement);
|
|
@@ -123,7 +143,15 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
|
|
|
123
143
|
}
|
|
124
144
|
}, [props.onChange]);
|
|
125
145
|
|
|
126
|
-
|
|
146
|
+
const handleOnClickLeftSectionIcon = useCallback(() => {
|
|
147
|
+
if (disabled) return;
|
|
148
|
+
|
|
149
|
+
onClickStartIcon?.();
|
|
150
|
+
if (inputRef.current) {
|
|
151
|
+
inputRef.current.focus();
|
|
152
|
+
}
|
|
153
|
+
}, [disabled, onClickStartIcon]);
|
|
154
|
+
|
|
127
155
|
const handleOnClickRightSectionIcon = useCallback(() => {
|
|
128
156
|
if (disabled) return;
|
|
129
157
|
|
|
@@ -133,10 +161,84 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
|
|
|
133
161
|
}
|
|
134
162
|
}, [disabled, onClickEndIcon]);
|
|
135
163
|
|
|
164
|
+
const startIconElement = useMemo(() => {
|
|
165
|
+
if (!hasLeftSectionIcon) return;
|
|
166
|
+
|
|
167
|
+
if (renderStartIcon) return renderStartIcon();
|
|
168
|
+
|
|
169
|
+
if (iconMode === "flat") {
|
|
170
|
+
return (
|
|
171
|
+
<div className={iconSearchWrapperClassname}>
|
|
172
|
+
<div
|
|
173
|
+
className={iconClassname}
|
|
174
|
+
onClick={handleOnClickLeftSectionIcon}
|
|
175
|
+
>
|
|
176
|
+
{startIcon}
|
|
177
|
+
</div>
|
|
178
|
+
</div>
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return (
|
|
183
|
+
<div
|
|
184
|
+
className={startIconWrapperClassname}
|
|
185
|
+
onClick={handleOnClickLeftSectionIcon}
|
|
186
|
+
>
|
|
187
|
+
{startIcon}
|
|
188
|
+
</div>
|
|
189
|
+
);
|
|
190
|
+
}, [
|
|
191
|
+
hasLeftSectionIcon,
|
|
192
|
+
startIcon,
|
|
193
|
+
iconMode,
|
|
194
|
+
iconSearchWrapperClassname,
|
|
195
|
+
startIconWrapperClassname,
|
|
196
|
+
iconClassname,
|
|
197
|
+
renderStartIcon,
|
|
198
|
+
handleOnClickLeftSectionIcon,
|
|
199
|
+
]);
|
|
200
|
+
|
|
201
|
+
const endIconElement = useMemo(() => {
|
|
202
|
+
if (!hasRightSectionIcon) return;
|
|
203
|
+
|
|
204
|
+
if (renderEndIcon) return renderEndIcon();
|
|
205
|
+
|
|
206
|
+
if (iconMode === "flat") {
|
|
207
|
+
return (
|
|
208
|
+
<div className={cn(iconWrapperClassname, "flex")}>
|
|
209
|
+
<div
|
|
210
|
+
className={iconClassname}
|
|
211
|
+
onClick={handleOnClickRightSectionIcon}
|
|
212
|
+
>
|
|
213
|
+
{endIcon}
|
|
214
|
+
</div>
|
|
215
|
+
</div>
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return (
|
|
220
|
+
<div
|
|
221
|
+
className={endIconWrapperClassname}
|
|
222
|
+
onClick={handleOnClickRightSectionIcon}
|
|
223
|
+
>
|
|
224
|
+
{endIcon}
|
|
225
|
+
</div>
|
|
226
|
+
);
|
|
227
|
+
}, [
|
|
228
|
+
hasRightSectionIcon,
|
|
229
|
+
endIcon,
|
|
230
|
+
iconMode,
|
|
231
|
+
iconSearchWrapperClassname,
|
|
232
|
+
endIconWrapperClassname,
|
|
233
|
+
iconClassname,
|
|
234
|
+
renderEndIcon,
|
|
235
|
+
handleOnClickRightSectionIcon,
|
|
236
|
+
]);
|
|
237
|
+
|
|
136
238
|
return (
|
|
137
239
|
<div className={`inline-flex flex-col ${fullwidth ? "w-full" : ""}`}>
|
|
138
240
|
<div className="relative">
|
|
139
|
-
{hasSearchIcon && (
|
|
241
|
+
{hasSearchIcon && !hasLeftSectionIcon && (
|
|
140
242
|
<div className={iconSearchWrapperClassname}>
|
|
141
243
|
<MagnifyingGlassIcon className={iconClassname} />
|
|
142
244
|
</div>
|
|
@@ -150,6 +252,8 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
|
|
|
150
252
|
disabled={disabled}
|
|
151
253
|
className={cn(inputClassname, props.className)}
|
|
152
254
|
/>
|
|
255
|
+
{startIconElement}
|
|
256
|
+
|
|
153
257
|
{hasClearIcon && !hasRightSectionIcon && (
|
|
154
258
|
<div
|
|
155
259
|
className={iconWrapperClassname}
|
|
@@ -165,17 +269,7 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
|
|
|
165
269
|
/>
|
|
166
270
|
</div>
|
|
167
271
|
)}
|
|
168
|
-
{
|
|
169
|
-
(renderEndIcon ? (
|
|
170
|
-
renderEndIcon()
|
|
171
|
-
) : (
|
|
172
|
-
<div
|
|
173
|
-
className={endIconWrapperClassname}
|
|
174
|
-
onClick={handleOnClickRightSectionIcon}
|
|
175
|
-
>
|
|
176
|
-
{endIcon}
|
|
177
|
-
</div>
|
|
178
|
-
))}
|
|
272
|
+
{endIconElement}
|
|
179
273
|
|
|
180
274
|
<label htmlFor={_id} className={cn(labelClassname, labelClassName)}>
|
|
181
275
|
{label}{" "}
|
|
@@ -93,7 +93,7 @@ const ToastDescription = React.forwardRef<
|
|
|
93
93
|
>(({ className, ...props }, ref) => (
|
|
94
94
|
<ToastPrimitives.Description
|
|
95
95
|
ref={ref}
|
|
96
|
-
className={cn("typography-subtitile5 text-input-default-
|
|
96
|
+
className={cn("typography-subtitile5 text-input-default-text", className)}
|
|
97
97
|
{...props}
|
|
98
98
|
/>
|
|
99
99
|
));
|
|
@@ -43,6 +43,8 @@ export function Toaster({
|
|
|
43
43
|
description,
|
|
44
44
|
action,
|
|
45
45
|
contentMode = "horizontal",
|
|
46
|
+
iconProps,
|
|
47
|
+
renderIcon,
|
|
46
48
|
...props
|
|
47
49
|
}) {
|
|
48
50
|
return (
|
|
@@ -53,7 +55,16 @@ export function Toaster({
|
|
|
53
55
|
iconWrapperClassName
|
|
54
56
|
)}
|
|
55
57
|
>
|
|
56
|
-
|
|
58
|
+
{renderIcon ? (
|
|
59
|
+
renderIcon?.()
|
|
60
|
+
) : (
|
|
61
|
+
<Icon
|
|
62
|
+
type="heroicons"
|
|
63
|
+
name="check-circle"
|
|
64
|
+
className="size-6"
|
|
65
|
+
{...iconProps}
|
|
66
|
+
/>
|
|
67
|
+
)}
|
|
57
68
|
</div>
|
|
58
69
|
<div
|
|
59
70
|
className={cn(
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// Inspired by react-hot-toast library
|
|
4
4
|
import * as React from "react";
|
|
5
5
|
import { ToastActionElement, ToastProps } from "./Toast";
|
|
6
|
+
import { IconProps } from "../Icon/Icon";
|
|
6
7
|
|
|
7
8
|
const TOAST_LIMIT = 1;
|
|
8
9
|
const TOAST_REMOVE_DELAY = 3000;
|
|
@@ -14,6 +15,8 @@ type ToasterToast = ToastProps & {
|
|
|
14
15
|
action?: ToastActionElement;
|
|
15
16
|
contentMode?: "vertical" | "horizontal";
|
|
16
17
|
onClose?: () => void;
|
|
18
|
+
iconProps?: IconProps;
|
|
19
|
+
renderIcon?: () => React.ReactElement;
|
|
17
20
|
};
|
|
18
21
|
|
|
19
22
|
type ToasterPosition =
|