@sproutsocial/seeds-react-toast 1.0.20 → 1.0.24
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/.turbo/turbo-build.log +9 -9
- package/CHANGELOG.md +44 -0
- package/dist/esm/index.js +2 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/package.json +5 -4
- package/src/Toast.stories.tsx +58 -0
- package/src/Toast.tsx +6 -1
- package/src/__tests__/Toast.test.tsx +171 -0
package/.turbo/turbo-build.log
CHANGED
|
@@ -3,19 +3,19 @@ $ tsup --dts
|
|
|
3
3
|
[34mCLI[39m Building entry: src/index.ts
|
|
4
4
|
[34mCLI[39m Using tsconfig: tsconfig.json
|
|
5
5
|
[34mCLI[39m tsup v8.5.0
|
|
6
|
-
[34mCLI[39m Using tsup config: /home/runner/
|
|
6
|
+
[34mCLI[39m Using tsup config: /home/runner/_work/seeds/seeds/seeds-react/seeds-react-toast/tsup.config.ts
|
|
7
7
|
[34mCLI[39m Target: es2022
|
|
8
8
|
[34mCLI[39m Cleaning output folder
|
|
9
9
|
[34mCJS[39m Build start
|
|
10
10
|
[34mESM[39m Build start
|
|
11
|
-
[32mCJS[39m [1mdist/index.js [22m[32m9.
|
|
12
|
-
[32mCJS[39m [1mdist/index.js.map [22m[32m13.
|
|
13
|
-
[32mCJS[39m ⚡️ Build success in
|
|
14
|
-
[32mESM[39m [1mdist/esm/index.js [22m[32m6.
|
|
15
|
-
[32mESM[39m [1mdist/esm/index.js.map [22m[32m12.
|
|
16
|
-
[32mESM[39m ⚡️ Build success in
|
|
11
|
+
[32mCJS[39m [1mdist/index.js [22m[32m9.75 KB[39m
|
|
12
|
+
[32mCJS[39m [1mdist/index.js.map [22m[32m13.32 KB[39m
|
|
13
|
+
[32mCJS[39m ⚡️ Build success in 15ms
|
|
14
|
+
[32mESM[39m [1mdist/esm/index.js [22m[32m6.93 KB[39m
|
|
15
|
+
[32mESM[39m [1mdist/esm/index.js.map [22m[32m12.88 KB[39m
|
|
16
|
+
[32mESM[39m ⚡️ Build success in 16ms
|
|
17
17
|
[34mDTS[39m Build start
|
|
18
|
-
[32mDTS[39m ⚡️ Build success in
|
|
18
|
+
[32mDTS[39m ⚡️ Build success in 5626ms
|
|
19
19
|
[32mDTS[39m [1mdist/index.d.ts [22m[32m3.18 KB[39m
|
|
20
20
|
[32mDTS[39m [1mdist/index.d.mts [22m[32m3.18 KB[39m
|
|
21
|
-
Done in
|
|
21
|
+
Done in 7.71s.
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,49 @@
|
|
|
1
1
|
# @sproutsocial/seeds-react-toast
|
|
2
2
|
|
|
3
|
+
## 1.0.24
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [17d4f12]
|
|
8
|
+
- @sproutsocial/seeds-react-theme@3.6.0
|
|
9
|
+
- @sproutsocial/seeds-react-box@1.1.14
|
|
10
|
+
- @sproutsocial/seeds-react-icon@2.2.5
|
|
11
|
+
|
|
12
|
+
## 1.0.23
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- 2689788: Fix Toast and Modal V1 being unclickable when Modal V2 is open
|
|
17
|
+
|
|
18
|
+
When a Radix Dialog (Modal V2) is open, it sets `pointer-events: none` on `document.body`
|
|
19
|
+
and listens for `pointerdown` on the document to detect outside clicks. This breaks non-Radix
|
|
20
|
+
overlays that portal to body (Toast, Modal V1) — making them unclickable and causing Modal V2
|
|
21
|
+
to dismiss when interacting with them.
|
|
22
|
+
|
|
23
|
+
**Toast**: Wrap `ToastRoot` in Radix `DismissableLayerBranch` with `pointer-events: auto`.
|
|
24
|
+
This registers the toast container as a branch of the dismissable layer system, preventing
|
|
25
|
+
Modal V2 from closing on toast interaction.
|
|
26
|
+
|
|
27
|
+
**Modal V1**: Use react-modal's `contentRef` to set `pointer-events: auto` on the portal node
|
|
28
|
+
and stop `pointerdown` propagation. `DismissableLayerBranch` can't be used here because
|
|
29
|
+
react-modal portals to `document.body`, and Modal V2's `transform` creates a containing block
|
|
30
|
+
that would break V1's `position: fixed` overlay if portaled inside V2.
|
|
31
|
+
|
|
32
|
+
## 1.0.22
|
|
33
|
+
|
|
34
|
+
### Patch Changes
|
|
35
|
+
|
|
36
|
+
- Updated dependencies [118e300]
|
|
37
|
+
- @sproutsocial/seeds-react-theme@3.5.1
|
|
38
|
+
- @sproutsocial/seeds-react-box@1.1.13
|
|
39
|
+
- @sproutsocial/seeds-react-icon@2.2.4
|
|
40
|
+
|
|
41
|
+
## 1.0.21
|
|
42
|
+
|
|
43
|
+
### Patch Changes
|
|
44
|
+
|
|
45
|
+
- @sproutsocial/seeds-react-icon@2.2.3
|
|
46
|
+
|
|
3
47
|
## 1.0.20
|
|
4
48
|
|
|
5
49
|
### Patch Changes
|
package/dist/esm/index.js
CHANGED
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
toast as toastifyToast,
|
|
4
4
|
cssTransition
|
|
5
5
|
} from "react-toastify";
|
|
6
|
+
import { DismissableLayerBranch } from "@radix-ui/react-dismissable-layer";
|
|
6
7
|
import Box2 from "@sproutsocial/seeds-react-box";
|
|
7
8
|
import Icon from "@sproutsocial/seeds-react-icon";
|
|
8
9
|
import Text from "@sproutsocial/seeds-react-text";
|
|
@@ -134,7 +135,7 @@ var SproutZoomTransition = cssTransition({
|
|
|
134
135
|
enter: "SproutToast__zoom-in",
|
|
135
136
|
exit: "SproutToast__zoom-out"
|
|
136
137
|
});
|
|
137
|
-
var ToastContainer2 = (props) => /* @__PURE__ */ jsx(ToastRoot, { ...props });
|
|
138
|
+
var ToastContainer2 = (props) => /* @__PURE__ */ jsx(DismissableLayerBranch, { style: { pointerEvents: "auto" }, children: /* @__PURE__ */ jsx(ToastRoot, { ...props }) });
|
|
138
139
|
var themeIcon = {
|
|
139
140
|
success: "circle-check-outline",
|
|
140
141
|
info: "circle-i-outline",
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/Toast.tsx","../../src/styles.ts","../../src/ToastTypes.ts"],"sourcesContent":["import type { PropsWithChildren, ReactNode, ComponentProps } from \"react\";\nimport {\n toast as toastifyToast,\n cssTransition,\n type ToastContent,\n} from \"react-toastify\";\nimport Box from \"@sproutsocial/seeds-react-box\";\nimport Icon, { type TypeIconName } from \"@sproutsocial/seeds-react-icon\";\nimport Text from \"@sproutsocial/seeds-react-text\";\nimport { Container, ToastRoot } from \"./styles\";\nimport type { TypeToastOptions, TypeToastTheme } from \"./ToastTypes\";\nimport styled from \"styled-components\";\n\nexport const toastDismiss: typeof toastifyToast.dismiss = (...input) =>\n // @ts-ignore Not sure what this type is supposed to be\n toastifyToast.dismiss(...input);\nexport const toastIsActive: typeof toastifyToast.isActive = (...input) =>\n toastifyToast.isActive(...input);\nexport const toastUpdate: typeof toastifyToast.update = (...input) =>\n toastifyToast.update(...input);\n\nconst NoTransition = cssTransition({\n enter: \"SproutToast__none-in\",\n exit: \"SproutToast__none-out\",\n});\nconst SproutZoomTransition = cssTransition({\n enter: \"SproutToast__zoom-in\",\n exit: \"SproutToast__zoom-out\",\n});\n\nexport const ToastContainer = (\n props: Partial<ComponentProps<typeof ToastRoot>>\n) => <ToastRoot {...props} />;\n\nconst themeIcon: Record<TypeToastTheme, TypeIconName> = {\n success: \"circle-check-outline\",\n info: \"circle-i-outline\",\n warning: \"triangle-exclamation-outline\",\n error: \"triangle-exclamation-outline\",\n} as const;\n\nexport function toast<TData = unknown>(\n options: TypeToastOptions<TData>\n): ReturnType<typeof toastifyToast> {\n const {\n closeOnClick = true,\n content,\n onClose,\n persist,\n toastId: inputToastId,\n useTransition = true,\n position = \"bottom-right\",\n autoClose = persist ? false : 6000,\n transition = useTransition ? SproutZoomTransition : NoTransition,\n ...rest\n } = options;\n\n let toastId = inputToastId;\n if (!toastId && typeof content === \"string\") {\n toastId = content;\n }\n\n const renderToast: ToastContent<TData> = (toastInput) => {\n const renderedContent =\n typeof content === \"function\" ? content(toastInput) : content;\n\n if (options.theme === \"custom\") {\n return renderedContent;\n }\n\n const theme = options.theme || \"info\";\n const iconName = options.icon || themeIcon[theme];\n const containerColor =\n options.color ||\n (\n {\n success: \"container.border.success\",\n error: \"container.border.error\",\n info: \"container.border.info\",\n warning: \"container.border.warning\",\n } as const\n )[theme];\n const iconColor =\n options.color ||\n (\n {\n success: \"icon.success\",\n error: \"icon.error\",\n info: \"icon.info\",\n warning: \"icon.warning\",\n } as const\n )[theme];\n\n return (\n // TODO: if this closes when clicked, there should be a label saying \"Click to close\" that can be overridden\n <ToastContentContainer\n icon={<Icon name={iconName} color={iconColor} />}\n close={<Icon name=\"x-outline\" color=\"icon.base\" aria-hidden />}\n highlightColor={containerColor}\n >\n {renderedContent}\n </ToastContentContainer>\n );\n };\n\n const toastOptions = {\n autoClose,\n closeOnClick,\n onClose,\n toastId: toastId || undefined,\n transition,\n position,\n ...rest,\n icon: undefined,\n color: undefined,\n } as const;\n\n if (toastId && toastIsActive(toastId)) {\n toastifyToast.update<TData>(toastId, {\n ...toastOptions,\n render: renderToast,\n });\n } else {\n toastId = toastifyToast<TData>(renderToast, toastOptions);\n }\n\n return toastId;\n}\n\nexport default ToastContainer;\n\nexport const ToastContentContainer = ({\n children,\n icon,\n close,\n highlightColor,\n}: PropsWithChildren<{\n /**\n * A ReactNode in the icon slot\n */\n icon: ReactNode;\n /**\n * A ReactNode in the close button slot\n */\n close: ReactNode;\n highlightColor?: ComponentProps<typeof Box>[\"bg\"];\n}>) => {\n return (\n <Container data-qa-toast=\"\">\n {highlightColor ? (\n <ToastHighlight bg={highlightColor} aria-hidden />\n ) : null}\n\n <Box css=\"line-height: 1;\">{icon}</Box>\n\n <Box flex={1}>\n <Text as=\"div\" color=\"text.body\" data-qa-toast-content=\"\">\n {children}\n </Text>\n </Box>\n\n <Box css=\"line-height: 1;\">{close}</Box>\n </Container>\n );\n};\n\nexport const ToastHighlight = styled(Box)<ComponentProps<typeof Box>>`\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n width: 2px;\n`;\n","import styled from \"styled-components\";\nimport type { ComponentProps } from \"react\";\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\nimport \"react-toastify/dist/ReactToastify.css\";\nimport Box from \"@sproutsocial/seeds-react-box\";\nimport { ToastContainer } from \"react-toastify\";\n\nexport const TOAST_Z_INDEX = 9999;\n\nexport const Container = styled(Box)<ComponentProps<typeof Box>>`\n display: flex;\n align-items: center;\n gap: ${({ theme }) => theme.space[350]};\n font-family: ${({ theme }) => theme.fontFamily};\n ${({ theme }) => theme.typography[200]}\n position: relative;\n padding: ${({ theme }) => theme.space[350]};\n`;\n\nexport const ToastRoot = styled(ToastContainer).attrs({\n toastClassName: \"Toastify-toast-overrides\",\n hideProgressBar: true,\n closeButton: false,\n icon: false,\n position: \"bottom-right\",\n})`\n --toastify-z-index: ${TOAST_Z_INDEX};\n --toastify-toast-offset: ${({ theme }) => theme.space[400]};\n --toastify-toast-width: 360px;\n --toastify-toast-min-height: 48px;\n --toastify-toast-max-height: 70vh;\n --toastify-toast-bd-radius: ${({ theme }) => theme.radii[400]};\n --toastify-toast-background: ${({ theme }) =>\n theme.colors.container.background.base};\n /* there's margin-bottom on the last toast so we can remove this */\n --toastify-toast-bottom: 0;\n\n padding: 0;\n\n .Toastify-toast-overrides {\n background: ${({ theme }) => theme.colors.container.background.base};\n color: ${({ theme }) => theme.colors.text.body};\n box-shadow: ${({ theme }) => theme.shadows.low};\n padding: 0;\n margin-bottom: var(--toastify-toast-offset);\n }\n\n .Toastify__toast-body {\n padding: 0;\n margin: 0;\n }\n\n /* Override React Toastify's mobile width styles */\n @media only screen and (max-width: 480px) {\n .Toastify-container-overrides {\n min-width: initial !important;\n }\n }\n\n /* Zoom animation */\n @keyframes SproutToast__zoom-in {\n from {\n opacity: 0;\n transform: scale3d(0.3, 0.3, 0.3);\n }\n 50% {\n opacity: 1;\n }\n }\n @keyframes SproutToast__zoom-out {\n from {\n opacity: 1;\n }\n 50% {\n opacity: 0;\n transform: scale3d(0.3, 0.3, 0.3) translate3d(0, var(--y), 0);\n }\n to {\n opacity: 0;\n }\n }\n .SproutToast__zoom-in {\n animation: SproutToast__zoom-in ${({ theme }) => theme.duration.medium}\n ${({ theme }) => theme.easing.ease_out} both;\n }\n .SproutToast__zoom-out {\n animation: SproutToast__zoom-out ${({ theme }) => theme.duration.slow}\n ${({ theme }) => theme.easing.ease_in} both;\n }\n\n /* No animation (it's still necessary to define classes for no animation to work properly) */\n @keyframes SproutToast__none-in {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n }\n @keyframes SproutToast__none-out {\n from {\n opacity: 1;\n }\n to {\n opacity: 0;\n }\n }\n .SproutToast__none-in {\n animation: SproutToast__none-in 0s both;\n }\n .SproutToast__none-out {\n animation: SproutToast__none-out 0s both;\n }\n`;\n","import type { ComponentProps } from \"react\";\nimport { type Icon, type TypeIconName } from \"@sproutsocial/seeds-react-icon\";\nimport type { ToastContent, ToastOptions } from \"react-toastify\";\n\nexport type TypeToastTheme = \"info\" | \"success\" | \"warning\" | \"error\";\n\ninterface BaseToastOptions<TData>\n extends Omit<ToastOptions<TData>, \"closeButton\" | \"icon\" | \"type\"> {\n theme?: TypeToastTheme | \"custom\";\n content: ToastContent<TData>;\n persist?: boolean;\n useTransition?: boolean;\n}\n\ninterface ThemedToastOptions<TData> extends BaseToastOptions<TData> {\n /**\n * One of `info`, `success`, `warning`, or `error`.\n */\n theme?: TypeToastTheme;\n /**\n * @deprecated Use `custom` theme instead.\n */\n color?: ComponentProps<typeof Icon>[\"color\"];\n /**\n * @deprecated Use `custom` theme instead.\n */\n icon?: TypeIconName;\n}\ninterface CustomToastOptions<TData> extends BaseToastOptions<TData> {\n /**\n * If you need to break out of the supported styles you can use the `custom` theme. You can use `ToastContentContainer` with `Icon` and `ToastHighlight` to build your custom toast.\n */\n theme: \"custom\";\n}\n\nexport type TypeToastOptions<TData> =\n | ThemedToastOptions<TData>\n | CustomToastOptions<TData>;\n"],"mappings":"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","names":["Box","styled","ToastContainer","Box","styled"]}
|
|
1
|
+
{"version":3,"sources":["../../src/Toast.tsx","../../src/styles.ts","../../src/ToastTypes.ts"],"sourcesContent":["import type { PropsWithChildren, ReactNode, ComponentProps } from \"react\";\nimport {\n toast as toastifyToast,\n cssTransition,\n type ToastContent,\n} from \"react-toastify\";\nimport { DismissableLayerBranch } from \"@radix-ui/react-dismissable-layer\";\nimport Box from \"@sproutsocial/seeds-react-box\";\nimport Icon, { type TypeIconName } from \"@sproutsocial/seeds-react-icon\";\nimport Text from \"@sproutsocial/seeds-react-text\";\nimport { Container, ToastRoot } from \"./styles\";\nimport type { TypeToastOptions, TypeToastTheme } from \"./ToastTypes\";\nimport styled from \"styled-components\";\n\nexport const toastDismiss: typeof toastifyToast.dismiss = (...input) =>\n // @ts-ignore Not sure what this type is supposed to be\n toastifyToast.dismiss(...input);\nexport const toastIsActive: typeof toastifyToast.isActive = (...input) =>\n toastifyToast.isActive(...input);\nexport const toastUpdate: typeof toastifyToast.update = (...input) =>\n toastifyToast.update(...input);\n\nconst NoTransition = cssTransition({\n enter: \"SproutToast__none-in\",\n exit: \"SproutToast__none-out\",\n});\nconst SproutZoomTransition = cssTransition({\n enter: \"SproutToast__zoom-in\",\n exit: \"SproutToast__zoom-out\",\n});\n\nexport const ToastContainer = (\n props: Partial<ComponentProps<typeof ToastRoot>>\n) => (\n <DismissableLayerBranch style={{ pointerEvents: \"auto\" }}>\n <ToastRoot {...props} />\n </DismissableLayerBranch>\n);\n\nconst themeIcon: Record<TypeToastTheme, TypeIconName> = {\n success: \"circle-check-outline\",\n info: \"circle-i-outline\",\n warning: \"triangle-exclamation-outline\",\n error: \"triangle-exclamation-outline\",\n} as const;\n\nexport function toast<TData = unknown>(\n options: TypeToastOptions<TData>\n): ReturnType<typeof toastifyToast> {\n const {\n closeOnClick = true,\n content,\n onClose,\n persist,\n toastId: inputToastId,\n useTransition = true,\n position = \"bottom-right\",\n autoClose = persist ? false : 6000,\n transition = useTransition ? SproutZoomTransition : NoTransition,\n ...rest\n } = options;\n\n let toastId = inputToastId;\n if (!toastId && typeof content === \"string\") {\n toastId = content;\n }\n\n const renderToast: ToastContent<TData> = (toastInput) => {\n const renderedContent =\n typeof content === \"function\" ? content(toastInput) : content;\n\n if (options.theme === \"custom\") {\n return renderedContent;\n }\n\n const theme = options.theme || \"info\";\n const iconName = options.icon || themeIcon[theme];\n const containerColor =\n options.color ||\n (\n {\n success: \"container.border.success\",\n error: \"container.border.error\",\n info: \"container.border.info\",\n warning: \"container.border.warning\",\n } as const\n )[theme];\n const iconColor =\n options.color ||\n (\n {\n success: \"icon.success\",\n error: \"icon.error\",\n info: \"icon.info\",\n warning: \"icon.warning\",\n } as const\n )[theme];\n\n return (\n // TODO: if this closes when clicked, there should be a label saying \"Click to close\" that can be overridden\n <ToastContentContainer\n icon={<Icon name={iconName} color={iconColor} />}\n close={<Icon name=\"x-outline\" color=\"icon.base\" aria-hidden />}\n highlightColor={containerColor}\n >\n {renderedContent}\n </ToastContentContainer>\n );\n };\n\n const toastOptions = {\n autoClose,\n closeOnClick,\n onClose,\n toastId: toastId || undefined,\n transition,\n position,\n ...rest,\n icon: undefined,\n color: undefined,\n } as const;\n\n if (toastId && toastIsActive(toastId)) {\n toastifyToast.update<TData>(toastId, {\n ...toastOptions,\n render: renderToast,\n });\n } else {\n toastId = toastifyToast<TData>(renderToast, toastOptions);\n }\n\n return toastId;\n}\n\nexport default ToastContainer;\n\nexport const ToastContentContainer = ({\n children,\n icon,\n close,\n highlightColor,\n}: PropsWithChildren<{\n /**\n * A ReactNode in the icon slot\n */\n icon: ReactNode;\n /**\n * A ReactNode in the close button slot\n */\n close: ReactNode;\n highlightColor?: ComponentProps<typeof Box>[\"bg\"];\n}>) => {\n return (\n <Container data-qa-toast=\"\">\n {highlightColor ? (\n <ToastHighlight bg={highlightColor} aria-hidden />\n ) : null}\n\n <Box css=\"line-height: 1;\">{icon}</Box>\n\n <Box flex={1}>\n <Text as=\"div\" color=\"text.body\" data-qa-toast-content=\"\">\n {children}\n </Text>\n </Box>\n\n <Box css=\"line-height: 1;\">{close}</Box>\n </Container>\n );\n};\n\nexport const ToastHighlight = styled(Box)<ComponentProps<typeof Box>>`\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n width: 2px;\n`;\n","import styled from \"styled-components\";\nimport type { ComponentProps } from \"react\";\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\nimport \"react-toastify/dist/ReactToastify.css\";\nimport Box from \"@sproutsocial/seeds-react-box\";\nimport { ToastContainer } from \"react-toastify\";\n\nexport const TOAST_Z_INDEX = 9999;\n\nexport const Container = styled(Box)<ComponentProps<typeof Box>>`\n display: flex;\n align-items: center;\n gap: ${({ theme }) => theme.space[350]};\n font-family: ${({ theme }) => theme.fontFamily};\n ${({ theme }) => theme.typography[200]}\n position: relative;\n padding: ${({ theme }) => theme.space[350]};\n`;\n\nexport const ToastRoot = styled(ToastContainer).attrs({\n toastClassName: \"Toastify-toast-overrides\",\n hideProgressBar: true,\n closeButton: false,\n icon: false,\n position: \"bottom-right\",\n})`\n --toastify-z-index: ${TOAST_Z_INDEX};\n --toastify-toast-offset: ${({ theme }) => theme.space[400]};\n --toastify-toast-width: 360px;\n --toastify-toast-min-height: 48px;\n --toastify-toast-max-height: 70vh;\n --toastify-toast-bd-radius: ${({ theme }) => theme.radii[400]};\n --toastify-toast-background: ${({ theme }) =>\n theme.colors.container.background.base};\n /* there's margin-bottom on the last toast so we can remove this */\n --toastify-toast-bottom: 0;\n\n padding: 0;\n\n .Toastify-toast-overrides {\n background: ${({ theme }) => theme.colors.container.background.base};\n color: ${({ theme }) => theme.colors.text.body};\n box-shadow: ${({ theme }) => theme.shadows.low};\n padding: 0;\n margin-bottom: var(--toastify-toast-offset);\n }\n\n .Toastify__toast-body {\n padding: 0;\n margin: 0;\n }\n\n /* Override React Toastify's mobile width styles */\n @media only screen and (max-width: 480px) {\n .Toastify-container-overrides {\n min-width: initial !important;\n }\n }\n\n /* Zoom animation */\n @keyframes SproutToast__zoom-in {\n from {\n opacity: 0;\n transform: scale3d(0.3, 0.3, 0.3);\n }\n 50% {\n opacity: 1;\n }\n }\n @keyframes SproutToast__zoom-out {\n from {\n opacity: 1;\n }\n 50% {\n opacity: 0;\n transform: scale3d(0.3, 0.3, 0.3) translate3d(0, var(--y), 0);\n }\n to {\n opacity: 0;\n }\n }\n .SproutToast__zoom-in {\n animation: SproutToast__zoom-in ${({ theme }) => theme.duration.medium}\n ${({ theme }) => theme.easing.ease_out} both;\n }\n .SproutToast__zoom-out {\n animation: SproutToast__zoom-out ${({ theme }) => theme.duration.slow}\n ${({ theme }) => theme.easing.ease_in} both;\n }\n\n /* No animation (it's still necessary to define classes for no animation to work properly) */\n @keyframes SproutToast__none-in {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n }\n @keyframes SproutToast__none-out {\n from {\n opacity: 1;\n }\n to {\n opacity: 0;\n }\n }\n .SproutToast__none-in {\n animation: SproutToast__none-in 0s both;\n }\n .SproutToast__none-out {\n animation: SproutToast__none-out 0s both;\n }\n`;\n","import type { ComponentProps } from \"react\";\nimport { type Icon, type TypeIconName } from \"@sproutsocial/seeds-react-icon\";\nimport type { ToastContent, ToastOptions } from \"react-toastify\";\n\nexport type TypeToastTheme = \"info\" | \"success\" | \"warning\" | \"error\";\n\ninterface BaseToastOptions<TData>\n extends Omit<ToastOptions<TData>, \"closeButton\" | \"icon\" | \"type\"> {\n theme?: TypeToastTheme | \"custom\";\n content: ToastContent<TData>;\n persist?: boolean;\n useTransition?: boolean;\n}\n\ninterface ThemedToastOptions<TData> extends BaseToastOptions<TData> {\n /**\n * One of `info`, `success`, `warning`, or `error`.\n */\n theme?: TypeToastTheme;\n /**\n * @deprecated Use `custom` theme instead.\n */\n color?: ComponentProps<typeof Icon>[\"color\"];\n /**\n * @deprecated Use `custom` theme instead.\n */\n icon?: TypeIconName;\n}\ninterface CustomToastOptions<TData> extends BaseToastOptions<TData> {\n /**\n * If you need to break out of the supported styles you can use the `custom` theme. You can use `ToastContentContainer` with `Icon` and `ToastHighlight` to build your custom toast.\n */\n theme: \"custom\";\n}\n\nexport type TypeToastOptions<TData> =\n | ThemedToastOptions<TData>\n | CustomToastOptions<TData>;\n"],"mappings":"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","names":["Box","styled","ToastContainer","Box","styled"]}
|
package/dist/index.js
CHANGED
|
@@ -43,6 +43,7 @@ module.exports = __toCommonJS(index_exports);
|
|
|
43
43
|
|
|
44
44
|
// src/Toast.tsx
|
|
45
45
|
var import_react_toastify2 = require("react-toastify");
|
|
46
|
+
var import_react_dismissable_layer = require("@radix-ui/react-dismissable-layer");
|
|
46
47
|
var import_seeds_react_box2 = __toESM(require("@sproutsocial/seeds-react-box"));
|
|
47
48
|
var import_seeds_react_icon = __toESM(require("@sproutsocial/seeds-react-icon"));
|
|
48
49
|
var import_seeds_react_text = __toESM(require("@sproutsocial/seeds-react-text"));
|
|
@@ -174,7 +175,7 @@ var SproutZoomTransition = (0, import_react_toastify2.cssTransition)({
|
|
|
174
175
|
enter: "SproutToast__zoom-in",
|
|
175
176
|
exit: "SproutToast__zoom-out"
|
|
176
177
|
});
|
|
177
|
-
var ToastContainer2 = (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ToastRoot, { ...props });
|
|
178
|
+
var ToastContainer2 = (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_dismissable_layer.DismissableLayerBranch, { style: { pointerEvents: "auto" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ToastRoot, { ...props }) });
|
|
178
179
|
var themeIcon = {
|
|
179
180
|
success: "circle-check-outline",
|
|
180
181
|
info: "circle-i-outline",
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/Toast.tsx","../src/styles.ts","../src/ToastTypes.ts"],"sourcesContent":["export * from \"./Toast\";\nexport * from \"./ToastTypes\";\nexport { TOAST_Z_INDEX } from \"./styles\";\n","import type { PropsWithChildren, ReactNode, ComponentProps } from \"react\";\nimport {\n toast as toastifyToast,\n cssTransition,\n type ToastContent,\n} from \"react-toastify\";\nimport Box from \"@sproutsocial/seeds-react-box\";\nimport Icon, { type TypeIconName } from \"@sproutsocial/seeds-react-icon\";\nimport Text from \"@sproutsocial/seeds-react-text\";\nimport { Container, ToastRoot } from \"./styles\";\nimport type { TypeToastOptions, TypeToastTheme } from \"./ToastTypes\";\nimport styled from \"styled-components\";\n\nexport const toastDismiss: typeof toastifyToast.dismiss = (...input) =>\n // @ts-ignore Not sure what this type is supposed to be\n toastifyToast.dismiss(...input);\nexport const toastIsActive: typeof toastifyToast.isActive = (...input) =>\n toastifyToast.isActive(...input);\nexport const toastUpdate: typeof toastifyToast.update = (...input) =>\n toastifyToast.update(...input);\n\nconst NoTransition = cssTransition({\n enter: \"SproutToast__none-in\",\n exit: \"SproutToast__none-out\",\n});\nconst SproutZoomTransition = cssTransition({\n enter: \"SproutToast__zoom-in\",\n exit: \"SproutToast__zoom-out\",\n});\n\nexport const ToastContainer = (\n props: Partial<ComponentProps<typeof ToastRoot>>\n) => <ToastRoot {...props} />;\n\nconst themeIcon: Record<TypeToastTheme, TypeIconName> = {\n success: \"circle-check-outline\",\n info: \"circle-i-outline\",\n warning: \"triangle-exclamation-outline\",\n error: \"triangle-exclamation-outline\",\n} as const;\n\nexport function toast<TData = unknown>(\n options: TypeToastOptions<TData>\n): ReturnType<typeof toastifyToast> {\n const {\n closeOnClick = true,\n content,\n onClose,\n persist,\n toastId: inputToastId,\n useTransition = true,\n position = \"bottom-right\",\n autoClose = persist ? false : 6000,\n transition = useTransition ? SproutZoomTransition : NoTransition,\n ...rest\n } = options;\n\n let toastId = inputToastId;\n if (!toastId && typeof content === \"string\") {\n toastId = content;\n }\n\n const renderToast: ToastContent<TData> = (toastInput) => {\n const renderedContent =\n typeof content === \"function\" ? content(toastInput) : content;\n\n if (options.theme === \"custom\") {\n return renderedContent;\n }\n\n const theme = options.theme || \"info\";\n const iconName = options.icon || themeIcon[theme];\n const containerColor =\n options.color ||\n (\n {\n success: \"container.border.success\",\n error: \"container.border.error\",\n info: \"container.border.info\",\n warning: \"container.border.warning\",\n } as const\n )[theme];\n const iconColor =\n options.color ||\n (\n {\n success: \"icon.success\",\n error: \"icon.error\",\n info: \"icon.info\",\n warning: \"icon.warning\",\n } as const\n )[theme];\n\n return (\n // TODO: if this closes when clicked, there should be a label saying \"Click to close\" that can be overridden\n <ToastContentContainer\n icon={<Icon name={iconName} color={iconColor} />}\n close={<Icon name=\"x-outline\" color=\"icon.base\" aria-hidden />}\n highlightColor={containerColor}\n >\n {renderedContent}\n </ToastContentContainer>\n );\n };\n\n const toastOptions = {\n autoClose,\n closeOnClick,\n onClose,\n toastId: toastId || undefined,\n transition,\n position,\n ...rest,\n icon: undefined,\n color: undefined,\n } as const;\n\n if (toastId && toastIsActive(toastId)) {\n toastifyToast.update<TData>(toastId, {\n ...toastOptions,\n render: renderToast,\n });\n } else {\n toastId = toastifyToast<TData>(renderToast, toastOptions);\n }\n\n return toastId;\n}\n\nexport default ToastContainer;\n\nexport const ToastContentContainer = ({\n children,\n icon,\n close,\n highlightColor,\n}: PropsWithChildren<{\n /**\n * A ReactNode in the icon slot\n */\n icon: ReactNode;\n /**\n * A ReactNode in the close button slot\n */\n close: ReactNode;\n highlightColor?: ComponentProps<typeof Box>[\"bg\"];\n}>) => {\n return (\n <Container data-qa-toast=\"\">\n {highlightColor ? (\n <ToastHighlight bg={highlightColor} aria-hidden />\n ) : null}\n\n <Box css=\"line-height: 1;\">{icon}</Box>\n\n <Box flex={1}>\n <Text as=\"div\" color=\"text.body\" data-qa-toast-content=\"\">\n {children}\n </Text>\n </Box>\n\n <Box css=\"line-height: 1;\">{close}</Box>\n </Container>\n );\n};\n\nexport const ToastHighlight = styled(Box)<ComponentProps<typeof Box>>`\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n width: 2px;\n`;\n","import styled from \"styled-components\";\nimport type { ComponentProps } from \"react\";\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\nimport \"react-toastify/dist/ReactToastify.css\";\nimport Box from \"@sproutsocial/seeds-react-box\";\nimport { ToastContainer } from \"react-toastify\";\n\nexport const TOAST_Z_INDEX = 9999;\n\nexport const Container = styled(Box)<ComponentProps<typeof Box>>`\n display: flex;\n align-items: center;\n gap: ${({ theme }) => theme.space[350]};\n font-family: ${({ theme }) => theme.fontFamily};\n ${({ theme }) => theme.typography[200]}\n position: relative;\n padding: ${({ theme }) => theme.space[350]};\n`;\n\nexport const ToastRoot = styled(ToastContainer).attrs({\n toastClassName: \"Toastify-toast-overrides\",\n hideProgressBar: true,\n closeButton: false,\n icon: false,\n position: \"bottom-right\",\n})`\n --toastify-z-index: ${TOAST_Z_INDEX};\n --toastify-toast-offset: ${({ theme }) => theme.space[400]};\n --toastify-toast-width: 360px;\n --toastify-toast-min-height: 48px;\n --toastify-toast-max-height: 70vh;\n --toastify-toast-bd-radius: ${({ theme }) => theme.radii[400]};\n --toastify-toast-background: ${({ theme }) =>\n theme.colors.container.background.base};\n /* there's margin-bottom on the last toast so we can remove this */\n --toastify-toast-bottom: 0;\n\n padding: 0;\n\n .Toastify-toast-overrides {\n background: ${({ theme }) => theme.colors.container.background.base};\n color: ${({ theme }) => theme.colors.text.body};\n box-shadow: ${({ theme }) => theme.shadows.low};\n padding: 0;\n margin-bottom: var(--toastify-toast-offset);\n }\n\n .Toastify__toast-body {\n padding: 0;\n margin: 0;\n }\n\n /* Override React Toastify's mobile width styles */\n @media only screen and (max-width: 480px) {\n .Toastify-container-overrides {\n min-width: initial !important;\n }\n }\n\n /* Zoom animation */\n @keyframes SproutToast__zoom-in {\n from {\n opacity: 0;\n transform: scale3d(0.3, 0.3, 0.3);\n }\n 50% {\n opacity: 1;\n }\n }\n @keyframes SproutToast__zoom-out {\n from {\n opacity: 1;\n }\n 50% {\n opacity: 0;\n transform: scale3d(0.3, 0.3, 0.3) translate3d(0, var(--y), 0);\n }\n to {\n opacity: 0;\n }\n }\n .SproutToast__zoom-in {\n animation: SproutToast__zoom-in ${({ theme }) => theme.duration.medium}\n ${({ theme }) => theme.easing.ease_out} both;\n }\n .SproutToast__zoom-out {\n animation: SproutToast__zoom-out ${({ theme }) => theme.duration.slow}\n ${({ theme }) => theme.easing.ease_in} both;\n }\n\n /* No animation (it's still necessary to define classes for no animation to work properly) */\n @keyframes SproutToast__none-in {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n }\n @keyframes SproutToast__none-out {\n from {\n opacity: 1;\n }\n to {\n opacity: 0;\n }\n }\n .SproutToast__none-in {\n animation: SproutToast__none-in 0s both;\n }\n .SproutToast__none-out {\n animation: SproutToast__none-out 0s both;\n }\n`;\n","import type { ComponentProps } from \"react\";\nimport { type Icon, type TypeIconName } from \"@sproutsocial/seeds-react-icon\";\nimport type { ToastContent, ToastOptions } from \"react-toastify\";\n\nexport type TypeToastTheme = \"info\" | \"success\" | \"warning\" | \"error\";\n\ninterface BaseToastOptions<TData>\n extends Omit<ToastOptions<TData>, \"closeButton\" | \"icon\" | \"type\"> {\n theme?: TypeToastTheme | \"custom\";\n content: ToastContent<TData>;\n persist?: boolean;\n useTransition?: boolean;\n}\n\ninterface ThemedToastOptions<TData> extends BaseToastOptions<TData> {\n /**\n * One of `info`, `success`, `warning`, or `error`.\n */\n theme?: TypeToastTheme;\n /**\n * @deprecated Use `custom` theme instead.\n */\n color?: ComponentProps<typeof Icon>[\"color\"];\n /**\n * @deprecated Use `custom` theme instead.\n */\n icon?: TypeIconName;\n}\ninterface CustomToastOptions<TData> extends BaseToastOptions<TData> {\n /**\n * If you need to break out of the supported styles you can use the `custom` theme. You can use `ToastContentContainer` with `Icon` and `ToastHighlight` to build your custom toast.\n */\n theme: \"custom\";\n}\n\nexport type TypeToastOptions<TData> =\n | ThemedToastOptions<TData>\n | CustomToastOptions<TData>;\n"],"mappings":"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","names":["ToastContainer","import_react_toastify","import_seeds_react_box","styled","Box","import_styled_components","toastifyToast","ToastContainer","Icon","Box","Text","styled","import_seeds_react_icon"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/Toast.tsx","../src/styles.ts","../src/ToastTypes.ts"],"sourcesContent":["export * from \"./Toast\";\nexport * from \"./ToastTypes\";\nexport { TOAST_Z_INDEX } from \"./styles\";\n","import type { PropsWithChildren, ReactNode, ComponentProps } from \"react\";\nimport {\n toast as toastifyToast,\n cssTransition,\n type ToastContent,\n} from \"react-toastify\";\nimport { DismissableLayerBranch } from \"@radix-ui/react-dismissable-layer\";\nimport Box from \"@sproutsocial/seeds-react-box\";\nimport Icon, { type TypeIconName } from \"@sproutsocial/seeds-react-icon\";\nimport Text from \"@sproutsocial/seeds-react-text\";\nimport { Container, ToastRoot } from \"./styles\";\nimport type { TypeToastOptions, TypeToastTheme } from \"./ToastTypes\";\nimport styled from \"styled-components\";\n\nexport const toastDismiss: typeof toastifyToast.dismiss = (...input) =>\n // @ts-ignore Not sure what this type is supposed to be\n toastifyToast.dismiss(...input);\nexport const toastIsActive: typeof toastifyToast.isActive = (...input) =>\n toastifyToast.isActive(...input);\nexport const toastUpdate: typeof toastifyToast.update = (...input) =>\n toastifyToast.update(...input);\n\nconst NoTransition = cssTransition({\n enter: \"SproutToast__none-in\",\n exit: \"SproutToast__none-out\",\n});\nconst SproutZoomTransition = cssTransition({\n enter: \"SproutToast__zoom-in\",\n exit: \"SproutToast__zoom-out\",\n});\n\nexport const ToastContainer = (\n props: Partial<ComponentProps<typeof ToastRoot>>\n) => (\n <DismissableLayerBranch style={{ pointerEvents: \"auto\" }}>\n <ToastRoot {...props} />\n </DismissableLayerBranch>\n);\n\nconst themeIcon: Record<TypeToastTheme, TypeIconName> = {\n success: \"circle-check-outline\",\n info: \"circle-i-outline\",\n warning: \"triangle-exclamation-outline\",\n error: \"triangle-exclamation-outline\",\n} as const;\n\nexport function toast<TData = unknown>(\n options: TypeToastOptions<TData>\n): ReturnType<typeof toastifyToast> {\n const {\n closeOnClick = true,\n content,\n onClose,\n persist,\n toastId: inputToastId,\n useTransition = true,\n position = \"bottom-right\",\n autoClose = persist ? false : 6000,\n transition = useTransition ? SproutZoomTransition : NoTransition,\n ...rest\n } = options;\n\n let toastId = inputToastId;\n if (!toastId && typeof content === \"string\") {\n toastId = content;\n }\n\n const renderToast: ToastContent<TData> = (toastInput) => {\n const renderedContent =\n typeof content === \"function\" ? content(toastInput) : content;\n\n if (options.theme === \"custom\") {\n return renderedContent;\n }\n\n const theme = options.theme || \"info\";\n const iconName = options.icon || themeIcon[theme];\n const containerColor =\n options.color ||\n (\n {\n success: \"container.border.success\",\n error: \"container.border.error\",\n info: \"container.border.info\",\n warning: \"container.border.warning\",\n } as const\n )[theme];\n const iconColor =\n options.color ||\n (\n {\n success: \"icon.success\",\n error: \"icon.error\",\n info: \"icon.info\",\n warning: \"icon.warning\",\n } as const\n )[theme];\n\n return (\n // TODO: if this closes when clicked, there should be a label saying \"Click to close\" that can be overridden\n <ToastContentContainer\n icon={<Icon name={iconName} color={iconColor} />}\n close={<Icon name=\"x-outline\" color=\"icon.base\" aria-hidden />}\n highlightColor={containerColor}\n >\n {renderedContent}\n </ToastContentContainer>\n );\n };\n\n const toastOptions = {\n autoClose,\n closeOnClick,\n onClose,\n toastId: toastId || undefined,\n transition,\n position,\n ...rest,\n icon: undefined,\n color: undefined,\n } as const;\n\n if (toastId && toastIsActive(toastId)) {\n toastifyToast.update<TData>(toastId, {\n ...toastOptions,\n render: renderToast,\n });\n } else {\n toastId = toastifyToast<TData>(renderToast, toastOptions);\n }\n\n return toastId;\n}\n\nexport default ToastContainer;\n\nexport const ToastContentContainer = ({\n children,\n icon,\n close,\n highlightColor,\n}: PropsWithChildren<{\n /**\n * A ReactNode in the icon slot\n */\n icon: ReactNode;\n /**\n * A ReactNode in the close button slot\n */\n close: ReactNode;\n highlightColor?: ComponentProps<typeof Box>[\"bg\"];\n}>) => {\n return (\n <Container data-qa-toast=\"\">\n {highlightColor ? (\n <ToastHighlight bg={highlightColor} aria-hidden />\n ) : null}\n\n <Box css=\"line-height: 1;\">{icon}</Box>\n\n <Box flex={1}>\n <Text as=\"div\" color=\"text.body\" data-qa-toast-content=\"\">\n {children}\n </Text>\n </Box>\n\n <Box css=\"line-height: 1;\">{close}</Box>\n </Container>\n );\n};\n\nexport const ToastHighlight = styled(Box)<ComponentProps<typeof Box>>`\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n width: 2px;\n`;\n","import styled from \"styled-components\";\nimport type { ComponentProps } from \"react\";\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\nimport \"react-toastify/dist/ReactToastify.css\";\nimport Box from \"@sproutsocial/seeds-react-box\";\nimport { ToastContainer } from \"react-toastify\";\n\nexport const TOAST_Z_INDEX = 9999;\n\nexport const Container = styled(Box)<ComponentProps<typeof Box>>`\n display: flex;\n align-items: center;\n gap: ${({ theme }) => theme.space[350]};\n font-family: ${({ theme }) => theme.fontFamily};\n ${({ theme }) => theme.typography[200]}\n position: relative;\n padding: ${({ theme }) => theme.space[350]};\n`;\n\nexport const ToastRoot = styled(ToastContainer).attrs({\n toastClassName: \"Toastify-toast-overrides\",\n hideProgressBar: true,\n closeButton: false,\n icon: false,\n position: \"bottom-right\",\n})`\n --toastify-z-index: ${TOAST_Z_INDEX};\n --toastify-toast-offset: ${({ theme }) => theme.space[400]};\n --toastify-toast-width: 360px;\n --toastify-toast-min-height: 48px;\n --toastify-toast-max-height: 70vh;\n --toastify-toast-bd-radius: ${({ theme }) => theme.radii[400]};\n --toastify-toast-background: ${({ theme }) =>\n theme.colors.container.background.base};\n /* there's margin-bottom on the last toast so we can remove this */\n --toastify-toast-bottom: 0;\n\n padding: 0;\n\n .Toastify-toast-overrides {\n background: ${({ theme }) => theme.colors.container.background.base};\n color: ${({ theme }) => theme.colors.text.body};\n box-shadow: ${({ theme }) => theme.shadows.low};\n padding: 0;\n margin-bottom: var(--toastify-toast-offset);\n }\n\n .Toastify__toast-body {\n padding: 0;\n margin: 0;\n }\n\n /* Override React Toastify's mobile width styles */\n @media only screen and (max-width: 480px) {\n .Toastify-container-overrides {\n min-width: initial !important;\n }\n }\n\n /* Zoom animation */\n @keyframes SproutToast__zoom-in {\n from {\n opacity: 0;\n transform: scale3d(0.3, 0.3, 0.3);\n }\n 50% {\n opacity: 1;\n }\n }\n @keyframes SproutToast__zoom-out {\n from {\n opacity: 1;\n }\n 50% {\n opacity: 0;\n transform: scale3d(0.3, 0.3, 0.3) translate3d(0, var(--y), 0);\n }\n to {\n opacity: 0;\n }\n }\n .SproutToast__zoom-in {\n animation: SproutToast__zoom-in ${({ theme }) => theme.duration.medium}\n ${({ theme }) => theme.easing.ease_out} both;\n }\n .SproutToast__zoom-out {\n animation: SproutToast__zoom-out ${({ theme }) => theme.duration.slow}\n ${({ theme }) => theme.easing.ease_in} both;\n }\n\n /* No animation (it's still necessary to define classes for no animation to work properly) */\n @keyframes SproutToast__none-in {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n }\n @keyframes SproutToast__none-out {\n from {\n opacity: 1;\n }\n to {\n opacity: 0;\n }\n }\n .SproutToast__none-in {\n animation: SproutToast__none-in 0s both;\n }\n .SproutToast__none-out {\n animation: SproutToast__none-out 0s both;\n }\n`;\n","import type { ComponentProps } from \"react\";\nimport { type Icon, type TypeIconName } from \"@sproutsocial/seeds-react-icon\";\nimport type { ToastContent, ToastOptions } from \"react-toastify\";\n\nexport type TypeToastTheme = \"info\" | \"success\" | \"warning\" | \"error\";\n\ninterface BaseToastOptions<TData>\n extends Omit<ToastOptions<TData>, \"closeButton\" | \"icon\" | \"type\"> {\n theme?: TypeToastTheme | \"custom\";\n content: ToastContent<TData>;\n persist?: boolean;\n useTransition?: boolean;\n}\n\ninterface ThemedToastOptions<TData> extends BaseToastOptions<TData> {\n /**\n * One of `info`, `success`, `warning`, or `error`.\n */\n theme?: TypeToastTheme;\n /**\n * @deprecated Use `custom` theme instead.\n */\n color?: ComponentProps<typeof Icon>[\"color\"];\n /**\n * @deprecated Use `custom` theme instead.\n */\n icon?: TypeIconName;\n}\ninterface CustomToastOptions<TData> extends BaseToastOptions<TData> {\n /**\n * If you need to break out of the supported styles you can use the `custom` theme. You can use `ToastContentContainer` with `Icon` and `ToastHighlight` to build your custom toast.\n */\n theme: \"custom\";\n}\n\nexport type TypeToastOptions<TData> =\n | ThemedToastOptions<TData>\n | CustomToastOptions<TData>;\n"],"mappings":"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","names":["ToastContainer","import_react_toastify","import_seeds_react_box","styled","Box","import_styled_components","toastifyToast","ToastContainer","Icon","Box","Text","styled","import_seeds_react_icon"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sproutsocial/seeds-react-toast",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.24",
|
|
4
4
|
"description": "Seeds React Toast",
|
|
5
5
|
"author": "Sprout Social, Inc.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -16,10 +16,11 @@
|
|
|
16
16
|
"typecheck": "tsc --noEmit"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@
|
|
19
|
+
"@radix-ui/react-dismissable-layer": "^1.1.11",
|
|
20
|
+
"@sproutsocial/seeds-react-theme": "^3.6.0",
|
|
20
21
|
"@sproutsocial/seeds-react-system-props": "^3.0.1",
|
|
21
|
-
"@sproutsocial/seeds-react-icon": "^2.2.
|
|
22
|
-
"@sproutsocial/seeds-react-box": "^1.1.
|
|
22
|
+
"@sproutsocial/seeds-react-icon": "^2.2.5",
|
|
23
|
+
"@sproutsocial/seeds-react-box": "^1.1.14",
|
|
23
24
|
"@sproutsocial/seeds-react-text": "^1.4.0"
|
|
24
25
|
},
|
|
25
26
|
"devDependencies": {
|
package/src/Toast.stories.tsx
CHANGED
|
@@ -12,6 +12,13 @@ import Link from "@sproutsocial/seeds-react-link";
|
|
|
12
12
|
import Radio from "@sproutsocial/seeds-react-radio";
|
|
13
13
|
import Switch from "@sproutsocial/seeds-react-switch";
|
|
14
14
|
import Text from "@sproutsocial/seeds-react-text";
|
|
15
|
+
import {
|
|
16
|
+
Modal,
|
|
17
|
+
ModalBody,
|
|
18
|
+
ModalCustomFooter,
|
|
19
|
+
ModalFooter,
|
|
20
|
+
ModalHeader,
|
|
21
|
+
} from "@sproutsocial/seeds-react-modal/v2";
|
|
15
22
|
import {
|
|
16
23
|
toast,
|
|
17
24
|
toastDismiss,
|
|
@@ -298,3 +305,54 @@ export const WithLink: Story = {
|
|
|
298
305
|
);
|
|
299
306
|
},
|
|
300
307
|
};
|
|
308
|
+
|
|
309
|
+
export const WithModalV2: Story = {
|
|
310
|
+
render: () => {
|
|
311
|
+
const triggerToast = () =>
|
|
312
|
+
toast({
|
|
313
|
+
persist: true,
|
|
314
|
+
content: (
|
|
315
|
+
<Box
|
|
316
|
+
display="inline-flex"
|
|
317
|
+
width="100%"
|
|
318
|
+
justifyContent="space-between"
|
|
319
|
+
alignItems="flex-start"
|
|
320
|
+
>
|
|
321
|
+
<Text>Message completed</Text>
|
|
322
|
+
<Link
|
|
323
|
+
onClick={() => alert("Clicked!")}
|
|
324
|
+
ml={300}
|
|
325
|
+
fontSize={200}
|
|
326
|
+
p={0}
|
|
327
|
+
>
|
|
328
|
+
Undo
|
|
329
|
+
</Link>
|
|
330
|
+
</Box>
|
|
331
|
+
),
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
return (
|
|
335
|
+
<Box>
|
|
336
|
+
<ToastContainer />
|
|
337
|
+
|
|
338
|
+
<Modal
|
|
339
|
+
modalTrigger={<Button appearance="secondary">Open Modal</Button>}
|
|
340
|
+
closeButtonAriaLabel="Close Modal"
|
|
341
|
+
>
|
|
342
|
+
<ModalHeader title="Testing Toasts + Modal v2" />
|
|
343
|
+
<ModalBody>
|
|
344
|
+
<Text as="p" mb={400}>
|
|
345
|
+
Click the button below to fire a toast while the modal is open.
|
|
346
|
+
The toast should be clickable and dismissable.
|
|
347
|
+
</Text>
|
|
348
|
+
</ModalBody>
|
|
349
|
+
<ModalCustomFooter>
|
|
350
|
+
<Button appearance="secondary" onClick={triggerToast}>
|
|
351
|
+
Fire toast
|
|
352
|
+
</Button>
|
|
353
|
+
</ModalCustomFooter>
|
|
354
|
+
</Modal>
|
|
355
|
+
</Box>
|
|
356
|
+
);
|
|
357
|
+
},
|
|
358
|
+
};
|
package/src/Toast.tsx
CHANGED
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
cssTransition,
|
|
5
5
|
type ToastContent,
|
|
6
6
|
} from "react-toastify";
|
|
7
|
+
import { DismissableLayerBranch } from "@radix-ui/react-dismissable-layer";
|
|
7
8
|
import Box from "@sproutsocial/seeds-react-box";
|
|
8
9
|
import Icon, { type TypeIconName } from "@sproutsocial/seeds-react-icon";
|
|
9
10
|
import Text from "@sproutsocial/seeds-react-text";
|
|
@@ -30,7 +31,11 @@ const SproutZoomTransition = cssTransition({
|
|
|
30
31
|
|
|
31
32
|
export const ToastContainer = (
|
|
32
33
|
props: Partial<ComponentProps<typeof ToastRoot>>
|
|
33
|
-
) =>
|
|
34
|
+
) => (
|
|
35
|
+
<DismissableLayerBranch style={{ pointerEvents: "auto" }}>
|
|
36
|
+
<ToastRoot {...props} />
|
|
37
|
+
</DismissableLayerBranch>
|
|
38
|
+
);
|
|
34
39
|
|
|
35
40
|
const themeIcon: Record<TypeToastTheme, TypeIconName> = {
|
|
36
41
|
success: "circle-check-outline",
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
import React from "react";
|
|
3
|
+
import {
|
|
4
|
+
render,
|
|
5
|
+
screen,
|
|
6
|
+
waitFor,
|
|
7
|
+
cleanup,
|
|
8
|
+
fireEvent,
|
|
9
|
+
} from "@sproutsocial/seeds-react-testing-library";
|
|
10
|
+
import userEvent from "@testing-library/user-event";
|
|
11
|
+
import { toast, ToastContainer, toastDismiss } from "../Toast";
|
|
12
|
+
|
|
13
|
+
// Mock matchMedia
|
|
14
|
+
beforeAll(() => {
|
|
15
|
+
Object.defineProperty(window, "matchMedia", {
|
|
16
|
+
writable: true,
|
|
17
|
+
value: jest.fn().mockImplementation((query) => ({
|
|
18
|
+
matches: false,
|
|
19
|
+
media: query,
|
|
20
|
+
onchange: null,
|
|
21
|
+
addListener: jest.fn(),
|
|
22
|
+
removeListener: jest.fn(),
|
|
23
|
+
addEventListener: jest.fn(),
|
|
24
|
+
removeEventListener: jest.fn(),
|
|
25
|
+
dispatchEvent: jest.fn(),
|
|
26
|
+
})),
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
afterEach(() => {
|
|
31
|
+
toastDismiss();
|
|
32
|
+
cleanup();
|
|
33
|
+
document.body.style.pointerEvents = "";
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
describe("Toast", () => {
|
|
37
|
+
describe("DismissableLayerBranch wrapper", () => {
|
|
38
|
+
it("should render inside a DismissableLayerBranch with pointer-events: auto", () => {
|
|
39
|
+
const { container } = render(<ToastContainer />);
|
|
40
|
+
const wrapper = container.firstElementChild as HTMLElement;
|
|
41
|
+
expect(wrapper.style.pointerEvents).toBe("auto");
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("should render the ToastRoot as a child of the branch wrapper", () => {
|
|
45
|
+
const { container } = render(<ToastContainer />);
|
|
46
|
+
const wrapper = container.firstElementChild as HTMLElement;
|
|
47
|
+
// The branch div should contain the Toastify container
|
|
48
|
+
const toastifyContainer = wrapper.querySelector(".Toastify");
|
|
49
|
+
expect(toastifyContainer).toBeInTheDocument();
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
describe("clickability when Modal V2 is open", () => {
|
|
54
|
+
it("should be clickable when document.body has pointer-events: none", async () => {
|
|
55
|
+
const user = userEvent.setup();
|
|
56
|
+
const handleClick = jest.fn();
|
|
57
|
+
|
|
58
|
+
render(
|
|
59
|
+
<>
|
|
60
|
+
<ToastContainer />
|
|
61
|
+
<button
|
|
62
|
+
onClick={() =>
|
|
63
|
+
toast({
|
|
64
|
+
persist: true,
|
|
65
|
+
content: (
|
|
66
|
+
<button data-testid="toast-action" onClick={handleClick}>
|
|
67
|
+
Click me
|
|
68
|
+
</button>
|
|
69
|
+
),
|
|
70
|
+
})
|
|
71
|
+
}
|
|
72
|
+
>
|
|
73
|
+
Trigger
|
|
74
|
+
</button>
|
|
75
|
+
</>
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
await user.click(screen.getByText("Trigger"));
|
|
79
|
+
|
|
80
|
+
await waitFor(() => {
|
|
81
|
+
expect(screen.getByTestId("toast-action")).toBeInTheDocument();
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// Simulate what Radix Dialog does when a modal opens
|
|
85
|
+
document.body.style.pointerEvents = "none";
|
|
86
|
+
|
|
87
|
+
await user.click(screen.getByTestId("toast-action"));
|
|
88
|
+
expect(handleClick).toHaveBeenCalledTimes(1);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it("should allow interacting with links inside a toast when body pointer-events are disabled", async () => {
|
|
92
|
+
const user = userEvent.setup();
|
|
93
|
+
const handleClick = jest.fn();
|
|
94
|
+
|
|
95
|
+
render(
|
|
96
|
+
<>
|
|
97
|
+
<ToastContainer />
|
|
98
|
+
<button
|
|
99
|
+
onClick={() =>
|
|
100
|
+
toast({
|
|
101
|
+
persist: true,
|
|
102
|
+
content: (
|
|
103
|
+
<a
|
|
104
|
+
data-testid="toast-link"
|
|
105
|
+
href="#"
|
|
106
|
+
onClick={(e) => {
|
|
107
|
+
e.preventDefault();
|
|
108
|
+
handleClick();
|
|
109
|
+
}}
|
|
110
|
+
>
|
|
111
|
+
Undo
|
|
112
|
+
</a>
|
|
113
|
+
),
|
|
114
|
+
})
|
|
115
|
+
}
|
|
116
|
+
>
|
|
117
|
+
Trigger
|
|
118
|
+
</button>
|
|
119
|
+
</>
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
await user.click(screen.getByText("Trigger"));
|
|
123
|
+
|
|
124
|
+
await waitFor(() => {
|
|
125
|
+
expect(screen.getByTestId("toast-link")).toBeInTheDocument();
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
document.body.style.pointerEvents = "none";
|
|
129
|
+
|
|
130
|
+
await user.click(screen.getByTestId("toast-link"));
|
|
131
|
+
expect(handleClick).toHaveBeenCalledTimes(1);
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
describe("normal behavior without Modal V2", () => {
|
|
136
|
+
it("should be clickable when body has default pointer-events", async () => {
|
|
137
|
+
const user = userEvent.setup();
|
|
138
|
+
const handleClick = jest.fn();
|
|
139
|
+
|
|
140
|
+
render(
|
|
141
|
+
<>
|
|
142
|
+
<ToastContainer />
|
|
143
|
+
<button
|
|
144
|
+
onClick={() =>
|
|
145
|
+
toast({
|
|
146
|
+
persist: true,
|
|
147
|
+
content: (
|
|
148
|
+
<button data-testid="toast-action" onClick={handleClick}>
|
|
149
|
+
Click me
|
|
150
|
+
</button>
|
|
151
|
+
),
|
|
152
|
+
})
|
|
153
|
+
}
|
|
154
|
+
>
|
|
155
|
+
Trigger
|
|
156
|
+
</button>
|
|
157
|
+
</>
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
await user.click(screen.getByText("Trigger"));
|
|
161
|
+
|
|
162
|
+
await waitFor(() => {
|
|
163
|
+
expect(screen.getByTestId("toast-action")).toBeInTheDocument();
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
// No pointer-events: none on body — normal usage
|
|
167
|
+
await user.click(screen.getByTestId("toast-action"));
|
|
168
|
+
expect(handleClick).toHaveBeenCalledTimes(1);
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
});
|