@v-c/notification 2.0.0-rc.2 → 2.0.0-rc.3

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.
@@ -5,9 +5,32 @@ import useStack from "../hooks/useStack.js";
5
5
  import Content from "./Content.js";
6
6
  import { TransitionGroup, computed, createVNode, defineComponent, isVNode, mergeProps, ref, shallowRef, toRef, watch, watchEffect } from "vue";
7
7
  import { clsx } from "@v-c/util";
8
- import { getTransitionGroupProps } from "@v-c/util/dist/utils/transition";
9
8
  import { unrefElement } from "@v-c/util/dist/vueuse/unref-element";
10
9
  //#region src/NotificationList/index.tsx
10
+ /**
11
+ * Map Vue's TransitionGroup enter/leave class hooks onto the rc-motion
12
+ * style class names that antdv-next 6.4.0 notification styles target
13
+ * (-enter-start / -enter-active / -leave-start / -leave-active).
14
+ *
15
+ * The shared @v-c/util getTransitionGroupProps puts -leave-active in the
16
+ * leaveActiveClass, which means the notice jumps straight to opacity:0
17
+ * on leave without animating. Wire each phase to the correct rc-motion
18
+ * suffix so the opacity/transform transition runs.
19
+ */
20
+ function buildMotionGroupProps(name, override) {
21
+ return {
22
+ name,
23
+ appear: true,
24
+ enterFromClass: `${name} ${name}-enter ${name}-appear ${name}-enter-start ${name}-appear-start`,
25
+ enterActiveClass: `${name} ${name}-enter ${name}-appear`,
26
+ enterToClass: `${name} ${name}-enter ${name}-appear ${name}-enter-active ${name}-appear-active`,
27
+ leaveFromClass: `${name} ${name}-leave ${name}-leave-start`,
28
+ leaveActiveClass: `${name} ${name}-leave`,
29
+ leaveToClass: `${name} ${name}-leave ${name}-leave-active`,
30
+ moveClass: `${name} ${name}-move`,
31
+ ...override
32
+ };
33
+ }
11
34
  function _isSlot(s) {
12
35
  return typeof s === "function" || Object.prototype.toString.call(s) === "[object Object]" && !isVNode(s);
13
36
  }
