@v-c/notification 1.0.0 → 2.0.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/dist/Notification.d.ts +59 -0
  2. package/dist/Notification.js +301 -0
  3. package/dist/NotificationList/Content.d.ts +11 -0
  4. package/dist/NotificationList/Content.js +60 -0
  5. package/dist/NotificationList/index.d.ts +35 -0
  6. package/dist/NotificationList/index.js +224 -0
  7. package/dist/NotificationProvider.js +3 -1
  8. package/dist/Notifications.d.ts +9 -3
  9. package/dist/Notifications.js +45 -21
  10. package/dist/Progress.d.ts +8 -0
  11. package/dist/Progress.js +31 -0
  12. package/dist/hooks/useClosable.d.ts +17 -0
  13. package/dist/hooks/useClosable.js +34 -0
  14. package/dist/hooks/useListPosition/index.d.ts +18 -0
  15. package/dist/hooks/useListPosition/index.js +41 -0
  16. package/dist/hooks/useListPosition/useSizes.d.ts +10 -0
  17. package/dist/hooks/useListPosition/useSizes.js +31 -0
  18. package/dist/hooks/useNoticeTimer.d.ts +7 -0
  19. package/dist/hooks/useNoticeTimer.js +63 -0
  20. package/dist/hooks/useNotification.d.ts +10 -8
  21. package/dist/hooks/useNotification.js +10 -4
  22. package/dist/hooks/useStack.d.ts +5 -0
  23. package/dist/hooks/useStack.js +13 -10
  24. package/dist/index.d.ts +9 -6
  25. package/dist/index.js +5 -3
  26. package/dist/interface.d.ts +18 -43
  27. package/package.json +3 -3
  28. package/src/Notification.tsx +326 -0
  29. package/src/NotificationList/Content.tsx +66 -0
  30. package/src/NotificationList/index.tsx +282 -0
  31. package/src/Notifications.tsx +58 -64
  32. package/src/Progress.tsx +27 -0
  33. package/src/hooks/useClosable.ts +53 -0
  34. package/src/hooks/useListPosition/index.ts +69 -0
  35. package/src/hooks/useListPosition/useSizes.ts +43 -0
  36. package/src/hooks/useNoticeTimer.ts +85 -0
  37. package/src/hooks/useNotification.tsx +30 -28
  38. package/src/hooks/useStack.ts +12 -8
  39. package/src/index.ts +47 -6
  40. package/src/interface.ts +28 -44
  41. package/vite.config.ts +4 -3
  42. package/dist/Notice.cjs +0 -235
  43. package/dist/Notice.d.ts +0 -15
  44. package/dist/Notice.js +0 -227
  45. package/dist/NoticeList.cjs +0 -170
  46. package/dist/NoticeList.d.ts +0 -13
  47. package/dist/NoticeList.js +0 -164
  48. package/dist/NotificationProvider.cjs +0 -14
  49. package/dist/Notifications.cjs +0 -146
  50. package/dist/_virtual/rolldown_runtime.cjs +0 -21
  51. package/dist/hooks/useNotification.cjs +0 -93
  52. package/dist/hooks/useStack.cjs +0 -27
  53. package/dist/index.cjs +0 -7
  54. package/dist/interface.cjs +0 -1
  55. package/src/Notice.tsx +0 -212
  56. package/src/NoticeList.tsx +0 -219
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@v-c/notification",
3
3
  "type": "module",
4
- "version": "1.0.0",
4
+ "version": "2.0.0-rc.1",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -9,7 +9,7 @@
9
9
  ".": {
10
10
  "types": "./dist/index.d.ts",
11
11
  "import": "./dist/index.js",
12
- "require": "./dist/index.cjs"
12
+ "default": "./dist/index.js"
13
13
  },
14
14
  "./dist/*": "./dist/*",
15
15
  "./package.json": "./package.json"
@@ -19,7 +19,7 @@
19
19
  "vue": "^3.0.0"
20
20
  },
21
21
  "dependencies": {
22
- "@v-c/util": "^1.0.9"
22
+ "@v-c/util": "^1.0.19"
23
23
  },
