feat(modal): clsPrefix

This commit is contained in:
07akioni 2021-04-16 21:55:06 +08:00
parent 979c3c4d98
commit 0af36ac95b
4 changed files with 163 additions and 148 deletions

View File

@ -1 +1,2 @@
export { default as NModal } from './src/Modal'
export type { ModalProps } from './src/Modal'

View File

@ -23,10 +23,9 @@ import { NDialog } from '../../dialog'
import { NCard } from '../../card'
import { getFirstSlotVNode, keep, warn } from '../../_utils'
import { presetProps } from './presetProps'
import type { ModalInjection } from './Modal'
import { drawerBodyInjectionKey } from '../../drawer/src/interface'
import { popoverBodyInjectionKey } from '../../popover/src/interface'
import { modalBodyInjectionKey } from './interface'
import { modalBodyInjectionKey, modalInjectionKey } from './interface'
export default defineComponent({
name: 'ModalBody',
@ -77,7 +76,8 @@ export default defineComponent({
watch(toRef(props, 'show'), (value) => {
if (value) displayedRef.value = true
})
const NModal = inject<ModalInjection>('NModal') as ModalInjection
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const NModal = inject(modalInjectionKey)!
function styleTransformOrigin (): string {
const { value: transformOriginX } = transformOriginXRef
const { value: transformOriginY } = transformOriginYRef
@ -139,7 +139,10 @@ export default defineComponent({
provide(drawerBodyInjectionKey, null)
provide(popoverBodyInjectionKey, null)
return {
NModal,
mergedTheme: NModal.mergedThemeRef,
appear: NModal.appearRef,
isMounted: NModal.isMountedRef,
cPrefix: NModal.cPrefixRef,
bodyRef,
scrollbarRef,
displayed: displayedRef,
@ -154,14 +157,14 @@ export default defineComponent({
},
render () {
const {
NModal,
$slots,
$attrs,
handleEnter,
handleAfterLeave,
handleBeforeLeave,
handleClickOutside,
preset
preset,
cPrefix
} = this
let childNode: VNode | null = null
if (!preset) {
@ -172,7 +175,7 @@ export default defineComponent({
}
childNode.props = mergeProps(
{
class: 'n-modal'
class: `${cPrefix}-modal`
},
$attrs,
childNode.props || {}
@ -180,18 +183,18 @@ export default defineComponent({
}
return this.displayDirective === 'show' || this.displayed || this.show
? withDirectives(
<div class="n-modal-body-wrapper">
<div class={`${cPrefix}-modal-body-wrapper`}>
<NScrollbar
ref="scrollbarRef"
theme={NModal.mergedTheme.peers.Scrollbar}
themeOverrides={NModal.mergedTheme.peerOverrides.Scrollbar}
contentClass="n-modal-scroll-content"
theme={this.mergedTheme.peers.Scrollbar}
themeOverrides={this.mergedTheme.peerOverrides.Scrollbar}
contentClass={`${cPrefix}-modal-scroll-content`}
>
{{
default: () => (
<Transition
name="n-fade-in-scale-up-transition"
appear={NModal.appear ?? NModal.isMounted}
appear={this.appear ?? this.isMounted}
onEnter={handleEnter as any}
onAfterLeave={handleAfterLeave}
onBeforeLeave={handleBeforeLeave as any}
@ -203,11 +206,11 @@ export default defineComponent({
this.preset === 'dialog' ? (
<NDialog
{...this.$attrs}
class="n-modal"
class={`${cPrefix}-modal`}
ref="bodyRef"
theme={NModal.mergedTheme.peers.Dialog}
theme={this.mergedTheme.peers.Dialog}
themeOverrides={
NModal.mergedTheme.peerOverrides.Dialog
this.mergedTheme.peerOverrides.Dialog
}
{...keep(this.$props, dialogPropKeys)}
>
@ -217,10 +220,10 @@ export default defineComponent({
<NCard
{...this.$attrs}
ref="bodyRef"
class="n-modal"
theme={NModal.mergedTheme.peers.Card}
class={`${cPrefix}-modal`}
theme={this.mergedTheme.peers.Card}
themeOverrides={
NModal.mergedTheme.peerOverrides.Card
this.mergedTheme.peerOverrides.Card
}
{...keep(this.$props, cardBasePropKeys)}
>

View File

@ -6,7 +6,6 @@ import {
computed,
defineComponent,
provide,
reactive,
PropType,
CSSProperties,
toRef,
@ -17,126 +16,125 @@ import { useIsMounted, useClicked, useClickPosition } from 'vooks'
import { VLazyTeleport } from 'vueuc'
import { dialogProviderInjectionKey } from '../../dialog/src/DialogProvider'
import { useConfig, useTheme } from '../../_mixins'
import type { ThemeProps, MergedTheme } from '../../_mixins'
import { warn, keep, call } from '../../_utils'
import type { ThemeProps } from '../../_mixins'
import { warn, keep, call, ExtractPublicPropTypes } from '../../_utils'
import type { MaybeArray } from '../../_utils'
import { modalLight } from '../styles'
import type { ModalTheme } from '../styles'
import { presetProps, presetPropsKeys } from './presetProps'
import NModalBodyWrapper from './BodyWrapper'
import { modalInjectionKey } from './interface'
import style from './styles/index.cssr'
export interface ModalInjection {
getMousePosition: () => {
x: number
y: number
} | null
mergedTheme: MergedTheme<ModalTheme>
isMounted: boolean
appear: boolean | undefined
const modalProps = {
...(useTheme.props as ThemeProps<ModalTheme>),
show: {
type: Boolean,
default: false
},
unstableShowMask: {
type: Boolean,
default: true
},
maskClosable: {
type: Boolean,
default: true
},
preset: String as PropType<'confirm' | 'dialog' | 'card'>,
to: [String, Object] as PropType<string | HTMLElement>,
displayDirective: {
type: String as PropType<'if' | 'show'>,
default: 'if'
},
...presetProps,
// events
// eslint-disable-next-line vue/prop-name-casing
'onUpdate:show': [Function, Array] as PropType<
MaybeArray<(value: boolean) => void>
>,
onUpdateShow: [Function, Array] as PropType<
MaybeArray<(value: boolean) => void>
>,
// private
dialog: Boolean,
appear: {
type: Boolean as PropType<boolean | undefined>,
default: undefined
},
onBeforeLeave: Function as PropType<() => void>,
onAfterLeave: Function as PropType<() => void>,
onClose: Function as PropType<() => Promise<boolean> | boolean | any>,
onPositiveClick: Function as PropType<() => Promise<boolean> | boolean | any>,
onNegativeClick: Function as PropType<() => Promise<boolean> | boolean | any>,
// deprecated
overlayStyle: {
type: [String, Object] as PropType<string | CSSProperties | undefined>,
validator: () => {
if (__DEV__) {
warn(
'modal',
'`overlay-style` is deprecated, please use `style` instead.'
)
}
return true
},
default: undefined
},
onBeforeHide: {
type: (Function as unknown) as PropType<(() => void) | undefined>,
validator: () => {
if (__DEV__) {
warn(
'modal',
'`on-before-hide` is deprecated, please use `on-before-leave` instead.'
)
}
return true
},
default: undefined
},
onAfterHide: {
type: (Function as unknown) as PropType<(() => void) | undefined>,
validator: () => {
if (__DEV__) {
warn(
'modal',
'`on-after-hide` is deprecated, please use `on-after-leave` instead.'
)
}
return true
},
default: undefined
},
onHide: {
type: (Function as unknown) as PropType<
((value: false) => void) | undefined
>,
validator: () => {
if (__DEV__) warn('modal', '`on-hide` is deprecated.')
return true
},
default: undefined
}
}
export type ModalProps = ExtractPublicPropTypes<typeof modalProps>
export default defineComponent({
name: 'Modal',
inheritAttrs: false,
props: {
...(useTheme.props as ThemeProps<ModalTheme>),
show: {
type: Boolean,
default: false
},
unstableShowMask: {
type: Boolean,
default: true
},
maskClosable: {
type: Boolean,
default: true
},
preset: String as PropType<'confirm' | 'dialog' | 'card'>,
to: [String, Object] as PropType<string | HTMLElement>,
displayDirective: {
type: String as PropType<'if' | 'show'>,
default: 'if'
},
...presetProps,
// events
// eslint-disable-next-line vue/prop-name-casing
'onUpdate:show': [Function, Array] as PropType<
MaybeArray<(value: boolean) => void>
>,
onUpdateShow: [Function, Array] as PropType<
MaybeArray<(value: boolean) => void>
>,
// private
dialog: Boolean,
appear: {
type: Boolean as PropType<boolean | undefined>,
default: undefined
},
onBeforeLeave: Function as PropType<() => void>,
onAfterLeave: Function as PropType<() => void>,
onClose: Function as PropType<() => Promise<boolean> | boolean | any>,
onPositiveClick: Function as PropType<
() => Promise<boolean> | boolean | any
>,
onNegativeClick: Function as PropType<
() => Promise<boolean> | boolean | any
>,
// deprecated
overlayStyle: {
type: [String, Object] as PropType<string | CSSProperties | undefined>,
validator: () => {
if (__DEV__) {
warn(
'modal',
'`overlay-style` is deprecated, please use `style` instead.'
)
}
return true
},
default: undefined
},
onBeforeHide: {
type: (Function as unknown) as PropType<(() => void) | undefined>,
validator: () => {
if (__DEV__) {
warn(
'modal',
'`on-before-hide` is deprecated, please use `on-before-leave` instead.'
)
}
return true
},
default: undefined
},
onAfterHide: {
type: (Function as unknown) as PropType<(() => void) | undefined>,
validator: () => {
if (__DEV__) {
warn(
'modal',
'`on-after-hide` is deprecated, please use `on-after-leave` instead.'
)
}
return true
},
default: undefined
},
onHide: {
type: (Function as unknown) as PropType<
((value: false) => void) | undefined
>,
validator: () => {
if (__DEV__) warn('modal', '`on-hide` is deprecated.')
return true
},
default: undefined
}
},
props: modalProps,
setup (props) {
const containerRef = ref<HTMLElement | null>(null)
const themeRef = useTheme('Modal', 'Modal', style, modalLight, props)
const { mergedClsPrefix, namespace } = useConfig(props)
const themeRef = useTheme(
'Modal',
'Modal',
style,
modalLight,
props,
mergedClsPrefix
)
const clickedRef = useClicked(64)
const clickedPositionRef = useClickPosition()
const isMountedRef = useIsMounted()
@ -201,28 +199,26 @@ export default defineComponent({
}
}
}
provide<ModalInjection>(
'NModal',
reactive({
getMousePosition: () => {
if (NDialogProvider) {
if (NDialogProvider.clicked && NDialogProvider.clickPosition) {
return NDialogProvider.clickPosition
}
provide(modalInjectionKey, {
getMousePosition: () => {
if (NDialogProvider) {
if (NDialogProvider.clicked && NDialogProvider.clickPosition) {
return NDialogProvider.clickPosition
}
if (clickedRef.value) {
return clickedPositionRef.value
}
return null
},
mergedTheme: themeRef,
isMounted: isMountedRef,
appear: toRef(props, 'appear')
})
)
provide('NDrawer', null)
}
if (clickedRef.value) {
return clickedPositionRef.value
}
return null
},
cPrefixRef: mergedClsPrefix,
mergedThemeRef: themeRef,
isMountedRef: isMountedRef,
appearRef: toRef(props, 'appear')
})
return {
...useConfig(props),
cPrefix: mergedClsPrefix,
namespace,
isMounted: isMountedRef,
containerRef,
presetProps: computed(() => {
@ -264,7 +260,7 @@ export default defineComponent({
'div',
{
ref: 'containerRef',
class: ['n-modal-container', this.namespace],
class: [`${this.cPrefix}-modal-container`, this.namespace],
style: this.cssVars as CSSProperties
},
[
@ -281,7 +277,7 @@ export default defineComponent({
return this.show
? h('div', {
ref: 'containerRef',
class: 'n-modal-mask'
class: `${this.cPrefix}-modal-mask`
})
: null
}

View File

@ -1,9 +1,24 @@
import { Ref, ComponentPublicInstance, InjectionKey } from 'vue'
import type { MergedTheme } from '../../_mixins'
import type { ModalTheme } from '../styles'
export type ModalBodyInjection = Ref<
HTMLElement | ComponentPublicInstance | null
> | null
export const modalBodyInjectionKey: InjectionKey<ModalBodyInjection> = Symbol(
'modalBodyInjection'
'modalBody'
)
export interface ModalInjection {
getMousePosition: () => {
x: number
y: number
} | null
cPrefixRef: Ref<string>
mergedThemeRef: Ref<MergedTheme<ModalTheme>>
isMountedRef: Ref<boolean>
appearRef: Ref<boolean | undefined>
}
export const modalInjectionKey: InjectionKey<ModalInjection> = Symbol('modal')