@yannickbaze/star-rating 1.0.0
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/LICENSE +21 -0
- package/README.md +129 -0
- package/index.js +3 -0
- package/package.json +31 -0
- package/src/StarRating.js +190 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Yannick Baze
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# ⭐ Star Rating React Component
|
|
2
|
+
|
|
3
|
+
A lightweight, customizable, and reusable star rating component for React applications.
|
|
4
|
+
|
|
5
|
+
Perfect for product reviews, feedback systems, and user ratings.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## ✨ Features
|
|
10
|
+
|
|
11
|
+
* ⭐ Interactive star rating UI
|
|
12
|
+
* 🎨 Custom colors and sizes
|
|
13
|
+
* 🖱️ Hover preview before selecting
|
|
14
|
+
* 💬 Optional rating messages
|
|
15
|
+
* ⚡ Lightweight and easy to use
|
|
16
|
+
* ♻️ Fully reusable component
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## 📦 Installation
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install star-rating-react-component
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
or
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
yarn add star-rating-react-component
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## 🚀 Usage
|
|
35
|
+
|
|
36
|
+
```jsx
|
|
37
|
+
import StarRating from "star-rating-react-component";
|
|
38
|
+
|
|
39
|
+
function App() {
|
|
40
|
+
return (
|
|
41
|
+
<StarRating
|
|
42
|
+
maxRating={5}
|
|
43
|
+
messages={["Bad", "Okay", "Good", "Very Good", "Excellent"]}
|
|
44
|
+
onSetRating={(rating) => console.log(rating)}
|
|
45
|
+
/>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export default App;
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## ⚙️ Props Default Values
|
|
55
|
+
|
|
56
|
+
`maxRating: 5 (number)`
|
|
57
|
+
`defaultRating: 0 (number)`
|
|
58
|
+
`color: #fcc419 (string)`
|
|
59
|
+
`size: 30 (number)`
|
|
60
|
+
`messages: 5 ([])`
|
|
61
|
+
`className: - (string)`
|
|
62
|
+
`onSetRating: 5 (function, callback when rating is selected)`
|
|
63
|
+
|
|
64
|
+
| Prop | Type | Default | Description |
|
|
65
|
+
| --------------- | -------- | --------- | -------------------------------- |
|
|
66
|
+
| `maxRating` | number | `5` | Total number of stars |
|
|
67
|
+
| `defaultRating` | number | `0` | Initial rating value |
|
|
68
|
+
| `color` | string | `#fcc419` | Star color |
|
|
69
|
+
| `size` | number | `30` | Star size in pixels |
|
|
70
|
+
| `messages` | string[] | `[]` | Text shown for each rating |
|
|
71
|
+
| `className` | string | — | Custom CSS class |
|
|
72
|
+
| `onSetRating` | function | — | Callback when rating is selected |
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## 🎨 Customization Example
|
|
77
|
+
|
|
78
|
+
```jsx
|
|
79
|
+
<StarRating
|
|
80
|
+
maxRating={10}
|
|
81
|
+
size={40}
|
|
82
|
+
color="tomato"
|
|
83
|
+
messages={[
|
|
84
|
+
"Terrible",
|
|
85
|
+
"Bad",
|
|
86
|
+
"Okay",
|
|
87
|
+
"Good",
|
|
88
|
+
"Great",
|
|
89
|
+
"Excellent",
|
|
90
|
+
"Amazing",
|
|
91
|
+
"Superb",
|
|
92
|
+
"Outstanding",
|
|
93
|
+
"Perfect",
|
|
94
|
+
]}
|
|
95
|
+
/>
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## 🧠 How It Works
|
|
101
|
+
|
|
102
|
+
* Hover over stars to preview rating
|
|
103
|
+
* Click to select a rating
|
|
104
|
+
* Optional messages update dynamically
|
|
105
|
+
* Callback returns selected value
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## 🛠️ Example With Callback
|
|
110
|
+
|
|
111
|
+
```jsx
|
|
112
|
+
<StarRating
|
|
113
|
+
onSetRating={(rating) => alert(`You rated: ${rating}`)}
|
|
114
|
+
/>
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## 📄 License
|
|
120
|
+
|
|
121
|
+
MIT © 2026
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## 🤝 Contributing
|
|
126
|
+
|
|
127
|
+
Contributions, issues, and feature requests are welcome!
|
|
128
|
+
|
|
129
|
+
If you like this project, give it a ⭐ on GitHub.
|
package/index.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@yannickbaze/star-rating",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Reusable star rating component for React",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"files": [
|
|
7
|
+
"src",
|
|
8
|
+
"index.js",
|
|
9
|
+
"README.md"
|
|
10
|
+
],
|
|
11
|
+
"keywords": [
|
|
12
|
+
"react",
|
|
13
|
+
"star-rating",
|
|
14
|
+
"rating-component",
|
|
15
|
+
"ui",
|
|
16
|
+
"react-component"
|
|
17
|
+
],
|
|
18
|
+
"author": "Yannick Baze",
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"peerDependencies": {
|
|
21
|
+
"react": "^18.0.0"
|
|
22
|
+
},
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "https://github.com/yannickbaze/star-rating.git"
|
|
26
|
+
},
|
|
27
|
+
"bugs": {
|
|
28
|
+
"url": "https://github.com/yannickbaze/star-rating/issues"
|
|
29
|
+
},
|
|
30
|
+
"homepage": "https://github.com/yannickbaze/star-rating#readme"
|
|
31
|
+
}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
import PropTypes from "prop-types";
|
|
3
|
+
|
|
4
|
+
const container = {
|
|
5
|
+
display: "flex",
|
|
6
|
+
alignItems: "center",
|
|
7
|
+
gap: "16px"
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const starContainerStyle = {
|
|
11
|
+
display: "flex",
|
|
12
|
+
gap: "4px"
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
StarRating.protoTypes = {
|
|
17
|
+
maxRating: PropTypes.number,
|
|
18
|
+
defaultRating: PropTypes.number,
|
|
19
|
+
color: PropTypes.string,
|
|
20
|
+
size: PropTypes.number,
|
|
21
|
+
messages: PropTypes.array,
|
|
22
|
+
className: PropTypes.string,
|
|
23
|
+
onSetRating: PropTypes.func,
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
export default function StarRating({
|
|
28
|
+
maxRating = 5,
|
|
29
|
+
color = "#fcc419",
|
|
30
|
+
size = 30,
|
|
31
|
+
className,
|
|
32
|
+
messages = [],
|
|
33
|
+
defaultRating = 0,
|
|
34
|
+
onSetRating,
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
{
|
|
38
|
+
const [rating, setRating] = useState(defaultRating);
|
|
39
|
+
const [tempRating, setTempRating] = useState(0);
|
|
40
|
+
|
|
41
|
+
function handleRating(rating)
|
|
42
|
+
{
|
|
43
|
+
setRating(rating)
|
|
44
|
+
if (onSetRating) onSetRating(rating)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const textStyle = {
|
|
48
|
+
lineHeight: "1",
|
|
49
|
+
margin: "0",
|
|
50
|
+
color,
|
|
51
|
+
fontSize: `${size / 1.5}px`,
|
|
52
|
+
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
return (
|
|
57
|
+
<div style={container} className={ className }>
|
|
58
|
+
<div style={starContainerStyle}>
|
|
59
|
+
{Array.from({ length: maxRating }, (_, i) => (
|
|
60
|
+
<Star
|
|
61
|
+
key={i}
|
|
62
|
+
onRate={() => handleRating(i + 1)}
|
|
63
|
+
full={tempRating ? tempRating >= i + 1 : rating >= i + 1}
|
|
64
|
+
onHoverIn={() => setTempRating(i + 1)}
|
|
65
|
+
onHoverOut={() => setTempRating(0)}
|
|
66
|
+
color={color}
|
|
67
|
+
size={size}
|
|
68
|
+
/>
|
|
69
|
+
))}
|
|
70
|
+
</div>
|
|
71
|
+
<p style={textStyle}>
|
|
72
|
+
{messages.length === maxRating ?
|
|
73
|
+
messages[tempRating ? tempRating - 1 : rating - 1] : tempRating || rating || ""}</p>
|
|
74
|
+
</div>
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
function Star({ onRate, full, onHoverIn, onHoverOut, color, size })
|
|
81
|
+
{
|
|
82
|
+
const starStyle = {
|
|
83
|
+
width: `${size}px`,
|
|
84
|
+
height: `${size}px`,
|
|
85
|
+
display: "block",
|
|
86
|
+
cursor: "pointer"
|
|
87
|
+
};
|
|
88
|
+
return (
|
|
89
|
+
<span
|
|
90
|
+
style={starStyle}
|
|
91
|
+
onClick={onRate}
|
|
92
|
+
onMouseEnter={onHoverIn}
|
|
93
|
+
onMouseLeave={onHoverOut}>
|
|
94
|
+
{full ? (
|
|
95
|
+
<svg
|
|
96
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
97
|
+
viewBox="0 0 20 20"
|
|
98
|
+
fill={color}
|
|
99
|
+
stroke={color}>
|
|
100
|
+
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" />
|
|
101
|
+
</svg>
|
|
102
|
+
) : (
|
|
103
|
+
<svg
|
|
104
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
105
|
+
fill="none"
|
|
106
|
+
viewBox="0 0 24 24"
|
|
107
|
+
stroke={ color }>
|
|
108
|
+
<path
|
|
109
|
+
strokeLinecap="round"
|
|
110
|
+
strokeLinejoin="round"
|
|
111
|
+
strokeWidth={2}
|
|
112
|
+
d="M11.049 2.927c.3-.921 1.603-.921 1.902 0l1.519 4.674a1 1 0 00.95.69h4.915c.969 0 1.371 1.24.588 1.81l-3.976 2.888a1 1 0 00-.363 1.118l1.518 4.674c.3.922-.755 1.688-1.538 1.118l-3.976-2.888a1 1 0 00-1.176 0l-3.976 2.888c-.783.57-1.838-.197-1.538-1.118l1.518-4.674a1 1 0 00-.363-1.118l-3.976-2.888c-.784-.57-.38-1.81.588-1.81h4.914a1 1 0 00.951-.69l1.519-4.674z"
|
|
113
|
+
/>
|
|
114
|
+
</svg>
|
|
115
|
+
)}
|
|
116
|
+
</span>
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
/*
|
|
122
|
+
FULL STAR
|
|
123
|
+
|
|
124
|
+
<svg
|
|
125
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
126
|
+
viewBox="0 0 20 20"
|
|
127
|
+
fill="#000"
|
|
128
|
+
stroke="#000"
|
|
129
|
+
>
|
|
130
|
+
<path
|
|
131
|
+
d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"
|
|
132
|
+
/>
|
|
133
|
+
</svg>
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
EMPTY STAR
|
|
137
|
+
|
|
138
|
+
<svg
|
|
139
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
140
|
+
fill="none"
|
|
141
|
+
viewBox="0 0 24 24"
|
|
142
|
+
stroke="#000"
|
|
143
|
+
>
|
|
144
|
+
<path
|
|
145
|
+
strokeLinecap="round"
|
|
146
|
+
strokeLinejoin="round"
|
|
147
|
+
strokeWidth="{2}"
|
|
148
|
+
d="M11.049 2.927c.3-.921 1.603-.921 1.902 0l1.519 4.674a1 1 0 00.95.69h4.915c.969 0 1.371 1.24.588 1.81l-3.976 2.888a1 1 0 00-.363 1.118l1.518 4.674c.3.922-.755 1.688-1.538 1.118l-3.976-2.888a1 1 0 00-1.176 0l-3.976 2.888c-.783.57-1.838-.197-1.538-1.118l1.518-4.674a1 1 0 00-.363-1.118l-3.976-2.888c-.784-.57-.38-1.81.588-1.81h4.914a1 1 0 00.951-.69l1.519-4.674z"
|
|
149
|
+
/>
|
|
150
|
+
</svg>
|
|
151
|
+
|
|
152
|
+
*/
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
|