From b01a6f4e8111bb8beb75deb4a79c7c301cd86120 Mon Sep 17 00:00:00 2001 From: zazzaz Date: Wed, 16 Sep 2020 14:49:21 +0800 Subject: [PATCH] feat: Feature/timepicker && repeat-click directive (#289) * feat: Feature/datepicker && repeat-click directive (#288) * style: fix lint * test: fix local test * test: update test * fix: update api to disabledHours * chore: update * chore: fix lint --- packages/button/index.ts | 2 + .../directives/__tests__/repeat-click.spec.ts | 35 ++ packages/directives/click-outside/index.ts | 4 +- packages/directives/index.ts | 1 + packages/directives/repeat-click/index.ts | 24 + packages/element-plus/index.ts | 3 + packages/element-plus/package.json | 1 + packages/locale/__test__/locale.spec.ts | 2 +- packages/locale/index.ts | 2 +- .../time-picker/__tests__/time-picker.spec.ts | 343 +++++++++++ packages/time-picker/index.ts | 5 + packages/time-picker/package.json | 12 + packages/time-picker/src/common/constant.ts | 12 + packages/time-picker/src/common/picker.vue | 577 ++++++++++++++++++ .../time-picker-com/basic-time-spinner.vue | 362 +++++++++++ .../src/time-picker-com/panel-time-pick.vue | 224 +++++++ .../src/time-picker-com/panel-time-range.vue | 340 +++++++++++ .../src/time-picker-com/useTimePicker.ts | 63 ++ packages/time-picker/src/time-picker.ts | 29 + packages/utils/util.ts | 5 +- src/utils/resize-event.ts | 4 +- website/docs/en-US/date-picker.md | 4 +- website/docs/en-US/datetime-picker.md | 4 +- website/docs/es/date-picker.md | 4 +- website/docs/es/datetime-picker.md | 4 +- website/docs/fr-FR/date-picker.md | 4 +- website/docs/fr-FR/datetime-picker.md | 4 +- website/docs/zh-CN/date-picker.md | 4 +- website/docs/zh-CN/datetime-picker.md | 4 +- 29 files changed, 2059 insertions(+), 23 deletions(-) create mode 100644 packages/directives/__tests__/repeat-click.spec.ts create mode 100644 packages/directives/repeat-click/index.ts create mode 100644 packages/time-picker/__tests__/time-picker.spec.ts create mode 100644 packages/time-picker/index.ts create mode 100644 packages/time-picker/package.json create mode 100644 packages/time-picker/src/common/constant.ts create mode 100644 packages/time-picker/src/common/picker.vue create mode 100644 packages/time-picker/src/time-picker-com/basic-time-spinner.vue create mode 100644 packages/time-picker/src/time-picker-com/panel-time-pick.vue create mode 100644 packages/time-picker/src/time-picker-com/panel-time-range.vue create mode 100644 packages/time-picker/src/time-picker-com/useTimePicker.ts create mode 100644 packages/time-picker/src/time-picker.ts diff --git a/packages/button/index.ts b/packages/button/index.ts index f8549ec2b2..ad34183422 100644 --- a/packages/button/index.ts +++ b/packages/button/index.ts @@ -6,3 +6,5 @@ export default (app: App): void => { app.component(Button.name, Button) app.component(ButtonGroup.name, ButtonGroup) } + +export { Button } diff --git a/packages/directives/__tests__/repeat-click.spec.ts b/packages/directives/__tests__/repeat-click.spec.ts new file mode 100644 index 0000000000..595cf85c90 --- /dev/null +++ b/packages/directives/__tests__/repeat-click.spec.ts @@ -0,0 +1,35 @@ +import { sleep } from '@element-plus/test-utils' +import { mount } from '@vue/test-utils' +import RepeatClick from '../repeat-click' + +const handler = jest.fn() +const _mount = () => mount({ + template: ` +
TEST
+ `, + directives: { + repeatClick: RepeatClick, + }, + methods: { + onClick() { + handler() + }, + }, +}) + +beforeEach(() => { + handler.mockClear() +}) + +describe('Directives.vue', () => { + test('Click test', async () => { + const wrapper = _mount() + const block = wrapper.find('#block') + block.trigger('mousedown') + const testTime = 330 + await sleep(testTime) + block.trigger('mouseup') + const expectResult = Math.floor(testTime / 100) + expect(handler).toHaveBeenCalledTimes(expectResult) + }) +}) diff --git a/packages/directives/click-outside/index.ts b/packages/directives/click-outside/index.ts index a26339aeb3..98ba3b0e79 100644 --- a/packages/directives/click-outside/index.ts +++ b/packages/directives/click-outside/index.ts @@ -1,7 +1,7 @@ -import isServer from '@element-plus/utils/isServer' import { on } from '@element-plus/utils/dom' +import isServer from '@element-plus/utils/isServer' +import type { ComponentPublicInstance, DirectiveBinding, ObjectDirective } from 'vue' -import type { DirectiveBinding, ObjectDirective, ComponentPublicInstance } from 'vue' type DocumentHandler = (mouseup: T, mousedown: T) => void; diff --git a/packages/directives/index.ts b/packages/directives/index.ts index bc871f62fd..dc6d1195b3 100644 --- a/packages/directives/index.ts +++ b/packages/directives/index.ts @@ -1,2 +1,3 @@ export { default as ClickOutside } from './click-outside' +export { default as RepeatClick } from './repeat-click' export { default as TrapFocus } from './trap-focus' diff --git a/packages/directives/repeat-click/index.ts b/packages/directives/repeat-click/index.ts new file mode 100644 index 0000000000..24daa0538a --- /dev/null +++ b/packages/directives/repeat-click/index.ts @@ -0,0 +1,24 @@ +import { on, once } from '@element-plus/utils/dom' + +export default { + beforeMount(el, binding) { + let interval = null + let startTime + const handler = () => binding.value && binding.value() + const clear = () => { + if (Date.now() - startTime < 100) { + handler() + } + clearInterval(interval) + interval = null + } + + on(el, 'mousedown', e => { + if ((e as any).button !== 0) return + startTime = Date.now() + once(document as any, 'mouseup', clear) + clearInterval(interval) + interval = setInterval(handler, 100) + }) + }, +} diff --git a/packages/element-plus/index.ts b/packages/element-plus/index.ts index 987a2d9966..8b5f958094 100644 --- a/packages/element-plus/index.ts +++ b/packages/element-plus/index.ts @@ -27,6 +27,7 @@ import ElScrollBar from '@element-plus/scrollbar' import ElSteps from '@element-plus/steps' import ElCollapse from '@element-plus/collapse' import ElPopper from '@element-plus/popper' +import ElTimePicker from '@element-plus/time-picker' import ElTabs from '@element-plus/tabs' import ElTooltip from '@element-plus/tooltip' import ElSlider from '@element-plus/slider' @@ -63,6 +64,7 @@ export { ElSteps, ElRadio, ElCollapse, + ElTimePicker, ElTabs, ElTooltip, ElSlider, @@ -101,6 +103,7 @@ const install = (app: App): void => { ElRadio(app) ElCollapse(app) ElPopper(app) + ElTimePicker(app) ElTabs(app) ElTooltip(app) ElSlider(app) diff --git a/packages/element-plus/package.json b/packages/element-plus/package.json index 9844113910..87f03436c2 100644 --- a/packages/element-plus/package.json +++ b/packages/element-plus/package.json @@ -36,6 +36,7 @@ "@element-plus/steps": "^0.0.0", "@element-plus/notification": "^0.0.0", "@element-plus/collapse": "^0.0.0", + "@element-plus/time-picker": "^0.0.0", "@element-plus/tabs": "^0.0.0" } } diff --git a/packages/locale/__test__/locale.spec.ts b/packages/locale/__test__/locale.spec.ts index e06121e96c..e10bba2070 100644 --- a/packages/locale/__test__/locale.spec.ts +++ b/packages/locale/__test__/locale.spec.ts @@ -10,7 +10,7 @@ describe('Locale', () => { }) test('return key name if not defined', () => { - expect(t('el.popconfirm.someThing')).toBe('someThing') + expect(t('el.popconfirm.someThing')).toBeUndefined() }) test('use', () => { diff --git a/packages/locale/index.ts b/packages/locale/index.ts index 73efd45124..f8d822a830 100644 --- a/packages/locale/index.ts +++ b/packages/locale/index.ts @@ -8,7 +8,7 @@ export const t = (path:string): string => { let current = lang for (let i = 0, j = array.length; i < j; i++) { const property = array[i] - value = current[property] || property + value = current[property] if (i === j - 1) return value if (!value) return '' current = value diff --git a/packages/time-picker/__tests__/time-picker.spec.ts b/packages/time-picker/__tests__/time-picker.spec.ts new file mode 100644 index 0000000000..3664e15eb8 --- /dev/null +++ b/packages/time-picker/__tests__/time-picker.spec.ts @@ -0,0 +1,343 @@ +import { mount } from '@vue/test-utils' +import { nextTick } from 'vue' +import TimePicker from '../src/time-picker' + +const _mount = (template: string, data, otherObj?) => mount({ + components: { + 'el-time-picker': TimePicker, + }, + template, + data, + ...otherObj, +}, { + global: { + provide: { + elForm: {}, + elFormItem: {}, + }, + }, +}) + +const makeRange = (start, end) => { + const result = [] + for (let i = start; i <= end; i++) { + result.push(i) + } + return result +} + +const getSpinnerTextAsArray = (dom, selector) => { + return [].slice + .call(dom.querySelectorAll(selector)) + .map(node => Number(node.textContent)) +} + +afterEach(() => { + document.documentElement.innerHTML = '' +}) + +describe('TimePicker', () => { + it('create', async () => { + const wrapper = _mount(``, () => ({ placeholder: 'test_', + readonly: true })) + const input = wrapper.find('input') + expect(input.attributes('placeholder')).toBe('test_') + expect(input.attributes('readonly')).not.toBeUndefined() + }) + + it('set format && default value && set AM/PM spinner', async () => { + const wrapper = _mount(``, () => ({ format: 'hh-mm:ss A', + value: new Date(2016, 9, 10, 18, 40) })) + await nextTick() + const input = wrapper.find('input') + expect(input.element.value).toBe('06-40:00 PM') // format + input.trigger('blur') + input.trigger('focus') + await nextTick() + const list = document.querySelectorAll('.el-time-spinner__list') + const hoursEl = list[0] + const items = hoursEl.querySelectorAll('.el-time-spinner__item') + expect(items[0].textContent).toBe('12 AM') // am pm + expect(items[1].textContent).toBe('01 AM') + expect(items[12].textContent).toBe('12 PM') + expect(items[15].textContent).toBe('03 PM') + const times = document.querySelectorAll('.el-time-spinner__list .active') + expect(times[0].textContent).toBe('06 PM') + expect(times[1].textContent).toBe('40') // default value + expect(times[2].textContent).toBe('00') + }) + + it('select time', async () => { + const wrapper = _mount(``, () => ({ value: '' })) + const input = wrapper.find('input') + input.trigger('blur') + input.trigger('focus') + await nextTick() + const list = document.querySelectorAll('.el-time-spinner__list') + const hoursEl = list[0] + const minutesEl = list[1] + const secondsEl = list[2] + const hourEl = hoursEl.querySelectorAll('.el-time-spinner__item')[4] as any + const minuteEl = minutesEl.querySelectorAll('.el-time-spinner__item')[36] as any + const secondEl = secondsEl.querySelectorAll('.el-time-spinner__item')[20] as any + // click hour, minute, second one at a time. + hourEl.click() + await nextTick() + minuteEl.click() + await nextTick() + secondEl.click() + await nextTick() + const vm = wrapper.vm as any + const date = vm.value + expect(hourEl.classList.contains('active')).toBeTruthy() + expect(minuteEl.classList.contains('active')).toBeTruthy() + expect(secondEl.classList.contains('active')).toBeTruthy() + expect(date.getHours()).toBe(4) + expect(date.getMinutes()).toBe(36) + expect(date.getSeconds()).toBe(20) + }) + + it('click confirm / cancel button', async () => { + const wrapper = _mount(``, () => ({ value: '' })) + const input = wrapper.find('input') + input.trigger('blur') + input.trigger('focus') + await nextTick(); + (document.querySelector('.el-time-panel__btn.cancel') as any).click() + const vm = wrapper.vm as any + expect(vm.value).toBe('') + input.trigger('blur') + input.trigger('focus') + await nextTick(); + (document.querySelector('.el-time-panel__btn.confirm') as any).click() + expect(vm.value instanceof Date).toBeTruthy() + }) + + it('set format', async () => { + const wrapper = _mount(``, () => ({ value: '' })) + const input = wrapper.find('input') + input.trigger('blur') + input.trigger('focus') + await nextTick() + const spinnerDom = document.querySelectorAll('.el-time-spinner__wrapper') + const minutesDom = spinnerDom[1] + const secondsDom = spinnerDom[2] + expect(minutesDom).not.toBeUndefined() + expect(secondsDom).toBeUndefined() + }) + + it('event change, focus, blur', async () => { + const changeHandler = jest.fn() + const focusHandler = jest.fn() + const blurHandler = jest.fn() + const wrapper = _mount(``, () => ({ value: new Date(2016, 9, 10, 18, 40) }), { + methods: { + onChange(e) { + return changeHandler(e) + }, + onFocus(e) { + return focusHandler(e) + }, + onBlur(e) { + return blurHandler(e) + }, + }, + }) + + const input = wrapper.find('input') + input.trigger('focus') + await nextTick() + expect(focusHandler).toHaveBeenCalledTimes(1) + const list = document.querySelectorAll('.el-time-spinner__list') + const hoursEl = list[0] + const hourEl = hoursEl.querySelectorAll('.el-time-spinner__item')[4] as any + hourEl.click() + await nextTick() + expect(changeHandler).toHaveBeenCalledTimes(1); + (document.querySelector('.el-time-panel__btn.cancel') as any).click() + await nextTick() + expect(blurHandler).toHaveBeenCalledTimes(1) + }) + + it('selectableRange ', async () => { + // ['17:30:00 - 18:30:00', '18:50:00 - 20:30:00', '21:00:00 - 22:00:00'] + const disabledHoursArr = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,23] + const wrapper = _mount(``, () => ({ value: '' }), { + methods: { + disabledHours() { + return disabledHoursArr + }, + disabledMinutes (hour) { + // ['17:30:00 - 18:30:00', '18:50:00 - 20:30:00', '21:00:00 - 22:00:00'] + if (hour === 17) { + return makeRange(0, 29) + } + if (hour === 18) { + return makeRange(31, 49) + } + if (hour === 20) { + return makeRange(31, 59) + } + if (hour === 22) { + return makeRange(1, 59) + } + }, + disabledSeconds(hour, minute) { + if (hour === 18 && minute === 30) { + return makeRange(1, 59) + } + if (hour === 20 && minute === 30) { + return makeRange(1, 59) + } + if (hour === 22 && minute === 0) { + return makeRange(1, 59) + } + }, + }, + }) + const input = wrapper.find('input') + input.trigger('focus') + await nextTick() + + const list = document.querySelectorAll('.el-time-spinner__list') + const hoursEl = list[0] + const minutesEl = list[1] + const secondsEl = list[2] + const disabledHours = getSpinnerTextAsArray(hoursEl, '.disabled') + expect(disabledHours).toEqual(disabledHoursArr) + const hourSpinners = hoursEl.querySelectorAll('.el-time-spinner__item'); + (hourSpinners[18] as any).click() + await nextTick() + const disabledMinutes = getSpinnerTextAsArray(minutesEl, '.disabled') + expect(disabledMinutes.every(t => t > 30 && t < 50)).toBeTruthy() + expect(disabledMinutes.length).toEqual(19); + (hourSpinners[22] as any).click() + await nextTick() + const enabledMinutes = getSpinnerTextAsArray(minutesEl, ':not(.disabled)') + const enabledSeconds = getSpinnerTextAsArray(secondsEl, ':not(.disabled)') + expect(enabledMinutes).toEqual([0]) + expect(enabledSeconds).toEqual([0]) + }) +}) + +describe('TimePicker(range)', () => { + it('create', async () => { + const wrapper = _mount(``, () => ({ value: [new Date(2016, 9, 10, 18, 40), new Date(2016, 9, 10, 19, 40)] })) + expect(wrapper.find('.el-range-editor--mini').exists()).toBeTruthy() + const input = wrapper.find('input') + input.trigger('blur') + input.trigger('focus') + await nextTick() + const list = document.querySelectorAll('.el-time-spinner__list .el-time-spinner__item.active'); + + ['18','40','00','19','40','00'].forEach((_, i) => { + expect(list[i].textContent).toBe(_) + }) + }) + + it('default value', async() => { + const defaultValue = [new Date(2000, 9, 1, 10, 20, 0), new Date(2000, 9, 1, 11, 10, 0)] + const wrapper = _mount(``, () => ({ value: '', + defaultValue })) + + const input = wrapper.find('input') + input.trigger('blur') + input.trigger('focus') + await nextTick() + + const list = document.querySelectorAll('.el-time-spinner__list .el-time-spinner__item.active'); + + ['10','20','00','11','10','00'].forEach((_, i) => { + expect(list[i].textContent).toBe(_) + }) + }) + + it('cancel button', async () => { + const wrapper = _mount(``, () => ({ value: '' })) + + const input = wrapper.find('input') + input.trigger('blur') + input.trigger('focus') + await nextTick(); + (document.querySelector('.el-time-panel__btn.cancel') as any).click() + await nextTick() + const vm = wrapper.vm as any + expect(vm.value).toBe('') + input.trigger('blur') + input.trigger('focus') + await nextTick(); + (document.querySelector('.el-time-panel__btn.confirm') as any).click() + expect(vm.value instanceof Array).toBeTruthy() + vm.value.forEach(_ => { + expect(_ instanceof Date).toBeTruthy() + }) + }) + + it('selectableRange ', async () => { + // left ['08:00:00 - 12:59:59'] right ['11:00:00 - 16:59:59'] + const wrapper = _mount(``, () => ({ value: [new Date(2016, 9, 10, 9, 40), new Date(2016, 9, 10, 15, 40)] }), { + methods: { + disabledHours(role) { + if (role === 'start') { + return makeRange(0, 7).concat(makeRange(13, 23)) + } + return makeRange(0, 10).concat(makeRange(17, 23)) + }, + }, + }) + const input = wrapper.find('input') + input.trigger('focus') + await nextTick() + + const list = document.querySelectorAll('.el-time-spinner__list') + const leftHoursEl = list[0] + const leftEndbledHours = getSpinnerTextAsArray(leftHoursEl, ':not(.disabled)') + expect(leftEndbledHours).toEqual([ 8, 9, 10, 11, 12 ]) + const rightHoursEl = list[3] + const rightEndbledHours = getSpinnerTextAsArray(rightHoursEl, ':not(.disabled)') + expect(rightEndbledHours).toEqual([ 11, 12, 13, 14, 15, 16 ]); + (leftHoursEl.querySelectorAll('.el-time-spinner__item')[12] as any).click() + await nextTick() + const NextRightEndbledHours = getSpinnerTextAsArray(rightHoursEl, ':not(.disabled)') + expect(NextRightEndbledHours).toEqual([ 12, 13, 14, 15, 16 ]) + }) +}) + diff --git a/packages/time-picker/index.ts b/packages/time-picker/index.ts new file mode 100644 index 0000000000..e7daddf0ca --- /dev/null +++ b/packages/time-picker/index.ts @@ -0,0 +1,5 @@ +import { App } from 'vue' +import TimePicker from './src/time-picker' +export default (app: App): void => { + app.component(TimePicker.name, TimePicker) +} diff --git a/packages/time-picker/package.json b/packages/time-picker/package.json new file mode 100644 index 0000000000..c681b7805a --- /dev/null +++ b/packages/time-picker/package.json @@ -0,0 +1,12 @@ +{ + "name": "@element-plus/time-picker", + "version": "0.0.0", + "main": "dist/index.js", + "license": "MIT", + "peerDependencies": { + "vue": "^3.0.0-rc.1" + }, + "devDependencies": { + "@vue/test-utils": "^2.0.0-beta.0" + } +} diff --git a/packages/time-picker/src/common/constant.ts b/packages/time-picker/src/common/constant.ts new file mode 100644 index 0000000000..41241d8643 --- /dev/null +++ b/packages/time-picker/src/common/constant.ts @@ -0,0 +1,12 @@ +// daterange: 'YYYY-MM-DD', +// monthrange: 'YYYY-MM', +// datetimerange: 'yyyy-MM-DD HH:mm:ss', +export const DEFAULT_FORMATS_TIME = 'HH:mm:ss' +export const DEFAULT_FORMATS_DATE = 'YYYY-MM-DD' +export const DEFAULT_FORMATS_DATEPICKER = { + 'date': DEFAULT_FORMATS_DATE, + 'week': 'YYYYwWW', + 'year': 'YYYY', + 'month': 'YYYY-MM', + 'datetime': 'YYYY-MM-DD HH:mm:ss', +} diff --git a/packages/time-picker/src/common/picker.vue b/packages/time-picker/src/common/picker.vue new file mode 100644 index 0000000000..775ab27789 --- /dev/null +++ b/packages/time-picker/src/common/picker.vue @@ -0,0 +1,577 @@ + + diff --git a/packages/time-picker/src/time-picker-com/basic-time-spinner.vue b/packages/time-picker/src/time-picker-com/basic-time-spinner.vue new file mode 100644 index 0000000000..c77f0b13dd --- /dev/null +++ b/packages/time-picker/src/time-picker-com/basic-time-spinner.vue @@ -0,0 +1,362 @@ + + diff --git a/packages/time-picker/src/time-picker-com/panel-time-pick.vue b/packages/time-picker/src/time-picker-com/panel-time-pick.vue new file mode 100644 index 0000000000..4e642b3adf --- /dev/null +++ b/packages/time-picker/src/time-picker-com/panel-time-pick.vue @@ -0,0 +1,224 @@ + + + + diff --git a/packages/time-picker/src/time-picker-com/panel-time-range.vue b/packages/time-picker/src/time-picker-com/panel-time-range.vue new file mode 100644 index 0000000000..961311ad29 --- /dev/null +++ b/packages/time-picker/src/time-picker-com/panel-time-range.vue @@ -0,0 +1,340 @@ + + + + diff --git a/packages/time-picker/src/time-picker-com/useTimePicker.ts b/packages/time-picker/src/time-picker-com/useTimePicker.ts new file mode 100644 index 0000000000..a46f39fa1d --- /dev/null +++ b/packages/time-picker/src/time-picker-com/useTimePicker.ts @@ -0,0 +1,63 @@ +const makeList = (total, method, methodFunc) => { + const arr = [] + const disabledArr = method && methodFunc() + for (let i = 0; i < total; i++) { + arr[i] = disabledArr ? disabledArr.includes(i) : false + } + return arr +} + +const makeAvaliableArr = list => { + return list.map((_, index) => !_ ? index : _).filter(_ => _ !== true) +} + +export const getTimeLists = (disabledHours, disabledMinutes, disabledSeconds) => { + const getHoursList = (role, compare?) => { + return makeList(24, disabledHours, () => disabledHours(role, compare)) + } + + const getMinutesList = (hour, role, compare?) => { + return makeList(60, disabledMinutes, () => disabledMinutes(hour, role, compare)) + } + + const getSecondsList = (hour, minute, role, compare?) => { + return makeList(60, disabledSeconds, () => disabledSeconds(hour, minute, role, compare)) + } + + return { + getHoursList, + getMinutesList, + getSecondsList, + } +} + + +export const getAvaliableArrs = (disabledHours, disabledMinutes, disabledSeconds) => { + const { + getHoursList, + getMinutesList, + getSecondsList, + } = getTimeLists( + disabledHours, + disabledMinutes, + disabledSeconds, + ) + + const getAvaliableHours = (role, compare?) => { + return makeAvaliableArr(getHoursList(role, compare)) + } + + const getAvaliableMinutes = (hour, role, compare?) => { + return makeAvaliableArr(getMinutesList(hour, role, compare)) + } + + const getAvaliableSeconds = (hour, minute, role, compare?) => { + return makeAvaliableArr(getSecondsList(hour, minute, role, compare)) + } + + return { + getAvaliableHours, + getAvaliableMinutes, + getAvaliableSeconds, + } +} diff --git a/packages/time-picker/src/time-picker.ts b/packages/time-picker/src/time-picker.ts new file mode 100644 index 0000000000..ca957a2ae4 --- /dev/null +++ b/packages/time-picker/src/time-picker.ts @@ -0,0 +1,29 @@ +import dayjs from 'dayjs' +import customParseFormat from 'dayjs/plugin/customParseFormat' +import { h } from 'vue' +import { DEFAULT_FORMATS_TIME } from './common/constant' +import Picker from './common/picker.vue' +import TimePickPanel from './time-picker-com/panel-time-pick.vue' +import TimeRangePanel from './time-picker-com/panel-time-range.vue' +dayjs.extend(customParseFormat) +export default { + name: 'ElTimePicker', + props: { + isRange: { + type: Boolean, + default: false, + }, + }, + setup(props) { + const type = props.isRange ? 'timerange' : 'time' + const panel = props.isRange ? TimeRangePanel : TimePickPanel + return () => h(Picker, { + format: DEFAULT_FORMATS_TIME, + ...props, + type, + }, + { + default: scopedProps => h(panel, scopedProps), + }) + }, +} diff --git a/packages/utils/util.ts b/packages/utils/util.ts index 5222ad606a..7acdef22f8 100644 --- a/packages/utils/util.ts +++ b/packages/utils/util.ts @@ -79,7 +79,10 @@ export const escapeRegexpString = (value = ''): string => // Use native Array.find, Array.findIndex instead // coerce truthy value to array -export const coerceTruthyValueToArray = castArray +export const coerceTruthyValueToArray = arr => { + if (!arr) { return [] } + return castArray(arr) +} export const isIE = function(): boolean { return !isServer && !isNaN(Number(document.DOCUMENT_NODE)) diff --git a/src/utils/resize-event.ts b/src/utils/resize-event.ts index 42a71dae46..9fa30aed96 100644 --- a/src/utils/resize-event.ts +++ b/src/utils/resize-event.ts @@ -1,5 +1,5 @@ import ResizeObserver from 'resize-observer-polyfill' - +import { NOOP } from '@vue/shared' const isServer = typeof window === 'undefined' // TODO: add hack prototype __resizeListeners__ @@ -21,7 +21,7 @@ export const addResizeListener = function(element, fn) { if (isServer) return if (!element.__resizeListeners__) { element.__resizeListeners__ = [] - element.__ro__ = new ResizeObserver(() => {}) + element.__ro__ = new ResizeObserver(NOOP) element.__ro__.observe(element) } element.__resizeListeners__.push(fn) diff --git a/website/docs/en-US/date-picker.md b/website/docs/en-US/date-picker.md index 0b43664feb..128ad46d0f 100644 --- a/website/docs/en-US/date-picker.md +++ b/website/docs/en-US/date-picker.md @@ -48,14 +48,14 @@ Basic date picker measured by 'day'. onClick(picker) { const date = new Date(); date.setTime(date.getTime() - 3600 * 1000 * 24); - picker.$emit('pick', date); + picker.emit('pick', date); } }, { text: 'A week ago', onClick(picker) { const date = new Date(); date.setTime(date.getTime() - 3600 * 1000 * 24 * 7); - picker.$emit('pick', date); + picker.emit('pick', date); } }] }, diff --git a/website/docs/en-US/datetime-picker.md b/website/docs/en-US/datetime-picker.md index ef14e13eee..7f86e4ae63 100644 --- a/website/docs/en-US/datetime-picker.md +++ b/website/docs/en-US/datetime-picker.md @@ -55,14 +55,14 @@ DateTimePicker is derived from DatePicker and TimePicker. For a more detailed ex onClick(picker) { const date = new Date(); date.setTime(date.getTime() - 3600 * 1000 * 24); - picker.$emit('pick', date); + picker.emit('pick', date); } }, { text: 'A week ago', onClick(picker) { const date = new Date(); date.setTime(date.getTime() - 3600 * 1000 * 24 * 7); - picker.$emit('pick', date); + picker.emit('pick', date); } }] }, diff --git a/website/docs/es/date-picker.md b/website/docs/es/date-picker.md index dd9b86beaf..f9195a0bd3 100644 --- a/website/docs/es/date-picker.md +++ b/website/docs/es/date-picker.md @@ -49,14 +49,14 @@ Date Picker básico por "día". onClick(picker) { const date = new Date(); date.setTime(date.getTime() - 3600 * 1000 * 24); - picker.$emit('pick', date); + picker.emit('pick', date); } }, { text: 'A week ago', onClick(picker) { const date = new Date(); date.setTime(date.getTime() - 3600 * 1000 * 24 * 7); - picker.$emit('pick', date); + picker.emit('pick', date); } }] }, diff --git a/website/docs/es/datetime-picker.md b/website/docs/es/datetime-picker.md index 0209838899..7293836a03 100644 --- a/website/docs/es/datetime-picker.md +++ b/website/docs/es/datetime-picker.md @@ -56,14 +56,14 @@ DateTimePicker se deriva de DatePicker y TimePicker. Por una explicación más d onClick(picker) { const date = new Date(); date.setTime(date.getTime() - 3600 * 1000 * 24); - picker.$emit('pick', date); + picker.emit('pick', date); } }, { text: 'A week ago', onClick(picker) { const date = new Date(); date.setTime(date.getTime() - 3600 * 1000 * 24 * 7); - picker.$emit('pick', date); + picker.emit('pick', date); } }] }, diff --git a/website/docs/fr-FR/date-picker.md b/website/docs/fr-FR/date-picker.md index 1b40290f6c..faf8e6017c 100644 --- a/website/docs/fr-FR/date-picker.md +++ b/website/docs/fr-FR/date-picker.md @@ -47,14 +47,14 @@ L'unité de base du DatePicker est le jour. onClick(picker) { const date = new Date(); date.setTime(date.getTime() - 3600 * 1000 * 24); - picker.$emit('pick', date); + picker.emit('pick', date); } }, { text: 'Il y a une semaine', onClick(picker) { const date = new Date(); date.setTime(date.getTime() - 3600 * 1000 * 24 * 7); - picker.$emit('pick', date); + picker.emit('pick', date); } }] }, diff --git a/website/docs/fr-FR/datetime-picker.md b/website/docs/fr-FR/datetime-picker.md index 64609219e8..55eb8dbea2 100644 --- a/website/docs/fr-FR/datetime-picker.md +++ b/website/docs/fr-FR/datetime-picker.md @@ -55,14 +55,14 @@ DateTimePicker est dérivé de DatePicker et TimePicker. Pour plus d'information onClick(picker) { const date = new Date(); date.setTime(date.getTime() - 3600 * 1000 * 24); - picker.$emit('pick', date); + picker.emit('pick', date); } }, { text: 'Il y a une semaine', onClick(picker) { const date = new Date(); date.setTime(date.getTime() - 3600 * 1000 * 24 * 7); - picker.$emit('pick', date); + picker.emit('pick', date); } }] }, diff --git a/website/docs/zh-CN/date-picker.md b/website/docs/zh-CN/date-picker.md index aa976775ab..8d458e5246 100644 --- a/website/docs/zh-CN/date-picker.md +++ b/website/docs/zh-CN/date-picker.md @@ -48,14 +48,14 @@ onClick(picker) { const date = new Date(); date.setTime(date.getTime() - 3600 * 1000 * 24); - picker.$emit('pick', date); + picker.emit('pick', date); } }, { text: '一周前', onClick(picker) { const date = new Date(); date.setTime(date.getTime() - 3600 * 1000 * 24 * 7); - picker.$emit('pick', date); + picker.emit('pick', date); } }] }, diff --git a/website/docs/zh-CN/datetime-picker.md b/website/docs/zh-CN/datetime-picker.md index c1f94a8f3b..5c92ed1e02 100644 --- a/website/docs/zh-CN/datetime-picker.md +++ b/website/docs/zh-CN/datetime-picker.md @@ -55,14 +55,14 @@ DateTimePicker 由 DatePicker 和 TimePicker 派生,`Picker Options` 或者其 onClick(picker) { const date = new Date(); date.setTime(date.getTime() - 3600 * 1000 * 24); - picker.$emit('pick', date); + picker.emit('pick', date); } }, { text: '一周前', onClick(picker) { const date = new Date(); date.setTime(date.getTime() - 3600 * 1000 * 24 * 7); - picker.$emit('pick', date); + picker.emit('pick', date); } }] },