mirror of
https://github.com/tusen-ai/naive-ui.git
synced 2025-01-06 12:17:13 +08:00
feat(notification): clsPrefix
This commit is contained in:
parent
86c2c6742e
commit
8f3fb3737c
@ -1,4 +1,3 @@
|
||||
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
||||
import { h, defineComponent, PropType, inject, computed, renderSlot } from 'vue'
|
||||
import { createId } from 'seemly'
|
||||
import { useMemo } from 'vooks'
|
||||
|
@ -75,7 +75,6 @@ export default defineComponent({
|
||||
<div
|
||||
class={`${clsPrefix}-color-picker-pallete__layer`}
|
||||
style={{
|
||||
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
||||
backgroundImage: `linear-gradient(90deg, white, hsl(${this.displayedHue}, 100%, 50%))`
|
||||
}}
|
||||
/>
|
||||
|
@ -58,7 +58,7 @@ interface PrivateMessageRef extends MessageReactive {
|
||||
|
||||
export type MessageProviderInst = MessageApiInjection
|
||||
|
||||
const messageProps = {
|
||||
const messageProviderProps = {
|
||||
...(useTheme.props as ThemeProps<MessageTheme>),
|
||||
to: {
|
||||
type: [String, Object],
|
||||
@ -66,9 +66,11 @@ const messageProps = {
|
||||
}
|
||||
}
|
||||
|
||||
export type MessageProviderProps = ExtractPublicPropTypes<typeof messageProps>
|
||||
export type MessageProviderProps = ExtractPublicPropTypes<
|
||||
typeof messageProviderProps
|
||||
>
|
||||
|
||||
type MessageProviderSetupProps = ExtractPropTypes<typeof messageProps>
|
||||
type MessageProviderSetupProps = ExtractPropTypes<typeof messageProviderProps>
|
||||
|
||||
export const messageProviderInjectionKey: InjectionKey<{
|
||||
props: MessageProviderSetupProps
|
||||
@ -77,7 +79,7 @@ export const messageProviderInjectionKey: InjectionKey<{
|
||||
|
||||
export default defineComponent({
|
||||
name: 'MessageProvider',
|
||||
props: messageProps,
|
||||
props: messageProviderProps,
|
||||
setup (props) {
|
||||
const { mergedClsPrefix } = useConfig(props)
|
||||
const messageListRef = ref<PrivateMessageReactive[]>([])
|
||||
@ -120,13 +122,15 @@ export default defineComponent({
|
||||
1
|
||||
)
|
||||
}
|
||||
return {
|
||||
cPrefix: mergedClsPrefix,
|
||||
messageRefs,
|
||||
messageList: messageListRef,
|
||||
handleAfterLeave,
|
||||
...api
|
||||
}
|
||||
return Object.assign(
|
||||
{
|
||||
cPrefix: mergedClsPrefix,
|
||||
messageRefs,
|
||||
messageList: messageListRef,
|
||||
handleAfterLeave
|
||||
},
|
||||
api
|
||||
)
|
||||
},
|
||||
render () {
|
||||
return (
|
||||
|
@ -1,2 +1,6 @@
|
||||
export { default as NNotificationProvider } from './src/NotificationProvider'
|
||||
export type {
|
||||
NotificationProviderProps,
|
||||
NotificationProviderInst
|
||||
} from './src/NotificationProvider'
|
||||
export { useNotification } from './src/use-notification'
|
||||
|
@ -16,7 +16,7 @@ import {
|
||||
WarningIcon,
|
||||
ErrorIcon
|
||||
} from '../../_internal/icons'
|
||||
import { NotificationProviderInjection } from './NotificationProvider'
|
||||
import { notificationProviderInjectionKey } from './NotificationProvider'
|
||||
|
||||
const iconMap = {
|
||||
info: <InfoIcon />,
|
||||
@ -57,10 +57,12 @@ export default defineComponent({
|
||||
name: 'Notification',
|
||||
props: notificationProps,
|
||||
setup (props) {
|
||||
const NNotificationProvider = inject<NotificationProviderInjection>(
|
||||
'NNotificationProvider'
|
||||
) as NotificationProviderInjection
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const { cPrefixRef, mergedThemeRef } = inject(
|
||||
notificationProviderInjectionKey
|
||||
)!
|
||||
return {
|
||||
cPrefix: cPrefixRef,
|
||||
showAvatar: computed(() => {
|
||||
return props.avatar || props.type !== 'default'
|
||||
}),
|
||||
@ -95,7 +97,7 @@ export default defineComponent({
|
||||
cubicBezierEaseIn,
|
||||
cubicBezierEaseInOut
|
||||
}
|
||||
} = NNotificationProvider.mergedTheme
|
||||
} = mergedThemeRef.value
|
||||
const { left, right, top, bottom } = getPadding(padding)
|
||||
return {
|
||||
'--color': color,
|
||||
@ -127,58 +129,61 @@ export default defineComponent({
|
||||
}
|
||||
},
|
||||
render () {
|
||||
const { cPrefix } = this
|
||||
return (
|
||||
<div
|
||||
class={[
|
||||
'n-notification',
|
||||
`${cPrefix}-notification`,
|
||||
{
|
||||
'n-notification--closable': this.closable,
|
||||
'n-notification--show-avatar': this.showAvatar
|
||||
[`${cPrefix}-notification--closable`]: this.closable,
|
||||
[`${cPrefix}-notification--show-avatar`]: this.showAvatar
|
||||
}
|
||||
]}
|
||||
style={this.cssVars as CSSProperties}
|
||||
>
|
||||
{this.showAvatar ? (
|
||||
<div class="n-notification__avatar">
|
||||
<div class={`${cPrefix}-notification__avatar`}>
|
||||
{this.avatar ? (
|
||||
<Render render={this.avatar} />
|
||||
) : this.type !== 'default' ? (
|
||||
<NBaseIcon>{{ default: () => iconMap[this.type] }}</NBaseIcon>
|
||||
<NBaseIcon clsPrefix={cPrefix}>
|
||||
{{ default: () => iconMap[this.type] }}
|
||||
</NBaseIcon>
|
||||
) : null}
|
||||
</div>
|
||||
) : null}
|
||||
{this.closable ? (
|
||||
<NBaseClose
|
||||
class="n-notification__close"
|
||||
clsPrefix={cPrefix}
|
||||
class={`${cPrefix}-notification__close`}
|
||||
onClick={this.handleCloseClick}
|
||||
/>
|
||||
) : null}
|
||||
<div ref="bodyRef" class="n-notification-main">
|
||||
<div ref="bodyRef" class={`${cPrefix}-notification-main`}>
|
||||
{this.title ? (
|
||||
<div class="n-notification-main__header">
|
||||
<div class={`${cPrefix}-notification-main__header`}>
|
||||
<Render render={this.title} />
|
||||
</div>
|
||||
) : null}
|
||||
{this.description ? (
|
||||
<div class="n-notification-main__description">
|
||||
<div class={`${cPrefix}-notification-main__description`}>
|
||||
<Render render={this.description} />
|
||||
</div>
|
||||
) : null}
|
||||
{this.content ? (
|
||||
<pre class="n-notification-main__content">
|
||||
<pre class={`${cPrefix}-notification-main__content`}>
|
||||
<Render render={this.content} />
|
||||
</pre>
|
||||
) : null}
|
||||
|
||||
{this.meta || this.action ? (
|
||||
<div class="n-notification-main-footer">
|
||||
<div class={`${cPrefix}-notification-main-footer`}>
|
||||
{this.meta ? (
|
||||
<div class="n-notification-main-footer__meta">
|
||||
<div class={`${cPrefix}-notification-main-footer__meta`}>
|
||||
<Render render={this.meta} />
|
||||
</div>
|
||||
) : null}
|
||||
{this.action ? (
|
||||
<div class="n-notification-main-footer__action">
|
||||
<div class={`${cPrefix}-notification-main-footer__action`}>
|
||||
<Render render={this.action} />
|
||||
</div>
|
||||
) : null}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { h, defineComponent, inject } from 'vue'
|
||||
import { NScrollbar } from '../../scrollbar'
|
||||
import { NotificationProviderInjection } from './NotificationProvider'
|
||||
import { notificationProviderInjectionKey } from './NotificationProvider'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'NotificationContainer',
|
||||
@ -11,29 +11,28 @@ export default defineComponent({
|
||||
}
|
||||
},
|
||||
setup () {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const { mergedThemeRef, cPrefixRef } = inject(
|
||||
notificationProviderInjectionKey
|
||||
)!
|
||||
return {
|
||||
NNotificationProvider: inject<NotificationProviderInjection>(
|
||||
'NNotificationProvider'
|
||||
) as NotificationProviderInjection
|
||||
mergedTheme: mergedThemeRef,
|
||||
cPrefix: cPrefixRef
|
||||
}
|
||||
},
|
||||
render () {
|
||||
const { $slots, scrollable, NNotificationProvider } = this
|
||||
const { $slots, scrollable, cPrefix, mergedTheme } = this
|
||||
return (
|
||||
<div
|
||||
class={[
|
||||
'n-notification-container',
|
||||
{
|
||||
'n-notification-container--scrollable': scrollable
|
||||
}
|
||||
`${cPrefix}-notification-container`,
|
||||
scrollable && `${cPrefix}-notification-container--scrollable`
|
||||
]}
|
||||
>
|
||||
{scrollable ? (
|
||||
<NScrollbar
|
||||
theme={NNotificationProvider.mergedTheme.peers.Scrollbar}
|
||||
themeOverrides={
|
||||
NNotificationProvider.mergedTheme.peerOverrides.Scrollbar
|
||||
}
|
||||
theme={mergedTheme.peers.Scrollbar}
|
||||
themeOverrides={mergedTheme.peerOverrides.Scrollbar}
|
||||
>
|
||||
{$slots}
|
||||
</NScrollbar>
|
||||
|
@ -118,29 +118,28 @@ export default defineComponent({
|
||||
}
|
||||
},
|
||||
render () {
|
||||
return h(
|
||||
Transition,
|
||||
{
|
||||
name: 'n-notification-transition',
|
||||
appear: true,
|
||||
return (
|
||||
<Transition
|
||||
name="notification-transition"
|
||||
appear={true}
|
||||
// convert to any since Element is not compitable with HTMLElement
|
||||
onBeforeEnter: this.handleBeforeEnter as any,
|
||||
onAfterEnter: this.handleAfterEnter as any,
|
||||
onBeforeLeave: this.handleBeforeLeave as any,
|
||||
onLeave: this.handleLeave as any,
|
||||
onAfterLeave: this.handleAfterLeave as any
|
||||
},
|
||||
{
|
||||
default: () => {
|
||||
const props = keep(this.$props, notificationPropKeys)
|
||||
return this.show
|
||||
? h(NNotification, {
|
||||
...props,
|
||||
onClose: this.handleClose
|
||||
})
|
||||
: null
|
||||
}
|
||||
}
|
||||
onBeforeEnter={this.handleBeforeEnter as any}
|
||||
onAfterEnter={this.handleAfterEnter as any}
|
||||
onBeforeLeave={this.handleBeforeLeave as any}
|
||||
onLeave={this.handleLeave as any}
|
||||
onAfterLeave={this.handleAfterLeave as any}
|
||||
>
|
||||
{{
|
||||
default: () => {
|
||||
return this.show ? (
|
||||
<NNotification
|
||||
{...keep(this.$props, notificationPropKeys)}
|
||||
onClose={this.handleClose}
|
||||
/>
|
||||
) : null
|
||||
}
|
||||
}}
|
||||
</Transition>
|
||||
)
|
||||
}
|
||||
})
|
@ -8,12 +8,15 @@ import {
|
||||
defineComponent,
|
||||
PropType,
|
||||
ExtractPropTypes,
|
||||
provide
|
||||
provide,
|
||||
InjectionKey,
|
||||
Ref,
|
||||
renderSlot
|
||||
} from 'vue'
|
||||
import { createId } from 'seemly'
|
||||
import { useTheme } from '../../_mixins'
|
||||
import { useConfig, useTheme } from '../../_mixins'
|
||||
import type { MergedTheme, ThemeProps } from '../../_mixins'
|
||||
import { omit } from '../../_utils'
|
||||
import { ExtractPublicPropTypes, omit } from '../../_utils'
|
||||
import { notificationLight, NotificationTheme } from '../styles'
|
||||
import NotificationContainer from './NotificationContainer'
|
||||
import NotificationEnvironment, {
|
||||
@ -26,9 +29,14 @@ ExtractPropTypes<typeof notificationEnvOptions>
|
||||
>
|
||||
|
||||
export interface NotificationProviderInjection {
|
||||
mergedTheme: MergedTheme<NotificationTheme>
|
||||
cPrefixRef: Ref<string>
|
||||
mergedThemeRef: Ref<MergedTheme<NotificationTheme>>
|
||||
}
|
||||
|
||||
export const notificationProviderInjectionKey: InjectionKey<NotificationProviderInjection> = Symbol(
|
||||
'notificationProvider'
|
||||
)
|
||||
|
||||
type Create = (options: NotificationOptions) => NotificationReactive
|
||||
type TypedCreate = (
|
||||
options: Omit<NotificationOptions, 'type'>
|
||||
@ -44,6 +52,12 @@ export interface NotificationApiInjection {
|
||||
open: Create
|
||||
}
|
||||
|
||||
export type NotificationProviderInst = NotificationApiInjection
|
||||
|
||||
export const notificationApiInjectionKey: InjectionKey<NotificationApiInjection> = Symbol(
|
||||
'notificationApi'
|
||||
)
|
||||
|
||||
type NotificationReactive = {
|
||||
readonly key: string
|
||||
readonly destroy: () => void
|
||||
@ -57,23 +71,29 @@ interface NotificationRef {
|
||||
hide: () => void
|
||||
}
|
||||
|
||||
const notificationProviderProps = {
|
||||
...(useTheme.props as ThemeProps<NotificationTheme>),
|
||||
to: [String, Object] as PropType<string | HTMLElement>,
|
||||
scrollable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
}
|
||||
|
||||
export type NotificationProviderProps = ExtractPublicPropTypes<
|
||||
typeof notificationProviderProps
|
||||
>
|
||||
|
||||
export default defineComponent({
|
||||
name: 'NotificationProvider',
|
||||
props: {
|
||||
...(useTheme.props as ThemeProps<NotificationTheme>),
|
||||
to: [String, Object] as PropType<string | HTMLElement>,
|
||||
scrollable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
props: notificationProviderProps,
|
||||
setup (props) {
|
||||
const { mergedClsPrefix } = useConfig(props)
|
||||
const notificationListRef = ref<NotificationReactive[]>([])
|
||||
const notificationRefs: Record<string, NotificationRef> = {}
|
||||
function create (options: NotificationOptions): NotificationReactive {
|
||||
const key = createId()
|
||||
const destroy = (): void =>
|
||||
notificationRefs[`n-notification-${key}`].hide()
|
||||
const destroy = (): void => notificationRefs[key].hide()
|
||||
const notificationReactive = reactive({
|
||||
...options,
|
||||
key,
|
||||
@ -103,72 +123,72 @@ export default defineComponent({
|
||||
'Notification',
|
||||
style,
|
||||
notificationLight,
|
||||
props
|
||||
props,
|
||||
mergedClsPrefix
|
||||
)
|
||||
provide<NotificationApiInjection>('notification', {
|
||||
const api = {
|
||||
create,
|
||||
info: apis[0],
|
||||
success: apis[1],
|
||||
warning: apis[2],
|
||||
error: apis[3],
|
||||
open
|
||||
}
|
||||
provide(notificationApiInjectionKey, api)
|
||||
provide(notificationProviderInjectionKey, {
|
||||
cPrefixRef: mergedClsPrefix,
|
||||
mergedThemeRef: themeRef
|
||||
})
|
||||
provide<NotificationProviderInjection>(
|
||||
'NNotificationProvider',
|
||||
reactive({
|
||||
mergedTheme: themeRef
|
||||
})
|
||||
)
|
||||
// deprecated
|
||||
function open (options: NotificationOptions): NotificationReactive {
|
||||
return create(options)
|
||||
}
|
||||
return {
|
||||
handleAfterLeave,
|
||||
notificationList: notificationListRef,
|
||||
notificationRefs
|
||||
}
|
||||
return Object.assign(
|
||||
{
|
||||
cPrefix: mergedClsPrefix,
|
||||
notificationList: notificationListRef,
|
||||
notificationRefs,
|
||||
handleAfterLeave
|
||||
},
|
||||
api
|
||||
)
|
||||
},
|
||||
render () {
|
||||
return h(Fragment, null, [
|
||||
h(
|
||||
Teleport,
|
||||
{
|
||||
to: this.to ?? 'body'
|
||||
},
|
||||
[
|
||||
this.notificationList.length
|
||||
? h(
|
||||
NotificationContainer,
|
||||
{
|
||||
scrollable: this.scrollable
|
||||
},
|
||||
{
|
||||
return (
|
||||
<>
|
||||
{renderSlot(this.$slots, 'default')}
|
||||
{this.notificationList.length ? (
|
||||
<Teleport to={this.to ?? 'body'}>
|
||||
<NotificationContainer scrollable={this.scrollable}>
|
||||
{{
|
||||
default: () => {
|
||||
return this.notificationList.map((notification) => {
|
||||
return h(NotificationEnvironment, {
|
||||
ref: ((inst: NotificationRef) => {
|
||||
const refKey = `n-notification-${notification.key}`
|
||||
if (inst === null) {
|
||||
delete this.notificationRefs[refKey]
|
||||
} else this.notificationRefs[refKey] = inst
|
||||
}) as any,
|
||||
...omit(notification, [
|
||||
'destroy',
|
||||
'hide',
|
||||
'deactivate'
|
||||
]),
|
||||
internalKey: notification.key,
|
||||
onInternalAfterLeave: this.handleAfterLeave
|
||||
})
|
||||
return (
|
||||
<NotificationEnvironment
|
||||
ref={
|
||||
((inst: NotificationRef) => {
|
||||
const refKey = notification.key
|
||||
if (inst === null) {
|
||||
delete this.notificationRefs[refKey]
|
||||
} else this.notificationRefs[refKey] = inst
|
||||
}) as any
|
||||
}
|
||||
{...omit(notification, [
|
||||
'destroy',
|
||||
'hide',
|
||||
'deactivate'
|
||||
])}
|
||||
internalKey={notification.key}
|
||||
onInternalAfterLeave={this.handleAfterLeave}
|
||||
/>
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
)
|
||||
: null
|
||||
]
|
||||
),
|
||||
this.$slots.default?.()
|
||||
])
|
||||
}}
|
||||
</NotificationContainer>
|
||||
</Teleport>
|
||||
) : null}
|
||||
</>
|
||||
)
|
||||
}
|
||||
})
|
@ -62,16 +62,16 @@ export default c([
|
||||
top: 0
|
||||
}),
|
||||
cB('notification', [
|
||||
c('&-transition-enter-from, &-transition-leave-to', `
|
||||
c('&.notification-transition-enter-from, &.notification-transition-leave-to', `
|
||||
opacity: 0;
|
||||
margin-bottom: 0 !important;
|
||||
transform: translateX(calc(100% + 16px));
|
||||
`),
|
||||
c('&-transition-leave-from, &-transition-enter-to', `
|
||||
c('&.notification-transition-leave-from, &.notification-transition-enter-to', `
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
`),
|
||||
c('&-transition-leave-active', `
|
||||
c('&.notification-transition-leave-active', `
|
||||
transition:
|
||||
background-color .3s var(--bezier),
|
||||
color .3s var(--bezier),
|
||||
|
@ -1,6 +1,12 @@
|
||||
import { inject } from 'vue'
|
||||
import { NotificationApiInjection } from './NotificationProvider'
|
||||
import { notificationApiInjectionKey } from './NotificationProvider'
|
||||
import type { NotificationApiInjection } from './NotificationProvider'
|
||||
import { throwError } from '../../_utils'
|
||||
|
||||
export function useNotification (): NotificationApiInjection | undefined {
|
||||
return inject<NotificationApiInjection>('notification')
|
||||
export function useNotification (): NotificationApiInjection {
|
||||
const api = inject(notificationApiInjectionKey, null)
|
||||
if (api === null) {
|
||||
throwError('use-notification', 'No outer `n-notification-provider` found.')
|
||||
}
|
||||
return api
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user