Skip to content

Commit

Permalink
✨ [feature] add feature of caption customized(#31)
Browse files Browse the repository at this point in the history
  • Loading branch information
lanjingling0510 committed Oct 26, 2018
1 parent fb2c2ef commit daf0b98
Show file tree
Hide file tree
Showing 8 changed files with 366 additions and 109 deletions.
35 changes: 18 additions & 17 deletions examples/basic/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,6 @@ import DatePicker from '../../lib/index';
}

render() {
const monthMap = {
'01': 'Jan',
'02': 'Feb',
'03': 'Mar',
'04': 'Apr',
'05': 'May',
'06': 'Jun',
'07': 'Jul',
'08': 'Aug',
'09': 'Sep',
'10': 'Oct',
'11': 'Nov',
'12': 'Dec',
};

return (
<div className="App">
<p className="select-time ">
Expand Down Expand Up @@ -74,11 +59,27 @@ import DatePicker from '../../lib/index';
</div>
<DatePicker
value={this.state.time}
dateSteps={[1, 1, 5]}
max={new Date()}
dateFormat={['YYYY', ['MM', (month) => monthMap[month]], 'DD']}
theme={this.state.theme}
isOpen={this.state.isOpen}
showCaption
dateConfig={{
'year': {
format: 'YYYY',
caption: '年',
step: 1,
},
'month': {
format: 'M',
caption: '月',
step: 1,
},
'date': {
format: 'D',
caption: '日',
step: 1,
},
}}
onSelect={this.handleSelect}
onCancel={this.handleToggle(false)} />
</div>
Expand Down
93 changes: 83 additions & 10 deletions lib/DatePicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import React, { Component } from 'react';
import DatePickerItem from './DatePickerItem.js';
import PureRender from './pureRender.js';
import { convertDate, nextDate } from './time.js';
import { dateConfigMap } from './dataSource';

type Props = {
theme: string,
Expand All @@ -14,9 +15,9 @@ type Props = {
max: Object,
customHeader?: React.Element<*>,
showHeader: boolean,
dateFormat: Array<*>,
dateSteps: Array<*>,
showFormat: string,
showCaption: boolean,
dateConfig: Object | Array<string>,
headerFormat: string,
confirmText: string,
cancelText: string,
onSelect: Function,
Expand All @@ -27,6 +28,18 @@ type State = {
value: Date,
}

/**
* 大写首字母
* @param {String} 字符串
*/
const capitalize = ([first, ...rest]) => first.toUpperCase() + rest.join('');

/**
* 判断数组
* @param {any} val
*/
const isArray = val => Object.prototype.toString.apply(val) === '[object Array]';

/**
* Class DatePicker Component Class
* @extends Component
Expand All @@ -38,6 +51,18 @@ class DatePicker extends Component<void, Props, State> {
value: nextDate(this.props.value),
};

if ('dateFormat' in props) {
console.warn('dateFormat已经被弃用, 请使用dateConfig属性配置');
}

if ('dateSteps' in props) {
console.warn('dateSteps已经被弃用, 请使用dateConfig属性配置');
}

if ('showFormat' in props) {
console.warn('headerFormat, 请使用dateConfig属性');
}

this.handleFinishBtnClick = this.handleFinishBtnClick.bind(this);
this.handleDateSelect = this.handleDateSelect.bind(this);
}
Expand Down Expand Up @@ -96,31 +121,79 @@ class DatePicker extends Component<void, Props, State> {
this.setState({ value });
}

/**
* 格式化dateConfig
* @param {*} dataConfig dateConfig属性
*/
normalizeDateConfig(dataConfig) {
const configList = [];
if (isArray(dataConfig)) {
for (let i = 0; i < dataConfig.length; i++) {
const value = dataConfig[i];
if (typeof value === 'string') {
const lowerCaseKey = value.toLocaleLowerCase();
configList.push({
...dateConfigMap[lowerCaseKey],
type: capitalize(lowerCaseKey),
});
}
}
} else {
for (const key in dataConfig) {
if (dataConfig.hasOwnProperty(key)) {
const lowerCaseKey = key.toLocaleLowerCase();
if (dateConfigMap.hasOwnProperty(lowerCaseKey)) {
configList.push({
...dateConfigMap[lowerCaseKey],
...dataConfig[key],
type: capitalize(lowerCaseKey),
});
}
}
}
}

return configList;
}

/**
* render函数
* @return {Object} JSX对象
*/
render() {
const { min, max, theme, dateFormat, confirmText, cancelText, showFormat, showHeader, customHeader, dateSteps } = this.props;
const { min, max, theme, dateConfig, confirmText, cancelText, headerFormat, showHeader, customHeader, showCaption } = this.props;
const value = this.state.value;
const themeClassName =
['default', 'dark', 'ios', 'android', 'android-dark'].indexOf(theme) === -1 ?
'default' : theme;


const dataConfigList = this.normalizeDateConfig(dateConfig);

return (
<div
className={`datepicker ${themeClassName}`}>
{showHeader &&
<div className="datepicker-header">{customHeader || convertDate(value, showFormat)}</div>}
{showHeader && (
<div className="datepicker-header">
{customHeader || convertDate(value, headerFormat)}
</div>
)}
{showCaption && (
<div className="datepicker-caption">
{dataConfigList.map((item, index) => (
<div key={index} className="datepicker-caption-item">{item.caption}</div>
))}
</div>
)}
<div className="datepicker-content">
{dateFormat.map((format, index) => (
{dataConfigList.map((item, index) => (
<DatePickerItem
key={index}
step={dateSteps[index] || 1}
value={value}
min={min}
max={max}
format={format}
step={item.step}
type={item.type}
format={item.format}
onSelect={this.handleDateSelect} />
))}
</div>
Expand Down
53 changes: 7 additions & 46 deletions lib/DatePickerItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,35 +13,8 @@ const MIDDLE_INDEX = Math.floor(DATE_LENGTH / 2); // 日期数组中间值
const MIDDLE_Y = - DATE_HEIGHT * MIDDLE_INDEX; // translateY值

const isUndefined = val => typeof val === 'undefined';
const isArray = val => Object.prototype.toString.apply(val) === '[object Array]';
const isFunction = val => Object.prototype.toString.apply(val) === '[object Function]';

/**
* 根据格式获取时间滑动的类别
* @param {String} format 格式
* @return {string} 类别名称
*/
const getTimeType = format => {
const typeMap = {
Y: 'Year',
M: 'Month',
D: 'Date',
h: 'Hour',
m: 'Minute',
s: 'Second',
};

for (const key in typeMap) {
if (typeMap.hasOwnProperty(key)) {
if (~format.indexOf(key)) {
return typeMap[key]
}
}
}

throw new Error('时间格式必须包含 Y, M, D, h, m 或 s字母');
}

type Props = {
value: Object,
min: Object,
Expand Down Expand Up @@ -74,20 +47,6 @@ class DatePickerItem extends Component<void, Props, State> {
marginTop: (this.currentIndex - MIDDLE_INDEX) * DATE_HEIGHT,
};

// 设置时间选择器单元的类别
if (isArray(props.format)) {
this.typeName = getTimeType(props.format[0]);
this.format = props.format[0];
if (isFunction(props.format[1])) {
this.formatTransform = props.format[1];
}
}

else {
this.format = props.format;
this.typeName = getTimeType(props.format);
}

this.renderDatepickerItem = this.renderDatepickerItem.bind(this);
this.handleContentTouch = this.handleContentTouch.bind(this);
this.handleContentMouseDown = this.handleContentMouseDown.bind(this);
Expand Down Expand Up @@ -141,15 +100,15 @@ class DatePickerItem extends Component<void, Props, State> {
}

_iniDates(date) {
const typeName = this.typeName;
const typeName = this.props.type;
const dates = Array(...Array(DATE_LENGTH))
.map((value, index) =>
TimeUtil[`next${typeName}`](date, (index - MIDDLE_INDEX) * this.props.step));
this.setState({ dates });
}

_updateDates(direction) {
const typeName = this.typeName;
const typeName = this.props.type;
const { dates } = this.state;
if (direction === 1) {
this.currentIndex ++;
Expand Down Expand Up @@ -325,9 +284,11 @@ class DatePickerItem extends Component<void, Props, State> {
(date < this.props.min || date > this.props.max) ?
'disabled' : '';

let formatDate = TimeUtil.convertDate(date, this.format);
if (this.formatTransform) {
formatDate = this.formatTransform(formatDate);
let formatDate;
if (isFunction(this.props.format)) {
formatDate = this.props.format(date);
} else {
formatDate = TimeUtil.convertDate(date, this.props.format);
}

return (
Expand Down
75 changes: 75 additions & 0 deletions lib/dataSource.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@

/**
* 默认属性
*/
export const defaultProps = {
isPopup: true,
isOpen: false,
theme: 'default',
value: new Date(),
min: new Date(1970, 0, 1),
max: new Date(2050, 0, 1),
showHeader: true,
showCaption: false,
dateConfig: {
'year': {
format: 'YYYY',
caption: 'Year',
step: 1,
},
'month': {
format: 'M',
caption: 'Mon',
step: 1,
},
'date': {
format: 'D',
caption: 'Day',
step: 1,
},
},
headerFormat: 'YYYY/MM/DD',
confirmText: '完成',
cancelText: '取消',
onSelect: () => {},
onCancel: () => {},
};

/**
* 日期配置
*/
export const dateConfigMap = {
'year': {
format: 'YYYY',
caption: 'Year',
step: 1,
},
'month': {
format: 'M',
caption: 'Mon',
step: 1,
},
'date': {
format: 'D',
caption: 'Day',
step: 1,
},
'hour': {
format: 'hh',
caption: 'Hour',
step: 1,
},
'minute': {
format: 'mm',
caption: 'Min',
step: 1,
},
'second': {
format: 'hh',
caption: 'Sec',
step: 1,
},
};



Loading

0 comments on commit daf0b98

Please sign in to comment.