- {showHeader &&
-
{customHeader || convertDate(value, showFormat)}
}
+ {showHeader && (
+
+ {customHeader || convertDate(value, headerFormat)}
+
+ )}
+ {showCaption && (
+
+ {dataConfigList.map((item, index) => (
+
{item.caption}
+ ))}
+
+ )}
- {dateFormat.map((format, index) => (
+ {dataConfigList.map((item, index) => (
))}
diff --git a/lib/DatePickerItem.js b/lib/DatePickerItem.js
index 372a35c..89078b2 100644
--- a/lib/DatePickerItem.js
+++ b/lib/DatePickerItem.js
@@ -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,
@@ -74,20 +47,6 @@ class DatePickerItem extends Component
{
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);
@@ -141,7 +100,7 @@ class DatePickerItem extends Component {
}
_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));
@@ -149,7 +108,7 @@ class DatePickerItem extends Component {
}
_updateDates(direction) {
- const typeName = this.typeName;
+ const typeName = this.props.type;
const { dates } = this.state;
if (direction === 1) {
this.currentIndex ++;
@@ -325,9 +284,11 @@ class DatePickerItem extends Component {
(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 (
diff --git a/lib/dataSource.js b/lib/dataSource.js
new file mode 100644
index 0000000..d9a1f85
--- /dev/null
+++ b/lib/dataSource.js
@@ -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,
+ },
+};
+
+
+
diff --git a/lib/index.css b/lib/index.css
index 7682fa8..b8cfe8f 100644
--- a/lib/index.css
+++ b/lib/index.css
@@ -70,6 +70,19 @@
cursor: pointer;
}
+ .datepicker-caption {
+ display: flex;
+ padding: .5em .25em;
+ }
+
+ .datepicker-caption-item {
+ flex: 1;
+ margin: 0 .25em;
+ height: 40px;
+ line-height: 40px;
+ font-size: 1.2em;
+ }
+
.datepicker-content {
display: flex;
padding: .5em .25em;
@@ -129,6 +142,9 @@
border-top: 1px solid var(--default-theme);
border-bottom: 1px solid var(--default-theme);
}
+ .datepicker-caption-item {
+ color: var(--default-color);
+ }
.datepicker-scroll {
li {
color: var(--default-color);
@@ -154,6 +170,9 @@
border-top: 1px solid var(--dark-theme);
border-bottom: 1px solid var(--dark-theme);
}
+ .datepicker-caption-item {
+ color: var(--dark-color);
+ }
.datepicker-scroll {
li {
color: var(--dark-color);
@@ -186,6 +205,9 @@
border-top: 1px solid var(--ios-theme);
border-bottom: 1px solid var(--ios-theme);
}
+ .datepicker-caption-item {
+ color: var(--ios-color);
+ }
.datepicker-scroll {
li {
color: var(--ios-color);
@@ -219,6 +241,10 @@
.datepicker-header + .datepicker-content {
padding-top: 0;
}
+
+ .datepicker-caption + .datepicker-content {
+ padding-top: 0;
+ }
}
@@ -240,7 +266,9 @@
border-top: 2px solid var(--android-theme);
border-bottom: 2px solid var(--android-theme);
}
-
+ .datepicker-caption-item {
+ color: var(--android-color);
+ }
.datepicker-scroll {
li {
font-size: 1.125em;
@@ -275,6 +303,9 @@
background-image: linear-gradient(#282828,rgba(40,40,40,0)52%,rgba(40,40,40,0)48%,#282828);
}
}
+ .datepicker-caption-item {
+ color: var(--android-dark-color);
+ }
.datepicker-scroll {
li {
color: var(--android-dark-color);
diff --git a/lib/index.js b/lib/index.js
index bc09e47..b67cba2 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -2,6 +2,7 @@ import './index.css';
import React from 'react';
import DatePicker from './DatePicker.js';
import Modal from './Modal.js';
+import {defaultProps} from './dataSource';
type EnhanceDatePickerProps = T & {
isOpen: boolean,
@@ -40,21 +41,6 @@ function ModalDatePicker({ isPopup, ...props }: ModalDatePickerProps) {
);
}
-ModalDatePicker.defaultProps = {
- isPopup: true,
- isOpen: false,
- theme: 'default',
- value: new Date(),
- min: new Date(1970, 0, 1),
- max: new Date(2050, 0, 1),
- showHeader: true,
- dateFormat: ['YYYY', 'M', 'D'],
- dateSteps: [1, 1, 1],
- showFormat: 'YYYY/MM/DD',
- confirmText: '完成',
- cancelText: '取消',
- onSelect: () => {},
- onCancel: () => {},
-};
+ModalDatePicker.defaultProps = defaultProps;
export default ModalDatePicker;
diff --git a/test/functional/DatePickerItem_spec.js b/test/functional/DatePickerItem_spec.js
index 1a9779b..f9c6ada 100644
--- a/test/functional/DatePickerItem_spec.js
+++ b/test/functional/DatePickerItem_spec.js
@@ -23,7 +23,7 @@ describe('DatePickerItem.js', () => {
it('should call componentWillMount and initialize dates of state', () => {
const spyFunction = sinon.spy(DatePickerItem.prototype, 'componentWillMount');
const datePicker = mount(
-
+
);
const dates = datePicker.state('dates');
sinon.assert.calledOnce(spyFunction);
@@ -38,7 +38,7 @@ describe('DatePickerItem.js', () => {
it('componentWillReceiveProps', () => {
const spyFunction = sinon.spy(DatePickerItem.prototype, 'componentWillReceiveProps');
const datePicker = mount(
-
+
);
datePicker.setProps({ date: new Date(2010, 3, 10) });
const dates = datePicker.state('dates');
@@ -54,7 +54,7 @@ describe('DatePickerItem.js', () => {
it('shouldComponentUpdate', () => {
const spyFunction = sinon.spy(DatePickerItem.prototype, 'shouldComponentUpdate');
const datePicker = mount(
-
+
);
datePicker.setProps({ value: new Date(2010, 3, 10) });
@@ -68,7 +68,7 @@ describe('DatePickerItem.js', () => {
it('should call handleContent three times after touching', () => {
const spyFunction = sinon.spy(DatePickerItem.prototype, 'handleContentTouch');
const datePicker = mount(
-
+
);
const touchstartEvent = {
@@ -96,7 +96,7 @@ describe('DatePickerItem.js', () => {
it('should analyzing the right direction', () => {
const spyFunction = sinon.spy(DatePickerItem.prototype, '_moveToNext');
const datePicker = mount(
-
+
);
const touchstartEvent = {
targetTouches: [{ pageY: 0 }],
@@ -113,7 +113,7 @@ describe('DatePickerItem.js', () => {
expect(spyFunction.getCall(0).args[0]).to.equal(-1);
const datePicker2 = mount(
-
+
);
const touchstartEvent2 = {
targetTouches: [{ pageY: 0 }],
@@ -135,7 +135,7 @@ describe('DatePickerItem.js', () => {
it('should update dates of state, When the sliding more than 20', () => {
const spyFunction = sinon.spy(DatePickerItem.prototype, '_updateDates');
const datePicker = mount(
-
+
);
const touchstartEvent = {
targetTouches: [{ pageY: 0 }],
@@ -164,7 +164,7 @@ describe('DatePickerItem.js', () => {
const spyFunction = sinon.spy(DatePickerItem.prototype, '_moveTo');
const datePicker = mount(
-
+
);
const touchstartEvent = {
diff --git a/test/functional/DatePicker_spec.js b/test/functional/DatePicker_spec.js
index 03c3616..bfdbe55 100644
--- a/test/functional/DatePicker_spec.js
+++ b/test/functional/DatePicker_spec.js
@@ -15,8 +15,23 @@ const DEFAULT_PROPS = {
value: new Date(2016, 8, 16),
min: new Date(2015, 10, 1),
max: new Date(2020, 10, 1),
- dateFormat: ['YYYY', 'M', 'D'],
- dateSteps: [1, 1, 1],
+ dateConfig: {
+ 'year': {
+ format: 'YYYY',
+ caption: 'Year',
+ step: 1,
+ },
+ 'month': {
+ format: 'M',
+ caption: 'Mon',
+ step: 1,
+ },
+ 'date': {
+ format: 'D',
+ caption: 'Day',
+ step: 1,
+ },
+ },
isOpen: true,
}
@@ -287,13 +302,22 @@ describe('渲染正确的DatepicketItem子组件', () => {
beforeEach(() => {
props = {
value: new Date(2016, 8, 16),
- dateSteps: [1, 1, 1]
};
mountedDatepicker = undefined;
});
it('当dateFormat等于[YYYY, MM, DD]', () => {
- props.dateFormat = ['YYYY', 'MM', 'DD'];
+ props.dateConfig = {
+ 'year': {
+ format: 'YYYY',
+ },
+ 'month': {
+ format: 'MM',
+ },
+ 'date': {
+ format: 'DD',
+ },
+ };
const datePickerItems = datePicker().find(DatePickerItem);
expect(datePickerItems.length).to.equals(3);
expect(datePickerItems.at(0).props().format).to.equals('YYYY');
@@ -302,7 +326,26 @@ describe('渲染正确的DatepicketItem子组件', () => {
});
it('当dateFormat等于[YYYY, MM, DD, hh, mm, ss]', () => {
- props.dateFormat = ['YYYY', 'MM', 'DD', 'hh', 'mm', 'ss'];
+ props.dateConfig = {
+ 'year': {
+ format: 'YYYY',
+ },
+ 'month': {
+ format: 'MM',
+ },
+ 'date': {
+ format: 'DD',
+ },
+ 'hour': {
+ format: 'hh',
+ },
+ 'minute': {
+ format: 'mm',
+ },
+ 'second': {
+ format: 'ss',
+ },
+ };
const datePickerItems = datePicker().find(DatePickerItem);
expect(datePickerItems.length).to.equals(6);
expect(datePickerItems.at(0).props().format).to.equals('YYYY');
@@ -314,7 +357,17 @@ describe('渲染正确的DatepicketItem子组件', () => {
});
it('当dateFormat等于[hh, mm, ss]', () => {
- props.dateFormat = ['hh', 'mm', 'ss'];
+ props.dateConfig = {
+ 'hour': {
+ format: 'hh',
+ },
+ 'minute': {
+ format: 'mm',
+ },
+ 'second': {
+ format: 'ss',
+ },
+ };
const datePickerItems = datePicker().find(DatePickerItem);
expect(datePickerItems.length).to.equals(3);
expect(datePickerItems.at(0).props().format).to.equals('hh');
@@ -323,7 +376,7 @@ describe('渲染正确的DatepicketItem子组件', () => {
});
});
-describe('测试dateSteps属性', () => {
+describe('测试step', () => {
let props;
let mountedDatepicker;
let yearPicker, monthPicker, dayPicker;
@@ -357,8 +410,20 @@ describe('测试dateSteps属性', () => {
it ('当datesteps等于[5, 5, 5], dateFormart等于[hh, mm, ss], 当前时间为8:20:57,向上滑动秒,分钟应该为23', () => {
- props.dateFormat = ['hh', 'mm', 'ss'];
- props.dateSteps = [1, 1, 5];
+ props.dateConfig = {
+ 'hour': {
+ format: 'hh',
+ step: 1,
+ },
+ 'minute': {
+ format: 'mm',
+ step: 1,
+ },
+ 'second': {
+ format: 'ss',
+ step: 5,
+ },
+ };
const datePickerItems = datePicker().find(DatePickerItem);
const second = dayPicker.find('.datepicker-viewport').instance();
@@ -385,8 +450,21 @@ describe('测试dateSteps属性', () => {
it ('当datesteps等于[5, 5, 5], dateFormart等于[hh, mm, ss], 当前时间为8:20:57,向上滑动秒,最大时间是8:20:59, 分钟应该为22', () => {
- props.dateFormat = ['hh', 'mm', 'ss'];
- props.dateSteps = [1, 1, 5];
+ props.dateConfig = {
+ 'hour': {
+ format: 'hh',
+ step: 1,
+ },
+ 'minute': {
+ format: 'mm',
+ step: 1,
+ },
+ 'second': {
+ format: 'ss',
+ step: 5,
+ },
+ };
+
props.max = new Date(2016, 8, 16, 8, 22, 59);
const datePickerItems = datePicker().find(DatePickerItem);
@@ -412,3 +490,55 @@ describe('测试dateSteps属性', () => {
})
});
});
+
+
+describe('测试showCaption属性', () => {
+ let props;
+ let mountedDatepicker;
+
+ const datePicker = () => {
+ if (!mountedDatepicker) {
+ mountedDatepicker = mount(
+
+ );
+ }
+
+ return mountedDatepicker;
+ }
+
+ beforeEach(() => {
+ props = {
+ value: new Date(2016, 8, 16, 8, 22, 57),
+ isOpen: true,
+ };
+ mountedDatepicker = undefined;
+ });
+
+ it ('不显示说明', () => {
+ const wrapper = datePicker();
+ expect(wrapper.find('.datepicker-caption'))
+ expect(wrapper.find('.datepicker-caption')).to.have.lengthOf(0);
+ });
+ it ('显示说明', () => {
+ props.showCaption = true;
+ props.dateConfig = {
+ 'month': {
+ format: 'M',
+ caption: 'Month',
+ step: 1,
+ },
+ 'date': {
+ format: 'D',
+ caption: 'Day',
+ step: 1,
+ },
+ 'hour': {
+ format: 'hh',
+ caption: 'Hour',
+ step: 1,
+ },
+ };
+ const wrapper = datePicker();
+ expect(wrapper.find('.datepicker-caption').text()).to.be.equal('MonthDayHour');
+ });
+})
\ No newline at end of file