@kaizen/components 1.35.2 → 1.36.0

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 (125) hide show
  1. package/dist/cjs/KaizenProvider/KaizenProvider.cjs +6 -1
  2. package/dist/cjs/KaizenProvider/KaizenProvider.cjs.map +1 -1
  3. package/dist/cjs/Modal/ContextModal/ContextModal.cjs +9 -6
  4. package/dist/cjs/Modal/ContextModal/ContextModal.cjs.map +1 -1
  5. package/dist/cjs/Notification/ToastNotification/ToastNotification/ToastNotification.cjs +33 -0
  6. package/dist/cjs/Notification/ToastNotification/ToastNotification/ToastNotification.cjs.map +1 -0
  7. package/dist/cjs/Notification/ToastNotification/ToastNotificationsList/ToastNotificationsList.cjs +36 -0
  8. package/dist/cjs/Notification/ToastNotification/ToastNotificationsList/ToastNotificationsList.cjs.map +1 -0
  9. package/dist/cjs/Notification/ToastNotification/ToastNotificationsList/ToastNotificationsList.module.scss.cjs +7 -0
  10. package/dist/cjs/Notification/ToastNotification/ToastNotificationsList/ToastNotificationsList.module.scss.cjs.map +1 -0
  11. package/dist/cjs/Notification/ToastNotification/ToastNotificationsList/subcomponents/ToastNotificationsMap/ToastNotificationsMap.cjs +42 -0
  12. package/dist/cjs/Notification/ToastNotification/ToastNotificationsList/subcomponents/ToastNotificationsMap/ToastNotificationsMap.cjs.map +1 -0
  13. package/dist/cjs/Notification/ToastNotification/context/ToastNotificationContext.cjs +72 -0
  14. package/dist/cjs/Notification/ToastNotification/context/ToastNotificationContext.cjs.map +1 -0
  15. package/dist/cjs/Notification/ToastNotification/hooks/useToastNotification.cjs +9 -0
  16. package/dist/cjs/Notification/ToastNotification/hooks/useToastNotification.cjs.map +1 -0
  17. package/dist/cjs/RichTextEditor/RichTextEditor/RichTextEditor.cjs +6 -2
  18. package/dist/cjs/RichTextEditor/RichTextEditor/RichTextEditor.cjs.map +1 -1
  19. package/dist/cjs/__future__/Select/Select.cjs +14 -1
  20. package/dist/cjs/__future__/Select/Select.cjs.map +1 -1
  21. package/dist/cjs/dts/Modal/ContextModal/ContextModal.d.ts +2 -1
  22. package/dist/cjs/dts/Notification/ToastNotification/ToastNotification/ToastNotification.d.ts +16 -0
  23. package/dist/cjs/dts/Notification/ToastNotification/ToastNotification/index.d.ts +1 -0
  24. package/dist/cjs/dts/Notification/ToastNotification/ToastNotificationsList/ToastNotificationsList.d.ts +4 -0
  25. package/dist/cjs/dts/Notification/ToastNotification/ToastNotificationsList/subcomponents/ToastNotificationsMap/ToastNotificationsMap.d.ts +12 -0
  26. package/dist/cjs/dts/Notification/ToastNotification/ToastNotificationsList/subcomponents/ToastNotificationsMap/index.d.ts +1 -0
  27. package/dist/cjs/dts/Notification/ToastNotification/context/ToastNotificationContext.d.ts +21 -0
  28. package/dist/cjs/dts/Notification/ToastNotification/hooks/useToastNotification.d.ts +2 -0
  29. package/dist/cjs/dts/Notification/ToastNotification/index.d.ts +3 -2
  30. package/dist/cjs/dts/Notification/ToastNotification/types.d.ts +1 -9
  31. package/dist/cjs/dts/Notification/index.d.ts +1 -0
  32. package/dist/cjs/dts/RichTextEditor/RichTextEditor/RichTextEditor.d.ts +1 -1
  33. package/dist/cjs/dts/__future__/Select/Select.d.ts +5 -1
  34. package/dist/cjs/index.cjs +6 -0
  35. package/dist/cjs/index.cjs.map +1 -1
  36. package/dist/cjs/index.css +6 -5
  37. package/dist/esm/KaizenProvider/KaizenProvider.mjs +6 -1
  38. package/dist/esm/KaizenProvider/KaizenProvider.mjs.map +1 -1
  39. package/dist/esm/Modal/ContextModal/ContextModal.mjs +9 -6
  40. package/dist/esm/Modal/ContextModal/ContextModal.mjs.map +1 -1
  41. package/dist/esm/Notification/ToastNotification/ToastNotification/ToastNotification.mjs +31 -0
  42. package/dist/esm/Notification/ToastNotification/ToastNotification/ToastNotification.mjs.map +1 -0
  43. package/dist/esm/Notification/ToastNotification/ToastNotificationsList/ToastNotificationsList.mjs +34 -0
  44. package/dist/esm/Notification/ToastNotification/ToastNotificationsList/ToastNotificationsList.mjs.map +1 -0
  45. package/dist/esm/Notification/ToastNotification/ToastNotificationsList/ToastNotificationsList.module.scss.mjs +5 -0
  46. package/dist/esm/Notification/ToastNotification/ToastNotificationsList/ToastNotificationsList.module.scss.mjs.map +1 -0
  47. package/dist/esm/Notification/ToastNotification/ToastNotificationsList/subcomponents/ToastNotificationsMap/ToastNotificationsMap.mjs +40 -0
  48. package/dist/esm/Notification/ToastNotification/ToastNotificationsList/subcomponents/ToastNotificationsMap/ToastNotificationsMap.mjs.map +1 -0
  49. package/dist/esm/Notification/ToastNotification/context/ToastNotificationContext.mjs +69 -0
  50. package/dist/esm/Notification/ToastNotification/context/ToastNotificationContext.mjs.map +1 -0
  51. package/dist/esm/Notification/ToastNotification/hooks/useToastNotification.mjs +7 -0
  52. package/dist/esm/Notification/ToastNotification/hooks/useToastNotification.mjs.map +1 -0
  53. package/dist/esm/RichTextEditor/RichTextEditor/RichTextEditor.mjs +6 -2
  54. package/dist/esm/RichTextEditor/RichTextEditor/RichTextEditor.mjs.map +1 -1
  55. package/dist/esm/__future__/Select/Select.mjs +15 -2
  56. package/dist/esm/__future__/Select/Select.mjs.map +1 -1
  57. package/dist/esm/dts/Modal/ContextModal/ContextModal.d.ts +2 -1
  58. package/dist/esm/dts/Notification/ToastNotification/ToastNotification/ToastNotification.d.ts +16 -0
  59. package/dist/esm/dts/Notification/ToastNotification/ToastNotification/index.d.ts +1 -0
  60. package/dist/esm/dts/Notification/ToastNotification/ToastNotificationsList/ToastNotificationsList.d.ts +4 -0
  61. package/dist/esm/dts/Notification/ToastNotification/ToastNotificationsList/subcomponents/ToastNotificationsMap/ToastNotificationsMap.d.ts +12 -0
  62. package/dist/esm/dts/Notification/ToastNotification/ToastNotificationsList/subcomponents/ToastNotificationsMap/index.d.ts +1 -0
  63. package/dist/esm/dts/Notification/ToastNotification/context/ToastNotificationContext.d.ts +21 -0
  64. package/dist/esm/dts/Notification/ToastNotification/hooks/useToastNotification.d.ts +2 -0
  65. package/dist/esm/dts/Notification/ToastNotification/index.d.ts +3 -2
  66. package/dist/esm/dts/Notification/ToastNotification/types.d.ts +1 -9
  67. package/dist/esm/dts/Notification/index.d.ts +1 -0
  68. package/dist/esm/dts/RichTextEditor/RichTextEditor/RichTextEditor.d.ts +1 -1
  69. package/dist/esm/dts/__future__/Select/Select.d.ts +5 -1
  70. package/dist/esm/index.css +5 -4
  71. package/dist/esm/index.mjs +3 -0
  72. package/dist/esm/index.mjs.map +1 -1
  73. package/dist/index.d.ts +50 -3
  74. package/dist/styles.css +1 -1
  75. package/package.json +2 -2
  76. package/src/DatePicker/DatePicker.spec.tsx +1 -1
  77. package/src/KaizenProvider/KaizenProvider.tsx +6 -1
  78. package/src/Modal/ContextModal/ContextModal.spec.tsx +3 -3
  79. package/src/Modal/ContextModal/ContextModal.tsx +9 -5
  80. package/src/Notification/ToastNotification/ToastNotification/ToastNotification.spec.tsx +33 -0
  81. package/src/Notification/ToastNotification/ToastNotification/ToastNotification.tsx +48 -0
  82. package/src/Notification/ToastNotification/ToastNotification/index.ts +1 -0
  83. package/src/Notification/ToastNotification/{subcomponents/ToastNotificationsList → ToastNotificationsList}/ToastNotificationsList.module.scss +1 -1
  84. package/src/Notification/ToastNotification/ToastNotificationsList/ToastNotificationsList.tsx +40 -0
  85. package/src/Notification/ToastNotification/ToastNotificationsList/subcomponents/ToastNotificationsMap/ToastNotificationsMap.tsx +49 -0
  86. package/src/Notification/ToastNotification/ToastNotificationsList/subcomponents/ToastNotificationsMap/index.ts +1 -0
  87. package/src/Notification/ToastNotification/_docs/ToastNotification.mdx +19 -14
  88. package/src/Notification/ToastNotification/_docs/ToastNotification.stickersheet.stories.tsx +33 -70
  89. package/src/Notification/ToastNotification/_docs/ToastNotification.stories.tsx +123 -93
  90. package/src/Notification/ToastNotification/context/ToastNotificationContext.tsx +96 -0
  91. package/src/Notification/ToastNotification/hooks/useToastNotification.ts +9 -0
  92. package/src/Notification/ToastNotification/index.ts +3 -2
  93. package/src/Notification/ToastNotification/types.ts +1 -18
  94. package/src/Notification/index.ts +1 -0
  95. package/src/RichTextEditor/RichTextEditor/RichTextEditor.tsx +6 -1
  96. package/src/RichTextEditor/utils/commands/addMark.spec.ts +0 -1
  97. package/src/Tooltip/Tooltip.spec.tsx +6 -1
  98. package/src/__future__/Select/Select.spec.tsx +78 -2
  99. package/src/__future__/Select/Select.tsx +18 -2
  100. package/src/__future__/Select/_docs/Select.mdx +8 -0
  101. package/src/__future__/Select/_docs/Select.stories.tsx +29 -0
  102. package/dist/cjs/dts/Notification/ToastNotification/ToastNotification.d.ts +0 -14
  103. package/dist/cjs/dts/Notification/ToastNotification/subcomponents/ToastNotificationManager/ToastNotificationManager.d.ts +0 -7
  104. package/dist/cjs/dts/Notification/ToastNotification/subcomponents/ToastNotificationManager/index.d.ts +0 -1
  105. package/dist/cjs/dts/Notification/ToastNotification/subcomponents/ToastNotificationsList/ToastNotificationsList.d.ts +0 -11
  106. package/dist/cjs/dts/Notification/ToastNotification/subcomponents/ToastNotificationsListContainer/ToastNotificationsListContainer.d.ts +0 -7
  107. package/dist/cjs/dts/Notification/ToastNotification/subcomponents/ToastNotificationsListContainer/index.d.ts +0 -1
  108. package/dist/esm/dts/Notification/ToastNotification/ToastNotification.d.ts +0 -14
  109. package/dist/esm/dts/Notification/ToastNotification/subcomponents/ToastNotificationManager/ToastNotificationManager.d.ts +0 -7
  110. package/dist/esm/dts/Notification/ToastNotification/subcomponents/ToastNotificationManager/index.d.ts +0 -1
  111. package/dist/esm/dts/Notification/ToastNotification/subcomponents/ToastNotificationsList/ToastNotificationsList.d.ts +0 -11
  112. package/dist/esm/dts/Notification/ToastNotification/subcomponents/ToastNotificationsListContainer/ToastNotificationsListContainer.d.ts +0 -7
  113. package/dist/esm/dts/Notification/ToastNotification/subcomponents/ToastNotificationsListContainer/index.d.ts +0 -1
  114. package/src/Notification/ToastNotification/ToastNotification.spec.tsx +0 -31
  115. package/src/Notification/ToastNotification/ToastNotification.tsx +0 -43
  116. package/src/Notification/ToastNotification/subcomponents/ToastNotificationManager/ToastNotificationManager.spec.tsx +0 -144
  117. package/src/Notification/ToastNotification/subcomponents/ToastNotificationManager/ToastNotificationManager.tsx +0 -135
  118. package/src/Notification/ToastNotification/subcomponents/ToastNotificationManager/index.ts +0 -1
  119. package/src/Notification/ToastNotification/subcomponents/ToastNotificationsList/ToastNotificationsList.tsx +0 -40
  120. package/src/Notification/ToastNotification/subcomponents/ToastNotificationsListContainer/ToastNotificationsListContainer.spec.tsx +0 -73
  121. package/src/Notification/ToastNotification/subcomponents/ToastNotificationsListContainer/ToastNotificationsListContainer.tsx +0 -31
  122. package/src/Notification/ToastNotification/subcomponents/ToastNotificationsListContainer/index.ts +0 -1
  123. /package/dist/cjs/dts/Notification/ToastNotification/{subcomponents/ToastNotificationsList → ToastNotificationsList}/index.d.ts +0 -0
  124. /package/dist/esm/dts/Notification/ToastNotification/{subcomponents/ToastNotificationsList → ToastNotificationsList}/index.d.ts +0 -0
  125. /package/src/Notification/ToastNotification/{subcomponents/ToastNotificationsList → ToastNotificationsList}/index.ts +0 -0
