@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.
Files changed (34) hide show
  1. package/dist/cjs/bundle.css +44 -0
  2. package/dist/cjs/bundle.js +3 -3
  3. package/dist/cjs/bundle.js.map +1 -1
  4. package/dist/cjs/types/components/Dropdown/Dropdown.stories.d.ts +2 -0
  5. package/dist/cjs/types/components/InputFilter/InputFilter.stories.d.ts +2 -0
  6. package/dist/cjs/types/components/Search/Search.stories.d.ts +2 -0
  7. package/dist/cjs/types/components/TextInput/TextInput.d.ts +4 -0
  8. package/dist/cjs/types/components/TextInput/TextInput.stories.d.ts +11 -0
  9. package/dist/cjs/types/components/TextInput/TextInput.styles.d.ts +1 -0
  10. package/dist/cjs/types/components/Toast/useToast.d.ts +3 -0
  11. package/dist/components/TextInput/TextInput.js +66 -14
  12. package/dist/components/TextInput/TextInput.stories.js +15 -0
  13. package/dist/components/TextInput/TextInput.styles.js +116 -7
  14. package/dist/components/Toast/Toast.js +1 -1
  15. package/dist/components/Toast/Toaster.js +2 -2
  16. package/dist/esm/bundle.css +44 -0
  17. package/dist/esm/bundle.js +2 -2
  18. package/dist/esm/bundle.js.map +1 -1
  19. package/dist/esm/types/components/Dropdown/Dropdown.stories.d.ts +2 -0
  20. package/dist/esm/types/components/InputFilter/InputFilter.stories.d.ts +2 -0
  21. package/dist/esm/types/components/Search/Search.stories.d.ts +2 -0
  22. package/dist/esm/types/components/TextInput/TextInput.d.ts +4 -0
  23. package/dist/esm/types/components/TextInput/TextInput.stories.d.ts +11 -0
  24. package/dist/esm/types/components/TextInput/TextInput.styles.d.ts +1 -0
  25. package/dist/esm/types/components/Toast/useToast.d.ts +3 -0
  26. package/dist/index.d.ts +6 -0
  27. package/dist/src/theme/global.css +56 -0
  28. package/package.json +1 -1
  29. package/src/components/TextInput/TextInput.stories.tsx +83 -0
  30. package/src/components/TextInput/TextInput.styles.ts +117 -7
  31. package/src/components/TextInput/TextInput.tsx +115 -21
  32. package/src/components/Toast/Toast.tsx +1 -1
  33. package/src/components/Toast/Toaster.tsx +12 -1
  34. 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
- hasClearIcon: hasRightSectionIcon ? false : hasClearIcon,
92
- leftSectionIcon: hasLeftSectionIcon,
93
- rightSectionIcon: hasRightSectionIcon,
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
- // TODO startIcon
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
- // TODO startIcon
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
- {hasRightSectionIcon &&
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-tex", className)}
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
- <Icon type="heroicons" name="check-circle" className="size-6" />
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 =