├── .github
└── workflows
│ └── release.yml
├── .gitignore
├── .storybook
└── main.js
├── .travis.yml
├── CHANGELOG.md
├── LICENSE
├── README.md
├── babel.config.js
├── caitou.yml
├── index.d.ts
├── package.json
├── prettier.config.js
├── rollup.config.js
├── src
├── __tests__
│ └── slider.js
├── index.js
├── slider.js
├── styles.js
└── utils.js
├── stories
└── InputSlider.stories.js
└── yarn.lock
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: release
2 | on:
3 | push:
4 | branches: [master]
5 | jobs:
6 | release:
7 | runs-on: ubuntu-latest
8 | steps:
9 | - uses: actions/checkout@v2
10 | - run: yarn install
11 | - run: yarn build-storybook
12 | - uses: caitouyun/actions@master
13 | with:
14 | args: caitou deploy --git
15 | env:
16 | CAITOU_TOKEN: ${{ secrets.CAITOU_TOKEN }}
17 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | dist
2 | coverage
3 | node_modules
4 |
--------------------------------------------------------------------------------
/.storybook/main.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | stories: ['../stories/**/*.stories.js'],
3 | addons: ['@storybook/addon-actions', '@storybook/addon-links'],
4 | };
5 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - node
4 | cache: yarn
5 | after_success:
6 | - bash <(curl -s https://codecov.io/bash)
7 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ## [Unreleased]
4 |
5 | ## [6.0.1]
6 |
7 | - update react peer deps
8 |
9 | ## [6.0.0]
10 |
11 | - upgrade rollup
12 | - allow mouse down and touch start at any position on the track [#63](https://github.com/swiftcarrot/react-input-slider/pull/63)
13 |
14 | ## [5.1.7]
15 |
16 | - export `InputSliderProps`
17 |
18 | ## [5.1.6]
19 |
20 | - improve styling for thumb
21 | - fix typescript definition
22 | - thumb with pointer cursor by default
23 |
24 | ## [5.1.5]
25 |
26 | - add reverse support
27 |
28 | ## [5.1.4]
29 |
30 | - add type definition file
31 |
32 | ## [5.1.3]
33 |
34 | - add `props.dragStart` support
35 |
36 | ## [5.1.2]
37 |
38 | - format changelog
39 |
40 | ## [5.1.1]
41 |
42 | - event disabled fix
43 |
44 | ## [5.1.0]
45 |
46 | - add `props.disabled` and `styles.disabled` support
47 |
48 | ## [5.0.7]
49 |
50 | - `sideEffects: false` in `package.json` for webpack tree shaking
51 |
52 | ## [5.0.6]
53 |
54 | - Fix wrong thumb's top position calculation
55 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Wang Zuo
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # react-input-slider
2 |
3 | [](https://www.npmjs.com/package/react-input-slider)
4 | [](https://www.npmjs.com/package/react-input-slider)
5 | [](https://travis-ci.org/swiftcarrot/react-input-slider)
6 | [](https://codecov.io/gh/swiftcarrot/react-input-slider)
7 | [](https://github.com/prettier/prettier)
8 |
9 | React slider component
10 |
11 | ### Installation
12 |
13 | ```sh
14 | yarn add react-input-slider
15 | npm install react-input-slider --save
16 | ```
17 |
18 | ### Storybook Demo
19 |
20 | [http://react-input-slider.caitouyun.com](http://react-input-slider.caitouyun.com)
21 |
22 | ### Usage
23 |
24 | ```javascript
25 | import React from 'react';
26 | import Slider from 'react-input-slider';
27 |
28 | function App() {
29 | const [state, setState] = useState({ x: 10, y: 10 });
30 |
31 | return (
32 |
33 | ({state.x}, {state.y})
34 |
35 | setState(state => ({ ...state, x }))}
39 | />
40 | setState(state => ({ ...state, y }))} />
41 |
42 | );
43 | }
44 | ```
45 |
46 | ### Styling
47 |
48 | v5 introduces a new styling api powered by [emotion](https://emotion.sh/)
49 |
50 | ```javascript
51 |
68 | ```
69 |
70 | ### Props
71 |
72 | | Name | Type | Description | Default |
73 | | ----------- | -------- | ------------------------------------- | ------- |
74 | | axis | string | type of slider (`'x'`, `'y'`, `'xy'`) | `'x'` |
75 | | x | number | value of x | `50` |
76 | | xmax | number | max of x | `100` |
77 | | xmin | number | min of x | `0` |
78 | | y | number | value of y | `50` |
79 | | ymax | number | max of y | `100` |
80 | | ymin | number | min of y | `0` |
81 | | xstep | number | step of x | `1` |
82 | | ystep | number | step of y | `1` |
83 | | onChange | function | handleChange | `null` |
84 | | onDragStart | function | handleDragStart | `null` |
85 | | onDragEnd | function | handleDragEnd | `null` |
86 | | disabled | boolean | input disabled | false |
87 | | xreverse | boolean | reverse on x | false |
88 | | yreverse | boolean | reverse on y | false |
89 |
90 | ### License
91 |
92 | MIT
93 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ['swiftcarrot']
3 | };
4 |
--------------------------------------------------------------------------------
/caitou.yml:
--------------------------------------------------------------------------------
1 | site: react-input-slider
2 | public: storybook-static
3 | force_ssl: true
4 |
--------------------------------------------------------------------------------
/index.d.ts:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { Interpolation } from '@emotion/serialize';
3 |
4 | export interface InputSliderProps {
5 | axis?: 'x' | 'y' | 'xy';
6 | x?: number;
7 | xmax?: number;
8 | xmin?: number;
9 | y?: number;
10 | ymax?: number;
11 | ymin?: number;
12 | xstep?: number;
13 | ystep?: number;
14 | onChange?: (values: { x: number; y: number }) => void;
15 | onDragStart?: (e: MouseEvent) => void;
16 | onDragEnd?: (e: MouseEvent) => void;
17 | disabled?: boolean;
18 | xreverse?: boolean;
19 | yreverse?: boolean;
20 | styles?: {
21 | track?: Interpolation;
22 | active?: Interpolation;
23 | thumb?: Interpolation;
24 | disabled?: Interpolation;
25 | };
26 | }
27 |
28 | export default class InputSlider extends React.Component {}
29 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-input-slider",
3 | "version": "6.0.1",
4 | "description": "React input slider component",
5 | "main": "dist/index.cjs.js",
6 | "module": "dist/index.esm.js",
7 | "types": "index.d.ts",
8 | "sideEffects": false,
9 | "scripts": {
10 | "build": "rollup -c",
11 | "test": "NODE_ENV=production jest --coverage",
12 | "prepublishOnly": "npm test && npm run build",
13 | "watch": "rollup -cw",
14 | "storybook": "start-storybook -p 6006",
15 | "build-storybook": "build-storybook"
16 | },
17 | "repository": {
18 | "type": "git",
19 | "url": "git+https://github.com/swiftcarrot/react-input-slider.git"
20 | },
21 | "bugs": {
22 | "url": "https://github.com/swiftcarrot/react-input-slider/issues"
23 | },
24 | "keywords": [
25 | "input",
26 | "react",
27 | "react-component",
28 | "slider"
29 | ],
30 | "files": [
31 | "index.d.ts",
32 | "dist"
33 | ],
34 | "author": "Wang Zuo (https://swiftcarrot.com)",
35 | "homepage": "https://swiftcarrot.dev/react-input-slider",
36 | "license": "MIT",
37 | "dependencies": {
38 | "@babel/runtime": "^7.9.2",
39 | "@emotion/core": "^10.0.14"
40 | },
41 | "devDependencies": {
42 | "@babel/core": "^7.9.0",
43 | "@rollup/plugin-babel": "^5.0.0",
44 | "@rollup/plugin-commonjs": "^11.1.0",
45 | "@rollup/plugin-node-resolve": "^7.1.3",
46 | "@storybook/addon-actions": "^5.3.18",
47 | "@storybook/addon-links": "^5.3.18",
48 | "@storybook/addons": "^5.3.18",
49 | "@storybook/react": "^5.3.18",
50 | "babel-jest": "^25.2.4",
51 | "babel-loader": "^8.1.0",
52 | "babel-preset-swiftcarrot": "^1.1.0",
53 | "jest": "^25.2.4",
54 | "prettier": "^1.19.1",
55 | "react": "^16.8.6",
56 | "react-dom": "^16.8.6",
57 | "react-test-renderer": "^16.8.6",
58 | "rollup": "^2.8.2"
59 | },
60 | "peerDependencies": {
61 | "react": ">=16",
62 | "react-dom": ">=16"
63 | },
64 | "jest": {
65 | "collectCoverage": true,
66 | "collectCoverageFrom": [
67 | "src/**/*.js"
68 | ]
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/prettier.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | singleQuote: true
3 | };
4 |
--------------------------------------------------------------------------------
/rollup.config.js:
--------------------------------------------------------------------------------
1 | import babel from '@rollup/plugin-babel';
2 | import commonjs from '@rollup/plugin-commonjs';
3 | import nodeResolve from '@rollup/plugin-node-resolve';
4 | import pkg from './package.json';
5 |
6 | const input = './src/index.js';
7 | const external = id => !id.startsWith('.') && !id.startsWith('/');
8 |
9 | export default [
10 | {
11 | input,
12 | output: {
13 | file: pkg.main,
14 | format: 'cjs'
15 | },
16 | external,
17 | plugins: [
18 | babel({
19 | babelHelpers: 'runtime',
20 | plugins: ['@babel/transform-runtime']
21 | }),
22 | nodeResolve(),
23 | commonjs()
24 | ]
25 | },
26 |
27 | {
28 | input,
29 | output: {
30 | file: pkg.module,
31 | format: 'esm'
32 | },
33 | external,
34 | plugins: [
35 | babel({
36 | babelHelpers: 'runtime',
37 | plugins: [['@babel/transform-runtime', { useESModules: true }]]
38 | }),
39 | nodeResolve(),
40 | commonjs()
41 | ]
42 | }
43 | ];
44 |
--------------------------------------------------------------------------------
/src/__tests__/slider.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import renderer from 'react-test-renderer';
3 | import Slider from '../slider';
4 |
5 | test('x', () => {
6 | const component = renderer.create();
7 | expect(component.toJSON()).toMatchInlineSnapshot(`
8 |
39 | `);
40 | });
41 |
42 | test('y', () => {
43 | const component = renderer.create();
44 | expect(component.toJSON()).toMatchInlineSnapshot(`
45 |
76 | `);
77 | });
78 |
79 | test('xy', () => {
80 | const component = renderer.create();
81 | expect(component.toJSON()).toMatchInlineSnapshot(`
82 |
109 | `);
110 | });
111 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | export default from './slider';
2 |
--------------------------------------------------------------------------------
/src/slider.js:
--------------------------------------------------------------------------------
1 | /** @jsx jsx */
2 | import { jsx } from '@emotion/core';
3 | import { useRef } from 'react';
4 | import { getClientPosition } from './utils';
5 | import defaultStyles from './styles';
6 |
7 | const Slider = ({
8 | disabled,
9 | axis,
10 | x,
11 | y,
12 | xmin,
13 | xmax,
14 | ymin,
15 | ymax,
16 | xstep,
17 | ystep,
18 | onChange,
19 | onDragStart,
20 | onDragEnd,
21 | xreverse,
22 | yreverse,
23 | styles: customStyles,
24 | ...props
25 | }) => {
26 | const container = useRef(null);
27 | const handle = useRef(null);
28 | const start = useRef({});
29 | const offset = useRef({});
30 |
31 | function getPosition() {
32 | let top = ((y - ymin) / (ymax - ymin)) * 100;
33 | let left = ((x - xmin) / (xmax - xmin)) * 100;
34 |
35 | if (top > 100) top = 100;
36 | if (top < 0) top = 0;
37 | if (axis === 'x') top = 0;
38 |
39 | if (left > 100) left = 100;
40 | if (left < 0) left = 0;
41 | if (axis === 'y') left = 0;
42 |
43 | return { top, left };
44 | }
45 |
46 | function change({ top, left }) {
47 | if (!onChange) return;
48 |
49 | const { width, height } = container.current.getBoundingClientRect();
50 | let dx = 0;
51 | let dy = 0;
52 |
53 | if (left < 0) left = 0;
54 | if (left > width) left = width;
55 | if (top < 0) top = 0;
56 | if (top > height) top = height;
57 |
58 | if (axis === 'x' || axis === 'xy') {
59 | dx = (left / width) * (xmax - xmin);
60 | }
61 |
62 | if (axis === 'y' || axis === 'xy') {
63 | dy = (top / height) * (ymax - ymin);
64 | }
65 |
66 | const x = (dx !== 0 ? parseInt(dx / xstep, 10) * xstep : 0) + xmin;
67 | const y = (dy !== 0 ? parseInt(dy / ystep, 10) * ystep : 0) + ymin;
68 |
69 | onChange({
70 | x: xreverse ? xmax - x + xmin : x,
71 | y: yreverse ? ymax - y + ymin : y
72 | });
73 | }
74 |
75 | function handleMouseDown(e) {
76 | if (disabled) return;
77 |
78 | e.preventDefault();
79 | e.stopPropagation();
80 | e.nativeEvent.stopImmediatePropagation();
81 | const dom = handle.current;
82 | const clientPos = getClientPosition(e);
83 |
84 | start.current = {
85 | x: dom.offsetLeft,
86 | y: dom.offsetTop
87 | };
88 |
89 | offset.current = {
90 | x: clientPos.x,
91 | y: clientPos.y
92 | };
93 |
94 | document.addEventListener('mousemove', handleDrag);
95 | document.addEventListener('mouseup', handleDragEnd);
96 | document.addEventListener('touchmove', handleDrag, { passive: false });
97 | document.addEventListener('touchend', handleDragEnd);
98 | document.addEventListener('touchcancel', handleDragEnd);
99 |
100 | if (onDragStart) {
101 | onDragStart(e);
102 | }
103 | }
104 |
105 | function getPos(e) {
106 | const clientPos = getClientPosition(e);
107 | const left = clientPos.x + start.current.x - offset.current.x;
108 | const top = clientPos.y + start.current.y - offset.current.y;
109 |
110 | return { left, top };
111 | }
112 |
113 | function handleDrag(e) {
114 | if (disabled) return;
115 |
116 | e.preventDefault();
117 | change(getPos(e));
118 | }
119 |
120 | function handleDragEnd(e) {
121 | if (disabled) return;
122 |
123 | e.preventDefault();
124 | document.removeEventListener('mousemove', handleDrag);
125 | document.removeEventListener('mouseup', handleDragEnd);
126 |
127 | document.removeEventListener('touchmove', handleDrag, {
128 | passive: false
129 | });
130 | document.removeEventListener('touchend', handleDragEnd);
131 | document.removeEventListener('touchcancel', handleDragEnd);
132 |
133 | if (onDragEnd) {
134 | onDragEnd(e);
135 | }
136 | }
137 |
138 | function handleTrackMouseDown(e) {
139 | if (disabled) return;
140 |
141 | e.preventDefault();
142 | const clientPos = getClientPosition(e);
143 | const rect = container.current.getBoundingClientRect();
144 |
145 | start.current = {
146 | x: clientPos.x - rect.left,
147 | y: clientPos.y - rect.top
148 | };
149 |
150 | offset.current = {
151 | x: clientPos.x,
152 | y: clientPos.y
153 | };
154 |
155 | document.addEventListener('mousemove', handleDrag);
156 | document.addEventListener('mouseup', handleDragEnd);
157 | document.addEventListener('touchmove', handleDrag, { passive: false });
158 | document.addEventListener('touchend', handleDragEnd);
159 | document.addEventListener('touchcancel', handleDragEnd);
160 |
161 | change({
162 | left: clientPos.x - rect.left,
163 | top: clientPos.y - rect.top
164 | });
165 |
166 | if (onDragStart) {
167 | onDragStart(e);
168 | }
169 | }
170 |
171 | const pos = getPosition();
172 | const valueStyle = {};
173 | if (axis === 'x') valueStyle.width = pos.left + '%';
174 | if (axis === 'y') valueStyle.height = pos.top + '%';
175 | if (xreverse) valueStyle.left = 100 - pos.left + '%';
176 | if (yreverse) valueStyle.top = 100 - pos.top + '%';
177 |
178 | const handleStyle = {
179 | position: 'absolute',
180 | transform: 'translate(-50%, -50%)',
181 | left: xreverse ? 100 - pos.left + '%' : pos.left + '%',
182 | top: yreverse ? 100 - pos.top + '%' : pos.top + '%'
183 | };
184 |
185 | if (axis === 'x') {
186 | handleStyle.top = '50%';
187 | } else if (axis === 'y') {
188 | handleStyle.left = '50%';
189 | }
190 |
191 | const styles = {
192 | track: { ...defaultStyles[axis].track, ...customStyles.track },
193 | active: { ...defaultStyles[axis].active, ...customStyles.active },
194 | thumb: { ...defaultStyles[axis].thumb, ...customStyles.thumb },
195 | disabled: { ...defaultStyles.disabled, ...customStyles.disabled }
196 | };
197 |
198 | return (
199 |
220 | );
221 | };
222 |
223 | Slider.defaultProps = {
224 | disabled: false,
225 | axis: 'x',
226 | x: 50,
227 | xmin: 0,
228 | xmax: 100,
229 | y: 50,
230 | ymin: 0,
231 | ymax: 100,
232 | xstep: 1,
233 | ystep: 1,
234 | xreverse: false,
235 | yreverse: false,
236 | styles: {}
237 | };
238 |
239 | export default Slider;
240 |
--------------------------------------------------------------------------------
/src/styles.js:
--------------------------------------------------------------------------------
1 | const track = {
2 | position: 'relative',
3 | display: 'inline-block',
4 | backgroundColor: '#ddd',
5 | borderRadius: 5,
6 | userSelect: 'none',
7 | boxSizing: 'border-box'
8 | };
9 |
10 | const active = {
11 | position: 'absolute',
12 | backgroundColor: '#5e72e4',
13 | borderRadius: 5,
14 | userSelect: 'none',
15 | boxSizing: 'border-box'
16 | };
17 |
18 | const thumb = {
19 | position: 'relative',
20 | display: 'block',
21 | content: '""',
22 | width: 18,
23 | height: 18,
24 | backgroundColor: '#fff',
25 | borderRadius: '50%',
26 | boxShadow: '0 1px 1px rgba(0,0,0,.5)',
27 | userSelect: 'none',
28 | cursor: 'pointer',
29 | boxSizing: 'border-box'
30 | };
31 |
32 | const styles = {
33 | x: {
34 | track: {
35 | ...track,
36 | width: 200,
37 | height: 10
38 | },
39 |
40 | active: {
41 | ...active,
42 | top: 0,
43 | height: '100%'
44 | },
45 |
46 | thumb: {
47 | ...thumb
48 | }
49 | },
50 |
51 | y: {
52 | track: {
53 | ...track,
54 | width: 10,
55 | height: 200
56 | },
57 |
58 | active: {
59 | ...active,
60 | left: 0,
61 | width: '100%'
62 | },
63 |
64 | thumb: {
65 | ...thumb
66 | }
67 | },
68 |
69 | xy: {
70 | track: {
71 | position: 'relative',
72 | overflow: 'hidden',
73 | width: 200,
74 | height: 200,
75 | backgroundColor: '#5e72e4',
76 | borderRadius: 0
77 | },
78 |
79 | active: {},
80 |
81 | thumb: {
82 | ...thumb
83 | }
84 | },
85 |
86 | disabled: {
87 | opacity: 0.5
88 | }
89 | };
90 |
91 | export default styles;
92 |
--------------------------------------------------------------------------------
/src/utils.js:
--------------------------------------------------------------------------------
1 | export function getClientPosition(e) {
2 | const touches = e.touches;
3 |
4 | if (touches && touches.length) {
5 | const finger = touches[0];
6 | return {
7 | x: finger.clientX,
8 | y: finger.clientY
9 | };
10 | }
11 |
12 | return {
13 | x: e.clientX,
14 | y: e.clientY
15 | };
16 | }
17 |
--------------------------------------------------------------------------------
/stories/InputSlider.stories.js:
--------------------------------------------------------------------------------
1 | import React, { Fragment, useState } from 'react';
2 | import Slider from '../src';
3 |
4 | export default {
5 | title: 'InputSlider',
6 | component: Slider
7 | };
8 |
9 | export const Default = () => {
10 | const [state, setState] = useState({ x: 120, y: 120 });
11 |
12 | return (
13 |
14 | {'x: ' + state.x}
15 | {'y: ' + state.y}
16 |
26 | setState({ ...state, x })}
32 | />
33 | setState({ ...state, y })}
39 | />
40 |
41 | );
42 | };
43 |
44 | export const XYExample = () => {
45 | const [state, setState] = useState({ x: 21, y: 73 });
46 |
47 | return (
48 |
49 | {'x: ' + state.x}
50 | {'y: ' + state.y}
51 | console.log('drag end')}
58 | onChange={setState}
59 | />
60 |
61 | );
62 | };
63 |
64 | export const XExample = () => {
65 | const [state, setState] = useState({ x: 0.3 });
66 |
67 | return (
68 |
69 | {'x: ' + state.x}
70 | setState({ x: parseFloat(x.toFixed(2)) })}
77 | />
78 |
79 | );
80 | };
81 |
82 | export const YExample = () => {
83 | const [state, setState] = useState({ y: 120 });
84 |
85 | return (
86 |
87 | {'y: ' + state.y}
88 |
89 |
90 | );
91 | };
92 |
93 | export const ReverseExample = () => {
94 | const [state, setState] = useState({ x: 120, y: 120 });
95 |
96 | return (
97 |
98 | {'x: ' + state.x}
99 | {'y: ' + state.y}
100 |
112 | setState({ ...state, x })}
118 | xreverse
119 | />
120 | setState({ ...state, y })}
126 | yreverse
127 | />
128 |
129 | );
130 | };
131 |
132 | export const CustomExample = () => {
133 | const [x, setX] = useState(200);
134 | const [y, setY] = useState(200);
135 |
136 | return (
137 |
138 | setX(x)}
141 | xmin={100}
142 | xmax={360}
143 | styles={{
144 | track: {
145 | backgroundColor: 'blue'
146 | },
147 | active: {
148 | backgroundColor: 'red'
149 | },
150 | thumb: {
151 | width: 20,
152 | height: 40,
153 | opacity: 0.8,
154 | '&:hover': {
155 | width: 40,
156 | height: 80
157 | }
158 | }
159 | }}
160 | />
161 | setY(y)}
165 | ymin={100}
166 | ymax={360}
167 | styles={{
168 | track: {
169 | backgroundColor: 'blue'
170 | },
171 | active: {
172 | backgroundColor: 'red'
173 | },
174 | thumb: {
175 | width: 20,
176 | height: 40,
177 | opacity: 0.8
178 | }
179 | }}
180 | />
181 |
182 | );
183 | };
184 |
185 | export const DisabledExample = () => {
186 | const [state, setState] = useState({ x: 10 });
187 | const [disabled, setDisabled] = useState(true);
188 |
189 | return (
190 |
191 | {'x: ' + state.x}
192 | {'disabled: ' + disabled}
193 | setDisabled(e.target.checked)}
197 | />
198 |
199 | setState({ x: parseFloat(x.toFixed(2)) })}
204 | />
205 |
206 |
207 | );
208 | };
209 |
--------------------------------------------------------------------------------