@rovula/ui 0.1.8 → 0.1.9
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 +0 -10
- package/dist/cjs/bundle.js +3 -3
- package/dist/cjs/bundle.js.map +1 -1
- package/dist/cjs/types/components/Form/ValidationHintList.d.ts +4 -1
- package/dist/components/Form/ValidationHintList.js +9 -9
- package/dist/components/OtpInput/OtpInput.js +1 -1
- package/dist/esm/bundle.css +0 -10
- package/dist/esm/bundle.js +2 -2
- package/dist/esm/bundle.js.map +1 -1
- package/dist/esm/types/components/Form/ValidationHintList.d.ts +4 -1
- package/dist/index.d.ts +4 -1
- package/dist/src/theme/global.css +0 -13
- package/package.json +1 -1
- package/src/components/Form/ValidationHintList.tsx +24 -11
- package/src/components/OtpInput/OtpInput.tsx +22 -9
|
@@ -6,12 +6,15 @@ export type ValidationHintRule<TValues> = {
|
|
|
6
6
|
validate: (values: TValues) => boolean;
|
|
7
7
|
when?: (values: TValues) => boolean;
|
|
8
8
|
};
|
|
9
|
+
export type ValidationHintStateClassMap = Partial<Record<ValidationHintState, string>>;
|
|
9
10
|
export type ValidationHintListProps<TValues> = {
|
|
10
11
|
values: TValues;
|
|
11
12
|
rules: ValidationHintRule<TValues>[];
|
|
12
13
|
mode?: ValidationHintMode;
|
|
13
14
|
className?: string;
|
|
14
15
|
itemClassName?: string;
|
|
16
|
+
labelStateClassName?: ValidationHintStateClassMap;
|
|
17
|
+
iconStateClassName?: ValidationHintStateClassMap;
|
|
15
18
|
};
|
|
16
|
-
export declare const ValidationHintList: <TValues>({ values, rules, mode, className, itemClassName, }: ValidationHintListProps<TValues>) => import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
export declare const ValidationHintList: <TValues>({ values, rules, mode, className, itemClassName, labelStateClassName, iconStateClassName, }: ValidationHintListProps<TValues>) => import("react/jsx-runtime").JSX.Element;
|
|
17
20
|
export default ValidationHintList;
|
package/dist/index.d.ts
CHANGED
|
@@ -1230,14 +1230,17 @@ type ValidationHintRule<TValues> = {
|
|
|
1230
1230
|
validate: (values: TValues) => boolean;
|
|
1231
1231
|
when?: (values: TValues) => boolean;
|
|
1232
1232
|
};
|
|
1233
|
+
type ValidationHintStateClassMap = Partial<Record<ValidationHintState, string>>;
|
|
1233
1234
|
type ValidationHintListProps<TValues> = {
|
|
1234
1235
|
values: TValues;
|
|
1235
1236
|
rules: ValidationHintRule<TValues>[];
|
|
1236
1237
|
mode?: ValidationHintMode;
|
|
1237
1238
|
className?: string;
|
|
1238
1239
|
itemClassName?: string;
|
|
1240
|
+
labelStateClassName?: ValidationHintStateClassMap;
|
|
1241
|
+
iconStateClassName?: ValidationHintStateClassMap;
|
|
1239
1242
|
};
|
|
1240
|
-
declare const ValidationHintList: <TValues>({ values, rules, mode, className, itemClassName, }: ValidationHintListProps<TValues>) => react_jsx_runtime.JSX.Element;
|
|
1243
|
+
declare const ValidationHintList: <TValues>({ values, rules, mode, className, itemClassName, labelStateClassName, iconStateClassName, }: ValidationHintListProps<TValues>) => react_jsx_runtime.JSX.Element;
|
|
1241
1244
|
|
|
1242
1245
|
type OptionValue = string | number;
|
|
1243
1246
|
type OptionLike<TValue extends OptionValue = string> = {
|
|
@@ -7889,11 +7889,6 @@ input[type=number] {
|
|
|
7889
7889
|
color: color-mix(in srgb, var(--text-g-contrast-medium) calc(100% * var(--tw-text-opacity, 1)), transparent);
|
|
7890
7890
|
}
|
|
7891
7891
|
|
|
7892
|
-
.text-text-white {
|
|
7893
|
-
--tw-text-opacity: 1;
|
|
7894
|
-
color: color-mix(in srgb, var(--text-white) calc(100% * var(--tw-text-opacity, 1)), transparent);
|
|
7895
|
-
}
|
|
7896
|
-
|
|
7897
7892
|
.text-warning {
|
|
7898
7893
|
--tw-text-opacity: 1;
|
|
7899
7894
|
color: color-mix(in srgb, var(--state-warning-default) calc(100% * var(--tw-text-opacity, 1)), transparent);
|
|
@@ -7920,14 +7915,6 @@ input[type=number] {
|
|
|
7920
7915
|
opacity: 0;
|
|
7921
7916
|
}
|
|
7922
7917
|
|
|
7923
|
-
.opacity-100 {
|
|
7924
|
-
opacity: 1;
|
|
7925
|
-
}
|
|
7926
|
-
|
|
7927
|
-
.opacity-40 {
|
|
7928
|
-
opacity: 0.4;
|
|
7929
|
-
}
|
|
7930
|
-
|
|
7931
7918
|
.opacity-50 {
|
|
7932
7919
|
opacity: 0.5;
|
|
7933
7920
|
}
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { CircleCheck } from "lucide-react";
|
|
3
3
|
import { cn } from "@/utils/cn";
|
|
4
4
|
|
|
5
5
|
export type ValidationHintState = "pending" | "valid" | "invalid";
|
|
@@ -12,12 +12,18 @@ export type ValidationHintRule<TValues> = {
|
|
|
12
12
|
when?: (values: TValues) => boolean;
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
+
export type ValidationHintStateClassMap = Partial<
|
|
16
|
+
Record<ValidationHintState, string>
|
|
17
|
+
>;
|
|
18
|
+
|
|
15
19
|
export type ValidationHintListProps<TValues> = {
|
|
16
20
|
values: TValues;
|
|
17
21
|
rules: ValidationHintRule<TValues>[];
|
|
18
22
|
mode?: ValidationHintMode;
|
|
19
23
|
className?: string;
|
|
20
24
|
itemClassName?: string;
|
|
25
|
+
labelStateClassName?: ValidationHintStateClassMap;
|
|
26
|
+
iconStateClassName?: ValidationHintStateClassMap;
|
|
21
27
|
};
|
|
22
28
|
|
|
23
29
|
const resolveHintState = <TValues,>(
|
|
@@ -30,16 +36,16 @@ const resolveHintState = <TValues,>(
|
|
|
30
36
|
return rule.validate(values) ? "valid" : "invalid";
|
|
31
37
|
};
|
|
32
38
|
|
|
33
|
-
const
|
|
34
|
-
valid: "text-
|
|
39
|
+
const hintLabelStateClass: Record<ValidationHintState, string> = {
|
|
40
|
+
valid: "text-text-g-contrast-high",
|
|
35
41
|
invalid: "text-input-error",
|
|
36
|
-
pending: "text-text-g-contrast-
|
|
42
|
+
pending: "text-text-g-contrast-high",
|
|
37
43
|
};
|
|
38
44
|
|
|
39
45
|
const hintIconStateClass: Record<ValidationHintState, string> = {
|
|
40
|
-
valid: "
|
|
41
|
-
invalid: "
|
|
42
|
-
pending: "
|
|
46
|
+
valid: "text-primary",
|
|
47
|
+
invalid: "text-input-error",
|
|
48
|
+
pending: "text-text-g-contrast-low",
|
|
43
49
|
};
|
|
44
50
|
|
|
45
51
|
export const ValidationHintList = <TValues,>({
|
|
@@ -48,6 +54,8 @@ export const ValidationHintList = <TValues,>({
|
|
|
48
54
|
mode = ["pending", "valid", "invalid"],
|
|
49
55
|
className,
|
|
50
56
|
itemClassName,
|
|
57
|
+
labelStateClassName,
|
|
58
|
+
iconStateClassName,
|
|
51
59
|
}: ValidationHintListProps<TValues>) => {
|
|
52
60
|
const enabledStates = new Set<ValidationHintState>(mode);
|
|
53
61
|
|
|
@@ -63,13 +71,18 @@ export const ValidationHintList = <TValues,>({
|
|
|
63
71
|
<li
|
|
64
72
|
key={rule.id}
|
|
65
73
|
className={cn(
|
|
66
|
-
"flex items-center gap-2 typography-small2",
|
|
67
|
-
|
|
74
|
+
"flex items-center gap-2 typography-small2 ",
|
|
75
|
+
hintLabelStateClass[normalizedState],
|
|
76
|
+
labelStateClassName?.[normalizedState],
|
|
68
77
|
itemClassName,
|
|
69
78
|
)}
|
|
70
79
|
>
|
|
71
|
-
<
|
|
72
|
-
className={cn(
|
|
80
|
+
<CircleCheck
|
|
81
|
+
className={cn(
|
|
82
|
+
"size-4",
|
|
83
|
+
hintIconStateClass[normalizedState],
|
|
84
|
+
iconStateClassName?.[normalizedState],
|
|
85
|
+
)}
|
|
73
86
|
/>
|
|
74
87
|
<span>{rule.label}</span>
|
|
75
88
|
</li>
|
|
@@ -26,7 +26,7 @@ export type OtpInputProps = {
|
|
|
26
26
|
const sanitizeChars = (
|
|
27
27
|
raw: string,
|
|
28
28
|
charPattern: RegExp,
|
|
29
|
-
maxLength: number
|
|
29
|
+
maxLength: number,
|
|
30
30
|
): string[] => {
|
|
31
31
|
const chars = Array.from(raw).filter((char) => charPattern.test(char));
|
|
32
32
|
return chars.slice(0, maxLength);
|
|
@@ -48,7 +48,7 @@ export const OtpInput = forwardRef<HTMLInputElement, OtpInputProps>(
|
|
|
48
48
|
className,
|
|
49
49
|
inputClassName,
|
|
50
50
|
},
|
|
51
|
-
ref
|
|
51
|
+
ref,
|
|
52
52
|
) => {
|
|
53
53
|
const inputRefs = useRef<Array<HTMLInputElement | null>>([]);
|
|
54
54
|
const containerRef = useRef<HTMLDivElement | null>(null);
|
|
@@ -58,7 +58,11 @@ export const OtpInput = forwardRef<HTMLInputElement, OtpInputProps>(
|
|
|
58
58
|
return Array.from({ length }, (_, index) => normalizedValue[index] || "");
|
|
59
59
|
}, [length, value]);
|
|
60
60
|
|
|
61
|
-
useImperativeHandle(
|
|
61
|
+
useImperativeHandle(
|
|
62
|
+
ref,
|
|
63
|
+
() => inputRefs.current[0] as HTMLInputElement,
|
|
64
|
+
[],
|
|
65
|
+
);
|
|
62
66
|
|
|
63
67
|
const setCode = (nextSlots: string[]) => {
|
|
64
68
|
const nextValue = nextSlots.join("");
|
|
@@ -107,7 +111,10 @@ export const OtpInput = forwardRef<HTMLInputElement, OtpInputProps>(
|
|
|
107
111
|
}
|
|
108
112
|
};
|
|
109
113
|
|
|
110
|
-
const handlePaste = (
|
|
114
|
+
const handlePaste = (
|
|
115
|
+
index: number,
|
|
116
|
+
event: ClipboardEvent<HTMLInputElement>,
|
|
117
|
+
) => {
|
|
111
118
|
event.preventDefault();
|
|
112
119
|
if (disabled) return;
|
|
113
120
|
|
|
@@ -125,7 +132,10 @@ export const OtpInput = forwardRef<HTMLInputElement, OtpInputProps>(
|
|
|
125
132
|
focusInput(nextFocusIndex);
|
|
126
133
|
};
|
|
127
134
|
|
|
128
|
-
const handleKeyDown = (
|
|
135
|
+
const handleKeyDown = (
|
|
136
|
+
index: number,
|
|
137
|
+
event: KeyboardEvent<HTMLInputElement>,
|
|
138
|
+
) => {
|
|
129
139
|
if (disabled) return;
|
|
130
140
|
|
|
131
141
|
if (event.key === "ArrowLeft") {
|
|
@@ -160,7 +170,10 @@ export const OtpInput = forwardRef<HTMLInputElement, OtpInputProps>(
|
|
|
160
170
|
};
|
|
161
171
|
|
|
162
172
|
return (
|
|
163
|
-
<div
|
|
173
|
+
<div
|
|
174
|
+
className={cn("flex items-center gap-3", className)}
|
|
175
|
+
ref={containerRef}
|
|
176
|
+
>
|
|
164
177
|
{slots.map((slot, index) => (
|
|
165
178
|
<input
|
|
166
179
|
key={index}
|
|
@@ -176,11 +189,11 @@ export const OtpInput = forwardRef<HTMLInputElement, OtpInputProps>(
|
|
|
176
189
|
autoFocus={autoFocus && index === 0}
|
|
177
190
|
aria-invalid={invalid || undefined}
|
|
178
191
|
className={cn(
|
|
179
|
-
"h-14 w-[46px] rounded-[8px] border bg-transparent text-center text-2xl font-semibold
|
|
192
|
+
"h-14 w-[46px] rounded-[8px] text-input-filled-text border bg-transparent text-center text-2xl font-semibold outline-none transition-all duration-200",
|
|
180
193
|
"border-input-default-stroke focus:border-input-active-stroke",
|
|
181
194
|
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
182
195
|
invalid && "border-input-error focus:border-input-error",
|
|
183
|
-
inputClassName
|
|
196
|
+
inputClassName,
|
|
184
197
|
)}
|
|
185
198
|
onFocus={(event) => {
|
|
186
199
|
event.target.select();
|
|
@@ -202,7 +215,7 @@ export const OtpInput = forwardRef<HTMLInputElement, OtpInputProps>(
|
|
|
202
215
|
))}
|
|
203
216
|
</div>
|
|
204
217
|
);
|
|
205
|
-
}
|
|
218
|
+
},
|
|
206
219
|
);
|
|
207
220
|
|
|
208
221
|
OtpInput.displayName = "OtpInput";
|