diff --git a/site/mobile/mobile.config.js b/site/mobile/mobile.config.js index 0cbb5c40..140b71f1 100644 --- a/site/mobile/mobile.config.js +++ b/site/mobile/mobile.config.js @@ -63,7 +63,7 @@ export default { { title: 'Rate 评分', name: 'rate', - component: () => import('tdesign-mobile-react/rate/_example/index.jsx'), + component: () => import('tdesign-mobile-react/rate/_example/index.tsx'), }, { title: 'Search 搜索框', diff --git a/src/rate/Rate.tsx b/src/rate/Rate.tsx index 8d5a9235..de5e9d80 100644 --- a/src/rate/Rate.tsx +++ b/src/rate/Rate.tsx @@ -1,119 +1,264 @@ -import React, { FC, forwardRef } from 'react'; -import { StarFilledIcon, StarIcon } from 'tdesign-icons-react'; -import isEmpty from 'lodash/isEmpty'; -import useConfig from '../_util/useConfig'; -import type { TdRateProps } from './type'; +import { useSize } from 'ahooks'; +import cx from 'classnames'; +import React, { forwardRef, useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import { usePrefixClass } from 'tdesign-mobile-react/hooks/useClass'; import useDefault from '../_util/useDefault'; -import useColor from '../_util/useColor'; -import withNativeProps, { NativeProps } from '../_util/withNativeProps'; +import type { StyledProps } from '../common'; +import useDefaultProps from '../hooks/useDefaultProps'; import { rateDefaultProps } from './defaultProps'; +import { RateIcon } from './RateIcon'; +import { RateText } from './RateText'; +import { RateTips } from './RateTips'; +import type { TdRateProps } from './type'; -export interface RateProps extends TdRateProps, NativeProps {} +export interface RateProps extends TdRateProps, StyledProps {} -const Star = (props) => { - const { size, style, variant } = props; - if (variant === 'outline') { - return ; - } - return ; +const convertToNumber = (str: string | number, defaultValue = 0) => { + const value = parseFloat(String(str)); + return isNaN(value) ? defaultValue : value; }; -const defaultUnCheck = '#E3E6EB'; -const defaultCheck = '#ED7B2F'; - -const Rate: FC = forwardRef((props, ref: React.LegacyRef) => { - const { allowHalf, color, count, gap, showText, size, texts, value, onChange, variant, defaultValue, disabled } = - props; - const { classPrefix } = useConfig(); - const name = `${classPrefix}-rate`; - - const [refValue, setRefValue] = useDefault(value, defaultValue, onChange); - const starClickHandle = (number) => { - setRefValue(refValue === number ? 0 : number); - }; - - const [checkColor, unCheckColor] = useColor(color, defaultCheck, defaultUnCheck); - - const getHalfCheckColor = (number) => (number <= refValue ? checkColor : 'transparent'); - - const getCheckColor = (number) => (number <= refValue ? checkColor : unCheckColor); - - const getVariant = (number) => (number <= refValue ? 'filled' : variant); - - const RateLi = (props) => { - const { number } = props; - if (allowHalf) { - const leftStarNumber = number - 0.5; - return ( - <> -
  • 0 ? gap : 0}px` }}> - - - - { - !disabled && starClickHandle(leftStarNumber); - }} - > - - - { - !disabled && starClickHandle(number); - }} - > - - -
  • - - ); - } - return ( -
  • 0 ? gap : 0}px` }}> - { - !disabled && starClickHandle(number); - }} - > - - -
  • - ); - }; - - const starList = []; - for (let i = 0; i < count; i++) { - starList.push(); - } - - const getText = () => { - if (!refValue) { - return ''; +const Rate = forwardRef((props, ref) => { + const rateClass = usePrefixClass('rate'); + + const { + style, + className, + count, + gap, + size, + color, + icon, + allowHalf, + placement, + value, + defaultValue, + onChange, + showText, + texts, + disabled, + } = useDefaultProps(props, rateDefaultProps); + + const [innerValue, setInnerValue] = useDefault(value, defaultValue, onChange); + + const wrapRef = useRef(null); + + const [currentValue, setCurrentValue] = useState(-1); + const [tipsVisible, setTipsVisible] = useState(false); + const [isDragging, setIsDragging] = useState(false); + + const controlRef = useRef({ + timer: 0, + enableClick: true, + touchStartX: 0, + enableTouch: false, + currentValue, + }); + + controlRef.current.enableClick = true; + + const onShowTips = useCallback(() => { + clearTimeout(controlRef.current.timer); + setTipsVisible(true); + }, []); + + const onHideTips = useCallback(() => { + clearTimeout(controlRef.current.timer); + setTipsVisible(false); + }, []); + + // 组件销毁的时候 清除定时器 + useEffect( + () => () => { + clearTimeout(controlRef.current.timer); + }, + [], + ); + + const onTouchStart = useCallback( + (e: React.TouchEvent) => { + controlRef.current.enableTouch = false; + const event = e.touches[0]; + if (!event || disabled) { + return; + } + controlRef.current.touchStartX = event.clientX; + }, + [disabled], + ); + + const onTouchMove = useCallback( + (e: React.TouchEvent) => { + const event = e.touches[0]; + const wrapEle = wrapRef.current; + if (!event || count < 1 || !wrapEle || disabled) { + return; + } + + if (Math.abs(event.clientX - controlRef.current.touchStartX) > 5) { + controlRef.current.enableTouch = true; + setIsDragging(true); + onShowTips(); + } + + if (!controlRef.current.enableTouch) { + return; + } + + // 计算 + const wrapRect = wrapEle.getBoundingClientRect(); + const gapNum = convertToNumber(gap); + const perWidth = (wrapRect.width + gapNum) / count; + // 左边 - gap / 2 右边 + gap / 2 + const x = event.clientX - wrapRect.x + gapNum / 2; + + let value = Math.min(Math.max(Math.floor(x / perWidth / 0.5) * 0.5 + 0.5, 0), count); + if (!allowHalf) { + value = Math.floor(value); + } + + setCurrentValue(value); + setTipsVisible(true); + controlRef.current.currentValue = value; + }, + [gap, count, allowHalf, onShowTips, disabled], + ); + + const onTouchEnd = useCallback(() => { + setIsDragging(false); + if (!controlRef.current.enableTouch || disabled) { + return; } - if (isEmpty(texts)) { - return refValue; + controlRef.current.enableTouch = false; + controlRef.current.enableClick = false; + // 根据记录去修改数据 + setInnerValue(controlRef.current.currentValue); + onHideTips(); + }, [onHideTips, setInnerValue, disabled]); + + const wrapSize = useSize(wrapRef); + + const tipsLeft = useMemo(() => { + if (count < 1 || !wrapSize) { + return 0; } - return texts?.[Math.ceil(refValue) - 1] ?? 'undefined'; - }; - - return withNativeProps( - props, -
    - -
      {starList}
    - {showText && {getText()}} -
    , + + const gapNum = convertToNumber(gap); + const perWidth = (wrapSize.width - (count - 1) * gapNum) / count; + const index = Math.max(Math.min(Math.ceil(currentValue), count), 1) - 1; + + return (index + 1) * perWidth - perWidth / 2 + index * gapNum; + }, [wrapSize, count, currentValue, gap]); + + const [clickTime, setClickTime] = useState(0); + + const doubleTips = allowHalf && !isDragging; + + return ( +
    +
    + {Array(count) + .fill('') + .map((_, index) => { + const itemValue = index + 1; + + const compareValue = isDragging ? currentValue : innerValue; + + return ( + compareValue && itemValue < compareValue + 1} + onClick={(placement) => { + if (!controlRef.current.enableClick || disabled) { + return; + } + const value = placement === 'left' && allowHalf ? itemValue - 0.5 : itemValue; + setClickTime(Date.now()); + setCurrentValue(value); + onShowTips(); + controlRef.current.timer = setTimeout(onHideTips, 3000) as any as number; + setInnerValue(value); + }} + /> + ); + })} +
    + {showText ? : null} + {/* 增加一个时间戳作为 key 保证每次点击的时候 组件都重新创建 防止重复利用 触发 onClickOutSide */} + {tipsVisible && placement && !disabled ? ( + { + let isHalf = false; + if (doubleTips) { + isHalf = index === 0; + } else { + isHalf = Math.ceil(currentValue) !== currentValue; + } + + let value = currentValue; + if (doubleTips) { + if (index === 0) { + value = Math.ceil(currentValue) - 0.5; + } else { + value = Math.ceil(currentValue); + } + } + + const actived = doubleTips ? value === currentValue : false; + + return { + icon: ( + + ), + text: value, + actived, + onClick: () => { + if (value === innerValue) { + return; + } + setInnerValue(value); + onHideTips(); + }, + }; + })} + /> + ) : null} +
    ); }); -Rate.defaultProps = rateDefaultProps; Rate.displayName = 'Rate'; export default Rate; diff --git a/src/rate/RateIcon.tsx b/src/rate/RateIcon.tsx new file mode 100644 index 00000000..f8b5ba14 --- /dev/null +++ b/src/rate/RateIcon.tsx @@ -0,0 +1,88 @@ +import cx from 'classnames'; +import React, { cloneElement, ReactNode, useMemo, useRef } from 'react'; +import { StarFilledIcon } from 'tdesign-icons-react'; +import { usePrefixClass } from 'tdesign-mobile-react/hooks/useClass'; +import { TdRateProps } from './type'; + +type Props = Required> & { + size: number; + isCurrent: boolean; + isSelected: boolean; + isHalf: boolean; + onClick?: (placement: 'left' | 'right', e: React.MouseEvent) => void; +}; + +export const RateIcon = (props: Props) => { + const iconClass = usePrefixClass('rate__icon'); + + const { size, icon, color, isCurrent, isSelected, isHalf, onClick } = props; + + const iconList: ReactNode[] = useMemo(() => { + const arr: ReactNode[] = []; + arr[0] = (typeof icon?.[0] === 'function' ? icon[0]() : icon?.[0]) || ; + arr[1] = (typeof icon?.[1] === 'function' ? icon[1]() : icon?.[1]) || ; + + // 防止传入的 element 上有 key + return arr.map((item) => { + if (React.isValidElement(item)) { + return cloneElement(item, { key: null }); + } + return item; + }); + }, [icon]); + + const style = useMemo(() => { + const style: React.CSSProperties = { + fontSize: `${size}px`, + }; + + const selectedColor = Array.isArray(color) ? color[0] : color; + if (selectedColor) { + style['--td-rate-selected-color'] = selectedColor; + } + + const unSelectedColor = Array.isArray(color) ? color[1] : ''; + if (unSelectedColor) { + style['--td-rate-unselected-color'] = unSelectedColor; + } + + return style; + }, [color, size]); + + const iconNode = <>{isSelected ? iconList[0] : iconList[1]}; + + const ref = useRef(null); + return ( +
    { + const dom = ref.current; + if (!dom) { + return; + } + const rect = dom.getBoundingClientRect(); + const isLeft = e.clientX < rect.x + rect.width / 2; + onClick?.(isLeft ? 'left' : 'right', e); + }} + style={style} + className={cx(iconClass, { + [`${iconClass}--current`]: isCurrent, + [`${iconClass}--selected`]: isSelected && !isHalf, + [`${iconClass}--unselected`]: !isSelected || isHalf, + })} + > + {isHalf ? ( +
    + {iconNode} +
    + ) : null} + + {iconNode} +
    + ); +}; diff --git a/src/rate/RateText.tsx b/src/rate/RateText.tsx new file mode 100644 index 00000000..e9b87bd0 --- /dev/null +++ b/src/rate/RateText.tsx @@ -0,0 +1,27 @@ +import cx from 'classnames'; +import React from 'react'; +import { usePrefixClass } from 'tdesign-mobile-react/hooks/useClass'; +import { TdRateProps } from './type'; + +type Props = { + texts: TdRateProps['texts']; + value: number; +}; + +export const RateText = (props: Props) => { + const textClass = usePrefixClass('rate__text'); + + const { value, texts } = props; + + const text = (Array.isArray(texts) ? texts[value - 1] : '') || `${value}分`; + + return ( + 0, + })} + > + {value ? text : '未评分'} + + ); +}; diff --git a/src/rate/RateTips.tsx b/src/rate/RateTips.tsx new file mode 100644 index 00000000..6226f5a7 --- /dev/null +++ b/src/rate/RateTips.tsx @@ -0,0 +1,51 @@ +import { useClickAway } from 'ahooks'; +import cx from 'classnames'; +import React, { ReactNode, useRef } from 'react'; +import { usePrefixClass } from 'tdesign-mobile-react/hooks/useClass'; +import { TdRateProps } from './type'; + +type Props = { + left: number; + placement: TdRateProps['placement']; + onClickOutside: () => void; + data: { + icon: ReactNode; + text: ReactNode; + actived?: boolean; + onClick?: (index: number) => void; + }[]; +}; + +export const RateTips = (props: Props) => { + const tipClass = usePrefixClass('rate__tips'); + + const { left, data, placement, onClickOutside } = props; + const ref = useRef(null); + + useClickAway(onClickOutside, ref); + + return ( +
    +
    + {data.map((item, index) => ( +
    item.onClick?.(index)} + > + {item.icon} + {item.text} +
    + ))} +
    +
    + ); +}; diff --git a/src/rate/_example/action.tsx b/src/rate/_example/action.tsx new file mode 100644 index 00000000..957bcf3c --- /dev/null +++ b/src/rate/_example/action.tsx @@ -0,0 +1,11 @@ +import React from 'react'; +import { Cell, Rate } from 'tdesign-mobile-react'; + +export default function Action(props: { allowHalf: boolean }) { + const { allowHalf } = props; + return ( + + + + ); +} diff --git a/src/rate/_example/allow-half.jsx b/src/rate/_example/allow-half.jsx deleted file mode 100644 index 83e401fe..00000000 --- a/src/rate/_example/allow-half.jsx +++ /dev/null @@ -1,20 +0,0 @@ -import React, { useState } from 'react'; -import { Rate } from 'tdesign-mobile-react'; -import CustomCell from './custom-cell'; - -export default function Base() { - const [value, setValue] = useState(3.5); - - return ( - - { - setValue(value); - }} - /> - - ); -} diff --git a/src/rate/_example/outline.jsx b/src/rate/_example/base.tsx similarity index 63% rename from src/rate/_example/outline.jsx rename to src/rate/_example/base.tsx index 61b53729..8b2a4c74 100644 --- a/src/rate/_example/outline.jsx +++ b/src/rate/_example/base.tsx @@ -1,18 +1,17 @@ import React, { useState } from 'react'; -import { Rate } from 'tdesign-mobile-react'; -import CustomCell from './custom-cell'; +import { Cell, Rate } from 'tdesign-mobile-react'; export default function Base() { const [value, setValue] = useState(3); return ( - + { setValue(value); }} /> - + ); } diff --git a/src/rate/_example/color.jsx b/src/rate/_example/color.jsx deleted file mode 100644 index d63d2cd4..00000000 --- a/src/rate/_example/color.jsx +++ /dev/null @@ -1,34 +0,0 @@ -import React, { useState } from 'react'; -import { Rate } from 'tdesign-mobile-react'; -import CustomCell from './custom-cell'; - -export default function Base() { - const [value, setValue] = useState(3); - const [value1, setValue1] = useState(2.5); - - return ( - <> - - { - setValue(value); - }} - /> - - - - { - setValue1(value); - }} - /> - - - ); -} diff --git a/src/rate/_example/color.tsx b/src/rate/_example/color.tsx new file mode 100644 index 00000000..b512f6e7 --- /dev/null +++ b/src/rate/_example/color.tsx @@ -0,0 +1,15 @@ +import React from 'react'; +import { Cell, CellGroup, Rate } from 'tdesign-mobile-react'; + +export default function Color() { + return ( + + + + + + + + + ); +} diff --git a/src/rate/_example/count.jsx b/src/rate/_example/count.jsx deleted file mode 100644 index 19f92076..00000000 --- a/src/rate/_example/count.jsx +++ /dev/null @@ -1,20 +0,0 @@ -import React, { useState } from 'react'; -import { Rate } from 'tdesign-mobile-react'; -import CustomCell from './custom-cell'; - -export default function Base() { - const [value, setValue] = useState(3); - - return ( - - { - setValue(value); - }} - /> - - ); -} diff --git a/src/rate/_example/count.tsx b/src/rate/_example/count.tsx new file mode 100644 index 00000000..548c7b99 --- /dev/null +++ b/src/rate/_example/count.tsx @@ -0,0 +1,18 @@ +import React, { useState } from 'react'; +import { Cell, Rate } from 'tdesign-mobile-react'; + +export default function Count() { + const [value, setValue] = useState(2); + + return ( + + { + setValue(value); + }} + /> + + ); +} diff --git a/src/rate/_example/custom-cell.jsx b/src/rate/_example/custom-cell.jsx deleted file mode 100644 index c317185a..00000000 --- a/src/rate/_example/custom-cell.jsx +++ /dev/null @@ -1,17 +0,0 @@ -import React from 'react'; -import './style/customCell.less'; - -export default function CustomCell(props) { - return ( -
    -
    {props.title}
    - {props.children} -
    - ); -} diff --git a/src/rate/_example/custom.tsx b/src/rate/_example/custom.tsx new file mode 100644 index 00000000..06a73d2c --- /dev/null +++ b/src/rate/_example/custom.tsx @@ -0,0 +1,19 @@ +import React, { useState } from 'react'; +import { ThumbUpIcon } from 'tdesign-icons-react'; +import { Cell, Rate } from 'tdesign-mobile-react'; + +export default function Custom() { + const [value, setValue] = useState(3); + + return ( + + , ]} + value={value} + onChange={(value) => { + setValue(value); + }} + /> + + ); +} diff --git a/src/rate/_example/disabled.jsx b/src/rate/_example/disabled.jsx deleted file mode 100644 index be9356d0..00000000 --- a/src/rate/_example/disabled.jsx +++ /dev/null @@ -1,11 +0,0 @@ -import React from 'react'; -import { Rate } from 'tdesign-mobile-react'; -import CustomCell from './custom-cell'; - -export default function Base() { - return ( - - - - ); -} diff --git a/src/rate/_example/filled.jsx b/src/rate/_example/filled.jsx deleted file mode 100644 index 5ff27520..00000000 --- a/src/rate/_example/filled.jsx +++ /dev/null @@ -1,19 +0,0 @@ -import React, { useState } from 'react'; -import { Rate } from 'tdesign-mobile-react'; -import CustomCell from './custom-cell'; - -export default function Base() { - const [value, setValue] = useState(3); - - return ( - - { - setValue(value); - }} - /> - - ); -} diff --git a/src/rate/_example/index.jsx b/src/rate/_example/index.jsx deleted file mode 100644 index e6a97fea..00000000 --- a/src/rate/_example/index.jsx +++ /dev/null @@ -1,49 +0,0 @@ -import React from 'react'; -import TDemoHeader from '../../../site/mobile/components/DemoHeader'; -import TDemoBlock from '../../../site/mobile/components/DemoBlock'; - -import FilledDemo from './filled'; -import OutlineDemo from './outline'; -import CountDemo from './count'; -import AllowHalfDemo from './allow-half'; -import DisabledDemo from './disabled'; -import ColorDemo from './color'; -import TextDemo from './text'; -import SizeDemo from './size'; - -import './style/index.less'; - -export default function RadioDemo() { - return ( -
    - - - - - - - - - - - - - - - - - - - - - - - - - -
    - ); -} diff --git a/src/rate/_example/index.tsx b/src/rate/_example/index.tsx new file mode 100644 index 00000000..9238da75 --- /dev/null +++ b/src/rate/_example/index.tsx @@ -0,0 +1,54 @@ +import React from 'react'; +import TDemoBlock from '../../../site/mobile/components/DemoBlock'; +import TDemoHeader from '../../../site/mobile/components/DemoHeader'; + +import ActionDemo from './action'; +import BaseDemo from './base'; +import ColorDemo from './color'; +import CountDemo from './count'; +import CustomDemo from './custom'; +import PlacementDemo from './placement'; +import ShowTextDemo from './show-text'; +import SizeDemo from './size'; +import SpecialDemo from './special'; + +export default function RateDemo() { + return ( + <> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} diff --git a/src/rate/_example/placement.tsx b/src/rate/_example/placement.tsx new file mode 100644 index 00000000..aee68003 --- /dev/null +++ b/src/rate/_example/placement.tsx @@ -0,0 +1,18 @@ +import React from 'react'; +import { Cell, CellGroup, Rate } from 'tdesign-mobile-react'; + +export default function Placement() { + return ( + + + + + + + + + + + + ); +} diff --git a/src/rate/_example/show-text.tsx b/src/rate/_example/show-text.tsx new file mode 100644 index 00000000..f6bbb77a --- /dev/null +++ b/src/rate/_example/show-text.tsx @@ -0,0 +1,18 @@ +import React from 'react'; +import { Cell, CellGroup, Rate } from 'tdesign-mobile-react'; + +export default function ShowText() { + return ( + + + + + + + + + + + + ); +} diff --git a/src/rate/_example/size.jsx b/src/rate/_example/size.jsx deleted file mode 100644 index fd343dca..00000000 --- a/src/rate/_example/size.jsx +++ /dev/null @@ -1,31 +0,0 @@ -import React, { useState } from 'react'; -import { Rate } from 'tdesign-mobile-react'; -import CustomCell from './custom-cell'; - -export default function Base() { - const [value, setValue] = useState(3); - - return ( - <> - - { - setValue(value); - }} - /> - - - { - setValue(value); - }} - /> - - - ); -} diff --git a/src/rate/_example/size.tsx b/src/rate/_example/size.tsx new file mode 100644 index 00000000..16623deb --- /dev/null +++ b/src/rate/_example/size.tsx @@ -0,0 +1,15 @@ +import React from 'react'; +import { Cell, CellGroup, Rate } from 'tdesign-mobile-react'; + +export default function Size() { + return ( + + + + + + + + + ); +} diff --git a/src/rate/_example/special.tsx b/src/rate/_example/special.tsx new file mode 100644 index 00000000..8a0384ab --- /dev/null +++ b/src/rate/_example/special.tsx @@ -0,0 +1,21 @@ +import React, { useState } from 'react'; +import { Cell, Rate } from 'tdesign-mobile-react'; + +export default function Special() { + const [value, setValue] = useState(3); + const texts = ['非常糟糕', '有些糟糕', '可以尝试', '可以前往', '推荐前往']; + + return ( + + { + setValue(value); + }} + /> +
    {texts[value - 1]}
    +
    + ); +} diff --git a/src/rate/_example/style/customCell.less b/src/rate/_example/style/customCell.less deleted file mode 100644 index ca7e191f..00000000 --- a/src/rate/_example/style/customCell.less +++ /dev/null @@ -1,6 +0,0 @@ -.custom-cell { - display: flex; - align-items: center; - padding: 12px 16px; - border-bottom: 1px solid #f5f5f5; -} diff --git a/src/rate/_example/style/index.less b/src/rate/_example/style/index.less deleted file mode 100644 index b72e1196..00000000 --- a/src/rate/_example/style/index.less +++ /dev/null @@ -1,3 +0,0 @@ -.tdesign-mobile-demo { - padding-bottom: 46px; -} diff --git a/src/rate/_example/text.jsx b/src/rate/_example/text.jsx deleted file mode 100644 index fd6c9ef5..00000000 --- a/src/rate/_example/text.jsx +++ /dev/null @@ -1,47 +0,0 @@ -import React, { useState } from 'react'; -import { Rate } from 'tdesign-mobile-react'; -import CustomCell from './custom-cell'; -import './style/index.less'; - -export default function Base() { - const [value2, setValue2] = useState(3); - - return ( - <> - - { - setValue2(value); - }} - /> - - - { - setValue2(value); - }} - /> - - - { - setValue2(value); - }} - /> - - - ); -} diff --git a/src/rate/defaultProps.ts b/src/rate/defaultProps.ts index ee6ed026..7449648f 100644 --- a/src/rate/defaultProps.ts +++ b/src/rate/defaultProps.ts @@ -8,12 +8,11 @@ export const rateDefaultProps: TdRateProps = { allowHalf: false, color: '#ED7B2F', count: 5, - disabled: false, + disabled: undefined, gap: 8, + placement: 'top', showText: false, - texts: ['极差', '失望', '一般', '满意', '惊喜'], + size: '24px', + texts: [], defaultValue: 0, - variant: 'outline', - value: 0, - size: '20', }; diff --git a/src/rate/rate.en-US.md b/src/rate/rate.en-US.md new file mode 100644 index 00000000..452d837c --- /dev/null +++ b/src/rate/rate.en-US.md @@ -0,0 +1,23 @@ +:: BASE_DOC :: + +## API + +### Rate Props + +name | type | default | description | required +-- | -- | -- | -- | -- +className | String | - | className of component | N +style | Object | - | CSS(Cascading Style Sheets),Typescript:`React.CSSProperties` | N +allowHalf | Boolean | false | \- | N +color | String / Array | '#ED7B2F' | Typescript:`string \| Array` | N +count | Number | 5 | \- | N +disabled | Boolean | undefined | \- | N +gap | String / Number | 8 | \- | N +icon | TNode | - | Typescript:`Array`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +placement | String | top | options: top / bottom / '' | N +showText | Boolean | false | \- | N +size | String | 24px | \- | N +texts | Array | [] | Typescript:`Array` | N +value | Number | 0 | \- | N +defaultValue | Number | 0 | uncontrolled property | N +onChange | Function | | Typescript:`(value: number) => void`
    | N diff --git a/src/rate/rate.md b/src/rate/rate.md index 1e35f486..2c7901a4 100644 --- a/src/rate/rate.md +++ b/src/rate/rate.md @@ -1,21 +1,23 @@ :: BASE_DOC :: ## API + ### Rate Props -名称 | 类型 | 默认值 | 说明 | 必传 +名称 | 类型 | 默认值 | 描述 | 必传 -- | -- | -- | -- | -- className | String | - | 类名 | N style | Object | - | 样式,TS 类型:`React.CSSProperties` | N allowHalf | Boolean | false | 是否允许半选 | N -color | String / Array | '#ED7B2F' | 评分图标的颜色,样式中默认为 #ED7B2F。一个值表示设置选中高亮的五角星颜色,示例:[选中颜色]。数组则表示分别设置 选中高亮的五角星颜色 和 未选中暗灰的五角星颜色,[选中颜色,未选中颜色]。示例:['#ED7B2F', '#E3E6EB']。TS 类型:`string | Array` | N +color | String / Array | '#ED7B2F' | 评分图标的颜色,样式中默认为 #ED7B2F。一个值表示设置选中高亮的五角星颜色,示例:[选中颜色]。数组则表示分别设置 选中高亮的五角星颜色 和 未选中暗灰的五角星颜色,[选中颜色,未选中颜色]。示例:['#ED7B2F', '#E3E6EB']。TS 类型:`string \| Array` | N count | Number | 5 | 评分的数量 | N -disabled | Boolean | false | 是否禁用评分 | N -gap | Number | 8 | 评分图标的间距 | N +disabled | Boolean | undefined | 是否禁用评分 | N +gap | String / Number | 8 | 评分图标的间距 | N +icon | TNode | - | 自定义评分图标,[选中图标,未选中图标]。TS 类型:`Array`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +placement | String | top | 选择评分弹框的位置,值为空字符表示不显示评分弹框。可选项:top / bottom / '' | N showText | Boolean | false | 是否显示对应的辅助文字 | N -size | String | - | 评分图标的大小,示例:`20` | N +size | String | 24px | 评分图标的大小 | N texts | Array | [] | 评分等级对应的辅助文字。组件内置默认值为:['极差', '失望', '一般', '满意', '惊喜']。自定义值示例:['1分', '2分', '3分', '4分', '5分']。TS 类型:`Array` | N value | Number | 0 | 选择评分的值 | N defaultValue | Number | 0 | 选择评分的值。非受控属性 | N -variant | String | outline | 形状类型,有描边类型和填充类型两种。可选项:outline/filled | N onChange | Function | | TS 类型:`(value: number) => void`
    评分数改变时触发 | N diff --git a/src/rate/style/index.js b/src/rate/style/index.js index 7502123a..8d4b4c68 100644 --- a/src/rate/style/index.js +++ b/src/rate/style/index.js @@ -1 +1 @@ -import '../../_common/style/mobile/components/rate/_index.less'; +import '../../_common/style/mobile/components/rate/v2/_index.less'; diff --git a/src/rate/type.ts b/src/rate/type.ts index 419decf8..ce319bdf 100644 --- a/src/rate/type.ts +++ b/src/rate/type.ts @@ -4,6 +4,8 @@ * 该文件为脚本自动生成文件,请勿随意修改。如需修改请联系 PMC * */ +import { TNode } from '../common'; + export interface TdRateProps { /** * 是否允许半选 @@ -22,22 +24,30 @@ export interface TdRateProps { count?: number; /** * 是否禁用评分 - * @default false */ disabled?: boolean; /** * 评分图标的间距 - * @default 6 + * @default 8 + */ + gap?: string | number; + /** + * 自定义评分图标,[选中图标,未选中图标] */ - gap?: number; + icon?: Array; + /** + * 选择评分弹框的位置,值为空字符表示不显示评分弹框 + * @default top + */ + placement?: 'top' | 'bottom' | ''; /** * 是否显示对应的辅助文字 * @default false */ showText?: boolean; /** - * 评分图标的大小,示例:`20` - * @default '' + * 评分图标的大小 + * @default 24px */ size?: string; /** @@ -55,11 +65,6 @@ export interface TdRateProps { * @default 0 */ defaultValue?: number; - /** - * 形状类型,有描边类型和填充类型两种 - * @default outline - */ - variant?: 'outline' | 'filled'; /** * 评分数改变时触发 */