Skip to content

Commit

Permalink
Add disabledDays and selectedDays props (close #34)
Browse files Browse the repository at this point in the history
  • Loading branch information
gpbl committed May 15, 2016
1 parent 94a6e04 commit f19c78f
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 19 deletions.
3 changes: 3 additions & 0 deletions src/Day.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export default function Day({
onTouchEnd,
ariaLabel,
ariaDisabled,
ariaSelected,
children,
}) {
let className = 'DayPicker-Day';
Expand All @@ -43,6 +44,7 @@ export default function Day({
role="gridcell"
aria-label={ariaLabel}
aria-disabled={ariaDisabled.toString()}
aria-selected={ariaSelected.toString()}
onClick={handleEvent(onClick, day, modifiers)}
onKeyDown={handleEvent(onKeyDown, day, modifiers)}
onMouseEnter={handleEvent(onMouseEnter, day, modifiers)}
Expand All @@ -61,6 +63,7 @@ Day.propTypes = {

ariaDisabled: PropTypes.bool,
ariaLabel: PropTypes.string,
ariaSelected: PropTypes.bool,
empty: PropTypes.bool,
modifiers: PropTypes.array,
onClick: PropTypes.func,
Expand Down
29 changes: 20 additions & 9 deletions src/DayPicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@ import * as LocaleUtils from './LocaleUtils';

import keys from './keys';
import DayPickerPropTypes from './PropTypes';

export default class DayPicker extends Component {
static VERSION = '2.0.0-beta';

static propTypes = {
initialMonth: PropTypes.instanceOf(Date),
numberOfMonths: PropTypes.number,
selectedDays: PropTypes.func,
disabledDays: PropTypes.func,

modifiers: PropTypes.object,

Expand Down Expand Up @@ -86,6 +87,17 @@ export default class DayPicker extends Component {
currentMonth: Helpers.startOfMonth(props.initialMonth),
})

getModifiersFromProps(props) {
const modifiers = { ...props.modifiers };
if (props.selectedDays) {
modifiers.selected = props.selectedDays;
}
if (props.disabledDays) {
modifiers.disabled = props.disabledDays;
}
return modifiers;
}

getDayNodes() {
return this.refs.dayPicker.querySelectorAll('.DayPicker-Day:not(.DayPicker-Day--outside)');
}
Expand Down Expand Up @@ -284,7 +296,7 @@ export default class DayPicker extends Component {

handleDayClick(e, day, modifiers) {
e.persist();
if (modifiers.indexOf('outside') > -1) {
if (modifiers.outside) {
this.handleOutsideDayClick(day);
}
this.props.onDayClick(e, day, modifiers);
Expand All @@ -309,11 +321,10 @@ export default class DayPicker extends Component {
if (day.getMonth() !== month.getMonth()) {
dayModifiers.push('outside');
}
if (this.props.modifiers) {
dayModifiers = dayModifiers.concat(
Helpers.getModifiersForDay(day, this.props.modifiers)
);
}
dayModifiers = [
...dayModifiers,
...Helpers.getModifiersForDay(day, this.getModifiersFromProps(this.props)),
];

const isOutside = day.getMonth() !== month.getMonth();
let tabIndex = null;
Expand All @@ -324,7 +335,6 @@ export default class DayPicker extends Component {
tabIndex = this.props.tabIndex;
}
}

const key = `${day.getFullYear()}${day.getMonth()}${day.getDate()}`;
return (
<Day
Expand All @@ -334,7 +344,8 @@ export default class DayPicker extends Component {
empty={isOutside && !this.props.enableOutsideDays}
tabIndex={tabIndex}
ariaLabel={this.props.localeUtils.formatDay(day, this.props.locale)}
ariaDisabled={isOutside}
ariaDisabled={isOutside || dayModifiers.indexOf('disabled') > -1}
ariaSelected={dayModifiers.indexOf('selected') > -1}
onMouseEnter={this.props.onDayMouseEnter}
onMouseLeave={this.props.onDayMouseLeave}
onKeyDown={this.handleDayKeyDown}
Expand Down
38 changes: 28 additions & 10 deletions test/DayPicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ describe('<DayPicker />', () => {
expect(dayPicker.props.renderDay).to.be.a('Function');
expect(dayPicker.props.tabIndex).to.equal(0);
});
it('should have the DayPicker classes', () => {
const wrapper = shallow(<DayPicker />);
expect(wrapper).to.have.className('DayPicker');
expect(wrapper).to.have.className('DayPicker--en');
expect(wrapper).to.have.className('DayPicker--interactionDisabled');
});
it('should use initialMonth as the current month', () => {
const wrapper = shallow(<DayPicker />);
const instance = wrapper.instance();
Expand All @@ -51,12 +57,6 @@ describe('<DayPicker />', () => {
expect(instance.state.currentMonth.getMonth()).to.equal(1);
expect(instance.state.currentMonth.getDate()).to.equal(1);
});
it('should have the DayPicker classes', () => {
const wrapper = shallow(<DayPicker />);
expect(wrapper).to.have.className('DayPicker');
expect(wrapper).to.have.className('DayPicker--en');
expect(wrapper).to.have.className('DayPicker--interactionDisabled');
});
it('should not include the interactionDisabled CSS modifier', () => {
const wrapper = shallow(<DayPicker onDayClick={() => {}} />);
expect(wrapper).to.not.have.className('DayPicker--interactionDisabled');
Expand Down Expand Up @@ -122,6 +122,24 @@ describe('<DayPicker />', () => {
});

describe('day modifiers', () => {
it('should use `selectedDays` prop as `selected` modifier', () => {
const wrapper = mount(<DayPicker selectedDays={() => true} modifiers={{ foo: () => true }} />);
expect(wrapper.find('.DayPicker-Day--selected')).to.have.length(35);
expect(wrapper.find('.DayPicker-Day--foo')).to.have.length(35);
});
it('should add the `aria-selected` attribute for `selected` days', () => {
const wrapper = mount(<DayPicker selectedDays={() => true} />);
expect(wrapper.find('.DayPicker-Day--selected').first()).to.have.attr('aria-selected', 'true');
});
it('should use `disabledDays` prop as `selected` modifier', () => {
const wrapper = mount(<DayPicker disabledDays={() => true} modifiers={{ foo: () => true }} />);
expect(wrapper.find('.DayPicker-Day--disabled')).to.have.length(35);
expect(wrapper.find('.DayPicker-Day--foo')).to.have.length(35);
});
it('should add the `aria-disabled` attribute for `disabled` days', () => {
const wrapper = mount(<DayPicker disabledDays={() => true} />);
expect(wrapper.find('.DayPicker-Day--disabled').first()).to.have.attr('aria-disabled', 'true');
});
it('should include "outside" for outside days', () => {
const wrapper = mount(
<DayPicker initialMonth={new Date(2015, 6)} enableOutsideDays />
Expand Down Expand Up @@ -464,7 +482,7 @@ describe('<DayPicker />', () => {
const eventArgs = [
sinon.match(e => e instanceof SyntheticEvent && e.target !== null, 'e'),
sinon.match(date => date.getFullYear() === (new Date()).getFullYear() && date.getMonth() === (new Date()).getMonth(), 'currentMonth'),
sinon.match(mods => mods.indexOf('foo') > -1, 'modifiers'),
sinon.match(mods => mods.foo, 'modifiers'),
];

wrapper.find('.DayPicker-Day--foo').simulate('click');
Expand Down Expand Up @@ -509,7 +527,7 @@ describe('<DayPicker />', () => {
});
it('should call `onDayClick` event handler when pressing the ENTER key', () => {
const handleDayClick = spy();
const modifiers = { foo: d => d.getDate() === 15 };
const modifiers = { foo: d => d.getDate() === 15, bar: () => false };
const wrapper = mount(
<DayPicker
modifiers={modifiers}
Expand All @@ -519,7 +537,7 @@ describe('<DayPicker />', () => {
const eventArgs = [
sinon.match(e => e instanceof SyntheticEvent && e.target !== null, 'e'),
sinon.match(date => date.getFullYear() === (new Date()).getFullYear() && date.getMonth() === (new Date()).getMonth(), 'currentMonth'),
sinon.match(mods => mods.indexOf('foo') > -1, 'modifiers'),
sinon.match(mods => mods.foo && !mods.bar, 'modifiers'),
];
wrapper.find('.DayPicker-Day--foo').simulate('keyDown', { keyCode: keys.ENTER });
expect(handleDayClick).to.have.been.calledWith(...eventArgs);
Expand All @@ -536,7 +554,7 @@ describe('<DayPicker />', () => {
const eventArgs = [
sinon.match(e => e instanceof SyntheticEvent && e.target !== null, 'e'),
sinon.match(date => date.getFullYear() === (new Date()).getFullYear() && date.getMonth() === (new Date()).getMonth(), 'currentMonth'),
sinon.match(mods => mods.indexOf('foo') > -1, 'modifiers'),
sinon.match(mods => mods.foo, 'modifiers'),
];
wrapper.find('.DayPicker-Day--foo').simulate('keyDown', { keyCode: keys.SPACE });
expect(handleDayClick).to.have.been.calledWith(...eventArgs);
Expand Down

0 comments on commit f19c78f

Please sign in to comment.