Skip to content

Commit

Permalink
feat(Calendar): support rtl
Browse files Browse the repository at this point in the history
  • Loading branch information
jinli.lyy committed Nov 30, 2018
1 parent 6a30ebe commit d1c1e44
Show file tree
Hide file tree
Showing 9 changed files with 120 additions and 22 deletions.
11 changes: 9 additions & 2 deletions src/calendar/calendar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { checkMomentObj, formatDateValue, getVisibleMonth, isSameYearMonth, CALE
class Calendar extends Component {
static propTypes = {
prefix: PropTypes.string,
rtl: PropTypes.bool,
/**
* 默认选中的日期(moment 对象)
*/
Expand Down Expand Up @@ -84,6 +85,7 @@ class Calendar extends Component {

static defaultProps = {
prefix: 'next-',
rtl: false,
shape: 'fullscreen',
modes: CALENDAR_MODES,
format: 'YYYY-MM-DD',
Expand Down Expand Up @@ -188,14 +190,18 @@ class Calendar extends Component {
}

render() {
const { prefix, className, shape, showOtherMonth, format, locale, dateCellRender, monthCellRender, disabledDate, ...others } = this.props;
const { prefix, rtl, className, shape, showOtherMonth, format, locale, dateCellRender, monthCellRender, disabledDate, ...others } = this.props;
const state = this.state;

const classNames = classnames({
[`${prefix}calendar`]: true,
[`${prefix}calendar-${shape}`]: shape,
}, className);

if (rtl) {
others.dir = 'rtl';
}

const visibleMonth = state.visibleMonth;

// reset moment locale
Expand All @@ -211,6 +217,7 @@ class Calendar extends Component {
value: state.value,
mode: state.mode,
locale,
rtl,
visibleMonth,
momentLocale: localeData,
changeMode: this.changeMode,
Expand Down Expand Up @@ -242,7 +249,7 @@ class Calendar extends Component {
const tables = {
[CALENDAR_MODE_DATE]: <DateTable format={format} {...tableProps} onSelectDate={this.onSelectCell} />,
[CALENDAR_MODE_MONTH]: <MonthTable {...tableProps} onSelectMonth={this.onSelectCell} />,
[CALENDAR_MODE_YEAR]: <YearTable {...tableProps} onSelectYear={this.onSelectCell} />,
[CALENDAR_MODE_YEAR]: <YearTable {...tableProps} rtl={rtl} onSelectYear={this.onSelectCell} />,
};

const panelHeaders = {
Expand Down
15 changes: 10 additions & 5 deletions src/calendar/head/date-panel-header.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,29 @@ import Icon from '../../icon';
class DatePanelHeader extends React.PureComponent {

render() {
const { prefix, visibleMonth, momentLocale, locale, changeMode, goNextMonth, goNextYear, goPrevMonth, goPrevYear } = this.props;
const { prefix, rtl, visibleMonth, momentLocale, locale, changeMode, goNextMonth, goNextYear, goPrevMonth, goPrevYear } = this.props;

const localedMonths = momentLocale.months();
const monthLabel = localedMonths[visibleMonth.month()];
const yearLable = visibleMonth.year();
const btnCls = `${prefix}calendar-btn`;

const leftIcon = rtl ? <Icon type="arrow-right" /> : <Icon type="arrow-left" />;
const rightIcon = rtl ? <Icon type="arrow-left" /> : <Icon type="arrow-right" />;
const leftDoubleIcon = rtl ? <Icon type="arrow-double-right" /> : <Icon type="arrow-double-left" />;
const rightDoubleIcon = rtl ? <Icon type="arrow-double-left" /> : <Icon type="arrow-double-right" />;

return (<div className={`${prefix}calendar-panel-header`}>
<button
role="button"
title={locale.prevYear}
className={`${btnCls} ${btnCls}-prev-year`}
onClick={goPrevYear}><Icon type="arrow-double-left" /></button>
onClick={goPrevYear}>{leftDoubleIcon}</button>
<button
role="button"
title={locale.prevMonth}
className={`${btnCls} ${btnCls}-prev-month`}
onClick={goPrevMonth}><Icon type="arrow-left" /></button>
onClick={goPrevMonth}>{leftIcon}</button>
<div className={`${prefix}calendar-panel-header-full`}>
<button role="button" className={btnCls} title={monthLabel} onClick={() => changeMode('month', 'start')}>{monthLabel}</button>
<button role="button" className={btnCls} title={yearLable} onClick={() => changeMode('year', 'start')}>{yearLable}</button>
Expand All @@ -30,12 +35,12 @@ class DatePanelHeader extends React.PureComponent {
role="button"
title={locale.nextMonth}
className={`${btnCls} ${btnCls}-next-month`}
onClick={goNextMonth}><Icon type="arrow-right" /></button>
onClick={goNextMonth}>{rightIcon}</button>
<button
role="button"
title={locale.nextYear}
className={`${btnCls} ${btnCls}-next-year`}
onClick={goNextYear}><Icon type="arrow-double-right" /></button>
onClick={goNextYear}>{rightDoubleIcon}</button>
</div>);
}
}
Expand Down
8 changes: 5 additions & 3 deletions src/calendar/head/month-panel-header.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,26 @@ import Icon from '../../icon';
class MonthPanelHeader extends React.PureComponent {

render() {
const { prefix, visibleMonth, locale, changeMode, goPrevYear, goNextYear } = this.props;
const { prefix, rtl, visibleMonth, locale, changeMode, goPrevYear, goNextYear } = this.props;
const yearLabel = visibleMonth.year();
const btnCls = `${prefix}calendar-btn`;
const leftDoubleIcon = rtl ? <Icon type="arrow-double-right" /> : <Icon type="arrow-double-left" />;
const rightDoubleIcon = rtl ? <Icon type="arrow-double-left" /> : <Icon type="arrow-double-right" />;

return (<div className={`${prefix}calendar-panel-header`}>
<button
role="button"
title={locale.prevYear}
className={`${btnCls} ${btnCls}-prev-year`}
onClick={goPrevYear}><Icon type="arrow-double-left" /></button>
onClick={goPrevYear}>{leftDoubleIcon}</button>
<div className={`${prefix}calendar-panel-header-full`}>
<button role="button" title={yearLabel} className={`${btnCls}`} onClick={() => changeMode('year')}>{yearLabel}</button>
</div>
<button
role="button"
title={locale.nextYear}
className={`${btnCls} ${btnCls}-next-year`}
onClick={goNextYear}><Icon type="arrow-double-right" /></button>
onClick={goNextYear}>{rightDoubleIcon}</button>
</div>);
}
}
Expand Down
14 changes: 9 additions & 5 deletions src/calendar/head/range-panel-header.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,30 @@ import Icon from '../../icon';
class RangePanelHeader extends React.PureComponent {

render() {
const { prefix, startVisibleMonth, endVisibleMonth, momentLocale, locale, changeMode, goNextMonth, goNextYear, goPrevMonth, goPrevYear } = this.props;
const { prefix, rtl, startVisibleMonth, endVisibleMonth, momentLocale, locale, changeMode, goNextMonth, goNextYear, goPrevMonth, goPrevYear } = this.props;

const localedMonths = momentLocale.months();
const startMonthLabel = localedMonths[startVisibleMonth.month()];
const endMonthLabel = localedMonths[endVisibleMonth.month()];
const startYearLable = startVisibleMonth.year();
const endYearLabel = endVisibleMonth.year();
const btnCls = `${prefix}calendar-btn`;
const leftIcon = rtl ? <Icon type="arrow-right" /> : <Icon type="arrow-left" />;
const rightIcon = rtl ? <Icon type="arrow-left" /> : <Icon type="arrow-right" />;
const leftDoubleIcon = rtl ? <Icon type="arrow-double-right" /> : <Icon type="arrow-double-left" />;
const rightDoubleIcon = rtl ? <Icon type="arrow-double-left" /> : <Icon type="arrow-double-right" />;

return (<div className={`${prefix}calendar-panel-header`}>
<button
role="button"
title={locale.prevYear}
className={`${btnCls} ${btnCls}-prev-year`}
onClick={goPrevYear}><Icon type="arrow-double-left" /></button>
onClick={goPrevYear}>{leftDoubleIcon}</button>
<button
role="button"
title={locale.prevMonth}
className={`${btnCls} ${btnCls}-prev-month`}
onClick={goPrevMonth}><Icon type="arrow-left" /></button>
onClick={goPrevMonth}>{leftIcon}</button>
<div className={`${prefix}calendar-panel-header-left`}>
<button role="button" title={startMonthLabel} className={btnCls} onClick={() => changeMode('month', 'start')}>{startMonthLabel}</button>
<button role="button" title={startYearLable} className={btnCls} onClick={() => changeMode('year', 'start')}>{startYearLable}</button>
Expand All @@ -36,12 +40,12 @@ class RangePanelHeader extends React.PureComponent {
role="button"
title={locale.nextMonth}
className={`${btnCls} ${btnCls}-next-month`}
onClick={goNextMonth}><Icon type="arrow-right" /></button>
onClick={goNextMonth}>{rightIcon}</button>
<button
role="button"
title={locale.nextYear}
className={`${btnCls} ${btnCls}-next-year`}
onClick={goNextYear}><Icon type="arrow-double-right" /></button>
onClick={goNextYear}>{rightDoubleIcon}</button>
</div>);
}
}
Expand Down
8 changes: 5 additions & 3 deletions src/calendar/head/year-panel-header.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,26 @@ class YearPanelHeader extends React.PureComponent {
}

render() {
const { prefix, visibleMonth, locale, goPrevDecade, goNextDecade } = this.props;
const { prefix, rtl, visibleMonth, locale, goPrevDecade, goNextDecade } = this.props;
const decadeLable = this.getDecadeLabel(visibleMonth);
const btnCls = `${prefix}calendar-btn`;
const leftDoubleIcon = rtl ? <Icon type="arrow-double-right" /> : <Icon type="arrow-double-left" />;
const rightDoubleIcon = rtl ? <Icon type="arrow-double-left" /> : <Icon type="arrow-double-right" />;

return (<div className={`${prefix}calendar-panel-header`}>
<button
role="button"
title={locale.prevDecade}
className={`${btnCls} ${btnCls}-prev-decade`}
onClick={goPrevDecade}><Icon type="arrow-double-left" /></button>
onClick={goPrevDecade}>{leftDoubleIcon}</button>
<div className={`${prefix}calendar-panel-header-full`}>
<button role="button" title={decadeLable} className={btnCls}>{decadeLable}</button>
</div>
<button
role="button"
title={locale.nextDecade}
className={`${btnCls} ${btnCls}-next-decade`}
onClick={goNextDecade}><Icon type="arrow-double-right" /></button>
onClick={goNextDecade}>{rightDoubleIcon}</button>
</div>);
}
}
Expand Down
1 change: 1 addition & 0 deletions src/calendar/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

@import "scss/header";
@import "scss/table";
@import "./rtl.scss";

#{$calendar-prefix} {
&-table {
Expand Down
10 changes: 9 additions & 1 deletion src/calendar/range-calendar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class RangeCalendar extends React.Component {
* 样式前缀
*/
prefix: PropTypes.string,
rtl: PropTypes.bool,
/**
* 默认的开始日期
*/
Expand Down Expand Up @@ -75,6 +76,7 @@ class RangeCalendar extends React.Component {

static defaultProps = {
prefix: 'next-',
rtl: false,
mode: CALENDAR_MODE_DATE,
format: 'YYYY-MM-DD',
dateCellRender: (value) => value.date(),
Expand Down Expand Up @@ -189,7 +191,7 @@ class RangeCalendar extends React.Component {
}

render() {
const { prefix, dateCellRender, className, format, locale, showOtherMonth, disabledDate, ...others } = this.props;
const { prefix, rtl, dateCellRender, className, format, locale, showOtherMonth, disabledDate, ...others } = this.props;
const { startValue, endValue, mode, startVisibleMonth, activePanel } = this.state;

// reset moment locale
Expand All @@ -199,11 +201,16 @@ class RangeCalendar extends React.Component {
startVisibleMonth.locale(locale.momentLocale);
}

if (rtl) {
others.dir = 'rtl';
}

const localeData = startVisibleMonth.localeData();
const endVisibleMonth = startVisibleMonth.clone().add(1, 'months');

const headerProps = {
prefix,
rtl,
mode,
locale,
momentLocale: localeData,
Expand Down Expand Up @@ -264,6 +271,7 @@ class RangeCalendar extends React.Component {
case CALENDAR_MODE_YEAR: {
table = (<YearTable
{...tableProps}
rtl={rtl}
visibleMonth={visibleMonth}
onSelectYear={this.onSelectCell}
goPrevDecade={this.goPrevDecade}
Expand Down
69 changes: 69 additions & 0 deletions src/calendar/rtl.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#{$calendar-prefix}[dir='rtl'] {
#{$calendar-prefix} {
&-header {
text-align: left;

#{$calendar-select-prefix} {
margin-right: 0;
margin-left: $s-1;
}

#{$calendar-menu-prefix} {
text-align: right;
}
}
&-btn-prev-decade,
&-btn-prev-year {
left: auto;
right: $calendar-btn-arrow-double-offset-lr;
}

&-btn-prev-month {
left: auto;
right: $calendar-btn-arrow-single-offset-lr;
}

&-btn-next-month {
right: auto;
left: $calendar-btn-arrow-single-offset-lr;
}

&-btn-next-year,
&-btn-next-decade {
right: auto;
left: $calendar-btn-arrow-double-offset-lr;
}
}
}

#{$calendar-prefix}-fullscreen[dir='rtl'] {
#{$calendar-prefix} {
&-th {
text-align: left;
padding-left: $calendar-fullscreen-table-head-padding-r;
padding-right: 0;
}
&-date,
&-month {
text-align: left;
}
}
}

#{$calendar-prefix}-range[dir='rtl'] {
#{$calendar-prefix} {
&-body-left, &-body-right {
float: right;
}

&-body-left {
padding-right: 0;
padding-left: $s-2;
}

&-body-right {
padding-left: 0;
padding-right: $s-2;
}
}
}
6 changes: 3 additions & 3 deletions src/calendar/table/year-table.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class YearTable extends React.PureComponent {
}

render() {
const { prefix, value, today, visibleMonth, locale, disabledDate, goPrevDecade, goNextDecade } = this.props;
const { prefix, rtl, value, today, visibleMonth, locale, disabledDate, goPrevDecade, goNextDecade } = this.props;
const currentYear = today.year();
const selectedYear = value ? value.year() : null;
const visibleYear = visibleMonth.year();
Expand All @@ -34,11 +34,11 @@ class YearTable extends React.PureComponent {
if (i === 0 && j === 0) {
title = locale.prevDecade;
onClick = goPrevDecade;
content = <Icon type="arrow-left" size="xs" />;
content = rtl ? <Icon type="arrow-right" size="xs" /> : <Icon type="arrow-left" size="xs" />;
} else if (i === lastRowIndex && j === lastColIndex) {
title = locale.nextDecade;
onClick = goNextDecade;
content = <Icon type="arrow-right" size="xs" />;
content = rtl ? <Icon type="arrow-left" size="xs" /> : <Icon type="arrow-right" size="xs" />;
} else {
year = startYear + counter++;
content = year;
Expand Down

0 comments on commit d1c1e44

Please sign in to comment.