fix(time-picker): optimization timePicker when outside step (#556)

* fix(timePicker): optimization timePicker when outside step

* feat: optimization

* Apply suggestions from code review

Co-authored-by: 07akioni <07akioni2@gmail.com>
This commit is contained in:
XieZongChen 2021-07-23 11:36:33 -05:00 committed by GitHub
parent 5833df0875
commit ff061c53f2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 143 additions and 112 deletions

View File

@ -1,7 +1,22 @@
# Step Time
Pass a number as step or use an array to specify the items you want to show.
Pass a number as step or use an array to specify the items you want to show, inputting values that don't follow step settings will cause displaying invalid status.
```html
<n-time-picker :seconds="[0]" :hours="[8,18]" :minutes="30" />
<n-time-picker
:hours="[8,18]"
:minutes="8"
:seconds="[0]"
v-model:value="time"
/>
```
```js
export default {
data () {
return {
time: 1183135260000
}
}
}
```

View File

@ -1,7 +1,22 @@
# 展示某些时间
传递单独的数字来定义时间步进或用数组指定你需要显示的内容。
传递单独的数字来定义时间步进或用数组指定你需要显示的内容,输入超出设定范围的值将将显示无效样式
```html
<n-time-picker :seconds="[0]" :hours="[8,18]" :minutes="30" />
<n-time-picker
:hours="[8,18]"
:minutes="8"
:seconds="[0]"
v-model:value="time"
/>
```
```js
export default {
data () {
return {
time: 1183135260000
}
}
}
```

View File

@ -2,7 +2,7 @@ import { h, ref, defineComponent, inject, PropType, computed } from 'vue'
import { NScrollbar } from '../../scrollbar'
import { NButton } from '../../button'
import { NBaseFocusDetector } from '../../_internal'
import { time, getFixValue } from './utils'
import { getTimeUnits, time } from './utils'
import {
IsHourDisabled,
IsMinuteDisabled,
@ -12,88 +12,75 @@ import {
import PanelCol, { Item } from './PanelCol'
import { MaybeArray } from '../../_utils'
const timePickerPanelProps = {
actions: {
type: Array as PropType<Array<'now' | 'confirm'>>,
default: () => ['now', 'confirm']
},
showHour: {
type: Boolean,
default: true
},
showMinute: {
type: Boolean,
default: true
},
showSecond: {
type: Boolean,
default: true
},
showPeriod: {
type: Boolean,
default: true
},
isHourInvalid: Boolean,
isMinuteInvalid: Boolean,
isSecondInvalid: Boolean,
isValueInvalid: Boolean,
hourValue: {
type: Number as PropType<number | null>,
default: null
},
minuteValue: {
type: Number as PropType<number | null>,
default: null
},
secondValue: {
type: Number as PropType<number | null>,
default: null
},
isHourDisabled: Function as PropType<IsHourDisabled>,
isMinuteDisabled: Function as PropType<IsMinuteDisabled>,
isSecondDisabled: Function as PropType<IsSecondDisabled>,
onHourClick: {
type: Function as PropType<(value: number) => void>,
required: true
},
onMinuteClick: {
type: Function as PropType<(value: number) => void>,
required: true
},
onSecondClick: {
type: Function as PropType<(value: number) => void>,
required: true
},
onNowClick: Function as PropType<() => void>,
nowText: String,
confirmText: String,
transitionDisabled: Boolean,
onConfirmClick: Function as PropType<() => void>,
onFocusin: Function as PropType<(e: FocusEvent) => void>,
onFocusout: Function as PropType<(e: FocusEvent) => void>,
onFocusDetectorFocus: Function as PropType<() => void>,
onKeydown: Function as PropType<(e: KeyboardEvent) => void>,
hours: [Number, Array] as PropType<MaybeArray<number>>,
minutes: [Number, Array] as PropType<MaybeArray<number>>,
seconds: [Number, Array] as PropType<MaybeArray<number>>
}
export default defineComponent({
name: 'TimePickerPanel',
props: {
actions: {
type: Array as PropType<Array<'now' | 'confirm'>>,
default: () => ['now', 'confirm']
},
showHour: {
type: Boolean,
default: true
},
showMinute: {
type: Boolean,
default: true
},
showSecond: {
type: Boolean,
default: true
},
showPeriod: {
type: Boolean,
default: true
},
isHourInvalid: {
type: Boolean,
default: false
},
isMinuteInvalid: {
type: Boolean,
default: false
},
isSecondInvalid: {
type: Boolean,
default: false
},
isValueInvalid: {
type: Boolean,
default: false
},
hourValue: {
type: Number as PropType<number | null>,
default: null
},
minuteValue: {
type: Number as PropType<number | null>,
default: null
},
secondValue: {
type: Number as PropType<number | null>,
default: null
},
isHourDisabled: Function as PropType<IsHourDisabled>,
isMinuteDisabled: Function as PropType<IsMinuteDisabled>,
isSecondDisabled: Function as PropType<IsSecondDisabled>,
onHourClick: {
type: Function as PropType<(value: number) => void>,
required: true
},
onMinuteClick: {
type: Function as PropType<(value: number) => void>,
required: true
},
onSecondClick: {
type: Function as PropType<(value: number) => void>,
required: true
},
onNowClick: Function as PropType<() => void>,
nowText: String,
confirmText: String,
transitionDisabled: {
type: Boolean,
default: false
},
onConfirmClick: Function as PropType<() => void>,
onFocusin: Function as PropType<(e: FocusEvent) => void>,
onFocusout: Function as PropType<(e: FocusEvent) => void>,
onFocusDetectorFocus: Function as PropType<() => void>,
onKeydown: Function as PropType<(e: KeyboardEvent) => void>,
hours: [Number, Array] as PropType<MaybeArray<number>>,
minutes: [Number, Array] as PropType<MaybeArray<number>>,
seconds: [Number, Array] as PropType<MaybeArray<number>>
},
props: timePickerPanelProps,
setup (props) {
const {
mergedThemeRef,
@ -101,19 +88,6 @@ export default defineComponent({
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
} = inject(timePickerInjectionKey)!
function getTimeUnits (
defaultValue: string[],
stepOrList: MaybeArray<number> | undefined
): string[] {
if (Array.isArray(stepOrList)) {
return stepOrList.map((v) => Math.floor(v)).map((v) => getFixValue(v))
} else if (typeof stepOrList === 'number') {
return defaultValue.filter((hour) => Number(hour) % stepOrList === 0)
} else {
return defaultValue
}
}
const hoursRef = computed<Item[]>(() => {
const { isHourDisabled, hours } = props

View File

@ -58,8 +58,9 @@ import {
timePickerInjectionKey
} from './interface'
import { happensIn } from 'seemly'
import { isTimeInStep } from './utils'
// validate hours,minutes,seconds prop
// validate hours, minutes, seconds prop
function validateUnits (value: MaybeArray<number>, max: number): boolean {
if (value === undefined) {
return true
@ -97,10 +98,7 @@ const timePickerProps = {
size: String as PropType<Size>,
isMinuteDisabled: Function as PropType<IsMinuteDisabled>,
isSecondDisabled: Function as PropType<IsSecondDisabled>,
clearable: {
type: Boolean,
default: false
},
clearable: Boolean,
// eslint-disable-next-line vue/prop-name-casing
'onUpdate:value': [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,
onUpdateValue: [Function, Array] as PropType<MaybeArray<OnUpdateValue>>,
@ -115,10 +113,7 @@ const timePickerProps = {
type: Boolean,
default: true
},
disabled: {
type: Boolean,
default: false
},
disabled: Boolean,
// deprecated
onChange: {
type: [Function, Array] as PropType<MaybeArray<OnUpdateValue> | undefined>,
@ -216,27 +211,30 @@ export default defineComponent({
})
const isHourInvalidRef = computed(() => {
const { isHourDisabled } = props
if (!isHourDisabled) return false
if (hourValueRef.value === null) return false
if (!isTimeInStep(hourValueRef.value, 'hours', props.hours)) return true
if (!isHourDisabled) return false
return isHourDisabled(hourValueRef.value)
})
const isMinuteInvalidRef = computed(() => {
const { isMinuteDisabled } = props
if (!isMinuteDisabled) return false
const { value: minuteValue } = minuteValueRef
const { value: hourValue } = hourValueRef
if (minuteValue === null || hourValue === null) return false
if (!isTimeInStep(minuteValue, 'minutes', props.minutes)) return true
const { isMinuteDisabled } = props
if (!isMinuteDisabled) return false
return isMinuteDisabled(minuteValue, hourValue)
})
const isSecondInvalidRef = computed(() => {
const { isSecondDisabled } = props
if (!isSecondDisabled) return false
const { value: minuteValue } = minuteValueRef
const { value: hourValue } = hourValueRef
const { value: secondValue } = secondValueRef
if (secondValue === null || minuteValue === null || hourValue === null) {
return false
}
if (!isTimeInStep(secondValue, 'seconds', props.seconds)) return true
const { isSecondDisabled } = props
if (!isSecondDisabled) return false
return isSecondDisabled(secondValue, minuteValue, hourValue)
})
const isValueInvalidRef = computed(() => {

View File

@ -1,3 +1,5 @@
import { MaybeArray } from '../../_utils'
export const time = {
hours: [
'00',
@ -155,3 +157,30 @@ export const time = {
export function getFixValue (value: number): string {
return `00${value}`.slice(-2)
}
export function getTimeUnits (
defaultValue: string[],
stepOrList: MaybeArray<number> | undefined
): string[] {
if (Array.isArray(stepOrList)) {
return stepOrList.map((v) => Math.floor(v)).map((v) => getFixValue(v))
} else if (typeof stepOrList === 'number') {
return defaultValue.filter((hour) => Number(hour) % stepOrList === 0)
} else {
return defaultValue
}
}
export function isTimeInStep (
value: number,
type: 'hours' | 'minutes' | 'seconds',
stepOrList: MaybeArray<number> | undefined
): boolean {
if (!stepOrList) {
return true
} else if (typeof stepOrList === 'number') {
return value % stepOrList === 0
} else {
return stepOrList.includes(value)
}
}