@rovula/ui 0.0.5 → 0.0.6

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,177 @@
1
+ import { cva } from "class-variance-authority";
2
+
3
+ export const inputVariant = cva(
4
+ [
5
+ "border-0 outline-none",
6
+ "p-1 flex",
7
+ "peer text-black placeholder:text-transparent",
8
+ ],
9
+ {
10
+ variants: {
11
+ size: {
12
+ sm: "p-2 px-3 typography-small1",
13
+ md: "py-2 px-3 typography-subtitile4",
14
+ lg: "p-4 typography-subtitile1",
15
+ },
16
+ rounded: {
17
+ none: "rounded-none",
18
+ normal: "rounded-xl",
19
+ full: "rounded-full",
20
+ },
21
+ variant: {
22
+ flat: "",
23
+ outline:
24
+ "ring-1 ring-inset ring-input-stroke hover:ring-input-active focus:ring-2 focus:ring-inset focus:ring-input-active",
25
+ underline:
26
+ "border-b-2 border-input-stroke transition-colors hover:border-input-stroke-active focus:border-input-stroke",
27
+ },
28
+ fullwidth: {
29
+ true: "w-full",
30
+ },
31
+ disabled: {
32
+ true: "text-input-text-disabled ring-input-stroke-disabled placeholder:text-input-text-disabled",
33
+ },
34
+ error: {
35
+ true: "ring-error",
36
+ },
37
+ hasClearIcon: {
38
+ true: "",
39
+ },
40
+ },
41
+ compoundVariants: [
42
+ {
43
+ variant: "underline",
44
+ className: "rounded-none",
45
+ },
46
+ {
47
+ hasClearIcon: true,
48
+ size: "sm",
49
+ class: "focus:pe-6",
50
+ },
51
+ {
52
+ hasClearIcon: true,
53
+ size: "md",
54
+ class: "focus:pe-8",
55
+ },
56
+ {
57
+ hasClearIcon: true,
58
+ size: "lg",
59
+ class: "focus:pe-10",
60
+ },
61
+ ],
62
+ defaultVariants: {
63
+ size: "md",
64
+ variant: "outline",
65
+ rounded: "normal",
66
+ fullwidth: false,
67
+ disabled: false,
68
+ error: false,
69
+ hasClearIcon: false,
70
+ },
71
+ }
72
+ );
73
+
74
+ export const labelVariant = cva(
75
+ [
76
+ "absolute block transition-all px-[2px] text-input-text peer-focus:text-input-text-active peer-focus:bg-input-label-background",
77
+ ],
78
+ {
79
+ variants: {
80
+ size: {
81
+ sm: [
82
+ "left-3 top-2 typography-small1 peer-focus:-top-1.5 peer-focus:typography-label2",
83
+ "bg-input-label-background peer-[:not(:placeholder-shown)]:-top-1.5 peer-[:not(:placeholder-shown)]:typography-label2",
84
+ ],
85
+ md: [
86
+ "left-3 top-2 typography-subtitile4 peer-focus:-top-1.5 peer-focus:typography-label1",
87
+ "bg-input-label-background peer-[:not(:placeholder-shown)]:-top-1.5 peer-[:not(:placeholder-shown)]:typography-label1",
88
+ ],
89
+ lg: [
90
+ "left-4 top-4 typography-subtitile1 peer-focus:-top-1.5 peer-focus:typography-label1",
91
+ "bg-input-label-background peer-[:not(:placeholder-shown)]:-top-1.5 peer-[:not(:placeholder-shown)]:typography-label1",
92
+ ],
93
+ },
94
+ disabled: {
95
+ true: "text-input-text-disabled ring-input-stroke-disabled placeholder:text-input-text-disabled",
96
+ },
97
+ error: {
98
+ true: "ring-error",
99
+ },
100
+ isFloating: {
101
+ true: "-top-1.5 typography-label1 bg-input-label-background",
102
+ },
103
+ },
104
+ compoundVariants: [
105
+ {
106
+ size: "sm",
107
+ isFloating: true,
108
+ class: "-top-1.5 typography-label2 bg-input-label-background",
109
+ },
110
+ ],
111
+ defaultVariants: {
112
+ size: "md",
113
+ disabled: false,
114
+ error: false,
115
+ isFloating: false,
116
+ },
117
+ }
118
+ );
119
+
120
+ export const helperTextVariant = cva(
121
+ ["text-small1 flex flex-row items-center gap-1"],
122
+ {
123
+ variants: {
124
+ size: {
125
+ sm: "mt-1",
126
+ md: "mt-[6px]",
127
+ lg: "mt-[6px]",
128
+ },
129
+ disabled: {
130
+ true: "text-input-text-disabled",
131
+ },
132
+ error: {
133
+ true: "text-error",
134
+ false: "text-input-text",
135
+ },
136
+ },
137
+ defaultVariants: {
138
+ size: "md",
139
+ disabled: false,
140
+ error: false,
141
+ },
142
+ }
143
+ );
144
+
145
+ export const iconWrapperVariant = cva(
146
+ [
147
+ "absolute inset-y-0 right-0 items-center justify-center hidden peer-focus:flex",
148
+ ],
149
+ {
150
+ variants: {
151
+ size: {
152
+ sm: "mr-2",
153
+ md: "mr-3",
154
+ lg: "mr-4",
155
+ },
156
+ },
157
+ defaultVariants: {
158
+ size: "md",
159
+ },
160
+ }
161
+ );
162
+
163
+ export const iconVariant = cva(
164
+ ["cursor-pointer z-50 fill-input-stroke-active hover:fill-input-text"],
165
+ {
166
+ variants: {
167
+ size: {
168
+ sm: "size-3",
169
+ md: "size-4",
170
+ lg: "size-5",
171
+ },
172
+ },
173
+ defaultVariants: {
174
+ size: "md",
175
+ },
176
+ }
177
+ );
@@ -0,0 +1,119 @@
1
+ import React, { FC, forwardRef, useImperativeHandle, useRef } from "react";
2
+ import {
3
+ helperTextVariant,
4
+ iconVariant,
5
+ iconWrapperVariant,
6
+ inputVariant,
7
+ labelVariant,
8
+ } from "./TextInput.styles";
9
+ import { twMerge } from "tailwind-merge";
10
+ import { XCircleIcon, ExclamationCircleIcon } from "@heroicons/react/16/solid";
11
+
12
+ type InputProps = {
13
+ id?: string;
14
+ label?: string;
15
+ size?: "sm" | "md" | "lg";
16
+ rounded?: "none" | "normal" | "full";
17
+ variant?: "flat" | "outline" | "underline";
18
+ type?: React.HTMLInputTypeAttribute;
19
+ helperText?: string;
20
+ errorMessage?: string;
21
+ fullwidth?: boolean;
22
+ disabled?: boolean;
23
+ error?: boolean;
24
+ required?: boolean;
25
+ hasClearIcon?: boolean;
26
+ className?: string;
27
+ } & Omit<React.InputHTMLAttributes<HTMLInputElement>, "size">;
28
+
29
+ const TextInput: FC<InputProps> = forwardRef(
30
+ (
31
+ {
32
+ id,
33
+ label,
34
+ size = "md",
35
+ rounded = "normal",
36
+ variant = "outline",
37
+ type = "text",
38
+ helperText,
39
+ errorMessage,
40
+ fullwidth = false,
41
+ disabled = false,
42
+ error = false,
43
+ required = true,
44
+ hasClearIcon = true,
45
+ ...props
46
+ },
47
+ ref
48
+ ) => {
49
+ const inputRef = useRef<HTMLInputElement>(null);
50
+ const _id = id || `${type}-${label}-input`;
51
+ const inputClassname = inputVariant({
52
+ size,
53
+ rounded,
54
+ variant,
55
+ fullwidth,
56
+ disabled,
57
+ error,
58
+ hasClearIcon,
59
+ });
60
+ const labelClassname = labelVariant({
61
+ size,
62
+ disabled,
63
+ error,
64
+ isFloating: !!props.value ?? false,
65
+ });
66
+ const helperTextClassname = helperTextVariant({ size, error, disabled });
67
+ const iconWrapperClassname = iconWrapperVariant({ size });
68
+ const iconClassname = iconVariant({ size });
69
+
70
+ useImperativeHandle(ref, () => ({
71
+ clearInput: handleClearInput,
72
+ }));
73
+
74
+ const handleClearInput = () => {
75
+ if (inputRef.current) {
76
+ inputRef.current.value = "";
77
+ }
78
+ };
79
+
80
+ return (
81
+ <div className={`flex flex-col ${fullwidth ? "w-full" : ""}`}>
82
+ <div className="relative">
83
+ <input
84
+ {...props}
85
+ ref={inputRef}
86
+ type={type}
87
+ id={_id}
88
+ disabled={disabled}
89
+ className={twMerge(inputClassname, props.className)}
90
+ />
91
+ {hasClearIcon && (
92
+ <div className={iconWrapperClassname}>
93
+ <XCircleIcon
94
+ type="button"
95
+ className={iconClassname}
96
+ onMouseDown={handleClearInput}
97
+ />
98
+ </div>
99
+ )}
100
+ <label htmlFor={_id} className={labelClassname}>
101
+ {label} {required && <span className="text-error">*</span>}
102
+ </label>
103
+ </div>
104
+ {(errorMessage || helperText) && (
105
+ <span className={helperTextClassname}>
106
+ <ExclamationCircleIcon
107
+ width={16}
108
+ height={16}
109
+ className={error ? "fill-error" : ""}
110
+ />{" "}
111
+ {errorMessage || helperText}
112
+ </span>
113
+ )}
114
+ </div>
115
+ );
116
+ }
117
+ );
118
+
119
+ export default TextInput;
@@ -128,9 +128,22 @@
128
128
  --error-default: var(--error-100);
