Skip to content

Commit

Permalink
fix(comp:time-picker,date-picker): refactor code and fix z-index (#886)
Browse files Browse the repository at this point in the history
1. refactor DateRangePicker activeDate control logic
2. refactor DateRangePicker input logic
3. unify DatePicker and TimePicker style variables
4. unify DatePicker and TimePicker code structure

feat(comp:time-panel): add activeValue prop

fix(comp:date-picker,time-picker): fix overlay z-index error
  • Loading branch information
sallerli1 committed May 9, 2022
1 parent 582cd4a commit 8d2133b
Show file tree
Hide file tree
Showing 69 changed files with 2,574 additions and 2,263 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,6 @@ export default defineComponent({
)
})
const isInRange = computed(() => {
if (outView.value) {
return false
}

const compareType = dayTypes.includes(activeType.value) ? 'date' : activeType.value
const cellDateValue = dateConfig.startOf(cellDate.value, compareType).valueOf()

Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
// Vitest Snapshot v1

exports[`TimePanelColumn > render work 1`] = `
"<ul class=\\"ix-time-Panel-column\\">
<li class=\\"ix-time-Panel-cell ix-time-Panel-cell-selected\\">01</li>
<li class=\\"ix-time-Panel-cell ix-time-Panel-cell-disabled\\">02</li>
<li class=\\"ix-time-Panel-cell\\">03</li>
<li class=\\"ix-time-Panel-cell\\">04</li>
<li class=\\"ix-time-Panel-cell ix-time-Panel-cell-disabled\\">05</li>
</ul>"
"<div class=\\"ix-time-Panel-column\\">
<ul class=\\"ix-time-Panel-column-inner\\">
<li class=\\"ix-time-Panel-cell ix-time-Panel-cell-selected\\">01</li>
<li class=\\"ix-time-Panel-cell ix-time-Panel-cell-disabled\\">02</li>
<li class=\\"ix-time-Panel-cell\\">03</li>
<li class=\\"ix-time-Panel-cell\\">04</li>
<li class=\\"ix-time-Panel-cell ix-time-Panel-cell-disabled\\">05</li>
</ul>
</div>"
`;
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,9 @@ describe('usePanelScroll', () => {
})
const onChange = vi.fn()
const props: TimePanelColumnProps = reactive({
visible: true,
selectedValue: selectedValue ?? 1,
activeValue: selectedValue ?? 1,
options,
onChange,
})
Expand Down Expand Up @@ -120,11 +122,11 @@ describe('usePanelScroll', () => {
await wait(400)
expect(wrapper.element.scrollTop).toBe(cellHeight)

props.selectedValue = 3
props.activeValue = 3
await wait(400)
expect(wrapper.element.scrollTop).toBe(2 * cellHeight)

props.selectedValue = 1
props.activeValue = 1
await wait(400)
expect(wrapper.element.scrollTop).toBe(0)
})
Expand Down
4 changes: 2 additions & 2 deletions packages/components/_private/time-panel/src/TimePanelCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ export default defineComponent({

const onClick = () => {
if (!props.disabled && !props.selected) {
callEmit(props.onChange, props.value)
callEmit(props.onChange, props.value!)
}
}

const displayValue = computed(() => displayFormat(props.value))
const displayValue = computed(() => displayFormat(props.value!))

return () => (
<li class={classes.value} onClick={onClick}>
Expand Down
37 changes: 19 additions & 18 deletions packages/components/_private/time-panel/src/TimePanelColumn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE
*/

import { defineComponent, inject, nextTick, ref } from 'vue'
import { defineComponent, inject, ref } from 'vue'

import { callEmit } from '@idux/cdk/utils'

Expand All @@ -19,34 +19,35 @@ export default defineComponent({
setup(props) {
const { mergedPrefixCls } = inject(timePanelContext)!
const listRef = ref<HTMLElement | null>(null)
const { scrollToSelected, handleScroll, handleScrollAdjust } = usePanelScroll(props, listRef, mergedPrefixCls)
const { handleScroll, handleScrollAdjust } = usePanelScroll(props, listRef, mergedPrefixCls)

function onChange(value: string | number) {
callEmit(props.onChange, value)
nextTick(scrollToSelected)
}

return () => (
<ul
<div
ref={listRef}
class={`${mergedPrefixCls.value}-column`}
onScroll={handleScroll}
onMousemove={handleScrollAdjust}
onMouseleave={handleScrollAdjust}
onMouseenter={handleScrollAdjust}
>
{props.options.map((item, index) => {
const { disabled, value } = item
return (
<PanelCell
key={index}
disabled={disabled}
selected={props.selectedValue === value}
value={value}
onChange={onChange}
/>
)
})}
</ul>
<ul class={`${mergedPrefixCls.value}-column-inner`}>
{props.options!.map((item, index) => {
const { disabled, value } = item
return (
<PanelCell
key={index}
disabled={disabled}
selected={props.selectedValue === value}
value={value}
onChange={onChange}
/>
)
})}
</ul>
</div>
)
},
})
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import type { ComputedRef } from 'vue'

import { computed } from 'vue'

import { callEmit } from '@idux/cdk/utils'
import { callEmit, useControlledProp } from '@idux/cdk/utils'

import { calculateValue, calculateViewHour, normalizeAmPm } from '../utils'

Expand All @@ -25,10 +25,13 @@ export function useOptions(
amPmOptionsProps: ComputedRef<TimePanelColumnProps>
} {
const { get } = dateConfig
const defaultOpenValue = computed(() => props.defaultOpenValue ?? dateConfig.startOf(dateConfig.now(), 'date'))
const selectedValue = computed(() => props.value ?? defaultOpenValue.value)
const viewHours = computed(() => calculateViewHour(get(selectedValue.value, 'hour'), props.use12Hours))
const ampm = computed(() => normalizeAmPm(get(selectedValue.value, 'hour'), props.use12Hours))
const [activeValue, setActiveValue] = useControlledProp(props, 'activeValue', () => dateConfig.now())
const [selectedValue, setSelectedValue] = useControlledProp(props, 'value')

const viewHours = computed(
() => selectedValue.value && calculateViewHour(get(selectedValue.value, 'hour'), props.use12Hours),
)
const ampm = computed(() => selectedValue.value && normalizeAmPm(get(selectedValue.value, 'hour'), props.use12Hours))

function getOptions(type: TimePanelColumnType): TimePanelCell[] {
const getHourOptions = () => {
Expand All @@ -54,7 +57,11 @@ export function useOptions(
return generateNumericOptions(
60,
props.secondStep,
props.disabledSeconds(viewHours.value, get(selectedValue.value, 'minute'), ampm.value),
props.disabledSeconds!(
viewHours.value,
selectedValue.value && get(selectedValue.value, 'minute'),
ampm.value,
),
props.hideDisabledOptions,
)
case 'minute':
Expand All @@ -71,46 +78,58 @@ export function useOptions(
}
}

const getHourValue = () => {
const value = ampm.value === 'pm' ? get(selectedValue.value, 'hour') % 12 : get(selectedValue.value, 'hour')
const getHourValue = (value: Date) => {
const hour = ampm.value === 'pm' ? get(value, 'hour') % 12 : get(value, 'hour')

if (ampm.value) {
return value === 0 ? 12 : value
return hour === 0 ? 12 : hour
}

return value
return hour
}

function getSelectedValue(type: TimePanelColumnType) {
function getColumnValue(value: Date, type: TimePanelColumnType) {
switch (type) {
case 'AM/PM':
return ampm.value
case 'hour':
default:
return getHourValue()
return getHourValue(value)
case 'minute':
return get(selectedValue.value, 'minute')
return get(value, 'minute')
case 'second':
return get(selectedValue.value, 'second')
return get(value, 'second')
}
}

function getOnChange(type: TimePanelColumnType) {
const onChange = (type: TimePanelColumnType, value: string | number) => {
const newValue = calculateValue(dateConfig, selectedValue.value, type, props.use12Hours, value)
callEmit(props['onUpdate:value'], newValue)
const newValue = calculateValue(
dateConfig,
selectedValue.value ?? activeValue.value,
type,
props.use12Hours,
value,
)

setSelectedValue(newValue)
setActiveValue(newValue)
callEmit(props.onChange, newValue)
}

return (value: string | number) => onChange(type, value)
}

const getProps = (type: TimePanelColumnType) => {
return computed(() => ({
selectedValue: getSelectedValue(type),
options: getOptions(type),
onChange: getOnChange(type),
}))
return computed(
() =>
({
activeValue: getColumnValue(activeValue.value, type),
selectedValue: selectedValue.value && getColumnValue(selectedValue.value, type),
options: getOptions(type),
onChange: getOnChange(type),
} as TimePanelColumnProps),
)
}

return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { callEmit } from '@idux/cdk/utils'

export interface PanelColumnScroll {
adjustPanel: (selectedIndex: number, duration?: number) => void
scrollToSelected: (duration?: number) => void
scrollToActive: (duration?: number) => void
handleScrollAdjust: () => void
handleScroll: () => void
}
Expand All @@ -28,6 +28,7 @@ export function usePanelScroll(
mergedPrefixCls: ComputedRef<string>,
): PanelColumnScroll {
let scrollHandlerLocked = false
let scrollHandlerLockedTmr: null | number = null
let isScrolling = false
let scrollTargetIndex: number | undefined

Expand All @@ -37,7 +38,7 @@ export function usePanelScroll(

function adjustPanel(selectedIndex: number, duration = 200) {
const target = listRef.value
if (!target || isScrolling || scrollHandlerLocked) {
if (!target || isScrolling) {
return
}

Expand All @@ -47,36 +48,42 @@ export function usePanelScroll(
}

scrollHandlerLocked = true

if (scrollHandlerLockedTmr) {
clearTimeout(scrollHandlerLockedTmr)
}

scrollToTop({
top,
target,
duration,
callback: () => {
setTimeout(() => {
scrollHandlerLockedTmr = setTimeout(() => {
scrollHandlerLocked = false
}, 100)
scrollHandlerLockedTmr = null
}, Math.max(duration, 200))
},
})
}

function scrollToSelected(duration?: number) {
const selectedIndex = props.options.findIndex(item => item.value === props.selectedValue)
adjustPanel(selectedIndex, duration)
function scrollToActive(duration?: number) {
const activeIndex = props.options!.findIndex(item => item.value === props.activeValue)
adjustPanel(activeIndex, duration)
}

function handleScrollAdjust() {
isNil(scrollTargetIndex) || scrollTargetIndex < 0 ? scrollToSelected() : adjustPanel(scrollTargetIndex)
isNil(scrollTargetIndex) || scrollTargetIndex < 0 ? scrollToActive() : adjustPanel(scrollTargetIndex)
}

function handleScroll() {
const target = listRef.value
if (!target || scrollHandlerLocked) {
if (!target || isScrolling || scrollHandlerLocked) {
return
}

isScrolling = true
scrollTargetIndex = Math.min(Math.round(getScroll(target).scrollTop / getCellHeight()), props.options.length - 1)
const targetItem = props.options[scrollTargetIndex]
scrollTargetIndex = Math.min(Math.round(getScroll(target).scrollTop / getCellHeight()), props.options!.length - 1)
const targetItem = props.options![scrollTargetIndex]
if (!targetItem.disabled) {
callEmit(props.onChange, targetItem.value)
}
Expand All @@ -87,23 +94,23 @@ export function usePanelScroll(

watchEffect(() => {
if (props.visible) {
nextTick(() => scrollToSelected(0))
nextTick(() => scrollToActive(0))
}
})
watch(
() => props.selectedValue,
() => props.activeValue,
value => {
const newScrollTargetIndex = props.options.findIndex(item => item.value === value)
const newScrollTargetIndex = props.options!.findIndex(item => item.value === value)
if (scrollTargetIndex !== newScrollTargetIndex) {
scrollTargetIndex = newScrollTargetIndex
!isScrolling && nextTick(scrollToSelected)
!isScrolling && nextTick(scrollToActive)
}
},
)

return {
adjustPanel,
scrollToSelected,
scrollToActive,
handleScrollAdjust,
handleScroll,
}
Expand Down
Loading

0 comments on commit 8d2133b

Please sign in to comment.