@v-c/notification 1.0.0 → 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
package/dist/interface.d.ts
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { VueNode } from '@v-c/util/dist/type';
|
|
2
|
-
import { CSSProperties } from 'vue';
|
|
3
|
-
export type Placement = 'top' | 'topLeft' | 'topRight' | 'bottom' | 'bottomLeft' | 'bottomRight';
|
|
4
|
-
type NoticeSemanticProps = 'wrapper';
|
|
5
|
-
export type Key = string | number;
|
|
6
|
-
export interface NoticeConfig {
|
|
7
|
-
content?: VueNode;
|
|
8
|
-
duration?: number | false | null;
|
|
9
|
-
showProgress?: boolean;
|
|
10
|
-
pauseOnHover?: boolean;
|
|
11
|
-
closeIcon?: VueNode;
|
|
12
|
-
closable?: boolean | ({
|
|
13
|
-
closeIcon?: VueNode;
|
|
14
|
-
onClose?: VoidFunction;
|
|
15
|
-
} & Record<string, any>);
|
|
16
|
-
className?: string;
|
|
17
|
-
style?: CSSProperties;
|
|
18
|
-
classNames?: {
|
|
19
|
-
[key in NoticeSemanticProps]?: string;
|
|
20
|
-
};
|
|
21
|
-
styles?: {
|
|
22
|
-
[key in NoticeSemanticProps]?: CSSProperties;
|
|
23
|
-
};
|
|
24
|
-
/** @private Internal usage. Do not override in your code */
|
|
25
|
-
props?: Record<string, any>;
|
|
26
|
-
onClose?: VoidFunction;
|
|
27
|
-
onClick?: (event: Event) => void;
|
|
28
|
-
}
|
|
29
|
-
export interface OpenConfig extends NoticeConfig {
|
|
30
|
-
key: Key;
|
|
31
|
-
placement?: Placement;
|
|
32
|
-
content?: VueNode;
|
|
33
|
-
duration?: number | false | null;
|
|
34
|
-
}
|
|
35
|
-
export type InnerOpenConfig = OpenConfig & {
|
|
36
|
-
times?: number;
|
|
37
|
-
};
|
|
38
|
-
export type Placements = Partial<Record<Placement, OpenConfig[]>>;
|
|
39
|
-
export type StackConfig = boolean | {
|
|
40
|
-
/**
|
|
41
|
-
* When number is greater than threshold, notifications will be stacked together.
|
|
42
|
-
* @default 3
|
|
43
|
-
*/
|
|
44
|
-
threshold?: number;
|
|
45
|
-
/**
|
|
46
|
-
* Offset when notifications are stacked together.
|
|
47
|
-
* @default 8
|
|
48
|
-
*/
|
|
49
|
-
offset?: number;
|
|
50
|
-
/**
|
|
51
|
-
* Spacing between each notification when expanded.
|
|
52
|
-
*/
|
|
53
|
-
gap?: number;
|
|
54
|
-
};
|
|
55
|
-
export {};
|
package/dist/interface.js
DELETED
|
File without changes
|
package/src/Notice.tsx
DELETED
|
@@ -1,212 +0,0 @@
|
|
|
1
|
-
import type { CSSProperties } from 'vue'
|
|
2
|
-
import type { Key, NoticeConfig } from './interface.ts'
|
|
3
|
-
import { classNames } from '@v-c/util'
|
|
4
|
-
import KeyCode from '@v-c/util/dist/KeyCode'
|
|
5
|
-
import pickAttrs from '@v-c/util/dist/pickAttrs'
|
|
6
|
-
import { computed, defineComponent, shallowRef, watch } from 'vue'
|
|
7
|
-
|
|
8
|
-
export interface NoticeProps extends Omit<NoticeConfig, 'onClose'> {
|
|
9
|
-
prefixCls: string
|
|
10
|
-
eventKey: Key
|
|
11
|
-
onClick?: (event: Event) => void
|
|
12
|
-
onNoticeClose?: (key: Key) => void
|
|
13
|
-
hovering?: boolean
|
|
14
|
-
props?: Record<string, any>
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const defaults = {
|
|
18
|
-
duration: 4.5,
|
|
19
|
-
pauseOnHover: true,
|
|
20
|
-
closeIcon: 'x',
|
|
21
|
-
} as const
|
|
22
|
-
|
|
23
|
-
const Notify = defineComponent<NoticeProps & { times?: number }>((props, { attrs }) => {
|
|
24
|
-
const hovering = shallowRef(false)
|
|
25
|
-
const percent = shallowRef(0)
|
|
26
|
-
const spentTime = shallowRef(0)
|
|
27
|
-
|
|
28
|
-
const mergedHovering = computed(() => props.hovering || hovering.value)
|
|
29
|
-
const mergedDuration = computed(() => {
|
|
30
|
-
if (typeof props.duration === 'number') {
|
|
31
|
-
return props.duration
|
|
32
|
-
}
|
|
33
|
-
if (props.duration === undefined) {
|
|
34
|
-
return defaults.duration
|
|
35
|
-
}
|
|
36
|
-
return 0
|
|
37
|
-
})
|
|
38
|
-
const mergedPauseOnHover = computed(() =>
|
|
39
|
-
props.pauseOnHover === undefined ? defaults.pauseOnHover : props.pauseOnHover,
|
|
40
|
-
)
|
|
41
|
-
const mergedShowProgress = computed(() => mergedDuration.value > 0 && props.showProgress)
|
|
42
|
-
const mergedCloseIcon = computed(() => props.closeIcon ?? defaults.closeIcon)
|
|
43
|
-
|
|
44
|
-
// ======================== Close =========================
|
|
45
|
-
const onInternalClose = () => {
|
|
46
|
-
props.onNoticeClose?.(props.eventKey)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const onCloseKeyDown = (e: KeyboardEvent) => {
|
|
50
|
-
if (e.key === 'Enter' || e.code === 'Enter' || e.keyCode === KeyCode.ENTER) {
|
|
51
|
-
onInternalClose()
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// ======================== Timing ========================
|
|
56
|
-
watch([
|
|
57
|
-
() => props.times,
|
|
58
|
-
mergedDuration,
|
|
59
|
-
mergedHovering,
|
|
60
|
-
], (_n, _, onCleanup) => {
|
|
61
|
-
const duration = mergedDuration.value
|
|
62
|
-
const hoveringValue = mergedHovering.value
|
|
63
|
-
const pauseOnHover = mergedPauseOnHover.value
|
|
64
|
-
if (!hoveringValue && duration > 0) {
|
|
65
|
-
const start = Date.now() - spentTime.value
|
|
66
|
-
const timeoutId = window.setTimeout(() => {
|
|
67
|
-
onInternalClose()
|
|
68
|
-
}, duration * 1000 - spentTime.value)
|
|
69
|
-
|
|
70
|
-
onCleanup(() => {
|
|
71
|
-
if (pauseOnHover) {
|
|
72
|
-
clearTimeout(timeoutId)
|
|
73
|
-
}
|
|
74
|
-
spentTime.value = Date.now() - start
|
|
75
|
-
})
|
|
76
|
-
}
|
|
77
|
-
}, {
|
|
78
|
-
immediate: true,
|
|
79
|
-
})
|
|
80
|
-
|
|
81
|
-
// ===================== Progress Bar =====================
|
|
82
|
-
watch([
|
|
83
|
-
() => props.times,
|
|
84
|
-
mergedDuration,
|
|
85
|
-
spentTime,
|
|
86
|
-
mergedHovering,
|
|
87
|
-
mergedShowProgress,
|
|
88
|
-
], (_n, _, onCleanup) => {
|
|
89
|
-
const hoveringValue = mergedHovering.value
|
|
90
|
-
const showProgress = mergedShowProgress.value
|
|
91
|
-
const pauseOnHover = mergedPauseOnHover.value
|
|
92
|
-
const duration = mergedDuration.value
|
|
93
|
-
const baseSpentTime = spentTime.value
|
|
94
|
-
|
|
95
|
-
if (!hoveringValue && showProgress && (pauseOnHover || baseSpentTime === 0)) {
|
|
96
|
-
const start = performance.now()
|
|
97
|
-
let animationFrame = 0
|
|
98
|
-
|
|
99
|
-
const calculate = () => {
|
|
100
|
-
cancelAnimationFrame(animationFrame)
|
|
101
|
-
animationFrame = requestAnimationFrame((timestamp) => {
|
|
102
|
-
const runtime = timestamp + baseSpentTime - start
|
|
103
|
-
const progress = Math.min(runtime / (duration * 1000), 1)
|
|
104
|
-
percent.value = progress * 100
|
|
105
|
-
if (progress < 1) {
|
|
106
|
-
calculate()
|
|
107
|
-
}
|
|
108
|
-
})
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
calculate()
|
|
112
|
-
|
|
113
|
-
onCleanup(() => {
|
|
114
|
-
if (pauseOnHover) {
|
|
115
|
-
cancelAnimationFrame(animationFrame)
|
|
116
|
-
}
|
|
117
|
-
})
|
|
118
|
-
}
|
|
119
|
-
}, {
|
|
120
|
-
immediate: true,
|
|
121
|
-
})
|
|
122
|
-
|
|
123
|
-
return () => {
|
|
124
|
-
const {
|
|
125
|
-
closable,
|
|
126
|
-
prefixCls,
|
|
127
|
-
props: divProps,
|
|
128
|
-
onClick,
|
|
129
|
-
content,
|
|
130
|
-
className,
|
|
131
|
-
style,
|
|
132
|
-
} = props
|
|
133
|
-
|
|
134
|
-
// ======================== Closable ========================
|
|
135
|
-
const closableConfig
|
|
136
|
-
= typeof closable === 'object' && closable !== null
|
|
137
|
-
? closable
|
|
138
|
-
: closable
|
|
139
|
-
? { closeIcon: mergedCloseIcon.value }
|
|
140
|
-
: {}
|
|
141
|
-
const ariaProps = pickAttrs(closableConfig, true)
|
|
142
|
-
|
|
143
|
-
// ======================== Progress ========================
|
|
144
|
-
const safePercent = percent.value <= 0 ? 0 : percent.value > 100 ? 100 : percent.value
|
|
145
|
-
const validPercent = 100 - safePercent
|
|
146
|
-
|
|
147
|
-
// ======================== Render ========================
|
|
148
|
-
const noticePrefixCls = `${prefixCls}-notice`
|
|
149
|
-
|
|
150
|
-
const mergedStyle: CSSProperties = {
|
|
151
|
-
...(typeof divProps?.style === 'object' && divProps?.style ? divProps.style : {}),
|
|
152
|
-
...(typeof (attrs as any).style === 'object' && (attrs as any).style ? (attrs as any).style : {}),
|
|
153
|
-
...(typeof style === 'object' && style ? style : {}),
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
return (
|
|
157
|
-
<div
|
|
158
|
-
{...divProps}
|
|
159
|
-
class={
|
|
160
|
-
classNames(
|
|
161
|
-
noticePrefixCls,
|
|
162
|
-
className,
|
|
163
|
-
(attrs as any).class,
|
|
164
|
-
{
|
|
165
|
-
[`${noticePrefixCls}-closable`]: !!closable,
|
|
166
|
-
},
|
|
167
|
-
)
|
|
168
|
-
}
|
|
169
|
-
style={mergedStyle}
|
|
170
|
-
onMouseenter={(e: MouseEvent) => {
|
|
171
|
-
hovering.value = true
|
|
172
|
-
divProps?.onMouseEnter?.(e)
|
|
173
|
-
}}
|
|
174
|
-
onMouseleave={(e: MouseEvent) => {
|
|
175
|
-
hovering.value = false
|
|
176
|
-
divProps?.onMouseLeave?.(e)
|
|
177
|
-
}}
|
|
178
|
-
onClick={onClick}
|
|
179
|
-
>
|
|
180
|
-
{/* Content */}
|
|
181
|
-
<div class={`${noticePrefixCls}-content`}>{content}</div>
|
|
182
|
-
|
|
183
|
-
{/* Close Icon */}
|
|
184
|
-
{closable && (
|
|
185
|
-
<button
|
|
186
|
-
type="button"
|
|
187
|
-
class={`${noticePrefixCls}-close`}
|
|
188
|
-
onKeydown={onCloseKeyDown}
|
|
189
|
-
aria-label="Close"
|
|
190
|
-
{...ariaProps}
|
|
191
|
-
onClick={(e) => {
|
|
192
|
-
e.preventDefault()
|
|
193
|
-
e.stopPropagation()
|
|
194
|
-
onInternalClose()
|
|
195
|
-
}}
|
|
196
|
-
>
|
|
197
|
-
{closableConfig.closeIcon ?? mergedCloseIcon.value}
|
|
198
|
-
</button>
|
|
199
|
-
)}
|
|
200
|
-
|
|
201
|
-
{/* Progress Bar */}
|
|
202
|
-
{mergedShowProgress.value && (
|
|
203
|
-
<progress class={`${noticePrefixCls}-progress`} max="100" value={validPercent}>
|
|
204
|
-
{`${validPercent}%`}
|
|
205
|
-
</progress>
|
|
206
|
-
)}
|
|
207
|
-
</div>
|
|
208
|
-
)
|
|
209
|
-
}
|
|
210
|
-
})
|
|
211
|
-
|
|
212
|
-
export default Notify
|
package/src/NoticeList.tsx
DELETED
|
@@ -1,219 +0,0 @@
|
|
|
1
|
-
import type { CSSProperties, TransitionGroupProps } from 'vue'
|
|
2
|
-
import type { InnerOpenConfig, Key, NoticeConfig, OpenConfig, Placement, StackConfig } from './interface.ts'
|
|
3
|
-
import { classNames as clsx } from '@v-c/util'
|
|
4
|
-
import { getTransitionGroupProps } from '@v-c/util/dist/utils/transition'
|
|
5
|
-
import { unrefElement } from '@v-c/util/dist/vueuse/unref-element'
|
|
6
|
-
import { computed, defineComponent, reactive, ref, shallowRef, toRef, TransitionGroup, watch, watchEffect } from 'vue'
|
|
7
|
-
import useStack from './hooks/useStack.ts'
|
|
8
|
-
import Notice from './Notice.tsx'
|
|
9
|
-
import { useNotificationContext } from './NotificationProvider.tsx'
|
|
10
|
-
|
|
11
|
-
export interface NoticeListProps {
|
|
12
|
-
configList?: OpenConfig[]
|
|
13
|
-
placement?: Placement
|
|
14
|
-
prefixCls?: string
|
|
15
|
-
motion?: TransitionGroupProps | ((placement: Placement) => TransitionGroupProps)
|
|
16
|
-
stack?: StackConfig
|
|
17
|
-
|
|
18
|
-
// Events
|
|
19
|
-
onAllNoticeRemoved?: (placement: Placement) => void
|
|
20
|
-
onNoticeClose?: (key: Key) => void
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const NoticeList = defineComponent<NoticeListProps>((props, { attrs }) => {
|
|
24
|
-
const ctx = useNotificationContext()
|
|
25
|
-
const dictRef = reactive<Record<string, HTMLDivElement | undefined>>({})
|
|
26
|
-
const keys = computed(() =>
|
|
27
|
-
(props.configList ?? []).map(config => ({
|
|
28
|
-
config,
|
|
29
|
-
key: String(config.key),
|
|
30
|
-
})),
|
|
31
|
-
)
|
|
32
|
-
const latestNotice = shallowRef<HTMLDivElement | null>(null)
|
|
33
|
-
const hoverKeys = ref<string[]>([])
|
|
34
|
-
|
|
35
|
-
const stackConfig = toRef(props, 'stack')
|
|
36
|
-
const [stackEnabled, stackOptions] = useStack(stackConfig)
|
|
37
|
-
const stackActive = computed(() => stackEnabled.value || stackConfig.value === false)
|
|
38
|
-
const expanded = computed(() => {
|
|
39
|
-
if (!stackActive.value) {
|
|
40
|
-
return false
|
|
41
|
-
}
|
|
42
|
-
if (!stackEnabled.value) {
|
|
43
|
-
return true
|
|
44
|
-
}
|
|
45
|
-
return hoverKeys.value.length > 0 || keys.value.length <= stackOptions.threshold!.value!
|
|
46
|
-
})
|
|
47
|
-
const placementMotion = computed(() => {
|
|
48
|
-
if (typeof props.motion === 'function') {
|
|
49
|
-
return props.placement ? props.motion(props.placement) : undefined
|
|
50
|
-
}
|
|
51
|
-
return props.motion
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
// Clean hover key
|
|
55
|
-
watch([hoverKeys, keys, stackEnabled], () => {
|
|
56
|
-
if (stackEnabled.value && hoverKeys.value.length > 1) {
|
|
57
|
-
hoverKeys.value = hoverKeys.value.filter(key =>
|
|
58
|
-
keys.value.some(({ key: dataKey }) => key === dataKey),
|
|
59
|
-
)
|
|
60
|
-
}
|
|
61
|
-
})
|
|
62
|
-
watch(stackEnabled, (enabled) => {
|
|
63
|
-
if (!enabled && hoverKeys.value.length) {
|
|
64
|
-
hoverKeys.value = []
|
|
65
|
-
}
|
|
66
|
-
})
|
|
67
|
-
|
|
68
|
-
// Sync latest notice after DOM updates so collapsed stack uses accurate height
|
|
69
|
-
watchEffect(
|
|
70
|
-
() => {
|
|
71
|
-
if (!stackActive.value) {
|
|
72
|
-
latestNotice.value = null
|
|
73
|
-
return
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
const lastKey = keys.value[keys.value.length - 1]?.key
|
|
77
|
-
latestNotice.value = lastKey ? dictRef[lastKey] ?? null : null
|
|
78
|
-
},
|
|
79
|
-
{ flush: 'post' },
|
|
80
|
-
)
|
|
81
|
-
|
|
82
|
-
const checkAllClosed = () => {
|
|
83
|
-
if (!props.placement) {
|
|
84
|
-
return
|
|
85
|
-
}
|
|
86
|
-
if (keys.value.length === 0) {
|
|
87
|
-
props.onAllNoticeRemoved?.(props.placement)
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
return () => {
|
|
92
|
-
const { prefixCls = '', placement = 'topRight', onNoticeClose } = props
|
|
93
|
-
|
|
94
|
-
const renderNotify = () =>
|
|
95
|
-
keys.value.map(({ config }, motionIndex) => {
|
|
96
|
-
const { key, times } = config as InnerOpenConfig
|
|
97
|
-
const strKey = String(key)
|
|
98
|
-
const {
|
|
99
|
-
className: configClassName,
|
|
100
|
-
style: configStyle,
|
|
101
|
-
classNames: configClassNames,
|
|
102
|
-
styles: configStyles,
|
|
103
|
-
...restConfig
|
|
104
|
-
} = config as NoticeConfig
|
|
105
|
-
const dataIndex = keys.value.findIndex(item => item.key === strKey)
|
|
106
|
-
const stackStyle: CSSProperties = {}
|
|
107
|
-
|
|
108
|
-
if (stackActive.value) {
|
|
109
|
-
const index = keys.value.length - 1 - (dataIndex > -1 ? dataIndex : motionIndex - 1)
|
|
110
|
-
const transformX = placement === 'top' || placement === 'bottom' ? '-50%' : '0'
|
|
111
|
-
if (index > 0) {
|
|
112
|
-
stackStyle.height = expanded.value
|
|
113
|
-
? dictRef[strKey]?.offsetHeight
|
|
114
|
-
: latestNotice.value?.offsetHeight
|
|
115
|
-
if (stackStyle.height && typeof stackStyle.height === 'number') {
|
|
116
|
-
stackStyle.height = `${stackStyle.height}px`
|
|
117
|
-
}
|
|
118
|
-
let verticalOffset = 0
|
|
119
|
-
for (let i = 0; i < index; i += 1) {
|
|
120
|
-
const targetKey = keys.value[keys.value.length - 1 - i]?.key
|
|
121
|
-
const node = targetKey ? dictRef[targetKey] : null
|
|
122
|
-
verticalOffset += (node?.offsetHeight ?? 0) + stackOptions.gap!.value!
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
const transformY
|
|
126
|
-
= (expanded.value ? verticalOffset : index * stackOptions.offset!.value!)
|
|
127
|
-
* (placement.startsWith('top') ? 1 : -1)
|
|
128
|
-
const currentWidth = dictRef[strKey]?.offsetWidth
|
|
129
|
-
const latestWidth = latestNotice.value?.offsetWidth
|
|
130
|
-
const scaleX
|
|
131
|
-
= !expanded.value && latestWidth && currentWidth
|
|
132
|
-
? (latestWidth - stackOptions.offset!.value! * 2 * (index < 3 ? index : 3))
|
|
133
|
-
/ currentWidth
|
|
134
|
-
: 1
|
|
135
|
-
stackStyle.transform = `translate3d(${transformX}, ${transformY}px, 0) scaleX(${scaleX})`
|
|
136
|
-
}
|
|
137
|
-
else {
|
|
138
|
-
stackStyle.transform = `translate3d(${transformX}, 0, 0)`
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
return (
|
|
142
|
-
<div
|
|
143
|
-
key={strKey}
|
|
144
|
-
class={clsx(`${prefixCls}-notice-wrapper`, configClassNames?.wrapper)}
|
|
145
|
-
style={{
|
|
146
|
-
...stackStyle,
|
|
147
|
-
...configStyles?.wrapper,
|
|
148
|
-
}}
|
|
149
|
-
onMouseenter={() => {
|
|
150
|
-
if (!stackEnabled.value) {
|
|
151
|
-
return
|
|
152
|
-
}
|
|
153
|
-
hoverKeys.value = hoverKeys.value.includes(strKey)
|
|
154
|
-
? hoverKeys.value
|
|
155
|
-
: [...hoverKeys.value, strKey]
|
|
156
|
-
}}
|
|
157
|
-
onMouseleave={() => {
|
|
158
|
-
if (!stackEnabled.value) {
|
|
159
|
-
return
|
|
160
|
-
}
|
|
161
|
-
hoverKeys.value = hoverKeys.value.filter(k => k !== strKey)
|
|
162
|
-
}}
|
|
163
|
-
>
|
|
164
|
-
<Notice
|
|
165
|
-
{...restConfig as any}
|
|
166
|
-
ref={(el) => {
|
|
167
|
-
const element = unrefElement<HTMLDivElement>(el as any) ?? undefined
|
|
168
|
-
if (dataIndex > -1) {
|
|
169
|
-
dictRef[strKey] = element
|
|
170
|
-
}
|
|
171
|
-
else {
|
|
172
|
-
delete dictRef[strKey]
|
|
173
|
-
}
|
|
174
|
-
}}
|
|
175
|
-
prefixCls={prefixCls}
|
|
176
|
-
classNames={configClassNames}
|
|
177
|
-
styles={configStyles}
|
|
178
|
-
class={clsx(configClassName, (ctx.value as any)?.classNames?.notice)}
|
|
179
|
-
style={configStyle}
|
|
180
|
-
times={times}
|
|
181
|
-
eventKey={key}
|
|
182
|
-
onNoticeClose={onNoticeClose}
|
|
183
|
-
hovering={stackEnabled.value && hoverKeys.value.length > 0}
|
|
184
|
-
/>
|
|
185
|
-
</div>
|
|
186
|
-
)
|
|
187
|
-
})
|
|
188
|
-
let motionGroupProps: TransitionGroupProps = {}
|
|
189
|
-
if (placementMotion.value) {
|
|
190
|
-
motionGroupProps = getTransitionGroupProps(placementMotion.value.name!, placementMotion.value)
|
|
191
|
-
}
|
|
192
|
-
return (
|
|
193
|
-
<TransitionGroup
|
|
194
|
-
key={placement}
|
|
195
|
-
tag="div"
|
|
196
|
-
appear
|
|
197
|
-
{...{
|
|
198
|
-
class: clsx(
|
|
199
|
-
prefixCls,
|
|
200
|
-
`${prefixCls}-${placement}`,
|
|
201
|
-
(ctx.value as any)?.classNames?.list,
|
|
202
|
-
(attrs as any).class,
|
|
203
|
-
{
|
|
204
|
-
[`${prefixCls}-stack-expanded`]: expanded.value,
|
|
205
|
-
[`${prefixCls}-stack`]: stackActive.value,
|
|
206
|
-
},
|
|
207
|
-
),
|
|
208
|
-
style: (attrs as any).style,
|
|
209
|
-
}}
|
|
210
|
-
{...motionGroupProps}
|
|
211
|
-
onAfterLeave={checkAllClosed}
|
|
212
|
-
>
|
|
213
|
-
{renderNotify()}
|
|
214
|
-
</TransitionGroup>
|
|
215
|
-
)
|
|
216
|
-
}
|
|
217
|
-
})
|
|
218
|
-
|
|
219
|
-
export default NoticeList
|
package/src/interface.ts
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import type { VueNode } from '@v-c/util/dist/type'
|
|
2
|
-
import type { CSSProperties } from 'vue'
|
|
3
|
-
|
|
4
|
-
export type Placement = 'top' | 'topLeft' | 'topRight' | 'bottom' | 'bottomLeft' | 'bottomRight'
|
|
5
|
-
|
|
6
|
-
type NoticeSemanticProps = 'wrapper'
|
|
7
|
-
|
|
8
|
-
export type Key = string | number
|
|
9
|
-
export interface NoticeConfig {
|
|
10
|
-
content?: VueNode
|
|
11
|
-
duration?: number | false | null
|
|
12
|
-
showProgress?: boolean
|
|
13
|
-
pauseOnHover?: boolean
|
|
14
|
-
closeIcon?: VueNode
|
|
15
|
-
closable?:
|
|
16
|
-
| boolean
|
|
17
|
-
| ({ closeIcon?: VueNode, onClose?: VoidFunction } & Record<string, any>)
|
|
18
|
-
className?: string
|
|
19
|
-
style?: CSSProperties
|
|
20
|
-
classNames?: {
|
|
21
|
-
[key in NoticeSemanticProps]?: string;
|
|
22
|
-
}
|
|
23
|
-
styles?: {
|
|
24
|
-
[key in NoticeSemanticProps]?: CSSProperties;
|
|
25
|
-
}
|
|
26
|
-
/** @private Internal usage. Do not override in your code */
|
|
27
|
-
props?: Record<string, any>
|
|
28
|
-
|
|
29
|
-
onClose?: VoidFunction
|
|
30
|
-
onClick?: (event: Event) => void
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export interface OpenConfig extends NoticeConfig {
|
|
34
|
-
key: Key
|
|
35
|
-
placement?: Placement
|
|
36
|
-
content?: VueNode
|
|
37
|
-
duration?: number | false | null
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export type InnerOpenConfig = OpenConfig & { times?: number }
|
|
41
|
-
|
|
42
|
-
export type Placements = Partial<Record<Placement, OpenConfig[]>>
|
|
43
|
-
|
|
44
|
-
export type StackConfig
|
|
45
|
-
= | boolean
|
|
46
|
-
| {
|
|
47
|
-
/**
|
|
48
|
-
* When number is greater than threshold, notifications will be stacked together.
|
|
49
|
-
* @default 3
|
|
50
|
-
*/
|
|
51
|
-
threshold?: number
|
|
52
|
-
/**
|
|
53
|
-
* Offset when notifications are stacked together.
|
|
54
|
-
* @default 8
|
|
55
|
-
*/
|
|
56
|
-
offset?: number
|
|
57
|
-
/**
|
|
58
|
-
* Spacing between each notification when expanded.
|
|
59
|
-
*/
|
|
60
|
-
gap?: number
|
|
61
|
-
}
|