Skip to content

Commit

Permalink
feat(comp:drawer): distance is configurable and determined by drawer …
Browse files Browse the repository at this point in the history
…size (#1767)
  • Loading branch information
sallerli1 committed Dec 11, 2023
1 parent dcdbfb3 commit 949e855
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 21 deletions.
1 change: 1 addition & 0 deletions packages/components/config/src/defaultConfig.ts
Expand Up @@ -125,6 +125,7 @@ export const defaultConfig: GlobalConfig = {
closable: true,
closeOnEsc: true,
closeIcon: 'close-filled',
distance: 160,
height: 256,
mask: true,
maskClosable: true,
Expand Down
1 change: 1 addition & 0 deletions packages/components/config/src/types.ts
Expand Up @@ -238,6 +238,7 @@ export interface DrawerConfig {
closeIcon: string
closeOnEsc: boolean
container?: PortalTargetType
distance: number
height: string | number
mask: boolean
maskClosable: boolean
Expand Down
2 changes: 1 addition & 1 deletion packages/components/drawer/demo/MultiLevel.vue
Expand Up @@ -3,7 +3,7 @@
<IxDrawer v-model:visible="visible" header="Parent drawer">
<p>This is parent drawer</p>
<IxButton @click="showChildDrawer">Open Child Drawer</IxButton>
<IxDrawer v-model:visible="childVisible" header="Child drawer">
<IxDrawer v-model:visible="childVisible" :width="800" header="Child drawer">
<p>This is child drawer</p>
<IxButton @click="showGrandchildDrawer">Open Grandchild Drawer</IxButton>
<IxDrawer v-model:visible="grandchildVisible" header="Grandchild drawer">
Expand Down
1 change: 1 addition & 0 deletions packages/components/drawer/docs/Api.zh.md
Expand Up @@ -19,6 +19,7 @@
| `maskClosable` | 点击蒙层是否允许关闭 | `boolean` | `true` || - |
| `offset` | 抽屉偏移量 | `number \| string` | `0` | - | `placement``start/end` 时, 为顶部偏移量,`top/bottom` 时, 为左边偏移量 |
| `placement` | 抽屉打开方向 | `'top' \| 'bottom' \| 'start' \| 'end'` | `'end'` | - | - |
| `distance` | 多层抽屉场景与子抽屉的距离 | `number` | `160` || 如果大于抽屉的宽度,则以抽屉的宽度为距离 |
| `width` | 抽屉宽度 | `string \| number` | `'480'` || 默认值仅在 `placement为``start/end` 时生效,其他情况默认为 `100%` |
| `zIndex` | 设置抽屉的 `z-index` | `number` | - | - | - |
| `onAfterOpen` | 打开后的回调 | `() => void` | - | - | - |
Expand Down
80 changes: 68 additions & 12 deletions packages/components/drawer/src/Drawer.tsx
Expand Up @@ -22,6 +22,7 @@ import {
} from 'vue'

import { CdkPortal } from '@idux/cdk/portal'
import { useResizeObserver } from '@idux/cdk/resize'
import { BlockScrollStrategy, type ScrollStrategy } from '@idux/cdk/scroll'
import { callEmit, useControlledProp } from '@idux/cdk/utils'
import { ɵMask } from '@idux/components/_private/mask'
Expand All @@ -48,26 +49,30 @@ export default defineComponent({
const mergedPortalTarget = usePortalTarget(props, config, common, mergedPrefixCls)

const mask = computed(() => props.mask ?? config.mask)
const mergedDistance = computed(() => props.distance ?? config.distance)

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

const drawerElRef = ref<HTMLElement>()

const { open, close } = useTrigger(props, setVisible)
const { level, levelAction, push, pull } = useLevel(visible)
const { levelAction, distance, push, pull } = useLevel(props, visible, mergedDistance, drawerElRef)

provide(drawerToken, {
props,
slots,
common,
config,
mergedPrefixCls,
drawerElRef,
visible,
delayedLoaded,
animatedVisible,
mergedVisible,
currentZIndex,
level,
levelAction,
distance,
push,
pull,
})
Expand Down Expand Up @@ -181,27 +186,78 @@ function useTrigger(props: DrawerProps, setVisible: (visible: boolean) => void)
return { open, close }
}

function useLevel(visible: Ref<boolean>) {
function useLevel(
props: DrawerProps,
visible: Ref<boolean>,
mergedDistance: ComputedRef<number>,
drawerElRef: Ref<HTMLElement | undefined>,
) {
const parentContext = inject(drawerToken, null)

const level = ref(0)
const distance = ref(0)
const levelAction = ref<'push' | 'pull'>()
const drawerSize = ref(0)
const sizeAttrName = computed(() => (['top', 'bottom'].includes(props.placement) ? 'height' : 'width'))

let sizeUpdateCb: (() => void) | undefined

useResizeObserver(drawerElRef, ({ contentRect }) => {
drawerSize.value = contentRect[sizeAttrName.value] ?? 0

sizeUpdateCb?.()
})

const onSizeUpdate = (cb: () => void) => {
sizeUpdateCb = () => {
cb()
sizeUpdateCb = undefined
}
}

const updateDistance = (childSize: number) => {
const minDisatance = Math.min(drawerSize.value, mergedDistance.value)
if (!drawerSize.value || !childSize || drawerSize.value - childSize >= minDisatance) {
distance.value = 0
} else {
distance.value = minDisatance - (drawerSize.value - childSize)
}
}

const push = () => {
const push = (childSize: number) => {
level.value++
parentContext?.push()

updateDistance(childSize)
pushParent()
}

const pull = () => {
const pull = (childSize: number) => {
level.value--
parentContext?.pull()

updateDistance(childSize)
pullParent()
}

const pushParent = () => {
if (parentContext?.props.placement !== props.placement) {
return
}

parentContext?.push(drawerSize.value + distance.value)
}
const pullParent = () => {
if (parentContext?.props.placement !== props.placement) {
return
}

parentContext?.pull(visible.value ? drawerSize.value + distance.value : 0)
}

watch(visible, value => {
if (value) {
parentContext?.push()
onSizeUpdate(pushParent)
} else {
parentContext?.pull()
pullParent()
levelAction.value = undefined
}
})
Expand All @@ -212,15 +268,15 @@ function useLevel(visible: Ref<boolean>) {

onMounted(() => {
if (visible.value) {
parentContext?.push()
pushParent()
}
})

onBeforeUnmount(() => {
if (visible.value) {
parentContext?.pull()
pullParent()
}
})

return { level, levelAction, push, pull }
return { levelAction, distance, push, pull }
}
12 changes: 7 additions & 5 deletions packages/components/drawer/src/DrawerWrapper.tsx
Expand Up @@ -37,7 +37,6 @@ const drawerTransitionMap = {
end: 'move-end',
}
const horizontalPlacement = ['start', 'end']
const defaultDistance = 160

export default defineComponent({
inheritAttrs: false,
Expand All @@ -49,13 +48,14 @@ export default defineComponent({
common,
config,
mergedPrefixCls,
drawerElRef,
visible,
delayedLoaded,
animatedVisible,
mergedVisible,
currentZIndex,
level,
levelAction,
distance,
} = inject(drawerToken)!
const { close } = inject(DRAWER_TOKEN)!
const { closable, closeIcon, closeOnEsc, mask, maskClosable } = useConfig(props, config)
Expand Down Expand Up @@ -83,12 +83,13 @@ export default defineComponent({
const transformStyle = computed(() => {
const { placement } = props
const horizontal = isHorizontal.value
const distance = level.value * defaultDistance
let transform
if (horizontal) {
transform = distance > 0 ? `translateX(${placement === 'start' ? distance : -distance}px)` : undefined
transform =
distance.value > 0 ? `translateX(${placement === 'start' ? distance.value : -distance.value}px)` : undefined
} else {
transform = distance > 0 ? `translateY(${placement === 'top' ? distance : -distance}px)` : undefined
transform =
distance.value > 0 ? `translateY(${placement === 'top' ? distance.value : -distance.value}px)` : undefined
}
return transform
})
Expand Down Expand Up @@ -158,6 +159,7 @@ export default defineComponent({
{delayedLoaded.value && (
<div
v-show={visible.value}
ref={drawerElRef}
role="document"
class={prefixCls}
style={contentStyle.value}
Expand Down
7 changes: 4 additions & 3 deletions packages/components/drawer/src/token.ts
Expand Up @@ -15,15 +15,16 @@ export interface DrawerContext {
common: CommonConfig
config: DrawerConfig
mergedPrefixCls: ComputedRef<string>
drawerElRef: Ref<HTMLElement | undefined>
visible: Ref<boolean>
delayedLoaded: Ref<boolean>
animatedVisible: Ref<boolean | undefined>
mergedVisible: ComputedRef<boolean>
currentZIndex: ComputedRef<number>
level: Ref<number>
levelAction: Ref<'push' | 'pull' | undefined>
push: () => void
pull: () => void
distance: Ref<number>
push: (childSize: number) => void
pull: (childSize: number) => void
}

export const drawerToken: InjectionKey<DrawerContext> = Symbol('drawerToken')
Expand Down
4 changes: 4 additions & 0 deletions packages/components/drawer/src/types.ts
Expand Up @@ -77,6 +77,10 @@ export const drawerProps = {
type: String as PropType<DrawerPlacement>,
default: 'end',
},
distance: {
type: Number,
default: undefined,
},
scrollStrategy: Object as PropType<ScrollStrategy>,
width: [String, Number] as PropType<string | number>,
zIndex: Number,
Expand Down

0 comments on commit 949e855

Please sign in to comment.