diff --git a/assets/index.less b/assets/index.less index 3c718e93d..aa10b3d3a 100644 --- a/assets/index.less +++ b/assets/index.less @@ -38,7 +38,8 @@ border-radius: @border-radius-base; } - &-track { + &-track, + &-tracks { position: absolute; height: 4px; background-color: tint(@primary-color, 60%); diff --git a/docs/demo/mulitple.md b/docs/demo/mulitple.md new file mode 100644 index 000000000..5159ac470 --- /dev/null +++ b/docs/demo/mulitple.md @@ -0,0 +1,8 @@ +--- +title: Multiple +nav: + title: Demo + path: /demo +--- + + diff --git a/docs/examples/multiple.tsx b/docs/examples/multiple.tsx new file mode 100644 index 000000000..baca5e0cb --- /dev/null +++ b/docs/examples/multiple.tsx @@ -0,0 +1,30 @@ +/* eslint react/no-multi-comp: 0, no-console: 0 */ +import Slider from 'rc-slider'; +import React from 'react'; +import '../../assets/index.less'; + +const style = { width: 400, margin: 50 }; + +function log(value) { + console.log(value); +} + +export default () => ( +
+
+ +
+
+); diff --git a/src/Handles/Handle.tsx b/src/Handles/Handle.tsx index 60d2c74c5..fd77771dd 100644 --- a/src/Handles/Handle.tsx +++ b/src/Handles/Handle.tsx @@ -1,9 +1,9 @@ -import * as React from 'react'; -import classNames from 'classnames'; +import cls from 'classnames'; import KeyCode from 'rc-util/lib/KeyCode'; +import * as React from 'react'; import SliderContext from '../context'; -import { getDirectionStyle, getIndex } from '../util'; import type { OnStartMove } from '../interface'; +import { getDirectionStyle, getIndex } from '../util'; interface RenderProps { index: number; @@ -48,6 +48,8 @@ const Handle = React.forwardRef((props: HandleProps, ref: React.Ref { className?: string; style?: React.CSSProperties; + classNames?: SliderClassNames; + styles?: SliderStyles; + // Status disabled?: boolean; keyboard?: boolean; @@ -70,8 +77,11 @@ export interface SliderProps { // Style included?: boolean; startPoint?: number; + /** @deprecated Please use `styles.track` instead */ trackStyle?: React.CSSProperties | React.CSSProperties[]; + /** @deprecated Please use `styles.handle` instead */ handleStyle?: React.CSSProperties | React.CSSProperties[]; + /** @deprecated Please use `styles.rail` instead */ railStyle?: React.CSSProperties; dotStyle?: React.CSSProperties | ((dotValue: number) => React.CSSProperties); activeDotStyle?: React.CSSProperties | ((dotValue: number) => React.CSSProperties); @@ -100,6 +110,8 @@ const Slider = React.forwardRef((props: SliderProps, ref: React.Ref) prefixCls = 'rc-slider', className, style, + classNames, + styles, // Status disabled = false, @@ -456,6 +468,8 @@ const Slider = React.forwardRef((props: SliderProps, ref: React.Ref) ariaLabelForHandle, ariaLabelledByForHandle, ariaValueTextFormatterForHandle, + styles: styles || {}, + classNames: classNames || {}, }), [ mergedMin, @@ -472,6 +486,8 @@ const Slider = React.forwardRef((props: SliderProps, ref: React.Ref) ariaLabelForHandle, ariaLabelledByForHandle, ariaValueTextFormatterForHandle, + styles, + classNames, ], ); @@ -480,7 +496,7 @@ const Slider = React.forwardRef((props: SliderProps, ref: React.Ref)
) style={style} onMouseDown={onSliderMouseDown} > -
+
{ if (!range) { // null value do not have track @@ -35,7 +37,7 @@ export default function Tracks(props: TrackProps) { } // Multiple - const list = []; + const list: { start: number; end: number }[] = []; for (let i = 0; i < values.length - 1; i += 1) { list.push({ @@ -47,17 +49,39 @@ export default function Tracks(props: TrackProps) { return list; }, [values, range, startPoint, min]); - return (included - ? trackList.map(({ start, end }, index) => ( + // ========================== Render ========================== + let tracksNode: React.ReactElement = null; + + if (classNames.tracks || styles.tracks) { + tracksNode = ( + + ); + } + + return (included ? ( + <> + {tracksNode} + {trackList.map(({ start, end }, index) => ( - )) - : null) as unknown as React.ReactElement; + ))} + + ) : null) as unknown as React.ReactElement; } diff --git a/src/context.ts b/src/context.ts index 0bd2e20b7..99b398ca5 100644 --- a/src/context.ts +++ b/src/context.ts @@ -1,5 +1,5 @@ import * as React from 'react'; -import type { AriaValueFormat, Direction } from './interface'; +import type { AriaValueFormat, Direction, SliderClassNames, SliderStyles } from './interface'; export interface SliderContextProps { min: number; @@ -16,6 +16,8 @@ export interface SliderContextProps { ariaLabelForHandle?: string | string[]; ariaLabelledByForHandle?: string | string[]; ariaValueTextFormatterForHandle?: AriaValueFormat | AriaValueFormat[]; + classNames: SliderClassNames; + styles: SliderStyles; } const SliderContext = React.createContext({ @@ -27,6 +29,8 @@ const SliderContext = React.createContext({ includedEnd: 0, tabIndex: 0, keyboard: true, + styles: {}, + classNames: {}, }); export default SliderContext; diff --git a/src/interface.ts b/src/interface.ts index 3bee691c3..0a52e22f3 100644 --- a/src/interface.ts +++ b/src/interface.ts @@ -5,3 +5,9 @@ export type Direction = 'rtl' | 'ltr' | 'ttb' | 'btt'; export type OnStartMove = (e: React.MouseEvent | React.TouchEvent, valueIndex: number) => void; export type AriaValueFormat = (value: number) => string; + +export type SemanticName = 'tracks' | 'track' | 'rail' | 'handle'; + +export type SliderClassNames = Partial>; + +export type SliderStyles = Partial>; diff --git a/tests/Range.test.js b/tests/Range.test.js index 5e5a25840..0d45511d6 100644 --- a/tests/Range.test.js +++ b/tests/Range.test.js @@ -1,11 +1,11 @@ /* eslint-disable max-len, no-undef, react/no-string-refs, no-param-reassign, max-classes-per-file */ -import React from 'react'; -import keyCode from 'rc-util/lib/KeyCode'; -import { render, fireEvent, createEvent } from '@testing-library/react'; import '@testing-library/jest-dom'; +import { createEvent, fireEvent, render } from '@testing-library/react'; +import keyCode from 'rc-util/lib/KeyCode'; import { spyElementPrototypes } from 'rc-util/lib/test/domHook'; -import Slider from '../src/'; import { resetWarned } from 'rc-util/lib/warning'; +import React from 'react'; +import Slider from '../src/'; describe('Range', () => { let container; @@ -546,4 +546,52 @@ describe('Range', () => { expect(container.querySelector('.rc-slider-track-draggable')).toBeTruthy(); expect(containerVertical.querySelector('.rc-slider-track-draggable')).toBeTruthy(); }); + + it('styles', () => { + const { container } = render( + , + ); + + expect(container.querySelector('.rc-slider-tracks')).toHaveStyle({ + backgroundColor: '#654321', + }); + expect(container.querySelector('.rc-slider-track')).toHaveStyle({ + backgroundColor: '#123456', + }); + expect(container.querySelector('.rc-slider-handle')).toHaveStyle({ + backgroundColor: '#112233', + }); + expect(container.querySelector('.rc-slider-rail')).toHaveStyle({ + backgroundColor: '#332211', + }); + }); + + it('classNames', () => { + const { container } = render( + , + ); + + expect(container.querySelector('.rc-slider-tracks')).toHaveClass('my-tracks'); + expect(container.querySelector('.rc-slider-track')).toHaveClass('my-track'); + expect(container.querySelector('.rc-slider-handle')).toHaveClass('my-handle'); + expect(container.querySelector('.rc-slider-rail')).toHaveClass('my-rail'); + }); }); diff --git a/tsconfig.json b/tsconfig.json index bb919a4ce..7d388903b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,7 +3,7 @@ "target": "esnext", "moduleResolution": "node", "baseUrl": "./", - "jsx": "preserve", + "jsx": "react", "declaration": true, "skipLibCheck": true, "esModuleInterop": true,