@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,38 @@
1
+ import React from "react";
2
+ export type TextAreaProps = {
3
+ id?: string;
4
+ label?: string;
5
+ size?: "sm" | "md" | "lg";
6
+ rounded?: "none" | "normal" | "full";
7
+ variant?: "flat" | "outline" | "underline";
8
+ helperText?: string;
9
+ errorMessage?: string;
10
+ fullwidth?: boolean;
11
+ disabled?: boolean;
12
+ error?: boolean;
13
+ required?: boolean;
14
+ isFloatingLabel?: boolean;
15
+ keepCloseIconOnValue?: boolean;
16
+ hasClearIcon?: boolean;
17
+ labelClassName?: string;
18
+ className?: string;
19
+ } & Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, "size">;
20
+ export declare const TextArea: React.ForwardRefExoticComponent<{
21
+ id?: string;
22
+ label?: string;
23
+ size?: "sm" | "md" | "lg";
24
+ rounded?: "none" | "normal" | "full";
25
+ variant?: "flat" | "outline" | "underline";
26
+ helperText?: string;
27
+ errorMessage?: string;
28
+ fullwidth?: boolean;
29
+ disabled?: boolean;
30
+ error?: boolean;
31
+ required?: boolean;
32
+ isFloatingLabel?: boolean;
33
+ keepCloseIconOnValue?: boolean;
34
+ hasClearIcon?: boolean;
35
+ labelClassName?: string;
36
+ className?: string;
37
+ } & Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, "size"> & React.RefAttributes<HTMLTextAreaElement>>;
38
+ export default TextArea;
@@ -0,0 +1,9 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { TextArea } from "@/index";
3
+ declare const meta: Meta<typeof TextArea>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof TextArea>;
6
+ export declare const Default: Story;
7
+ export declare const ErrorState: Story;
8
+ export declare const HelperText: Story;
9
+ export declare const Disabled: Story;
@@ -0,0 +1,27 @@
1
+ export declare const textareaVariant: (props?: ({
2
+ size?: "sm" | "md" | "lg" | null | undefined;
3
+ rounded?: "none" | "normal" | "full" | null | undefined;
4
+ variant?: "outline" | "flat" | "underline" | null | undefined;
5
+ fullwidth?: boolean | null | undefined;
6
+ disabled?: boolean | null | undefined;
7
+ error?: boolean | null | undefined;
8
+ hasClearIcon?: boolean | null | undefined;
9
+ isFloatingLabel?: boolean | null | undefined;
10
+ } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
11
+ export declare const labelVariant: (props?: ({
12
+ size?: "sm" | "md" | "lg" | null | undefined;
13
+ disabled?: boolean | null | undefined;
14
+ error?: boolean | null | undefined;
15
+ isFloatingLabel?: boolean | null | undefined;
16
+ } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
17
+ export declare const clearIconWrapperVariant: (props?: ({
18
+ size?: "sm" | "md" | "lg" | null | undefined;
19
+ } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
20
+ export declare const clearIconVariant: (props?: ({
21
+ size?: "sm" | "md" | "lg" | null | undefined;
22
+ } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
23
+ export declare const helperTextVariant: (props?: ({
24
+ size?: "sm" | "md" | "lg" | null | undefined;
25
+ disabled?: boolean | null | undefined;
26
+ error?: boolean | null | undefined;
27
+ } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
@@ -2,6 +2,7 @@ import "./theme/global.css";
2
2
  import "./icons/iconConfig";
3
3
  export { default as Button } from "./components/Button/Button";
4
4
  export { default as TextInput } from "./components/TextInput/TextInput";
5
+ export { default as TextArea } from "./components/TextArea/TextArea";
5
6
  export { default as Text } from "./components/Text/Text";
6
7
  export { default as Tabs } from "./components/Tabs/Tabs";
7
8
  export { default as Dropdown } from "./components/Dropdown/Dropdown";
@@ -37,6 +38,7 @@ export * from "./components/FocusedScrollView/FocusedScrollView";
37
38
  export * from "./components/RadioGroup/RadioGroup";
38
39
  export type { ButtonProps } from "./components/Button/Button";
39
40
  export type { InputProps } from "./components/TextInput/TextInput";
41
+ export type { TextAreaProps } from "./components/TextArea/TextArea";
40
42
  export type { DropdownProps, Options } from "./components/Dropdown/Dropdown";
41
43
  export type { NavbarProps } from "./components/Navbar/Navbar";
42
44
  export type { AvatarProps } from "./components/Avatar/Avatar";
@@ -0,0 +1,55 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
12
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
+ import { forwardRef, useImperativeHandle, useMemo, useRef } from "react";
14
+ import { cn } from "@/utils/cn";
15
+ import { textareaVariant, labelVariant as textareaLabelVariant, helperTextVariant as textareaHelperTextVariant, clearIconWrapperVariant, clearIconVariant, } from "./TextArea.styles";
16
+ import { XCircleIcon } from "@heroicons/react/16/solid";
17
+ export const TextArea = forwardRef((_a, ref) => {
18
+ var { id, label, size = "md", rounded = "normal", variant = "outline", helperText, errorMessage, fullwidth = true, disabled = false, error = false, required = true, isFloatingLabel = true, keepCloseIconOnValue = false, hasClearIcon = true, labelClassName, className } = _a, props = __rest(_a, ["id", "label", "size", "rounded", "variant", "helperText", "errorMessage", "fullwidth", "disabled", "error", "required", "isFloatingLabel", "keepCloseIconOnValue", "hasClearIcon", "labelClassName", "className"]);
19
+ const textareaRef = useRef(null);
20
+ const _id = id || `textarea-${label !== null && label !== void 0 ? label : ""}`;
21
+ useImperativeHandle(ref, () => textareaRef === null || textareaRef === void 0 ? void 0 : textareaRef.current);
22
+ // Reuse TextInput visual language via utility classes to stay consistent
23
+ const containerClassName = useMemo(() => `inline-flex flex-col ${fullwidth ? "w-full" : ""}`, [fullwidth]);
24
+ const textareaClassName = textareaVariant({
25
+ size,
26
+ rounded,
27
+ variant,
28
+ fullwidth,
29
+ disabled,
30
+ error,
31
+ hasClearIcon,
32
+ isFloatingLabel,
33
+ });
34
+ return (_jsxs("div", { className: containerClassName, children: [_jsxs("div", { className: "relative", children: [_jsx("textarea", Object.assign({}, props, { id: _id, ref: textareaRef, disabled: disabled, placeholder: isFloatingLabel ? " " : props.placeholder, className: cn(textareaClassName, className) })), hasClearIcon && (_jsx("div", { className: clearIconWrapperVariant({ size }), style: {
35
+ display: keepCloseIconOnValue && props.value ? "flex" : undefined,
36
+ }, children: _jsx(XCircleIcon, { type: "button", className: clearIconVariant({ size }), onMouseDown: (e) => {
37
+ e.preventDefault();
38
+ if (textareaRef.current) {
39
+ const prev = textareaRef.current.value;
40
+ textareaRef.current.value = "";
41
+ if (props.onChange && prev !== "") {
42
+ props.onChange({ target: { value: "" } });
43
+ }
44
+ textareaRef.current.focus();
45
+ }
46
+ } }) })), label && (_jsxs("label", { htmlFor: _id, className: cn(textareaLabelVariant({
47
+ size,
48
+ disabled,
49
+ error,
50
+ isFloatingLabel,
51
+ }), labelClassName), children: [label, " ", required && (_jsx("span", { className: cn("text-error", {
52
+ "text-input-disable-text": disabled,
53
+ }), children: "*" }))] }))] }), (errorMessage || helperText) && (_jsx("span", { className: textareaHelperTextVariant({ size, disabled, error }), children: errorMessage || helperText }))] }));
54
+ });
55
+ export default TextArea;
@@ -0,0 +1,86 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { TextArea } from "@/index";
3
+ const meta = {
4
+ title: "Components/TextArea",
5
+ component: TextArea,
6
+ parameters: {
7
+ layout: "fullscreen",
8
+ },
9
+ tags: ["autodocs"],
10
+ decorators: [
11
+ (Story) => (_jsx("div", { className: "p-5 flex h-screen w-full bg-base-bg2", children: _jsx(Story, {}) })),
12
+ ],
13
+ argTypes: {
14
+ size: {
15
+ control: { type: "radio" },
16
+ options: ["sm", "md", "lg"],
17
+ },
18
+ rounded: {
19
+ control: { type: "radio" },
20
+ options: ["none", "normal", "full"],
21
+ },
22
+ variant: {
23
+ control: { type: "radio" },
24
+ options: ["flat", "outline", "underline"],
25
+ },
26
+ isFloatingLabel: { control: "boolean" },
27
+ fullwidth: { control: "boolean" },
28
+ disabled: { control: "boolean" },
29
+ error: { control: "boolean" },
30
+ required: { control: "boolean" },
31
+ },
32
+ args: {
33
+ label: "Description",
34
+ placeholder: "Type here...",
35
+ size: "md",
36
+ rounded: "normal",
37
+ variant: "outline",
38
+ isFloatingLabel: true,
39
+ fullwidth: true,
40
+ disabled: false,
41
+ error: false,
42
+ required: true,
43
+ hasClearIcon: true,
44
+ rows: 2,
45
+ },
46
+ };
47
+ export default meta;
48
+ export const Default = {
49
+ render: (args) => {
50
+ console.log("args ", args);
51
+ const props = Object.assign({}, args);
52
+ return (_jsxs("div", { className: "flex flex-row gap-4 w-full", children: [_jsx(TextArea, Object.assign({ id: "1" }, props, { size: "lg" })), _jsx(TextArea, Object.assign({ id: "2" }, props, { size: "md" })), _jsx(TextArea, Object.assign({ id: "3" }, props, { size: "sm" }))] }));
53
+ },
54
+ };
55
+ export const ErrorState = {
56
+ args: {
57
+ error: true,
58
+ errorMessage: "This field is required",
59
+ },
60
+ render: (args) => {
61
+ console.log("args ", args);
62
+ const props = Object.assign({}, args);
63
+ return (_jsxs("div", { className: "flex flex-row gap-4 w-full", children: [_jsx(TextArea, Object.assign({ id: "1" }, props, { size: "lg" })), _jsx(TextArea, Object.assign({ id: "2" }, props, { size: "md" })), _jsx(TextArea, Object.assign({ id: "3" }, props, { size: "sm" }))] }));
64
+ },
65
+ };
66
+ export const HelperText = {
67
+ args: {
68
+ helperText: "You can write up to 500 characters.",
69
+ },
70
+ render: (args) => {
71
+ console.log("args ", args);
72
+ const props = Object.assign({}, args);
73
+ return (_jsxs("div", { className: "flex flex-row gap-4 w-full", children: [_jsx(TextArea, Object.assign({ id: "1" }, props, { size: "lg" })), _jsx(TextArea, Object.assign({ id: "2" }, props, { size: "md" })), _jsx(TextArea, Object.assign({ id: "3" }, props, { size: "sm" }))] }));
74
+ },
75
+ };
76
+ export const Disabled = {
77
+ args: {
78
+ disabled: true,
79
+ value: "Disabled text area",
80
+ },
81
+ render: (args) => {
82
+ console.log("args ", args);
83
+ const props = Object.assign({}, args);
84
+ return (_jsxs("div", { className: "flex flex-row gap-4 w-full", children: [_jsx(TextArea, Object.assign({ id: "1" }, props, { size: "lg" })), _jsx(TextArea, Object.assign({ id: "2" }, props, { size: "md" })), _jsx(TextArea, Object.assign({ id: "3" }, props, { size: "sm" }))] }));
85
+ },
86
+ };
@@ -0,0 +1,207 @@
1
+ import { cva } from "class-variance-authority";
2
+ export const textareaVariant = cva([
3
+ "peer block w-full bg-transparent outline-none placeholder:text-transparent resize-y ui-scrollbar",
4
+ "text-input-filled-text caret-primary",
5
+ ], {
6
+ variants: {
7
+ size: {
8
+ sm: "p-2 px-3 typography-small1",
9
+ md: "py-2 px-3 typography-subtitile4",
10
+ lg: "p-4 typography-subtitile1",
11
+ },
12
+ rounded: {
13
+ none: "rounded-none",
14
+ normal: "rounded-md",
15
+ full: "rounded-full",
16
+ },
17
+ variant: {
18
+ flat: "",
19
+ outline: [
20
+ "ring-1 ring-inset ring-input-default-stroke",
21
+ "hover:ring-input-active-stroke",
22
+ "focus:ring-1 focus:ring-inset focus:ring-input-active-stroke",
23
+ ],
24
+ underline: "border-b-2 border-input-default-stroke transition-colors hover:border-input-active-stroke focus:border-input-stroke",
25
+ },
26
+ fullwidth: {
27
+ true: "w-full",
28
+ },
29
+ disabled: {
30
+ true: [
31
+ "bg-input-disable-bg text-input-disable-text ring-input-disable-stroke placeholder:text-input-disable-text",
32
+ "hover:ring-input-disable-stroke",
33
+ "cursor-not-allowed",
34
+ ],
35
+ },
36
+ error: {
37
+ true: "ring-input-error focus:ring-input-error",
38
+ },
39
+ hasClearIcon: {
40
+ true: "",
41
+ },
42
+ isFloatingLabel: {
43
+ true: "",
44
+ false: "placeholder:text-input-placeholder",
45
+ },
46
+ },
47
+ compoundVariants: [
48
+ {
49
+ variant: "underline",
50
+ className: "rounded-none",
51
+ },
52
+ {
53
+ hasClearIcon: true,
54
+ size: "sm",
55
+ class: "focus:pe-6",
56
+ },
57
+ {
58
+ hasClearIcon: true,
59
+ size: "md",
60
+ class: "focus:pe-8",
61
+ },
62
+ {
63
+ hasClearIcon: true,
64
+ size: "lg",
65
+ class: "focus:pe-10",
66
+ },
67
+ ],
68
+ defaultVariants: {
69
+ size: "md",
70
+ variant: "outline",
71
+ rounded: "normal",
72
+ fullwidth: false,
73
+ disabled: false,
74
+ error: false,
75
+ hasClearIcon: false,
76
+ isFloatingLabel: true,
77
+ },
78
+ });
79
+ export const labelVariant = cva([
80
+ "absolute block duration-450 transition-all px-[2px] text-input-default-text",
81
+ "peer-focus:text-input-filled-text peer-focus:bg-input-label-bg",
82
+ ], {
83
+ variants: {
84
+ size: {
85
+ sm: [],
86
+ md: [],
87
+ lg: [],
88
+ },
89
+ disabled: {
90
+ true: "text-input-default-text placeholder:text-input-default-text",
91
+ },
92
+ error: {
93
+ true: "ring-error",
94
+ },
95
+ isFloatingLabel: {
96
+ false: "hidden peer-placeholder-shown:block peer-focus:bg-transparent",
97
+ },
98
+ },
99
+ compoundVariants: [
100
+ // floating = true
101
+ {
102
+ isFloatingLabel: true,
103
+ size: "sm",
104
+ className: [
105
+ "left-3 -top-1.5 typography-label2 bg-input-label-bg",
106
+ "peer-placeholder-shown:top-2 peer-placeholder-shown:typography-small1 peer-placeholder-shown:bg-transparent",
107
+ "peer-focus:-top-1.5 peer-focus:typography-label2",
108
+ ],
109
+ },
110
+ {
111
+ isFloatingLabel: true,
112
+ size: "md",
113
+ className: [
114
+ "left-3 -top-1.5 typography-label1 bg-input-label-bg",
115
+ "peer-placeholder-shown:top-2 peer-placeholder-shown:typography-subtitile4 peer-placeholder-shown:bg-transparent",
116
+ "peer-focus:-top-1.5 peer-focus:typography-label1",
117
+ ],
118
+ },
119
+ {
120
+ isFloatingLabel: true,
121
+ size: "lg",
122
+ className: [
123
+ "left-4 -top-1.5 typography-label1 bg-input-label-bg",
124
+ "peer-placeholder-shown:top-4 peer-placeholder-shown:typography-subtitile1 peer-placeholder-shown:bg-transparent",
125
+ "peer-focus:-top-1.5 peer-focus:typography-label1",
126
+ ],
127
+ },
128
+ // --------------
129
+ // floating = false
130
+ {
131
+ isFloatingLabel: false,
132
+ size: "sm",
133
+ className: [
134
+ "left-3 peer-placeholder-shown:top-2 peer-placeholder-shown:typography-small1",
135
+ ],
136
+ },
137
+ {
138
+ isFloatingLabel: false,
139
+ size: "md",
140
+ className: [
141
+ "left-3 peer-placeholder-shown:top-2 peer-placeholder-shown:typography-subtitile4",
142
+ ],
143
+ },
144
+ {
145
+ isFloatingLabel: false,
146
+ size: "lg",
147
+ className: [
148
+ "left-4 peer-placeholder-shown:top-4 peer-placeholder-shown:typography-subtitile1",
149
+ ],
150
+ },
151
+ ],
152
+ defaultVariants: {
153
+ size: "md",
154
+ disabled: false,
155
+ error: false,
156
+ isFloatingLabel: true,
157
+ },
158
+ });
159
+ export const clearIconWrapperVariant = cva([
160
+ "absolute inset-y-0 right-0 items-start justify-center hidden peer-focus:flex",
161
+ ], {
162
+ variants: {
163
+ size: {
164
+ sm: "mr-2 pt-2",
165
+ md: "mr-3 pt-2",
166
+ lg: "mr-4 pt-4",
167
+ },
168
+ },
169
+ defaultVariants: {
170
+ size: "md",
171
+ },
172
+ });
173
+ export const clearIconVariant = cva([
174
+ "cursor-pointer z-50 fill-input-active-stroke hover:fill-input-default-text",
175
+ ], {
176
+ variants: {
177
+ size: {
178
+ sm: "size-3",
179
+ md: "size-4",
180
+ lg: "size-5",
181
+ },
182
+ },
183
+ defaultVariants: {
184
+ size: "md",
185
+ },
186
+ });
187
+ export const helperTextVariant = cva(["text-small1 flex flex-row items-center gap-1"], {
188
+ variants: {
189
+ size: {
190
+ sm: "mt-1",
191
+ md: "mt-[6px]",
192
+ lg: "mt-[6px]",
193
+ },
194
+ disabled: {
195
+ true: "text-input-disable-text",
196
+ },
197
+ error: {
198
+ true: "text-input-error",
199
+ false: "text-input-filled-text",
200
+ },
201
+ },
202
+ defaultVariants: {
203
+ size: "md",
204
+ disabled: false,
205
+ error: false,
206
+ },
207
+ });
@@ -1041,6 +1041,9 @@ input[type=number] {
1041
1041
  .cursor-default{
1042
1042
  cursor: default;
1043
1043
  }
1044
+ .cursor-not-allowed{
1045
+ cursor: not-allowed;
1046
+ }
1044
1047
  .cursor-pointer{
1045
1048
  cursor: pointer;
1046
1049
  }
@@ -1052,6 +1055,9 @@ input[type=number] {
1052
1055
  -moz-user-select: none;
1053
1056
  user-select: none;
1054
1057
  }
1058
+ .resize-y{
1059
+ resize: vertical;
1060
+ }
1055
1061
  .resize{
1056
1062
  resize: both;
1057
1063
  }
@@ -3062,6 +3068,12 @@ input[type=number] {
3062
3068
  .pr-xxl{
3063
3069
  padding-right: var(--spacing-spacing-xxl);
3064
3070
  }
3071
+ .pt-2{
3072
+ padding-top: 0.5rem;
3073
+ }
3074
+ .pt-4{
3075
+ padding-top: 1rem;
3076
+ }
3065
3077
  .text-left{
3066
3078
  text-align: left;
3067
3079
  }
@@ -3806,6 +3818,24 @@ input[type=number] {
3806
3818
  line-height: var(--button-button-ms-line-height, 22px);
3807
3819
  font-weight: var(--button-button-ms-weight, 700);
3808
3820
  }
3821
+ .ui-scrollbar::-webkit-scrollbar {
3822
+ height: 6px;
3823
+ width: 6px;
3824
+ background: rgba(0, 0, 0, 0.08);
3825
+ }
3826
+ .ui-scrollbar::-webkit-scrollbar-thumb {
3827
+ border-radius: 6px;
3828
+ background: rgba(121, 141, 150, 0.48);
3829
+ width: 6px;
3830
+ }
3831
+ .ui-scrollbar::-webkit-scrollbar-thumb:hover {
3832
+ background: rgba(251, 252, 253, 0.48);
3833
+ cursor: pointer;
3834
+ }
3835
+ .ui-scrollbar::-webkit-scrollbar-corner {
3836
+ display: none;
3837
+ /* background: transparent; */
3838
+ }
3809
3839
  .placeholder\:text-input-default-text::-moz-placeholder{
3810
3840
  --tw-text-opacity: 1;
3811
3841
  color: color-mix(in srgb, var(--input-color-default-text) calc(100% * var(--tw-text-opacity, 1)), transparent);