@@ -1,11 +0,0 @@
1
- import { HTMLAttributes } from "react";
2
- import { OverrideClassName } from "../../../../types/OverrideClassName";
3
- import { RemoveToastNotification, ToastNotification } from "../../types";
4
- export type ToastNotificationsListProps = {
5
- notifications: ToastNotification[];
6
- onHide: RemoveToastNotification;
7
- } & OverrideClassName<HTMLAttributes<HTMLDivElement>>;
8
- export declare const ToastNotificationsList: {
9
- ({ notifications, onHide: defaultOnHide, }: ToastNotificationsListProps): JSX.Element;
10
- displayName: string;
11
- };
@@ -1,7 +0,0 @@
1
- import React from "react";
2
- import { RemoveToastNotification, ToastNotification } from "../../types";
3
- export type ToastNotificationsListContainerProps = {
4
- removeToastNotification: RemoveToastNotification;
5
- registerSetNotificationsCallback: (callback: React.Dispatch<React.SetStateAction<ToastNotification[]>>) => void;
6
- };
7
- export declare const ToastNotificationsListContainer: ({ removeToastNotification, registerSetNotificationsCallback, }: ToastNotificationsListContainerProps) => JSX.Element;
@@ -1 +0,0 @@
1
- export * from "./ToastNotificationsListContainer";
@@ -1,14 +0,0 @@
1
- import React from "react";
2
- import { ToastNotificationWithOptionals } from "./types";
3
- export type ToastNotificationProps = Omit<ToastNotificationWithOptionals, "message" | "persistent"> & {
4
- /**
5
- * Removes the dismiss trigger. functions the same as `persistent` in `addToastNotification`. If this is true you will need to manage the removal of notifications manually.
6
- * @default false
7
- */
8
- hideCloseIcon?: boolean;
9
- children: React.ReactNode;
10
- };
11
- export declare const ToastNotification: {
12
- ({ id: propsId, hideCloseIcon, type, title, onHide, children, ...restProps }: ToastNotificationProps): null;
13
- displayName: string;
14
- };
@@ -1,7 +0,0 @@
1
- import { AddToastNotification, ClearToastNotifications, RemoveToastNotification } from "../../types";
2
- /**
3
- * Export the curried API methods
4
- */
5
- export declare const addToastNotification: AddToastNotification;
6
- export declare const clearToastNotifications: ClearToastNotifications;
7
- export declare const removeToastNotification: RemoveToastNotification;
@@ -1 +0,0 @@
1
- export * from "./ToastNotificationManager";
@@ -1,11 +0,0 @@
1
- import { HTMLAttributes } from "react";
2
- import { OverrideClassName } from "../../../../types/OverrideClassName";
3
- import { RemoveToastNotification, ToastNotification } from "../../types";
4
- export type ToastNotificationsListProps = {
5
- notifications: ToastNotification[];
6
- onHide: RemoveToastNotification;
7
- } & OverrideClassName<HTMLAttributes<HTMLDivElement>>;
8
- export declare const ToastNotificationsList: {
9
- ({ notifications, onHide: defaultOnHide, }: ToastNotificationsListProps): JSX.Element;
10
- displayName: string;
11
- };
@@ -1,7 +0,0 @@
1
- import React from "react";
2
- import { RemoveToastNotification, ToastNotification } from "../../types";
3
- export type ToastNotificationsListContainerProps = {
4
- removeToastNotification: RemoveToastNotification;
5
- registerSetNotificationsCallback: (callback: React.Dispatch<React.SetStateAction<ToastNotification[]>>) => void;
6
- };
7
- export declare const ToastNotificationsListContainer: ({ removeToastNotification, registerSetNotificationsCallback, }: ToastNotificationsListContainerProps) => JSX.Element;
@@ -1 +0,0 @@
1
- export * from "./ToastNotificationsListContainer";
@@ -1,31 +0,0 @@
1
- import React from "react"
2
- import { render, screen } from "@testing-library/react"
3
- import { ToastNotification } from "./ToastNotification"
4
- import { clearToastNotifications } from "./subcomponents/ToastNotificationManager"
5
-
6
- describe("<ToastNotification />", () => {
7
- beforeEach(() => {
8
- clearToastNotifications()
9
- })
10
- it('creates a single "status" container for notifications', async () => {
11
- render(
12
- <ToastNotification type="positive" title="Success">
13
- It worked!
14
- </ToastNotification>
15
- )
16
-
17
- const toastPortalManager = await screen.getAllByRole("status")
18
-
19
- expect(toastPortalManager).toHaveLength(1)
20
- })
21
- it("renders a basic notification correctly", async () => {
22
- render(
23
- <ToastNotification type="positive" title="Success">
24
- It worked!
25
- </ToastNotification>
26
- )
27
-
28
- const notification = await screen.findByText("Success")
29
- expect(notification).toBeInTheDocument()
30
- })
31
- })
@@ -1,43 +0,0 @@
1
- import React, { useId } from "react"
2
- import { addToastNotification } from "./subcomponents/ToastNotificationManager"
3
- import { ToastNotificationWithOptionals } from "./types"
4
-
5
- export type ToastNotificationProps = Omit<
6
- ToastNotificationWithOptionals,
7
- "message" | "persistent"
8
- > & {
9
- /**
10
- * Removes the dismiss trigger. functions the same as `persistent` in `addToastNotification`. If this is true you will need to manage the removal of notifications manually.
11
- * @default false
12
- */
13
- hideCloseIcon?: boolean
14
- children: React.ReactNode
15
- }
16
-
17
- export const ToastNotification = ({
18
- id: propsId,
19
- hideCloseIcon = false,
20
- type,
21
- title,
22
- onHide,
23
- children,
24
- ...restProps
25
- }: ToastNotificationProps): null => {
26
- const reactId = useId()
27
- const id = propsId || reactId
28
- const persistent = hideCloseIcon
29
-
30
- addToastNotification({
31
- id,
32
- type,
33
- title,
34
- message: children,
35
- persistent,
36
- onHide,
37
- ...restProps,
38
- })
39
-
40
- return null
41
- }
42
-
43
- ToastNotification.displayName = "ToastNotification"
@@ -1,144 +0,0 @@
1
- import React from "react"
2
- import { act, screen } from "@testing-library/react"
3
- import {
4
- addToastNotification,
5
- removeToastNotification,
6
- clearToastNotifications,
7
- } from "."
8
-
9
- describe("ToastNotificationsManager", () => {
10
- beforeEach(() => {
11
- act(() => {
12
- clearToastNotifications()
13
- })
14
- })
15
-
16
- describe("addToastNotification", () => {
17
- it('creates a single "status" container for notifications', async () => {
18
- await act(async () => {
19
- addToastNotification({
20
- type: "informative",
21
- title: "Test portal",
22
- message: <p>Message goes here</p>,
23
- persistent: false,
24
- })
25
- })
26
-
27
- const toastPortalManager = await screen.getAllByRole("status")
28
-
29
- expect(toastPortalManager).toHaveLength(1)
30
-
31
- // This is currently hard coded
32
- expect(
33
- await screen.getByTestId("toast-notification-manager-portal")
34
- ).toBeInTheDocument()
35
- })
36
-
37
- it("creates a notification", async () => {
38
- await act(async () => {
39
- addToastNotification({
40
- id: "abc-123",
41
- type: "informative",
42
- title: "Test portal",
43
- message: <p>Message goes here</p>,
44
- persistent: false,
45
- })
46
- })
47
-
48
- const toastItem = await screen.findByText("Message goes here")
49
-
50
- expect(toastItem).toBeInTheDocument()
51
- })
52
-
53
- it("updates the existing notification if addToastNotification is called with the same id", async () => {
54
- await act(async () => {
55
- addToastNotification({
56
- id: "abc-123",
57
- type: "informative",
58
- title: "Test portal",
59
- message: <p>Message goes here</p>,
60
- persistent: false,
61
- "data-testid": "bbc-324",
62
- })
63
- })
64
-
65
- const toastItem = await screen.getByTestId("bbc-324")
66
-
67
- expect(toastItem).toHaveTextContent("Message goes here")
68
-
69
- await act(async () => {
70
- addToastNotification({
71
- id: "abc-123",
72
- type: "informative",
73
- title: "Test portal",
74
- message: <p>Updated Message</p>,
75
- persistent: false,
76
- "data-testid": "bbc-324",
77
- })
78
- })
79
-
80
- expect(toastItem).toHaveTextContent("Updated Message")
81
- })
82
- })
83
-
84
- describe("removeToastNotification", () => {
85
- it("removes a single notifciation", async () => {
86
- await act(async () => {
87
- addToastNotification({
88
- id: "abc-123",
89
- type: "informative",
90
- title: "Test portal",
91
- message: <p>Message goes here</p>,
92
- persistent: false,
93
- })
94
- })
95
-
96
- const toastItem = await screen.findByText("Message goes here")
97
- expect(toastItem).toBeInTheDocument()
98
-
99
- await act(async () => {
100
- removeToastNotification("abc-123")
101
- })
102
- expect(toastItem).not.toBeInTheDocument()
103
- })
104
- })
105
-
106
- describe("clearToastNotifications", () => {
107
- it("clears all notifications", async () => {
108
- await act(async () => {
109
- addToastNotification({
110
- id: "abc-123",
111
- type: "informative",
112
- title: "Test portal",
113
- message: <p>Message goes here</p>,
114
- persistent: false,
115
- "data-testid": "id--toast-1",
116
- })
117
- })
118
-
119
- await act(async () => {
120
- addToastNotification({
121
- id: "abc-456",
122
- type: "informative",
123
- title: "Test portal 2",
124
- message: <p>Second message goes here</p>,
125
- persistent: false,
126
- "data-testid": "id--toast-2",
127
- })
128
- })
129
-
130
- const toastItem1 = await screen.getByTestId("id--toast-1")
131
- const toastItem2 = await screen.getByTestId("id--toast-2")
132
-
133
- expect(toastItem1).toBeInTheDocument()
134
- expect(toastItem2).toBeInTheDocument()
135
-
136
- await act(async () => {
137
- clearToastNotifications()
138
- })
139
-
140
- await expect(toastItem1).not.toBeInTheDocument()
141
- await expect(toastItem2).not.toBeInTheDocument()
142
- })
143
- })
144
- })
@@ -1,135 +0,0 @@
1
- import React from "react"
2
- import { createRoot } from "react-dom/client"
3
- import { v4 } from "uuid"
4
- import {
5
- AddToastNotification,
6
- ClearToastNotifications,
7
- RemoveToastNotification,
8
- ToastNotification,
9
- ToastNotificationWithOptionals,
10
- } from "../../types"
11
-
12
- import { ToastNotificationsListContainer } from "../ToastNotificationsListContainer"
13
-
14
- type ToastNotificationApi = {
15
- addToastNotification: AddToastNotification
16
- removeToastNotification: RemoveToastNotification
17
- clearToastNotifications: ClearToastNotifications
18
- }
19
-
20
- /**
21
- * Persistent reference to a "portal" for rendering the separate DOM tree
22
- */
23
- let portal: HTMLDivElement | undefined
24
-
25
- /**
26
- * Set default values for optional params
27
- */
28
- const setDefaults = (
29
- notificationMaybe: ToastNotificationWithOptionals
30
- ): ToastNotification => {
31
- const copy = { ...notificationMaybe }
32
- if (typeof copy.id === "undefined") {
33
- copy.id = v4()
34
- }
35
- return copy as ToastNotification
36
- }
37
-
38
- /**
39
- * Create an instance of the toast notification manager
40
- * Renders ToastNotifications in an independent React tree
41
- * @returns { addToastNotification, removeToastNotification, clearToastNotifications }
42
- */
43
- const createToastNotificationManager = (): ToastNotificationApi => {
44
- let setNotifications:
45
- | React.Dispatch<React.SetStateAction<ToastNotification[]>>
46
- | undefined
47
- if (portal === undefined && typeof window !== "undefined") {
48
- // automation and testid appear to be consumed in other repos, we'll need to refactor before we remove so they can be added in
49
- portal = document.createElement("div")
50
- portal.setAttribute("data-testid", "toast-notification-manager-portal")
51
- portal.setAttribute("role", "status")
52
-
53
- document.body.appendChild(portal)
54
- }
55
-
56
- const state: {
57
- notifications: ToastNotification[]
58
- } = {
59
- notifications: [],
60
- }
61
-
62
- const addToastNotification: AddToastNotification = notification => {
63
- const notificationWithId = setDefaults(notification)
64
-
65
- const notificationIndex = state.notifications.findIndex(
66
- n => n.id === notification.id
67
- )
68
-
69
- if (notificationIndex > -1) {
70
- const copy = state.notifications.slice()
71
- copy.splice(notificationIndex, 1, notificationWithId) // Mutation to insert notification over itself
72
- state.notifications = copy
73
- } else {
74
- state.notifications = [...state.notifications, notificationWithId]
75
- }
76
- render()
77
- }
78
-
79
- const removeToastNotification = (notificationID: string): void => {
80
- const notificationIndex = state.notifications.findIndex(
81
- notification => notification.id === notificationID
82
- )
83
- const copy = state.notifications.slice()
84
- copy.splice(notificationIndex, 1) // Mutation
85
- state.notifications = copy
86
- render()
87
- }
88
-
89
- const clearToastNotifications = (): void => {
90
- state.notifications = []
91
- render()
92
- }
93
-
94
- const registerSetNotificationsCallback = (
95
- cb: React.Dispatch<React.SetStateAction<ToastNotification[]>>
96
- ): void => {
97
- setNotifications = cb
98
- render()
99
- }
100
-
101
- const render = (): void => {
102
- if (setNotifications) {
103
- setNotifications(state.notifications)
104
- }
105
- }
106
-
107
- if (portal) {
108
- const root = createRoot(portal)
109
-
110
- root.render(
111
- <ToastNotificationsListContainer
112
- removeToastNotification={removeToastNotification}
113
- registerSetNotificationsCallback={registerSetNotificationsCallback}
114
- />
115
- )
116
- }
117
-
118
- return {
119
- addToastNotification,
120
- clearToastNotifications,
121
- removeToastNotification,
122
- }
123
- }
124
-
125
- /**
126
- * Singleton instance of the toast notification manager
127
- */
128
- const instance = createToastNotificationManager()
129
-
130
- /**
131
- * Export the curried API methods
132
- */
133
- export const addToastNotification = instance.addToastNotification
134
- export const clearToastNotifications = instance.clearToastNotifications
135
- export const removeToastNotification = instance.removeToastNotification
@@ -1 +0,0 @@
1
- export * from "./ToastNotificationManager"
@@ -1,40 +0,0 @@
1
- import React, { HTMLAttributes } from "react"
2
- import { GenericNotification } from "~components/Notification/subcomponents/GenericNotification"
3
- import { OverrideClassName } from "~types/OverrideClassName"
4
- import { RemoveToastNotification, ToastNotification } from "../../types"
5
- import styles from "./ToastNotificationsList.module.scss"
6
-
7
- export type ToastNotificationsListProps = {
8
- notifications: ToastNotification[]
9
- onHide: RemoveToastNotification
10
- } & OverrideClassName<HTMLAttributes<HTMLDivElement>>
11
-
12
- export const ToastNotificationsList = ({
13
- notifications,
14
- onHide: defaultOnHide,
15
- }: ToastNotificationsListProps): JSX.Element => (
16
- <div className={styles.list}>
17
- {notifications.map(
18
- ({ id, type, title, persistent, onHide, message, ...restProps }) => (
19
- <GenericNotification
20
- key={id}
21
- style="toast"
22
- type={type}
23
- title={title}
24
- persistent={persistent}
25
- onHide={(): void => {
26
- if (typeof onHide !== "undefined") {
27
- onHide()
28
- }
29
- defaultOnHide(id)
30
- }}
31
- {...restProps}
32
- >
33
- {message}
34
- </GenericNotification>
35
- )
36
- )}
37
- </div>
38
- )
39
-
40
- ToastNotificationsList.displayName = "ToastNotificationsList"
@@ -1,73 +0,0 @@
1
- import React from "react"
2
- import { fireEvent } from "@testing-library/dom"
3
- import { render, act, waitFor, screen } from "@testing-library/react"
4
- import { ToastNotification } from "../../types"
5
- import { ToastNotificationsListContainer } from "./ToastNotificationsListContainer"
6
-
7
- describe("<ToastNotificationsListContainer />", () => {
8
- it("passes the setNotifications callback", () => {
9
- const registerCallback = jest.fn()
10
- render(
11
- <ToastNotificationsListContainer
12
- registerSetNotificationsCallback={registerCallback}
13
- removeToastNotification={jest.fn()}
14
- />
15
- )
16
-
17
- expect(registerCallback).toHaveBeenCalledTimes(1)
18
- })
19
-
20
- it("renders notifications added through the setNotifications callback", async () => {
21
- let callback: (notifications: ToastNotification[]) => void | undefined
22
- const registerCallback = jest.fn(cb => (callback = cb))
23
- const removeToastNotification = jest.fn()
24
- render(
25
- <ToastNotificationsListContainer
26
- registerSetNotificationsCallback={registerCallback}
27
- removeToastNotification={removeToastNotification}
28
- />
29
- )
30
- act(() => {
31
- callback([
32
- {
33
- id: "abc123",
34
- type: "informative",
35
- title: "Title goes here",
36
- message: <>Child content</>,
37
- onHide: removeToastNotification,
38
- },
39
- ])
40
- })
41
-
42
- expect(await screen.findByText("Title goes here")).toBeInTheDocument()
43
- })
44
-
45
- it("calls removeToastNotification when a notification is hidden", async () => {
46
- let callback: (notifications: ToastNotification[]) => void | undefined
47
- const registerCallback = jest.fn(cb => (callback = cb))
48
- const removeToastNotification = jest.fn()
49
- const { getByRole } = render(
50
- <ToastNotificationsListContainer
51
- registerSetNotificationsCallback={registerCallback}
52
- removeToastNotification={removeToastNotification}
53
- />
54
- )
55
- act(() => {
56
- callback([
57
- {
58
- id: "abc123",
59
- type: "informative",
60
- title: "Title goes here",
61
- message: <>Child content</>,
62
- onHide: removeToastNotification,
63
- },
64
- ])
65
- })
66
- const button = getByRole("button")
67
- fireEvent.click(button)
68
-
69
- waitFor(() => {
70
- expect(removeToastNotification).toHaveBeenCalled()
71
- })
72
- })
73
- })
@@ -1,31 +0,0 @@
1
- import React, { useEffect, useState } from "react"
2
- import { RemoveToastNotification, ToastNotification } from "../../types"
3
- import { ToastNotificationsList } from "../ToastNotificationsList"
4
-
5
- export type ToastNotificationsListContainerProps = {
6
- removeToastNotification: RemoveToastNotification
7
- registerSetNotificationsCallback: (
8
- callback: React.Dispatch<React.SetStateAction<ToastNotification[]>>
9
- ) => void
10
- }
11
- export const ToastNotificationsListContainer = ({
12
- removeToastNotification,
13
- registerSetNotificationsCallback,
14
- }: ToastNotificationsListContainerProps): JSX.Element => {
15
- const [notifications, setNotifications] = useState<ToastNotification[]>([])
16
-
17
- // Pass the local setNotifications function back up to the caller
18
- // via the registerSetNotificationsCallback
19
- useEffect(() => {
20
- registerSetNotificationsCallback(setNotifications)
21
- }, [setNotifications])
22
-
23
- return (
24
- <ToastNotificationsList
25
- notifications={notifications}
26
- onHide={removeToastNotification}
27
- />
28
- )
29
- }
30
-
31
- ToastNotificationsList.displayName = "ToastNotificationsListContainer"
@@ -1 +0,0 @@
1
- export * from "./ToastNotificationsListContainer"