next-helios-fe 1.7.28 → 1.8.1
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/components/form/index.d.ts +2 -0
- package/dist/components/form/other/rate.d.ts +9 -0
- package/dist/components/form/other/rating.d.ts +9 -0
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/src/components/form/index.tsx +3 -0
- package/src/components/form/other/rating.tsx +121 -0
package/package.json
CHANGED
@@ -22,6 +22,7 @@ import {
|
|
22
22
|
type MultipleSelectProps,
|
23
23
|
} from "./other/multipleSelect";
|
24
24
|
import { Autocomplete, type AutocompleteProps } from "./other/autocomplete";
|
25
|
+
import { Rating, type RatingProps } from "./other/rating";
|
25
26
|
import { Emoji, type EmojiProps } from "./other/emoji";
|
26
27
|
|
27
28
|
interface FormProps extends React.FormHTMLAttributes<HTMLFormElement> {
|
@@ -48,6 +49,7 @@ interface FormComponent extends React.FC<FormProps> {
|
|
48
49
|
Select: React.FC<SelectProps>;
|
49
50
|
MultipleSelect: React.FC<MultipleSelectProps>;
|
50
51
|
Autocomplete: React.FC<AutocompleteProps>;
|
52
|
+
Rating: React.FC<RatingProps>;
|
51
53
|
Emoji: React.FC<EmojiProps>;
|
52
54
|
}
|
53
55
|
|
@@ -84,4 +86,5 @@ Form.Textarea = Textarea;
|
|
84
86
|
Form.Select = Select;
|
85
87
|
Form.MultipleSelect = MultipleSelect;
|
86
88
|
Form.Autocomplete = Autocomplete;
|
89
|
+
Form.Rating = Rating;
|
87
90
|
Form.Emoji = Emoji;
|
@@ -0,0 +1,121 @@
|
|
1
|
+
"use client";
|
2
|
+
import React, { useState, useEffect } from "react";
|
3
|
+
import { Icon } from "@iconify/react";
|
4
|
+
|
5
|
+
export interface RatingProps extends React.InputHTMLAttributes<HTMLInputElement> {
|
6
|
+
label?: string;
|
7
|
+
description?: string;
|
8
|
+
options?: {
|
9
|
+
height?: "short" | "medium" | "high";
|
10
|
+
};
|
11
|
+
}
|
12
|
+
|
13
|
+
export const Rating: React.FC<RatingProps> = ({
|
14
|
+
options,
|
15
|
+
label,
|
16
|
+
description,
|
17
|
+
...rest
|
18
|
+
}) => {
|
19
|
+
const [tempValue, setTempValue] = useState("");
|
20
|
+
const height =
|
21
|
+
options?.height === "short"
|
22
|
+
? "py-1"
|
23
|
+
: options?.height === "high"
|
24
|
+
? "py-2"
|
25
|
+
: "py-1.5";
|
26
|
+
|
27
|
+
const starHeight =
|
28
|
+
options?.height === "short"
|
29
|
+
? "text-3xl"
|
30
|
+
: options?.height === "high"
|
31
|
+
? "text-5xl"
|
32
|
+
: "text-4xl";
|
33
|
+
|
34
|
+
useEffect(() => {
|
35
|
+
if (rest.value || rest.value === "") {
|
36
|
+
setTempValue(rest.value as string);
|
37
|
+
return;
|
38
|
+
} else if (rest.defaultValue || rest.defaultValue === "") {
|
39
|
+
setTempValue(rest.defaultValue as string);
|
40
|
+
return;
|
41
|
+
}
|
42
|
+
}, [rest.value, rest.defaultValue]);
|
43
|
+
|
44
|
+
return (
|
45
|
+
<div className="grid gap-2 w-fit">
|
46
|
+
{(label || description) && (
|
47
|
+
<div className="flex items-center">
|
48
|
+
{label && (
|
49
|
+
<span
|
50
|
+
className={`text-sm select-none ${
|
51
|
+
rest.required &&
|
52
|
+
"after:content-['*'] after:ml-1 after:text-danger"
|
53
|
+
}`}
|
54
|
+
>
|
55
|
+
{label}
|
56
|
+
</span>
|
57
|
+
)}
|
58
|
+
{description && (
|
59
|
+
<span
|
60
|
+
title={description}
|
61
|
+
className="ms-auto text-sm text-primary-dark"
|
62
|
+
>
|
63
|
+
<Icon icon="octicon:info-16" />
|
64
|
+
</span>
|
65
|
+
)}
|
66
|
+
</div>
|
67
|
+
)}
|
68
|
+
<div className="relative">
|
69
|
+
<div className="flex items-center gap-2">
|
70
|
+
{Array.from({
|
71
|
+
length: 5,
|
72
|
+
}).map((_, index) => {
|
73
|
+
return (
|
74
|
+
<button
|
75
|
+
key={index}
|
76
|
+
type="button"
|
77
|
+
disabled={rest.disabled}
|
78
|
+
onClick={() => {
|
79
|
+
if (tempValue !== (index + 1).toString()) {
|
80
|
+
setTempValue((index + 1).toString());
|
81
|
+
|
82
|
+
if (rest.onChange) {
|
83
|
+
rest.onChange({
|
84
|
+
target: {
|
85
|
+
value: (index + 1).toString(),
|
86
|
+
} as HTMLSelectElement,
|
87
|
+
} as any);
|
88
|
+
}
|
89
|
+
} else {
|
90
|
+
setTempValue("");
|
91
|
+
|
92
|
+
if (rest.onChange) {
|
93
|
+
rest.onChange({
|
94
|
+
target: { value: "" } as HTMLSelectElement,
|
95
|
+
} as any);
|
96
|
+
}
|
97
|
+
}
|
98
|
+
}}
|
99
|
+
className={`duration-300 ease-in-out ${starHeight} ${
|
100
|
+
rest.disabled ? "text-slate-400" : "text-warning"
|
101
|
+
}`}
|
102
|
+
>
|
103
|
+
<Icon
|
104
|
+
icon={`fluent:star-12-${
|
105
|
+
parseInt(tempValue) >= index + 1 ? "filled" : "regular"
|
106
|
+
}`}
|
107
|
+
/>
|
108
|
+
</button>
|
109
|
+
);
|
110
|
+
})}
|
111
|
+
</div>
|
112
|
+
<input
|
113
|
+
type="text"
|
114
|
+
className={`absolute top-0 w-full border-0 bg-transparent text-transparent caret-transparent pointer-events-none focus:ring-0 ${height}`}
|
115
|
+
value={tempValue}
|
116
|
+
required={rest.required}
|
117
|
+
/>
|
118
|
+
</div>
|
119
|
+
</div>
|
120
|
+
);
|
121
|
+
};
|