@v-c/notification 0.0.3 → 2.0.0-beta.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.
- package/dist/Notification.d.ts +286 -0
- package/dist/Notification.js +237 -0
- package/dist/NotificationList/Content.d.ts +88 -0
- package/dist/NotificationList/Content.js +74 -0
- package/dist/NotificationList/index.d.ts +156 -0
- package/dist/NotificationList/index.js +204 -0
- package/dist/NotificationProvider.d.ts +20 -1
- package/dist/NotificationProvider.js +16 -3
- package/dist/Notifications.d.ts +136 -8
- package/dist/Notifications.js +118 -109
- package/dist/Progress.d.ts +8 -0
- package/dist/Progress.js +18 -0
- package/dist/hooks/useClosable.d.ts +22 -0
- package/dist/hooks/useClosable.js +33 -0
- package/dist/hooks/useListPosition/index.d.ts +17 -0
- package/dist/hooks/useListPosition/index.js +48 -0
- package/dist/hooks/useListPosition/useSizes.d.ts +13 -0
- package/dist/hooks/useListPosition/useSizes.js +29 -0
- package/dist/hooks/useNoticeTimer.d.ts +6 -0
- package/dist/hooks/useNoticeTimer.js +71 -0
- package/dist/hooks/useNotification.d.ts +8 -24
- package/dist/hooks/useNotification.js +33 -22
- package/dist/hooks/useStack.d.ts +8 -4
- package/dist/hooks/useStack.js +15 -18
- package/dist/index.d.ts +7 -5
- package/dist/index.js +5 -3
- package/docs/context.vue +1 -1
- package/docs/hooks.vue +4 -4
- package/docs/index.less +62 -143
- package/docs/maxCount.vue +1 -1
- package/docs/showProgress.vue +2 -2
- package/docs/stack.vue +1 -1
- package/package.json +5 -4
- package/src/Notification.tsx +363 -0
- package/src/NotificationList/Content.tsx +84 -0
- package/src/NotificationList/index.tsx +298 -0
- package/src/NotificationProvider.tsx +23 -3
- package/src/Notifications.tsx +103 -87
- package/src/Progress.tsx +23 -0
- package/src/hooks/useClosable.ts +54 -0
- package/src/hooks/useListPosition/index.ts +85 -0
- package/src/hooks/useListPosition/useSizes.ts +42 -0
- package/src/hooks/useNoticeTimer.ts +96 -0
- package/src/hooks/useNotification.tsx +54 -80
- package/src/hooks/useStack.ts +26 -18
- package/src/index.ts +31 -5
- package/tests/index.spec.tsx +200 -0
- package/vite.config.ts +4 -3
- package/vitest.config.ts +3 -1
- package/dist/Notice.cjs +0 -235
- package/dist/Notice.d.ts +0 -15
- package/dist/Notice.js +0 -227
- package/dist/NoticeList.cjs +0 -170
- package/dist/NoticeList.d.ts +0 -13
- package/dist/NoticeList.js +0 -164
- package/dist/NotificationProvider.cjs +0 -14
- package/dist/Notifications.cjs +0 -146
- package/dist/_virtual/rolldown_runtime.cjs +0 -21
- package/dist/hooks/useNotification.cjs +0 -93
- package/dist/hooks/useStack.cjs +0 -27
- package/dist/index.cjs +0 -7
- package/dist/interface.cjs +0 -1
- package/dist/interface.d.ts +0 -55
- package/dist/interface.js +0 -0
- package/src/Notice.tsx +0 -212
- package/src/NoticeList.tsx +0 -219
- package/src/interface.ts +0 -61
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import type { ComputedRef, MaybeRef } from 'vue'
|
|
2
|
+
import type { StackConfig } from '../useStack'
|
|
3
|
+
import { computed, unref } from 'vue'
|
|
4
|
+
import useSizes from './useSizes'
|
|
5
|
+
|
|
6
|
+
type Key = string | number | symbol
|
|
7
|
+
|
|
8
|
+
export interface ConfigItem {
|
|
9
|
+
key: Key
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Calculates each notification's position and the full list height.
|
|
14
|
+
*/
|
|
15
|
+
export default function useListPosition(
|
|
16
|
+
configList: MaybeRef<readonly ConfigItem[]>,
|
|
17
|
+
stack: MaybeRef<StackConfig | undefined>,
|
|
18
|
+
gap: MaybeRef<number> = 0,
|
|
19
|
+
): [
|
|
20
|
+
ComputedRef<Map<string, number>>,
|
|
21
|
+
(key: string, node: HTMLElement | null) => void,
|
|
22
|
+
ComputedRef<number>,
|
|
23
|
+
ComputedRef<number | undefined>,
|
|
24
|
+
ComputedRef<number | undefined>,
|
|
25
|
+
] {
|
|
26
|
+
const [sizeMap, setNodeSize] = useSizes()
|
|
27
|
+
|
|
28
|
+
const result = computed(() => {
|
|
29
|
+
const list = unref(configList)
|
|
30
|
+
const stackValue = unref(stack)
|
|
31
|
+
const gapValue = unref(gap) ?? 0
|
|
32
|
+
|
|
33
|
+
let offsetY = 0
|
|
34
|
+
let nextTotalHeight = 0
|
|
35
|
+
const stackThreshold = stackValue?.threshold ?? 0
|
|
36
|
+
const positions = new Map<string, number>()
|
|
37
|
+
let topNoticeHeight: number | undefined
|
|
38
|
+
let topNoticeWidth: number | undefined
|
|
39
|
+
|
|
40
|
+
list
|
|
41
|
+
.slice()
|
|
42
|
+
.reverse()
|
|
43
|
+
.forEach((config, index) => {
|
|
44
|
+
const key = String(config.key)
|
|
45
|
+
const height = sizeMap.value[key]?.height ?? 0
|
|
46
|
+
const y
|
|
47
|
+
= stackValue && index > 0
|
|
48
|
+
? offsetY + (stackValue.offset ?? 0) - height
|
|
49
|
+
: offsetY
|
|
50
|
+
|
|
51
|
+
positions.set(key, y)
|
|
52
|
+
|
|
53
|
+
if (index === 0) {
|
|
54
|
+
topNoticeHeight = height
|
|
55
|
+
topNoticeWidth = sizeMap.value[key]?.width ?? 0
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (!stackValue || index < stackThreshold) {
|
|
59
|
+
nextTotalHeight = Math.max(nextTotalHeight, y + height)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (stackValue) {
|
|
63
|
+
offsetY = y + height
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
offsetY += height + gapValue
|
|
67
|
+
}
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
return {
|
|
71
|
+
positions,
|
|
72
|
+
totalHeight: nextTotalHeight,
|
|
73
|
+
topNoticeHeight,
|
|
74
|
+
topNoticeWidth,
|
|
75
|
+
}
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
return [
|
|
79
|
+
computed(() => result.value.positions),
|
|
80
|
+
setNodeSize,
|
|
81
|
+
computed(() => result.value.totalHeight),
|
|
82
|
+
computed(() => result.value.topNoticeHeight),
|
|
83
|
+
computed(() => result.value.topNoticeWidth),
|
|
84
|
+
]
|
|
85
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { Ref } from 'vue'
|
|
2
|
+
import { ref } from 'vue'
|
|
3
|
+
|
|
4
|
+
export interface NodeSize {
|
|
5
|
+
width: number
|
|
6
|
+
height: number
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export type NodeSizeMap = Record<string, NodeSize>
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Track measured node sizes by key. Returns the size map ref and a setter callback.
|
|
13
|
+
*/
|
|
14
|
+
export default function useSizes(): [
|
|
15
|
+
Ref<NodeSizeMap>,
|
|
16
|
+
(key: string, node: HTMLElement | null) => void,
|
|
17
|
+
] {
|
|
18
|
+
const sizeMap = ref<NodeSizeMap>({})
|
|
19
|
+
|
|
20
|
+
function setNodeSize(key: string, node: HTMLElement | null) {
|
|
21
|
+
if (!node) {
|
|
22
|
+
if (!(key in sizeMap.value)) {
|
|
23
|
+
return
|
|
24
|
+
}
|
|
25
|
+
const { [key]: _, ...rest } = sizeMap.value
|
|
26
|
+
sizeMap.value = rest
|
|
27
|
+
return
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const next: NodeSize = {
|
|
31
|
+
width: node.offsetWidth,
|
|
32
|
+
height: node.offsetHeight,
|
|
33
|
+
}
|
|
34
|
+
const prev = sizeMap.value[key]
|
|
35
|
+
if (prev && prev.width === next.width && prev.height === next.height) {
|
|
36
|
+
return
|
|
37
|
+
}
|
|
38
|
+
sizeMap.value = { ...sizeMap.value, [key]: next }
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return [sizeMap, setNodeSize]
|
|
42
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import type { ComputedRef, MaybeRef } from 'vue'
|
|
2
|
+
import raf from '@v-c/util/dist/raf'
|
|
3
|
+
import { computed, onBeforeUnmount, shallowRef, unref, watch } from 'vue'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Run the auto-close timer for a notice and report progress updates.
|
|
7
|
+
* Returns controls to pause and resume the timer.
|
|
8
|
+
*/
|
|
9
|
+
export default function useNoticeTimer(
|
|
10
|
+
duration: MaybeRef<number | false | null | undefined>,
|
|
11
|
+
onClose: () => void,
|
|
12
|
+
onUpdate: (ptg: number) => void,
|
|
13
|
+
): [() => void, () => void, ComputedRef<number>] {
|
|
14
|
+
const durationMs = computed(() => {
|
|
15
|
+
const value = unref(duration)
|
|
16
|
+
const merged = typeof value === 'number' ? value : 0
|
|
17
|
+
return Math.max(merged, 0) * 1000
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
const walking = shallowRef(durationMs.value > 0)
|
|
21
|
+
const passTime = shallowRef(0)
|
|
22
|
+
let lastRafTime: number | null = null
|
|
23
|
+
let rafId: number | null = null
|
|
24
|
+
|
|
25
|
+
function syncPassTime() {
|
|
26
|
+
const now = Date.now()
|
|
27
|
+
if (lastRafTime !== null) {
|
|
28
|
+
passTime.value += now - lastRafTime
|
|
29
|
+
}
|
|
30
|
+
lastRafTime = now
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function cancelRaf() {
|
|
34
|
+
if (rafId !== null) {
|
|
35
|
+
raf.cancel(rafId)
|
|
36
|
+
rafId = null
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function onPause() {
|
|
41
|
+
syncPassTime()
|
|
42
|
+
walking.value = false
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function onResume() {
|
|
46
|
+
if (durationMs.value > 0) {
|
|
47
|
+
lastRafTime = Date.now()
|
|
48
|
+
walking.value = true
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
onUpdate(0)
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Reset when durationMs changed.
|
|
56
|
+
watch(durationMs, () => {
|
|
57
|
+
passTime.value = 0
|
|
58
|
+
lastRafTime = null
|
|
59
|
+
walking.value = durationMs.value > 0
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
// Drive raf loop while walking.
|
|
63
|
+
watch(walking, (isWalking) => {
|
|
64
|
+
cancelRaf()
|
|
65
|
+
if (!isWalking) {
|
|
66
|
+
return
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function step() {
|
|
70
|
+
syncPassTime()
|
|
71
|
+
|
|
72
|
+
if (passTime.value >= durationMs.value) {
|
|
73
|
+
onUpdate(1)
|
|
74
|
+
onClose()
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
onUpdate(Math.min(passTime.value / durationMs.value, 1))
|
|
78
|
+
rafId = raf(step)
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
step()
|
|
83
|
+
}, { immediate: true })
|
|
84
|
+
|
|
85
|
+
onBeforeUnmount(() => {
|
|
86
|
+
cancelRaf()
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
const percent = computed(() => {
|
|
90
|
+
if (durationMs.value <= 0)
|
|
91
|
+
return 0
|
|
92
|
+
return Math.min(passTime.value / durationMs.value, 1)
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
return [onResume, onPause, percent]
|
|
96
|
+
}
|
|
@@ -1,36 +1,29 @@
|
|
|
1
1
|
import type { VueNode } from '@v-c/util/dist/type'
|
|
2
2
|
import type { CSSProperties, MaybeRef, TransitionGroupProps } from 'vue'
|
|
3
|
-
import type {
|
|
3
|
+
import type { NotificationListConfig, Placement, StackInput } from '../NotificationList'
|
|
4
4
|
import type { NotificationsProps, NotificationsRef } from '../Notifications'
|
|
5
5
|
import { computed, onMounted, shallowRef, unref, watch } from 'vue'
|
|
6
6
|
import Notifications from '../Notifications'
|
|
7
7
|
|
|
8
|
+
type Key = string | number | symbol
|
|
9
|
+
|
|
8
10
|
const defaultGetContainer = () => document.body
|
|
9
11
|
|
|
10
|
-
type OptionalConfig = Partial<
|
|
12
|
+
type OptionalConfig = Partial<NotificationListConfig>
|
|
13
|
+
type SharedConfig = Pick<
|
|
14
|
+
NotificationListConfig,
|
|
15
|
+
'placement' | 'closable' | 'duration' | 'showProgress'
|
|
16
|
+
>
|
|
11
17
|
|
|
12
|
-
export interface NotificationConfig {
|
|
13
|
-
|
|
14
|
-
|
|
18
|
+
export interface NotificationConfig extends Omit<NotificationsProps, 'container'> {
|
|
19
|
+
// UI
|
|
20
|
+
placement?: Placement
|
|
15
21
|
getContainer?: () => HTMLElement | ShadowRoot
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
closable?:
|
|
19
|
-
| boolean
|
|
20
|
-
| ({ closeIcon?: VueNode, onClose?: VoidFunction } & Record<string, any>)
|
|
21
|
-
maxCount?: number
|
|
22
|
+
|
|
23
|
+
// Behavior
|
|
24
|
+
closable?: NotificationListConfig['closable']
|
|
22
25
|
duration?: number | false | null
|
|
23
|
-
showProgress?:
|
|
24
|
-
pauseOnHover?: boolean
|
|
25
|
-
/** @private. Config for notification holder style. Safe to remove if refactor */
|
|
26
|
-
className?: (placement: Placement) => string
|
|
27
|
-
/** @private. Config for notification holder style. Safe to remove if refactor */
|
|
28
|
-
style?: (placement: Placement) => CSSProperties
|
|
29
|
-
/** @private Trigger when all the notification closed. */
|
|
30
|
-
onAllRemoved?: VoidFunction
|
|
31
|
-
stack?: StackConfig
|
|
32
|
-
/** @private Slot for style in Notifications */
|
|
33
|
-
renderNotifications?: NotificationsProps['renderNotifications']
|
|
26
|
+
showProgress?: NotificationListConfig['showProgress']
|
|
34
27
|
}
|
|
35
28
|
|
|
36
29
|
export interface NotificationAPI {
|
|
@@ -41,7 +34,7 @@ export interface NotificationAPI {
|
|
|
41
34
|
|
|
42
35
|
interface OpenTask {
|
|
43
36
|
type: 'open'
|
|
44
|
-
config:
|
|
37
|
+
config: NotificationListConfig
|
|
45
38
|
}
|
|
46
39
|
|
|
47
40
|
interface CloseTask {
|
|
@@ -58,46 +51,34 @@ type Task = OpenTask | CloseTask | DestroyTask
|
|
|
58
51
|
let uniqueKey = 0
|
|
59
52
|
|
|
60
53
|
function mergeConfig<T>(...objList: Partial<T>[]): T {
|
|
61
|
-
const clone
|
|
62
|
-
|
|
63
|
-
objList.forEach((obj: any) => {
|
|
54
|
+
const clone = {} as T
|
|
55
|
+
objList.forEach((obj) => {
|
|
64
56
|
if (obj) {
|
|
65
57
|
Object.keys(obj).forEach((key) => {
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
clone[key] = val
|
|
58
|
+
const value = (obj as any)[key]
|
|
59
|
+
if (value !== undefined) {
|
|
60
|
+
;(clone as any)[key] = value
|
|
70
61
|
}
|
|
71
62
|
})
|
|
72
63
|
}
|
|
73
64
|
})
|
|
74
|
-
|
|
75
65
|
return clone
|
|
76
66
|
}
|
|
77
67
|
|
|
78
|
-
export default function useNotification(
|
|
68
|
+
export default function useNotification(
|
|
69
|
+
rootConfig: MaybeRef<NotificationConfig> = {},
|
|
70
|
+
): [NotificationAPI, () => VueNode] {
|
|
79
71
|
const configRef = computed(() => unref(rootConfig) || {})
|
|
80
72
|
const container = shallowRef<HTMLElement | ShadowRoot>()
|
|
73
|
+
const notificationsRef = shallowRef<NotificationsRef>()
|
|
74
|
+
const taskQueue = shallowRef<Task[]>([])
|
|
81
75
|
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
const {
|
|
86
|
-
getContainer,
|
|
87
|
-
motion,
|
|
88
|
-
prefixCls,
|
|
89
|
-
maxCount,
|
|
90
|
-
className,
|
|
91
|
-
style,
|
|
92
|
-
onAllRemoved,
|
|
93
|
-
stack,
|
|
94
|
-
renderNotifications,
|
|
95
|
-
...restConfig
|
|
96
|
-
} = configRef.value
|
|
97
|
-
return restConfig
|
|
76
|
+
const shareConfig = computed<SharedConfig>(() => {
|
|
77
|
+
const { placement, closable, duration, showProgress } = configRef.value
|
|
78
|
+
return { placement, closable, duration, showProgress }
|
|
98
79
|
})
|
|
99
80
|
|
|
100
|
-
|
|
81
|
+
function resolveContainer() {
|
|
101
82
|
const getContainer = configRef.value.getContainer || defaultGetContainer
|
|
102
83
|
return getContainer()
|
|
103
84
|
}
|
|
@@ -105,31 +86,30 @@ export default function useNotification(rootConfig: MaybeRef<NotificationConfig>
|
|
|
105
86
|
const contextHolder = () => (
|
|
106
87
|
<Notifications
|
|
107
88
|
container={container.value}
|
|
108
|
-
ref={
|
|
89
|
+
ref={notificationsRef as any}
|
|
109
90
|
prefixCls={configRef.value.prefixCls}
|
|
110
|
-
motion={configRef.value.motion}
|
|
91
|
+
motion={configRef.value.motion as TransitionGroupProps | ((p: Placement) => TransitionGroupProps) | undefined}
|
|
111
92
|
maxCount={configRef.value.maxCount}
|
|
93
|
+
pauseOnHover={configRef.value.pauseOnHover}
|
|
94
|
+
classNames={configRef.value.classNames}
|
|
95
|
+
styles={configRef.value.styles}
|
|
96
|
+
components={configRef.value.components}
|
|
112
97
|
className={configRef.value.className}
|
|
113
|
-
style={configRef.value.style}
|
|
98
|
+
style={configRef.value.style as ((p: Placement) => CSSProperties) | undefined}
|
|
114
99
|
onAllRemoved={configRef.value.onAllRemoved}
|
|
115
|
-
stack={configRef.value.stack}
|
|
100
|
+
stack={configRef.value.stack as StackInput | undefined}
|
|
116
101
|
renderNotifications={configRef.value.renderNotifications}
|
|
117
102
|
/>
|
|
118
103
|
)
|
|
119
104
|
|
|
120
|
-
const taskQueue = shallowRef<Task[]>([])
|
|
121
|
-
|
|
122
|
-
// ========================= Refs =========================
|
|
123
|
-
|
|
124
105
|
const api: NotificationAPI = {
|
|
125
106
|
open(config) {
|
|
126
|
-
const
|
|
127
|
-
if (
|
|
128
|
-
|
|
107
|
+
const merged = mergeConfig<NotificationListConfig>(shareConfig.value, config as any)
|
|
108
|
+
if (merged.key === null || merged.key === undefined) {
|
|
109
|
+
merged.key = `vc-notification-${uniqueKey}`
|
|
129
110
|
uniqueKey += 1
|
|
130
111
|
}
|
|
131
|
-
|
|
132
|
-
taskQueue.value = [...taskQueue.value, { type: 'open', config: mergedConfig }]
|
|
112
|
+
taskQueue.value = [...taskQueue.value, { type: 'open', config: merged }]
|
|
133
113
|
},
|
|
134
114
|
close(key) {
|
|
135
115
|
taskQueue.value = [...taskQueue.value, { type: 'close', key }]
|
|
@@ -139,41 +119,35 @@ export default function useNotification(rootConfig: MaybeRef<NotificationConfig>
|
|
|
139
119
|
},
|
|
140
120
|
}
|
|
141
121
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
onMounted(
|
|
146
|
-
() => {
|
|
147
|
-
container.value = resolveContainer()
|
|
148
|
-
},
|
|
149
|
-
)
|
|
122
|
+
onMounted(() => {
|
|
123
|
+
container.value = resolveContainer()
|
|
124
|
+
})
|
|
150
125
|
watch(
|
|
151
126
|
() => configRef.value.getContainer,
|
|
152
127
|
() => {
|
|
153
128
|
container.value = resolveContainer()
|
|
154
129
|
},
|
|
155
130
|
)
|
|
131
|
+
|
|
156
132
|
watch(taskQueue, () => {
|
|
157
|
-
if (
|
|
158
|
-
taskQueue.value
|
|
133
|
+
if (notificationsRef.value && taskQueue.value.length) {
|
|
134
|
+
const tasks = taskQueue.value
|
|
135
|
+
tasks.forEach((task) => {
|
|
159
136
|
switch (task.type) {
|
|
160
137
|
case 'open':
|
|
161
|
-
|
|
138
|
+
notificationsRef.value?.open(task.config)
|
|
162
139
|
break
|
|
163
140
|
case 'close':
|
|
164
|
-
|
|
141
|
+
notificationsRef.value?.close(task.key)
|
|
165
142
|
break
|
|
166
143
|
case 'destroy':
|
|
167
|
-
|
|
168
|
-
break
|
|
169
|
-
default:
|
|
144
|
+
notificationsRef.value?.destroy()
|
|
170
145
|
break
|
|
171
146
|
}
|
|
172
147
|
})
|
|
173
|
-
taskQueue.value = taskQueue.value.filter(task => !
|
|
148
|
+
taskQueue.value = taskQueue.value.filter(task => !tasks.includes(task))
|
|
174
149
|
}
|
|
175
150
|
})
|
|
176
151
|
|
|
177
|
-
|
|
178
|
-
return [api, contextHolder] as [NotificationAPI, () => VueNode]
|
|
152
|
+
return [api, contextHolder]
|
|
179
153
|
}
|
package/src/hooks/useStack.ts
CHANGED
|
@@ -1,32 +1,40 @@
|
|
|
1
|
-
import type { ComputedRef, MaybeRef
|
|
2
|
-
import
|
|
3
|
-
|
|
1
|
+
import type { ComputedRef, MaybeRef } from 'vue'
|
|
2
|
+
import { computed, unref } from 'vue'
|
|
3
|
+
|
|
4
|
+
export interface StackConfig {
|
|
5
|
+
threshold?: number
|
|
6
|
+
offset?: number
|
|
7
|
+
}
|
|
4
8
|
|
|
5
9
|
const DEFAULT_OFFSET = 8
|
|
6
10
|
const DEFAULT_THRESHOLD = 3
|
|
7
|
-
const DEFAULT_GAP = 16
|
|
8
11
|
|
|
9
|
-
type StackParams =
|
|
12
|
+
type StackParams = Required<StackConfig>
|
|
13
|
+
|
|
14
|
+
export type StackInput = boolean | StackConfig
|
|
10
15
|
|
|
11
|
-
type UseStack = (
|
|
16
|
+
type UseStack = (
|
|
17
|
+
config?: MaybeRef<StackInput | undefined>,
|
|
18
|
+
) => [ComputedRef<boolean>, ComputedRef<StackParams>]
|
|
12
19
|
|
|
13
20
|
const useStack: UseStack = (config) => {
|
|
14
|
-
const
|
|
15
|
-
offset: DEFAULT_OFFSET,
|
|
16
|
-
threshold: DEFAULT_THRESHOLD,
|
|
17
|
-
gap: DEFAULT_GAP,
|
|
18
|
-
})
|
|
21
|
+
const enabled = computed(() => !!unref(config))
|
|
19
22
|
|
|
20
|
-
|
|
21
|
-
const
|
|
22
|
-
if (
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
const params = computed<StackParams>(() => {
|
|
24
|
+
const value = unref(config)
|
|
25
|
+
if (value && typeof value === 'object') {
|
|
26
|
+
return {
|
|
27
|
+
offset: value.offset ?? DEFAULT_OFFSET,
|
|
28
|
+
threshold: value.threshold ?? DEFAULT_THRESHOLD,
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
offset: DEFAULT_OFFSET,
|
|
33
|
+
threshold: DEFAULT_THRESHOLD,
|
|
26
34
|
}
|
|
27
35
|
})
|
|
28
36
|
|
|
29
|
-
return [
|
|
37
|
+
return [enabled, params]
|
|
30
38
|
}
|
|
31
39
|
|
|
32
40
|
export default useStack
|
package/src/index.ts
CHANGED
|
@@ -1,9 +1,35 @@
|
|
|
1
1
|
import type { NotificationAPI, NotificationConfig } from './hooks/useNotification'
|
|
2
|
+
import type { ComponentsType, NotificationProps } from './Notification'
|
|
3
|
+
import type { NotificationProgressProps } from './Progress'
|
|
2
4
|
import useNotification from './hooks/useNotification'
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
+
import Notification from './Notification'
|
|
6
|
+
import NotificationList from './NotificationList'
|
|
7
|
+
import NotificationProvider, { useNotificationProvider } from './NotificationProvider'
|
|
8
|
+
import Progress from './Progress'
|
|
5
9
|
|
|
6
|
-
export {
|
|
7
|
-
|
|
10
|
+
export {
|
|
11
|
+
Notification,
|
|
12
|
+
NotificationList,
|
|
13
|
+
NotificationProvider,
|
|
14
|
+
Progress,
|
|
15
|
+
useNotification,
|
|
16
|
+
useNotificationProvider,
|
|
17
|
+
}
|
|
8
18
|
|
|
9
|
-
export type {
|
|
19
|
+
export type {
|
|
20
|
+
ComponentsType,
|
|
21
|
+
NotificationAPI,
|
|
22
|
+
NotificationConfig,
|
|
23
|
+
NotificationProgressProps,
|
|
24
|
+
NotificationProps,
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export type {
|
|
28
|
+
NotificationClassNames,
|
|
29
|
+
NotificationListConfig,
|
|
30
|
+
NotificationListProps,
|
|
31
|
+
NotificationStyles,
|
|
32
|
+
Placement,
|
|
33
|
+
StackConfig,
|
|
34
|
+
StackInput,
|
|
35
|
+
} from './NotificationList'
|