Skip to content

Commit

Permalink
feat(CustomIcon): support custom Icon
Browse files Browse the repository at this point in the history
  • Loading branch information
samsan1212 committed Jan 7, 2021
1 parent 8e3d151 commit 41e08f2
Show file tree
Hide file tree
Showing 13 changed files with 289 additions and 206 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ umd
lib
node_modules
npm-debug.log
**.tgz
**.tgz
example
3 changes: 2 additions & 1 deletion .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ rollup.config.js
tsconfig.json
yarn.lock
node_modules
**.tgz
**.tgz
example
5 changes: 5 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"endOfLine": "lf",
"tabWidth": 2,
"printWidth": 100
}
118 changes: 83 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# React Rating Star #
# React Rating Star

Rating Star UI Component powered by ReactJS

[![npm](https://img.shields.io/npm/v/rating-star?color=%23ffb100&style=flat-square)](https://www.npmjs.com/package/rating-star)

## Installation ##
## Installation

```bash
npm i rating-star
Expand All @@ -14,11 +14,11 @@ npm i rating-star
yarn add rating-star
```

## Prerequisite ##
## Prerequisite

The version of React has to be **16.8.0** or above.

## How To Use ##
## How To Use

Javascript / Typescript

Expand All @@ -28,7 +28,7 @@ import { RatingStar } from "rating-star";
export default function App() {
const [rating, setRating] = React.useState(30);

const onRatingChange = score => {
const onRatingChange = (score) => {
setRating(score);
};

Expand All @@ -49,7 +49,7 @@ export default function App() {

For more details, can go to [Demos](#demos).

## Props ##
## Props

| Name | Description |
| --------------------------- | ---------------------------------------------------- |
Expand All @@ -63,35 +63,82 @@ For more details, can go to [Demos](#demos).
| `colors` (optional) | colours of the star icon |
| `onRatingChange` (optional) | a callback of `rating` changes |

### Prop Types ###
### Prop Types

```typescript
interface ColourTheme {
stroke: string;
mask: string;
rear: string;
stroke: string;
mask: string;
rear: string;
}

interface RatingStarProps {
id: string;
clickable?: boolean;
noBorder?: boolean;
size?: number;
maxScore?: number;
rating?: number;
numberOfStar?: number;
colors?: Partial<ColourTheme>;
onRatingChange?: (rating: number) => void;
id: string;
clickable?: boolean;
noBorder?: boolean;
size?: number;
maxScore?: number;
rating?: number;
numberOfStar?: number;
colors?: Partial<ColourTheme>;
onRatingChange?: (rating: number) => void;
}
```

## Customise the Styles ##
## Customise the Star Icon

You can customise the star icon with your needs.

Example:

```tsx
import AcUnitIcon from "@material-ui/icons/AcUnit";
import { RatingStar } from "rating-star";

function App() {
return (
<RatingStar
id="custom-icon-wow"
rating={3}
starIcon={AcUnitIcon}
colors={{ mask: "#43a7e3" }}
noBorder
/>
);
}
```

### Caveat

- The custom icon must be a SVG React component which contains only one child element.

The child element can be one of:

- `path`
- `polygon`
- `circle`
- `rect`
- `image`

e.g.

```jsx
function CustomIcon() {
return (
<svg>
<path d="..." />
</svg>
);
}
```

## Customise the Styles

You can customise the styles of the `rating-star` container by CSS class name, "rating-star",

or use the `id` you have assigned to the `rating-star` component.

### Use with Styled Components ###
### Use with Styled Components

For `styled-components` lover, you can modify the styles with the power of the `styled-components`.

Expand All @@ -101,22 +148,23 @@ import styled from "styled-components";
import { RatingStarContainer, RatingStarIconsWrapper } from "rating-star";

const YourStyledComponent = styled.div`
${RatingStarContainer}{
margin: 10px 0;
}
${RatingStarIconsWrapper}{
> svg {
margin: 3px 0;
}
${RatingStarContainer} {
margin: 10px 0;
}
${RatingStarIconsWrapper} {
> svg {
margin: 3px 0;
}
}
`;
```

## Demos ##
## Demos

* [Fixed rating](https://codesandbox.io/s/fixed-rating-fjjm8)
* [Controlled rating](https://codesandbox.io/s/controlled-rating-hlmmb)
* [Customising the style](https://codesandbox.io/s/customising-the-style-qi24u)
* [Using different maximum score](https://codesandbox.io/s/using-different-maximum-score-95krf)
* [Using different number of star](https://codesandbox.io/s/using-different-number-of-star-h67fy)
* [Using with `styled-components`](https://codesandbox.io/s/using-with-styled-components-dqvii)
- [Fixed rating](https://codesandbox.io/s/fixed-rating-fjjm8)
- [Controlled rating](https://codesandbox.io/s/controlled-rating-hlmmb)
- [Customising the style](https://codesandbox.io/s/customising-the-style-qi24u)
- [Using different maximum score](https://codesandbox.io/s/using-different-maximum-score-95krf)
- [Using different number of star](https://codesandbox.io/s/using-different-number-of-star-h67fy)
- [Using with `styled-components`](https://codesandbox.io/s/using-with-styled-components-dqvii)
- [Using with custom icon](https://codesandbox.io/s/custom-star-icon-k58rb)
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "rating-star",
"version": "1.0.0",
"version": "1.1.0",
"description": "React rating star merely using SVG + CSS",
"main": "./lib/RatingStar.js",
"module": "./esm/RatingStar.js",
Expand Down Expand Up @@ -35,11 +35,11 @@
"react": "16.8.0",
"react-dom": "16.8.0",
"rollup": "^2.23.0",
"tslib": "^2.0.0",
"typescript": "^3.9.7"
"tslib": "^2.1.0",
"typescript": "^4.1.3"
},
"resolutions": {
"styled-components": "^5"
"styled-components": "^4"
},
"scripts": {
"build": "rollup -c"
Expand Down
22 changes: 11 additions & 11 deletions src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@ import { createContext } from "react";
import { ColourTheme } from "../types/RatingStar";

interface ContextProps {
id: string;
colours: ColourTheme;
offsets: number[];
size: number;
noBorder: boolean;
id: string;
colours: ColourTheme;
offsets: number[];
size: number;
noBorder: boolean;
}

export default createContext<ContextProps>({
id: "",
colours: { mask: "", rear: "", stroke: "" },
offsets: [],
size: 24,
noBorder: false
})
id: "",
colours: { mask: "", rear: "", stroke: "" },
offsets: [],
size: 24,
noBorder: false,
});
59 changes: 34 additions & 25 deletions src/ic-star.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,44 @@
*/
import React from "react";
import Context from "./context";
import { StarIconWrapper } from "./styled";

import type { CustomStarIconProps } from "../types/RatingStar";

interface Props {
index: number;
onClick?: () => void;
onMouseOver?: () => void
index: number;
StarIcon?: (props: CustomStarIconProps<unknown>) => JSX.Element;
onClick?: () => void;
onMouseOver?: () => void;
}

const IcStar: React.FC<Props> = ({ index, onClick, onMouseOver }) => {
const { id, colours, offsets, size, noBorder } = React.useContext(Context);
return (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width={size} height={size}>
<defs>
<linearGradient id={`star_mask_${id}-${index}`}>
<stop offset="0" stopColor={colours.mask} />
<stop stopColor={colours.mask} offset={offsets[index] ?? 0} />
<stop stopColor={colours.rear} offset="0" />
<stop offset="1" stopColor={colours.rear} />
</linearGradient>
</defs>
<g stroke={colours.stroke} strokeWidth={noBorder ? 0 : 0.5}>
<polygon
fill={`url(#star_mask_${id}-${index})`}
points="14.43,10 12,2 9.57,10 2,10 8.18,14.41 5.83,22 12,17.31 18.18,22 15.83,14.41 22,10"
onClick={onClick}
onMouseOver={onMouseOver}
/>
</g>
</svg>
)
const IcStar: React.FC<Props> = ({ index, onClick, StarIcon, onMouseOver }) => {
const { id, colours, offsets, size, noBorder } = React.useContext(Context);
return (
<StarIconWrapper elemId={id} index={index}>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width={size} height={size}>
<defs>
<linearGradient id={`star_mask_${id}-${index}`}>
<stop offset="0" stopColor={colours.mask} />
<stop stopColor={colours.mask} offset={offsets[index] ?? 0} />
<stop stopColor={colours.rear} offset="0" />
<stop offset="1" stopColor={colours.rear} />
</linearGradient>
</defs>
<g stroke={colours.stroke} strokeWidth={noBorder ? 0 : 0.5}>
{!StarIcon ? (
<polygon
points="14.43,10 12,2 9.57,10 2,10 8.18,14.41 5.83,22 12,17.31 18.18,22 15.83,14.41 22,10"
onClick={onClick}
onMouseOver={onMouseOver}
/>
) : (
<StarIcon onClick={onClick} onMouseOver={onMouseOver} />
)}
</g>
</svg>
</StarIconWrapper>
);
};

export default IcStar;
Loading

0 comments on commit 41e08f2

Please sign in to comment.