{
  "name": "@plnkr/starter-react",
  "version": "1.0.2",
  "description": "React starter template",
  "dependencies": {
    "react": "^16.4.1",
    "react-dom": "^16.4.1",
    "@types/react": "16.0.31",
    "@types/react-dom": "16.0.3"
  },
  "plnkr": {
    "runtime": "system",
    "useHotReload": true
  },
  "devDependencies": {
    "react-scripts-ts": "latest"
  }
}
body{
  text-align: center;
  padding: 50px 0;
}
.star{
  margin: 0 1px;
  color: lightgray;
  display: inline-block;
  cursor: pointer;
  font-size: x-large;
  text-shadow: 1px 1px 1px rgba(0, 0, 0,0.5);
}
.star.potentialSelect{
 color: yellow; 
}
.star.selected{
  color: gold;
  text-shadow: 1px 1px 3px black;
}

import React, { Component } from 'react';
import './star.css';

export class Star extends Component {
  static defaultProps = {
    selected: false,
    potentialRate: 0
  }

  updateClassName() {
    let cl =
      this.props.selected ?
        "star selected" :
        (this.props.potentialRate >= this.props.val) ?
          "star potentialSelect" : "star";

    return cl;
  }
  render() {
    return (<span
      onClick={() => this.props.setRate(this.props.val)}
      onMouseEnter={() => this.props.readyToRate(this.props.val)}
      title={this.props.val.toString()}
      className={this.updateClassName()}>&#x2605;</span>)
  }
}
import React, { Component } from 'react';
import { Star } from '../Star/Star';

export class Rating extends Component {

  style = {
    display: 'inline-block',
    margin: "-2px 0 0  10px",
    border: "solid 1px gray",
    borderRadius: "50%",
    width: "18px",
    height: "18px",
    textAlign: "center"
  }

  constructor(props) {
    super(props);
    this.state = {
      rate: 0,
      potentialRate: 0
    }
  }
  static defaultProps = { starCount: 5 }
  setRate(rate) {
    if (!this.state.rate) {
      this.setState({ rate: rate });
    }
  }

  readyToRate(potentialRate = 0) {
    if (!this.state.rate) {
      this.setState({ potentialRate });
    }
  }

  reset() {
    this.setState({ rate: 0 });
  }

  render() {
    let rate = this.state.rate;

    return (
      <div
        className="ratingControl"
        onMouseLeave={() => { this.readyToRate() }}>
        {
          Array(this.props.starCount).fill(0).map((m, x) => {
            return (
              <Star
                potentialRate={this.state.potentialRate}
                readyToRate={this.readyToRate.bind(this)}
                setRate={this.setRate.bind(this)}
                selected={rate > x}
                val={x + 1}
              />
            );
          })
        }
        <span style={this.style}>{this.state.rate} </span>
        <span
          onClick={() => { this.reset() }}
          style={{ cursor: "pointer", display: (rate > 0) ? "block" : "none" }}>&#x27f2;</span>
      </div>
    );
  }
}
import React, { Component } from 'react';
import { render } from 'react-dom';
import {Rating} from './Rating/Rating'
import './style.css';

class App extends Component {
  render() {
    return (
      <div>
        <Rating starCount={10}/>
      </div>
    );
  }
}

render(<App />, document.getElementById('root'));