Skip to content

Commit 6819bce

Browse files
authored
refactor: Star Component Refactor (#140)
* refactor: Star Component Refactor * fix: ci
1 parent 503a275 commit 6819bce

3 files changed

Lines changed: 74 additions & 55 deletions

File tree

now.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
{
66
"src": "package.json",
77
"use": "@now/static-build",
8-
"config": { "distDir": ".doc" }
8+
"config": { "distDir": "dist" }
99
}
1010
],
1111
"routes": [

src/Rate.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ import type { StarProps } from './Star';
88

99
function noop() {}
1010

11-
export interface RateProps extends Pick<StarProps, "count" | "character" | "characterRender" | "allowHalf" | "disabled"> {
11+
export interface RateProps
12+
extends Pick<StarProps, 'count' | 'character' | 'characterRender' | 'allowHalf' | 'disabled'> {
1213
value?: number;
1314
defaultValue?: number;
1415
allowClear?: boolean;
@@ -47,7 +48,7 @@ class Rate extends React.Component<RateProps, RateState> {
4748
direction: 'ltr',
4849
};
4950

50-
stars: Record<string, Star>;
51+
stars: Record<string, HTMLLIElement>;
5152

5253
rate: HTMLUListElement;
5354

@@ -131,7 +132,7 @@ class Rate extends React.Component<RateProps, RateState> {
131132
}
132133
};
133134

134-
onKeyDown: React.KeyboardEventHandler<HTMLUListElement> = event => {
135+
onKeyDown: React.KeyboardEventHandler<HTMLUListElement> = (event) => {
135136
const { keyCode } = event;
136137
const { count, allowHalf, onKeyDown, direction } = this.props;
137138
const reverse = direction === 'rtl';
@@ -205,7 +206,7 @@ class Rate extends React.Component<RateProps, RateState> {
205206
return value;
206207
}
207208

208-
saveRef = (index: number) => (node: Star) => {
209+
saveRef = (index: number) => (node: HTMLLIElement) => {
209210
this.stars[index] = node;
210211
};
211212

src/Star.tsx

Lines changed: 68 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import React from 'react';
2+
import KeyCode from 'rc-util/lib/KeyCode';
3+
import classNames from 'classnames';
24

35
export interface StarProps {
46
value?: number;
@@ -17,70 +19,86 @@ export interface StarProps {
1719
count?: number;
1820
}
1921

20-
export default class Star extends React.Component<StarProps> {
21-
onHover: React.MouseEventHandler<HTMLDivElement> = e => {
22-
const { onHover, index } = this.props;
22+
function Star(props: StarProps, ref: React.Ref<HTMLLIElement>) {
23+
const {
24+
disabled,
25+
prefixCls,
26+
character,
27+
characterRender,
28+
index,
29+
count,
30+
value,
31+
allowHalf,
32+
focused,
33+
onHover,
34+
onClick,
35+
} = props;
36+
37+
// =========================== Events ===========================
38+
const onInternalHover: React.MouseEventHandler<HTMLDivElement> = (e) => {
2339
onHover(e, index);
2440
};
2541

26-
onClick = e => {
27-
const { onClick, index } = this.props;
42+
const onInternalClick: React.MouseEventHandler<HTMLDivElement> = (e) => {
2843
onClick(e, index);
2944
};
3045

31-
onKeyDown: React.KeyboardEventHandler<HTMLDivElement> = e => {
32-
const { onClick, index } = this.props;
33-
if (e.keyCode === 13) {
46+
const onInternalKeyDown: React.KeyboardEventHandler<HTMLDivElement> = (e) => {
47+
if (e.keyCode === KeyCode.ENTER) {
3448
onClick(e, index);
3549
}
3650
};
3751

38-
getClassName() {
39-
const { prefixCls, index, value, allowHalf, focused } = this.props;
40-
const starValue = index + 1;
41-
let className = prefixCls;
42-
if (value === 0 && index === 0 && focused) {
43-
className += ` ${prefixCls}-focused`;
44-
} else if (allowHalf && value + 0.5 >= starValue && value < starValue) {
45-
className += ` ${prefixCls}-half ${prefixCls}-active`;
46-
if (focused) {
47-
className += ` ${prefixCls}-focused`;
48-
}
52+
// =========================== Render ===========================
53+
// >>>>> ClassName
54+
const starValue = index + 1;
55+
const classNameList = new Set([prefixCls]);
56+
57+
// TODO: Current we just refactor from CC to FC. This logic seems can be optimized.
58+
if (value === 0 && index === 0 && focused) {
59+
classNameList.add(`${prefixCls}-focused`);
60+
} else if (allowHalf && value + 0.5 >= starValue && value < starValue) {
61+
classNameList.add(`${prefixCls}-half`);
62+
classNameList.add(`${prefixCls}-active`);
63+
if (focused) {
64+
classNameList.add(`${prefixCls}-focused`);
65+
}
66+
} else {
67+
if (starValue <= value) {
68+
classNameList.add(`${prefixCls}-full`);
4969
} else {
50-
className += starValue <= value ? ` ${prefixCls}-full` : ` ${prefixCls}-zero`;
51-
if (starValue === value && focused) {
52-
className += ` ${prefixCls}-focused`;
53-
}
70+
classNameList.add(`${prefixCls}-zero`);
71+
}
72+
if (starValue === value && focused) {
73+
classNameList.add(`${prefixCls}-focused`);
5474
}
55-
return className;
5675
}
5776

58-
render() {
59-
const { onHover, onClick, onKeyDown } = this;
60-
const { disabled, prefixCls, character, characterRender, index, count, value } = this.props;
61-
const characterNode = typeof character === 'function' ? character(this.props) : character;
62-
let start: React.ReactNode = (
63-
<li className={this.getClassName()}>
64-
<div
65-
onClick={disabled ? null : onClick}
66-
onKeyDown={disabled ? null : onKeyDown}
67-
onMouseMove={disabled ? null : onHover}
68-
role="radio"
69-
aria-checked={value > index ? 'true' : 'false'}
70-
aria-posinset={index + 1}
71-
aria-setsize={count}
72-
tabIndex={disabled ? -1 : 0}
73-
>
74-
<div className={`${prefixCls}-first`}>{characterNode}</div>
75-
<div className={`${prefixCls}-second`}>{characterNode}</div>
76-
</div>
77-
</li>
78-
);
77+
// >>>>> Node
78+
const characterNode = typeof character === 'function' ? character(props) : character;
79+
let start: React.ReactNode = (
80+
<li className={classNames(Array.from(classNameList))} ref={ref}>
81+
<div
82+
onClick={disabled ? null : onInternalClick}
83+
onKeyDown={disabled ? null : onInternalKeyDown}
84+
onMouseMove={disabled ? null : onInternalHover}
85+
role="radio"
86+
aria-checked={value > index ? 'true' : 'false'}
87+
aria-posinset={index + 1}
88+
aria-setsize={count}
89+
tabIndex={disabled ? -1 : 0}
90+
>
91+
<div className={`${prefixCls}-first`}>{characterNode}</div>
92+
<div className={`${prefixCls}-second`}>{characterNode}</div>
93+
</div>
94+
</li>
95+
);
7996

80-
if (characterRender) {
81-
start = characterRender(start as React.ReactElement, this.props);
82-
}
83-
84-
return start;
97+
if (characterRender) {
98+
start = characterRender(start as React.ReactElement, props);
8599
}
100+
101+
return start as React.ReactElement;
86102
}
103+
104+
export default React.forwardRef(Star);

0 commit comments

Comments
 (0)