feat: Slider support multiple points (#45000)

* feat: slider support multiple & classNames

* test: update snapshot

* chore: fix lint
This commit is contained in:
二货爱吃白萝卜 2023-09-22 14:19:53 +08:00 committed by GitHub
parent 431e00b1d0
commit 05878dd300
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 270 additions and 17 deletions

View File

@ -1600,6 +1600,123 @@ Array [
exports[`renders components/slider/demo/mark.tsx extend context correctly 2`] = `[]`;
exports[`renders components/slider/demo/multiple.tsx extend context correctly 1`] = `
<div
class="ant-slider ant-slider-horizontal"
>
<div
class="ant-slider-rail"
/>
<div
class="ant-slider-tracks"
style="left: 0%; width: 20%;"
/>
<div
class="ant-slider-track ant-slider-track-1"
style="left: 0%; width: 10%; background: transparent;"
/>
<div
class="ant-slider-track ant-slider-track-2"
style="left: 10%; width: 10%; background: transparent;"
/>
<div
class="ant-slider-step"
/>
<div
aria-disabled="false"
aria-orientation="horizontal"
aria-valuemax="100"
aria-valuemin="0"
aria-valuenow="0"
class="ant-slider-handle ant-slider-handle-1"
role="slider"
style="left: 0%; transform: translateX(-50%);"
tabindex="0"
/>
<div
class="ant-tooltip ant-zoom-big-fast-appear ant-zoom-big-fast-appear-prepare ant-zoom-big-fast ant-slider-tooltip ant-tooltip-placement-top"
style="--arrow-x: 0px; --arrow-y: 0px; left: -1000vw; top: -1000vh; box-sizing: border-box;"
>
<div
class="ant-tooltip-arrow"
style="position: absolute; bottom: 0px; left: 0px;"
/>
<div
class="ant-tooltip-content"
>
<div
class="ant-tooltip-inner"
role="tooltip"
>
0
</div>
</div>
</div>
<div
aria-disabled="false"
aria-orientation="horizontal"
aria-valuemax="100"
aria-valuemin="0"
aria-valuenow="10"
class="ant-slider-handle ant-slider-handle-2"
role="slider"
style="left: 10%; transform: translateX(-50%);"
tabindex="0"
/>
<div
class="ant-tooltip ant-zoom-big-fast-appear ant-zoom-big-fast-appear-prepare ant-zoom-big-fast ant-slider-tooltip ant-tooltip-placement-top"
style="--arrow-x: 0px; --arrow-y: 0px; left: -1000vw; top: -1000vh; box-sizing: border-box;"
>
<div
class="ant-tooltip-arrow"
style="position: absolute; bottom: 0px; left: 0px;"
/>
<div
class="ant-tooltip-content"
>
<div
class="ant-tooltip-inner"
role="tooltip"
>
10
</div>
</div>
</div>
<div
aria-disabled="false"
aria-orientation="horizontal"
aria-valuemax="100"
aria-valuemin="0"
aria-valuenow="20"
class="ant-slider-handle ant-slider-handle-3"
role="slider"
style="left: 20%; transform: translateX(-50%);"
tabindex="0"
/>
<div
class="ant-tooltip ant-zoom-big-fast-appear ant-zoom-big-fast-appear-prepare ant-zoom-big-fast ant-slider-tooltip ant-tooltip-placement-top"
style="--arrow-x: 0px; --arrow-y: 0px; left: -1000vw; top: -1000vh; box-sizing: border-box;"
>
<div
class="ant-tooltip-arrow"
style="position: absolute; bottom: 0px; left: 0px;"
/>
<div
class="ant-tooltip-content"
>
<div
class="ant-tooltip-inner"
role="tooltip"
>
20
</div>
</div>
</div>
</div>
`;
exports[`renders components/slider/demo/multiple.tsx extend context correctly 2`] = `[]`;
exports[`renders components/slider/demo/reverse.tsx extend context correctly 1`] = `
Array [
<div

View File

@ -1111,6 +1111,64 @@ Array [
]
`;
exports[`renders components/slider/demo/multiple.tsx correctly 1`] = `
<div
class="ant-slider ant-slider-horizontal"
>
<div
class="ant-slider-rail"
/>
<div
class="ant-slider-tracks"
style="left:0%;width:20%;background:linear-gradient(to right, rgb(135,208,104) 0%, rgb(159,207,123) 100%)"
/>
<div
class="ant-slider-track ant-slider-track-1"
style="left:0%;width:10%;background:transparent"
/>
<div
class="ant-slider-track ant-slider-track-2"
style="left:10%;width:10%;background:transparent"
/>
<div
class="ant-slider-step"
/>
<div
aria-disabled="false"
aria-orientation="horizontal"
aria-valuemax="100"
aria-valuemin="0"
aria-valuenow="0"
class="ant-slider-handle ant-slider-handle-1"
role="slider"
style="left:0%;transform:translateX(-50%)"
tabindex="0"
/>
<div
aria-disabled="false"
aria-orientation="horizontal"
aria-valuemax="100"
aria-valuemin="0"
aria-valuenow="10"
class="ant-slider-handle ant-slider-handle-2"
role="slider"
style="left:10%;transform:translateX(-50%)"
tabindex="0"
/>
<div
aria-disabled="false"
aria-orientation="horizontal"
aria-valuemax="100"
aria-valuemin="0"
aria-valuenow="20"
class="ant-slider-handle ant-slider-handle-3"
role="slider"
style="left:20%;transform:translateX(-50%)"
tabindex="0"
/>
</div>
`;
exports[`renders components/slider/demo/reverse.tsx correctly 1`] = `
Array [
<div

View File

@ -1,11 +1,11 @@
import React from 'react';
import { Slider } from 'antd';
const onChange = (value: number | [number, number]) => {
const onChange = (value: number | number[]) => {
console.log('onChange: ', value);
};
const onAfterChange = (value: number | [number, number]) => {
const onAfterChange = (value: number | number[]) => {
console.log('onAfterChange: ', value);
};

View File

@ -0,0 +1,7 @@
## zh-CN
范围多个点组合。
## en-US
Multiple handles combination.

View File

@ -0,0 +1,42 @@
import React from 'react';
import { Slider } from 'antd';
function getGradientColor(percentage: number) {
const startColor = [135, 208, 104];
const endColor = [255, 204, 199];
const midColor = startColor.map((start, i) => {
const end = endColor[i];
const delta = end - start;
return (start + delta * percentage).toFixed(0);
});
return `rgb(${midColor.join(',')})`;
}
const App: React.FC = () => {
const [value, setValue] = React.useState([0, 10, 20]);
const start = value[0] / 100;
const end = value[value.length - 1] / 100;
return (
<Slider
range
defaultValue={value}
onChange={setValue}
styles={{
track: {
background: 'transparent',
},
tracks: {
background: `linear-gradient(to right, ${getGradientColor(start)} 0%, ${getGradientColor(
end,
)} 100%)`,
},
}}
/>
);
};
export default App;

View File

@ -27,6 +27,7 @@ To input a value in a range.
<code src="./demo/show-tooltip.tsx">Control visible of ToolTip</code>
<code src="./demo/reverse.tsx">Reverse</code>
<code src="./demo/draggableTrack.tsx">Draggable track</code>
<code src="./demo/multiple.tsx">Multiple handles</code>
<code src="./demo/component-token.tsx" debug>Component Token</code>
## API
@ -53,9 +54,15 @@ Common props ref[Common props](/docs/react/common-props)
| vertical | If true, the slider will be vertical | boolean | false | |
| onAfterChange | Fire when onmouseup is fired | (value) => void | - | |
| onChange | Callback function that is fired when the user changes the slider's value | (value) => void | - | |
| trackStyle | The style of slider track (the active range) | CSSProperties | - | |
| railStyle | The style of slider rail (the background) | CSSProperties | - | |
| handleStyle | The style of slider handle | CSSProperties | - | |
### `styles``classNames` 属性
| Property | Description | Version |
| -------- | ------------------------------------------- | ------- |
| track | The track between handle to handle in range | 5.10.0 |
| tracks | Who track in range | 5.10.0 |
| rail | Background rail | 5.10.0 |
| handle | The handle pointer | 5.10.0 |
### range

View File

@ -56,6 +56,9 @@ export interface SliderBaseProps {
tooltip?: SliderTooltipProps;
autoFocus?: boolean;
styles?: RcSliderProps['styles'];
classNames?: RcSliderProps['classNames'];
// Deprecated
/** @deprecated `tooltipPrefixCls` is deprecated. Please use `tooltip.prefixCls` instead. */
tooltipPrefixCls?: string;
@ -78,19 +81,25 @@ export interface SliderSingleProps extends SliderBaseProps {
defaultValue?: number;
onChange?: (value: number) => void;
onAfterChange?: (value: number) => void;
/** @deprecated Please use `styles.handle` instead */
handleStyle?: React.CSSProperties;
/** @deprecated Please use `styles.track` instead */
trackStyle?: React.CSSProperties;
/** @deprecated Please use `styles.rail` instead */
railStyle?: React.CSSProperties;
}
export interface SliderRangeProps extends SliderBaseProps {
range: true | SliderRange;
value?: [number, number];
defaultValue?: [number, number];
onChange?: (value: [number, number]) => void;
onAfterChange?: (value: [number, number]) => void;
value?: number[];
defaultValue?: number[];
onChange?: (value: number[]) => void;
onAfterChange?: (value: number[]) => void;
/** @deprecated Please use `styles.handle` instead */
handleStyle?: React.CSSProperties[];
/** @deprecated Please use `styles.track` instead */
trackStyle?: React.CSSProperties[];
/** @deprecated Please use `styles.rail` instead */
railStyle?: React.CSSProperties;
}

View File

@ -28,6 +28,7 @@ demo:
<code src="./demo/show-tooltip.tsx">控制 ToolTip 的显示</code>
<code src="./demo/reverse.tsx">反向</code>
<code src="./demo/draggableTrack.tsx">范围可拖拽</code>
<code src="./demo/multiple.tsx">多点组合</code>
<code src="./demo/component-token.tsx" debug>组件 Token</code>
## API
@ -37,6 +38,7 @@ demo:
| 参数 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- |
| autoFocus | 自动获取焦点 | boolean | false | |
| classNames | 语义化结构 className | Record<SemanticDOM, string> | - | 5.10.0 |
| defaultValue | 设置初始取值。当 `range` 为 false 时,使用 number否则用 \[number, number] | number \| \[number, number] | 0 \| \[0, 0] | |
| disabled | 值为 true 时,滑块为禁用状态 | boolean | false | |
| keyboard | 支持使用键盘操作 handler | boolean | true | 5.2.0+ |
@ -48,14 +50,21 @@ demo:
| range | 双滑块模式 | boolean \| [range](#range) | false | |
| reverse | 反向坐标轴 | boolean | false | |
| step | 步长,取值必须大于 0并且可被 (max - min) 整除。当 `marks` 不为空对象时,可以设置 `step` 为 null此时 Slider 的可选值仅有 marks 标出来的部分 | number \| null | 1 | |
| styles | 语义化结构 className | Record<SemanticDOM, React.CSSProperties> | - | 5.10.0 |
| tooltip | 设置 Tooltip 相关属性 | [tooltip](#tooltip) | - | 4.23.0 |
| value | 设置当前取值。当 `range` 为 false 时,使用 number否则用 \[number, number] | number \| \[number, number] | - | |
| vertical | 值为 true 时Slider 为垂直方向 | boolean | false | |
| onAfterChange | 与 `onmouseup` 触发时机一致,把当前值作为参数传入 | (value) => void | - | |
| onChange | 当 Slider 的值发生改变时,会触发 onChange 事件,并把改变后的值作为参数传入 | (value) => void | - | |
| trackStyle | Slider 滑动条轨道样式 (选中范围内) | CSSProperties | - | |
| railStyle | Slider 滑动条轨道样式 (背景) | CSSProperties | - | |
| handleStyle | Slider 滑动滑块样式 | CSSProperties | - | |
### `styles``classNames` 属性
| 名称 | 说明 | 版本 |
| ------ | -------------------------------- | ------ |
| track | 范围选择下,点和点之间单个选取条 | 5.10.0 |
| tracks | 范围选择下,整个范围选取条 | 5.10.0 |
| rail | 背景条 | 5.10.0 |
| handle | 抓取点 | 5.10.0 |
### range

View File

@ -1,6 +1,7 @@
import type * as React from 'react';
import type { CSSObject } from '@ant-design/cssinjs';
import { TinyColor } from '@ctrl/tinycolor';
import type * as React from 'react';
import { resetComponent } from '../../style';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
@ -98,11 +99,14 @@ const genBaseStyle: GenerateStyle<SliderToken> = (token) => {
transition: `background-color ${token.motionDurationMid}`,
},
[`${componentCls}-track`]: {
[`${componentCls}-track,${componentCls}-tracks`]: {
position: 'absolute',
transition: `background-color ${token.motionDurationMid}`,
},
[`${componentCls}-track`]: {
backgroundColor: token.trackBg,
borderRadius: token.borderRadiusXS,
transition: `background-color ${token.motionDurationMid}`,
},
[`${componentCls}-track-draggable`]: {
@ -320,7 +324,7 @@ const genDirectionStyle = (token: SliderToken, horizontal: boolean): CSSObject =
[part]: railSize,
},
[`${componentCls}-track`]: {
[`${componentCls}-track,${componentCls}-tracks`]: {
[part]: railSize,
},

View File

@ -144,7 +144,7 @@
"rc-resize-observer": "^1.3.1",
"rc-segmented": "~2.2.2",
"rc-select": "~14.9.0",
"rc-slider": "~10.2.1",
"rc-slider": "~10.3.0",
"rc-steps": "~6.0.1",
"rc-switch": "~4.1.0",
"rc-table": "~7.34.0",