Skip to content

Instantly share code, notes, and snippets.

@JesseRWeigel
Forked from RedHatter/DateMultiPicker.jsx
Created October 7, 2019 18:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JesseRWeigel/5122357e558a7bd50f85a5afaf3a4c2c to your computer and use it in GitHub Desktop.
Save JesseRWeigel/5122357e558a7bd50f85a5afaf3a4c2c to your computer and use it in GitHub Desktop.
Range and multi select for @dmtrKovalenko/material-ui-pickers
import React, { useState, useContext, useRef } from 'react'
import { DatePicker } from 'material-ui-pickers'
import { MuiPickersContext } from 'material-ui-pickers'
export default function DateMultiPicker({
value,
onChange,
labelFunc,
format,
emptyLabel,
onClose,
...props
}) {
const [dates, setDates] = useState(value)
const utils = useContext(MuiPickersContext)
function renderDay(day, selectedDate, dayInCurrentMonth, dayComponent) {
return React.cloneElement(dayComponent, {
onClick: e => {
e.stopPropagation()
const i = dates.findIndex(d => utils.isSameDay(d, day))
if (i >= 0) {
const nextDates = [...dates]
nextDates.splice(i, 1)
setDates(nextDates)
} else {
setDates([...dates, day])
}
},
selected: !!dates.find(d => utils.isSameDay(d, day))
})
}
const formatDate = date => utils.format(date, format || utils.dateFormat)
return (
<DatePicker
{...props}
value={dates[0]}
renderDay={renderDay}
onClose={() => {
onChange(dates)
if (onClose) onClose()
}}
onChange={() => {}}
onClear={ () => {
setDates([])
onChange([])
}}
labelFunc={(date, invalid) =>
labelFunc
? labelFunc(dates, invalid)
: date && dates.length > 0
? dates.map(formatDate).join(', ')
: emptyLabel || ''
}
/>
)
}
import React, { useState, useContext, useRef } from 'react'
import { DatePicker } from 'material-ui-pickers'
import { MuiPickersContext } from 'material-ui-pickers'
import withStyles from '@material-ui/core/styles/withStyles'
import { styles as dayStyles } from 'material-ui-pickers/DatePicker/components/Day'
import clsx from 'clsx'
function DateRangePicker({
classes,
value,
onChange,
labelFunc,
format,
emptyLabel,
autoOk,
onClose,
...props
}) {
const [begin, setBegin] = useState(value[0])
const [end, setEnd] = useState(value[1])
const [hover, setHover] = useState(undefined)
const picker = useRef()
const utils = useContext(MuiPickersContext)
const min = Math.min(begin, end || hover)
const max = Math.max(begin, end || hover)
function renderDay(day, selectedDate, dayInCurrentMonth, dayComponent) {
return React.cloneElement(dayComponent, {
onClick: e => {
e.stopPropagation()
if (!begin) setBegin(day)
else if (!end) {
setEnd(day)
if (autoOk) {
onChange([begin, day].sort())
picker.current.close()
}
} else {
setBegin(day)
setEnd(undefined)
}
},
onMouseEnter: e => setHover(day),
className: clsx(classes.day, {
[classes.hidden]: dayComponent.props.hidden,
[classes.current]: dayComponent.props.current,
[classes.isDisabled]: dayComponent.props.disabled,
[classes.isSelected]: day >= min && day <= max,
[classes.beginCap]: utils.isSameDay(day, min),
[classes.endCap]: utils.isSameDay(day, max)
})
})
}
const formatDate = date => utils.format(date, format || utils.dateFormat)
return (
<DatePicker
{...props}
value={begin}
renderDay={renderDay}
onClose={() => {
onChange([begin, end].sort())
if (onClose) onClose()
}}
onChange={() => {}}
onClear={() => {
setBegin(undefined)
setEnd(undefined)
setHover(undefined)
onChange([])
}}
ref={picker}
labelFunc={(date, invalid) =>
labelFunc
? labelFunc([begin, end].sort(), invalid)
: date && begin && end
? `${formatDate(begin)} - ${formatDate(end)}`
: emptyLabel || ''
}
/>
)
}
export const styles = theme => {
const base = dayStyles(theme)
return {
...base,
day: {
...base.day,
margin: 0,
width: '40px',
borderRadius: '0'
},
beginCap: {
borderRadius: '50% 0 0 50%'
},
endCap: {
borderRadius: '0 50% 50% 0'
}
}
}
export default withStyles(styles, { name: 'DateRangePicker' })(DateRangePicker)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment