Skip to content

Commit

Permalink
Merge c44eb75 into 409c280
Browse files Browse the repository at this point in the history
  • Loading branch information
sallerli1 committed Aug 4, 2023
2 parents 409c280 + c44eb75 commit fa83cfb
Show file tree
Hide file tree
Showing 8 changed files with 111 additions and 39 deletions.
1 change: 1 addition & 0 deletions packages/components/tour/__tests__/tour.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ describe('Tour', () => {
)

await wrapper.setProps({ activeIndex: 1 })
await wait(50)
await flushPromises()

expect(document.querySelector('.active-index-test .ix-tour-panel .ix-header .ix-header-title')?.textContent).toBe(
Expand Down
8 changes: 5 additions & 3 deletions packages/components/tour/src/Tour.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ import { tourProps } from './types'

export default defineComponent({
name: 'IxTour',
inheritAttrs: false,
props: tourProps,
setup(props, { slots }) {
setup(props, { slots, attrs }) {
const common = useGlobalConfig('common')
const config = useGlobalConfig('tour')
const locale = useGlobalConfig('locale')
Expand All @@ -52,7 +53,7 @@ export default defineComponent({

useCloseTrigger(mergedProps, positionInfo, visible, setVisible)
const stepChangeContext = useStepChange(mergedProps, activeIndex, activeStep, visible, onAnimateEnd)
const { isStepChanging } = stepChangeContext
const { isStepChanging, onStepChange } = stepChangeContext

const mergedContainerFallback = computed(() => `.${mergedPrefixCls.value}-overlay-container`)
const mergedContainer = computed(() => mergedProps.value.overlayContainer ?? mergedContainerFallback.value)
Expand All @@ -65,6 +66,7 @@ export default defineComponent({
isStepChanging,
visible,
currentZIndex,
onStepChange,
)

const placeholderStyle = computed(() => {
Expand Down Expand Up @@ -108,7 +110,7 @@ export default defineComponent({
<Mask v-show={visible.value && !!activeStep.value?.mask} />
</Transition>
</CdkPortal>
<ɵOverlay class={`${prefixCls}-overlay`} {...overlayProps.value} v-slots={overlaySlots} />
<ɵOverlay class={`${prefixCls}-overlay`} {...overlayProps.value} {...attrs} v-slots={overlaySlots} />
</>
)
}
Expand Down
13 changes: 9 additions & 4 deletions packages/components/tour/src/composables/useActiveStep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
* found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE
*/

import type { MergedTourProps } from './useMergedProps'
import type { ResolvedTourStep } from '../types'
import type { MergedTourProps } from './useMergedProps'
import type { ButtonMode, ButtonSize } from '@idux/components/button'
import type { TourLocale } from '@idux/components/locales'

Expand Down Expand Up @@ -97,6 +97,11 @@ export function useActiveStep(
}

const pushCurrentUpdate = async (index: number) => {
if (index < 0) {
setActiveStep(undefined)
return
}

const promise = getActiveStep(index)

destructions.push(async () => {
Expand All @@ -113,15 +118,15 @@ export function useActiveStep(

watch(
activeIndex,
async (current, pre) => {
if (current === pre) {
async current => {
if (current === activeStep.value?.index) {
return
}

destroySteps()
pushCurrentUpdate(current)
},
{ immediate: true },
{ immediate: true, flush: 'post' },
)

return activeStep
Expand Down
27 changes: 21 additions & 6 deletions packages/components/tour/src/composables/useMask.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
* found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE
*/

import type { MergedTourProps } from './useMergedProps'
import type { ResolvedTourStep, TargetPositionInfo } from '../types'
import type { MergedTourProps } from './useMergedProps'

import {
type CSSProperties,
Expand All @@ -20,7 +20,7 @@ import {

import { isBoolean } from 'lodash-es'

import { convertCssPixel, rAF, useState } from '@idux/cdk/utils'
import { cancelRAF, convertCssPixel, rAF, useState } from '@idux/cdk/utils'

import { easeInOutQuad } from '../utils'

Expand Down Expand Up @@ -75,6 +75,13 @@ export function useMask(
animateCbs.clear()
})

let rAFHandle: number

const cancelAnimate = () => {
cancelRAF(rAFHandle)
setIsAnimating(false)
}

const animate = (from: TargetPositionInfo, to: TargetPositionInfo) => {
const start = Date.now()
setIsAnimating(true)
Expand All @@ -95,15 +102,15 @@ export function useMask(
)

if (elapsed < animateDuration) {
rAF(tick)
rAFHandle = rAF(tick)
} else {
setMaskPath(getMaskPath(to))
setIsAnimating(false)
runAnimateCbs()
}
}

rAF(tick)
rAFHandle = rAF(tick)
}

let _tempIndex = activeIndex.value
Expand All @@ -116,10 +123,18 @@ export function useMask(
}

if (!activeStep.value?.mask) {
cancelAnimate()
setMaskPath('')
} else if (!mergedProps.value.animatable || !prePos || !pos || _tempIndex === activeIndex.value) {
} else if (!mergedProps.value.animatable || pos?.origin !== 'index' || !prePos || !pos) {
setMaskPath(getMaskPath(pos))

if (mergedProps.value.animatable && (isAnimating.value || activeIndex.value !== _tempIndex)) {
runAnimateCbs()
}

cancelAnimate()
} else {
cancelAnimate()
animate(prePos, pos)
}

Expand All @@ -140,7 +155,7 @@ export function useMask(
}
}

function getMaskPath(positionInfo: TargetPositionInfo | null): string {
function getMaskPath(positionInfo: Omit<TargetPositionInfo, 'origin'> | null): string {
const viewBoxRect = (width: number, height: number) => `M${width},0L0,0L0,${height}L${width},${height}L${width},0Z`

if (!positionInfo) {
Expand Down
15 changes: 11 additions & 4 deletions packages/components/tour/src/composables/useOverlayProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
* found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE
*/

import type { MergedTourProps } from './useMergedProps'
import type { ResolvedTourStep } from '../types'
import type { MergedTourProps } from './useMergedProps'
import type { ɵOverlayProps } from '@idux/components/_private/overlay'
import type { CommonConfig } from '@idux/components/config'

import { type ComputedRef, computed } from 'vue'
import { type ComputedRef, computed, ref } from 'vue'

export function useOverlayProps(
componentCommonConfig: CommonConfig,
Expand All @@ -20,13 +20,20 @@ export function useOverlayProps(
isStepChanging: ComputedRef<boolean>,
visible: ComputedRef<boolean>,
currentZIndex: ComputedRef<number>,
onStepChange: (cb: () => void) => void,
): ComputedRef<ɵOverlayProps> {
const currentActiveStep = ref(activeStep.value)

onStepChange(() => {
currentActiveStep.value = activeStep.value
})

return computed(() => {
const { animatable, overlayContainer, offset } = mergedProps.value
const { placement = 'bottomStart', showArrow } = activeStep.value ?? {}
const { placement = 'bottomStart', showArrow } = currentActiveStep.value ?? {}

return {
visible: visible.value && !!activeStep.value && !isStepChanging.value,
visible: visible.value && !!currentActiveStep.value && !isStepChanging.value,
container: overlayContainer,
containerFallback: containerFallback.value,
trigger: 'manual',
Expand Down
57 changes: 42 additions & 15 deletions packages/components/tour/src/composables/useStepChange.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
* found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE
*/

import type { MergedTourProps } from './useMergedProps'
import type { ResolvedTourStep } from '../types'
import type { MergedTourProps } from './useMergedProps'

import { type ComputedRef, onUnmounted, watch } from 'vue'

Expand All @@ -28,6 +28,25 @@ export function useStepChange(
): StepChangeContext {
const stepChangeCbs = new Set<() => void>()
const [isStepChanging, _setIsStepChanging] = useState<boolean>(false)
let transitionTmr: number

const locks = {
stepChange: false,
animate: false,
}

const lock = () => {
Object.keys(locks).forEach(key => (locks[key as keyof typeof locks] = true))

setIsStepChanging(true)
}
const unlock = (lock: keyof typeof locks) => {
locks[lock] = false

if (Object.keys(locks).every(key => !locks[key as keyof typeof locks])) {
setIsStepChanging(false)
}
}

const setIsStepChanging = (changing: boolean) => {
if (isStepChanging.value === changing) {
Expand All @@ -37,20 +56,20 @@ export function useStepChange(
_setIsStepChanging(changing)

if (!changing) {
stepChangeCbs.forEach(cb => cb())
runStepChangeCbs()
}
}

const onStepChange = (cb: () => void) => {
stepChangeCbs.add(cb)
}

let transitionTmr: number
const runStepChangeCbs = () => {
stepChangeCbs.forEach(cb => cb())
}

onAnimateEnd(() => {
if (mergedProps.value.animatable && activeStep.value?.mask) {
transitionTmr && clearTimeout(transitionTmr)
setIsStepChanging(false)
unlock('animate')
}
})

Expand All @@ -59,7 +78,7 @@ export function useStepChange(
(current, pre) => {
if (current !== pre) {
transitionTmr && clearTimeout(transitionTmr)
setIsStepChanging(true)
lock()
}
},
{
Expand All @@ -68,18 +87,26 @@ export function useStepChange(
)
watch(
activeStep,
step => {
(step, preStep) => {
if (step && !preStep) {
runStepChangeCbs()
return
}

if (!mergedProps.value.animatable || !step?.mask || !visible.value) {
transitionTmr && clearTimeout(transitionTmr)
transitionTmr = setTimeout(
() => {
setIsStepChanging(false)
},
mergedProps.value.animatable ? transitionDuration : 0,
)
unlock('animate')
}

transitionTmr && clearTimeout(transitionTmr)
transitionTmr = setTimeout(
() => {
unlock('stepChange')
},
mergedProps.value.animatable ? transitionDuration : 0,
)
},
{
immediate: true,
flush: 'post',
},
)
Expand Down
26 changes: 19 additions & 7 deletions packages/components/tour/src/composables/useTarget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
* found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE
*/

import type { ResolvedTourStep, TargetPositionInfo, TargetPositionOrigin } from '../types'
import type { MergedTourProps } from './useMergedProps'
import type { ResolvedTourStep, TargetPositionInfo } from '../types'

import { type ComputedRef, type Ref, onMounted, onUnmounted, shallowRef, watch } from 'vue'

Expand All @@ -33,7 +33,7 @@ export function useTarget(
targetRef.value = (await activeStep.value?.target()) ?? null
}

const updatePopsition = (scrollIntoView = false) => {
const updatePopsition = (scrollIntoView = false, origin: TargetPositionOrigin = 'index') => {
const targetEl = targetRef.value
const { offset = 0, radius = 0 } = activeStep.value?.gap ?? {}

Expand All @@ -46,6 +46,7 @@ export function useTarget(
width: 0,
height: 0,
radius,
origin,
})
return
}
Expand All @@ -61,7 +62,16 @@ export function useTarget(
const { x, y, width, height } = targetEl.getBoundingClientRect()

if (!offset) {
setPositionInfo({ windowWidth: window.innerWidth, windowHeight: window.innerHeight, x, y, width, height, radius })
setPositionInfo({
windowWidth: window.innerWidth,
windowHeight: window.innerHeight,
x,
y,
width,
height,
radius,
origin,
})
} else {
setPositionInfo({
windowWidth: window.innerWidth,
Expand All @@ -71,6 +81,7 @@ export function useTarget(
width: width + offset * 2,
height: height + offset * 2,
radius,
origin,
})
}
}
Expand All @@ -79,14 +90,15 @@ export function useTarget(
let stopScrollLisiten: (() => void) | undefined

onMounted(() => {
watch(() => activeStep.value?.target, updateTarget, { immediate: true })
watch([targetRef, visible], () => updatePopsition(true), { immediate: true })
watch([() => activeStep.value?.target, visible], updateTarget, { immediate: true })
watch(targetRef, () => updatePopsition(true, 'index'), { immediate: true })
watch(visible, () => updatePopsition(true, 'visible'))
watch(
visible,
v => {
if (v) {
stopResizeLisiten = useEventListener(window, 'resize', () => updatePopsition(false))
stopScrollLisiten = useEventListener(window, 'scroll', () => updatePopsition(false))
stopResizeLisiten = useEventListener(window, 'resize', () => updatePopsition(false, 'resize'))
stopScrollLisiten = useEventListener(window, 'scroll', () => updatePopsition(false, 'scroll'))
} else {
stopResizeLisiten?.()
stopScrollLisiten?.()
Expand Down
3 changes: 3 additions & 0 deletions packages/components/tour/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import type { DefineComponent, HTMLAttributes, PropType } from 'vue'

import { ɵOverlayPlacementDef } from '@idux/components/_private/overlay'

export type TargetPositionOrigin = 'resize' | 'scroll' | 'index' | 'visible'

export interface TargetPositionInfo {
windowWidth: number
windowHeight: number
Expand All @@ -20,6 +22,7 @@ export interface TargetPositionInfo {
width: number
height: number
radius: number
origin: TargetPositionOrigin
}

export interface TargetGap {
Expand Down

0 comments on commit fa83cfb

Please sign in to comment.