@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
|
@@ -0,0 +1,200 @@
|
|
|
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
|
+
})
|
package/vite.config.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import type { UserConfig } from 'vite'
|
|
2
|
-
import fg from 'fast-glob'
|
|
3
2
|
import { defineConfig, mergeConfig } from 'vite'
|
|
4
|
-
import { buildCommon } from '../../scripts/build.common'
|
|
3
|
+
import { buildCommon, resolveBuildEntries } from '../../scripts/build.common'
|
|
5
4
|
|
|
6
|
-
const
|
|
5
|
+
const packageRoot = new URL('.', import.meta.url)
|
|
6
|
+
const entry = resolveBuildEntries(packageRoot, ['src/**/*.ts', 'src/**/*.tsx', '!src/**/*.test.ts', '!src/**/tests'])
|
|
7
7
|
|
|
8
8
|
export default defineConfig({
|
|
9
9
|
...mergeConfig(buildCommon({
|
|
10
|
+
packageRoot,
|
|
10
11
|
external: ['vue', 'classnames', /^@v-c\/util/],
|
|
11
12
|
}), {
|
|
12
13
|
build: {
|
package/vitest.config.ts
CHANGED
package/dist/Notice.cjs
DELETED
|
@@ -1,235 +0,0 @@
|
|
|
1
|
-
Object.defineProperties(exports, {
|
|
2
|
-
__esModule: { value: true },
|
|
3
|
-
[Symbol.toStringTag]: { value: "Module" }
|
|
4
|
-
});
|
|
5
|
-
const require_rolldown_runtime = require("./_virtual/rolldown_runtime.cjs");
|
|
6
|
-
let vue = require("vue");
|
|
7
|
-
let _v_c_util = require("@v-c/util");
|
|
8
|
-
let _v_c_util_dist_KeyCode = require("@v-c/util/dist/KeyCode");
|
|
9
|
-
_v_c_util_dist_KeyCode = require_rolldown_runtime.__toESM(_v_c_util_dist_KeyCode);
|
|
10
|
-
let _v_c_util_dist_pickAttrs = require("@v-c/util/dist/pickAttrs");
|
|
11
|
-
_v_c_util_dist_pickAttrs = require_rolldown_runtime.__toESM(_v_c_util_dist_pickAttrs);
|
|
12
|
-
var defaults = {
|
|
13
|
-
duration: 4.5,
|
|
14
|
-
pauseOnHover: true,
|
|
15
|
-
closeIcon: "x"
|
|
16
|
-
};
|
|
17
|
-
var Notify = /* @__PURE__ */ (0, vue.defineComponent)((props, { attrs }) => {
|
|
18
|
-
const hovering = (0, vue.shallowRef)(false);
|
|
19
|
-
const percent = (0, vue.shallowRef)(0);
|
|
20
|
-
const spentTime = (0, vue.shallowRef)(0);
|
|
21
|
-
const mergedHovering = (0, vue.computed)(() => props.hovering || hovering.value);
|
|
22
|
-
const mergedDuration = (0, vue.computed)(() => {
|
|
23
|
-
if (typeof props.duration === "number") return props.duration;
|
|
24
|
-
if (props.duration === void 0) return defaults.duration;
|
|
25
|
-
return 0;
|
|
26
|
-
});
|
|
27
|
-
const mergedPauseOnHover = (0, vue.computed)(() => props.pauseOnHover === void 0 ? defaults.pauseOnHover : props.pauseOnHover);
|
|
28
|
-
const mergedShowProgress = (0, vue.computed)(() => mergedDuration.value > 0 && props.showProgress);
|
|
29
|
-
const mergedCloseIcon = (0, vue.computed)(() => props.closeIcon ?? defaults.closeIcon);
|
|
30
|
-
const onInternalClose = () => {
|
|
31
|
-
props.onNoticeClose?.(props.eventKey);
|
|
32
|
-
};
|
|
33
|
-
const onCloseKeyDown = (e) => {
|
|
34
|
-
if (e.key === "Enter" || e.code === "Enter" || e.keyCode === _v_c_util_dist_KeyCode.default.ENTER) onInternalClose();
|
|
35
|
-
};
|
|
36
|
-
(0, vue.watch)([
|
|
37
|
-
() => props.times,
|
|
38
|
-
mergedDuration,
|
|
39
|
-
mergedHovering
|
|
40
|
-
], (_n, _, onCleanup) => {
|
|
41
|
-
const duration = mergedDuration.value;
|
|
42
|
-
const hoveringValue = mergedHovering.value;
|
|
43
|
-
const pauseOnHover = mergedPauseOnHover.value;
|
|
44
|
-
if (!hoveringValue && duration > 0) {
|
|
45
|
-
const start = Date.now() - spentTime.value;
|
|
46
|
-
const timeoutId = window.setTimeout(() => {
|
|
47
|
-
onInternalClose();
|
|
48
|
-
}, duration * 1e3 - spentTime.value);
|
|
49
|
-
onCleanup(() => {
|
|
50
|
-
if (pauseOnHover) clearTimeout(timeoutId);
|
|
51
|
-
spentTime.value = Date.now() - start;
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
}, { immediate: true });
|
|
55
|
-
(0, vue.watch)([
|
|
56
|
-
() => props.times,
|
|
57
|
-
mergedDuration,
|
|
58
|
-
spentTime,
|
|
59
|
-
mergedHovering,
|
|
60
|
-
mergedShowProgress
|
|
61
|
-
], (_n, _, onCleanup) => {
|
|
62
|
-
const hoveringValue = mergedHovering.value;
|
|
63
|
-
const showProgress = mergedShowProgress.value;
|
|
64
|
-
const pauseOnHover = mergedPauseOnHover.value;
|
|
65
|
-
const duration = mergedDuration.value;
|
|
66
|
-
const baseSpentTime = spentTime.value;
|
|
67
|
-
if (!hoveringValue && showProgress && (pauseOnHover || baseSpentTime === 0)) {
|
|
68
|
-
const start = performance.now();
|
|
69
|
-
let animationFrame = 0;
|
|
70
|
-
const calculate = () => {
|
|
71
|
-
cancelAnimationFrame(animationFrame);
|
|
72
|
-
animationFrame = requestAnimationFrame((timestamp) => {
|
|
73
|
-
const runtime = timestamp + baseSpentTime - start;
|
|
74
|
-
const progress = Math.min(runtime / (duration * 1e3), 1);
|
|
75
|
-
percent.value = progress * 100;
|
|
76
|
-
if (progress < 1) calculate();
|
|
77
|
-
});
|
|
78
|
-
};
|
|
79
|
-
calculate();
|
|
80
|
-
onCleanup(() => {
|
|
81
|
-
if (pauseOnHover) cancelAnimationFrame(animationFrame);
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
}, { immediate: true });
|
|
85
|
-
return () => {
|
|
86
|
-
const { closable, prefixCls, props: divProps, onClick, content, className, style } = props;
|
|
87
|
-
const closableConfig = typeof closable === "object" && closable !== null ? closable : closable ? { closeIcon: mergedCloseIcon.value } : {};
|
|
88
|
-
const ariaProps = (0, _v_c_util_dist_pickAttrs.default)(closableConfig, true);
|
|
89
|
-
const validPercent = 100 - (percent.value <= 0 ? 0 : percent.value > 100 ? 100 : percent.value);
|
|
90
|
-
const noticePrefixCls = `${prefixCls}-notice`;
|
|
91
|
-
const mergedStyle = {
|
|
92
|
-
...typeof divProps?.style === "object" && divProps?.style ? divProps.style : {},
|
|
93
|
-
...typeof attrs.style === "object" && attrs.style ? attrs.style : {},
|
|
94
|
-
...typeof style === "object" && style ? style : {}
|
|
95
|
-
};
|
|
96
|
-
return (0, vue.createVNode)("div", (0, vue.mergeProps)(divProps, {
|
|
97
|
-
"class": (0, _v_c_util.classNames)(noticePrefixCls, className, attrs.class, { [`${noticePrefixCls}-closable`]: !!closable }),
|
|
98
|
-
"style": mergedStyle,
|
|
99
|
-
"onMouseenter": (e) => {
|
|
100
|
-
hovering.value = true;
|
|
101
|
-
divProps?.onMouseEnter?.(e);
|
|
102
|
-
},
|
|
103
|
-
"onMouseleave": (e) => {
|
|
104
|
-
hovering.value = false;
|
|
105
|
-
divProps?.onMouseLeave?.(e);
|
|
106
|
-
},
|
|
107
|
-
"onClick": onClick
|
|
108
|
-
}), [
|
|
109
|
-
(0, vue.createVNode)("div", { "class": `${noticePrefixCls}-content` }, [content]),
|
|
110
|
-
closable && (0, vue.createVNode)("button", (0, vue.mergeProps)({
|
|
111
|
-
"type": "button",
|
|
112
|
-
"class": `${noticePrefixCls}-close`,
|
|
113
|
-
"onKeydown": onCloseKeyDown,
|
|
114
|
-
"aria-label": "Close"
|
|
115
|
-
}, ariaProps, { "onClick": (e) => {
|
|
116
|
-
e.preventDefault();
|
|
117
|
-
e.stopPropagation();
|
|
118
|
-
onInternalClose();
|
|
119
|
-
} }), [closableConfig.closeIcon ?? mergedCloseIcon.value]),
|
|
120
|
-
mergedShowProgress.value && (0, vue.createVNode)("progress", {
|
|
121
|
-
"class": `${noticePrefixCls}-progress`,
|
|
122
|
-
"max": "100",
|
|
123
|
-
"value": validPercent
|
|
124
|
-
}, [`${validPercent}%`])
|
|
125
|
-
]);
|
|
126
|
-
};
|
|
127
|
-
}, { props: {
|
|
128
|
-
prefixCls: {
|
|
129
|
-
type: String,
|
|
130
|
-
required: true,
|
|
131
|
-
default: void 0
|
|
132
|
-
},
|
|
133
|
-
eventKey: {
|
|
134
|
-
type: [String, Number],
|
|
135
|
-
required: true,
|
|
136
|
-
default: void 0
|
|
137
|
-
},
|
|
138
|
-
onClick: {
|
|
139
|
-
type: Function,
|
|
140
|
-
required: false,
|
|
141
|
-
default: void 0
|
|
142
|
-
},
|
|
143
|
-
onNoticeClose: {
|
|
144
|
-
type: Function,
|
|
145
|
-
required: false,
|
|
146
|
-
default: void 0
|
|
147
|
-
},
|
|
148
|
-
hovering: {
|
|
149
|
-
type: Boolean,
|
|
150
|
-
required: false,
|
|
151
|
-
default: void 0
|
|
152
|
-
},
|
|
153
|
-
props: {
|
|
154
|
-
type: Object,
|
|
155
|
-
required: false,
|
|
156
|
-
default: void 0
|
|
157
|
-
},
|
|
158
|
-
content: {
|
|
159
|
-
type: [
|
|
160
|
-
Object,
|
|
161
|
-
Function,
|
|
162
|
-
String,
|
|
163
|
-
Number,
|
|
164
|
-
null,
|
|
165
|
-
Boolean,
|
|
166
|
-
Array
|
|
167
|
-
],
|
|
168
|
-
required: false,
|
|
169
|
-
default: void 0
|
|
170
|
-
},
|
|
171
|
-
duration: {
|
|
172
|
-
type: [
|
|
173
|
-
Number,
|
|
174
|
-
Boolean,
|
|
175
|
-
null
|
|
176
|
-
],
|
|
177
|
-
required: false,
|
|
178
|
-
default: void 0
|
|
179
|
-
},
|
|
180
|
-
showProgress: {
|
|
181
|
-
type: Boolean,
|
|
182
|
-
required: false,
|
|
183
|
-
default: void 0
|
|
184
|
-
},
|
|
185
|
-
pauseOnHover: {
|
|
186
|
-
type: Boolean,
|
|
187
|
-
required: false,
|
|
188
|
-
default: void 0
|
|
189
|
-
},
|
|
190
|
-
closeIcon: {
|
|
191
|
-
type: [
|
|
192
|
-
Object,
|
|
193
|
-
Function,
|
|
194
|
-
String,
|
|
195
|
-
Number,
|
|
196
|
-
null,
|
|
197
|
-
Boolean,
|
|
198
|
-
Array
|
|
199
|
-
],
|
|
200
|
-
required: false,
|
|
201
|
-
default: void 0
|
|
202
|
-
},
|
|
203
|
-
closable: {
|
|
204
|
-
type: [Boolean, Object],
|
|
205
|
-
required: false,
|
|
206
|
-
default: void 0
|
|
207
|
-
},
|
|
208
|
-
className: {
|
|
209
|
-
type: String,
|
|
210
|
-
required: false,
|
|
211
|
-
default: void 0
|
|
212
|
-
},
|
|
213
|
-
style: {
|
|
214
|
-
type: Object,
|
|
215
|
-
required: false,
|
|
216
|
-
default: void 0
|
|
217
|
-
},
|
|
218
|
-
classNames: {
|
|
219
|
-
type: Object,
|
|
220
|
-
required: false,
|
|
221
|
-
default: void 0
|
|
222
|
-
},
|
|
223
|
-
styles: {
|
|
224
|
-
type: Object,
|
|
225
|
-
required: false,
|
|
226
|
-
default: void 0
|
|
227
|
-
},
|
|
228
|
-
times: {
|
|
229
|
-
type: Number,
|
|
230
|
-
required: false,
|
|
231
|
-
default: void 0
|
|
232
|
-
}
|
|
233
|
-
} });
|
|
234
|
-
var Notice_default = Notify;
|
|
235
|
-
exports.default = Notice_default;
|
package/dist/Notice.d.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { Key, NoticeConfig } from './interface.ts';
|
|
2
|
-
export interface NoticeProps extends Omit<NoticeConfig, 'onClose'> {
|
|
3
|
-
prefixCls: string;
|
|
4
|
-
eventKey: Key;
|
|
5
|
-
onClick?: (event: Event) => void;
|
|
6
|
-
onNoticeClose?: (key: Key) => void;
|
|
7
|
-
hovering?: boolean;
|
|
8
|
-
props?: Record<string, any>;
|
|
9
|
-
}
|
|
10
|
-
declare const Notify: import('vue').DefineSetupFnComponent<NoticeProps & {
|
|
11
|
-
times?: number;
|
|
12
|
-
}, {}, {}, NoticeProps & {
|
|
13
|
-
times?: number;
|
|
14
|
-
} & {}, import('vue').PublicProps>;
|
|
15
|
-
export default Notify;
|
package/dist/Notice.js
DELETED
|
@@ -1,227 +0,0 @@
|
|
|
1
|
-
import { computed, createVNode, defineComponent, mergeProps, shallowRef, watch } from "vue";
|
|
2
|
-
import { classNames } from "@v-c/util";
|
|
3
|
-
import KeyCode from "@v-c/util/dist/KeyCode";
|
|
4
|
-
import pickAttrs from "@v-c/util/dist/pickAttrs";
|
|
5
|
-
var defaults = {
|
|
6
|
-
duration: 4.5,
|
|
7
|
-
pauseOnHover: true,
|
|
8
|
-
closeIcon: "x"
|
|
9
|
-
};
|
|
10
|
-
var Notice_default = /* @__PURE__ */ defineComponent((props, { attrs }) => {
|
|
11
|
-
const hovering = shallowRef(false);
|
|
12
|
-
const percent = shallowRef(0);
|
|
13
|
-
const spentTime = shallowRef(0);
|
|
14
|
-
const mergedHovering = computed(() => props.hovering || hovering.value);
|
|
15
|
-
const mergedDuration = computed(() => {
|
|
16
|
-
if (typeof props.duration === "number") return props.duration;
|
|
17
|
-
if (props.duration === void 0) return defaults.duration;
|
|
18
|
-
return 0;
|
|
19
|
-
});
|
|
20
|
-
const mergedPauseOnHover = computed(() => props.pauseOnHover === void 0 ? defaults.pauseOnHover : props.pauseOnHover);
|
|
21
|
-
const mergedShowProgress = computed(() => mergedDuration.value > 0 && props.showProgress);
|
|
22
|
-
const mergedCloseIcon = computed(() => props.closeIcon ?? defaults.closeIcon);
|
|
23
|
-
const onInternalClose = () => {
|
|
24
|
-
props.onNoticeClose?.(props.eventKey);
|
|
25
|
-
};
|
|
26
|
-
const onCloseKeyDown = (e) => {
|
|
27
|
-
if (e.key === "Enter" || e.code === "Enter" || e.keyCode === KeyCode.ENTER) onInternalClose();
|
|
28
|
-
};
|
|
29
|
-
watch([
|
|
30
|
-
() => props.times,
|
|
31
|
-
mergedDuration,
|
|
32
|
-
mergedHovering
|
|
33
|
-
], (_n, _, onCleanup) => {
|
|
34
|
-
const duration = mergedDuration.value;
|
|
35
|
-
const hoveringValue = mergedHovering.value;
|
|
36
|
-
const pauseOnHover = mergedPauseOnHover.value;
|
|
37
|
-
if (!hoveringValue && duration > 0) {
|
|
38
|
-
const start = Date.now() - spentTime.value;
|
|
39
|
-
const timeoutId = window.setTimeout(() => {
|
|
40
|
-
onInternalClose();
|
|
41
|
-
}, duration * 1e3 - spentTime.value);
|
|
42
|
-
onCleanup(() => {
|
|
43
|
-
if (pauseOnHover) clearTimeout(timeoutId);
|
|
44
|
-
spentTime.value = Date.now() - start;
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
}, { immediate: true });
|
|
48
|
-
watch([
|
|
49
|
-
() => props.times,
|
|
50
|
-
mergedDuration,
|
|
51
|
-
spentTime,
|
|
52
|
-
mergedHovering,
|
|
53
|
-
mergedShowProgress
|
|
54
|
-
], (_n, _, onCleanup) => {
|
|
55
|
-
const hoveringValue = mergedHovering.value;
|
|
56
|
-
const showProgress = mergedShowProgress.value;
|
|
57
|
-
const pauseOnHover = mergedPauseOnHover.value;
|
|
58
|
-
const duration = mergedDuration.value;
|
|
59
|
-
const baseSpentTime = spentTime.value;
|
|
60
|
-
if (!hoveringValue && showProgress && (pauseOnHover || baseSpentTime === 0)) {
|
|
61
|
-
const start = performance.now();
|
|
62
|
-
let animationFrame = 0;
|
|
63
|
-
const calculate = () => {
|
|
64
|
-
cancelAnimationFrame(animationFrame);
|
|
65
|
-
animationFrame = requestAnimationFrame((timestamp) => {
|
|
66
|
-
const runtime = timestamp + baseSpentTime - start;
|
|
67
|
-
const progress = Math.min(runtime / (duration * 1e3), 1);
|
|
68
|
-
percent.value = progress * 100;
|
|
69
|
-
if (progress < 1) calculate();
|
|
70
|
-
});
|
|
71
|
-
};
|
|
72
|
-
calculate();
|
|
73
|
-
onCleanup(() => {
|
|
74
|
-
if (pauseOnHover) cancelAnimationFrame(animationFrame);
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
}, { immediate: true });
|
|
78
|
-
return () => {
|
|
79
|
-
const { closable, prefixCls, props: divProps, onClick, content, className, style } = props;
|
|
80
|
-
const closableConfig = typeof closable === "object" && closable !== null ? closable : closable ? { closeIcon: mergedCloseIcon.value } : {};
|
|
81
|
-
const ariaProps = pickAttrs(closableConfig, true);
|
|
82
|
-
const validPercent = 100 - (percent.value <= 0 ? 0 : percent.value > 100 ? 100 : percent.value);
|
|
83
|
-
const noticePrefixCls = `${prefixCls}-notice`;
|
|
84
|
-
const mergedStyle = {
|
|
85
|
-
...typeof divProps?.style === "object" && divProps?.style ? divProps.style : {},
|
|
86
|
-
...typeof attrs.style === "object" && attrs.style ? attrs.style : {},
|
|
87
|
-
...typeof style === "object" && style ? style : {}
|
|
88
|
-
};
|
|
89
|
-
return createVNode("div", mergeProps(divProps, {
|
|
90
|
-
"class": classNames(noticePrefixCls, className, attrs.class, { [`${noticePrefixCls}-closable`]: !!closable }),
|
|
91
|
-
"style": mergedStyle,
|
|
92
|
-
"onMouseenter": (e) => {
|
|
93
|
-
hovering.value = true;
|
|
94
|
-
divProps?.onMouseEnter?.(e);
|
|
95
|
-
},
|
|
96
|
-
"onMouseleave": (e) => {
|
|
97
|
-
hovering.value = false;
|
|
98
|
-
divProps?.onMouseLeave?.(e);
|
|
99
|
-
},
|
|
100
|
-
"onClick": onClick
|
|
101
|
-
}), [
|
|
102
|
-
createVNode("div", { "class": `${noticePrefixCls}-content` }, [content]),
|
|
103
|
-
closable && createVNode("button", mergeProps({
|
|
104
|
-
"type": "button",
|
|
105
|
-
"class": `${noticePrefixCls}-close`,
|
|
106
|
-
"onKeydown": onCloseKeyDown,
|
|
107
|
-
"aria-label": "Close"
|
|
108
|
-
}, ariaProps, { "onClick": (e) => {
|
|
109
|
-
e.preventDefault();
|
|
110
|
-
e.stopPropagation();
|
|
111
|
-
onInternalClose();
|
|
112
|
-
} }), [closableConfig.closeIcon ?? mergedCloseIcon.value]),
|
|
113
|
-
mergedShowProgress.value && createVNode("progress", {
|
|
114
|
-
"class": `${noticePrefixCls}-progress`,
|
|
115
|
-
"max": "100",
|
|
116
|
-
"value": validPercent
|
|
117
|
-
}, [`${validPercent}%`])
|
|
118
|
-
]);
|
|
119
|
-
};
|
|
120
|
-
}, { props: {
|
|
121
|
-
prefixCls: {
|
|
122
|
-
type: String,
|
|
123
|
-
required: true,
|
|
124
|
-
default: void 0
|
|
125
|
-
},
|
|
126
|
-
eventKey: {
|
|
127
|
-
type: [String, Number],
|
|
128
|
-
required: true,
|
|
129
|
-
default: void 0
|
|
130
|
-
},
|
|
131
|
-
onClick: {
|
|
132
|
-
type: Function,
|
|
133
|
-
required: false,
|
|
134
|
-
default: void 0
|
|
135
|
-
},
|
|
136
|
-
onNoticeClose: {
|
|
137
|
-
type: Function,
|
|
138
|
-
required: false,
|
|
139
|
-
default: void 0
|
|
140
|
-
},
|
|
141
|
-
hovering: {
|
|
142
|
-
type: Boolean,
|
|
143
|
-
required: false,
|
|
144
|
-
default: void 0
|
|
145
|
-
},
|
|
146
|
-
props: {
|
|
147
|
-
type: Object,
|
|
148
|
-
required: false,
|
|
149
|
-
default: void 0
|
|
150
|
-
},
|
|
151
|
-
content: {
|
|
152
|
-
type: [
|
|
153
|
-
Object,
|
|
154
|
-
Function,
|
|
155
|
-
String,
|
|
156
|
-
Number,
|
|
157
|
-
null,
|
|
158
|
-
Boolean,
|
|
159
|
-
Array
|
|
160
|
-
],
|
|
161
|
-
required: false,
|
|
162
|
-
default: void 0
|
|
163
|
-
},
|
|
164
|
-
duration: {
|
|
165
|
-
type: [
|
|
166
|
-
Number,
|
|
167
|
-
Boolean,
|
|
168
|
-
null
|
|
169
|
-
],
|
|
170
|
-
required: false,
|
|
171
|
-
default: void 0
|
|
172
|
-
},
|
|
173
|
-
showProgress: {
|
|
174
|
-
type: Boolean,
|
|
175
|
-
required: false,
|
|
176
|
-
default: void 0
|
|
177
|
-
},
|
|
178
|
-
pauseOnHover: {
|
|
179
|
-
type: Boolean,
|
|
180
|
-
required: false,
|
|
181
|
-
default: void 0
|
|
182
|
-
},
|
|
183
|
-
closeIcon: {
|
|
184
|
-
type: [
|
|
185
|
-
Object,
|
|
186
|
-
Function,
|
|
187
|
-
String,
|
|
188
|
-
Number,
|
|
189
|
-
null,
|
|
190
|
-
Boolean,
|
|
191
|
-
Array
|
|
192
|
-
],
|
|
193
|
-
required: false,
|
|
194
|
-
default: void 0
|
|
195
|
-
},
|
|
196
|
-
closable: {
|
|
197
|
-
type: [Boolean, Object],
|
|
198
|
-
required: false,
|
|
199
|
-
default: void 0
|
|
200
|
-
},
|
|
201
|
-
className: {
|
|
202
|
-
type: String,
|
|
203
|
-
required: false,
|
|
204
|
-
default: void 0
|
|
205
|
-
},
|
|
206
|
-
style: {
|
|
207
|
-
type: Object,
|
|
208
|
-
required: false,
|
|
209
|
-
default: void 0
|
|
210
|
-
},
|
|
211
|
-
classNames: {
|
|
212
|
-
type: Object,
|
|
213
|
-
required: false,
|
|
214
|
-
default: void 0
|
|
215
|
-
},
|
|
216
|
-
styles: {
|
|
217
|
-
type: Object,
|
|
218
|
-
required: false,
|
|
219
|
-
default: void 0
|
|
220
|
-
},
|
|
221
|
-
times: {
|
|
222
|
-
type: Number,
|
|
223
|
-
required: false,
|
|
224
|
-
default: void 0
|
|
225
|
-
}
|
|
226
|
-
} });
|
|
227
|
-
export { Notice_default as default };
|