diff --git a/site/mobile/mobile.config.js b/site/mobile/mobile.config.js index cb9a29f6..67b2c42e 100644 --- a/site/mobile/mobile.config.js +++ b/site/mobile/mobile.config.js @@ -73,7 +73,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..2ab1b43c 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 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 { usePrefixClass } from '../hooks/useClass'; 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..9afc0b35 --- /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 '../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..dac45273 --- /dev/null +++ b/src/rate/RateText.tsx @@ -0,0 +1,27 @@ +import cx from 'classnames'; +import React from 'react'; +import { usePrefixClass } from '../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..37bf01bd --- /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 '../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'; /** * 评分数改变时触发 */ diff --git a/test/snap/__snapshots__/csr.test.jsx.snap b/test/snap/__snapshots__/csr.test.jsx.snap index 727169d6..3e3120ab 100644 --- a/test/snap/__snapshots__/csr.test.jsx.snap +++ b/test/snap/__snapshots__/csr.test.jsx.snap @@ -39512,6 +39512,3712 @@ exports[`csr snapshot test > csr test src/radio/_example/status.tsx 1`] = ` `; +exports[`csr snapshot test > csr test src/rate/_example/action.tsx 1`] = ` +
    +
    +
    +
    +
    + 点击或滑动 +
    +
    +
    +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    +
    +
    +
    +`; + +exports[`csr snapshot test > csr test src/rate/_example/base.tsx 1`] = ` +
    +
    +
    +
    +
    + 实心评分 +
    +
    +
    +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    +
    +
    +
    +`; + +exports[`csr snapshot test > csr test src/rate/_example/color.tsx 1`] = ` +
    +
    +
    +
    +
    +
    +
    + 选中及未选中颜色 +
    +
    +
    +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    +
    +
    +
    +
    +
    +
    + 仅选中颜色 +
    +
    +
    +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    +
    +
    +
    +
    +
    +`; + +exports[`csr snapshot test > csr test src/rate/_example/count.tsx 1`] = ` +
    +
    +
    +
    +
    + 自定义评分数量 +
    +
    +
    +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    +
    +
    +
    +`; + +exports[`csr snapshot test > csr test src/rate/_example/custom.tsx 1`] = ` +
    +
    +
    +
    +
    + 自定义评分 +
    +
    +
    +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    +
    +
    +
    +`; + +exports[`csr snapshot test > csr test src/rate/_example/index.tsx 1`] = ` +
    +
    +

    + Rate 评分 +

    +

    + 用于对某行为/事物进行打分。 +

    +
    +
    +
    +

    + 01 类型 +

    +

    + 实心评分 +

    +
    +
    +
    +
    +
    +
    + 实心评分 +
    +
    +
    +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    +
    +
    +
    +
    +
    +
    + +

    + 自定义评分 +

    +
    +
    +
    +
    +
    +
    + 自定义评分 +
    +
    +
    +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    +
    +
    +
    +
    +
    +
    + +

    + 自定义数量评分 +

    +
    +
    +
    +
    +
    +
    + 自定义评分数量 +
    +
    +
    +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    +
    +
    +
    +
    +
    +
    + +

    + 带描述评分 +

    +
    +
    +
    +
    +
    +
    +
    +
    + 带描述评分 +
    +
    +
    +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + 很差 + +
    +
    +
    +
    +
    +
    + 带描述评分 +
    +
    +
    +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + 5分 + +
    +
    +
    +
    +
    +
    + 带描述评分 +
    +
    +
    +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + 未评分 + +
    +
    +
    +
    +
    +
    +
    +
    + +

    + 评分弹框位置 +

    +
    +
    +
    +
    +
    +
    +
    +
    + 顶部显示 +
    +
    +
    +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    +
    +
    +
    +
    +
    +
    + 底部显示 +
    +
    +
    +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    +
    +
    +
    +
    +
    +
    + 不显示 +
    +
    +
    +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    + 02 组件状态 +

    +

    + 只可选全星时 +

    +
    +
    +
    +
    +
    +
    + 点击或滑动 +
    +
    +
    +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    +
    +
    +
    +
    +
    +
    + +

    + 可选半星时 +

    +
    +
    +
    +
    +
    +
    + 点击或滑动 +
    +
    +
    +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    +
    +
    +
    +
    +
    +
    +

    + 03 组件样式 +

    +

    + 评分打小 +

    +
    +
    +
    +
    +
    +
    +
    +
    + 大尺寸24 +
    +
    +
    +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    +
    +
    +
    +
    +
    +
    + 小尺寸20 +
    +
    +
    +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +

    + 设置评分颜色 +

    +
    +
    +
    +
    +
    +
    +
    +
    + 选中及未选中颜色 +
    +
    +
    +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    +
    +
    +
    +
    +
    +
    + 仅选中颜色 +
    +
    +
    +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    + 04 特殊样式 +

    +

    + 竖向带描述评分 +

    +
    +
    +
    +
    +
    +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    +
    +
    + 可以尝试 +
    +
    +
    +
    +
    +
    +
    +
    +`; + +exports[`csr snapshot test > csr test src/rate/_example/placement.tsx 1`] = ` +
    +
    +
    +
    +
    +
    +
    + 顶部显示 +
    +
    +
    +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    +
    +
    +
    +
    +
    +
    + 底部显示 +
    +
    +
    +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    +
    +
    +
    +
    +
    +
    + 不显示 +
    +
    +
    +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    +
    +
    +
    +
    +
    +`; + +exports[`csr snapshot test > csr test src/rate/_example/show-text.tsx 1`] = ` +
    +
    +
    +
    +
    +
    +
    + 带描述评分 +
    +
    +
    +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + 很差 + +
    +
    +
    +
    +
    +
    + 带描述评分 +
    +
    +
    +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + 5分 + +
    +
    +
    +
    +
    +
    + 带描述评分 +
    +
    +
    +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + 未评分 + +
    +
    +
    +
    +
    +`; + +exports[`csr snapshot test > csr test src/rate/_example/size.tsx 1`] = ` +
    +
    +
    +
    +
    +
    +
    + 大尺寸24 +
    +
    +
    +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    +
    +
    +
    +
    +
    +
    + 小尺寸20 +
    +
    +
    +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    +
    +
    +
    +
    +
    +`; + +exports[`csr snapshot test > csr test src/rate/_example/special.tsx 1`] = ` +
    +
    +
    +
    +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    + + + +
    +
    +
    +
    + 可以尝试 +
    +
    +
    +`; + exports[`csr snapshot test > csr test src/result/_example/custom.tsx 1`] = `
    ssr test src/radio/_example/placement.tsx 1`] = `"< exports[`ssr snapshot test > ssr test src/radio/_example/status.tsx 1`] = `"
    选项禁用-已选
    选项禁用-默认
    "`; +exports[`ssr snapshot test > ssr test src/rate/_example/action.tsx 1`] = `"
    点击或滑动
    "`; + +exports[`ssr snapshot test > ssr test src/rate/_example/base.tsx 1`] = `"
    实心评分
    "`; + +exports[`ssr snapshot test > ssr test src/rate/_example/color.tsx 1`] = `"
    选中及未选中颜色
    仅选中颜色
    "`; + +exports[`ssr snapshot test > ssr test src/rate/_example/count.tsx 1`] = `"
    自定义评分数量
    "`; + +exports[`ssr snapshot test > ssr test src/rate/_example/custom.tsx 1`] = `"
    自定义评分
    "`; + +exports[`ssr snapshot test > ssr test src/rate/_example/index.tsx 1`] = `"

    Rate 评分

    用于对某行为/事物进行打分。

    01 类型

    实心评分

    实心评分

    自定义评分

    自定义评分

    自定义数量评分

    自定义评分数量

    带描述评分

    带描述评分
    很差
    带描述评分
    5分
    带描述评分
    未评分

    评分弹框位置

    顶部显示
    底部显示
    不显示

    02 组件状态

    只可选全星时

    点击或滑动

    可选半星时

    点击或滑动

    03 组件样式

    评分打小

    大尺寸24
    小尺寸20

    设置评分颜色

    选中及未选中颜色
    仅选中颜色

    04 特殊样式

    竖向带描述评分

    可以尝试
    "`; + +exports[`ssr snapshot test > ssr test src/rate/_example/placement.tsx 1`] = `"
    顶部显示
    底部显示
    不显示
    "`; + +exports[`ssr snapshot test > ssr test src/rate/_example/show-text.tsx 1`] = `"
    带描述评分
    很差
    带描述评分
    5分
    带描述评分
    未评分
    "`; + +exports[`ssr snapshot test > ssr test src/rate/_example/size.tsx 1`] = `"
    大尺寸24
    小尺寸20
    "`; + +exports[`ssr snapshot test > ssr test src/rate/_example/special.tsx 1`] = `"
    可以尝试
    "`; + exports[`ssr snapshot test > ssr test src/result/_example/custom.tsx 1`] = `"
    自定义结果
    描述文字
    "`; exports[`ssr snapshot test > ssr test src/result/_example/index.tsx 1`] = `"

    Result 结果

    结果反馈

    01类型

    不同结果反馈

    成功状态
    描述文字
    失败状态
    描述文字
    警示状态
    描述文字
    默认状态
    描述文字

    自定义结果

    自定义结果
    描述文字

    页面位置展示

    "`; diff --git a/test/snap/__snapshots__/ssr.test.jsx.snap b/test/snap/__snapshots__/ssr.test.jsx.snap index ea2a563b..80e9404f 100644 --- a/test/snap/__snapshots__/ssr.test.jsx.snap +++ b/test/snap/__snapshots__/ssr.test.jsx.snap @@ -350,6 +350,26 @@ exports[`ssr snapshot test > ssr test src/radio/_example/placement.tsx 1`] = `"< exports[`ssr snapshot test > ssr test src/radio/_example/status.tsx 1`] = `"
    选项禁用-已选
    选项禁用-默认
    "`; +exports[`ssr snapshot test > ssr test src/rate/_example/action.tsx 1`] = `"
    点击或滑动
    "`; + +exports[`ssr snapshot test > ssr test src/rate/_example/base.tsx 1`] = `"
    实心评分
    "`; + +exports[`ssr snapshot test > ssr test src/rate/_example/color.tsx 1`] = `"
    选中及未选中颜色
    仅选中颜色
    "`; + +exports[`ssr snapshot test > ssr test src/rate/_example/count.tsx 1`] = `"
    自定义评分数量
    "`; + +exports[`ssr snapshot test > ssr test src/rate/_example/custom.tsx 1`] = `"
    自定义评分
    "`; + +exports[`ssr snapshot test > ssr test src/rate/_example/index.tsx 1`] = `"

    Rate 评分

    用于对某行为/事物进行打分。

    01 类型

    实心评分

    实心评分

    自定义评分

    自定义评分

    自定义数量评分

    自定义评分数量

    带描述评分

    带描述评分
    很差
    带描述评分
    5分
    带描述评分
    未评分

    评分弹框位置

    顶部显示
    底部显示
    不显示

    02 组件状态

    只可选全星时

    点击或滑动

    可选半星时

    点击或滑动

    03 组件样式

    评分打小

    大尺寸24
    小尺寸20

    设置评分颜色

    选中及未选中颜色
    仅选中颜色

    04 特殊样式

    竖向带描述评分

    可以尝试
    "`; + +exports[`ssr snapshot test > ssr test src/rate/_example/placement.tsx 1`] = `"
    顶部显示
    底部显示
    不显示
    "`; + +exports[`ssr snapshot test > ssr test src/rate/_example/show-text.tsx 1`] = `"
    带描述评分
    很差
    带描述评分
    5分
    带描述评分
    未评分
    "`; + +exports[`ssr snapshot test > ssr test src/rate/_example/size.tsx 1`] = `"
    大尺寸24
    小尺寸20
    "`; + +exports[`ssr snapshot test > ssr test src/rate/_example/special.tsx 1`] = `"
    可以尝试
    "`; + exports[`ssr snapshot test > ssr test src/result/_example/custom.tsx 1`] = `"
    自定义结果
    描述文字
    "`; exports[`ssr snapshot test > ssr test src/result/_example/index.tsx 1`] = `"

    Result 结果

    结果反馈

    01类型

    不同结果反馈

    成功状态
    描述文字
    失败状态
    描述文字
    警示状态
    描述文字
    默认状态
    描述文字

    自定义结果

    自定义结果
    描述文字

    页面位置展示

    "`;