wix-style-react
Version:
181 lines (156 loc) • 6.03 kB
JavaScript
import React from 'react';
import PropTypes from 'prop-types';
import { classes } from './CalendarPanel.st.css';
import DropdownLayout from '../DropdownLayout';
import Calendar from '../Calendar';
import { DIVIDER_OPTION_VALUE } from '../DropdownLayout/DropdownLayout';
import { supportedWixlocales } from 'wix-design-systems-locale-utils';
class CalendarPanel extends React.Component {
static displayName = 'CalendarPanel';
static propTypes = {
/** Applies a data-hook HTML attribute that can be used in the tests */
dataHook: PropTypes.string,
/** Specifies a CSS class name to be appended to the component’s root element */
className: PropTypes.string,
/** Defines a callback function which is called whenever the user selects a day or a date range in the calendar */
onChange: PropTypes.func.isRequired,
/** Defines a callback function which is called whenever user press `escape` or click outside of the element */
onClose: PropTypes.func,
/** Specifies whether past dates should be selectable or not */
excludePastDates: PropTypes.bool,
/** Specifies dates that are selectable. Only the dates that match defined criteria will be available for a user to select. */
filterDate: PropTypes.func,
/** Defines a selected date or date range */
value: PropTypes.oneOfType([
PropTypes.string,
PropTypes.instanceOf(Date),
PropTypes.shape({
from: PropTypes.oneOfType([
PropTypes.string,
PropTypes.instanceOf(Date),
]),
to: PropTypes.oneOfType([PropTypes.string, PropTypes.instanceOf(Date)]),
}),
]),
/** Specifies if user can select a single day or a date range */
selectionMode: PropTypes.oneOf(['day', 'range']),
/** Specifies whether to display a year selection dropdown inside of a calendar */
showYearDropdown: PropTypes.bool,
/** Specifies whether to display a month selection dropdown inside of a calendar */
showMonthDropdown: PropTypes.bool,
/** Specifies whether calendar should close on a day selection */
shouldCloseOnSelect: PropTypes.bool,
/** Specifies date picker instance locale */
locale: PropTypes.oneOfType([
PropTypes.oneOf(supportedWixlocales),
PropTypes.shape({
code: PropTypes.string,
formatDistance: PropTypes.func,
formatRelative: PropTypes.func,
localize: PropTypes.object,
formatLong: PropTypes.object,
match: PropTypes.object,
options: PropTypes.object,
}),
]),
/** Defines a number of months to display inside of a panel */
numOfMonths: PropTypes.number,
/** Defines an array of predefined calendar presets that are displayed as select items on the left side of a panel */
presets: PropTypes.arrayOf(
PropTypes.oneOfType([
PropTypes.shape({
id: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
.isRequired,
value: PropTypes.oneOfType([
PropTypes.node,
PropTypes.string,
PropTypes.func,
]).isRequired,
disabled: PropTypes.bool,
overrideStyle: PropTypes.bool,
selectedDays: PropTypes.oneOfType([
PropTypes.string,
PropTypes.instanceOf(Date),
PropTypes.shape({
from: PropTypes.oneOfType([
PropTypes.string,
PropTypes.instanceOf(Date),
]).isRequired,
to: PropTypes.oneOfType([
PropTypes.string,
PropTypes.instanceOf(Date),
]).isRequired,
}),
]).isRequired,
}),
// A divider option without an id
PropTypes.shape({
value: PropTypes.oneOf([DIVIDER_OPTION_VALUE]),
}),
]),
PropTypes.shape({
selectedDays: PropTypes.object,
id: PropTypes.oneOf([PropTypes.string, PropTypes.number]),
}),
),
/** Renders a panel footer. Pass `<CalendarPanelFooter/>` in all common cases. `({selectedDays, submitDisabled}) => void` - `selectedDays` is the same as the CalendarPanel's `value` prop. `submitDisabled` is true when the current selectedDays is not valida for submission. */
footer: PropTypes.func,
};
static defaultProps = {
numOfMonths: 2,
};
onSelectPreset = preset => {
const { onChange } = this.props;
onChange(preset.selectedDays);
};
getSelectedPresetId() {
const { presets = [], value } = this.props;
const selectedPreset = presets.find(preset =>
Calendar.areValuesEqual(preset.selectedDays, value),
);
return selectedPreset ? selectedPreset.id : -1;
}
isSubmitDisabled() {
const { selectionMode, value } = this.props;
if (selectionMode === 'range') {
return !Boolean(value) || !Boolean(value.from) || !Boolean(value.to);
}
return !Boolean(value);
}
render() {
const { dataHook, presets, footer, ...calendarProps } = this.props;
return (
<div className={classes.root} data-hook={dataHook}>
<div className={classes.calendarWithPresets}>
{Boolean(presets && presets.length) && (
<div className={classes.presets}>
<DropdownLayout
visible
inContainer
onSelect={this.onSelectPreset}
dataHook={'dropdown-layout'}
options={presets}
maxHeightPixels={342}
selectedId={this.getSelectedPresetId()}
/>
</div>
)}
<Calendar
{...calendarProps}
dataHook={'calendar'}
className={classes.calendar}
/>
</div>
{footer && (
<div className={classes.footer}>
{footer({
selectedDays: calendarProps.value,
submitDisabled: this.isSubmitDisabled(),
})}
</div>
)}
</div>
);
}
}
export default CalendarPanel;