feat: update slider

pull/1845/head
tangjinzhou 2020-02-18 16:07:56 +08:00
parent 4efc5099c6
commit f39da916af
21 changed files with 372 additions and 187 deletions

View File

@ -1,5 +1,5 @@
module.exports = {
dev: {
componentName: 'icon', // dev components
componentName: 'slider', // dev components
},
};

View File

@ -101,7 +101,7 @@ module.exports = {
```
```jsx
import { Icon } from 'antd';
import { Icon } from 'ant-design-vue';
import MessageSvg from 'path/to/message.svg'; // path to your '*.svg' file.
new Vue({

View File

@ -23,7 +23,7 @@
更多讨论可参考:[#10353](https://github.com/ant-design/ant-design/issues/10353)。
> ⚠️ 1.2.0 之后我们全量引入了所有图标,导致 antd 默认的包体积有一定增加,我们会在不远的未来增加新的 API 来实现图标的按需使用,更多相关讨论可关注:[#12011](https://github.com/ant-design/ant-design/issues/12011)。在此之前,你可以通过来自社区同学的 [webpack 插件](https://github.com/Beven91/webpack-ant-icon-loader)将图标文件拆分。
> ⚠️ 1.2.0 之后我们全量引入了所有图标,导致 ant-design-vue 默认的包体积有一定增加,我们会在不远的未来增加新的 API 来实现图标的按需使用,更多相关讨论可关注:[#12011](https://github.com/ant-design/ant-design/issues/12011)。在此之前,你可以通过来自社区同学的 [webpack 插件](https://github.com/Beven91/webpack-ant-icon-loader)将图标文件拆分。
其中 `theme`, `component`, `twoToneColor``1.2.x` 版本新增加的属性。最佳实践是给使用的 `<Icon />` 组件传入属性 `theme` 以明确图标的主题风格。例如:

View File

@ -6,15 +6,15 @@ exports[`renders ./components/slider/demo/basic.md correctly 1`] = `
<div class="ant-slider-rail"></div>
<div class="ant-slider-track" style="left: 0%; width: 30%;"></div>
<div class="ant-slider-step"></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="30" class="ant-slider-handle" style="left: 30%;"></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="30" class="ant-slider-handle" style="left: 30%; transform: translateX(-50%);"></div>
<div class="ant-slider-mark"></div>
</div>
<div tabindex="-1" class="ant-slider">
<div class="ant-slider-rail"></div>
<div class="ant-slider-track ant-slider-track-1" style="left: 20%; width: 30%;"></div>
<div class="ant-slider-step"></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="20" class="ant-slider-handle ant-slider-handle-1" style="left: 20%;"></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="50" class="ant-slider-handle ant-slider-handle-2" style="left: 50%;"></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="20" class="ant-slider-handle ant-slider-handle-1" style="left: 20%; transform: translateX(-50%);"></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="50" class="ant-slider-handle ant-slider-handle-2" style="left: 50%; transform: translateX(-50%);"></div>
<div class="ant-slider-mark"></div>
</div>
Disabled: <button type="button" role="switch" class="ant-switch ant-switch-small"><span class="ant-switch-inner"></span></button>
@ -27,15 +27,15 @@ exports[`renders ./components/slider/demo/event.md correctly 1`] = `
<div class="ant-slider-rail"></div>
<div class="ant-slider-track" style="left: 0%; width: 30%;"></div>
<div class="ant-slider-step"></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="30" class="ant-slider-handle" style="left: 30%;"></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="30" class="ant-slider-handle" style="left: 30%; transform: translateX(-50%);"></div>
<div class="ant-slider-mark"></div>
</div>
<div tabindex="-1" class="ant-slider">
<div class="ant-slider-rail"></div>
<div class="ant-slider-track ant-slider-track-1" style="left: 20%; width: 30%;"></div>
<div class="ant-slider-step"></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="20" class="ant-slider-handle ant-slider-handle-1" style="left: 20%;"></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="50" class="ant-slider-handle ant-slider-handle-2" style="left: 50%;"></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="20" class="ant-slider-handle ant-slider-handle-1" style="left: 20%; transform: translateX(-50%);"></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="50" class="ant-slider-handle ant-slider-handle-2" style="left: 50%; transform: translateX(-50%);"></div>
<div class="ant-slider-mark"></div>
</div>
</div>
@ -49,14 +49,14 @@ exports[`renders ./components/slider/demo/icon-slider.md correctly 1`] = `
<div class="ant-slider-rail"></div>
<div class="ant-slider-track" style="left: 0%; width: 0%;"></div>
<div class="ant-slider-step"></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="20" aria-valuenow="0" class="ant-slider-handle" style="left: 0%;"></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="20" aria-valuenow="0" class="ant-slider-handle" style="left: 0%; transform: translateX(-50%);"></div>
<div class="ant-slider-mark"></div>
</div>
<div tabindex="-1" class="ant-slider">
<div class="ant-slider-rail"></div>
<div class="ant-slider-track" style="left: 0%; width: 0%;"></div>
<div class="ant-slider-step"></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="20" aria-valuenow="0" class="ant-slider-handle" style="left: 0%;"></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="20" aria-valuenow="0" class="ant-slider-handle" style="left: 0%; transform: translateX(-50%);"></div>
<div class="ant-slider-mark"></div>
</div> <i aria-label="icon: smile-o" class="anticon anticon-smile-o"><svg viewBox="64 64 896 896" data-icon="smile" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class="">
<path d="M288 421a48 48 0 1 0 96 0 48 48 0 1 0-96 0zm352 0a48 48 0 1 0 96 0 48 48 0 1 0-96 0zM512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm263 711c-34.2 34.2-74 61-118.3 79.8C611 874.2 562.3 884 512 884c-50.3 0-99-9.8-144.8-29.2A370.4 370.4 0 0 1 248.9 775c-34.2-34.2-61-74-79.8-118.3C149.8 611 140 562.3 140 512s9.8-99 29.2-144.8A370.4 370.4 0 0 1 249 248.9c34.2-34.2 74-61 118.3-79.8C413 149.8 461.7 140 512 140c50.3 0 99 9.8 144.8 29.2A370.4 370.4 0 0 1 775.1 249c34.2 34.2 61 74 79.8 118.3C874.2 413 884 461.7 884 512s-9.8 99-29.2 144.8A368.89 368.89 0 0 1 775 775zM664 533h-48.1c-4.2 0-7.8 3.2-8.1 7.4C604 589.9 562.5 629 512 629s-92.1-39.1-95.8-88.6c-.3-4.2-3.9-7.4-8.1-7.4H360a8 8 0 0 0-8 8.4c4.4 84.3 74.5 151.6 160 151.6s155.6-67.3 160-151.6a8 8 0 0 0-8-8.4z"></path>
@ -67,16 +67,16 @@ exports[`renders ./components/slider/demo/icon-slider.md correctly 1`] = `
exports[`renders ./components/slider/demo/input-number.md correctly 1`] = `
<div>
<div class="ant-row">
<div class="ant-col-12">
<div class="ant-col ant-col-12">
<div tabindex="-1" class="ant-slider">
<div class="ant-slider-rail"></div>
<div class="ant-slider-track" style="left: 0%; width: 0%;"></div>
<div class="ant-slider-step"></div>
<div role="slider" tabindex="0" aria-valuemin="1" aria-valuemax="20" aria-valuenow="1" class="ant-slider-handle" style="left: 0%;"></div>
<div role="slider" tabindex="0" aria-valuemin="1" aria-valuemax="20" aria-valuenow="1" class="ant-slider-handle" style="left: 0%; transform: translateX(-50%);"></div>
<div class="ant-slider-mark"></div>
</div>
</div>
<div class="ant-col-4">
<div class="ant-col ant-col-4">
<div class="ant-input-number" style="margin-left: 16px;">
<div class="ant-input-number-handler-wrap"><span class="ant-input-number-handler ant-input-number-handler-up " unselectable="unselectable" role="button" aria-label="Increase Value"><i aria-label="icon: up" class="ant-input-number-handler-up-inner anticon anticon-up"><svg viewBox="64 64 896 896" data-icon="up" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class=""><path d="M890.5 755.3L537.9 269.2c-12.8-17.6-39-17.6-51.7 0L133.5 755.3A8 8 0 0 0 140 768h75c5.1 0 9.9-2.5 12.9-6.6L512 369.8l284.1 391.6c3 4.1 7.8 6.6 12.9 6.6h75c6.5 0 10.3-7.4 6.5-12.7z"></path></svg></i></span><span class="ant-input-number-handler ant-input-number-handler-down ant-input-number-handler-down-disabled" unselectable="unselectable" role="button" aria-label="Decrease Value" aria-disabled="true"><i aria-label="icon: down" class="ant-input-number-handler-down-inner anticon anticon-down"><svg viewBox="64 64 896 896" data-icon="down" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class=""><path d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"></path></svg></i></span></div>
<div role="spinbutton" aria-valuemin="1" aria-valuemax="20" aria-valuenow="1" class="ant-input-number-input-wrap"><input autocomplete="off" max="20" min="1" step="1" class="ant-input-number-input"></div>
@ -84,16 +84,16 @@ exports[`renders ./components/slider/demo/input-number.md correctly 1`] = `
</div>
</div>
<div class="ant-row">
<div class="ant-col-12">
<div class="ant-col ant-col-12">
<div tabindex="-1" class="ant-slider">
<div class="ant-slider-rail"></div>
<div class="ant-slider-track" style="left: 0%; width: 0%;"></div>
<div class="ant-slider-step"></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="1" aria-valuenow="0" class="ant-slider-handle" style="left: 0%;"></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="1" aria-valuenow="0" class="ant-slider-handle" style="left: 0%; transform: translateX(-50%);"></div>
<div class="ant-slider-mark"></div>
</div>
</div>
<div class="ant-col-4">
<div class="ant-col ant-col-4">
<div class="ant-input-number" style="margin-left: 16px;">
<div class="ant-input-number-handler-wrap"><span class="ant-input-number-handler ant-input-number-handler-up " unselectable="unselectable" role="button" aria-label="Increase Value"><i aria-label="icon: up" class="ant-input-number-handler-up-inner anticon anticon-up"><svg viewBox="64 64 896 896" data-icon="up" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class=""><path d="M890.5 755.3L537.9 269.2c-12.8-17.6-39-17.6-51.7 0L133.5 755.3A8 8 0 0 0 140 768h75c5.1 0 9.9-2.5 12.9-6.6L512 369.8l284.1 391.6c3 4.1 7.8 6.6 12.9 6.6h75c6.5 0 10.3-7.4 6.5-12.7z"></path></svg></i></span><span class="ant-input-number-handler ant-input-number-handler-down ant-input-number-handler-down-disabled" unselectable="unselectable" role="button" aria-label="Decrease Value" aria-disabled="true"><i aria-label="icon: down" class="ant-input-number-handler-down-inner anticon anticon-down"><svg viewBox="64 64 896 896" data-icon="down" width="1em" height="1em" fill="currentColor" aria-hidden="true" focusable="false" class=""><path d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"></path></svg></i></span></div>
<div role="spinbutton" aria-valuemin="0" aria-valuemax="1" aria-valuenow="0" class="ant-input-number-input-wrap"><input autocomplete="off" max="1" min="0" step="0.01" class="ant-input-number-input"></div>
@ -110,50 +110,71 @@ exports[`renders ./components/slider/demo/mark.md correctly 1`] = `
<div class="ant-slider-rail"></div>
<div class="ant-slider-track" style="left: 0%; width: 37%;"></div>
<div class="ant-slider-step"><span class="ant-slider-dot ant-slider-dot-active" style="left: 0%;"></span><span class="ant-slider-dot ant-slider-dot-active" style="left: 26%;"></span><span class="ant-slider-dot ant-slider-dot-active" style="left: 37%;"></span><span class="ant-slider-dot" style="left: 100%;"></span></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="37" class="ant-slider-handle" style="left: 37%;"></div>
<div class="ant-slider-mark"><span class="ant-slider-mark-text ant-slider-mark-text-active" style="left: 0%; transform: translateX(-50%);">0°C</span><span class="ant-slider-mark-text ant-slider-mark-text-active" style="left: 26%; transform: translateX(-50%);">26°C</span><span class="ant-slider-mark-text ant-slider-mark-text-active" style="left: 37%; transform: translateX(-50%);">37°C</span><span class="ant-slider-mark-text" style="left: 100%; transform: translateX(-50%); color: rgb(255, 85, 0);"><strong>100°C</strong></span></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="37" class="ant-slider-handle" style="left: 37%; transform: translateX(-50%);"></div>
<div class="ant-slider-mark"><span class="ant-slider-mark-text ant-slider-mark-text-active" style="transform: translateX(-50%); left: 0%;">0°C</span><span class="ant-slider-mark-text ant-slider-mark-text-active" style="transform: translateX(-50%); left: 26%;">26°C</span><span class="ant-slider-mark-text ant-slider-mark-text-active" style="transform: translateX(-50%); left: 37%;">37°C</span><span class="ant-slider-mark-text" style="transform: translateX(-50%); left: 100%; color: rgb(255, 85, 0);"><strong>100°C</strong></span></div>
</div>
<div tabindex="-1" class="ant-slider ant-slider-with-marks">
<div class="ant-slider-rail"></div>
<div class="ant-slider-track ant-slider-track-1" style="left: 26%; width: 11%;"></div>
<div class="ant-slider-step"><span class="ant-slider-dot" style="left: 0%;"></span><span class="ant-slider-dot ant-slider-dot-active" style="left: 26%;"></span><span class="ant-slider-dot ant-slider-dot-active" style="left: 37%;"></span><span class="ant-slider-dot" style="left: 100%;"></span></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="26" class="ant-slider-handle ant-slider-handle-1" style="left: 26%;"></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="37" class="ant-slider-handle ant-slider-handle-2" style="left: 37%;"></div>
<div class="ant-slider-mark"><span class="ant-slider-mark-text" style="left: 0%; transform: translateX(-50%);">0°C</span><span class="ant-slider-mark-text ant-slider-mark-text-active" style="left: 26%; transform: translateX(-50%);">26°C</span><span class="ant-slider-mark-text ant-slider-mark-text-active" style="left: 37%; transform: translateX(-50%);">37°C</span><span class="ant-slider-mark-text" style="left: 100%; transform: translateX(-50%); color: rgb(255, 85, 0);"><strong>100°C</strong></span></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="26" class="ant-slider-handle ant-slider-handle-1" style="left: 26%; transform: translateX(-50%);"></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="37" class="ant-slider-handle ant-slider-handle-2" style="left: 37%; transform: translateX(-50%);"></div>
<div class="ant-slider-mark"><span class="ant-slider-mark-text" style="transform: translateX(-50%); left: 0%;">0°C</span><span class="ant-slider-mark-text ant-slider-mark-text-active" style="transform: translateX(-50%); left: 26%;">26°C</span><span class="ant-slider-mark-text ant-slider-mark-text-active" style="transform: translateX(-50%); left: 37%;">37°C</span><span class="ant-slider-mark-text" style="transform: translateX(-50%); left: 100%; color: rgb(255, 85, 0);"><strong>100°C</strong></span></div>
</div>
<h4>included=false</h4>
<div tabindex="-1" class="ant-slider ant-slider-with-marks">
<div class="ant-slider-rail"></div>
<!---->
<div class="ant-slider-step"><span class="ant-slider-dot" style="left: 0%;"></span><span class="ant-slider-dot" style="left: 26%;"></span><span class="ant-slider-dot ant-slider-dot-active" style="left: 37%;"></span><span class="ant-slider-dot" style="left: 100%;"></span></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="37" class="ant-slider-handle" style="left: 37%;"></div>
<div class="ant-slider-mark"><span class="ant-slider-mark-text" style="left: 0%; transform: translateX(-50%);">0°C</span><span class="ant-slider-mark-text" style="left: 26%; transform: translateX(-50%);">26°C</span><span class="ant-slider-mark-text ant-slider-mark-text-active" style="left: 37%; transform: translateX(-50%);">37°C</span><span class="ant-slider-mark-text" style="left: 100%; transform: translateX(-50%); color: rgb(255, 85, 0);"><strong>100°C</strong></span></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="37" class="ant-slider-handle" style="left: 37%; transform: translateX(-50%);"></div>
<div class="ant-slider-mark"><span class="ant-slider-mark-text" style="transform: translateX(-50%); left: 0%;">0°C</span><span class="ant-slider-mark-text" style="transform: translateX(-50%); left: 26%;">26°C</span><span class="ant-slider-mark-text ant-slider-mark-text-active" style="transform: translateX(-50%); left: 37%;">37°C</span><span class="ant-slider-mark-text" style="transform: translateX(-50%); left: 100%; color: rgb(255, 85, 0);"><strong>100°C</strong></span></div>
</div>
<h4>marks &amp; step</h4>
<div tabindex="-1" class="ant-slider ant-slider-with-marks">
<div class="ant-slider-rail"></div>
<div class="ant-slider-track" style="left: 0%; width: 37%;"></div>
<div class="ant-slider-step"><span class="ant-slider-dot ant-slider-dot-active" style="left: 0%;"></span><span class="ant-slider-dot ant-slider-dot-active" style="left: 26%;"></span><span class="ant-slider-dot ant-slider-dot-active" style="left: 37%;"></span><span class="ant-slider-dot" style="left: 100%;"></span></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="37" class="ant-slider-handle" style="left: 37%;"></div>
<div class="ant-slider-mark"><span class="ant-slider-mark-text ant-slider-mark-text-active" style="left: 0%; transform: translateX(-50%);">0°C</span><span class="ant-slider-mark-text ant-slider-mark-text-active" style="left: 26%; transform: translateX(-50%);">26°C</span><span class="ant-slider-mark-text ant-slider-mark-text-active" style="left: 37%; transform: translateX(-50%);">37°C</span><span class="ant-slider-mark-text" style="left: 100%; transform: translateX(-50%); color: rgb(255, 85, 0);"><strong>100°C</strong></span></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="37" class="ant-slider-handle" style="left: 37%; transform: translateX(-50%);"></div>
<div class="ant-slider-mark"><span class="ant-slider-mark-text ant-slider-mark-text-active" style="transform: translateX(-50%); left: 0%;">0°C</span><span class="ant-slider-mark-text ant-slider-mark-text-active" style="transform: translateX(-50%); left: 26%;">26°C</span><span class="ant-slider-mark-text ant-slider-mark-text-active" style="transform: translateX(-50%); left: 37%;">37°C</span><span class="ant-slider-mark-text" style="transform: translateX(-50%); left: 100%; color: rgb(255, 85, 0);"><strong>100°C</strong></span></div>
</div>
<h4>step=null</h4>
<div tabindex="-1" class="ant-slider ant-slider-with-marks">
<div class="ant-slider-rail"></div>
<div class="ant-slider-track" style="left: 0%; width: 37%;"></div>
<div class="ant-slider-step"><span class="ant-slider-dot ant-slider-dot-active" style="left: 0%;"></span><span class="ant-slider-dot ant-slider-dot-active" style="left: 26%;"></span><span class="ant-slider-dot ant-slider-dot-active" style="left: 37%;"></span><span class="ant-slider-dot" style="left: 100%;"></span></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="37" class="ant-slider-handle" style="left: 37%;"></div>
<div class="ant-slider-mark"><span class="ant-slider-mark-text ant-slider-mark-text-active" style="left: 0%; transform: translateX(-50%);">0°C</span><span class="ant-slider-mark-text ant-slider-mark-text-active" style="left: 26%; transform: translateX(-50%);">26°C</span><span class="ant-slider-mark-text ant-slider-mark-text-active" style="left: 37%; transform: translateX(-50%);">37°C</span><span class="ant-slider-mark-text" style="left: 100%; transform: translateX(-50%); color: rgb(255, 85, 0);"><strong>100°C</strong></span></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="37" class="ant-slider-handle" style="left: 37%; transform: translateX(-50%);"></div>
<div class="ant-slider-mark"><span class="ant-slider-mark-text ant-slider-mark-text-active" style="transform: translateX(-50%); left: 0%;">0°C</span><span class="ant-slider-mark-text ant-slider-mark-text-active" style="transform: translateX(-50%); left: 26%;">26°C</span><span class="ant-slider-mark-text ant-slider-mark-text-active" style="transform: translateX(-50%); left: 37%;">37°C</span><span class="ant-slider-mark-text" style="transform: translateX(-50%); left: 100%; color: rgb(255, 85, 0);"><strong>100°C</strong></span></div>
</div>
</div>
`;
exports[`renders ./components/slider/demo/reverse.md correctly 1`] = `
<div>
<div tabindex="-1" class="ant-slider">
<div class="ant-slider-rail"></div>
<div class="ant-slider-track" style="right: 0%; width: 30%;"></div>
<div class="ant-slider-step"></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="30" class="ant-slider-handle" style="right: 30%; transform: translateX(+50%);"></div>
<div class="ant-slider-mark"></div>
</div>
<div tabindex="-1" class="ant-slider">
<div class="ant-slider-rail"></div>
<div class="ant-slider-track ant-slider-track-1" style="right: 20%; width: 30%;"></div>
<div class="ant-slider-step"></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="20" class="ant-slider-handle ant-slider-handle-1" style="right: 20%; transform: translateX(+50%);"></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="50" class="ant-slider-handle ant-slider-handle-2" style="right: 50%; transform: translateX(+50%);"></div>
<div class="ant-slider-mark"></div>
</div>
Reversed: <button type="button" role="switch" aria-checked="true" class="ant-switch ant-switch-checked ant-switch-small"><span class="ant-switch-inner"></span></button>
</div>
`;
exports[`renders ./components/slider/demo/show-tooltip.md correctly 1`] = `
<div tabindex="-1" class="ant-slider">
<div class="ant-slider-rail"></div>
<div class="ant-slider-track" style="left: 0%; width: 30%;"></div>
<div class="ant-slider-step"></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="30" class="ant-slider-handle ant-tooltip-open" style="left: 30%;"></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="30" class="ant-slider-handle ant-tooltip-open" style="left: 30%; transform: translateX(-50%);"></div>
<div class="ant-slider-mark"></div>
</div>
`;
@ -164,14 +185,14 @@ exports[`renders ./components/slider/demo/tip-formatter.md correctly 1`] = `
<div class="ant-slider-rail"></div>
<div class="ant-slider-track" style="left: 0%; width: 0%;"></div>
<div class="ant-slider-step"></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0" class="ant-slider-handle" style="left: 0%;"></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0" class="ant-slider-handle" style="left: 0%; transform: translateX(-50%);"></div>
<div class="ant-slider-mark"></div>
</div>
<div tabindex="-1" class="ant-slider">
<div class="ant-slider-rail"></div>
<div class="ant-slider-track" style="left: 0%; width: 0%;"></div>
<div class="ant-slider-step"></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0" class="ant-slider-handle" style="left: 0%;"></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0" class="ant-slider-handle" style="left: 0%; transform: translateX(-50%);"></div>
<div class="ant-slider-mark"></div>
</div>
</div>
@ -179,32 +200,32 @@ exports[`renders ./components/slider/demo/tip-formatter.md correctly 1`] = `
exports[`renders ./components/slider/demo/vertical.md correctly 1`] = `
<div style="height: 300px;">
<div style="float: left; height: 300px; margin-left: 70px;">
<div style="display: inline-block; height: 300px; margin-left: 70px;">
<div tabindex="-1" class="ant-slider ant-slider-vertical">
<div class="ant-slider-rail"></div>
<div class="ant-slider-track" style="bottom: 0%; height: 30%;"></div>
<div class="ant-slider-step"></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="30" class="ant-slider-handle" style="bottom: 30%;"></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="30" class="ant-slider-handle" style="bottom: 30%; transform: translateY(+50%);"></div>
<div class="ant-slider-mark"></div>
</div>
</div>
<div style="float: left; height: 300px; margin-left: 70px;">
<div style="display: inline-block; height: 300px; margin-left: 70px;">
<div tabindex="-1" class="ant-slider ant-slider-vertical">
<div class="ant-slider-rail"></div>
<div class="ant-slider-track ant-slider-track-1" style="bottom: 20%; height: 30%;"></div>
<div class="ant-slider-step"></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="20" class="ant-slider-handle ant-slider-handle-1" style="bottom: 20%;"></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="50" class="ant-slider-handle ant-slider-handle-2" style="bottom: 50%;"></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="20" class="ant-slider-handle ant-slider-handle-1" style="bottom: 20%; transform: translateY(+50%);"></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="50" class="ant-slider-handle ant-slider-handle-2" style="bottom: 50%; transform: translateY(+50%);"></div>
<div class="ant-slider-mark"></div>
</div>
</div>
<div style="float: left; height: 300px; margin-left: 70px;">
<div style="display: inline-block; height: 300px; margin-left: 70px;">
<div tabindex="-1" class="ant-slider ant-slider-with-marks ant-slider-vertical">
<div class="ant-slider-rail"></div>
<div class="ant-slider-track ant-slider-track-1" style="bottom: 26%; height: 11%;"></div>
<div class="ant-slider-step"><span class="ant-slider-dot" style="bottom: 0%;"></span><span class="ant-slider-dot ant-slider-dot-active" style="bottom: 26%;"></span><span class="ant-slider-dot ant-slider-dot-active" style="bottom: 37%;"></span><span class="ant-slider-dot" style="bottom: 100%;"></span></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="26" class="ant-slider-handle ant-slider-handle-1" style="bottom: 26%;"></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="37" class="ant-slider-handle ant-slider-handle-2" style="bottom: 37%;"></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="26" class="ant-slider-handle ant-slider-handle-1" style="bottom: 26%; transform: translateY(+50%);"></div>
<div role="slider" tabindex="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="37" class="ant-slider-handle ant-slider-handle-2" style="bottom: 37%; transform: translateY(+50%);"></div>
<div class="ant-slider-mark"><span class="ant-slider-mark-text" style="margin-bottom: -50%; bottom: 0%;">0°C</span><span class="ant-slider-mark-text ant-slider-mark-text-active" style="margin-bottom: -50%; bottom: 26%;">26°C</span><span class="ant-slider-mark-text ant-slider-mark-text-active" style="margin-bottom: -50%; bottom: 37%;">37°C</span><span class="ant-slider-mark-text" style="margin-bottom: -50%; bottom: 100%; color: rgb(255, 85, 0);"><strong>100°C</strong></span></div>
</div>
</div>

View File

@ -2,7 +2,7 @@
exports[`Slider should show tooltip when hovering slider handler 1`] = `
<div>
<div class="ant-tooltip ant-tooltip-placement-top" style="left: -999px; top: -1003px; transform-origin: 50% 4px;">
<div class="ant-tooltip ant-slider-tooltip ant-tooltip-placement-top" style="left: -999px; top: -1003px; transform-origin: 50% 4px;">
<div class="ant-tooltip-content">
<div class="ant-tooltip-arrow"></div>
<div role="tooltip" class="ant-tooltip-inner">30</div>
@ -13,7 +13,7 @@ exports[`Slider should show tooltip when hovering slider handler 1`] = `
exports[`Slider should show tooltip when hovering slider handler 2`] = `
<div>
<div class="ant-tooltip ant-tooltip-placement-top" style="display: none;">
<div class="ant-tooltip ant-slider-tooltip ant-tooltip-placement-top" style="display: none;">
<div class="ant-tooltip-content">
<div class="ant-tooltip-arrow"></div>
<div role="tooltip" class="ant-tooltip-inner">30</div>

View File

@ -1,8 +1,10 @@
import { mount } from '@vue/test-utils';
import { asyncExpect } from '@/tests/utils';
import Slider from '..';
import mountTest from '../../../tests/shared/mountTest';
describe('Slider', () => {
mountTest(Slider);
it('should show tooltip when hovering slider handler', async () => {
const wrapper = mount(Slider, {
propsData: {

View File

@ -7,6 +7,7 @@ import Event from './event.md';
import Mark from './mark.md';
import Vertical from './vertical.md';
import ShowTooltip from './show-tooltip.md';
import Reverse from './reverse';
import CN from '../index.zh-CN.md';
import US from '../index.en-US.md';
@ -40,6 +41,7 @@ export default {
<Mark />
<Vertical />
<ShowTooltip />
<Reverse />
<api>
<template slot="cn">
<CN />

View File

@ -0,0 +1,33 @@
<cn>
#### 反向
设置 `reverse` 可以将滑动条置反。
</cn>
<us>
#### Reverse
Using `reverse` to render slider reversely.
</us>
```tpl
<template>
<div>
<a-slider :defaultValue="30" :reverse="reverse" />
<a-slider range :defaultValue="[20, 50]" :reverse="reverse" />
Reversed: <a-switch size="small" :checked="reverse" @change="handleReverseChange" />
</div>
</template>
<script>
export default {
data() {
return {
reverse: true,
};
},
methods: {
handleReverseChange(reverse) {
this.reverse = reverse;
},
},
};
</script>
```

View File

@ -11,13 +11,13 @@ The vertical Slider.
```tpl
<template>
<div style="height: 300px">
<div style="float:left;height: 300px;marginLeft: 70px">
<div style="display: inline-block;height: 300px;marginLeft: 70px">
<a-slider vertical :defaultValue="30" />
</div>
<div style="float:left;height: 300px;marginLeft: 70px">
<div style="display: inline-block;height: 300px;marginLeft: 70px">
<a-slider vertical range :step="10" :defaultValue="[20, 50]" />
</div>
<div style="float:left;height: 300px;marginLeft: 70px">
<div style="display: inline-block;height: 300px;marginLeft: 70px">
<a-slider vertical range :marks="marks" :defaultValue="[26, 37]" />
</div>
</div>

View File

@ -1,21 +1,24 @@
## API
| Property | Description | Type | Default |
| --- | --- | --- | --- |
| autoFocus | get focus when component mounted | boolean | false |
| defaultValue | The default value of slider. When `range` is `false`, use `number`, otherwise, use `[number, number]` | number\|number\[] | 0 or \[0, 0] |
| disabled | If true, the slider will not be interactable. | boolean | false |
| dots | Whether the thumb can drag over tick only. | boolean | false |
| included | Make effect when `marks` not null`true` means containment and `false` means coordinative | boolean | true |
| marks | Tick mark of Slider, type of key must be `number`, and must in closed interval \[min, max], each mark can declare its own style. | object | { number: string\|VNode } or { number: { style: object, label: string\|VNode } } or { number: () => VNode } |
| max | The maximum value the slider can slide to | number | 100 |
| min | The minimum value the slider can slide to. | number | 0 |
| range | dual thumb mode | boolean | false |
| step | The granularity the slider can step through values. Must greater than 0, and be divided by (max - min) . When `marks` no null, `step` can be `null`. | number\|null | 1 |
| tipFormatter | Slider will pass its value to `tipFormatter`, and display its value in Tooltip, and hide Tooltip when return value is null. | Function\|null | IDENTITY |
| value(v-model) | The value of slider. When `range` is `false`, use `number`, otherwise, use `[number, number]` | number\|number\[] | |
| Property | Description | Type | Default | Version |
| --- | --- | --- | --- | --- |
| autoFocus | get focus when component mounted | boolean | false | |
| defaultValue | The default value of slider. When `range` is `false`, use `number`, otherwise, use `[number, number]` | number\|number\[] | 0 or \[0, 0] | |
| disabled | If true, the slider will not be interactable. | boolean | false | |
| dots | Whether the thumb can drag over tick only. | boolean | false | |
| included | Make effect when `marks` not null`true` means containment and `false` means coordinative | boolean | true | |
| marks | Tick mark of Slider, type of key must be `number`, and must in closed interval \[min, max], each mark can declare its own style. | object | { number: string\|VNode } or { number: { style: object, label: string\|VNode } } or { number: () => VNode } | |
| max | The maximum value the slider can slide to | number | 100 | |
| min | The minimum value the slider can slide to. | number | 0 | |
| range | dual thumb mode | boolean | false | |
| reverse | reverse the component | boolean | false | 1.5.0 |
| step | The granularity the slider can step through values. Must greater than 0, and be divided by (max - min) . When `marks` no null, `step` can be `null`. | number\|null | 1 | |
| tipFormatter | Slider will pass its value to `tipFormatter`, and display its value in Tooltip, and hide Tooltip when return value is null. | Function\|null | IDENTITY | |
| value(v-model) | The value of slider. When `range` is `false`, use `number`, otherwise, use `[number, number]` | number\|number\[] | | |
| vertical | If true, the slider will be vertical. | Boolean | false |
| tooltipVisible | If true, Tooltip will show always, or it will not show anyway, even if dragging or hovering. | Boolean | |
| tooltipPlacement | Set Tooltip display position. Ref [`Tooltip`](/components/tooltip/). | string | | 1.5.0 |
| tooltipVisible | If true, Tooltip will show always, or it will not show anyway, even if dragging or hovering. | Boolean | | |
| getTooltipPopupContainer | The DOM container of the Tooltip, the default behavior is to create a div element in body. | Function | () => document.body | 1.5.0 |
### events

View File

@ -7,6 +7,7 @@ import VcHandle from '../vc-slider/src/Handle';
import Tooltip from '../tooltip';
import Base from '../base';
import { ConfigConsumerProps } from '../config-provider';
import abstractTooltipProps from '../tooltip/abstractTooltipProps';
// export interface SliderMarks {
// [key]: React.ReactNode | {
@ -18,11 +19,12 @@ import { ConfigConsumerProps } from '../config-provider';
// style: PropTypes.object,
// label: PropTypes.any,
// }).loose
const tooltipProps = abstractTooltipProps();
export const SliderProps = () => ({
prefixCls: PropTypes.string,
tooltipPrefixCls: PropTypes.string,
range: PropTypes.bool,
reverse: PropTypes.bool,
min: PropTypes.number,
max: PropTypes.number,
step: PropTypes.oneOfType([PropTypes.number, PropTypes.any]),
@ -35,6 +37,8 @@ export const SliderProps = () => ({
vertical: PropTypes.bool,
tipFormatter: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
tooltipVisible: PropTypes.bool,
tooltipPlacement: tooltipProps.placement,
getTooltipPopupContainer: PropTypes.func,
});
const Slider = {
@ -67,8 +71,17 @@ const Slider = {
},
}));
},
handleWithTooltip(tooltipPrefixCls, { value, dragging, index, directives, on, ...restProps }) {
const { tipFormatter, tooltipVisible } = this.$props;
handleWithTooltip(
tooltipPrefixCls,
prefixCls,
{ value, dragging, index, directives, on, ...restProps },
) {
const {
tipFormatter,
tooltipVisible,
tooltipPlacement,
getTooltipPopupContainer,
} = this.$props;
const { visibles } = this;
const isTipFormatter = tipFormatter ? visibles[index] || dragging : false;
const visible = tooltipVisible || (tooltipVisible === undefined && isTipFormatter);
@ -77,8 +90,10 @@ const Slider = {
prefixCls: tooltipPrefixCls,
title: tipFormatter ? tipFormatter(value) : '',
visible,
placement: 'top',
transitionName: 'fade',
placement: tooltipPlacement || 'top',
transitionName: 'zoom-down',
overlayClassName: `${prefixCls}-tooltip`,
getPopupContainer: getTooltipPopupContainer || (() => document.body),
},
key: index,
};
@ -124,7 +139,7 @@ const Slider = {
...restProps,
prefixCls,
tooltipPrefixCls,
handle: info => this.handleWithTooltip(tooltipPrefixCls, info),
handle: info => this.handleWithTooltip(tooltipPrefixCls, prefixCls, info),
},
ref: 'sliderRef',
on: listeners,
@ -136,7 +151,7 @@ const Slider = {
...restProps,
prefixCls,
tooltipPrefixCls,
handle: info => this.handleWithTooltip(tooltipPrefixCls, info),
handle: info => this.handleWithTooltip(tooltipPrefixCls, prefixCls, info),
},
ref: 'sliderRef',
on: listeners,

View File

@ -1,21 +1,24 @@
## API
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| autoFocus | 自动获取焦点 | boolean | false |
| defaultValue | 设置初始取值。当 `range``false` 时,使用 `number`,否则用 `[number, number]` | number\|number\[] | 0 or \[0, 0] |
| disabled | 值为 `true` 时,滑块为禁用状态 | boolean | false |
| dots | 是否只能拖拽到刻度上 | boolean | false |
| included | `marks` 不为空对象时有效,值为 true 时表示值为包含关系false 表示并列 | boolean | true |
| marks | 刻度标记key 的类型必须为 `number` 且取值在闭区间 \[min, max] 内,每个标签可以单独设置样式 | object | { number: string\|VNode } or { number: { style: object, label: string\|VNode } } or { number: () => VNode } |
| max | 最大值 | number | 100 |
| min | 最小值 | number | 0 |
| range | 双滑块模式 | boolean | false |
| step | 步长,取值必须大于 0并且可被 (max - min) 整除。当 `marks` 不为空对象时,可以设置 `step``null`,此时 Slider 的可选值仅有 marks 标出来的部分。 | number\|null | 1 |
| tipFormatter | Slider 会把当前值传给 `tipFormatter`,并在 Tooltip 中显示 `tipFormatter` 的返回值,若为 null则隐藏 Tooltip。 | Function\|null | IDENTITY |
| value(v-model) | 设置当前取值。当 `range``false` 时,使用 `number`,否则用 `[number, number]` | number\|number\[] | |
| vertical | 值为 `true`Slider 为垂直方向 | Boolean | false |
| tooltipVisible | 值为`true`时Tooltip 将会始终显示;否则始终不显示,哪怕在拖拽及移入时。 | Boolean | |
| 参数 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- |
| autoFocus | 自动获取焦点 | boolean | false | |
| defaultValue | 设置初始取值。当 `range``false` 时,使用 `number`,否则用 `[number, number]` | number\|number\[] | 0 or \[0, 0] | |
| disabled | 值为 `true` 时,滑块为禁用状态 | boolean | false | |
| dots | 是否只能拖拽到刻度上 | boolean | false | |
| included | `marks` 不为空对象时有效,值为 true 时表示值为包含关系false 表示并列 | boolean | true | |
| marks | 刻度标记key 的类型必须为 `number` 且取值在闭区间 \[min, max] 内,每个标签可以单独设置样式 | object | { number: string\|VNode } or { number: { style: object, label: string\|VNode } } or { number: () => VNode } | |
| max | 最大值 | number | 100 | |
| min | 最小值 | number | 0 | |
| range | 双滑块模式 | boolean | false | |
| reverse | 反向坐标轴 | boolean | false | 1.5.0 |
| step | 步长,取值必须大于 0并且可被 (max - min) 整除。当 `marks` 不为空对象时,可以设置 `step``null`,此时 Slider 的可选值仅有 marks 标出来的部分。 | number\|null | 1 | |
| tipFormatter | Slider 会把当前值传给 `tipFormatter`,并在 Tooltip 中显示 `tipFormatter` 的返回值,若为 null则隐藏 Tooltip。 | Function\|null | IDENTITY | |
| value(v-model) | 设置当前取值。当 `range``false` 时,使用 `number`,否则用 `[number, number]` | number\|number\[] | | |
| vertical | 值为 `true`Slider 为垂直方向 | Boolean | false | |
| tooltipPlacement | 设置 Tooltip 展示位置。参考 [`Tooltip`](/components/tooltip/)。 | string | | 1.5.0 |
| tooltipVisible | 值为`true`时Tooltip 将会始终显示;否则始终不显示,哪怕在拖拽及移入时。 | Boolean | | |
| getTooltipPopupContainer | Tooltip 渲染父节点,默认渲染到 body 上。 | Function | () => document.body | 1.5.0 |
### 事件

View File

@ -1,4 +1,4 @@
// base rc-slider 8.6.6
// base rc-slider 8.7.1
import Vue from 'vue';
import ref from 'vue-ref';
import Slider from './src/';

View File

@ -17,6 +17,7 @@ export default {
value: PropTypes.number,
tabIndex: PropTypes.number,
className: PropTypes.string,
reverse: PropTypes.bool,
// handleFocus: PropTypes.func.def(noop),
// handleBlur: PropTypes.func.def(noop),
},
@ -68,14 +69,32 @@ export default {
},
},
render() {
const { prefixCls, vertical, offset, disabled, min, max, value, tabIndex } = getOptionProps(
this,
);
const {
prefixCls,
vertical,
reverse,
offset,
disabled,
min,
max,
value,
tabIndex,
} = getOptionProps(this);
const className = classNames(this.$props.className, {
[`${prefixCls}-handle-click-focused`]: this.clickFocused,
});
const postionStyle = vertical ? { bottom: `${offset}%` } : { left: `${offset}%` };
const positionStyle = vertical
? {
[reverse ? 'top' : 'bottom']: `${offset}%`,
[reverse ? 'bottom' : 'top']: 'auto',
transform: `translateY(+50%)`,
}
: {
[reverse ? 'right' : 'left']: `${offset}%`,
[reverse ? 'left' : 'right']: 'auto',
transform: `translateX(${reverse ? '+' : '-'}50%)`,
};
const ariaProps = {
'aria-valuemin': min,
@ -83,11 +102,15 @@ export default {
'aria-valuenow': value,
'aria-disabled': !!disabled,
};
let _tabIndex = tabIndex || 0;
if (disabled || tabIndex === null) {
_tabIndex = null;
}
const handleProps = {
attrs: {
role: 'slider',
tabIndex: disabled ? null : tabIndex || 0,
tabIndex: _tabIndex,
...ariaProps,
},
class: className,
@ -98,7 +121,7 @@ export default {
mousedown: this.handleMousedown,
},
ref: 'handle',
style: postionStyle,
style: positionStyle,
};
return <div {...handleProps} />;
},

View File

@ -6,6 +6,22 @@ import Track from './common/Track';
import createSlider from './common/createSlider';
import * as utils from './utils';
const trimAlignValue = ({ value, handle, bounds, props }) => {
const { allowCross, pushable } = props;
const thershold = Number(pushable);
const valInRange = utils.ensureValueInRange(value, props);
let valNotConflict = valInRange;
if (!allowCross && handle != null && bounds !== undefined) {
if (handle > 0 && valInRange <= bounds[handle - 1] + thershold) {
valNotConflict = bounds[handle - 1] + thershold;
}
if (handle < bounds.length - 1 && valInRange >= bounds[handle + 1] - thershold) {
valNotConflict = bounds[handle + 1] - thershold;
}
}
return utils.ensureValuePrecision(valNotConflict, props);
};
const rangeProps = {
defaultValue: PropTypes.arrayOf(PropTypes.number),
value: PropTypes.arrayOf(PropTypes.number),
@ -13,10 +29,12 @@ const rangeProps = {
pushable: PropTypes.oneOfType([PropTypes.bool, PropTypes.number]),
allowCross: PropTypes.bool,
disabled: PropTypes.bool,
reverse: PropTypes.bool,
tabIndex: PropTypes.arrayOf(PropTypes.number),
prefixCls: PropTypes.string,
min: PropTypes.number,
max: PropTypes.number,
autoFocus: PropTypes.bool,
};
const Range = {
name: 'Range',
@ -36,7 +54,13 @@ const Range = {
if (value === undefined) {
value = defaultValue;
}
const bounds = value.map((v, i) => this.trimAlignValue(v, i));
const bounds = value.map((v, i) =>
trimAlignValue({
value: v,
handle: i,
props: this.$props,
}),
);
const recent = bounds[0] === max ? 0 : bounds.length - 1;
return {
sHandle: null,
@ -47,37 +71,43 @@ const Range = {
watch: {
value: {
handler(val) {
const { min, max } = this;
this.setChangeValue(val, min, max);
const { min, max, bounds } = this;
this.setChangeValue(val || bounds, min, max);
},
deep: true,
},
min(val) {
const { bounds, max } = this;
this.setChangeValue(bounds, val, max);
const { value = bounds, max } = this;
this.setChangeValue(value, val, max);
},
max(val) {
const { bounds, min } = this;
this.setChangeValue(bounds, min, val);
const { value = bounds, min } = this;
this.setChangeValue(value, min, val);
},
},
methods: {
setChangeValue(value, min, max) {
const { bounds } = this;
const newValue = value || bounds;
const minAmaxProps = {
min,
max,
};
const nextBounds = newValue.map((v, i) => this.trimAlignValue(v, i, minAmaxProps));
const nextBounds = value.map((v, i) =>
trimAlignValue({
value: v,
handle: i,
bounds,
props: this.$props,
}),
);
if (nextBounds.length === bounds.length && nextBounds.every((v, i) => v === bounds[i]))
return;
this.setState({ bounds: nextBounds });
if (value.some(v => utils.isValueOutOfRange(v, minAmaxProps))) {
if (value.some(v => utils.isValueOutOfRange(v, this.$props))) {
const newValues = value.map(v => {
return utils.ensureValueInRange(v, minAmaxProps);
return utils.ensureValueInRange(v, this.$props);
});
this.$emit('change', newValues);
}
@ -86,8 +116,18 @@ const Range = {
const isNotControlled = !hasProp(this, 'value');
if (isNotControlled) {
this.setState(state);
} else if (state.sHandle !== undefined) {
this.setState({ sHandle: state.sHandle });
} else {
const controlledState = {};
['sHandle', 'recent'].forEach(item => {
if (state[item] !== undefined) {
controlledState[item] = state[item];
}
});
if (Object.keys(controlledState).length) {
this.setState(controlledState);
}
}
const data = { ...this.$data, ...state };
@ -119,7 +159,7 @@ const Range = {
onEnd(force) {
const { sHandle } = this;
this.removeDocumentEvents();
if (sHandle || force) {
if (sHandle !== null || force) {
this.$emit('afterChange', this.bounds);
}
this.setState({ sHandle: null });
@ -134,14 +174,20 @@ const Range = {
this.moveTo(value);
},
onKeyboard(e) {
const valueMutator = utils.getKeyboardValueMutator(e);
const { reverse, vertical } = this.$props;
const valueMutator = utils.getKeyboardValueMutator(e, vertical, reverse);
if (valueMutator) {
utils.pauseEvent(e);
const { bounds, sHandle } = this;
const oldValue = bounds[sHandle === null ? this.recent : sHandle];
const mutatedValue = valueMutator(oldValue, this.$props);
const value = this.trimAlignValue(mutatedValue);
const value = trimAlignValue({
value: mutatedValue,
handle: sHandle,
bounds: bounds,
props: this.$props,
});
if (value === oldValue) return;
const isFromKeyboardEvent = true;
this.moveTo(value, isFromKeyboardEvent);
@ -215,6 +261,7 @@ const Range = {
nextHandle = nextBounds.indexOf(value);
}
this.onChange({
recent: nextHandle,
sHandle: nextHandle,
bounds: nextBounds,
});
@ -223,9 +270,11 @@ const Range = {
// so trigger focus will invoke handler's onEnd and another handler's onStart too early,
// cause onBeforeChange and onAfterChange receive wrong value.
// here use setState callback to hackbut not elegant
this.$emit('afterChange', nextBounds);
this.setState({}, () => {
this.handlesRefs[nextHandle].focus();
});
this.onEnd();
}
},
@ -288,11 +337,14 @@ const Range = {
bounds[handle] = nextValue;
return true;
},
trimAlignValue(v, handle, nextProps = {}) {
const mergedProps = { ...this.$props, ...nextProps };
const valInRange = utils.ensureValueInRange(v, mergedProps);
const valNotConflict = this.ensureValueNotConflict(handle, valInRange, mergedProps);
return utils.ensureValuePrecision(valNotConflict, mergedProps);
trimAlignValue(value) {
const { sHandle, bounds } = this;
return trimAlignValue({
value,
handle: sHandle,
bounds,
props: this.$props,
});
},
ensureValueNotConflict(handle, val, { allowCross, pushable: thershold }) {
const state = this.$data || {};
@ -311,7 +363,7 @@ const Range = {
/* eslint-enable eqeqeq */
return val;
},
getTrack({ bounds, prefixCls, vertical, included, offsets, trackStyle }) {
getTrack({ bounds, prefixCls, reverse, vertical, included, offsets, trackStyle }) {
return bounds.slice(0, -1).map((_, index) => {
const i = index + 1;
const trackClassName = classNames({
@ -322,6 +374,7 @@ const Range = {
<Track
class={trackClassName}
vertical={vertical}
reverse={reverse}
included={included}
offset={offsets[i - 1]}
length={offsets[i] - offsets[i - 1]}
@ -341,6 +394,7 @@ const Range = {
disabled,
min,
max,
reverse,
handle,
defaultHandle,
trackStyle,
@ -351,8 +405,12 @@ const Range = {
const offsets = bounds.map(v => this.calcOffset(v));
const handleClassName = `${prefixCls}-handle`;
const handles = bounds.map((v, i) =>
handleGenerator({
const handles = bounds.map((v, i) => {
let _tabIndex = tabIndex[i] || 0;
if (disabled || tabIndex[i] === null) {
_tabIndex = null;
}
return handleGenerator({
className: classNames({
[handleClassName]: true,
[`${handleClassName}-${i + 1}`]: true,
@ -363,9 +421,10 @@ const Range = {
value: v,
dragging: sHandle === i,
index: i,
tabIndex: tabIndex[i] || 0,
tabIndex: _tabIndex,
min,
max,
reverse,
disabled,
style: handleStyle[i],
directives: [
@ -378,11 +437,19 @@ const Range = {
focus: this.onFocus,
blur: this.onBlur,
},
}),
);
});
});
return {
tracks: this.getTrack({ bounds, prefixCls, vertical, included, offsets, trackStyle }),
tracks: this.getTrack({
bounds,
prefixCls,
reverse,
vertical,
included,
offsets,
trackStyle,
}),
handles,
};
},

View File

@ -15,6 +15,7 @@ const Slider = {
disabled: PropTypes.bool,
autoFocus: PropTypes.bool,
tabIndex: PropTypes.number,
reverse: PropTypes.bool,
min: PropTypes.number,
max: PropTypes.number,
},
@ -22,29 +23,21 @@ const Slider = {
const defaultValue = this.defaultValue !== undefined ? this.defaultValue : this.min;
const value = this.value !== undefined ? this.value : defaultValue;
if (utils.isDev()) {
warning(
!hasProp(this, 'minimumTrackStyle'),
'minimumTrackStyle will be deprecate, please use trackStyle instead.',
);
warning(
!hasProp(this, 'maximumTrackStyle'),
'maximumTrackStyle will be deprecate, please use railStyle instead.',
);
}
warning(
!hasProp(this, 'minimumTrackStyle'),
'Slider',
'minimumTrackStyle will be deprecate, please use trackStyle instead.',
);
warning(
!hasProp(this, 'maximumTrackStyle'),
'Slider',
'maximumTrackStyle will be deprecate, please use railStyle instead.',
);
return {
sValue: this.trimAlignValue(value),
dragging: false,
};
},
mounted() {
this.$nextTick(() => {
const { autoFocus, disabled } = this;
if (autoFocus && !disabled) {
this.focus();
}
});
},
watch: {
value: {
handler(val) {
@ -69,21 +62,22 @@ const Slider = {
max,
};
const newValue = value !== undefined ? value : this.sValue;
const nextValue = this.trimAlignValue(newValue, minAmaxProps);
const nextValue = this.trimAlignValue(newValue, this.$props);
if (nextValue === this.sValue) return;
this.setState({ sValue: nextValue });
if (utils.isValueOutOfRange(newValue, minAmaxProps)) {
if (utils.isValueOutOfRange(newValue, this.$props)) {
this.$emit('change', nextValue);
}
},
onChange(state) {
const isNotControlled = !hasProp(this, 'value');
const nextState = state.sValue > this.max ? { ...state, sValue: this.max } : state;
if (isNotControlled) {
this.setState(state);
this.setState(nextState);
}
const changedValue = state.sValue;
const changedValue = nextState.sValue;
this.$emit('change', changedValue);
},
onStart(position) {
@ -117,8 +111,8 @@ const Slider = {
this.onChange({ sValue: value });
},
onKeyboard(e) {
const valueMutator = utils.getKeyboardValueMutator(e);
const { reverse, vertical } = this.$props;
const valueMutator = utils.getKeyboardValueMutator(e, vertical, reverse);
if (valueMutator) {
utils.pauseEvent(e);
const { sValue } = this;
@ -127,6 +121,8 @@ const Slider = {
if (value === sValue) return;
this.onChange({ sValue: value });
this.$emit('afterChange', value);
this.onEnd();
}
},
getLowerBound() {
@ -143,13 +139,14 @@ const Slider = {
const val = utils.ensureValueInRange(v, mergedProps);
return utils.ensureValuePrecision(val, mergedProps);
},
getTrack({ prefixCls, vertical, included, offset, minimumTrackStyle, _trackStyle }) {
getTrack({ prefixCls, reverse, vertical, included, offset, minimumTrackStyle, _trackStyle }) {
return (
<Track
class={`${prefixCls}-track`}
vertical={vertical}
included={included}
offset={0}
reverse={reverse}
length={offset}
style={{
...minimumTrackStyle,
@ -170,6 +167,7 @@ const Slider = {
tabIndex,
min,
max,
reverse,
handle,
defaultHandle,
} = this;
@ -186,6 +184,7 @@ const Slider = {
disabled,
min,
max,
reverse,
index: 0,
tabIndex,
style: handleStyle[0] || handleStyle,
@ -205,6 +204,7 @@ const Slider = {
return {
tracks: this.getTrack({
prefixCls,
reverse,
vertical,
included,
offset,

View File

@ -7,6 +7,7 @@ const Marks = {
const {
className,
vertical,
reverse,
marks,
included,
upperBound,
@ -39,13 +40,15 @@ const Marks = {
const bottomStyle = {
marginBottom: '-50%',
bottom: `${((point - min) / range) * 100}%`,
[reverse ? 'top' : 'bottom']: `${((point - min) / range) * 100}%`,
};
const leftStyle = {
left: `${((point - min) / range) * 100}%`,
transform: `translateX(-50%)`,
msTransform: `translateX(-50%)`,
[reverse ? 'right' : 'left']: reverse
? `${((point - min / 4) / range) * 100}%`
: `${((point - min) / range) * 100}%`,
};
const style = vertical ? bottomStyle : leftStyle;

View File

@ -4,12 +4,13 @@ import warning from '../../../_util/warning';
const calcPoints = (vertical, marks, dots, step, min, max) => {
warning(
dots ? step > 0 : true,
'Slider',
'`Slider[step]` should be a positive number in order to make Slider[dots] work.',
);
const points = Object.keys(marks)
.map(parseFloat)
.sort((a, b) => a - b);
if (dots) {
if (dots && step) {
for (let i = min; i <= max; i += step) {
if (points.indexOf(i) === -1) {
points.push(i);
@ -25,6 +26,7 @@ const Steps = {
const {
prefixCls,
vertical,
reverse,
marks,
dots,
step,
@ -43,7 +45,9 @@ const Steps = {
const isActived =
(!included && point === upperBound) ||
(included && point <= upperBound && point >= lowerBound);
let style = vertical ? { bottom: offset, ...dotStyle } : { left: offset, ...dotStyle };
let style = vertical
? { ...dotStyle, [reverse ? 'top' : 'bottom']: offset }
: { ...dotStyle, [reverse ? 'right' : 'left']: offset };
if (isActived) {
style = { ...style, ...activeDotStyle };
}
@ -51,6 +55,7 @@ const Steps = {
const pointClassName = classNames({
[`${prefixCls}-dot`]: true,
[`${prefixCls}-dot-active`]: isActived,
[`${prefixCls}-dot-reverse`]: reverse,
});
return <span class={pointClassName} style={style} key={point} />;

View File

@ -1,17 +1,19 @@
/* eslint-disable */
const Track = {
functional: true,
render(createElement, context) {
const { included, vertical, offset, length } = context.props;
render(h, context) {
const { included, vertical, offset, length, reverse } = context.props;
const { style, class: className } = context.data;
const positonStyle = vertical
? {
bottom: `${offset}%`,
[reverse ? 'top' : 'bottom']: `${offset}%`,
[reverse ? 'bottom' : 'top']: 'auto',
height: `${length}%`,
}
: {
left: `${offset}%`,
[reverse ? 'right' : 'left']: `${offset}%`,
[reverse ? 'left' : 'right']: 'auto',
width: `${length}%`,
};

View File

@ -23,6 +23,7 @@ export default function createSlider(Component) {
handle: PropTypes.func,
dots: PropTypes.bool,
vertical: PropTypes.bool,
reverse: PropTypes.bool,
minimumTrackStyle: PropTypes.object, // just for compatibility, will be deperecate
maximumTrackStyle: PropTypes.object, // just for compatibility, will be deperecate
handleStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.arrayOf(PropTypes.object)]),
@ -45,23 +46,11 @@ export default function createSlider(Component) {
max: 100,
step: 1,
marks: {},
// handle ({ index, ref, className, style, ...restProps }) {
// delete restProps.dragging
// const handleProps = {
// props: {
// ...restProps,
// },
// class: className,
// style,
// key: index,
// ref,
// }
// return <Handle {...handleProps} />
// },
included: true,
disabled: false,
dots: false,
vertical: false,
reverse: false,
trackStyle: [{}],
handleStyle: [{}],
railStyle: {},
@ -69,16 +58,15 @@ export default function createSlider(Component) {
activeDotStyle: {},
}),
data() {
if (utils.isDev()) {
const { step, max, min } = this;
const isPointDiffEven = isFinite(max - min) ? (max - min) % step === 0 : true; // eslint-disable-line
warning(
step && Math.floor(step) === step ? isPointDiffEven : true,
'Slider[max] - Slider[min] (%s) should be a multiple of Slider[step] (%s)',
max - min,
step,
);
}
const { step, max, min } = this;
const isPointDiffEven = isFinite(max - min) ? (max - min) % step === 0 : true; // eslint-disable-line
warning(
step && Math.floor(step) === step ? isPointDiffEven : true,
'Slider',
'Slider[max] - Slider[min] (%s) should be a multiple of Slider[step] (%s)',
max - min,
step,
);
this.handlesRefs = {};
return {};
},
@ -87,6 +75,10 @@ export default function createSlider(Component) {
// Snapshot testing cannot handle refs, so be sure to null-check this.
this.document = this.$refs.sliderRef && this.$refs.sliderRef.ownerDocument;
// this.setHandleRefs()
const { autoFocus, disabled } = this;
if (autoFocus && !disabled) {
this.focus();
}
});
},
beforeDestroy() {
@ -191,13 +183,16 @@ export default function createSlider(Component) {
onClickMarkLabel(e, value) {
e.stopPropagation();
this.onChange({ sValue: value });
this.onEnd(true);
this.setState({ sValue: value }, () => this.onEnd(true));
},
getSliderStart() {
const slider = this.$refs.sliderRef;
const { vertical, reverse } = this;
const rect = slider.getBoundingClientRect();
return this.vertical ? rect.top : rect.left + window.pageXOffset;
if (vertical) {
return reverse ? rect.bottom : rect.top;
}
return window.pageXOffset + (reverse ? rect.right : rect.left);
},
getSliderLength() {
const slider = this.$refs.sliderRef;
@ -247,7 +242,8 @@ export default function createSlider(Component) {
return value;
},
calcValueByPos(position) {
const pixelOffset = position - this.getSliderStart();
const sign = this.reverse ? -1 : +1;
const pixelOffset = sign * (position - this.getSliderStart());
const nextValue = this.trimAlignValue(this.calcValue(pixelOffset));
return nextValue;
},
@ -269,6 +265,7 @@ export default function createSlider(Component) {
included,
disabled,
vertical,
reverse,
min,
max,
maximumTrackStyle,
@ -292,6 +289,7 @@ export default function createSlider(Component) {
upperBound: this.getUpperBound(),
max,
min,
reverse,
className: `${prefixCls}-mark`,
},
on: {
@ -321,6 +319,7 @@ export default function createSlider(Component) {
<Steps
prefixCls={prefixCls}
vertical={vertical}
reverse={reverse}
marks={marks}
dots={dots}
step={step}

View File

@ -1,9 +1,5 @@
import keyCode from '../../_util/KeyCode';
export function isDev() {
return process.env.NODE_ENV !== 'production';
}
export function isEventFromHandle(e, handles) {
try {
return Object.keys(handles).some(
@ -22,10 +18,12 @@ export function isNotTouchEvent(e) {
return e.touches.length > 1 || (e.type.toLowerCase() === 'touchend' && e.touches.length > 0);
}
export function getClosestPoint(val, { marks, step, min }) {
export function getClosestPoint(val, { marks, step, min, max }) {
const points = Object.keys(marks).map(parseFloat);
if (step !== null) {
const closestStep = Math.round((val - min) / step) * step + min;
const maxSteps = Math.floor((max - min) / step);
const steps = Math.min((val - min) / step, maxSteps);
const closestStep = Math.round(steps) * step + min;
points.push(closestStep);
}
const diffs = points.map(point => Math.abs(val - point));
@ -102,15 +100,23 @@ export function calculateNextValue(func, value, props) {
return value;
}
export function getKeyboardValueMutator(e) {
export function getKeyboardValueMutator(e, vertical, reverse) {
const increase = 'increase';
const decrease = 'decrease';
let method = increase;
switch (e.keyCode) {
case keyCode.UP:
method = vertical && reverse ? decrease : increase;
break;
case keyCode.RIGHT:
return (value, props) => calculateNextValue('increase', value, props);
method = !vertical && reverse ? decrease : increase;
break;
case keyCode.DOWN:
method = vertical && reverse ? increase : decrease;
break;
case keyCode.LEFT:
return (value, props) => calculateNextValue('decrease', value, props);
method = !vertical && reverse ? increase : decrease;
break;
case keyCode.END:
return (value, props) => props.max;
@ -124,4 +130,5 @@ export function getKeyboardValueMutator(e) {
default:
return undefined;
}
return (value, props) => calculateNextValue(method, value, props);
}