@v-c/notification 0.0.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/LICENSE +21 -0
- package/bump.config.ts +6 -0
- package/dist/Notice.cjs +230 -0
- package/dist/Notice.d.ts +15 -0
- package/dist/Notice.js +225 -0
- package/dist/NoticeList.cjs +157 -0
- package/dist/NoticeList.d.ts +13 -0
- package/dist/NoticeList.js +154 -0
- package/dist/NotificationProvider.cjs +13 -0
- package/dist/NotificationProvider.d.ts +10 -0
- package/dist/NotificationProvider.js +10 -0
- package/dist/Notifications.cjs +146 -0
- package/dist/Notifications.d.ts +24 -0
- package/dist/Notifications.js +143 -0
- package/dist/_virtual/rolldown_runtime.cjs +21 -0
- package/dist/hooks/useNotification.cjs +80 -0
- package/dist/hooks/useNotification.d.ts +36 -0
- package/dist/hooks/useNotification.js +78 -0
- package/dist/hooks/useStack.cjs +24 -0
- package/dist/hooks/useStack.d.ts +6 -0
- package/dist/hooks/useStack.js +22 -0
- package/dist/index.cjs +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +4 -0
- package/dist/interface.cjs +0 -0
- package/dist/interface.d.ts +55 -0
- package/dist/interface.js +0 -0
- package/docs/context.vue +34 -0
- package/docs/hooks.vue +89 -0
- package/docs/index.less +265 -0
- package/docs/maxCount.vue +24 -0
- package/docs/motion.ts +33 -0
- package/docs/notification.stories.vue +31 -0
- package/docs/showProgress.vue +34 -0
- package/docs/stack.vue +39 -0
- package/package.json +30 -0
- package/src/Notice.tsx +212 -0
- package/src/NoticeList.tsx +203 -0
- package/src/NotificationProvider.tsx +19 -0
- package/src/Notifications.tsx +164 -0
- package/src/hooks/useNotification.tsx +163 -0
- package/src/hooks/useStack.ts +32 -0
- package/src/index.ts +9 -0
- package/src/interface.ts +61 -0
- package/tsconfig.json +7 -0
- package/vite.config.ts +18 -0
- package/vitest.config.ts +9 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import Notifications_default from "../Notifications.js";
|
|
2
|
+
import { createVNode, onMounted, shallowRef, watch } from "vue";
|
|
3
|
+
var defaultGetContainer = () => document.body;
|
|
4
|
+
var uniqueKey = 0;
|
|
5
|
+
function mergeConfig(...objList) {
|
|
6
|
+
const clone = {};
|
|
7
|
+
objList.forEach((obj) => {
|
|
8
|
+
if (obj) Object.keys(obj).forEach((key) => {
|
|
9
|
+
const val = obj[key];
|
|
10
|
+
if (val !== void 0) clone[key] = val;
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
return clone;
|
|
14
|
+
}
|
|
15
|
+
function useNotification(rootConfig = {}) {
|
|
16
|
+
const { getContainer = defaultGetContainer, motion, prefixCls, maxCount, className, style, onAllRemoved, stack, renderNotifications,...shareConfig } = rootConfig;
|
|
17
|
+
const container = shallowRef();
|
|
18
|
+
const notificationRef = shallowRef();
|
|
19
|
+
const contextHolder = () => createVNode(Notifications_default, {
|
|
20
|
+
"container": container.value,
|
|
21
|
+
"ref": notificationRef,
|
|
22
|
+
"prefixCls": prefixCls,
|
|
23
|
+
"motion": motion,
|
|
24
|
+
"maxCount": maxCount,
|
|
25
|
+
"className": className,
|
|
26
|
+
"style": style,
|
|
27
|
+
"onAllRemoved": onAllRemoved,
|
|
28
|
+
"stack": stack,
|
|
29
|
+
"renderNotifications": renderNotifications
|
|
30
|
+
}, null);
|
|
31
|
+
const taskQueue = shallowRef([]);
|
|
32
|
+
const api = {
|
|
33
|
+
open(config) {
|
|
34
|
+
const mergedConfig = mergeConfig(shareConfig, config);
|
|
35
|
+
if (mergedConfig.key === null || mergedConfig.key === void 0) {
|
|
36
|
+
mergedConfig.key = `vc-notification-${uniqueKey}`;
|
|
37
|
+
uniqueKey += 1;
|
|
38
|
+
}
|
|
39
|
+
taskQueue.value = [...taskQueue.value, {
|
|
40
|
+
type: "open",
|
|
41
|
+
config: mergedConfig
|
|
42
|
+
}];
|
|
43
|
+
},
|
|
44
|
+
close(key) {
|
|
45
|
+
taskQueue.value = [...taskQueue.value, {
|
|
46
|
+
type: "close",
|
|
47
|
+
key
|
|
48
|
+
}];
|
|
49
|
+
},
|
|
50
|
+
destroy() {
|
|
51
|
+
taskQueue.value = [...taskQueue.value, { type: "destroy" }];
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
onMounted(() => {
|
|
55
|
+
container.value = getContainer();
|
|
56
|
+
});
|
|
57
|
+
watch(taskQueue, () => {
|
|
58
|
+
if (notificationRef.value && taskQueue.value.length) {
|
|
59
|
+
taskQueue.value.forEach((task) => {
|
|
60
|
+
switch (task.type) {
|
|
61
|
+
case "open":
|
|
62
|
+
notificationRef.value?.open(task.config);
|
|
63
|
+
break;
|
|
64
|
+
case "close":
|
|
65
|
+
notificationRef.value?.close(task.key);
|
|
66
|
+
break;
|
|
67
|
+
case "destroy":
|
|
68
|
+
notificationRef.value?.destroy();
|
|
69
|
+
break;
|
|
70
|
+
default: break;
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
taskQueue.value = taskQueue.value.filter((task) => !taskQueue.value.includes(task));
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
return [api, contextHolder];
|
|
77
|
+
}
|
|
78
|
+
export { useNotification as default };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
2
|
+
const require_rolldown_runtime = require("../_virtual/rolldown_runtime.cjs");
|
|
3
|
+
let vue = require("vue");
|
|
4
|
+
var DEFAULT_OFFSET = 8;
|
|
5
|
+
var DEFAULT_THRESHOLD = 3;
|
|
6
|
+
var DEFAULT_GAP = 16;
|
|
7
|
+
var useStack = (config) => {
|
|
8
|
+
const result = (0, vue.reactive)({
|
|
9
|
+
offset: DEFAULT_OFFSET,
|
|
10
|
+
threshold: DEFAULT_THRESHOLD,
|
|
11
|
+
gap: DEFAULT_GAP
|
|
12
|
+
});
|
|
13
|
+
(0, vue.watchEffect)(() => {
|
|
14
|
+
const _config = (0, vue.unref)(config);
|
|
15
|
+
if (_config && typeof _config === "object") {
|
|
16
|
+
result.offset = _config.offset ?? DEFAULT_OFFSET;
|
|
17
|
+
result.threshold = _config.threshold ?? DEFAULT_THRESHOLD;
|
|
18
|
+
result.gap = _config.gap ?? DEFAULT_GAP;
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
return [(0, vue.computed)(() => !!(0, vue.unref)(config)), (0, vue.toRefs)(result)];
|
|
22
|
+
};
|
|
23
|
+
var useStack_default = useStack;
|
|
24
|
+
exports.default = useStack_default;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { ComputedRef, MaybeRef, ToRefs } from 'vue';
|
|
2
|
+
import { StackConfig } from '../interface';
|
|
3
|
+
type StackParams = Exclude<StackConfig, boolean>;
|
|
4
|
+
type UseStack = (config?: MaybeRef<StackConfig | undefined>) => [ComputedRef<boolean>, ToRefs<StackParams>];
|
|
5
|
+
declare const useStack: UseStack;
|
|
6
|
+
export default useStack;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { computed, reactive, toRefs, unref, watchEffect } from "vue";
|
|
2
|
+
var DEFAULT_OFFSET = 8;
|
|
3
|
+
var DEFAULT_THRESHOLD = 3;
|
|
4
|
+
var DEFAULT_GAP = 16;
|
|
5
|
+
var useStack = (config) => {
|
|
6
|
+
const result = reactive({
|
|
7
|
+
offset: DEFAULT_OFFSET,
|
|
8
|
+
threshold: DEFAULT_THRESHOLD,
|
|
9
|
+
gap: DEFAULT_GAP
|
|
10
|
+
});
|
|
11
|
+
watchEffect(() => {
|
|
12
|
+
const _config = unref(config);
|
|
13
|
+
if (_config && typeof _config === "object") {
|
|
14
|
+
result.offset = _config.offset ?? DEFAULT_OFFSET;
|
|
15
|
+
result.threshold = _config.threshold ?? DEFAULT_THRESHOLD;
|
|
16
|
+
result.gap = _config.gap ?? DEFAULT_GAP;
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
return [computed(() => !!unref(config)), toRefs(result)];
|
|
20
|
+
};
|
|
21
|
+
var useStack_default = useStack;
|
|
22
|
+
export { useStack_default as default };
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
const require_Notice = require("./Notice.cjs");
|
|
2
|
+
const require_NotificationProvider = require("./NotificationProvider.cjs");
|
|
3
|
+
const require_useNotification = require("./hooks/useNotification.cjs");
|
|
4
|
+
exports.Notice = require_Notice.default;
|
|
5
|
+
exports.useNotification = require_useNotification.default;
|
|
6
|
+
exports.useNotificationProvider = require_NotificationProvider.useNotificationProvider;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { NotificationAPI, NotificationConfig, default as useNotification } from './hooks/useNotification';
|
|
2
|
+
import { default as Notice } from './Notice';
|
|
3
|
+
import { useNotificationProvider } from './NotificationProvider';
|
|
4
|
+
export { Notice, useNotification, useNotificationProvider };
|
|
5
|
+
export type { NotificationAPI, NotificationConfig };
|
|
6
|
+
export type { NoticeProps } from './Notice';
|
package/dist/index.js
ADDED
|
File without changes
|
|
@@ -0,0 +1,55 @@
|
|
|
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 {};
|
|
File without changes
|
package/docs/context.vue
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { h } from 'vue'
|
|
3
|
+
import { useNotification } from '../src'
|
|
4
|
+
import motion from './motion'
|
|
5
|
+
|
|
6
|
+
const [{ open }, holder] = useNotification({ motion })
|
|
7
|
+
const NOTICE = {
|
|
8
|
+
content: h('span', ['simple show']),
|
|
9
|
+
onclose() {
|
|
10
|
+
console.log('simple close')
|
|
11
|
+
},
|
|
12
|
+
}
|
|
13
|
+
function handleClick() {
|
|
14
|
+
open({
|
|
15
|
+
...NOTICE,
|
|
16
|
+
props: {
|
|
17
|
+
'data-testid': 'my-data-testid',
|
|
18
|
+
},
|
|
19
|
+
})
|
|
20
|
+
}
|
|
21
|
+
</script>
|
|
22
|
+
|
|
23
|
+
<template>
|
|
24
|
+
<div>
|
|
25
|
+
<button @click="handleClick">
|
|
26
|
+
simple show
|
|
27
|
+
</button>
|
|
28
|
+
<holder />
|
|
29
|
+
</div>
|
|
30
|
+
</template>
|
|
31
|
+
|
|
32
|
+
<style lang="less">
|
|
33
|
+
@import "./index.less";
|
|
34
|
+
</style>
|
package/docs/hooks.vue
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { useNotification } from '../src'
|
|
3
|
+
import motion from './motion'
|
|
4
|
+
|
|
5
|
+
const [notice, contextHolder] = useNotification({ motion, closable: true })
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<template>
|
|
9
|
+
<div>
|
|
10
|
+
<!-- Default -->
|
|
11
|
+
<button
|
|
12
|
+
@click="() => {
|
|
13
|
+
notice.open({
|
|
14
|
+
content: `${new Date().toISOString()}`,
|
|
15
|
+
})
|
|
16
|
+
}"
|
|
17
|
+
>
|
|
18
|
+
Basic
|
|
19
|
+
</button>
|
|
20
|
+
<button
|
|
21
|
+
@click="() => {
|
|
22
|
+
notice.open({
|
|
23
|
+
content: `${Array(Math.round(Math.random() * 5) + 1)
|
|
24
|
+
.fill(1)
|
|
25
|
+
.map(() => new Date().toISOString())
|
|
26
|
+
.join('\n')}`,
|
|
27
|
+
duration: null,
|
|
28
|
+
})
|
|
29
|
+
}"
|
|
30
|
+
>
|
|
31
|
+
Not Auto Close
|
|
32
|
+
</button>
|
|
33
|
+
|
|
34
|
+
<button
|
|
35
|
+
@click="() => {
|
|
36
|
+
notice.open({
|
|
37
|
+
content: `${Array(5)
|
|
38
|
+
.fill(1)
|
|
39
|
+
.map(() => new Date().toISOString())
|
|
40
|
+
.join('\n')}`,
|
|
41
|
+
duration: null,
|
|
42
|
+
});
|
|
43
|
+
}"
|
|
44
|
+
>
|
|
45
|
+
Not Auto Close
|
|
46
|
+
</button>
|
|
47
|
+
</div>
|
|
48
|
+
|
|
49
|
+
<div>
|
|
50
|
+
<button
|
|
51
|
+
@click="() => {
|
|
52
|
+
notice.open({
|
|
53
|
+
content: `No Close! ${new Date().toISOString()}`,
|
|
54
|
+
duration: null,
|
|
55
|
+
closable: false,
|
|
56
|
+
key: 'No Close',
|
|
57
|
+
onClose: () => {
|
|
58
|
+
console.log('Close!!!');
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
}"
|
|
62
|
+
>
|
|
63
|
+
No Closable
|
|
64
|
+
</button>
|
|
65
|
+
|
|
66
|
+
<button
|
|
67
|
+
@click="() => {
|
|
68
|
+
notice.close('No Close');
|
|
69
|
+
}"
|
|
70
|
+
>
|
|
71
|
+
Force Close No Closable
|
|
72
|
+
</button>
|
|
73
|
+
</div>
|
|
74
|
+
|
|
75
|
+
<div>
|
|
76
|
+
<button
|
|
77
|
+
@click="() => {
|
|
78
|
+
notice.destroy();
|
|
79
|
+
}"
|
|
80
|
+
>
|
|
81
|
+
Destroy All
|
|
82
|
+
</button>
|
|
83
|
+
</div>
|
|
84
|
+
<contextHolder />
|
|
85
|
+
</template>
|
|
86
|
+
|
|
87
|
+
<style scoped>
|
|
88
|
+
|
|
89
|
+
</style>
|
package/docs/index.less
ADDED
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
@notificationPrefixCls: vc-notification;
|
|
2
|
+
|
|
3
|
+
.@{notificationPrefixCls} {
|
|
4
|
+
// ====================== Notification ======================
|
|
5
|
+
position: fixed;
|
|
6
|
+
z-index: 1000;
|
|
7
|
+
display: flex;
|
|
8
|
+
max-height: 100vh;
|
|
9
|
+
padding: 10px;
|
|
10
|
+
align-items: flex-end;
|
|
11
|
+
width: 340px;
|
|
12
|
+
overflow-x: hidden;
|
|
13
|
+
overflow-y: auto;
|
|
14
|
+
height: 100vh;
|
|
15
|
+
box-sizing: border-box;
|
|
16
|
+
pointer-events: none;
|
|
17
|
+
flex-direction: column;
|
|
18
|
+
|
|
19
|
+
// Position
|
|
20
|
+
&-top,
|
|
21
|
+
&-topLeft,
|
|
22
|
+
&-topRight {
|
|
23
|
+
top: 0;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
&-bottom,
|
|
27
|
+
&-bottomRight,
|
|
28
|
+
&-bottomLeft {
|
|
29
|
+
bottom: 0;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
&-bottomRight,
|
|
33
|
+
&-topRight {
|
|
34
|
+
right: 0;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// ========================= Notice =========================
|
|
38
|
+
&-notice {
|
|
39
|
+
position: relative;
|
|
40
|
+
display: block;
|
|
41
|
+
box-sizing: border-box;
|
|
42
|
+
line-height: 1.5;
|
|
43
|
+
width: 100%;
|
|
44
|
+
|
|
45
|
+
&-wrapper {
|
|
46
|
+
pointer-events: auto;
|
|
47
|
+
position: relative;
|
|
48
|
+
display: block;
|
|
49
|
+
box-sizing: border-box;
|
|
50
|
+
border-radius: 3px 3px;
|
|
51
|
+
box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
|
|
52
|
+
margin: 0 0 16px;
|
|
53
|
+
border: 1px solid #999;
|
|
54
|
+
border: 0px solid rgba(0, 0, 0, 0);
|
|
55
|
+
background: #fff;
|
|
56
|
+
width: 300px;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Content
|
|
60
|
+
&-content {
|
|
61
|
+
padding: 7px 20px 7px 10px;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
&-closable &-content {
|
|
65
|
+
padding-right: 20px;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
&-close {
|
|
69
|
+
position: absolute;
|
|
70
|
+
top: 3px;
|
|
71
|
+
right: 5px;
|
|
72
|
+
color: #000;
|
|
73
|
+
font-weight: 700;
|
|
74
|
+
font-size: 16px;
|
|
75
|
+
line-height: 1;
|
|
76
|
+
text-decoration: none;
|
|
77
|
+
text-shadow: 0 1px 0 #fff;
|
|
78
|
+
outline: none;
|
|
79
|
+
cursor: pointer;
|
|
80
|
+
opacity: 0.2;
|
|
81
|
+
filter: alpha(opacity=20);
|
|
82
|
+
border: 0;
|
|
83
|
+
background-color: #fff;
|
|
84
|
+
|
|
85
|
+
&-x:after {
|
|
86
|
+
content: '×';
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
&:hover {
|
|
90
|
+
text-decoration: none;
|
|
91
|
+
opacity: 1;
|
|
92
|
+
filter: alpha(opacity=100);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Progress
|
|
97
|
+
&-progress {
|
|
98
|
+
position: absolute;
|
|
99
|
+
left: 3px;
|
|
100
|
+
right: 3px;
|
|
101
|
+
border-radius: 1px;
|
|
102
|
+
overflow: hidden;
|
|
103
|
+
appearance: none;
|
|
104
|
+
-webkit-appearance: none;
|
|
105
|
+
display: block;
|
|
106
|
+
inline-size: 100%;
|
|
107
|
+
block-size: 2px;
|
|
108
|
+
border: 0;
|
|
109
|
+
|
|
110
|
+
&,
|
|
111
|
+
&::-webkit-progress-bar {
|
|
112
|
+
background-color: rgba(0, 0, 0, 0.04);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
&::-moz-progress-bar {
|
|
116
|
+
background-color: #31afff;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
&::-webkit-progress-value {
|
|
120
|
+
background-color: #31afff;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
&-fade {
|
|
126
|
+
overflow: hidden;
|
|
127
|
+
transition: all 0.3s;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
&-fade-appear-prepare {
|
|
131
|
+
pointer-events: none;
|
|
132
|
+
opacity: 0 !important;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
&-fade-appear-start {
|
|
136
|
+
transform: translateX(100%);
|
|
137
|
+
opacity: 0;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
&-fade-appear-active {
|
|
141
|
+
transform: translateX(0);
|
|
142
|
+
opacity: 1;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// .fade-effect() {
|
|
146
|
+
// animation-duration: 0.3s;
|
|
147
|
+
// animation-timing-function: cubic-bezier(0.55, 0, 0.55, 0.2);
|
|
148
|
+
// animation-fill-mode: both;
|
|
149
|
+
// }
|
|
150
|
+
|
|
151
|
+
// &-fade-appear,
|
|
152
|
+
// &-fade-enter {
|
|
153
|
+
// opacity: 0;
|
|
154
|
+
// animation-play-state: paused;
|
|
155
|
+
// .fade-effect();
|
|
156
|
+
// }
|
|
157
|
+
|
|
158
|
+
// &-fade-leave {
|
|
159
|
+
// .fade-effect();
|
|
160
|
+
// animation-play-state: paused;
|
|
161
|
+
// }
|
|
162
|
+
|
|
163
|
+
// &-fade-appear&-fade-appear-active,
|
|
164
|
+
// &-fade-enter&-fade-enter-active {
|
|
165
|
+
// animation-name: rcNotificationFadeIn;
|
|
166
|
+
// animation-play-state: running;
|
|
167
|
+
// }
|
|
168
|
+
|
|
169
|
+
// &-fade-leave&-fade-leave-active {
|
|
170
|
+
// animation-name: rcDialogFadeOut;
|
|
171
|
+
// animation-play-state: running;
|
|
172
|
+
// }
|
|
173
|
+
|
|
174
|
+
// @keyframes rcNotificationFadeIn {
|
|
175
|
+
// 0% {
|
|
176
|
+
// opacity: 0;
|
|
177
|
+
// }
|
|
178
|
+
// 100% {
|
|
179
|
+
// opacity: 1;
|
|
180
|
+
// }
|
|
181
|
+
// }
|
|
182
|
+
|
|
183
|
+
// @keyframes rcDialogFadeOut {
|
|
184
|
+
// 0% {
|
|
185
|
+
// opacity: 1;
|
|
186
|
+
// }
|
|
187
|
+
// 100% {
|
|
188
|
+
// opacity: 0;
|
|
189
|
+
// }
|
|
190
|
+
// }
|
|
191
|
+
|
|
192
|
+
// ========================= Stack =========================
|
|
193
|
+
&-stack {
|
|
194
|
+
& > .@{notificationPrefixCls}-notice {
|
|
195
|
+
&-wrapper {
|
|
196
|
+
transition: all 0.3s;
|
|
197
|
+
position: absolute;
|
|
198
|
+
top: 12px;
|
|
199
|
+
opacity: 1;
|
|
200
|
+
|
|
201
|
+
&:not(:nth-last-child(-n + 3)) {
|
|
202
|
+
opacity: 0;
|
|
203
|
+
right: 34px;
|
|
204
|
+
width: 252px;
|
|
205
|
+
overflow: hidden;
|
|
206
|
+
color: transparent;
|
|
207
|
+
pointer-events: none;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
&:nth-last-child(1) {
|
|
211
|
+
right: 10px;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
&:nth-last-child(2) {
|
|
215
|
+
right: 18px;
|
|
216
|
+
width: 284px;
|
|
217
|
+
color: transparent;
|
|
218
|
+
overflow: hidden;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
&:nth-last-child(3) {
|
|
222
|
+
right: 26px;
|
|
223
|
+
width: 268px;
|
|
224
|
+
color: transparent;
|
|
225
|
+
overflow: hidden;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
&&-expanded {
|
|
231
|
+
& > .@{notificationPrefixCls}-notice {
|
|
232
|
+
&-wrapper {
|
|
233
|
+
&:not(:nth-last-child(-n + 1)) {
|
|
234
|
+
opacity: 1;
|
|
235
|
+
width: 300px;
|
|
236
|
+
right: 10px;
|
|
237
|
+
overflow: unset;
|
|
238
|
+
color: inherit;
|
|
239
|
+
pointer-events: auto;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
&::before {
|
|
243
|
+
content: "";
|
|
244
|
+
position: absolute;
|
|
245
|
+
left: 0;
|
|
246
|
+
right: 0;
|
|
247
|
+
top: -16px;
|
|
248
|
+
width: 100%;
|
|
249
|
+
height: calc(100% + 32px);
|
|
250
|
+
background: transparent;
|
|
251
|
+
pointer-events: auto;
|
|
252
|
+
color: rgb(0,0,0);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
&.@{notificationPrefixCls}-bottomRight {
|
|
259
|
+
& > .@{notificationPrefixCls}-notice-wrapper {
|
|
260
|
+
top: unset;
|
|
261
|
+
bottom: 12px;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { useNotification } from '../src'
|
|
3
|
+
import motion from './motion.ts'
|
|
4
|
+
import './index.less'
|
|
5
|
+
|
|
6
|
+
const [notice, contextHolder] = useNotification({ maxCount: 3, motion })
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<template>
|
|
10
|
+
<button
|
|
11
|
+
@click="() => {
|
|
12
|
+
notice.open({
|
|
13
|
+
content: `${new Date().toISOString()}`,
|
|
14
|
+
});
|
|
15
|
+
}"
|
|
16
|
+
>
|
|
17
|
+
Max Count
|
|
18
|
+
</button>
|
|
19
|
+
<contextHolder />
|
|
20
|
+
</template>
|
|
21
|
+
|
|
22
|
+
<style scoped>
|
|
23
|
+
|
|
24
|
+
</style>
|
package/docs/motion.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { TransitionGroupProps } from 'vue'
|
|
2
|
+
|
|
3
|
+
const motion: TransitionGroupProps = {
|
|
4
|
+
appear: true,
|
|
5
|
+
name: 'vc-notification-fade',
|
|
6
|
+
// enterFromClass: 'vc-notification-fade-appear-start vc-notification-fade-appear-prepare',
|
|
7
|
+
// enterActiveClass: 'vc-notification-fade',
|
|
8
|
+
// enterToClass: 'vc-notification-fade-appear-active',
|
|
9
|
+
// leaveFromClass: 'vc-notification-fade-appear-active',
|
|
10
|
+
// leaveToClass: 'vc-notification-fade-appear-start vc-notification-fade-appear-prepare',
|
|
11
|
+
// leaveActiveClass: 'vc-notification-fade vc-notification-fade-appear-leave',
|
|
12
|
+
// moveClass: 'vc-notification-fade',
|
|
13
|
+
onBeforeLeave: (el) => {
|
|
14
|
+
const _el = el as HTMLDivElement
|
|
15
|
+
_el.style.height = `${_el.offsetHeight}px`
|
|
16
|
+
},
|
|
17
|
+
onLeave(el) {
|
|
18
|
+
setTimeout(() => {
|
|
19
|
+
const _el = el as HTMLDivElement
|
|
20
|
+
_el.style.height = '0px'
|
|
21
|
+
_el.style.opacity = '1'
|
|
22
|
+
_el.style.margin = '0px'
|
|
23
|
+
})
|
|
24
|
+
},
|
|
25
|
+
onAfterLeave(el) {
|
|
26
|
+
const _el = el as HTMLDivElement
|
|
27
|
+
_el.style.height = ''
|
|
28
|
+
_el.style.opacity = ''
|
|
29
|
+
_el.style.margin = ''
|
|
30
|
+
},
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export default motion
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import Context from './context.vue'
|
|
3
|
+
import Hooks from './hooks.vue'
|
|
4
|
+
import MaxCount from './maxCount.vue'
|
|
5
|
+
import ShowProgress from './showProgress.vue'
|
|
6
|
+
import Stack from './stack.vue'
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<template>
|
|
10
|
+
<Story title="Notification">
|
|
11
|
+
<Variant title="Context">
|
|
12
|
+
<Context />
|
|
13
|
+
</Variant>
|
|
14
|
+
|
|
15
|
+
<Variant title="Hooks">
|
|
16
|
+
<Hooks />
|
|
17
|
+
</Variant>
|
|
18
|
+
|
|
19
|
+
<Variant title="MaxCount">
|
|
20
|
+
<MaxCount />
|
|
21
|
+
</Variant>
|
|
22
|
+
|
|
23
|
+
<Variant title="ShowProgress">
|
|
24
|
+
<ShowProgress />
|
|
25
|
+
</Variant>
|
|
26
|
+
|
|
27
|
+
<Variant title="Stack">
|
|
28
|
+
<Stack />
|
|
29
|
+
</Variant>
|
|
30
|
+
</Story>
|
|
31
|
+
</template>
|