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 # 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) ## 2.20.1 (2021-11-01)
### Fixes ### Fixes

View File

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

View File

@ -12,6 +12,7 @@ custom-position
preset-card preset-card
preset-confirm preset-confirm
preset-confirm-slot preset-confirm-slot
transform-origin
``` ```
## API ## API
@ -24,6 +25,7 @@ preset-confirm-slot
| mask-closable | `boolean` | `true` | Whether to emit `hide` event when click mask. | | mask-closable | `boolean` | `true` | Whether to emit `hide` event when click mask. |
| preset | `'card' \| 'confirm'` | `undefined` | The preset of `n-modal`. | | preset | `'card' \| 'confirm'` | `undefined` | The preset of `n-modal`. |
| show | `boolean` | `false` | Whether to show 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-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-enter | `() => void` | `undefined` | Callback after modal is opened. |
| on-after-leave | `() => void` | `undefined` | Callback after modal is closed. | | 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-card
preset-confirm preset-confirm
preset-confirm-slot preset-confirm-slot
transform-origin
raw-debug raw-debug
dark-1-debug dark-1-debug
dark-2-debug dark-2-debug
@ -36,6 +37,7 @@ dark-10-debug
| mask-closable | `boolean` | `true` | 点击遮罩时是否发出 `update:show` 事件 | | mask-closable | `boolean` | `true` | 点击遮罩时是否发出 `update:show` 事件 |
| preset | `'card' \| 'dialog'` | `undefined` | 模态框使用何种预设 | | preset | `'card' \| 'dialog'` | `undefined` | 模态框使用何种预设 |
| show | `boolean` | `false` | 是否展示 Modal | | show | `boolean` | `false` | 是否展示 Modal |
| transform-origin | `'mouse' \| 'center'` | `'mouse'` | 模态框动画出现的位置 |
| on-update:show | `(value: boolean) => void` | `undefined` | 模态框更新是否展示状态的回调 | | on-update:show | `(value: boolean) => void` | `undefined` | 模态框更新是否展示状态的回调 |
| on-after-enter | `() => void` | `undefined` | Modal 出现后的回调 | | on-after-enter | `() => void` | `undefined` | Modal 出现后的回调 |
| on-after-leave | `() => 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 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const NModal = inject(modalInjectionKey)! const NModal = inject(modalInjectionKey)!
function styleTransformOrigin (): string { function styleTransformOrigin (): string {
if (NModal.transformOriginRef.value === 'center') {
return ''
}
const { value: transformOriginX } = transformOriginXRef const { value: transformOriginX } = transformOriginXRef
const { value: transformOriginY } = transformOriginYRef const { value: transformOriginY } = transformOriginYRef
if (transformOriginX === null || transformOriginY === null) { if (transformOriginX === null || transformOriginY === null) {
@ -92,6 +95,9 @@ export default defineComponent({
return '' return ''
} }
function syncTransformOrigin (el: HTMLElement): void { function syncTransformOrigin (el: HTMLElement): void {
if (NModal.transformOriginRef.value === 'center') {
return
}
const mousePosition = NModal.getMousePosition() const mousePosition = NModal.getMousePosition()
if (!mousePosition) { if (!mousePosition) {
return return

View File

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

View File

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