├── .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 | [![NPM](https://img.shields.io/npm/v/react-simple-star-rating.svg)](https://www.npmjs.com/package/react-simple-star-rating) [![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)![npm bundle size](https://img.shields.io/bundlephobia/min/react-simple-star-rating)![GitHub](https://img.shields.io/github/license/awran5/react-simple-star-rating) 6 | 7 |

8 | screenshot 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 | [![Edit react-simple-rating-ts](https://codesandbox.io/static/img/play-codesandbox.svg)](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 | 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 | 31 | 32 | 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 | [![NPM](https://img.shields.io/npm/v/react-simple-star-rating.svg)](https://www.npmjs.com/package/react-simple-star-rating) [![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)![npm bundle size](https://img.shields.io/bundlephobia/min/react-simple-star-rating)![GitHub](https://img.shields.io/github/license/awran5/react-simple-star-rating) 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 |
203 | Changelog 204 |
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 | --------------------------------------------------------------------------------