129
129
  --error-foreground: var(--white);
130
130
 
131
-
131
+ /* Button */
132
132
  --btn-rounded-sm: 10px;
133
133
  --btn-rounded-md: 12px;
134
134
  --btn-rounded-lg: 16px;
135
+
136
+ /* Input */
137
+ --input-default-text-color: 164 169 178;
138
+ --input-default-stroke-color: 231 231 231;
139
+
140
+ --input-active-text-color: 29 30 39;
141
+ --input-active-stroke-color: 208 208 208;
142
+
143
+ --input-disabled-text-color: 196 199 205;
144
+ --input-disabled-stroke-color: 239 239 239;
145
+ --input-disabled-background-color: 247 247 247;
146
+
147
+ --input-label-background-color: 249 251 255;
135
148
  }
136
- }
149
+ }
@@ -1,8 +1,11 @@
1
+ const { DEFAULTS } = require("@rollup/plugin-node-resolve");
2
+
1
3
  /** @type {import('tailwindcss').Config} */
2
4
  module.exports = {
3
5
  theme: {
4
6
  extend: {
5
7
  colors: {
8
+ // Palette colors
6
9
  themes: {
7
10
  50: "rgb(var(--themes-50) / <alpha-value>)",
8
11
  100: "rgb(var(--themes-100) / <alpha-value>)",
@@ -134,6 +137,29 @@ module.exports = {
134
137
  DEFAULT: "rgb(var(--error-100) / <alpha-value>)",
135
138
  foreground: "rgb(var(--error-foreground) / <alpha-value>)",
136
139
  },
140
+ // Component color
141
+ input: {
142
+ text: {
143
+ DEFAULT: "rgb(var(--input-default-text-color) / <alpha-value>)",
144
+ active: "rgb(var(--input-active-text-color) / <alpha-value>)",
145
+ disabled: "rgb(var(--input-disabled-text-color) / <alpha-value>)",
146
+ },
147
+ stroke: {
148
+ DEFAULT: "rgb(var(--input-default-stroke-color) / <alpha-value>)",
149
+ active: "rgb(var(--input-active-stroke-color) / <alpha-value>)",
150
+ disabled: "rgb(var(--input-disabled-stroke-color) / <alpha-value>)",
151
+ },
152
+ background: {
153
+ DEFAULT: "transparent",
154
+ active: "transparent",
155
+ disabled:
156
+ "rgb(var(--input-disabled-background-color) / <alpha-value>)",
157
+ },
158
+ label: {
159
+ background:
160
+ "rgb(var(--input-label-background-color) / <alpha-value>)",
161
+ },
162
+ },
137
163
  },
138
164
  },
139
165
  },