mirror of
https://github.com/tusen-ai/naive-ui.git
synced 2025-01-06 12:17:13 +08:00
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:
parent
5833df0875
commit
ff061c53f2
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -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
|
||||
|
||||
|
@ -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(() => {
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user