feat: Slider support editable (#49923)

* feat: Slider support editable

* test: update snapshot

* test: update snapshot

* docs: update docs

* chore: fix lint

* test: update snapshot

* test: coverage
This commit is contained in:
二货爱吃白萝卜 2024-07-18 19:19:02 +08:00 committed by GitHub
parent 105bd19614
commit 21194da96a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 141 additions and 339 deletions

View File

@ -7,10 +7,16 @@ import { composeRef } from 'rc-util/lib/ref';
import type { TooltipProps } from '../tooltip';
import Tooltip from '../tooltip';
const SliderTooltip = React.forwardRef<SliderRef, TooltipProps>((props, ref) => {
const { open } = props;
export type SliderTooltipProps = TooltipProps & {
draggingDelete?: boolean;
};
const SliderTooltip = React.forwardRef<SliderRef, SliderTooltipProps>((props, ref) => {
const { open, draggingDelete } = props;
const innerRef = useRef<any>(null);
const mergedOpen = open && !draggingDelete;
const rafRef = useRef<number | null>(null);
function cancelKeepAlign() {
@ -26,16 +32,16 @@ const SliderTooltip = React.forwardRef<SliderRef, TooltipProps>((props, ref) =>
}
React.useEffect(() => {
if (open) {
if (mergedOpen) {
keepAlign();
} else {
cancelKeepAlign();
}
return cancelKeepAlign;
}, [open, props.title]);
}, [mergedOpen, props.title]);
return <Tooltip ref={composeRef(innerRef, ref)} {...props} />;
return <Tooltip ref={composeRef(innerRef, ref)} {...props} open={mergedOpen} />;
});
if (process.env.NODE_ENV !== 'production') {

View File

@ -81,28 +81,6 @@ Array [
style="left: 50%; transform: translateX(-50%);"
tabindex="0"
/>
<div
aria-hidden="true"
class="ant-slider-handle"
style="transform: translateX(-50%); pointer-events: none; visibility: hidden;"
/>
<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"
/>
</div>
</div>
</div>,
Disabled: ,
<button
@ -210,28 +188,6 @@ Array [
style="left: 50%; transform: translateX(-50%);"
tabindex="0"
/>
<div
aria-hidden="true"
class="ant-slider-handle"
style="transform: translateX(-50%); pointer-events: none; visibility: hidden;"
/>
<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"
/>
</div>
</div>
</div>,
<div
style="display: inline-block; height: 300px; margin-left: 70px;"
@ -319,28 +275,6 @@ Array [
style="bottom: 50%; transform: translateY(50%);"
tabindex="0"
/>
<div
aria-hidden="true"
class="ant-slider-handle"
style="transform: translateY(50%); pointer-events: none; visibility: hidden;"
/>
<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-right"
style="--arrow-x: 0px; --arrow-y: 0px; left: -1000vw; top: -1000vh; box-sizing: border-box;"
>
<div
class="ant-tooltip-arrow"
style="position: absolute; top: 0px; left: 0px;"
/>
<div
class="ant-tooltip-content"
>
<div
class="ant-tooltip-inner"
role="tooltip"
/>
</div>
</div>
</div>
</div>,
<div
@ -398,28 +332,6 @@ Array [
style="bottom: 37%; transform: translateY(50%);"
tabindex="0"
/>
<div
aria-hidden="true"
class="ant-slider-handle"
style="transform: translateY(50%); pointer-events: none; visibility: hidden;"
/>
<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-right"
style="--arrow-x: 0px; --arrow-y: 0px; left: -1000vw; top: -1000vh; box-sizing: border-box;"
>
<div
class="ant-tooltip-arrow"
style="position: absolute; top: 0px; left: 0px;"
/>
<div
class="ant-tooltip-content"
>
<div
class="ant-tooltip-inner"
role="tooltip"
/>
</div>
</div>
<div
class="ant-slider-mark"
>
@ -493,33 +405,52 @@ exports[`renders components/slider/demo/draggableTrack.tsx extend context correc
style="left: 50%; transform: translateX(-50%);"
tabindex="0"
/>
<div
aria-hidden="true"
class="ant-slider-handle"
style="transform: translateX(-50%); pointer-events: none; visibility: hidden;"
/>
<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"
/>
</div>
</div>
</div>
`;
exports[`renders components/slider/demo/draggableTrack.tsx extend context correctly 2`] = `[]`;
exports[`renders components/slider/demo/editable.tsx extend context correctly 1`] = `
<div
class="ant-slider ant-slider-horizontal"
>
<div
class="ant-slider-rail"
/>
<div
class="ant-slider-track ant-slider-track-1"
style="left: 20%; width: 60%;"
/>
<div
class="ant-slider-step"
/>
<div
aria-disabled="false"
aria-orientation="horizontal"
aria-valuemax="100"
aria-valuemin="0"
aria-valuenow="20"
class="ant-slider-handle ant-slider-handle-1"
role="slider"
style="left: 20%; transform: translateX(-50%);"
tabindex="0"
/>
<div
aria-disabled="false"
aria-orientation="horizontal"
aria-valuemax="100"
aria-valuemin="0"
aria-valuenow="80"
class="ant-slider-handle ant-slider-handle-2"
role="slider"
style="left: 80%; transform: translateX(-50%);"
tabindex="0"
/>
</div>
`;
exports[`renders components/slider/demo/editable.tsx extend context correctly 2`] = `[]`;
exports[`renders components/slider/demo/event.tsx extend context correctly 1`] = `
Array [
<div
@ -601,28 +532,6 @@ Array [
style="left: 50%; transform: translateX(-50%);"
tabindex="0"
/>
<div
aria-hidden="true"
class="ant-slider-handle"
style="transform: translateX(-50%); pointer-events: none; visibility: hidden;"
/>
<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"
/>
</div>
</div>
</div>,
]
`;
@ -1152,28 +1061,6 @@ Array [
style="left: 37%; transform: translateX(-50%);"
tabindex="0"
/>
<div
aria-hidden="true"
class="ant-slider-handle"
style="transform: translateX(-50%); pointer-events: none; visibility: hidden;"
/>
<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"
/>
</div>
</div>
<div
class="ant-slider-mark"
>
@ -1543,28 +1430,6 @@ exports[`renders components/slider/demo/multiple.tsx extend context correctly 1`
style="left: 20%; transform: translateX(-50%);"
tabindex="0"
/>
<div
aria-hidden="true"
class="ant-slider-handle"
style="transform: translateX(-50%); pointer-events: none; visibility: hidden;"
/>
<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"
/>
</div>
</div>
</div>
`;
@ -1651,28 +1516,6 @@ Array [
style="right: 50%; transform: translateX(50%);"
tabindex="0"
/>
<div
aria-hidden="true"
class="ant-slider-handle"
style="transform: translateX(50%); pointer-events: none; visibility: hidden;"
/>
<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"
/>
</div>
</div>
</div>,
Reversed: ,
<button
@ -1930,28 +1773,6 @@ Array [
style="bottom: 50%; transform: translateY(50%);"
tabindex="0"
/>
<div
aria-hidden="true"
class="ant-slider-handle"
style="transform: translateY(50%); pointer-events: none; visibility: hidden;"
/>
<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-right"
style="--arrow-x: 0px; --arrow-y: 0px; left: -1000vw; top: -1000vh; box-sizing: border-box;"
>
<div
class="ant-tooltip-arrow"
style="position: absolute; top: 0px; left: 0px;"
/>
<div
class="ant-tooltip-content"
>
<div
class="ant-tooltip-inner"
role="tooltip"
/>
</div>
</div>
</div>
</div>,
<div
@ -2009,28 +1830,6 @@ Array [
style="bottom: 37%; transform: translateY(50%);"
tabindex="0"
/>
<div
aria-hidden="true"
class="ant-slider-handle"
style="transform: translateY(50%); pointer-events: none; visibility: hidden;"
/>
<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-right"
style="--arrow-x: 0px; --arrow-y: 0px; left: -1000vw; top: -1000vh; box-sizing: border-box;"
>
<div
class="ant-tooltip-arrow"
style="position: absolute; top: 0px; left: 0px;"
/>
<div
class="ant-tooltip-content"
>
<div
class="ant-tooltip-inner"
role="tooltip"
/>
</div>
</div>
<div
class="ant-slider-mark"
>

View File

@ -62,11 +62,6 @@ Array [
style="left:50%;transform:translateX(-50%)"
tabindex="0"
/>
<div
aria-hidden="true"
class="ant-slider-handle"
style="left:NaN%;transform:translateX(-50%);pointer-events:none;visibility:hidden"
/>
</div>,
Disabled: ,
<button
@ -153,11 +148,6 @@ Array [
style="left:50%;transform:translateX(-50%)"
tabindex="0"
/>
<div
aria-hidden="true"
class="ant-slider-handle"
style="left:NaN%;transform:translateX(-50%);pointer-events:none;visibility:hidden"
/>
</div>,
<div
style="display:inline-block;height:300px;margin-left:70px"
@ -226,11 +216,6 @@ Array [
style="bottom:50%;transform:translateY(50%)"
tabindex="0"
/>
<div
aria-hidden="true"
class="ant-slider-handle"
style="bottom:NaN%;transform:translateY(50%);pointer-events:none;visibility:hidden"
/>
</div>
</div>,
<div
@ -288,11 +273,6 @@ Array [
style="bottom:37%;transform:translateY(50%)"
tabindex="0"
/>
<div
aria-hidden="true"
class="ant-slider-handle"
style="bottom:NaN%;transform:translateY(50%);pointer-events:none;visibility:hidden"
/>
<div
class="ant-slider-mark"
>
@ -364,10 +344,44 @@ exports[`renders components/slider/demo/draggableTrack.tsx correctly 1`] = `
style="left:50%;transform:translateX(-50%)"
tabindex="0"
/>
</div>
`;
exports[`renders components/slider/demo/editable.tsx correctly 1`] = `
<div
class="ant-slider ant-slider-horizontal"
>
<div
aria-hidden="true"
class="ant-slider-handle"
style="left:NaN%;transform:translateX(-50%);pointer-events:none;visibility:hidden"
class="ant-slider-rail"
/>
<div
class="ant-slider-track ant-slider-track-1"
style="left:20%;width:60%"
/>
<div
class="ant-slider-step"
/>
<div
aria-disabled="false"
aria-orientation="horizontal"
aria-valuemax="100"
aria-valuemin="0"
aria-valuenow="20"
class="ant-slider-handle ant-slider-handle-1"
role="slider"
style="left:20%;transform:translateX(-50%)"
tabindex="0"
/>
<div
aria-disabled="false"
aria-orientation="horizontal"
aria-valuemax="100"
aria-valuemin="0"
aria-valuenow="80"
class="ant-slider-handle ant-slider-handle-2"
role="slider"
style="left:80%;transform:translateX(-50%)"
tabindex="0"
/>
</div>
`;
@ -434,11 +448,6 @@ Array [
style="left:50%;transform:translateX(-50%)"
tabindex="0"
/>
<div
aria-hidden="true"
class="ant-slider-handle"
style="left:NaN%;transform:translateX(-50%);pointer-events:none;visibility:hidden"
/>
</div>,
]
`;
@ -886,11 +895,6 @@ Array [
style="left:37%;transform:translateX(-50%)"
tabindex="0"
/>
<div
aria-hidden="true"
class="ant-slider-handle"
style="left:NaN%;transform:translateX(-50%);pointer-events:none;visibility:hidden"
/>
<div
class="ant-slider-mark"
>
@ -1201,11 +1205,6 @@ exports[`renders components/slider/demo/multiple.tsx correctly 1`] = `
style="left:20%;transform:translateX(-50%)"
tabindex="0"
/>
<div
aria-hidden="true"
class="ant-slider-handle"
style="left:NaN%;transform:translateX(-50%);pointer-events:none;visibility:hidden"
/>
</div>
`;
@ -1271,11 +1270,6 @@ Array [
style="right:50%;transform:translateX(50%)"
tabindex="0"
/>
<div
aria-hidden="true"
class="ant-slider-handle"
style="right:NaN%;transform:translateX(50%);pointer-events:none;visibility:hidden"
/>
</div>,
Reversed: ,
<button
@ -1425,11 +1419,6 @@ Array [
style="bottom:50%;transform:translateY(50%)"
tabindex="0"
/>
<div
aria-hidden="true"
class="ant-slider-handle"
style="bottom:NaN%;transform:translateY(50%);pointer-events:none;visibility:hidden"
/>
</div>
</div>,
<div
@ -1487,11 +1476,6 @@ Array [
style="bottom:37%;transform:translateY(50%)"
tabindex="0"
/>
<div
aria-hidden="true"
class="ant-slider-handle"
style="bottom:NaN%;transform:translateY(50%);pointer-events:none;visibility:hidden"
/>
<div
class="ant-slider-mark"
>

View File

@ -54,6 +54,17 @@ describe('Slider.Tooltip', () => {
expect(tooltipProps().open).toBeFalsy();
});
it('range show the tooltip', async () => {
const { container } = render(<Slider range defaultValue={[0, 100]} />);
const handleEle = container.querySelector('.ant-slider-handle')!;
// Enter
fireEvent.mouseEnter(handleEle);
await waitFakeTimer();
expect(tooltipProps().open).toBeTruthy();
});
it('tooltip should not display when formatter is null or open is false', async () => {
// https://github.com/ant-design/ant-design/issues/48668
const { container: container1 } = render(

View File

@ -0,0 +1,7 @@
## zh-CN
点击添加节点,拖出或者按键删除节点。
## en-US
Click to add a node, drag out or press the key to delete the node.

View File

@ -0,0 +1,10 @@
import React from 'react';
import { Slider } from 'antd';
const App: React.FC = () => {
const [value, setValue] = React.useState([20, 80]);
return <Slider range={{ editable: true }} value={value} onChange={setValue} />;
};
export default App;

View File

@ -27,6 +27,7 @@ To input a value in a range.
<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/editable.tsx" version="5.20.0">Dynamic edit nodes</code>
<code src="./demo/component-token.tsx" debug>Component Token</code>
## API
@ -57,9 +58,10 @@ Common props ref[Common props](/docs/react/common-props)
### range
| Property | Description | Type | Default | Version |
| -------------- | ------------------------------- | ------- | ------- | ------- |
| draggableTrack | Whether range track can be drag | boolean | false | 4.10.0 |
| Property | Description | Type | Default | Version |
| --- | --- | --- | --- | --- |
| draggableTrack | Whether range track can be drag | boolean | false | - |
| editable | Dynamic edit nodes, can't be used with `draggableTrack` | boolean | false | 5.20.0 |
### tooltip

View File

@ -5,6 +5,7 @@ import RcSlider from 'rc-slider';
import type { SliderProps, SliderRef } from 'rc-slider/lib/Slider';
import raf from 'rc-util/lib/raf';
import type { GetProp } from '../_util/type';
import { devUseWarning } from '../_util/warning';
import { ConfigContext } from '../config-provider';
import DisabledContext from '../config-provider/DisabledContext';
@ -110,9 +111,7 @@ export interface SliderRangeProps extends SliderBaseProps {
railStyle?: React.CSSProperties;
}
interface SliderRange {
draggableTrack?: boolean;
}
type SliderRange = Exclude<GetProp<RcSliderProps, 'range'>, boolean>;
export type Opens = { [index: number]: boolean };
@ -212,16 +211,6 @@ const Slider = React.forwardRef<SliderRef, SliderSingleProps | SliderRangeProps>
restProps.reverse = !restProps.reverse;
}
// ============================= Multiple =============================
// Range config
const [mergedRange, draggableTrack] = React.useMemo(() => {
if (!range) {
return [false];
}
return typeof range === 'object' ? [true, range.draggableTrack] : [true, false];
}, [range]);
// ============================= Warning ==============================
// Warning for deprecated usage
if (process.env.NODE_ENV !== 'production') {
@ -255,7 +244,7 @@ const Slider = React.forwardRef<SliderRef, SliderSingleProps | SliderRangeProps>
};
}, []);
const useActiveTooltipHandle = mergedRange && !lockOpen;
const useActiveTooltipHandle = range && !lockOpen;
const handleRender: RcSliderProps['handleRender'] = (node, info) => {
const { index } = info;
@ -338,6 +327,7 @@ const Slider = React.forwardRef<SliderRef, SliderSingleProps | SliderRangeProps>
getPopupContainer={
getTooltipPopupContainer || legacyGetTooltipPopupContainer || getPopupContainer
}
draggingDelete={info.draggingDelete}
>
{cloneNode}
</SliderTooltip>
@ -353,8 +343,7 @@ const Slider = React.forwardRef<SliderRef, SliderSingleProps | SliderRangeProps>
<RcSlider
{...restProps}
step={restProps.step}
range={mergedRange}
draggableTrack={draggableTrack}
range={range}
className={cls}
style={mergedStyle}
disabled={mergedDisabled}

View File

@ -28,6 +28,7 @@ demo:
<code src="./demo/reverse.tsx">反向</code>
<code src="./demo/draggableTrack.tsx">范围可拖拽</code>
<code src="./demo/multiple.tsx">多点组合</code>
<code src="./demo/editable.tsx" version="5.20.0">动态增减节点</code>
<code src="./demo/component-token.tsx" debug>组件 Token</code>
## API
@ -58,9 +59,10 @@ demo:
### range
| 参数 | 说明 | 类型 | 默认值 | 版本 |
| -------------- | -------------------- | ------- | ------ | ------ |
| draggableTrack | 范围刻度是否可被拖拽 | boolean | false | 4.10.0 |
| 参数 | 说明 | 类型 | 默认值 | 版本 |
| -------------- | -------------------------------------------------- | ------- | ------ | ------ |
| draggableTrack | 范围刻度是否可被拖拽 | boolean | false | |
| editable | 启动动态增减节点,不能和 `draggableTrack` 一同使用 | boolean | false | 5.20.0 |
### tooltip

View File

@ -199,6 +199,11 @@ const genBaseStyle: GenerateStyle<SliderToken> = (token) => {
height: handleSize,
outline: 'none',
// Dragging status
'&-dragging-delete': {
opacity: 0,
},
// 扩大选区
'&::before': {
content: '""',

View File

@ -26,20 +26,12 @@
"url": "https://opencollective.com/ant-design"
},
"license": "MIT",
"sideEffects": [
"*.css"
],
"sideEffects": ["*.css"],
"main": "lib/index.js",
"unpkg": "dist/antd.min.js",
"module": "es/index.js",
"typings": "es/index.d.ts",
"files": [
"dist",
"es",
"lib",
"locale",
"BUG_VERSIONS.json"
],
"files": ["dist", "es", "lib", "locale", "BUG_VERSIONS.json"],
"scripts": {
"api-collection": "antd-tools run api-collection",
"authors": "tsx scripts/generate-authors.ts",
@ -105,12 +97,7 @@
"tsc:old": "tsc --noEmit -p tsconfig-old-react.json",
"version": "tsx scripts/generate-version.ts"
},
"browserslist": [
"> 0.5%",
"last 2 versions",
"Firefox ESR",
"not dead"
],
"browserslist": ["> 0.5%", "last 2 versions", "Firefox ESR", "not dead"],
"dependencies": {
"@ant-design/colors": "^7.1.0",
"@ant-design/cssinjs": "^1.21.0",
@ -147,7 +134,7 @@
"rc-resize-observer": "^1.4.0",
"rc-segmented": "~2.3.0",
"rc-select": "~14.15.0",
"rc-slider": "~10.6.2",
"rc-slider": "~11.0.5",
"rc-steps": "~6.0.1",
"rc-switch": "~4.1.0",
"rc-table": "~7.45.7",