@v-c/notification 2.0.0-beta.1 → 2.0.0-rc.2
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.
- package/dist/Notification.d.ts +7 -234
- package/dist/Notification.js +199 -135
- package/dist/NotificationList/Content.d.ts +3 -80
- package/dist/NotificationList/Content.js +33 -47
- package/dist/NotificationList/index.d.ts +7 -128
- package/dist/NotificationList/index.js +139 -122
- package/dist/NotificationProvider.d.ts +1 -20
- package/dist/NotificationProvider.js +2 -13
- package/dist/Notifications.d.ts +10 -132
- package/dist/Notifications.js +123 -108
- package/dist/Progress.d.ts +3 -3
- package/dist/Progress.js +24 -11
- package/dist/hooks/useClosable.d.ts +6 -11
- package/dist/hooks/useClosable.js +7 -6
- package/dist/hooks/useListPosition/index.d.ts +14 -13
- package/dist/hooks/useListPosition/index.js +16 -23
- package/dist/hooks/useListPosition/useSizes.d.ts +3 -6
- package/dist/hooks/useListPosition/useSizes.js +12 -10
- package/dist/hooks/useNoticeTimer.d.ts +5 -4
- package/dist/hooks/useNoticeTimer.js +33 -41
- package/dist/hooks/useNotification.d.ts +25 -7
- package/dist/hooks/useNotification.js +20 -25
- package/dist/hooks/useStack.d.ts +9 -8
- package/dist/hooks/useStack.js +17 -11
- package/dist/index.d.ts +9 -8
- package/dist/index.js +2 -2
- package/dist/interface.d.ts +30 -0
- package/dist/interface.js +0 -0
- package/docs/context.vue +1 -1
- package/docs/hooks.vue +4 -4
- package/docs/index.less +143 -62
- package/docs/maxCount.vue +1 -1
- package/docs/showProgress.vue +2 -2
- package/docs/stack.vue +1 -1
- package/package.json +2 -3
- package/src/Notification.tsx +128 -165
- package/src/NotificationList/Content.tsx +36 -54
- package/src/NotificationList/index.tsx +131 -135
- package/src/NotificationProvider.tsx +3 -23
- package/src/Notifications.tsx +62 -84
- package/src/Progress.tsx +19 -15
- package/src/hooks/useClosable.ts +15 -16
- package/src/hooks/useListPosition/index.ts +24 -40
- package/src/hooks/useListPosition/useSizes.ts +16 -15
- package/src/hooks/useNoticeTimer.ts +34 -45
- package/src/hooks/useNotification.tsx +71 -43
- package/src/hooks/useStack.ts +20 -24
- package/src/index.ts +28 -13
- package/src/interface.ts +45 -0
- package/vitest.config.ts +1 -3
- package/tests/index.spec.tsx +0 -200
package/src/index.ts
CHANGED
|
@@ -1,35 +1,50 @@
|
|
|
1
|
-
import type { NotificationAPI, NotificationConfig } from './hooks/useNotification'
|
|
2
|
-
import type { ComponentsType, NotificationProps } from './Notification'
|
|
3
|
-
import type { NotificationProgressProps } from './Progress'
|
|
4
1
|
import useNotification from './hooks/useNotification'
|
|
5
2
|
import Notification from './Notification'
|
|
6
3
|
import NotificationList from './NotificationList'
|
|
7
|
-
import
|
|
4
|
+
import { useNotificationContext, useNotificationProvider } from './NotificationProvider'
|
|
8
5
|
import Progress from './Progress'
|
|
9
6
|
|
|
7
|
+
import type { NotificationAPI, NotificationConfig } from './hooks/useNotification'
|
|
8
|
+
import type {
|
|
9
|
+
ComponentsType,
|
|
10
|
+
NotificationClassNames as NoticeClassNames,
|
|
11
|
+
NotificationProps,
|
|
12
|
+
NotificationStyles as NoticeStyles,
|
|
13
|
+
} from './Notification'
|
|
14
|
+
import type {
|
|
15
|
+
NotificationClassNames,
|
|
16
|
+
NotificationListProps,
|
|
17
|
+
NotificationStyles,
|
|
18
|
+
Placement,
|
|
19
|
+
} from './NotificationList'
|
|
20
|
+
import type { NotificationProgressProps } from './Progress'
|
|
21
|
+
import type { Key, NotificationListConfig, StackConfig } from './interface'
|
|
22
|
+
import type { ClosableType, ParsedClosableConfig } from './hooks/useClosable'
|
|
23
|
+
|
|
10
24
|
export {
|
|
11
25
|
Notification,
|
|
12
26
|
NotificationList,
|
|
13
|
-
NotificationProvider,
|
|
14
27
|
Progress,
|
|
15
28
|
useNotification,
|
|
29
|
+
useNotificationContext,
|
|
16
30
|
useNotificationProvider,
|
|
17
31
|
}
|
|
18
32
|
|
|
19
33
|
export type {
|
|
34
|
+
ClosableType,
|
|
20
35
|
ComponentsType,
|
|
36
|
+
Key,
|
|
37
|
+
NoticeClassNames,
|
|
38
|
+
NoticeStyles,
|
|
21
39
|
NotificationAPI,
|
|
22
|
-
NotificationConfig,
|
|
23
|
-
NotificationProgressProps,
|
|
24
|
-
NotificationProps,
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export type {
|
|
28
40
|
NotificationClassNames,
|
|
41
|
+
NotificationConfig,
|
|
29
42
|
NotificationListConfig,
|
|
30
43
|
NotificationListProps,
|
|
44
|
+
NotificationProgressProps,
|
|
45
|
+
NotificationProps,
|
|
31
46
|
NotificationStyles,
|
|
47
|
+
ParsedClosableConfig,
|
|
32
48
|
Placement,
|
|
33
49
|
StackConfig,
|
|
34
|
-
|
|
35
|
-
} from './NotificationList'
|
|
50
|
+
}
|
package/src/interface.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { ClosableType } from './hooks/useClosable'
|
|
2
|
+
import type {
|
|
3
|
+
ComponentsType,
|
|
4
|
+
NotificationProps,
|
|
5
|
+
} from './Notification'
|
|
6
|
+
|
|
7
|
+
export type Placement = 'top' | 'topLeft' | 'topRight' | 'bottom' | 'bottomLeft' | 'bottomRight'
|
|
8
|
+
|
|
9
|
+
export type Key = string | number
|
|
10
|
+
|
|
11
|
+
export type StackConfig
|
|
12
|
+
= | boolean
|
|
13
|
+
| {
|
|
14
|
+
/**
|
|
15
|
+
* When the notice count exceeds this threshold, notices will be stacked.
|
|
16
|
+
* @default 3
|
|
17
|
+
*/
|
|
18
|
+
threshold?: number
|
|
19
|
+
/**
|
|
20
|
+
* Vertical offset applied between stacked notices.
|
|
21
|
+
* @default 8
|
|
22
|
+
*/
|
|
23
|
+
offset?: number
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Configuration accepted by the public `api.open` call.
|
|
28
|
+
* Mirrors rc-notification@2.0 NotificationListConfig.
|
|
29
|
+
*/
|
|
30
|
+
export interface NotificationListConfig extends Omit<NotificationProps, 'prefixCls'> {
|
|
31
|
+
key: Key
|
|
32
|
+
placement?: Placement
|
|
33
|
+
times?: number
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export type Placements = Partial<Record<Placement, NotificationListConfig[]>>
|
|
37
|
+
|
|
38
|
+
export type InnerOpenConfig = NotificationListConfig & { times?: number }
|
|
39
|
+
|
|
40
|
+
// Re-export common surfaces consumers used to import from interface.ts directly.
|
|
41
|
+
export type {
|
|
42
|
+
ClosableType,
|
|
43
|
+
ComponentsType,
|
|
44
|
+
NotificationProps,
|
|
45
|
+
}
|
package/vitest.config.ts
CHANGED
package/tests/index.spec.tsx
DELETED
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
import type { NotificationAPI, NotificationConfig } from '../src'
|
|
2
|
-
import { mount } from '@vue/test-utils'
|
|
3
|
-
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
|
4
|
-
import { defineComponent, h, nextTick } from 'vue'
|
|
5
|
-
import { useNotification } from '../src'
|
|
6
|
-
|
|
7
|
-
async function flush() {
|
|
8
|
-
await nextTick()
|
|
9
|
-
vi.runAllTimers()
|
|
10
|
-
await nextTick()
|
|
11
|
-
await nextTick()
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
function renderDemo(config?: NotificationConfig) {
|
|
15
|
-
let api!: NotificationAPI
|
|
16
|
-
|
|
17
|
-
const Demo = defineComponent({
|
|
18
|
-
setup() {
|
|
19
|
-
const [_api, holder] = useNotification(config)
|
|
20
|
-
api = _api
|
|
21
|
-
return () => holder()
|
|
22
|
-
},
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
const wrapper = mount(Demo, {
|
|
26
|
-
global: {
|
|
27
|
-
stubs: {
|
|
28
|
-
'transition': false,
|
|
29
|
-
'transition-group': false,
|
|
30
|
-
},
|
|
31
|
-
},
|
|
32
|
-
})
|
|
33
|
-
return { wrapper, get api() {
|
|
34
|
-
return api
|
|
35
|
-
} }
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
describe('@v-c/notification', () => {
|
|
39
|
-
beforeEach(() => {
|
|
40
|
-
vi.useFakeTimers()
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
afterEach(() => {
|
|
44
|
-
document.body.innerHTML = ''
|
|
45
|
-
vi.useRealTimers()
|
|
46
|
-
vi.restoreAllMocks()
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
it('opens notice with description', async () => {
|
|
50
|
-
const { api } = renderDemo()
|
|
51
|
-
api.open({ description: h('p', { class: 'test' }, '1'), duration: 0.1 })
|
|
52
|
-
await flush()
|
|
53
|
-
expect(document.querySelector('.test')).toBeTruthy()
|
|
54
|
-
|
|
55
|
-
// Run all timers to flush duration
|
|
56
|
-
await flush()
|
|
57
|
-
expect(document.querySelector('.test')).toBeFalsy()
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
it('renders semantic slots when provided', async () => {
|
|
61
|
-
const { api } = renderDemo()
|
|
62
|
-
api.open({
|
|
63
|
-
title: 'bamboo',
|
|
64
|
-
description: 'little',
|
|
65
|
-
icon: h('span'),
|
|
66
|
-
actions: h('button', { type: 'button' }, 'light'),
|
|
67
|
-
closable: true,
|
|
68
|
-
showProgress: true,
|
|
69
|
-
duration: 3,
|
|
70
|
-
})
|
|
71
|
-
await flush()
|
|
72
|
-
|
|
73
|
-
expect(document.querySelector('.vc-notification-notice-title')).toBeTruthy()
|
|
74
|
-
expect(document.querySelector('.vc-notification-notice-description')).toBeTruthy()
|
|
75
|
-
expect(document.querySelector('.vc-notification-notice-icon')).toBeTruthy()
|
|
76
|
-
expect(document.querySelector('.vc-notification-notice-actions')).toBeTruthy()
|
|
77
|
-
expect(document.querySelector('.vc-notification-notice-close')).toBeTruthy()
|
|
78
|
-
expect(document.querySelector('.vc-notification-notice-progress')).toBeTruthy()
|
|
79
|
-
expect(document.querySelector('.vc-notification-notice-section')).toBeTruthy()
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
it('does not wrap in section when only one of title/description provided', async () => {
|
|
83
|
-
const { api } = renderDemo()
|
|
84
|
-
api.open({ description: 'only-description' })
|
|
85
|
-
await flush()
|
|
86
|
-
expect(document.querySelector('.vc-notification-notice-section')).toBeFalsy()
|
|
87
|
-
expect(document.querySelector('.vc-notification-notice-description')).toBeTruthy()
|
|
88
|
-
})
|
|
89
|
-
|
|
90
|
-
it('forwards classNames and styles for list and listContent', async () => {
|
|
91
|
-
const { api } = renderDemo({
|
|
92
|
-
classNames: {
|
|
93
|
-
list: 'root-list',
|
|
94
|
-
listContent: 'inner-content',
|
|
95
|
-
},
|
|
96
|
-
styles: {
|
|
97
|
-
list: { color: 'red' },
|
|
98
|
-
listContent: { color: 'blue' },
|
|
99
|
-
},
|
|
100
|
-
})
|
|
101
|
-
api.open({ description: 'x' })
|
|
102
|
-
await flush()
|
|
103
|
-
expect(document.querySelector('.vc-notification-list')?.classList.contains('root-list')).toBe(true)
|
|
104
|
-
expect(document.querySelector('.vc-notification-list-content')?.classList.contains('inner-content')).toBe(true)
|
|
105
|
-
})
|
|
106
|
-
|
|
107
|
-
it('respects maxCount', async () => {
|
|
108
|
-
const { api } = renderDemo({ maxCount: 1 })
|
|
109
|
-
api.open({ description: h('span', { class: 'a' }, 'a'), duration: 0 })
|
|
110
|
-
api.open({ description: h('span', { class: 'b' }, 'b'), duration: 0 })
|
|
111
|
-
api.open({ description: h('span', { class: 'c' }, 'c'), duration: 0 })
|
|
112
|
-
await flush()
|
|
113
|
-
expect(document.querySelectorAll('.a, .b, .c')).toHaveLength(1)
|
|
114
|
-
expect(document.querySelector('.c')).toBeTruthy()
|
|
115
|
-
})
|
|
116
|
-
|
|
117
|
-
it('triggers onClose only when close button is clicked', async () => {
|
|
118
|
-
const { api } = renderDemo()
|
|
119
|
-
let clicks = 0
|
|
120
|
-
let closes = 0
|
|
121
|
-
api.open({
|
|
122
|
-
description: h('p', 'x'),
|
|
123
|
-
closable: true,
|
|
124
|
-
duration: 0,
|
|
125
|
-
onClick: () => {
|
|
126
|
-
clicks += 1
|
|
127
|
-
},
|
|
128
|
-
onClose: () => {
|
|
129
|
-
closes += 1
|
|
130
|
-
},
|
|
131
|
-
})
|
|
132
|
-
await nextTick()
|
|
133
|
-
await nextTick()
|
|
134
|
-
const closeBtn = document.querySelector('.vc-notification-notice-close') as HTMLButtonElement
|
|
135
|
-
closeBtn.click()
|
|
136
|
-
expect(clicks).toBe(0)
|
|
137
|
-
expect(closes).toBe(1)
|
|
138
|
-
})
|
|
139
|
-
|
|
140
|
-
it('destroy removes everything', async () => {
|
|
141
|
-
const { api } = renderDemo()
|
|
142
|
-
api.open({ description: h('p', { class: 'test' }, 'x'), duration: 0 })
|
|
143
|
-
await flush()
|
|
144
|
-
expect(document.querySelector('.test')).toBeTruthy()
|
|
145
|
-
api.destroy()
|
|
146
|
-
await flush()
|
|
147
|
-
expect(document.querySelector('.test')).toBeFalsy()
|
|
148
|
-
})
|
|
149
|
-
|
|
150
|
-
it('placement adds className', async () => {
|
|
151
|
-
const { api } = renderDemo()
|
|
152
|
-
api.open({ description: 'x', placement: 'bottomLeft' })
|
|
153
|
-
await flush()
|
|
154
|
-
expect(document.querySelector('.vc-notification')?.classList.contains('vc-notification-bottomLeft')).toBe(true)
|
|
155
|
-
})
|
|
156
|
-
|
|
157
|
-
it('motion as function receives placement', async () => {
|
|
158
|
-
const motionFn = vi.fn().mockReturnValue({})
|
|
159
|
-
const { api } = renderDemo({ motion: motionFn })
|
|
160
|
-
api.open({ description: 'x', placement: 'bottomLeft' })
|
|
161
|
-
await flush()
|
|
162
|
-
expect(motionFn).toHaveBeenCalledWith('bottomLeft')
|
|
163
|
-
})
|
|
164
|
-
|
|
165
|
-
it('open with custom close icon', async () => {
|
|
166
|
-
const { api } = renderDemo()
|
|
167
|
-
api.open({
|
|
168
|
-
description: 'x',
|
|
169
|
-
closable: { closeIcon: h('span', { class: 'test-icon' }, 'X') },
|
|
170
|
-
duration: 0,
|
|
171
|
-
})
|
|
172
|
-
await flush()
|
|
173
|
-
expect(document.querySelector('.test-icon')?.textContent).toBe('X')
|
|
174
|
-
})
|
|
175
|
-
|
|
176
|
-
it('forwards data and aria attrs via props', async () => {
|
|
177
|
-
const { api } = renderDemo()
|
|
178
|
-
api.open({
|
|
179
|
-
description: 'x',
|
|
180
|
-
class: 'notice-class',
|
|
181
|
-
props: {
|
|
182
|
-
'data-test': 'data-test-value',
|
|
183
|
-
'aria-describedby': 'desc-id',
|
|
184
|
-
'role': 'status',
|
|
185
|
-
},
|
|
186
|
-
})
|
|
187
|
-
await flush()
|
|
188
|
-
const notice = document.querySelector('.notice-class')
|
|
189
|
-
expect(notice?.getAttribute('data-test')).toBe('data-test-value')
|
|
190
|
-
expect(notice?.getAttribute('aria-describedby')).toBe('desc-id')
|
|
191
|
-
expect(notice?.getAttribute('role')).toBe('status')
|
|
192
|
-
})
|
|
193
|
-
|
|
194
|
-
it('default role is alert', async () => {
|
|
195
|
-
const { api } = renderDemo()
|
|
196
|
-
api.open({ description: 'x' })
|
|
197
|
-
await flush()
|
|
198
|
-
expect(document.querySelector('.vc-notification-notice')?.getAttribute('role')).toBe('alert')
|
|
199
|
-
})
|
|
200
|
-
})
|