feat(modal): add transform-origin prop, closes #1498

This commit is contained in:
07akioni 2021-11-02 01:19:15 +08:00
parent 98a8c1b01d
commit 19c5d71410
9 changed files with 83 additions and 4 deletions

View File

@ -1,5 +1,11 @@
# CHANGELOG
## Pending
### Feats
- `n-modal` add `transform-origin` prop, closes [#1498](https://github.com/TuSimple/naive-ui/issues/1498).
## 2.20.1 (2021-11-01)
### Fixes

View File

@ -1,5 +1,11 @@
# CHANGELOG
## Pending
### Feats
- `n-modal` 新增 `transform-origin` 属性,关闭 [#1498](https://github.com/TuSimple/naive-ui/issues/1498)
## 2.20.1 (2021-11-01)
### Fixes

View File

@ -12,6 +12,7 @@ custom-position
preset-card
preset-confirm
preset-confirm-slot
transform-origin
```
## API
@ -24,6 +25,7 @@ preset-confirm-slot
| mask-closable | `boolean` | `true` | Whether to emit `hide` event when click mask. |
| preset | `'card' \| 'confirm'` | `undefined` | The preset of `n-modal`. |
| show | `boolean` | `false` | Whether to show modal. |
| transform-origin | `'mouse' \| 'center'` | `'mouse'` | The transform origin of the modal's display animation. |
| on-update:show | `(value: boolean) => void` | `undefined` | Callback when modal's display status is changed. |
| on-after-enter | `() => void` | `undefined` | Callback after modal is opened. |
| on-after-leave | `() => void` | `undefined` | Callback after modal is closed. |

View File

@ -0,0 +1,26 @@
# Transform Origin
Although the emerging animation from your click position is cool, sometimes we need a plain animation which occurs from the center of the screen. You can set `transfrom-origin` to `'center'` to achieve it.
```html
<n-button @click="showModal = true">Nothing</n-button>
<n-modal v-model:show="showModal" transform-origin="center">
<n-card style="width: 600px;" title="Okay" :bordered="false" size="huge">
<template #header-extra>Great</template>
Fine
<template #footer>Nice</template>
</n-card>
</n-modal>
```
```js
import { defineComponent, ref } from 'vue'
export default defineComponent({
setup () {
return {
showModal: ref(false)
}
}
})
```

View File

@ -12,6 +12,7 @@ custom-position
preset-card
preset-confirm
preset-confirm-slot
transform-origin
raw-debug
dark-1-debug
dark-2-debug
@ -36,6 +37,7 @@ dark-10-debug
| mask-closable | `boolean` | `true` | 点击遮罩时是否发出 `update:show` 事件 |
| preset | `'card' \| 'dialog'` | `undefined` | 模态框使用何种预设 |
| show | `boolean` | `false` | 是否展示 Modal |
| transform-origin | `'mouse' \| 'center'` | `'mouse'` | 模态框动画出现的位置 |
| on-update:show | `(value: boolean) => void` | `undefined` | 模态框更新是否展示状态的回调 |
| on-after-enter | `() => void` | `undefined` | Modal 出现后的回调 |
| on-after-leave | `() => void` | `undefined` | Modal 关闭后的回调 |

View File

@ -0,0 +1,26 @@
# 出现位置
虽然从鼠标位置出现的动画看起来很酷,但是我们有时也想要一些朴实无华的从屏幕中间弹出来的动画。这时你可以将 `transform-origin` 设为 `'center'`
```html
<n-button @click="showModal = true">没什么的</n-button>
<n-modal v-model:show="showModal" transform-origin="center">
<n-card style="width: 600px;" title="自愿" :bordered="false" size="huge">
<template #header-extra>按需</template>
原则
<template #footer>支持一下</template>
</n-card>
</n-modal>
```
```js
import { defineComponent, ref } from 'vue'
export default defineComponent({
setup () {
return {
showModal: ref(false)
}
}
})
```

View File

@ -81,6 +81,9 @@ export default defineComponent({
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const NModal = inject(modalInjectionKey)!
function styleTransformOrigin (): string {
if (NModal.transformOriginRef.value === 'center') {
return ''
}
const { value: transformOriginX } = transformOriginXRef
const { value: transformOriginY } = transformOriginYRef
if (transformOriginX === null || transformOriginY === null) {
@ -92,6 +95,9 @@ export default defineComponent({
return ''
}
function syncTransformOrigin (el: HTMLElement): void {
if (NModal.transformOriginRef.value === 'center') {
return
}
const mousePosition = NModal.getMousePosition()
if (!mousePosition) {
return

View File

@ -43,6 +43,10 @@ const modalProps = {
type: String as PropType<'if' | 'show'>,
default: 'if'
},
transformOrigin: {
type: String as PropType<'center' | 'mouse'>,
default: 'mouse'
},
...presetProps,
// events
'onUpdate:show': [Function, Array] as PropType<
@ -196,7 +200,8 @@ export default defineComponent({
mergedClsPrefixRef,
mergedThemeRef: themeRef,
isMountedRef,
appearRef: toRef(props, 'appear')
appearRef: toRef(props, 'appear'),
transformOriginRef: toRef(props, 'transformOrigin')
})
return {
mergedClsPrefix: mergedClsPrefixRef,

View File

@ -6,9 +6,8 @@ export type ModalBodyInjection = Ref<
HTMLElement | ComponentPublicInstance | null
> | null
export const modalBodyInjectionKey: InjectionKey<ModalBodyInjection> = Symbol(
'modalBody'
)
export const modalBodyInjectionKey: InjectionKey<ModalBodyInjection> =
Symbol('modalBody')
export interface ModalInjection {
getMousePosition: () => {
@ -19,6 +18,7 @@ export interface ModalInjection {
mergedThemeRef: Ref<MergedTheme<ModalTheme>>
isMountedRef: Ref<boolean>
appearRef: Ref<boolean | undefined>
transformOriginRef: Ref<'mouse' | 'center'>
}
export const modalInjectionKey: InjectionKey<ModalInjection> = Symbol('modal')