@@ -90,7 +113,7 @@ var NotificationList = /* @__PURE__ */ defineComponent((props, { attrs }) => {
90
113
  const listPrefixCls = `${prefixCls}-list`;
91
114
  const positionResult = position.value;
92
115
  let motionGroupProps = {};
93
- if (placementMotion.value) motionGroupProps = getTransitionGroupProps(placementMotion.value.name, placementMotion.value);
116
+ if (placementMotion.value?.name) motionGroupProps = buildMotionGroupProps(placementMotion.value.name, placementMotion.value);
94
117
  const renderItems = () => keys.value.map((config) => {
95
118
  const { key, placement: _itemPlacement, classNames: configClassNames, styles: configStyles, className: configClassName, style: configStyle, onClose: configOnClose, ...notificationConfig } = config;
96
119
  const strKey = String(key);
@@ -8,10 +8,6 @@ var defaults = { prefixCls: "vc-notification" };
8
8
  var Notifications = /* @__PURE__ */ defineComponent((props, { expose }) => {
9
9
  const configList = shallowRef([]);
10
10
  const onNoticeClose = (key) => {
11
- const config = configList.value.find((item) => item.key === key);
12
- const closable = config?.closable;
13
- (closable && typeof closable === "object" ? closable : null)?.onClose?.();
14
- config?.onClose?.();
15
11
  configList.value = configList.value.filter((item) => item.key !== key);
16
12
  };
17
13
  expose({
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@v-c/notification",
3
3
  "type": "module",
4
- "version": "2.0.0-rc.2",
4
+ "version": "2.0.0-rc.3",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -7,9 +7,37 @@ import type {
7
7
  NotificationStyles as NoticeStyles,
8
8
  } from '../Notification'
9
9
  import { clsx } from '@v-c/util'
10
- import { getTransitionGroupProps } from '@v-c/util/dist/utils/transition'
11
10
  import { unrefElement } from '@v-c/util/dist/vueuse/unref-element'
12
11
  import { computed, defineComponent, ref, shallowRef, toRef, TransitionGroup, watch, watchEffect } from 'vue'
12
+
13
+ /**
14
+ * Map Vue's TransitionGroup enter/leave class hooks onto the rc-motion
15
+ * style class names that antdv-next 6.4.0 notification styles target
16
+ * (-enter-start / -enter-active / -leave-start / -leave-active).
17
+ *
18
+ * The shared @v-c/util getTransitionGroupProps puts -leave-active in the
19
+ * leaveActiveClass, which means the notice jumps straight to opacity:0
20
+ * on leave without animating. Wire each phase to the correct rc-motion
21
+ * suffix so the opacity/transform transition runs.
22
+ */
23
+ function buildMotionGroupProps(name: string, override?: Partial<TransitionGroupProps>): TransitionGroupProps {
24
+ return {
25
+ name,
26
+ appear: true,
27
+ // ENTER: from = opacity 0 (-enter-start / -appear-start)
28
+ // to = opacity 1 (-enter-active / -appear-active)
29
+ enterFromClass: `${name} ${name}-enter ${name}-appear ${name}-enter-start ${name}-appear-start`,
30
+ enterActiveClass: `${name} ${name}-enter ${name}-appear`,
31
+ enterToClass: `${name} ${name}-enter ${name}-appear ${name}-enter-active ${name}-appear-active`,
32
+ // LEAVE: from = opacity 1 (-leave-start)
33
+ // to = opacity 0 (-leave-active)
34
+ leaveFromClass: `${name} ${name}-leave ${name}-leave-start`,
35
+ leaveActiveClass: `${name} ${name}-leave`,
36
+ leaveToClass: `${name} ${name}-leave ${name}-leave-active`,
37
+ moveClass: `${name} ${name}-move`,
38
+ ...override,
39
+ }
40
+ }
13
41
  import useListPosition from '../hooks/useListPosition'
14
42
  import useStack from '../hooks/useStack'
15
43
  import Notification from '../Notification'
@@ -185,8 +213,8 @@ const NotificationList = defineComponent<NotificationListProps>(
185
213
  const positionResult = position.value
186
214
 
187
215
  let motionGroupProps: TransitionGroupProps = {}
188
- if (placementMotion.value) {
189
- motionGroupProps = getTransitionGroupProps(placementMotion.value.name!, placementMotion.value)
216
+ if (placementMotion.value?.name) {
217
+ motionGroupProps = buildMotionGroupProps(placementMotion.value.name, placementMotion.value)
190
218
  }
191
219
 
192
220
  const renderItems = () =>
@@ -42,11 +42,6 @@ const Notifications = defineComponent<NotificationsProps>(
42
42
  const configList = shallowRef<NotificationListConfig[]>([])
43
43
 
44
44
  const onNoticeClose = (key: Key) => {
45
- const config = configList.value.find(item => item.key === key)
46
- const closable = config?.closable
47
- const closableObj = closable && typeof closable === 'object' ? closable : null
48
- closableObj?.onClose?.()
49
- config?.onClose?.()
50
45
  configList.value = configList.value.filter(item => item.key !== key)
51
46
  }
52
47
 
@@ -0,0 +1,70 @@
1
+ import { mount } from '@vue/test-utils'
2
+ import { nextTick } from 'vue'
3
+ import { afterEach, describe, expect, it, vi } from 'vitest'
4
+ import Notifications from '../src/Notifications'
5
+
6
+ describe('notification', () => {
7
+ afterEach(() => {
8
+ document.body.innerHTML = ''
9
+ })
10
+
11
+ it('calls close callbacks once when notice close button is clicked', async () => {
12
+ const onClose = vi.fn()
13
+ const closableOnClose = vi.fn()
14
+ const wrapper = mount(Notifications, {
15
+ props: {
16
+ container: document.body,
17
+ },
18
+ attachTo: document.body,
19
+ })
20
+
21
+ wrapper.vm.open({
22
+ key: 'notice',
23
+ title: 'Notice',
24
+ duration: false,
25
+ closable: {
26
+ closeIcon: 'x',
27
+ onClose: closableOnClose,
28
+ },
29
+ onClose,
30
+ })
31
+
32
+ await nextTick()
33
+ await nextTick()
34
+ await document.querySelector<HTMLButtonElement>('.vc-notification-notice-close')!.click()
35
+ await nextTick()
36
+
37
+ expect(closableOnClose).toHaveBeenCalledTimes(1)
38
+ expect(onClose).toHaveBeenCalledTimes(1)
39
+ })
40
+
41
+ it('does not call notice close callbacks when closed by api', async () => {
42
+ const onClose = vi.fn()
43
+ const closableOnClose = vi.fn()
44
+ const wrapper = mount(Notifications, {
45
+ props: {
46
+ container: document.body,
47
+ },
48
+ attachTo: document.body,
49
+ })
50
+
51
+ wrapper.vm.open({
52
+ key: 'notice',
53
+ title: 'Notice',
54
+ duration: false,
55
+ closable: {
56
+ closeIcon: 'x',
57
+ onClose: closableOnClose,
58
+ },
59
+ onClose,
60
+ })
61
+
62
+ await nextTick()
63
+ await nextTick()
64
+ wrapper.vm.close('notice')
65
+ await nextTick()
66
+
67
+ expect(closableOnClose).not.toHaveBeenCalled()
68
+ expect(onClose).not.toHaveBeenCalled()
69
+ })
70
+ })
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
  )