(this.calendar = ref)}
+ onSelect={this.onSelect}
+ {...calCalendarProps({ rules })}
+ {...rest}
+ />
+ );
+ }
+}
+
+export default Month;
diff --git a/src/components/Calendar/__demo__/month.jsx b/src/components/Calendar/__demo__/month.jsx
new file mode 100644
index 00000000..6b67da0c
--- /dev/null
+++ b/src/components/Calendar/__demo__/month.jsx
@@ -0,0 +1,16 @@
+import React from 'react';
+import Calendar from 'components/Calendar';
+
+// demo start
+const Demo = () => (
+
+ console.log('select', v)}
+ onChange={v => console.log('change', v)}
+ rules={{ range: [Date.now() - 3 * 30 * 24 * 60 * 60 * 1000, Date.now() + 3 * 30 * 24 * 60 * 60 * 1000] }}
+ />
+
+);
+// demo end
+
+export default Demo;
diff --git a/src/components/Calendar/__tests__/__snapshots__/demo.test.js.snap b/src/components/Calendar/__tests__/__snapshots__/demo.test.js.snap
index dabe530a..2ed30c1c 100644
--- a/src/components/Calendar/__tests__/__snapshots__/demo.test.js.snap
+++ b/src/components/Calendar/__tests__/__snapshots__/demo.test.js.snap
@@ -2632,6 +2632,478 @@ exports[`Calendar demo -- controlled 1`] = `
`;
+exports[`Calendar demo -- month 1`] = `
+.c0.uc-fe-calendar,
+.c0 .uc-fe-calendar {
+ outline: none;
+ position: relative;
+ box-shadow: 0 0 8px rgba(0,0,0,0.2);
+}
+
+.c0 .uc-fe-calendar-month-panel,
+.c0 .uc-fe-calendar-year-panel,
+.c0 .uc-fe-calendar-decade-panel {
+ background: #FFF;
+}
+
+.c0 .uc-fe-calendar-header,
+.c0 .uc-fe-calendar-month-panel-header,
+.c0 .uc-fe-calendar-year-panel-header,
+.c0 .uc-fe-calendar-decade-panel-header {
+ width: 100%;
+ height: 38px;
+ line-height: 38px;
+ background-color: #4683e6;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+.c0 .uc-fe-calendar-month-header-wrap {
+ height: 180px;
+}
+
+.c0 .uc-fe-calendar-month-panel-body {
+ height: 140px;
+}
+
+.c0 .uc-fe-calendar-prev-year-btn,
+.c0 .uc-fe-calendar-prev-month-btn,
+.c0 .uc-fe-calendar-next-year-btn,
+.c0 .uc-fe-calendar-next-month-btn,
+.c0 .uc-fe-calendar-month-panel-prev-year-btn,
+.c0 .uc-fe-calendar-month-panel-next-year-btn,
+.c0 .uc-fe-calendar-year-panel-prev-decade-btn,
+.c0 .uc-fe-calendar-year-panel-next-decade-btn,
+.c0 .uc-fe-calendar-decade-panel-prev-century-btn,
+.c0 .uc-fe-calendar-decade-panel-next-century-btn {
+ cursor: pointer;
+ padding: 0 8px;
+ display: inline-block;
+ color: #FFF;
+ box-sizing: border-box;
+ position: absolute;
+ font-family: Arial,'Hiragino Sans GB','Microsoft Yahei','Microsoft Sans Serif',sans-serif;
+ font-size: 16px;
+}
+
+.c0 .uc-fe-calendar-prev-year-btn,
+.c0 .uc-fe-calendar-month-panel-prev-year-btn,
+.c0 .uc-fe-calendar-year-panel-prev-decade-btn,
+.c0 .uc-fe-calendar-decade-panel-prev-century-btn {
+ left: 0;
+}
+
+.c0 .uc-fe-calendar-prev-month-btn {
+ left: 30px;
+}
+
+.c0 .uc-fe-calendar-next-year-btn,
+.c0 .uc-fe-calendar-month-panel-next-year-btn,
+.c0 .uc-fe-calendar-year-panel-next-decade-btn,
+.c0 .uc-fe-calendar-decade-panel-next-century-btn {
+ right: 0;
+}
+
+.c0 .uc-fe-calendar-next-month-btn {
+ right: 30px;
+}
+
+.c0 .uc-fe-calendar-prev-year-btn::before,
+.c0 .uc-fe-calendar-month-panel-prev-year-btn::before,
+.c0 .uc-fe-calendar-year-panel-prev-decade-btn::before,
+.c0 .uc-fe-calendar-decade-panel-prev-century-btn::before {
+ content: '\\AB';
+}
+
+.c0 .uc-fe-calendar-prev-month-btn::before {
+ content: '\\2039';
+}
+
+.c0 .uc-fe-calendar-next-year-btn::before,
+.c0 .uc-fe-calendar-month-panel-next-year-btn::before,
+.c0 .uc-fe-calendar-year-panel-next-decade-btn::before,
+.c0 .uc-fe-calendar-decade-panel-next-century-btn::before {
+ content: '\\BB';
+}
+
+.c0 .uc-fe-calendar-next-month-btn::before {
+ content: '\\203A';
+}
+
+.c0 .uc-fe-calendar-year-select,
+.c0 .uc-fe-calendar-month-select,
+.c0 .uc-fe-calendar-day-select {
+ margin-right: 8px;
+}
+
+.c0 .uc-fe-calendar-my-select,
+.c0 .uc-fe-calendar-ym-select,
+.c0 .uc-fe-calendar-month-panel-year-select,
+.c0 .uc-fe-calendar-year-panel-decade-select,
+.c0 .uc-fe-calendar-decade-panel-century {
+ position: absolute;
+ top: 0;
+ left: 50%;
+ margin-left: -75px;
+ width: 150px;
+ text-align: center;
+ display: block;
+ color: #FFF;
+}
+
+.c0 .uc-fe-calendar-body {
+ width: 100%;
+ padding: 0 5px 5px;
+ background-color: #fff;
+ box-sizing: border-box;
+}
+
+.c0 .uc-fe-calendar-table,
+.c0 .uc-fe-calendar-month-panel-table,
+.c0 .uc-fe-calendar-year-panel-table,
+.c0 .uc-fe-calendar-decade-panel-table {
+ width: 100%;
+}
+
+.c0 .uc-fe-calendar-table > thead,
+.c0 .uc-fe-calendar-month-panel-table > thead {
+ border-bottom: 1px solid #c3cad9;
+}
+
+.c0 .uc-fe-calendar-column-header,
+.c0 .uc-fe-calendar-cell,
+.c0 .uc-fe-calendar-month-panel-cell,
+.c0 .uc-fe-calendar-year-panel-cell,
+.c0 .uc-fe-calendar-decade-panel-cell {
+ cursor: pointer;
+ height: 35px;
+ line-height: 35px;
+ text-align: center;
+}
+
+.c0 .uc-fe-calendar-last-month-cell,
+.c0 .uc-fe-calendar-month-panel-last-year-cell,
+.c0 .uc-fe-calendar-year-panel-last-decade-cell,
+.c0 .uc-fe-calendar-decade-panel-last-century-cell,
+.c0 .uc-fe-calendar-next-month-btn-day,
+.c0 .uc-fe-calendar-month-panel-next-year-cell,
+.c0 .uc-fe-calendar-year-panel-next-decade-cell,
+.c0 .uc-fe-calendar-decade-panel-next-century-cell {
+ color: #bbb;
+}
+
+.c0 .uc-fe-calendar-disabled-cell,
+.c0 .uc-fe-calendar-month-panel-cell-disabled {
+ color: #bbb;
+}
+
+.c0 .uc-fe-calendar-month-panel,
+.c0 .uc-fe-calendar-year-panel,
+.c0 .uc-fe-calendar-decade-panel {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ z-index: 1;
+}
+
+.c0 .uc-fe-calendar-today,
+.c0 .uc-fe-calendar-month-panel-current-cell {
+ position: relative;
+ color: #4074e1;
+}
+
+.c0 .uc-fe-calendar-today::after,
+.c0 .uc-fe-calendar-month-panel-current-cell::after {
+ content: '•';
+ position: absolute;
+ bottom: 0px;
+ left: 0;
+ right: 0;
+ height: 10px;
+ line-height: 10px;
+ margin: auto;
+}
+
+.c0 .uc-fe-calendar-selected-day {
+ background: #eaf3fd;
+}
+
+.c0 .uc-fe-calendar-selected-date,
+.c0 .uc-fe-calendar-month-panel-selected-cell,
+.c0 .uc-fe-calendar-year-panel-selected-cell,
+.c0 .uc-fe-calendar-decade-panel-selected-cell {
+ color: #FFF;
+ background: #4683e6;
+}
+
+.c0 .uc-fe-calendar-month-panel-year-select-arrow,
+.c0 .uc-fe-calendar-year-panel-decade-select-arrow {
+ display: none;
+}
+
+
+`;
+
exports[`Calendar demo -- rules 1`] = `
.c0.uc-fe-calendar,
.c0 .uc-fe-calendar {
diff --git a/src/components/Calendar/__tests__/index.test.js b/src/components/Calendar/__tests__/index.test.js
index 60ee13c3..868b7a8e 100644
--- a/src/components/Calendar/__tests__/index.test.js
+++ b/src/components/Calendar/__tests__/index.test.js
@@ -13,6 +13,7 @@ describe('Calendar', () => {
const now = moment.now();
const wrapper = mount();
+ wrapper.instance().focus();
wrapper.simulate('focus');
wrapper.simulate('keydown', { keyCode: KEYCODE['ARROW_DOWN'] });
expect(onChange).toHaveBeenCalledTimes(1);
@@ -31,6 +32,32 @@ describe('Calendar', () => {
});
});
+describe('Month', () => {
+ test('month keyboard action', () => {
+ const onSelect = jest.fn();
+ const onChange = jest.fn();
+ const now = moment.now();
+ const wrapper = mount();
+
+ wrapper.instance().focus();
+ wrapper.simulate('focus');
+ wrapper.simulate('keydown', { keyCode: KEYCODE['ARROW_DOWN'] });
+ expect(onChange).toHaveBeenCalledTimes(1);
+ expect(onChange.mock.calls[0][0].toString()).toBe(
+ moment(now)
+ .add({ month: 3 })
+ .toString()
+ );
+ wrapper.simulate('keydown', { keyCode: KEYCODE['ENTER'] });
+ expect(onSelect).toHaveBeenCalledTimes(1);
+ expect(onSelect.mock.calls[0][0].toString()).toBe(
+ moment(now)
+ .add({ month: 3 })
+ .toString()
+ );
+ });
+});
+
describe('utils', () => {
test('isDateDisabled', () => {
const value = moment.now();
diff --git a/src/components/Calendar/index.jsx b/src/components/Calendar/index.jsx
index 315cefb7..0bb8ca06 100644
--- a/src/components/Calendar/index.jsx
+++ b/src/components/Calendar/index.jsx
@@ -1,2 +1,5 @@
import Calendar from './Calendar';
export default Calendar;
+
+import MonthCalendar from './Month';
+Calendar.Month = MonthCalendar;
diff --git a/src/components/Calendar/style/index.js b/src/components/Calendar/style/index.js
index e15672e1..ec3141d1 100644
--- a/src/components/Calendar/style/index.js
+++ b/src/components/Calendar/style/index.js
@@ -1,5 +1,6 @@
import styled, { css } from 'styled-components';
import RcCalendar from 'rc-calendar';
+import RcMonthCalendar from 'rc-calendar/lib/MonthCalendar';
import { Color } from 'src/style';
@@ -194,3 +195,7 @@ export const calendarMixin = css`
export const CalendarWrap = styled(RcCalendar)`
${calendarMixin};
`;
+
+export const MonthCalendarWrap = styled(RcMonthCalendar)`
+ ${calendarMixin};
+`;
diff --git a/src/components/LocaleProvider/localeConsumerDecorator.jsx b/src/components/LocaleProvider/localeConsumerDecorator.jsx
index 58d9cef6..4a0ea174 100644
--- a/src/components/LocaleProvider/localeConsumerDecorator.jsx
+++ b/src/components/LocaleProvider/localeConsumerDecorator.jsx
@@ -1,8 +1,14 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
-const localeConsumerDecorator = ({ defaultLocale = {}, localeName }) => Child => {
+const localeConsumerDecorator = ({ defaultLocale = {}, localeName, publicFn = [] }) => Child => {
class LocalConsumerWrappedComponent extends Component {
+ constructor(...args) {
+ super(...args);
+ publicFn.forEach(fnName => {
+ this[fnName] = (...args) => this.child && this.child[fnName](...args);
+ });
+ }
static propTypes = {
locale: PropTypes.object
};
@@ -15,7 +21,13 @@ const localeConsumerDecorator = ({ defaultLocale = {}, localeName }) => Child =>
render() {
const { locale, ...rest } = this.props;
const context = this.context.UC_FE_LOCALE || {};
- return ;
+ return (
+ (this.child = ref)}
+ locale={{ ...defaultLocale, ...context[localeName], ...locale }}
+ {...rest}
+ />
+ );
}
}
return LocalConsumerWrappedComponent;