Skip to content

Commit

Permalink
feat(cdk:utils): add zIndex manager
Browse files Browse the repository at this point in the history
  • Loading branch information
brenner8023 committed Jul 24, 2022
1 parent 5d023a8 commit bfd4d85
Show file tree
Hide file tree
Showing 18 changed files with 185 additions and 33 deletions.
72 changes: 72 additions & 0 deletions packages/cdk/utils/__tests__/zIndex.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { mount } from '@vue/test-utils'
import { computed, defineComponent, toRef } from 'vue'

import { useZIndex } from '../src/zIndex'

describe('zIndex.ts', () => {
const TestComp = defineComponent({
props: {
visible: { type: Boolean, required: true },
zIndex: { type: Number, default: undefined },
},
setup(props) {
const visible = toRef(props, 'visible')
const { currentZIndex } = useZIndex(visible, toRef(props, 'zIndex'), 3000)
const style = computed(() => ({ zIndex: currentZIndex.value }))

return {
style,
}
},
template: `
<div utid="test-el" :style="style"></div>
`,
})

test('custdom zIndex work', async () => {
const wrapper = mount(TestComp, {
props: {
visible: false,
zIndex: 2022,
},
})

expect(wrapper.find('[utid="test-el"]').attributes('style')).toContain('z-index: 2022')

await wrapper.setProps({ visible: true })
expect(wrapper.find('[utid="test-el"]').attributes('style')).toContain('z-index: 2022')
})

test('increment zIndex work', async () => {
const wrapper = mount(TestComp, {
props: {
visible: false,
},
})

expect(wrapper.find('[utid="test-el"]').attributes('style')).toContain('z-index: 3000')

await wrapper.setProps({ visible: true })
expect(wrapper.find('[utid="test-el"]').attributes('style')).toContain('z-index: 3000')

const wrapper2 = mount(TestComp, {
props: {
visible: false,
},
})
await wrapper2.setProps({ visible: true })
expect(wrapper2.find('[utid="test-el"]').attributes('style')).toContain('z-index: 3001')

const wrapper3 = mount(TestComp, {
props: {
visible: true,
},
})
expect(wrapper3.find('[utid="test-el"]').attributes('style')).toContain('z-index: 3002')

expect(wrapper.find('[utid="test-el"]').attributes('style')).toContain('z-index: 3000')
await wrapper.setProps({ visible: false })
await wrapper.setProps({ visible: true })
expect(wrapper.find('[utid="test-el"]').attributes('style')).toContain('z-index: 3003')
})
})
1 change: 1 addition & 0 deletions packages/cdk/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ export * from './src/typeof'
export * from './src/uniqueId'
export * from './src/useEventListener'
export * from './src/vNode'
export * from './src/zIndex'
36 changes: 36 additions & 0 deletions packages/cdk/utils/src/zIndex.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
* @license
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE
*/

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

const zIndexCount = ref(0)
const getZIndex = (commonZIndex: number) => zIndexCount.value + (commonZIndex ?? 1000)

type UseZIndex = (
visible: Ref<boolean>,
controlZIndex: Ref<number | undefined>,
commonZIndex: number,
) => { currentZIndex: ComputedRef<number> }
export const useZIndex: UseZIndex = (visible, controlZIndex, commonZIndex) => {
const innerZIndex = ref(getZIndex(commonZIndex))
const currentZIndex = computed(() => (controlZIndex.value ? controlZIndex.value : innerZIndex.value))

watch(
visible,
newVisible => {
if (newVisible && !controlZIndex.value) {
innerZIndex.value = getZIndex(commonZIndex)
zIndexCount.value++
}
},
{ immediate: true },
)

return {
currentZIndex,
}
}
15 changes: 11 additions & 4 deletions packages/components/_private/overlay/src/Overlay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,18 @@

import type { OverlayProps } from './types'
import type { PopperElement, PopperEvents } from '@idux/cdk/popper'
import type { ComputedRef, Ref, VNode } from 'vue'

