├── demo.gif
├── .babelrc
├── src
├── components
│ ├── SliderRail.js
│ ├── KeyboardHandle.js
│ ├── Tick.js
│ ├── Handle.js
│ └── Track.js
├── styles
│ └── index.scss
└── index.js
├── .gitignore
├── webpack.config.js
├── LICENSE
├── package.json
└── README.md
/demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lizashkod/react-timeline-range-slider/HEAD/demo.gif
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["@babel/preset-env"],
3 | "plugins": [
4 | "transform-object-rest-spread",
5 | "transform-react-jsx",
6 | "@babel/plugin-proposal-class-properties"
7 | ]
8 | }
9 |
--------------------------------------------------------------------------------
/src/components/SliderRail.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import PropTypes from 'prop-types'
3 |
4 | export const SliderRail = ({ getRailProps }) => (
5 | <>
6 |
7 |
8 | >
9 | )
10 |
11 | SliderRail.propTypes = { getRailProps: PropTypes.func.isRequired }
12 |
13 | export default SliderRail
14 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 | /.idea
8 | /dist
9 |
10 | # testing
11 | /coverage
12 |
13 | # production
14 | /build
15 |
16 | # misc
17 | .DS_Store
18 | .env.local
19 | .env.development.local
20 | .env.test.local
21 | .env.production.local
22 |
23 | npm-debug.log*
24 | yarn-debug.log*
25 | yarn-error.log*
26 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 |
3 | module.exports = {
4 | mode: 'production',
5 | entry: './src/index.js',
6 | output: {
7 | path: path.resolve(__dirname, 'dist'),
8 | filename: 'index.js',
9 | library: 'react-timeline-range-slider',
10 | libraryTarget: 'commonjs2'
11 | },
12 | module: {
13 | rules: [
14 | {
15 | test: /\.js$/,
16 | include: path.resolve(__dirname, 'src'),
17 | exclude: /node_modules/,
18 | use: {
19 | loader: 'babel-loader',
20 | options: {
21 | presets: ['@babel/preset-react', "@babel/preset-env"]
22 | }
23 | }
24 | }, {
25 | test: /\.s[ac]ss$/i,
26 | use : [ 'style-loader', 'css-loader', 'sass-loader']
27 | },
28 | ]
29 | },
30 | externals: {
31 | 'react': 'commonjs react'
32 | }
33 | };
34 |
--------------------------------------------------------------------------------
/src/components/KeyboardHandle.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types'
2 | import React from 'react'
3 |
4 | const KeyboardHandle = ({ domain: [min, max], handle: { id, value, percent = 0 }, disabled, getHandleProps }) => (
5 |
17 | )
18 |
19 | KeyboardHandle.propTypes = {
20 | domain: PropTypes.array.isRequired,
21 | handle: PropTypes.shape({
22 | id: PropTypes.string.isRequired,
23 | value: PropTypes.number.isRequired,
24 | percent: PropTypes.number.isRequired
25 | }).isRequired,
26 | getHandleProps: PropTypes.func.isRequired,
27 | disabled: PropTypes.bool
28 | }
29 |
30 | KeyboardHandle.defaultProps = { disabled: false }
31 |
32 | export default KeyboardHandle
33 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Elizaveta Shkodkina
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 |
--------------------------------------------------------------------------------
/src/components/Tick.js:
--------------------------------------------------------------------------------
1 | import { getMinutes } from 'date-fns'
2 | import PropTypes from 'prop-types'
3 | import React from 'react'
4 |
5 | const Tick = ({ tick, count, format }) => {
6 | const isFullHour = !getMinutes(tick.value)
7 |
8 | const tickLabelStyle = {
9 | marginLeft: `${-(100 / count) / 2}%`,
10 | width: `${100 / count}%`,
11 | left: `${tick.percent}%`,
12 | }
13 |
14 | return (
15 | <>
16 |
20 | {isFullHour && (
21 |
22 | {format(tick.value)}
23 |
24 | )}
25 | >
26 | )
27 | }
28 |
29 | Tick.propTypes = {
30 | tick: PropTypes.shape({
31 | id: PropTypes.string.isRequired,
32 | value: PropTypes.number.isRequired,
33 | percent: PropTypes.number.isRequired
34 | }).isRequired,
35 | count: PropTypes.number.isRequired,
36 | format: PropTypes.func.isRequired
37 | }
38 |
39 | Tick.defaultProps = { format: d => d }
40 |
41 | export default Tick
42 |
--------------------------------------------------------------------------------
/src/components/Handle.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types'
2 | import React from 'react'
3 |
4 | const Handle = ({
5 | error,
6 | domain: [min, max],
7 | handle: { id, value, percent = 0 },
8 | disabled,
9 | getHandleProps,
10 | }) => {
11 | const leftPosition = `${percent}%`
12 |
13 | return (
14 | <>
15 |
16 |
26 | >
27 | )
28 | }
29 |
30 | Handle.propTypes = {
31 | domain: PropTypes.array.isRequired,
32 | handle: PropTypes.shape({
33 | id: PropTypes.string.isRequired,
34 | value: PropTypes.number.isRequired,
35 | percent: PropTypes.number.isRequired
36 | }).isRequired,
37 | getHandleProps: PropTypes.func.isRequired,
38 | disabled: PropTypes.bool,
39 | style: PropTypes.object,
40 | }
41 |
42 | Handle.defaultProps = { disabled: false }
43 |
44 | export default Handle
45 |
--------------------------------------------------------------------------------
/src/components/Track.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types'
2 | import React from 'react'
3 |
4 | const getTrackConfig = ({ error, source, target, disabled }) => {
5 | const basicStyle = {
6 | left: `${source.percent}%`,
7 | width: `calc(${target.percent - source.percent}% - 1px)`,
8 | }
9 |
10 | if (disabled) return basicStyle
11 |
12 | const coloredTrackStyle = error
13 | ? {
14 | backgroundColor: 'rgba(214,0,11,0.5)',
15 | borderLeft: '1px solid rgba(214,0,11,0.5)',
16 | borderRight: '1px solid rgba(214,0,11,0.5)',
17 | }
18 | : {
19 | backgroundColor: 'rgba(98, 203, 102, 0.5)',
20 | borderLeft: '1px solid #62CB66',
21 | borderRight: '1px solid #62CB66',
22 | }
23 |
24 | return { ...basicStyle, ...coloredTrackStyle }
25 | }
26 |
27 | const Track = ({ error, source, target, getTrackProps, disabled }) => (
28 |
33 | )
34 |
35 | Track.propTypes = {
36 | source: PropTypes.shape({
37 | id: PropTypes.string.isRequired,
38 | value: PropTypes.number.isRequired,
39 | percent: PropTypes.number.isRequired
40 | }).isRequired,
41 | target: PropTypes.shape({
42 | id: PropTypes.string.isRequired,
43 | value: PropTypes.number.isRequired,
44 | percent: PropTypes.number.isRequired
45 | }).isRequired,
46 | getTrackProps: PropTypes.func.isRequired,
47 | disabled: PropTypes.bool
48 | }
49 |
50 | Track.defaultProps = { disabled: false }
51 |
52 | export default Track
53 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-timeline-range-slider",
3 | "version": "1.4.1",
4 | "description": "Time Slider component for React",
5 | "author": "Elizaveta Shkodkina ",
6 | "main": "dist/index.js",
7 | "license": "MIT",
8 | "homepage": "https://github.com/lizashkod/react-time-range-slider",
9 | "repository": {
10 | "type": "git",
11 | "url": "https://github.com/lizashkod/react-time-range-slider"
12 | },
13 | "keywords": [
14 | "react-component",
15 | "react",
16 | "slider",
17 | "component",
18 | "time-picker",
19 | "react-slider",
20 | "range-slider",
21 | "range"
22 | ],
23 | "peerDependencies": {
24 | "react": "^17.0.2",
25 | "react-dom": "^17.0.2"
26 | },
27 | "scripts": {
28 | "start": "webpack --watch",
29 | "build": "webpack"
30 | },
31 | "eslintConfig": {
32 | "extends": "react-app"
33 | },
34 | "browserslist": {
35 | "production": [
36 | ">0.2%",
37 | "not dead",
38 | "not op_mini all"
39 | ],
40 | "development": [
41 | "last 1 chrome version",
42 | "last 1 firefox version",
43 | "last 1 safari version"
44 | ]
45 | },
46 | "dependencies": {
47 | "prop-types": "^15.7.2",
48 | "d3-scale": "^3.2.3",
49 | "date-fns": "^2.19.0",
50 | "node-sass": "^5.0.0",
51 | "react-compound-slider": "^3.3.1"
52 | },
53 | "devDependencies": {
54 | "@babel/core": "^7.13.10",
55 | "@babel/plugin-proposal-class-properties": "^7.13.0",
56 | "@babel/preset-env": "^7.13.12",
57 | "@babel/preset-react": "^7.12.13",
58 | "babel-loader": "^8.2.2",
59 | "babel-plugin-transform-object-rest-spread": "^6.26.0",
60 | "babel-plugin-transform-react-jsx": "^6.24.1",
61 | "css-loader": "^5.1.3",
62 | "sass-loader": "^10.0.0",
63 | "style-loader": "^2.0.0",
64 | "webpack": "^4.43.0",
65 | "webpack-cli": "^3.3.12"
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ### react-timeline-range-slider
2 | 
3 | ### Installation
4 |
5 | npm i react-timeline-range-slider
6 | ### Props
7 |
8 | | Prop | Type | Default | Description|
9 | |--|--|--|--|
10 | | timelineInterval | array |[startOfToday(), endOfToday()]|Interval to display|
11 | |selectedInterval|array|[new Date(), addHours(new Date(), 1)]|Selected interval inside the timeline|
12 | |disabledIntervals|array|[]|Array of disabled intervals inside the timeline|
13 | |containerClassName|string||ClassName of the wrapping container|
14 | |step|number|1800000|Number of milliseconds between steps (the default value is 30 minutes)|
15 | |ticksNumber|number|48|Number of steps on the timeline (the default value is 30 minutes)|
16 | |error|bool|false|Is the selected interval is not valid|
17 | |mode|int/function|3|The interaction mode. Value of 1 will allow handles to cross each other. Value of 2 will keep the sliders from crossing and separated by a step. Value of 3 will make the handles pushable and keep them a step apart. ADVANCED: You can also supply a function that will be passed the current values and the incoming update. Your function should return what the state should be set as.|
18 | |formatTick|function|ms => format(new Date(ms), 'HH:mm')|Function that determines the format in which the date will be displayed|
19 | |onUpdateCallback|function|||
20 | |onChangeCallback|function|||
21 | ### Example
22 | [Live demo](https://codesandbox.io/s/react-timeline-range-slider-ve7w2?file=/src/App.js)
23 | ```javascript
24 | import React from 'react'
25 | import { endOfToday, set } from 'date-fns'
26 | import TimeRange from 'react-timeline-range-slider'
27 |
28 | const now = new Date()
29 | const getTodayAtSpecificHour = (hour = 12) =>
30 | set(now, { hours: hour, minutes: 0, seconds: 0, milliseconds: 0 })
31 |
32 | const selectedStart = getTodayAtSpecificHour()
33 | const selectedEnd = getTodayAtSpecificHour(14)
34 |
35 | const startTime = getTodayAtSpecificHour(7)
36 | const endTime = endOfToday()
37 |
38 | const disabledIntervals = [
39 | { start: getTodayAtSpecificHour(16), end: getTodayAtSpecificHour(17) },
40 | { start: getTodayAtSpecificHour(7), end: getTodayAtSpecificHour(12) },
41 | { start: getTodayAtSpecificHour(20), end: getTodayAtSpecificHour(24) }
42 | ]
43 |
44 | class App extends React.Component {
45 | state = {
46 | error: false,
47 | selectedInterval: [selectedStart, selectedEnd],
48 | }
49 |
50 | errorHandler = ({ error }) => this.setState({ error })
51 |
52 | onChangeCallback = selectedInterval => this.setState({ selectedInterval })
53 |
54 | render() {
55 | const { selectedInterval, error } = this.state
56 | return (
57 |
66 | )
67 | }
68 | }
69 |
70 | export default App
71 | ```
72 |
--------------------------------------------------------------------------------
/src/styles/index.scss:
--------------------------------------------------------------------------------
1 | $react-time-range--gray: #C8CACC;
2 | $react-time-range--highlight-tap: #000000;
3 | $react-time-range--rail-bg: #F5F7FA;
4 | $react-time-range--handle-bg: #FFFFFF;
5 | $react-time-range--handle-bg--disabled: #666;
6 | $react-time-range--track--valid: rgb(98, 203, 102);
7 | $react-time-range--track--not-valid: rgb(214, 0, 11);
8 | $react-time-range--tick-label: #77828C;
9 | $react-time-range--track--disabled: repeating-linear-gradient( -45deg, transparent, transparent 3px, #D0D3D7 4px, #D0D3D7 2px);
10 |
11 | .react_time_range__time_range_container {
12 | padding: 30px 10% 0;
13 | height: 70px;
14 | width: 90%;
15 | box-sizing: border-box;
16 | }
17 |
18 | .react_time_range__keyboard_handle {
19 | position: absolute;
20 | transform: translate(-50%, -50%);
21 | z-index: 3;
22 | width: 24px;
23 | height: 24px;
24 | border-radius: 50%;
25 | box-shadow: 1px 1px 1px 1px rgba(0, 0, 0, 0.3);
26 | }
27 |
28 | .react_time_range__track {
29 | position: absolute;
30 | transform: translate(0%, -50%);
31 | height: 50px;
32 | cursor: pointer;
33 | transition: background-color .15s ease-in-out, border-color .15s ease;
34 | z-index: 3;
35 | &__disabled {
36 | @extend .react_time_range__track;
37 | z-index: 1;
38 | border-left: 1px solid $react-time-range--gray;
39 | border-right: 1px solid $react-time-range--gray;
40 | background: $react-time-range--track--disabled;
41 | }
42 | }
43 |
44 | .react_time_range__rail {
45 | &__outer {
46 | position: absolute;
47 | width: 100%;
48 | height: 50px;
49 | transform: translate(0%, -50%);
50 | cursor: pointer;
51 | }
52 | &__inner {
53 | position: absolute;
54 | width: 100%;
55 | height: 50px;
56 | transform: translate(0%, -50%);
57 | pointer-events: none;
58 | background-color: $react-time-range--rail-bg;
59 | border-bottom: 1px solid $react-time-range--gray;
60 | }
61 | }
62 |
63 | .react_time_range__handle {
64 | &_wrapper {
65 | position: absolute;
66 | transform: translate(-50%, -50%);
67 | -webkit-tap-highlight-color: $react-time-range--highlight-tap;
68 | z-index: 6;
69 | width: 24px;
70 | height: 24px;
71 | cursor: pointer;
72 | background-color: transparent;
73 | }
74 | &_container {
75 | position: absolute;
76 | display: flex;
77 | transform: translate(-50%, -50%);
78 | z-index: 4;
79 | width: 10px;
80 | height: 24px;
81 | border-radius: 4px;
82 | box-shadow: 0 0 3px rgba(0,0,0, 0.4);
83 | background-color: $react-time-range--handle-bg;
84 | &__disabled {
85 | @extend .react_time_range__handle_container;
86 | background-color: $react-time-range--handle-bg--disabled;
87 | }
88 | }
89 | &_marker {
90 | width: 2px;
91 | height: 12px;
92 | margin: auto;
93 | border-radius: 2px;
94 | background-color: $react-time-range--track--valid;
95 | transition: background-color .2s ease;
96 | &__error {
97 | @extend .react_time_range__handle_marker;
98 | background-color: $react-time-range--track--not-valid;
99 | }
100 | }
101 | }
102 |
103 | .react_time_range__tick {
104 | &_marker {
105 | position: absolute;
106 | margin-top: 20px;
107 | width: 1px;
108 | height: 5px;
109 | background-color: $react-time-range--gray;
110 | z-index: 2;
111 | &__large {
112 | @extend .react_time_range__tick_marker;
113 | margin-top: 15px;
114 | height: 10px;
115 | }
116 | }
117 | &_label {
118 | position: absolute;
119 | margin-top: 28px;
120 | font-size: 10px;
121 | text-align: center;
122 | z-index: 2;
123 | color: $react-time-range--tick-label;
124 | font-family: sans-serif;
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import PropTypes from 'prop-types'
3 | import { scaleTime } from 'd3-scale'
4 | import { Slider, Rail, Handles, Tracks, Ticks } from 'react-compound-slider'
5 | import {
6 | format,
7 | addHours,
8 | startOfToday,
9 | endOfToday,
10 | differenceInMilliseconds,
11 | isBefore,
12 | isAfter,
13 | set,
14 | addMinutes,
15 | } from 'date-fns'
16 |
17 | import SliderRail from './components/SliderRail'
18 | import Track from './components/Track'
19 | import Tick from './components/Tick'
20 | import Handle from './components/Handle'
21 |
22 | import './styles/index.scss'
23 |
24 | const getTimelineConfig = (timelineStart, timelineLength) => (date) => {
25 | const percent = differenceInMilliseconds(date, timelineStart)/timelineLength * 100
26 | const value = Number(format(date, 'T'))
27 | return { percent, value }
28 | }
29 |
30 | const getFormattedBlockedIntervals = (blockedDates = [], [startTime, endTime]) => {
31 | if (!blockedDates.length) return null
32 |
33 | const timelineLength = differenceInMilliseconds(endTime, startTime)
34 | const getConfig = getTimelineConfig(startTime, timelineLength)
35 |
36 | const formattedBlockedDates = blockedDates.map((interval, index) => {
37 | let { start, end } = interval
38 |
39 | if (isBefore(start, startTime)) start = startTime
40 | if (isAfter(end, endTime)) end = endTime
41 |
42 | const source = getConfig(start)
43 | const target = getConfig(end)
44 |
45 | return { id: `blocked-track-${index}`, source, target }
46 | })
47 |
48 | return formattedBlockedDates
49 | }
50 |
51 | const getNowConfig = ([startTime, endTime]) => {
52 | const timelineLength = differenceInMilliseconds(endTime, startTime)
53 | const getConfig = getTimelineConfig(startTime, timelineLength)
54 |
55 | const source = getConfig(new Date())
56 | const target = getConfig(addMinutes(new Date(), 1))
57 |
58 | return { id: 'now-track', source, target }
59 | }
60 |
61 | class TimeRange extends React.Component {
62 | get disabledIntervals () {
63 | return getFormattedBlockedIntervals(this.props.disabledIntervals, this.props.timelineInterval)
64 | }
65 |
66 | get now () {
67 | return getNowConfig(this.props.timelineInterval)
68 | }
69 |
70 | onChange = newTime => {
71 | const formattedNewTime = newTime.map(t => new Date(t))
72 | this.props.onChangeCallback(formattedNewTime)
73 | }
74 |
75 | checkIsSelectedIntervalNotValid = ([start, end], source, target) => {
76 | const { value: startInterval } = source
77 | const { value: endInterval } = target
78 |
79 | if (startInterval > start && endInterval <= end || startInterval >= start && endInterval < end)
80 | return true
81 | if (start >= startInterval && end <= endInterval) return true
82 |
83 | const isStartInBlockedInterval = start > startInterval && start < endInterval && end >= endInterval
84 | const isEndInBlockedInterval = end < endInterval && end > startInterval && start <= startInterval
85 |
86 | return isStartInBlockedInterval || isEndInBlockedInterval
87 | }
88 |
89 | onUpdate = newTime => {
90 | const { onUpdateCallback } = this.props
91 | const disabledIntervals = this.disabledIntervals
92 |
93 | if (disabledIntervals?.length) {
94 | const isValuesNotValid = disabledIntervals.some(({ source, target }) =>
95 | this.checkIsSelectedIntervalNotValid(newTime, source, target))
96 | const formattedNewTime = newTime.map(t => new Date(t))
97 | onUpdateCallback({ error: isValuesNotValid, time: formattedNewTime })
98 | return
99 | }
100 |
101 | const formattedNewTime = newTime.map(t => new Date(t))
102 | onUpdateCallback({ error: false, time: formattedNewTime })
103 | }
104 |
105 | getDateTicks = () => {
106 | const { timelineInterval, ticksNumber } = this.props
107 | return scaleTime().domain(timelineInterval).ticks(ticksNumber).map(t => +t)
108 | }
109 |
110 | render() {
111 | const {
112 | sliderRailClassName,
113 | timelineInterval,
114 | selectedInterval,
115 | containerClassName,
116 | error,
117 | step,
118 | showNow,
119 | formatTick,
120 | mode,
121 | } = this.props
122 |
123 | const domain = timelineInterval.map(t => Number(t))
124 |
125 | const disabledIntervals = this.disabledIntervals
126 |
127 | return (
128 |
129 | +t)}
136 | rootStyle={{ position: 'relative', width: '100%' }}
137 | >
138 |
139 | {({ getRailProps }) =>
140 | }
141 |
142 |
143 |
144 | {({ handles, getHandleProps }) => (
145 | <>
146 | {handles.map(handle => (
147 |
154 | ))}
155 | >
156 | )}
157 |
158 |
159 |
160 | {({ tracks, getTrackProps }) => (
161 | <>
162 | {tracks?.map(({ id, source, target }) =>
163 |
170 | )}
171 | >
172 | )}
173 |
174 |
175 | {disabledIntervals?.length && (
176 |
177 | {({ getTrackProps }) => (
178 | <>
179 | {disabledIntervals.map(({ id, source, target }) => (
180 |
187 | ))}
188 | >
189 | )}
190 |
191 | )}
192 |
193 | {showNow && (
194 |
195 | {({ getTrackProps }) => (
196 |
202 | )}
203 |
204 | )}
205 |
206 |
207 | {({ ticks }) => (
208 | <>
209 | {ticks.map(tick => (
210 |
216 | ))}
217 | >
218 | )}
219 |
220 |
221 |
222 | )
223 | }
224 | }
225 |
226 | TimeRange.propTypes = {
227 | ticksNumber: PropTypes.number.isRequired,
228 | selectedInterval: PropTypes.arrayOf(PropTypes.object),
229 | timelineInterval: PropTypes.arrayOf(PropTypes.object),
230 | disabledIntervals: PropTypes.arrayOf(PropTypes.object),
231 | containerClassName: PropTypes.string,
232 | sliderRailClassName: PropTypes.string,
233 | step: PropTypes.number,
234 | formatTick: PropTypes.func,
235 | }
236 |
237 | TimeRange.defaultProps = {
238 | selectedInterval: [
239 | set(new Date(), { minutes: 0, seconds: 0, milliseconds: 0 }),
240 | set(addHours(new Date(), 1), { minutes: 0, seconds: 0, milliseconds: 0 })
241 | ],
242 | timelineInterval: [startOfToday(), endOfToday()],
243 | formatTick: ms => format(new Date(ms), 'HH:mm'),
244 | disabledIntervals: [],
245 | step: 1000*60*30,
246 | ticksNumber: 48,
247 | error: false,
248 | mode: 3,
249 | }
250 |
251 | export default TimeRange
252 |
--------------------------------------------------------------------------------