24
24
  "scripts": {
25
25
  "build": "vite build",
@@ -0,0 +1,326 @@
1
+ import type { Component, CSSProperties, HTMLAttributes } from 'vue'
2
+ import type { VueNode } from '@v-c/util/dist/type'
3
+ import type { ClosableType } from './hooks/useClosable'
4
+ import type { NotificationProgressProps } from './Progress'
5
+ import { clsx } from '@v-c/util'
6
+ import { computed, defineComponent, ref, shallowRef, watch } from 'vue'
7
+ import useClosable from './hooks/useClosable'
8
+ import useNoticeTimer from './hooks/useNoticeTimer'
9
+ import DefaultProgress from './Progress'
10
+
11
+ export interface NotificationClassNames {
12
+ wrapper?: string
13
+ root?: string
14
+ icon?: string
15
+ section?: string
16
+ title?: string
17
+ description?: string
18
+ actions?: string
19
+ close?: string
20
+ progress?: string
21
+ }
22
+
23
+ export interface NotificationStyles {
24
+ wrapper?: CSSProperties
25
+ root?: CSSProperties
26
+ icon?: CSSProperties
27
+ section?: CSSProperties
28
+ title?: CSSProperties
29
+ description?: CSSProperties
30
+ actions?: CSSProperties
31
+ close?: CSSProperties
32
+ progress?: CSSProperties
33
+ }
34
+
35
+ export interface ComponentsType {
36
+ progress?: Component<NotificationProgressProps>
37
+ }
38
+
39
+ export interface NotificationProps {
40
+ // Style
41
+ prefixCls: string
42
+ className?: string
43
+ style?: CSSProperties
44
+ classNames?: NotificationClassNames
45
+ styles?: NotificationStyles
46
+ components?: ComponentsType
47
+
48
+ // UI
49
+ title?: VueNode
50
+ description?: VueNode
51
+ icon?: VueNode
52
+ actions?: VueNode
53
+ role?: string
54
+ closable?: ClosableType
55
+ offset?: number
56
+ notificationIndex?: number
57
+ stackInThreshold?: boolean
58
+ props?: HTMLAttributes & Record<string, any>
59
+
60
+ // Behavior
61
+ duration?: number | false | null
62
+ showProgress?: boolean
63
+ times?: number
64
+ hovering?: boolean
65
+ pauseOnHover?: boolean
66
+
67
+ // Function
68
+ onClick?: (e: MouseEvent) => void
69
+ onMouseEnter?: (e: MouseEvent) => void
70
+ onMouseLeave?: (e: MouseEvent) => void
71
+ /** @deprecated Please use `closable.onClose` instead. */
72
+ onClose?: () => void
73
+ }
74
+
75
+ interface NoticeStyle extends CSSProperties {
76
+ '--notification-index'?: number
77
+ '--notification-y'?: string
78
+ }
79
+
80
+ const Notification = defineComponent<NotificationProps>(
81
+ (props, { attrs, expose }) => {
82
+ const nodeRef = ref<HTMLDivElement | null>(null)
83
+ const percent = shallowRef(0)
84
+ const hovering = shallowRef(false)
85
+
86
+ expose({
87
+ nativeElement: nodeRef,
88
+ })
89
+
90
+ // ========================= Close ==========================
91
+ const closableRef = computed(() => props.closable)
92
+ const [mergedClosable, closableConfig, closeBtnAriaProps] = useClosable(closableRef)
93
+
94
+ const onInternalClose = () => {
95
+ closableConfig.value.onClose?.()
96
+ props.onClose?.()
97
+ }
98
+
99
+ // ======================== Duration ========================
100
+ const mergedDuration = computed(() => {
101
+ if (props.duration === undefined) {
102
+ return 4.5
103
+ }
104
+ return props.duration
105
+ })
106
+ const [onResume, onPause] = useNoticeTimer(
107
+ mergedDuration,
108
+ onInternalClose,
109
+ (next) => {
110
+ percent.value = next
111
+ },
112
+ )
113
+
114
+ // Sync pause/resume to forced and local hover.
115
+ watch(
116
+ [
117
+ () => props.hovering,
118
+ hovering,
119
+ () => props.pauseOnHover,
120
+ ],
121
+ () => {
122
+ const pauseOnHover = props.pauseOnHover ?? true
123
+ if (!pauseOnHover) {
124
+ return
125
+ }
126
+ if (props.hovering) {
127
+ onPause()
128
+ }
129
+ else if (!hovering.value) {
130
+ onResume()
131
+ }
132
+ },
133
+ { immediate: true },
134
+ )
135
+
136
+ // Cache offset/notificationIndex so transitions still have a value
137
+ // even when the controlling list omits them temporarily.
138
+ const offsetRef = shallowRef(props.offset)
139
+ const indexRef = shallowRef(props.notificationIndex)
140
+ watch(() => props.offset, (next) => {
141
+ if (next !== undefined) {
142
+ offsetRef.value = next
143
+ }
144
+ })
145
+ watch(() => props.notificationIndex, (next) => {
146
+ if (next !== undefined) {
147
+ indexRef.value = next
148
+ }
149
+ })
150
+
151
+ // ======================== Hover ==========================
152
+ const onInternalMouseEnter = (e: MouseEvent) => {
153
+ hovering.value = true
154
+ if ((props.pauseOnHover ?? true)) {
155
+ onPause()
156
+ }
157
+ props.onMouseEnter?.(e)
158
+ ;(props.props?.onMouseenter as any)?.(e)
159
+ }
160
+
161
+ const onInternalMouseLeave = (e: MouseEvent) => {
162
+ hovering.value = false
163
+ const pauseOnHover = props.pauseOnHover ?? true
164
+ if (pauseOnHover && !props.hovering) {
165
+ onResume()
166
+ }
167
+ props.onMouseLeave?.(e)
168
+ ;(props.props?.onMouseleave as any)?.(e)
169
+ }
170
+
171
+ const onInternalCloseClick = (e: MouseEvent) => {
172
+ e.preventDefault()
173
+ e.stopPropagation()
174
+ onInternalClose()
175
+ }
176
+
177
+ return () => {
178
+ const {
179
+ prefixCls,
180
+ className,
181
+ style,
182
+ classNames: ncs,
183
+ styles: nss,
184
+ components,
185
+ title,
186
+ description,
187
+ icon,
188
+ actions,
189
+ role,
190
+ stackInThreshold,
191
+ props: rootProps,
192
+ showProgress,
193
+ duration,
194
+ } = props
195
+
196
+ const noticePrefixCls = `${prefixCls}-notice`
197
+
198
+ // ======================== Content =========================
199
+ const titleNode = title !== undefined && title !== null
200
+ ? (
201
+ <div class={clsx(`${noticePrefixCls}-title`, ncs?.title)} style={nss?.title}>
202
+ {title}
203
+ </div>
204
+ )
205
+ : null
206
+
207
+ const descNode = description !== undefined && description !== null
208
+ ? (
209
+ <div class={clsx(`${noticePrefixCls}-description`, ncs?.description)} style={nss?.description}>
210
+ {description}
211
+ </div>
212
+ )
213
+ : null
214
+
215
+ const hasTitle = titleNode !== null
216
+ const hasDescription = descNode !== null
217
+
218
+ let contentNode: VueNode = null
219
+ if (hasTitle && hasDescription) {
220
+ contentNode = (
221
+ <div class={clsx(`${noticePrefixCls}-section`, ncs?.section)} style={nss?.section}>
222
+ {titleNode}
223
+ {descNode}
224
+ </div>
225
+ )
226
+ }
227
+ else {
228
+ contentNode = titleNode || descNode
229
+ }
230
+
231
+ if (icon !== undefined && icon !== null) {
232
+ contentNode = (
233
+ <div class={clsx(`${noticePrefixCls}-wrapper`, ncs?.wrapper)} style={nss?.wrapper}>
234
+ <div class={clsx(`${noticePrefixCls}-icon`, ncs?.icon)} style={nss?.icon}>
235
+ {icon}
236
+ </div>
237
+ {contentNode}
238
+ </div>
239
+ )
240
+ }
241
+
242
+ const actionsNode = actions
243
+ ? (
244
+ <div class={clsx(`${noticePrefixCls}-actions`, ncs?.actions)} style={nss?.actions}>
245
+ {actions}
246
+ </div>
247
+ )
248
+ : null
249
+
250
+ // ========================= Render =========================
251
+ const mergedOffset = props.offset ?? offsetRef.value
252
+ const mergedIndex = props.notificationIndex ?? indexRef.value ?? 0
253
+ const safePercent = Math.min(Math.max(percent.value * 100, 0), 100)
254
+ const validPercent = 100 - safePercent
255
+ const ProgressComponent = (components?.progress || DefaultProgress) as any
256
+
257
+ const mergedStyle: NoticeStyle = {
258
+ '--notification-index': mergedIndex,
259
+ ...nss?.root,
260
+ ...style,
261
+ }
262
+ if (mergedOffset !== undefined) {
263
+ mergedStyle['--notification-y'] = `${mergedOffset}px`
264
+ }
265
+
266
+ const mergedRole = role ?? (rootProps as any)?.role ?? 'alert'
267
+
268
+ return (
269
+ <div
270
+ {...rootProps}
271
+ ref={nodeRef}
272
+ role={mergedRole}
273
+ data-notification-index={mergedIndex}
274
+ class={clsx(
275
+ noticePrefixCls,
276
+ className,
277
+ (attrs as any).class,
278
+ ncs?.root,
279
+ {
280
+ [`${noticePrefixCls}-closable`]: mergedClosable.value,
281
+ [`${noticePrefixCls}-stack-in-threshold`]: stackInThreshold,
282
+ },
283
+ )}
284
+ style={{
285
+ ...mergedStyle,
286
+ ...((attrs as any).style as CSSProperties | undefined),
287
+ }}
288
+ onClick={props.onClick}
289
+ onMouseenter={onInternalMouseEnter}
290
+ onMouseleave={onInternalMouseLeave}
291
+ >
292
+ {contentNode}
293
+ {actionsNode}
294
+
295
+ {mergedClosable.value && (
296
+ <button
297
+ class={clsx(`${noticePrefixCls}-close`, ncs?.close)}
298
+ aria-label="Close"
299
+ {...closeBtnAriaProps.value}
300
+ style={nss?.close}
301
+ onClick={onInternalCloseClick}
302
+ >
303
+ {closableConfig.value.closeIcon}
304
+ </button>
305
+ )}
306
+
307
+ {showProgress && typeof duration === 'number' && duration > 0 && (
308
+ <ProgressComponent
309
+ {...{
310
+ className: clsx(`${noticePrefixCls}-progress`, ncs?.progress),
311
+ percent: validPercent,
312
+ style: nss?.progress,
313
+ } as NotificationProgressProps}
314
+ />
315
+ )}
316
+ </div>
317
+ )
318
+ }
319
+ },
320
+ {
321
+ name: 'Notification',
322
+ inheritAttrs: false,
323
+ },
324
+ )
325
+
326
+ export default Notification
@@ -0,0 +1,66 @@
1
+ import type { CSSProperties } from 'vue'
2
+ import { clsx } from '@v-c/util'
3
+ import { defineComponent, ref } from 'vue'
4
+
5
+ export interface ContentProps {
6
+ listPrefixCls: string
7
+ height: number
8
+ topNoticeHeight?: number
9
+ topNoticeWidth?: number
10
+ className?: string
11
+ style?: CSSProperties
12
+ }
13
+
14
+ interface ContentStyle extends CSSProperties {
15
+ '--top-notificiation-height': string
16
+ '--top-notificiation-width': string
17
+ }
18
+
19
+ const Content = defineComponent<ContentProps>(
20
+ (props, { slots, expose }) => {
21
+ const contentRef = ref<HTMLDivElement | null>(null)
22
+ let prevHeight = props.height
23
+
24
+ expose({
25
+ nativeElement: contentRef,
26
+ })
27
+
28
+ return () => {
29
+ const {
30
+ listPrefixCls,
31
+ height,
32
+ topNoticeHeight = 0,
33
+ topNoticeWidth = 0,
34
+ className,
35
+ style,
36
+ } = props
37
+
38
+ const heightStatus = height < prevHeight ? 'decrease' : 'increase'
39
+ prevHeight = height
40
+
41
+ const contentPrefixCls = `${listPrefixCls}-content`
42
+ const contentStyle: ContentStyle = {
43
+ ...style,
44
+ height,
45
+ '--top-notificiation-height': `${topNoticeHeight}px`,
46
+ '--top-notificiation-width': `${topNoticeWidth}px`,
47
+ }
48
+
49
+ return (
50
+ <div
51
+ ref={contentRef}
52
+ class={clsx(contentPrefixCls, `${contentPrefixCls}-${heightStatus}`, className)}
53
+ style={contentStyle}
54
+ >
55
+ {slots.default?.()}
56
+ </div>
57
+ )
58
+ }
59
+ },
60
+ {
61
+ name: 'NotificationListContent',
62
+ inheritAttrs: false,
63
+ },
64
+ )
65
+
66
+ export default Content
@@ -0,0 +1,282 @@
1
+ import type { CSSProperties, TransitionGroupProps } from 'vue'
2
+ import type { Key, StackConfig } from '../interface'
3
+ import type {
4
+ ComponentsType,
5
+ NotificationClassNames as NoticeClassNames,
6
+ NotificationProps,
7
+ NotificationStyles as NoticeStyles,
8
+ } from '../Notification'
9
+ import { clsx } from '@v-c/util'
10
+ import { getTransitionGroupProps } from '@v-c/util/dist/utils/transition'
11
+ import { unrefElement } from '@v-c/util/dist/vueuse/unref-element'
12
+ import { computed, defineComponent, ref, shallowRef, toRef, TransitionGroup, watch, watchEffect } from 'vue'
13
+ import useListPosition from '../hooks/useListPosition'
14
+ import useStack from '../hooks/useStack'
15
+ import Notification from '../Notification'
16
+ import { useNotificationContext } from '../NotificationProvider'
17
+ import Content from './Content'
18
+
19
+ export type Placement = 'top' | 'topLeft' | 'topRight' | 'bottom' | 'bottomLeft' | 'bottomRight'
20
+
21
+ export type { StackConfig }
22
+
23
+ export interface NotificationListConfig extends Omit<NotificationProps, 'prefixCls'> {
24
+ key: Key
25
+ placement?: Placement
26
+ times?: number
27
+ }
28
+
29
+ export interface NotificationClassNames extends NoticeClassNames {
30
+ list?: string
31
+ listContent?: string
32
+ }
33
+
34
+ export interface NotificationStyles extends NoticeStyles {
35
+ list?: CSSProperties
36
+ listContent?: CSSProperties
37
+ }
38
+
39
+ export interface NotificationListProps {
40
+ configList?: NotificationListConfig[]
41
+ prefixCls?: string
42
+ placement: Placement
43
+ pauseOnHover?: boolean
44
+ classNames?: NotificationClassNames
45
+ styles?: NotificationStyles
46
+ components?: ComponentsType
47
+ stack?: StackConfig
48
+ motion?: TransitionGroupProps | ((placement: Placement) => TransitionGroupProps)
49
+ className?: string
50
+ style?: CSSProperties
51
+ onNoticeClose?: (key: Key) => void
52
+ onAllRemoved?: (placement: Placement) => void
53
+ }
54
+
55
+ const noticeSlotKeys: (keyof NoticeClassNames)[] = [
56
+ 'wrapper',
57
+ 'root',
58
+ 'icon',
59
+ 'section',
60
+ 'title',
61
+ 'description',
62
+ 'actions',
63
+ 'close',
64
+ 'progress',
65
+ ]
66
+
67
+ function fillClassNames(
68
+ list: (NotificationClassNames | undefined)[],
69
+ ): NotificationClassNames {
70
+ return noticeSlotKeys.reduce<NotificationClassNames>((merged, key) => {
71
+ merged[key] = clsx(...list.map(item => item?.[key]))
72
+ return merged
73
+ }, {})
74
+ }
75
+
76
+ function fillStyles(
77
+ list: (NotificationStyles | undefined)[],
78
+ ): NotificationStyles {
79
+ return noticeSlotKeys.reduce<NotificationStyles>((merged, key) => {
80
+ merged[key] = Object.assign({}, ...list.map(item => item?.[key]))
81
+ return merged
82
+ }, {})
83
+ }
84
+
85
+ function getIndex(keys: { key: Key }[], key: Key): number | undefined {
86
+ const strKey = String(key)
87
+ const index = keys.findIndex(item => String(item.key) === strKey)
88
+ if (index === -1) {
89
+ return undefined
90
+ }
91
+ return keys.length - index - 1
92
+ }
93
+
94
+ const NotificationList = defineComponent<NotificationListProps>(
95
+ (props, { attrs }) => {
96
+ const ctx = useNotificationContext()
97
+
98
+ const configList = computed(() => props.configList ?? [])
99
+ const keys = computed(() =>
100
+ configList.value.map(config => ({ ...config, key: String(config.key) as Key })),
101
+ )
102
+
103
+ // ====================== Stack State =======================
104
+ const stackConfig = toRef(props, 'stack')
105
+ const [stackEnabled, stackParams] = useStack(stackConfig)
106
+ const listHovering = shallowRef(false)
107
+ const expanded = computed(() =>
108
+ stackEnabled.value && (listHovering.value || keys.value.length <= (stackParams.threshold?.value ?? 0)),
109
+ )
110
+
111
+ const stackPosition = computed(() => {
112
+ if (!stackEnabled.value || expanded.value) {
113
+ return undefined
114
+ }
115
+ return {
116
+ offset: stackParams.offset?.value,
117
+ threshold: stackParams.threshold?.value,
118
+ }
119
+ })
120
+
121
+ // ====================== List Measure ======================
122
+ const gap = ref(0)
123
+ const contentRef = ref<{ nativeElement: { value: HTMLDivElement | null } } | null>(null)
124
+ const [position, setNodeSize] = useListPosition(keys as any, stackPosition as any, gap)
125
+
126
+ const hasConfigList = computed(() => !!configList.value.length)
127
+ watchEffect(() => {
128
+ if (!hasConfigList.value) {
129
+ return
130
+ }
131
+ const listNode = unrefElement<HTMLDivElement>(contentRef.value?.nativeElement as any)
132
+ if (!listNode) {
133
+ return
134
+ }
135
+ const { gap: cssGap, rowGap } = window.getComputedStyle(listNode)
136
+ const nextGap = Number.parseFloat(rowGap || cssGap) || 0
137
+ if (gap.value !== nextGap) {
138
+ gap.value = nextGap
139
+ }
140
+ }, { flush: 'post' })
141
+
142
+ // Notify when list becomes empty (after motion finished).
143
+ const checkAllClosed = () => {
144
+ if (configList.value.length === 0) {
145
+ props.onAllRemoved?.(props.placement)
146
+ }
147
+ }
148
+
149
+ // Compute motion props per placement.
150
+ const placementMotion = computed(() => {
151
+ if (typeof props.motion === 'function') {
152
+ return props.placement ? props.motion(props.placement) : undefined
153
+ }
154
+ return props.motion
155
+ })
156
+
157
+ // Cleanup node sizes when items leave permanently.
158
+ watch(keys, (next, prev) => {
159
+ if (!prev) {
160
+ return
161
+ }
162
+ const nextKeySet = new Set(next.map(item => String(item.key)))
163
+ prev.forEach((item) => {
164
+ const key = String(item.key)
165
+ if (!nextKeySet.has(key)) {
166
+ setNodeSize(key, null)
167
+ }
168
+ })
169
+ })
170
+
171
+ return () => {
172
+ const {
173
+ prefixCls = 'vc-notification',
174
+ pauseOnHover,
175
+ classNames: ncs,
176
+ styles: nss,
177
+ components,
178
+ placement,
179
+ className,
180
+ style,
181
+ onNoticeClose,
182
+ } = props
183
+
184
+ const listPrefixCls = `${prefixCls}-list`
185
+ const positionResult = position.value
186
+
187
+ let motionGroupProps: TransitionGroupProps = {}
188
+ if (placementMotion.value) {
189
+ motionGroupProps = getTransitionGroupProps(placementMotion.value.name!, placementMotion.value)
190
+ }
191
+
192
+ const renderItems = () =>
193
+ keys.value.map((config) => {
194
+ const { key, placement: _itemPlacement, classNames: configClassNames, styles: configStyles, className: configClassName, style: configStyle, ...notificationConfig } = config
195
+ const strKey = String(key)
196
+ const notificationIndex = getIndex(keys.value, key)
197
+ const stackInThreshold
198
+ = stackEnabled.value && notificationIndex !== undefined && notificationIndex < (stackParams.threshold?.value ?? 0)
199
+
200
+ return (
201
+ <Notification
202
+ key={strKey}
203
+ {...notificationConfig}
204
+ ref={(el: any) => {
205
+ const node = unrefElement<HTMLDivElement>(el?.nativeElement as any)
206
+ setNodeSize(strKey, node ?? null)
207
+ }}
208
+ prefixCls={prefixCls}
209
+ class={clsx((ctx.value as any)?.classNames?.notice, configClassName)}
210
+ style={configStyle}
211
+ classNames={fillClassNames([ncs, configClassNames])}
212
+ styles={fillStyles([nss, configStyles])}
213
+ components={{
214
+ ...components,
215
+ ...(config as NotificationListConfig).components,
216
+ }}
217
+ hovering={stackEnabled.value && listHovering.value}
218
+ pauseOnHover={config.pauseOnHover ?? pauseOnHover}
219
+ offset={positionResult.notificationPosition.get(strKey)}
220
+ notificationIndex={notificationIndex}
221
+ stackInThreshold={stackInThreshold}
222
+ onClose={() => {
223
+ (config as NotificationListConfig).onClose?.()
224
+ onNoticeClose?.(key)
225
+ }}
226
+ />
227
+ )
228
+ })
229
+
230
+ return (
231
+ <div
232
+ class={clsx(
233
+ prefixCls,
234
+ listPrefixCls,
235
+ `${prefixCls}-${placement}`,
236
+ (ctx.value as any)?.classNames?.list,
237
+ className,
238
+ ncs?.list,
239
+ (attrs as any).class,
240
+ {
241
+ [`${prefixCls}-stack`]: stackEnabled.value,
242
+ [`${prefixCls}-stack-expanded`]: expanded.value,
243
+ [`${listPrefixCls}-hovered`]: listHovering.value,
244
+ },
245
+ )}
246
+ onMouseenter={() => {
247
+ listHovering.value = true
248
+ }}
249
+ onMouseleave={() => {
250
+ listHovering.value = false
251
+ }}
252
+ style={{ ...nss?.list, ...style, ...((attrs as any).style ?? {}) } as CSSProperties}
253
+ >
254
+ <Content
255
+ ref={contentRef as any}
256
+ listPrefixCls={listPrefixCls}
257
+ height={positionResult.totalHeight}
258
+ topNoticeHeight={positionResult.topNoticeHeight}
259
+ topNoticeWidth={positionResult.topNoticeWidth}
260
+ className={ncs?.listContent}
261
+ style={nss?.listContent}
262
+ >
263
+ <TransitionGroup
264
+ tag={false as any}
265
+ appear
266
+ {...motionGroupProps}
267
+ onAfterLeave={checkAllClosed}
268
+ >
269
+ {renderItems()}
270
+ </TransitionGroup>
271
+ </Content>
272
+ </div>
273
+ )
274
+ }
275
+ },
276
+ {
277
+ name: 'NotificationList',
278
+ inheritAttrs: false,
279
+ },
280
+ )
281
+
282
+ export default NotificationList