import {
type ComputedRef,
type Ref,
Transition,
type VNode,
cloneVNode,
computed,
defineComponent,
onBeforeUnmount,
onMounted,
toRef,
vShow,
watch,
withDirectives,
Expand All @@ -24,7 +27,7 @@ import {
import { clickOutside } from '@idux/cdk/click-outside'
import { usePopper } from '@idux/cdk/popper'
import { CdkPortal } from '@idux/cdk/portal'
import { Logger, callEmit, convertElement, getFirstValidNode } from '@idux/cdk/utils'
import { Logger, callEmit, convertElement, getFirstValidNode, useZIndex } from '@idux/cdk/utils'
import { useGlobalConfig } from '@idux/components/config'

import { overlayProps } from './types'
Expand Down Expand Up @@ -53,6 +56,8 @@ export default defineComponent({
destroy,
} = usePopper({ ...popperOptions.value, visible: props.visible })

const { currentZIndex } = useZIndex(visibility, toRef(props, 'zIndex'), common.zIndex)

onMounted(() => initialize())
onBeforeUnmount(() => destroy())

Expand Down Expand Up @@ -101,6 +106,7 @@ export default defineComponent({
props,
mergedPrefixCls,
visibility,
currentZIndex,
contentNode!,
arrowRef,
popperRef,
Expand Down Expand Up @@ -133,6 +139,7 @@ function renderContent(
props: OverlayProps,
mergedPrefixCls: ComputedRef<string>,
visibility: ComputedRef<boolean>,
currentZIndex: ComputedRef<number>,
contentNode: VNode[],
arrowRef: Ref<PopperElement | null>,
popperRef: Ref<PopperElement | null>,
Expand All @@ -143,9 +150,9 @@ function renderContent(
return null
}
const prefixCls = mergedPrefixCls.value
const { triggerId, zIndex } = props
const { triggerId } = props
const overlayId = triggerId != null ? `overlay-${triggerId}` : undefined
const style = zIndex != null ? `z-index: ${zIndex}` : undefined
const style = currentZIndex.value ? `z-index: ${currentZIndex.value}` : undefined
const overlay = (
<div ref={popperRef} id={overlayId} class={prefixCls} style={style} {...popperEvents.value} {...attrs}>
{contentNode}
Expand Down
1 change: 1 addition & 0 deletions packages/components/config/src/defaultConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { type GlobalConfig } from './types'
export const defaultConfig: GlobalConfig = {
common: {
prefixCls: 'ix',
zIndex: 1000,
},
locale: zhCN,

Expand Down
3 changes: 1 addition & 2 deletions packages/components/config/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ export interface GlobalConfig {
export type GlobalConfigKey = keyof GlobalConfig
export interface CommonConfig {
prefixCls: string
zIndex: number
}

export interface AlertConfig {
Expand Down Expand Up @@ -199,7 +200,6 @@ export interface DrawerConfig {
maskClosable: boolean
target?: PortalTargetType
width: string | number
zIndex?: number
}

export interface DropdownConfig {
Expand Down Expand Up @@ -294,7 +294,6 @@ export interface ModalConfig {
maskClosable: boolean
target?: PortalTargetType
width: string | number
zIndex?: number
}

export interface NotificationConfig {
Expand Down
9 changes: 5 additions & 4 deletions packages/components/drawer/src/Drawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ import type { DrawerProps } from './types'
import type { ScrollStrategy } from '@idux/cdk/scroll'
import type { ComputedRef, Ref } from 'vue'

import { computed, defineComponent, inject, onBeforeUnmount, onMounted, provide, ref, watch } from 'vue'
import { computed, defineComponent, inject, onBeforeUnmount, onMounted, provide, ref, toRef, watch } from 'vue'

import { CdkPortal } from '@idux/cdk/portal'
import { BlockScrollStrategy } from '@idux/cdk/scroll'
import { callEmit, useControlledProp } from '@idux/cdk/utils'
import { callEmit, useControlledProp, useZIndex } from '@idux/cdk/utils'
import { ɵMask } from '@idux/components/_private/mask'
import { useGlobalConfig } from '@idux/components/config'

Expand All @@ -30,9 +30,9 @@ export default defineComponent({
const mergedPrefixCls = computed(() => `${common.prefixCls}-drawer`)
const config = useGlobalConfig('drawer')
const mask = computed(() => props.mask ?? config.mask)
const zIndex = computed(() => props.zIndex ?? config.zIndex)

const { visible, setVisible, animatedVisible, mergedVisible } = useVisible(props)
const { currentZIndex } = useZIndex(visible, toRef(props, 'zIndex'), common.zIndex)

const { open, close } = useTrigger(props, setVisible)
const { level, levelAction, push, pull } = useLevel(visible)
Expand All @@ -46,6 +46,7 @@ export default defineComponent({
visible,
animatedVisible,
mergedVisible,
currentZIndex,
level,
levelAction,
push,
Expand All @@ -69,7 +70,7 @@ export default defineComponent({
class={`${mergedPrefixCls.value}-mask`}
mask={mask.value}
visible={visible.value}
zIndex={zIndex.value}
zIndex={currentZIndex.value}
/>
<DrawerWrapper {...attrs}></DrawerWrapper>
</CdkPortal>
Expand Down
21 changes: 15 additions & 6 deletions packages/components/drawer/src/DrawerWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,20 @@ const defaultDistance = 160
export default defineComponent({
inheritAttrs: false,
setup(_, { attrs }) {
const { props, slots, common, config, mergedPrefixCls, visible, animatedVisible, level, levelAction } =
inject(drawerToken)!
const {
props,
slots,
common,
config,
mergedPrefixCls,
visible,
animatedVisible,
currentZIndex,
level,
levelAction,
} = inject(drawerToken)!
const { close } = inject(DRAWER_TOKEN)!
const { closable, closeIcon, closeOnEsc, mask, maskClosable, zIndex } = useConfig(props, config)
const { closable, closeIcon, closeOnEsc, mask, maskClosable } = useConfig(props, config)

const transitionName = computed(() => `${common.prefixCls}-${drawerTransitionMap[props.placement]}`)
const isHorizontal = computed(() => horizontalPlacement.includes(props.placement))
Expand Down Expand Up @@ -95,7 +105,7 @@ export default defineComponent({

const wrapperStyle = computed(() => {
const placement = mask.value ? undefined : placementStyle.value
return { zIndex: zIndex.value, transform: transformStyle.value, ...placement }
return { zIndex: currentZIndex.value, transform: transformStyle.value, ...placement }
})

const contentStyle = computed(() => {
Expand Down Expand Up @@ -178,9 +188,8 @@ function useConfig(props: DrawerProps, config: DrawerConfig) {
const closeOnEsc = computed(() => props.closeOnEsc ?? config.closeOnEsc)
const mask = computed(() => props.mask ?? config.mask)
const maskClosable = computed(() => props.maskClosable ?? config.maskClosable)
const zIndex = computed(() => props.zIndex ?? config.zIndex)

return { closable, closeIcon, closeOnEsc, mask, maskClosable, zIndex }
return { closable, closeIcon, closeOnEsc, mask, maskClosable }
}

function watchVisibleChange(
Expand Down
1 change: 1 addition & 0 deletions packages/components/drawer/src/token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export interface DrawerContext {
visible: ComputedRef<boolean>
animatedVisible: Ref<boolean | undefined>
mergedVisible: ComputedRef<boolean>
currentZIndex: ComputedRef<number>
level: Ref<number>
levelAction: Ref<'push' | 'pull' | undefined>
push: () => void
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Vitest Snapshot v1

exports[`Message > render work 1`] = `
"<div class=\\"ix-message ix-message-info\\">
"<div class=\\"ix-message ix-message-info\\" style=\\"z-index: 1000;\\">
<div class=\\"ix-message-content\\"><span class=\\"ix-message-content-icon\\"><i class=\\"ix-icon ix-icon-info-circle-filled\\" role=\\"img\\" aria-label=\\"info-circle-filled\\"></i></span><span class=\\"ix-message-content-text\\">This is a message</span></div>
</div>"
`;
15 changes: 12 additions & 3 deletions packages/components/message/src/Message.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@
import type { MessageProps } from './types'
import type { MessageConfig } from '@idux/components/config'

import { computed, defineComponent, onBeforeUnmount, onMounted, watchEffect } from 'vue'
import { computed, defineComponent, onBeforeUnmount, onMounted, ref, watchEffect } from 'vue'

import { isString } from 'lodash-es'

import { callEmit, useControlledProp } from '@idux/cdk/utils'
import { callEmit, useControlledProp, useZIndex } from '@idux/cdk/utils'
import { useGlobalConfig } from '@idux/components/config'
import { IxIcon } from '@idux/components/icon'

Expand All @@ -37,13 +37,22 @@ export default defineComponent({
})

const { visible, onMouseEnter, onMouseLeave } = useEvents(props, config)
const { currentZIndex } = useZIndex(visible, ref(undefined), common.zIndex)

return () => {
const icon = mergedIcon.value
const iconNode = isString(icon) ? <IxIcon name={icon}></IxIcon> : icon
const prefixCls = mergedPrefixCls.value
const style = { zIndex: currentZIndex.value }

return (
<div v-show={visible.value} class={classes.value} onMouseenter={onMouseEnter} onMouseleave={onMouseLeave}>
<div
v-show={visible.value}
class={classes.value}
style={style}
onMouseenter={onMouseEnter}
onMouseleave={onMouseLeave}
>
<div class={`${prefixCls}-content`}>
<span class={`${prefixCls}-content-icon`}>{iconNode}</span>
<span class={`${prefixCls}-content-text`}>{slots.default?.()}</span>
Expand Down
Loading

0 comments on commit bfd4d85

Please sign in to comment.