├── .gitignore
├── .npmignore
├── .prettierrc
├── .storybook
├── main.js
└── preview.js
├── CHANGELOG.md
├── LICENSE
├── README.md
├── package.json
├── rollup.config.js
├── screenshot.gif
├── src
├── components
│ ├── Rating.tsx
│ └── StarIcon.tsx
├── index.tsx
├── react-app-env.d.ts
├── reducer.ts
├── stories
│ ├── Changelog.stories.mdx
│ ├── Introduction.stories.mdx
│ └── Rating.stories.tsx
└── style.module.css
├── tsconfig.json
└── yarn.lock
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # See https://help.github.com/ignore-files/ for more about ignoring files.
3 |
4 | # dependencies
5 | node_modules
6 | example/node_modules
7 |
8 | # builds
9 | build
10 | storybook-static
11 | dist
12 |
13 | # misc
14 | .DS_Store
15 | .env
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 | .vercel
25 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | src
2 | example
3 | .storybook
4 | .vercel
5 | .eslintignore
6 | .eslintrc.js
7 | .prettierrc
8 | tsconfig.json
9 | rollup.*
10 | storybook-static
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "jsxSingleQuote": true,
4 | "semi": false,
5 | "printWidth": 120,
6 | "tabWidth": 2,
7 | "bracketSpacing": true,
8 | "jsxBracketSameLine": false,
9 | "arrowParens": "always",
10 | "trailingComma": "none"
11 | }
--------------------------------------------------------------------------------
/.storybook/main.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'],
3 | addons: [
4 | '@storybook/addon-links',
5 | '@storybook/addon-essentials',
6 | '@storybook/addon-interactions',
7 | '@storybook/preset-create-react-app',
8 | {
9 | name: '@storybook/addon-docs',
10 | options: { transcludeMarkdown: true }
11 | }
12 | ],
13 | framework: '@storybook/react',
14 | core: {
15 | builder: '@storybook/builder-webpack5',
16 | disableTelemetry: true
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/.storybook/preview.js:
--------------------------------------------------------------------------------
1 | export const parameters = {
2 | options: {
3 | storySort: {
4 | order: ['Introduction', 'Changelog']
5 | }
6 | },
7 | actions: { argTypesRegex: '^on[A-Z].*' },
8 | controls: {
9 | matchers: {
10 | color: /(background|color)$/i,
11 | date: /Date$/
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to this project will be documented in this file.
4 |
5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7 |
8 | Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
9 |
10 | ## [v5.1.7](https://github.com/awran5/react-simple-star-rating/compare/v5.1.7...v5.1.7)
11 |
12 | ## [v5.1.7](https://github.com/awran5/react-simple-star-rating/compare/v5.1.6...v5.1.7) - 2022-11-22
13 |
14 | ### Commits
15 |
16 | - fix: incorrent value when use even icons [#32](https://github.com/awran5/react-simple-star-rating/issues/32)
17 | - feat: new `allowTitleTag` prop to disable HTML title tag
18 | - build: safe upgrade [`de3584d`](https://github.com/awran5/react-simple-star-rating/commit/de3584dd80fa54ef67e2b98f00844ccd8edea44d)
19 | - build: remove deprecated standard-version [`1b108bf`](https://github.com/awran5/react-simple-star-rating/commit/1b108bf05568f65c843168f835b865a7e41134e6)
20 | - docs: add `preset-create-react-app` [`3c108ec`](https://github.com/awran5/react-simple-star-rating/commit/3c108ecd423682482bbbed4b31630376a99d0a8b)
21 |
22 | ## [v5.1.6](https://github.com/awran5/react-simple-star-rating/compare/v5.1.5...v5.1.6) - 2022-10-28
23 |
24 | ### Commits
25 |
26 | - chore(release): 5.1.6 [`c763647`](https://github.com/awran5/react-simple-star-rating/commit/c7636471266799c45a23dec253b4b89bb64fe5d9)
27 | - docs: correct spelling of CHANGELOG [`fbe5fcc`](https://github.com/awran5/react-simple-star-rating/commit/fbe5fcc863f110f488a3c730b00cde6dbd80c922)
28 |
29 | ## [v5.1.5](https://github.com/awran5/react-simple-star-rating/compare/v5.1.4...v5.1.5) - 2022-10-28
30 |
31 | ### Commits
32 |
33 | - chore(release): 5.1.5 [`c786973`](https://github.com/awran5/react-simple-star-rating/commit/c786973fcfb60bce9e2cb5029e0824a5569cbf77)
34 |
35 | ## [v5.1.4](https://github.com/awran5/react-simple-star-rating/compare/v5.1.3...v5.1.4) - 2022-10-28
36 |
37 | ### Commits
38 |
39 | - build: update storybook [`5c133e7`](https://github.com/awran5/react-simple-star-rating/commit/5c133e73daa96bfb25d558d4547332c827af43cb)
40 | - docs: update docs [`203fa74`](https://github.com/awran5/react-simple-star-rating/commit/203fa740f89dcf5dd7cbcbdf10979e68280072c2)
41 | - fix: option to reset rating #31 [`37882b2`](https://github.com/awran5/react-simple-star-rating/commit/37882b2cecbaabd199e33324af394ce5233beabf)
42 |
43 | ## [v5.1.3](https://github.com/awran5/react-simple-star-rating/compare/v5.1.2...v5.1.3) - 2022-10-11
44 |
45 | ### Fixed
46 |
47 | - fix: window is not defined error while using Next.js [`#28`](https://github.com/awran5/react-simple-star-rating/issues/28)
48 |
49 | ### Commits
50 |
51 | - build: update dependencies [`861a357`](https://github.com/awran5/react-simple-star-rating/commit/861a357a6c6ac4227d7373af437b7bb3ba8d2153)
52 | - chore(release): 5.1.3 [`4c34a26`](https://github.com/awran5/react-simple-star-rating/commit/4c34a263ace89a3b44e6a66287247f76e357a4e2)
53 | - fix: window is undefined" and "navigator is undefined" when using in Next.js [`abb3c5b`](https://github.com/awran5/react-simple-star-rating/commit/abb3c5bcf566bee4ec07dfdab350fac93182b43b)
54 |
55 | ## [v5.1.2](https://github.com/awran5/react-simple-star-rating/compare/v5.1.1...v5.1.2) - 2022-10-07
56 |
57 | ### Commits
58 |
59 | - chore(release): 5.1.2 [`ec47c2c`](https://github.com/awran5/react-simple-star-rating/commit/ec47c2c3354c1441cf12b6391d9b6f2b1b900788)
60 |
61 | ## [v5.1.1](https://github.com/awran5/react-simple-star-rating/compare/v5.1.0...v5.1.1) - 2022-10-07
62 |
63 | ### Merged
64 |
65 | - resolve next js window and navigator undefined issue [`#27`](https://github.com/awran5/react-simple-star-rating/pull/27)
66 |
67 | ## [v5.1.0](https://github.com/awran5/react-simple-star-rating/compare/v5.0.0...v5.1.0) - 2022-10-03
68 |
69 | ### Commits
70 |
71 | - chore(release): 5.1.0 [`667a628`](https://github.com/awran5/react-simple-star-rating/commit/667a628c3703d94390a6bd46479b029105142143)
72 | - fix: remove unnecessary css [`962c126`](https://github.com/awran5/react-simple-star-rating/commit/962c1267c9c41cfd5652e0362c7dcb25a47ff1de)
73 |
74 | ## [v5.0.0](https://github.com/awran5/react-simple-star-rating/compare/v4.1.1...v5.0.0) - 2022-10-03
75 |
76 | ### Commits
77 |
78 | - chore(release): 5.0.0 [`b1d6f2d`](https://github.com/awran5/react-simple-star-rating/commit/b1d6f2d44ecf044c21e98d3cf3aab11f81373e9a)
79 |
80 | ## [v4.1.1](https://github.com/awran5/react-simple-star-rating/compare/v4.1.0...v4.1.1) - 2022-10-03
81 |
82 | ### Commits
83 |
84 | - doc: v4.1.0 [`4eef0f2`](https://github.com/awran5/react-simple-star-rating/commit/4eef0f2b409d12401280b81d838a8748e3092d0a)
85 | - build: add vercel script [`2e501c3`](https://github.com/awran5/react-simple-star-rating/commit/2e501c36e7cfa36743216f6ed6f77d1c6bbfe200)
86 |
87 | ## [v4.1.0](https://github.com/awran5/react-simple-star-rating/compare/v4.0.5...v4.1.0) - 2022-10-03
88 |
89 | ### Merged
90 |
91 | - feat: add allowHoverOnDefault prop & update docs [`#19`](https://github.com/awran5/react-simple-star-rating/pull/19)
92 | - fix: issue #10 [`#16`](https://github.com/awran5/react-simple-star-rating/pull/16)
93 | - fix: adds default styling for starsvg [`#14`](https://github.com/awran5/react-simple-star-rating/pull/14)
94 | - Export Types Again (This was removed in V4) [`#8`](https://github.com/awran5/react-simple-star-rating/pull/8)
95 |
96 | ### Commits
97 |
98 | - build: update dependencies [`8241eed`](https://github.com/awran5/react-simple-star-rating/commit/8241eede17b08730f5542bb946c188fdcf4e6eb2)
99 | - feat: add storybook build [`4ddc939`](https://github.com/awran5/react-simple-star-rating/commit/4ddc939ab7dcb962c24e98d5676d18d740990bd5)
100 | - feat: add storybook [`adc8285`](https://github.com/awran5/react-simple-star-rating/commit/adc8285f752df41ffe5c1a4a601decdc14a6b70b)
101 |
102 | ## [v4.0.5](https://github.com/awran5/react-simple-star-rating/compare/v4.0.4...v4.0.5) - 2021-12-13
103 |
104 | ### Commits
105 |
106 | - docs: update docs [`d324033`](https://github.com/awran5/react-simple-star-rating/commit/d324033f49ee3ee4ae0fdcf37b329212348ab12a)
107 | - chore(release): 4.0.5 [`82d2cdd`](https://github.com/awran5/react-simple-star-rating/commit/82d2cddd871376ae2bcd1f19eb1708ba24f04015)
108 |
109 | ## [v4.0.4](https://github.com/awran5/react-simple-star-rating/compare/v4.0.3...v4.0.4) - 2021-12-13
110 |
111 | ### Commits
112 |
113 | - fix: handle value issue #7 [`b28b534`](https://github.com/awran5/react-simple-star-rating/commit/b28b534ce6a55bf18ff38817f1bd59610769eb4b)
114 | - add reset example [`7e8c5f2`](https://github.com/awran5/react-simple-star-rating/commit/7e8c5f2e26b08173323c9179628855e9850b8fd8)
115 | - chore(release): 4.0.4 [`548257c`](https://github.com/awran5/react-simple-star-rating/commit/548257c71e90c62af77e61788db52a442e5a5ddb)
116 |
117 | ## [v4.0.3](https://github.com/awran5/react-simple-star-rating/compare/v4.0.2...v4.0.3) - 2021-12-11
118 |
119 | ### Commits
120 |
121 | - fix: click on touch devices [`cee11c2`](https://github.com/awran5/react-simple-star-rating/commit/cee11c2e7fa2e23d872395fbaa1dc9f527aa4591)
122 | - chore(release): 4.0.3 [`883a497`](https://github.com/awran5/react-simple-star-rating/commit/883a4973597f01443c7b19b3e461c98ba54a9f4f)
123 |
124 | ## [v4.0.2](https://github.com/awran5/react-simple-star-rating/compare/v4.0.0...v4.0.2) - 2021-12-10
125 |
126 | ### Fixed
127 |
128 | - fix: fix #6 not working on mobile browsers [`#6`](https://github.com/awran5/react-simple-star-rating/issues/6) [`#6`](https://github.com/awran5/react-simple-star-rating/issues/6)
129 |
130 | ### Commits
131 |
132 | - switch to standard-version [`1114086`](https://github.com/awran5/react-simple-star-rating/commit/11140866efa22b39079104b500236d507adc9121)
133 | - fix(responsive issue): add missing CSS to fix responsive [`5e20f1e`](https://github.com/awran5/react-simple-star-rating/commit/5e20f1e78ea1480620b9ffc0303a3f646dfe3bcf)
134 | - docs: log changes [`2d1d6e1`](https://github.com/awran5/react-simple-star-rating/commit/2d1d6e11654abd2bdc087b9f4da2328f31977381)
135 |
136 | ## [v4.0.0](https://github.com/awran5/react-simple-star-rating/compare/v3.0.0...v4.0.0) - 2021-11-28
137 |
138 | ### Commits
139 |
140 | - docs: add: more demos and examples [`4ae2ed6`](https://github.com/awran5/react-simple-star-rating/commit/4ae2ed64e110e8848fb4b3fc50619c33745e8e65)
141 | - update [`00c657e`](https://github.com/awran5/react-simple-star-rating/commit/00c657e2f2d963782e181ca02f9a98208c3756b4)
142 | - chore: update dependencies [`9521d14`](https://github.com/awran5/react-simple-star-rating/commit/9521d148d542d0d9e36c4aec4355f5a32577a95d)
143 |
144 | ## [v3.0.0](https://github.com/awran5/react-simple-star-rating/compare/v2.1.0...v3.0.0) - 2021-07-06
145 |
146 | ### Commits
147 |
148 | - build: github actions [`cef37e9`](https://github.com/awran5/react-simple-star-rating/commit/cef37e9ce0ef6acc2a62eb555ed1d20df6b54da9)
149 |
150 | ## [v2.1.0](https://github.com/awran5/react-simple-star-rating/compare/v2.0.0...v2.1.0) - 2021-07-06
151 |
152 | ### Commits
153 |
154 | - feat: moved to semantic-release [`8ff381d`](https://github.com/awran5/react-simple-star-rating/commit/8ff381dfce92cf816821e296046bc5533f982d8c)
155 | - fix(github action setup): edit release.yml to setup github action [`ea0e87d`](https://github.com/awran5/react-simple-star-rating/commit/ea0e87dda5212360bfc87b17b79fef4f99cab28a)
156 | - edit readme [`dcb75a6`](https://github.com/awran5/react-simple-star-rating/commit/dcb75a6d6dfd943ecdf4cdfada6acab3f540c6aa)
157 |
158 | ## v2.0.0 - 2021-07-05
159 |
160 | ### Merged
161 |
162 | - Version Packages [`#4`](https://github.com/awran5/react-simple-star-rating/pull/4)
163 |
164 | ### Commits
165 |
166 | - first release [`1364dd0`](https://github.com/awran5/react-simple-star-rating/commit/1364dd022d31c101f0b145ca3bc17e899bddc312)
167 | - v2 release [`923df0d`](https://github.com/awran5/react-simple-star-rating/commit/923df0d69447bd2331478b33bcb28db42532a8fa)
168 | - icon size fixed [`4ec1bce`](https://github.com/awran5/react-simple-star-rating/commit/4ec1bce1e452a5e0e37b74bf277ec03103377dc1)
169 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2021-present awran5
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.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # React Simple Rating
2 |
3 | > A simple react component for adding a star rating to your project.
4 |
5 | [](https://www.npmjs.com/package/react-simple-star-rating) [](https://standardjs.com)
6 |
7 |
8 |
9 |
10 |
11 | ## Install
12 |
13 | #### npm
14 |
15 | ```sh
16 | npm i react-simple-star-rating
17 | ```
18 |
19 | #### Yarn
20 |
21 | ```sh
22 | yarn add react-simple-star-rating
23 | ```
24 |
25 |
26 |
27 | ## Usage
28 |
29 | ```jsx
30 | import React, { useState } from 'react'
31 | import { Rating } from 'react-simple-star-rating'
32 |
33 | export function MyComponent() {
34 | const [rating, setRating] = useState(0)
35 |
36 | // Catch Rating value
37 | const handleRating = (rate: number) => {
38 | setRating(rate)
39 |
40 | // other logic
41 | }
42 | // Optinal callback functions
43 | const onPointerEnter = () => console.log('Enter')
44 | const onPointerLeave = () => console.log('Leave')
45 | const onPointerMove = (value: number, index: number) => console.log(value, index)
46 |
47 | return (
48 |
49 |
56 |
57 | )
58 | }
59 | ```
60 |
61 | ## Reset Rating Value
62 |
63 | ```jsx
64 | import React, { useState } from 'react'
65 | import { Rating } from 'react-simple-star-rating'
66 |
67 | export function MyComponent() {
68 | const [rating, setRating] = useState(0)
69 |
70 | // Catch Rating value
71 | const handleRating = (rate: number) => {
72 | setRating(rate)
73 | }
74 |
75 | const handleReset = () => {
76 | // Set the initial value
77 | setRating(0)
78 | }
79 |
80 | return (
81 |
82 | {/* set initial value */}
83 |
84 |
85 |
86 |
87 | )
88 | }
89 | ```
90 |
91 | ### Available Props
92 |
93 | | Prop | Type | Options | Description | Default |
94 | | -------------------- | ---------------- | -------- | --------------------------------------------------------- | :------------------------: |
95 | | `onClick` | function | Optional | callback with `hover`, `index` and `event` values passed | `-` |
96 | | `onPointerMove` | function | Optional | callback with `hover`, `index` and `event` values passed | `-` |
97 | | `onPointerEnter` | function | Optional | callback with `event` passed | `-` |
98 | | `onPointerLeave` | function | Optional | callback with `event` passed | `-` |
99 | | `initialValue` | number | Optional | Set initial value | `0` |
100 | | `iconsCount` | number | Optional | Number of the icons | `5` |
101 | | `readonly` | boolean | Optional | Readonly mode | `false` |
102 | | `rtl` | boolean | Optional | RTL mode | `false` |
103 | | `transition` | boolean | Optional | Adds a smooth transition effect on mouse hover | `false` |
104 | | `allowFraction` | boolean | Optional | Enable a fractional icon (half icon) | `false` |
105 | | `className` | string | Optional | Applied to the `main` span | `react-simple-star-rating` |
106 | | `style` | CSSProperties | Optional | Inline style applied to the `main` span | `basic style` |
107 | | `size` | number | Optional | SVG Icon width / height in `px` | `25` |
108 | | `SVGstrokeColor` | string | Optional | SVG Icon stroke color | `currentColor` |
109 | | `SVGstorkeWidth` | string \| number | Optional | SVG Icon storke width | `0` |
110 | | `SVGclassName` | string | Optional | SVG Icon css class | `star-svg` |
111 | | `SVGstyle` | CSSProperties | Optional | SVG inline style | `-` |
112 | | `fillIcon` | ReactNode | Optional | Custom fill icon SVG | `null` |
113 | | `fillColor` | string | Optional | Fill icons color | `#f1a545` |
114 | | `fillColorArray` | array | Optional | Array of string to add color range | `[]` |
115 | | `fillStyle` | CSSProperties | Optional | Inline style applied to `filled` icon span | `basic style` |
116 | | `fillClassName` | string | Optional | Applied to the `filled` icon span | `filled-icons` |
117 | | `emptyIcon` | ReactNode | Optional | Custom empty icon SVG | `null` |
118 | | `emptyColor` | string | Optional | Empty icons color | `#cccccc` |
119 | | `emptyStyle` | CSSProperties | Optional | Inline style applied to `empty` icon span | `basic style` |
120 | | `emptyClassName` | string | Optional | Applied to the `empty` icon span | `empty-icons` |
121 | | `customIcons` | array of object | Optional | Add a group of icons | `[]` |
122 | | `allowHover` | boolean | Optional | Enable / Disable hover effect | `true` |
123 | | `disableFillHover` | boolean | Optional | Enable / Disable hover effect on filled stars | `false` |
124 | | `allowTitleTag` | boolean | Optional | Enable / Disable HTML`title` Tag | `true` |
125 | | `showTooltip` | boolean | Optional | Show a tooltip with live values | `false` |
126 | | `tooltipDefaultText` | string | Optional | Initial tooltip text if no rating value | `Your Rate` |
127 | | `tooltipArray` | array | Optional | Array of strings to show inside tooltip | `[]` |
128 | | `tooltipClassName` | string | Optional | Tooltip CSS class | `rating-tooltip` |
129 | | `tooltipStyle` | CSSProperties | Optional | Inline style applied to the `tooltip` span | `basic style` |
130 | | `titleSeparator` | string | Optional | Separator word in a title of a rating star `(1 out of 5)` | `out of` |
131 |
132 | ---
133 |
134 |
135 |
136 | ## BREAKING CHANGES: version [4.1.0](https://github.com/awran5/react-simple-star-rating/compare/v4.0.5...v4.1.0) (2022-10-03)
137 |
138 | | old | new | changes |
139 | | --------------- | --------------- | --------- |
140 | | `allowHalfIcon` | `allowFraction` | `Renamed` |
141 | | `fullIcon` | `fillIcon` | `Renamed` |
142 | | `fullStyle` | `fillStyle` | `Renamed` |
143 | | `fullClassName` | `fillClassName` | `Renamed` |
144 | | `ratingValue` | `-` | `Removed` |
145 |
146 | ## Demos
147 |
148 | See all demos and usage examples [in action](https://react-simple-star-rating.vercel.app/).
149 |
150 |
151 |
152 | [](https://codesandbox.io/s/react-simple-rating-ts-fzmpu?fontsize=14&hidenavigation=1&theme=dark)
153 |
154 | ### License
155 |
156 | MIT © [awran5](https://github.com/awran5/)
157 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-simple-star-rating",
3 | "version": "5.1.7",
4 | "private": false,
5 | "description": "A simple react component for adding a star rating to your project.",
6 | "author": {
7 | "name": "awran5",
8 | "email": "awran5@yahoo.com"
9 | },
10 | "license": "MIT",
11 | "repository": {
12 | "type": "git",
13 | "url": "https://github.com/awran5/react-simple-star-rating.git"
14 | },
15 | "bugs": {
16 | "url": "https://github.com/awran5/react-simple-star-rating/issues"
17 | },
18 | "homepage": "https://github.com/awran5/react-simple-star-rating#readme",
19 | "main": "dist/index.js",
20 | "source": "src/index.tsx",
21 | "engines": {
22 | "node": ">=14"
23 | },
24 | "scripts": {
25 | "clean": "rm -rf dist",
26 | "start:rollup": "rollup -cw --exports auto",
27 | "build": "rollup -c --exports auto",
28 | "log": "auto-changelog -p --template keepachangelog && git add CHANGELOG.md",
29 | "start": "start-storybook -p 6006",
30 | "build-storybook": "build-storybook && vercel --prod"
31 | },
32 | "peerDependencies": {
33 | "react": ">=18.0.0",
34 | "react-dom": ">=18.0.0"
35 | },
36 | "devDependencies": {
37 | "@babel/core": "^7.19.1",
38 | "@rollup/plugin-commonjs": "^23.0.0",
39 | "@rollup/plugin-node-resolve": "^15.0.0",
40 | "@storybook/addon-actions": "^6.5.13",
41 | "@storybook/addon-docs": "^6.5.13",
42 | "@storybook/addon-essentials": "^6.5.13",
43 | "@storybook/addon-interactions": "^6.5.13",
44 | "@storybook/addon-links": "^6.5.13",
45 | "@storybook/builder-webpack5": "^6.5.13",
46 | "@storybook/manager-webpack5": "^6.5.13",
47 | "@storybook/preset-create-react-app": "^4.1.2",
48 | "@storybook/react": "^6.5.13",
49 | "@storybook/testing-library": "^0.0.13",
50 | "@types/react": "^18.0.21",
51 | "@types/react-dom": "^18.0.6",
52 | "auto-changelog": "^2.4.0",
53 | "autoprefixer": "^10.4.12",
54 | "babel-loader": "^8.2.5",
55 | "postcss": "^8.4.17",
56 | "prettier": "^2.7.1",
57 | "react": "^18.2.0",
58 | "react-dom": "^18.2.0",
59 | "react-icons": "^4.4.0",
60 | "react-scripts": "^5.0.1",
61 | "rollup": "^2.79.1",
62 | "rollup-plugin-peer-deps-external": "^2.2.4",
63 | "rollup-plugin-postcss": "^4.0.2",
64 | "rollup-plugin-terser": "^7.0.2",
65 | "rollup-plugin-typescript2": "^0.34.1",
66 | "typescript": "^4.8.3"
67 | },
68 | "files": [
69 | "dist"
70 | ],
71 | "publishConfig": {
72 | "access": "public"
73 | },
74 | "eslintConfig": {
75 | "extends": [
76 | "react-app"
77 | ]
78 | },
79 | "keywords": [
80 | "react",
81 | "star rating",
82 | "react component",
83 | "react rating"
84 | ],
85 | "tags": [
86 | "react",
87 | "star-rating",
88 | "react-component",
89 | "react-rating"
90 | ],
91 | "dependencies": {}
92 | }
93 |
--------------------------------------------------------------------------------
/rollup.config.js:
--------------------------------------------------------------------------------
1 | import typescript from "rollup-plugin-typescript2"
2 | import peerDepsExternal from "rollup-plugin-peer-deps-external"
3 | import resolve from "@rollup/plugin-node-resolve"
4 | import commonjs from "@rollup/plugin-commonjs"
5 | import postcss from "rollup-plugin-postcss"
6 | import autoprefixer from "autoprefixer"
7 | import { terser } from "rollup-plugin-terser"
8 | import packageJson from "./package.json"
9 |
10 | const config = {
11 | input: "src/index.tsx",
12 | plugins: [
13 | peerDepsExternal(),
14 | resolve(),
15 | commonjs(),
16 | typescript({
17 | exclude: ["src/stories/**"]
18 | }),
19 | postcss({
20 | modules: true,
21 | extract: false,
22 | minimize: true,
23 | plugins: [autoprefixer()]
24 | }),
25 | terser()
26 | ],
27 | output: {
28 | file: packageJson.main,
29 | format: "cjs",
30 | sourcemap: true
31 | }
32 | }
33 | export default config
34 |
--------------------------------------------------------------------------------
/screenshot.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awran5/react-simple-star-rating/87cce97df8f8177e1a4bcad8e375593b7be991ee/screenshot.gif
--------------------------------------------------------------------------------
/src/components/Rating.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | useMemo,
3 | useReducer,
4 | useCallback,
5 | Fragment,
6 | ReactNode,
7 | CSSProperties,
8 | MouseEvent,
9 | PointerEvent,
10 | useEffect
11 | } from 'react'
12 | import { StarIcon, StarIconProps } from './StarIcon'
13 | import { reducer } from '../reducer'
14 | import css from '../style.module.css'
15 |
16 | export interface RatingProps extends StarIconProps {
17 | /** Handles the returned rating value */
18 | onClick?: (value: number, index: number, event?: MouseEvent) => void
19 | /** onPointerMove callback function with `hover`, `index` alongside `event` values passed */
20 | onPointerMove?: (value: number, index: number, event: PointerEvent) => void
21 | /** onPointerEnter callback function */
22 | onPointerEnter?: (event: PointerEvent) => void
23 | /** onPointerLeave callback function */
24 | onPointerLeave?: (event: PointerEvent) => void
25 | /** Set initial value */
26 | initialValue?: number
27 | /** Number of the icons */
28 | iconsCount?: number
29 | /** Read only mode */
30 | readonly?: boolean
31 | /** Add a group of icons */
32 | customIcons?: {
33 | icon: ReactNode
34 | }[]
35 | /** RTL mode */
36 | rtl?: boolean
37 | /** Enable a fractional rate (half icon) */
38 | allowFraction?: boolean
39 | /** Enable / Disable hover effect on empty icons */
40 | allowHover?: boolean
41 | /** Enable / Disable hover effect on filled icons */
42 | disableFillHover?: boolean
43 | /** Enable / Disable transition effect on mouse hover */
44 | transition?: boolean
45 | /** Applied to the `main` span */
46 | className?: string
47 | /** Inline style applied to the `main` span */
48 | style?: CSSProperties
49 |
50 | /** Custom fill icon SVG */
51 | fillIcon?: ReactNode | null
52 | /** Filled icons color */
53 | fillColor?: string
54 | /** Array of string to add color range */
55 | fillColorArray?: string[]
56 | /** Inline style applied to `filled-icons` icon span */
57 | fillStyle?: CSSProperties
58 | /** Filled icons `span` className */
59 | fillClassName?: string
60 |
61 | /** Custom empty icon SVG */
62 | emptyIcon?: ReactNode | null
63 | /** Empty icons color */
64 | emptyColor?: string
65 | /** Inline style applied to `empty-icons` span */
66 | emptyStyle?: CSSProperties
67 | /** ٌُEmpty icons `span` className */
68 | emptyClassName?: string
69 |
70 | /** Enable / Disable HTML`title` Tag */
71 | allowTitleTag?: boolean
72 | /** Show a tooltip with live values */
73 | showTooltip?: boolean
74 | /** Initial tooltip text if there is no rating value */
75 | tooltipDefaultText?: string
76 | /** Array of strings that will show inside the tooltip */
77 | tooltipArray?: string[]
78 | /** Inline style applied to the `tooltip` span */
79 | tooltipStyle?: CSSProperties
80 | /** Tooltip CSS className */
81 | tooltipClassName?: string
82 | /** Separator word in a title of a rating star `(1 out of 5)` */
83 | titleSeparator?: string
84 | }
85 |
86 | /**
87 | * Check for touch devices
88 | * @returns `boolean`
89 | */
90 | function isTouchDevice() {
91 | return (
92 | (typeof window !== 'undefined' && window.matchMedia('(pointer: coarse)').matches) ||
93 | 'ontouchstart' in window ||
94 | (typeof navigator !== 'undefined' && navigator.maxTouchPoints > 0)
95 | )
96 | }
97 |
98 | export function Rating({
99 | onClick,
100 | onPointerMove,
101 | onPointerEnter,
102 | onPointerLeave,
103 | initialValue = 0,
104 | iconsCount = 5,
105 | size = 40,
106 | readonly = false,
107 | rtl = false,
108 | customIcons = [],
109 | allowFraction = false,
110 | style,
111 | className = 'react-simple-star-rating',
112 | transition = false,
113 |
114 | allowHover = true,
115 | disableFillHover = false,
116 |
117 | fillIcon = null,
118 | fillColor = '#ffbc0b',
119 | fillColorArray = [],
120 | fillStyle,
121 | fillClassName = 'filled-icons',
122 |
123 | emptyIcon = null,
124 | emptyColor = '#cccccc',
125 | emptyStyle,
126 | emptyClassName = 'empty-icons',
127 |
128 | allowTitleTag = true,
129 | showTooltip = false,
130 | tooltipDefaultText = 'Your Rate',
131 | tooltipArray = [],
132 | tooltipStyle,
133 | tooltipClassName = 'react-simple-star-rating-tooltip',
134 |
135 | SVGclassName = 'star-svg',
136 | titleSeparator = 'out of',
137 | SVGstyle,
138 | SVGstorkeWidth = 0,
139 | SVGstrokeColor = 'currentColor'
140 | }: RatingProps) {
141 | const [{ ratingValue, hoverValue, hoverIndex, valueIndex }, dispatch] = useReducer(reducer, {
142 | hoverIndex: 0,
143 | valueIndex: 0,
144 | ratingValue: initialValue,
145 | hoverValue: null
146 | })
147 |
148 | useEffect(() => {
149 | if (initialValue) dispatch({ type: 'MouseClick', payload: 0 })
150 | }, [initialValue])
151 |
152 | const totalIcons = useMemo(() => (allowFraction ? iconsCount * 2 : iconsCount), [allowFraction, iconsCount])
153 |
154 | // Convert local rating value to precentage
155 | const localRating = useMemo(() => {
156 | if (initialValue > totalIcons) return 0
157 |
158 | // Check for a decimal value
159 | if (!allowFraction && Math.floor(initialValue) !== initialValue) {
160 | return Math.ceil(initialValue) * 2 * 10
161 | }
162 |
163 | return Math.round((initialValue / iconsCount) * 100)
164 | }, [allowFraction, initialValue, iconsCount, totalIcons])
165 |
166 | const localRatingIndex = useMemo(() => (allowFraction ? initialValue * 2 - 1 : initialValue - 1) || 0, [
167 | allowFraction,
168 | initialValue
169 | ])
170 |
171 | const renderValue = useCallback(
172 | (value: number) => (iconsCount % 2 !== 0 ? value / 2 / 10 : (value * iconsCount) / 100),
173 | [iconsCount]
174 | )
175 |
176 | const handlePointerMove = (event: PointerEvent) => {
177 | const { clientX, currentTarget } = event
178 | // Get main span element position and width
179 | const { left, right, width } = currentTarget.children[0].getBoundingClientRect()
180 |
181 | // Handle RTL
182 | const positionX = rtl ? right - clientX : clientX - left
183 |
184 | // Get current pointer position while moves over the icons
185 | let currentValue = totalIcons
186 | const iconWidth = Math.round(width / totalIcons)
187 |
188 | for (let i = 0; i <= totalIcons; i = i + 1) {
189 | if (positionX <= iconWidth * i) {
190 | if (i === 0 && positionX < iconWidth) currentValue = 0
191 | else currentValue = i
192 | break
193 | }
194 | }
195 |
196 | const index = currentValue - 1
197 |
198 | if (currentValue > 0) {
199 | // Set value and index state
200 | dispatch({ type: 'PointerMove', payload: (currentValue * 100) / totalIcons, index })
201 |
202 | if (onPointerMove) {
203 | if (hoverValue) onPointerMove(renderValue(hoverValue), index, event)
204 | }
205 | }
206 | }
207 |
208 | const handlePointerEnter = (event: PointerEvent) => {
209 | if (onPointerEnter) onPointerEnter(event)
210 | // Enable only on touch devices
211 | if (!isTouchDevice()) return
212 |
213 | handlePointerMove(event)
214 | }
215 |
216 | const handleClick = (event?: MouseEvent) => {
217 | if (hoverValue) {
218 | dispatch({ type: 'MouseClick', payload: hoverValue })
219 | if (onClick) onClick(renderValue(hoverValue), hoverIndex, event)
220 | }
221 | }
222 |
223 | const handlePointerLeave = (event: PointerEvent) => {
224 | if (isTouchDevice()) handleClick()
225 |
226 | dispatch({ type: 'PointerLeave' })
227 | if (onPointerLeave) onPointerLeave(event)
228 | }
229 |
230 | const valuePercentage = useMemo(() => {
231 | if (allowHover) {
232 | if (disableFillHover) {
233 | const currentValue = (ratingValue && ratingValue) || localRating
234 | return hoverValue && hoverValue > currentValue ? hoverValue : currentValue
235 | }
236 | return (hoverValue && hoverValue) || (ratingValue && ratingValue) || localRating
237 | }
238 |
239 | return (ratingValue && ratingValue) || localRating
240 | }, [allowHover, disableFillHover, hoverValue, ratingValue, localRating])
241 |
242 | useEffect(() => {
243 | if (tooltipArray.length > totalIcons) {
244 | console.error('tooltipArray Array length is bigger then Icons Count length.')
245 | }
246 | }, [tooltipArray.length, totalIcons])
247 |
248 | const ratingArray = useCallback(
249 | (array: string[]) => {
250 | return (
251 | (hoverValue && array[hoverIndex]) ||
252 | (ratingValue && array[valueIndex]) ||
253 | (initialValue && array[localRatingIndex])
254 | )
255 | },
256 | [hoverValue, hoverIndex, ratingValue, valueIndex, initialValue, localRatingIndex]
257 | )
258 |
259 | const ratingRenderValues = useMemo(() => {
260 | return (
261 | (hoverValue && renderValue(hoverValue)) ||
262 | (ratingValue && renderValue(ratingValue)) ||
263 | (initialValue && renderValue(localRating))
264 | )
265 | }, [hoverValue, renderValue, ratingValue, initialValue, localRating])
266 |
267 | return (
268 |
269 |
281 |
288 | {[...Array(iconsCount)].map((_, index) => (
289 |
290 | {customIcons[index]?.icon || emptyIcon || (
291 |
298 | )}
299 |
300 | ))}
301 |
302 |
303 |
314 | {[...Array(iconsCount)].map((_, index) => (
315 |
316 | {customIcons[index]?.icon || fillIcon || (
317 |
324 | )}
325 |
326 | ))}
327 |
328 |
329 |
330 | {showTooltip && (
331 |
338 | {(tooltipArray.length > 0 ? ratingArray(tooltipArray) : ratingRenderValues) || tooltipDefaultText}
339 |
340 | )}
341 |
342 | )
343 | }
344 |
--------------------------------------------------------------------------------
/src/components/StarIcon.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | export interface StarIconProps {
4 | /** Icon width / height in `px` */
5 | size?: number
6 | SVGstrokeColor?: string
7 | SVGstorkeWidth?: string | number
8 | SVGclassName?: string
9 | SVGstyle?: React.CSSProperties
10 | }
11 |
12 | export function StarIcon({
13 | size = 25,
14 | SVGstrokeColor = 'currentColor',
15 | SVGstorkeWidth = 0,
16 | SVGclassName = 'star-svg',
17 | SVGstyle
18 | }: StarIconProps) {
19 | return (
20 |
33 | )
34 | }
35 |
--------------------------------------------------------------------------------
/src/index.tsx:
--------------------------------------------------------------------------------
1 | export * from './components/Rating'
2 |
--------------------------------------------------------------------------------
/src/react-app-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/src/reducer.ts:
--------------------------------------------------------------------------------
1 | type State = {
2 | ratingValue: number | null
3 | hoverValue: number | null
4 | hoverIndex: number
5 | valueIndex: number
6 | }
7 |
8 | type Action =
9 | | { type: 'PointerMove'; payload: number | null; index: number }
10 | | { type: 'PointerLeave' }
11 | | { type: 'MouseClick'; payload: number }
12 |
13 | export function reducer(state: State, action: Action): State {
14 | switch (action.type) {
15 | case 'PointerMove':
16 | return {
17 | ...state,
18 | hoverValue: action.payload,
19 | hoverIndex: action.index
20 | }
21 |
22 | case 'PointerLeave':
23 | return {
24 | ...state,
25 | ratingValue: state.ratingValue,
26 | hoverIndex: 0,
27 | hoverValue: null
28 | }
29 |
30 | case 'MouseClick':
31 | return {
32 | ...state,
33 | valueIndex: state.hoverIndex,
34 | ratingValue: action.payload
35 | }
36 |
37 | default:
38 | return state
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/stories/Changelog.stories.mdx:
--------------------------------------------------------------------------------
1 | import Changelog from '../../CHANGELOG.md'
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/stories/Introduction.stories.mdx:
--------------------------------------------------------------------------------
1 | import { Meta, ArgsTable } from '@storybook/addon-docs'
2 | import { FaGithub, FaCodepen } from 'react-icons/fa'
3 | import { Rating } from '../components/Rating'
4 |
5 |
6 |
7 |
102 |
103 | # React simple star rating
104 |
105 | A simple yet powerful react component for adding a nice rating icons to your project.
106 |
107 | [](https://www.npmjs.com/package/react-simple-star-rating) [](https://standardjs.com)
108 |
109 | ---
110 |
111 | ##### Install with npm
112 |
113 | ```sh
114 | npm i react-simple-star-rating
115 |
116 | ```
117 |
118 | ##### Yarn
119 |
120 | ```sh
121 | yarn add react-simple-star-rating
122 | ```
123 |
124 |
125 | Usage
126 |
127 |
128 | ```jsx
129 | import React, { useState } from 'react'
130 | import { Rating } from 'react-simple-star-rating'
131 |
132 | function App() {
133 | const [ratingValue, setRatingValue] = useState(0)
134 |
135 | const handleRating = (rate: number) => {
136 | setRatingValue(rate)
137 | }
138 | return (
139 |
142 | )
143 | ```
144 |
145 |
146 | Reset Rating Value
147 |
148 |
149 | ```jsx
150 | import React, { useState } from 'react'
151 | import { Rating } from 'react-simple-star-rating'
152 |
153 | function App() {
154 | const [ratingValue, setRatingValue] = useState(0)
155 |
156 | const handleRating = (rate: number) => {
157 | setRatingValue(rate)
158 | }
159 | const handleReset = () => {
160 | // Set the initial value
161 | setRating(0)
162 | }
163 | return (
164 | <>
165 | {/* set initial value */}
166 |
167 |
168 |
169 | >
170 | )
171 | ```
172 |
173 | #### Props
174 |
175 |
176 |
177 |
178 |
179 |
201 |
202 |
205 |
206 | ##### License MIT © [awran5](https://github.com/awran5/)
207 |
208 |
209 | TipEdit the Markdown in stories/Introduction.stories.mdx
210 |
211 |
--------------------------------------------------------------------------------
/src/stories/Rating.stories.tsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable @typescript-eslint/no-unused-vars */
2 | import { ComponentStory, ComponentMeta } from '@storybook/react'
3 | import { useState } from 'react'
4 | import {
5 | MdFavoriteBorder,
6 | MdFavorite,
7 | MdOutlineSentimentDissatisfied,
8 | MdOutlineSentimentNeutral,
9 | MdOutlineSentimentSatisfied,
10 | MdOutlineSentimentVeryDissatisfied,
11 | MdOutlineSentimentVerySatisfied
12 | } from 'react-icons/md'
13 |
14 | import { Rating } from '../components/Rating'
15 |
16 | export default {
17 | title: 'Example',
18 | component: Rating,
19 | argTypes: {}
20 | } as ComponentMeta
21 |
22 | const Template: ComponentStory = (args) => {
23 | const [rating, setRating] = useState(0)
24 | const handleClick = (value: number) => setRating(value)
25 |
26 | return (
27 |
34 |
35 |
36 | )
37 | }
38 |
39 | export const Default = Template.bind({})
40 | Default.args = {
41 | onPointerEnter: undefined,
42 | onPointerLeave: undefined,
43 | onPointerMove: undefined
44 | }
45 |
46 | export const TransitionEffect = Template.bind({})
47 | TransitionEffect.args = {
48 | transition: true,
49 | onPointerEnter: undefined,
50 | onPointerLeave: undefined,
51 | onPointerMove: undefined
52 | }
53 |
54 | export const InitialValue = Template.bind({})
55 | InitialValue.args = {
56 | initialValue: 3,
57 | transition: true,
58 | onPointerEnter: undefined,
59 | onPointerLeave: undefined,
60 | onPointerMove: undefined
61 | }
62 |
63 | export const ColorRange = Template.bind({})
64 | ColorRange.args = {
65 | transition: true,
66 | fillColorArray: ['#f14f45', '#f16c45', '#f18845', '#f1b345', '#f1d045'],
67 | onPointerEnter: undefined,
68 | onPointerLeave: undefined,
69 | onPointerMove: undefined
70 | }
71 |
72 | export const WithTooltip = Template.bind({})
73 | WithTooltip.args = {
74 | showTooltip: true,
75 | onPointerEnter: undefined,
76 | onPointerLeave: undefined,
77 | onPointerMove: undefined
78 | }
79 |
80 | export const CustomTooltip = Template.bind({})
81 | CustomTooltip.args = {
82 | showTooltip: true,
83 | tooltipArray: ['Terrible', 'Bad', 'Average', 'Great', 'Prefect'],
84 | onPointerEnter: undefined,
85 | onPointerLeave: undefined,
86 | onPointerMove: undefined
87 | }
88 |
89 | export const ReadOnlyMode = Template.bind({})
90 | ReadOnlyMode.args = {
91 | initialValue: 2,
92 | readonly: true,
93 | onPointerEnter: undefined,
94 | onPointerLeave: undefined,
95 | onPointerMove: undefined
96 | }
97 |
98 | export const FractionRate = Template.bind({})
99 | FractionRate.args = {
100 | allowFraction: true,
101 | transition: true,
102 | showTooltip: true,
103 | tooltipArray: [
104 | 'Terrible',
105 | 'Terrible+',
106 | 'Bad',
107 | 'Bad+',
108 | 'Average',
109 | 'Average+',
110 | 'Great',
111 | 'Great+',
112 | 'Awesome',
113 | 'Awesome+'
114 | ],
115 | onPointerEnter: undefined,
116 | onPointerLeave: undefined,
117 | onPointerMove: undefined
118 | }
119 |
120 | export const CustomSVG = Template.bind({})
121 | CustomSVG.args = {
122 | fillIcon: ,
123 | emptyIcon: ,
124 | transition: true,
125 | onPointerEnter: undefined,
126 | onPointerLeave: undefined,
127 | onPointerMove: undefined
128 | }
129 |
130 | export const CustomSVGGroup = Template.bind({})
131 | CustomSVGGroup.args = {
132 | customIcons: [
133 | { icon: },
134 | { icon: },
135 | { icon: },
136 | { icon: },
137 | { icon: }
138 | ],
139 | transition: true,
140 | onPointerEnter: undefined,
141 | onPointerLeave: undefined,
142 | onPointerMove: undefined
143 | }
144 |
145 | export const DisableHover = Template.bind({})
146 | DisableHover.args = {
147 | allowHover: false,
148 | disableFillHover: false,
149 | onPointerEnter: undefined,
150 | onPointerLeave: undefined,
151 | onPointerMove: undefined
152 | }
153 |
154 | export const DisableFillHover = Template.bind({})
155 | DisableFillHover.args = {
156 | disableFillHover: true,
157 | onPointerEnter: undefined,
158 | onPointerLeave: undefined,
159 | onPointerMove: undefined
160 | }
161 |
162 | export const IconsCount = Template.bind({})
163 | IconsCount.args = {
164 | iconsCount: 10,
165 | showTooltip: true,
166 | transition: true,
167 | tooltipArray: [
168 | 'Terrible',
169 | 'Terrible+',
170 | 'Bad',
171 | 'Bad+',
172 | 'Average',
173 | 'Average+',
174 | 'Great',
175 | 'Great+',
176 | 'Awesome',
177 | 'Awesome+'
178 | ],
179 | fillColorArray: [
180 | '#f14f45',
181 | '#f14f45',
182 | '#f16c45',
183 | '#f17a45',
184 | '#f18845',
185 | '#f19745',
186 | '#f1b345',
187 | '#f1c245',
188 | '#f1d045',
189 | '#f1de45'
190 | ],
191 | onPointerEnter: undefined,
192 | onPointerLeave: undefined,
193 | onPointerMove: undefined
194 | }
195 |
196 | export const RTLSupport = Template.bind({})
197 | RTLSupport.args = {
198 | rtl: true,
199 | showTooltip: true,
200 | titleSeparator: 'من',
201 | tooltipDefaultText: 'التقييم',
202 | tooltipArray: ['سيئ جدا', 'سيئ', 'متوسط', 'رائع', 'ممتاز'],
203 | onPointerEnter: undefined,
204 | onPointerLeave: undefined,
205 | onPointerMove: undefined
206 | }
207 |
208 | export const onPointerEnter = Template.bind({})
209 | onPointerEnter.args = {
210 | onClick: undefined,
211 | onPointerLeave: undefined,
212 | onPointerMove: undefined
213 | }
214 |
215 | export const onPointerLeave = Template.bind({})
216 | onPointerLeave.args = {
217 | onClick: undefined,
218 | onPointerEnter: undefined,
219 | onPointerMove: undefined
220 | }
221 |
222 | export const onPointerMove = Template.bind({})
223 | onPointerMove.args = {
224 | onClick: undefined,
225 | onPointerEnter: undefined,
226 | onPointerLeave: undefined
227 | }
228 |
229 | export const ResetRating: ComponentStory = (args) => {
230 | const [rating, setRating] = useState(0)
231 | const handleClick = (value: number) => setRating(value)
232 | const handleReset = () => setRating(0)
233 |
234 | return (
235 |
241 |
242 |
245 |
246 | )
247 | }
248 | ResetRating.args = {
249 | onPointerEnter: undefined,
250 | onPointerLeave: undefined,
251 | onPointerMove: undefined
252 | }
253 |
--------------------------------------------------------------------------------
/src/style.module.css:
--------------------------------------------------------------------------------
1 | .starRatingWrap {
2 | display: inline-block;
3 | touch-action: none;
4 | }
5 |
6 | .simpleStarRating {
7 | position: relative;
8 | display: inline-block;
9 | overflow: hidden;
10 | white-space: nowrap;
11 | vertical-align: middle;
12 | user-select: none;
13 | touch-action: none;
14 | }
15 |
16 | .fillIcons {
17 | position: absolute;
18 | top: 0;
19 | overflow: hidden;
20 | display: inline-block;
21 | white-space: nowrap;
22 | }
23 |
24 | .emptyIcons {
25 | display: inline-block;
26 | }
27 |
28 | .tooltip {
29 | display: inline-block;
30 | padding: 5px 15px;
31 | background-color: #333;
32 | color: #fff;
33 | vertical-align: middle;
34 | border-radius: 5px;
35 | }
36 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "outDir": "dist",
4 | "module": "esnext",
5 | "lib": ["dom", "esnext"],
6 | "moduleResolution": "node",
7 | "jsx": "react-jsx",
8 | "sourceMap": true,
9 | "declaration": true,
10 | "esModuleInterop": true,
11 | "noImplicitReturns": true,
12 | "noImplicitThis": true,
13 | "noImplicitAny": true,
14 | "strictNullChecks": true,
15 | "suppressImplicitAnyIndexErrors": true,
16 | "noUnusedParameters": true,
17 | "allowSyntheticDefaultImports": true,
18 | "target": "es5",
19 | "allowJs": true,
20 | "skipLibCheck": true,
21 | "strict": true,
22 | "forceConsistentCasingInFileNames": true,
23 | "noFallthroughCasesInSwitch": true,
24 | "resolveJsonModule": true,
25 | "isolatedModules": true,
26 | "noEmit": true
27 | },
28 | "include": ["src"]
29 | }
30 |
--------------------------------------------------------------------------------