@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.
Files changed (67) hide show
  1. package/dist/Notification.d.ts +286 -0
  2. package/dist/Notification.js +237 -0
  3. package/dist/NotificationList/Content.d.ts +88 -0
  4. package/dist/NotificationList/Content.js +74 -0
  5. package/dist/NotificationList/index.d.ts +156 -0
  6. package/dist/NotificationList/index.js +204 -0
  7. package/dist/NotificationProvider.d.ts +20 -1
  8. package/dist/NotificationProvider.js +16 -3
  9. package/dist/Notifications.d.ts +136 -8
  10. package/dist/Notifications.js +118 -109
  11. package/dist/Progress.d.ts +8 -0
  12. package/dist/Progress.js +18 -0
  13. package/dist/hooks/useClosable.d.ts +22 -0
  14. package/dist/hooks/useClosable.js +33 -0
  15. package/dist/hooks/useListPosition/index.d.ts +17 -0
  16. package/dist/hooks/useListPosition/index.js +48 -0
  17. package/dist/hooks/useListPosition/useSizes.d.ts +13 -0
  18. package/dist/hooks/useListPosition/useSizes.js +29 -0
  19. package/dist/hooks/useNoticeTimer.d.ts +6 -0
  20. package/dist/hooks/useNoticeTimer.js +71 -0
  21. package/dist/hooks/useNotification.d.ts +8 -24
  22. package/dist/hooks/useNotification.js +33 -22
  23. package/dist/hooks/useStack.d.ts +8 -4
  24. package/dist/hooks/useStack.js +15 -18
  25. package/dist/index.d.ts +7 -5
  26. package/dist/index.js +5 -3
  27. package/docs/context.vue +1 -1
  28. package/docs/hooks.vue +4 -4
  29. package/docs/index.less +62 -143
  30. package/docs/maxCount.vue +1 -1
  31. package/docs/showProgress.vue +2 -2
  32. package/docs/stack.vue +1 -1
  33. package/package.json +5 -4
  34. package/src/Notification.tsx +363 -0
  35. package/src/NotificationList/Content.tsx +84 -0
  36. package/src/NotificationList/index.tsx +298 -0
  37. package/src/NotificationProvider.tsx +23 -3
  38. package/src/Notifications.tsx +103 -87
  39. package/src/Progress.tsx +23 -0
  40. package/src/hooks/useClosable.ts +54 -0
  41. package/src/hooks/useListPosition/index.ts +85 -0
  42. package/src/hooks/useListPosition/useSizes.ts +42 -0
  43. package/src/hooks/useNoticeTimer.ts +96 -0
  44. package/src/hooks/useNotification.tsx +54 -80
  45. package/src/hooks/useStack.ts +26 -18
  46. package/src/index.ts +31 -5
  47. package/tests/index.spec.tsx +200 -0
  48. package/vite.config.ts +4 -3
  49. package/vitest.config.ts +3 -1
  50. package/dist/Notice.cjs +0 -235
  51. package/dist/Notice.d.ts +0 -15
  52. package/dist/Notice.js +0 -227
  53. package/dist/NoticeList.cjs +0 -170
  54. package/dist/NoticeList.d.ts +0 -13
  55. package/dist/NoticeList.js +0 -164
  56. package/dist/NotificationProvider.cjs +0 -14
  57. package/dist/Notifications.cjs +0 -146
  58. package/dist/_virtual/rolldown_runtime.cjs +0 -21
  59. package/dist/hooks/useNotification.cjs +0 -93
  60. package/dist/hooks/useStack.cjs +0 -27
  61. package/dist/index.cjs +0 -7
  62. package/dist/interface.cjs +0 -1
  63. package/dist/interface.d.ts +0 -55
  64. package/dist/interface.js +0 -0
  65. package/src/Notice.tsx +0 -212
  66. package/src/NoticeList.tsx +0 -219
  67. 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 entry = fg.sync(['src/**/*.ts', 'src/**/*.tsx', '!src/**/*.test.ts', '!src/**/tests'])
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
@@ -4,6 +4,8 @@ import configShared from '../../vitest.config'
4
4
  export default mergeConfig(
5
5
  configShared,
6
6
  defineProject({
7
-
7
+ test: {
8
+ environment: 'jsdom',
9
+ },
8
10
  }),
9
11
  )
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 };