@rovula/ui 0.0.74 → 0.0.75

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.
@@ -0,0 +1,150 @@
1
+ import React, { forwardRef, useImperativeHandle, useMemo, useRef } from "react";
2
+ import { cn } from "@/utils/cn";
3
+ import {
4
+ textareaVariant,
5
+ labelVariant as textareaLabelVariant,
6
+ helperTextVariant as textareaHelperTextVariant,
7
+ clearIconWrapperVariant,
8
+ clearIconVariant,
9
+ } from "./TextArea.styles";
10
+ import { XCircleIcon } from "@heroicons/react/16/solid";
11
+
12
+ export type TextAreaProps = {
13
+ id?: string;
14
+ label?: string;
15
+ size?: "sm" | "md" | "lg";
16
+ rounded?: "none" | "normal" | "full";
17
+ variant?: "flat" | "outline" | "underline";
18
+ helperText?: string;
19
+ errorMessage?: string;
20
+ fullwidth?: boolean;
21
+ disabled?: boolean;
22
+ error?: boolean;
23
+ required?: boolean;
24
+ isFloatingLabel?: boolean;
25
+ keepCloseIconOnValue?: boolean;
26
+ hasClearIcon?: boolean;
27
+ labelClassName?: string;
28
+ className?: string;
29
+ } & Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, "size">;
30
+
31
+ export const TextArea = forwardRef<HTMLTextAreaElement, TextAreaProps>(
32
+ (
33
+ {
34
+ id,
35
+ label,
36
+ size = "md",
37
+ rounded = "normal",
38
+ variant = "outline",
39
+ helperText,
40
+ errorMessage,
41
+ fullwidth = true,
42
+ disabled = false,
43
+ error = false,
44
+ required = true,
45
+ isFloatingLabel = true,
46
+ keepCloseIconOnValue = false,
47
+ hasClearIcon = true,
48
+ labelClassName,
49
+ className,
50
+ ...props
51
+ },
52
+ ref
53
+ ) => {
54
+ const textareaRef = useRef<HTMLTextAreaElement>(null);
55
+ const _id = id || `textarea-${label ?? ""}`;
56
+
57
+ useImperativeHandle(ref, () => textareaRef?.current as HTMLTextAreaElement);
58
+
59
+ // Reuse TextInput visual language via utility classes to stay consistent
60
+ const containerClassName = useMemo(
61
+ () => `inline-flex flex-col ${fullwidth ? "w-full" : ""}`,
62
+ [fullwidth]
63
+ );
64
+
65
+ const textareaClassName = textareaVariant({
66
+ size,
67
+ rounded,
68
+ variant,
69
+ fullwidth,
70
+ disabled,
71
+ error,
72
+ hasClearIcon,
73
+ isFloatingLabel,
74
+ } as any);
75
+
76
+ return (
77
+ <div className={containerClassName}>
78
+ <div className="relative">
79
+ <textarea
80
+ {...props}
81
+ id={_id}
82
+ ref={textareaRef}
83
+ disabled={disabled}
84
+ placeholder={isFloatingLabel ? " " : props.placeholder}
85
+ className={cn(textareaClassName, className)}
86
+ />
87
+ {hasClearIcon && (
88
+ <div
89
+ className={clearIconWrapperVariant({ size })}
90
+ style={{
91
+ display:
92
+ keepCloseIconOnValue && props.value ? "flex" : undefined,
93
+ }}
94
+ >
95
+ <XCircleIcon
96
+ type="button"
97
+ className={clearIconVariant({ size })}
98
+ onMouseDown={(e) => {
99
+ e.preventDefault();
100
+ if (textareaRef.current) {
101
+ const prev = textareaRef.current.value;
102
+ textareaRef.current.value = "";
103
+ if (props.onChange && prev !== "") {
104
+ props.onChange({ target: { value: "" } } as any);
105
+ }
106
+ textareaRef.current.focus();
107
+ }
108
+ }}
109
+ />
110
+ </div>
111
+ )}
112
+ {label && (
113
+ <label
114
+ htmlFor={_id}
115
+ className={cn(
116
+ textareaLabelVariant({
117
+ size,
118
+ disabled,
119
+ error,
120
+ isFloatingLabel,
121
+ }),
122
+ labelClassName
123
+ )}
124
+ >
125
+ {label}{" "}
126
+ {required && (
127
+ <span
128
+ className={cn("text-error", {
129
+ "text-input-disable-text": disabled,
130
+ })}
131
+ >
132
+ *
133
+ </span>
134
+ )}
135
+ </label>
136
+ )}
137
+ </div>
138
+ {(errorMessage || helperText) && (
139
+ <span
140
+ className={textareaHelperTextVariant({ size, disabled, error })}
141
+ >
142
+ {errorMessage || helperText}
143
+ </span>
144
+ )}
145
+ </div>
146
+ );
147
+ }
148
+ );
149
+
150
+ export default TextArea;
package/src/index.ts CHANGED
@@ -5,6 +5,7 @@ import "./icons/iconConfig";
5
5
 
6
6
  export { default as Button } from "./components/Button/Button";
7
7
  export { default as TextInput } from "./components/TextInput/TextInput";
8
+ export { default as TextArea } from "./components/TextArea/TextArea";
8
9
  export { default as Text } from "./components/Text/Text";
9
10
  export { default as Tabs } from "./components/Tabs/Tabs";
10
11
  export { default as Dropdown } from "./components/Dropdown/Dropdown";
@@ -46,6 +47,7 @@ export * from "./components/RadioGroup/RadioGroup";
46
47
  // Export component types
47
48
  export type { ButtonProps } from "./components/Button/Button";
48
49
  export type { InputProps } from "./components/TextInput/TextInput";
50
+ export type { TextAreaProps } from "./components/TextArea/TextArea";
49
51
  export type { DropdownProps, Options } from "./components/Dropdown/Dropdown";
50
52
  export type { NavbarProps } from "./components/Navbar/Navbar";
51
53
  export type { AvatarProps } from "./components/Avatar/Avatar";
@@ -28,3 +28,29 @@
28
28
  -moz-appearance: textfield;
29
29
  }
30
30
  }
31
+
32
+ @layer utilities {
33
+
34
+ .ui-scrollbar::-webkit-scrollbar {
35
+ height: 6px;
36
+ width: 6px;
37
+ background: rgba(0, 0, 0, 0.08);
38
+ }
39
+
40
+ .ui-scrollbar::-webkit-scrollbar-thumb {
41
+ border-radius: 6px;
42
+ background: rgba(121, 141, 150, 0.48);
43
+ width: 6px;
44
+ }
45
+
46
+ .ui-scrollbar::-webkit-scrollbar-thumb:hover {
47
+ background: rgba(251, 252, 253, 0.48);
48
+ cursor: pointer;
49
+ }
50
+
51
+ .ui-scrollbar::-webkit-scrollbar-corner {
52
+ display: none;
53
+ /* background: transparent; */
54
+ }
55
+
56
+ }