@impulse-ui-native/toast 0.0.0-stage → 6.1.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 (60) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +111 -2
  3. package/dist/components/index.d.mts +20 -0
  4. package/dist/components/index.js +7 -0
  5. package/dist/components/index.js.map +1 -0
  6. package/dist/components/toast-action.d.mts +10 -0
  7. package/dist/components/toast-action.js +64 -0
  8. package/dist/components/toast-action.js.map +1 -0
  9. package/dist/components/toast-close.d.mts +10 -0
  10. package/dist/components/toast-close.js +13 -0
  11. package/dist/components/toast-close.js.map +1 -0
  12. package/dist/components/toast-content.d.mts +10 -0
  13. package/dist/components/toast-content.js +27 -0
  14. package/dist/components/toast-content.js.map +1 -0
  15. package/dist/components/toast-description.d.mts +10 -0
  16. package/dist/components/toast-description.js +22 -0
  17. package/dist/components/toast-description.js.map +1 -0
  18. package/dist/components/toast-icon.d.mts +10 -0
  19. package/dist/components/toast-icon.js +33 -0
  20. package/dist/components/toast-icon.js.map +1 -0
  21. package/dist/components/toast-parts.d.mts +18 -0
  22. package/dist/components/toast-parts.js +20 -0
  23. package/dist/components/toast-parts.js.map +1 -0
  24. package/dist/components/toast-root.d.mts +10 -0
  25. package/dist/components/toast-root.js +103 -0
  26. package/dist/components/toast-root.js.map +1 -0
  27. package/dist/components/toast-title.d.mts +10 -0
  28. package/dist/components/toast-title.js +22 -0
  29. package/dist/components/toast-title.js.map +1 -0
  30. package/dist/components/toast.d.mts +10 -0
  31. package/dist/components/toast.js +48 -0
  32. package/dist/components/toast.js.map +1 -0
  33. package/dist/constants/toast-icons.constants.d.mts +17 -0
  34. package/dist/constants/toast-icons.constants.js +14 -0
  35. package/dist/constants/toast-icons.constants.js.map +1 -0
  36. package/dist/constants/toast.constants.d.mts +6 -0
  37. package/dist/constants/toast.constants.js +11 -0
  38. package/dist/constants/toast.constants.js.map +1 -0
  39. package/dist/contexts/toast.context.d.mts +9 -0
  40. package/dist/contexts/toast.context.js +8 -0
  41. package/dist/contexts/toast.context.js.map +1 -0
  42. package/dist/hooks/use-toast-context.hook.d.mts +9 -0
  43. package/dist/hooks/use-toast-context.hook.js +13 -0
  44. package/dist/hooks/use-toast-context.hook.js.map +1 -0
  45. package/dist/hooks/use-toast-lifecycle.hook.d.mts +15 -0
  46. package/dist/hooks/use-toast-lifecycle.hook.js +129 -0
  47. package/dist/hooks/use-toast-lifecycle.hook.js.map +1 -0
  48. package/dist/hooks/use-toast-timer.hook.d.mts +3 -0
  49. package/dist/hooks/use-toast-timer.hook.js +50 -0
  50. package/dist/hooks/use-toast-timer.hook.js.map +1 -0
  51. package/dist/index.d.mts +7 -0
  52. package/dist/index.js +3 -0
  53. package/dist/index.js.map +1 -0
  54. package/dist/types/index.d.mts +5 -0
  55. package/dist/types/index.js +2 -0
  56. package/dist/types/index.js.map +1 -0
  57. package/dist/types/toast.types.d.mts +35 -0
  58. package/dist/types/toast.types.js +1 -0
  59. package/dist/types/toast.types.js.map +1 -0
  60. package/package.json +67 -3
@@ -0,0 +1,10 @@
1
+ import * as react from 'react';
2
+ import * as react_jsx_runtime from 'react/jsx-runtime';
3
+ import { ToastProps } from '../types/toast.types.mjs';
4
+ import '@impulse-ui-native/overlay';
5
+ import '@impulse-ui-native/primitives';
6
+ import '@impulse-ui-native/theme';
7
+
8
+ declare const ToastComponent: react.MemoExoticComponent<({ children, title, description, action, actionProps, tone, hideIcon, hideClose, ...props }: ToastProps) => react_jsx_runtime.JSX.Element>;
9
+
10
+ export { ToastComponent };
@@ -0,0 +1,48 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { memo } from "react";
3
+ import { Icon } from "@impulse-ui-native/icon/components/icon";
4
+ import { XIcon } from "@impulse-ui-native/icon/icons/x";
5
+ import { useComponentsTokens } from "@impulse-ui-native/theme";
6
+ import { ToastIcons } from "../constants/toast-icons.constants";
7
+ import { Toast } from "./toast-parts";
8
+ const ToastComponent = memo(function ToastComponent2({
9
+ children,
10
+ title,
11
+ description,
12
+ action,
13
+ actionProps,
14
+ tone = "success",
15
+ hideIcon = false,
16
+ hideClose = false,
17
+ ...props
18
+ }) {
19
+ const tokens = useComponentsTokens().toast;
20
+ return /* @__PURE__ */ jsxs(Toast.Root, { ...props, tone, children: [
21
+ !hideIcon ? /* @__PURE__ */ jsx(Toast.Icon, { children: /* @__PURE__ */ jsx(
22
+ Icon,
23
+ {
24
+ icon: ToastIcons[tone],
25
+ size: tokens.iconSize,
26
+ color: tokens.tones[tone].value
27
+ }
28
+ ) }) : null,
29
+ /* @__PURE__ */ jsxs(Toast.Content, { children: [
30
+ title ? /* @__PURE__ */ jsx(Toast.Title, { children: title }) : null,
31
+ description !== null && description !== void 0 ? /* @__PURE__ */ jsx(Toast.Description, { children: description }) : null,
32
+ children
33
+ ] }),
34
+ action !== null && action !== void 0 ? /* @__PURE__ */ jsx(Toast.Action, { ...actionProps, children: action }) : null,
35
+ !hideClose ? /* @__PURE__ */ jsx(Toast.Close, { children: /* @__PURE__ */ jsx(
36
+ Icon,
37
+ {
38
+ icon: XIcon,
39
+ size: tokens.iconSize,
40
+ color: tokens.descriptionColor
41
+ }
42
+ ) }) : null
43
+ ] });
44
+ });
45
+ export {
46
+ ToastComponent
47
+ };
48
+ //# sourceMappingURL=toast.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/toast.tsx"],"sourcesContent":["import { memo } from \"react\";\n\nimport { Icon } from \"@impulse-ui-native/icon/components/icon\";\nimport { XIcon } from \"@impulse-ui-native/icon/icons/x\";\nimport { useComponentsTokens } from \"@impulse-ui-native/theme\";\n\nimport type { ToastProps } from \"../types\";\nimport { ToastIcons } from \"../constants/toast-icons.constants\";\nimport { Toast } from \"./toast-parts\";\n\nexport const ToastComponent = memo(function ToastComponent({\n children,\n title,\n description,\n action,\n actionProps,\n tone = \"success\",\n hideIcon = false,\n hideClose = false,\n ...props\n}: ToastProps) {\n const tokens = useComponentsTokens().toast;\n\n return (\n <Toast.Root {...props} tone={tone}>\n {!hideIcon ? (\n <Toast.Icon>\n <Icon\n icon={ToastIcons[tone]}\n size={tokens.iconSize}\n color={tokens.tones[tone].value}\n />\n </Toast.Icon>\n ) : null}\n <Toast.Content>\n {title ? <Toast.Title>{title}</Toast.Title> : null}\n {description !== null && description !== undefined ? (\n <Toast.Description>{description}</Toast.Description>\n ) : null}\n {children}\n </Toast.Content>\n {action !== null && action !== undefined ? (\n <Toast.Action {...actionProps}>{action}</Toast.Action>\n ) : null}\n {!hideClose ? (\n <Toast.Close>\n <Icon\n icon={XIcon}\n size={tokens.iconSize}\n color={tokens.descriptionColor}\n />\n </Toast.Close>\n ) : null}\n </Toast.Root>\n );\n});\n"],"mappings":"AA2BU,cAOJ,YAPI;AA3BV,SAAS,YAAY;AAErB,SAAS,YAAY;AACrB,SAAS,aAAa;AACtB,SAAS,2BAA2B;AAGpC,SAAS,kBAAkB;AAC3B,SAAS,aAAa;AAEf,MAAM,iBAAiB,KAAK,SAASA,gBAAe;AAAA,EACzD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,GAAG;AACL,GAAe;AACb,QAAM,SAAS,oBAAoB,EAAE;AAErC,SACE,qBAAC,MAAM,MAAN,EAAY,GAAG,OAAO,MACpB;AAAA,KAAC,WACA,oBAAC,MAAM,MAAN,EACC;AAAA,MAAC;AAAA;AAAA,QACC,MAAM,WAAW,IAAI;AAAA,QACrB,MAAM,OAAO;AAAA,QACb,OAAO,OAAO,MAAM,IAAI,EAAE;AAAA;AAAA,IAC5B,GACF,IACE;AAAA,IACJ,qBAAC,MAAM,SAAN,EACE;AAAA,cAAQ,oBAAC,MAAM,OAAN,EAAa,iBAAM,IAAiB;AAAA,MAC7C,gBAAgB,QAAQ,gBAAgB,SACvC,oBAAC,MAAM,aAAN,EAAmB,uBAAY,IAC9B;AAAA,MACH;AAAA,OACH;AAAA,IACC,WAAW,QAAQ,WAAW,SAC7B,oBAAC,MAAM,QAAN,EAAc,GAAG,aAAc,kBAAO,IACrC;AAAA,IACH,CAAC,YACA,oBAAC,MAAM,OAAN,EACC;AAAA,MAAC;AAAA;AAAA,QACC,MAAM;AAAA,QACN,MAAM,OAAO;AAAA,QACb,OAAO,OAAO;AAAA;AAAA,IAChB,GACF,IACE;AAAA,KACN;AAEJ,CAAC;","names":["ToastComponent"]}
@@ -0,0 +1,17 @@
1
+ import * as react from 'react';
2
+ import * as react_jsx_runtime from 'react/jsx-runtime';
3
+ import { SvgProps } from 'react-native-svg';
4
+
5
+ type IconVariant = "bold" | "duotone" | "fill" | "light" | "regular" | "thin";
6
+ interface IconWrapperProps extends SvgProps {
7
+ variant?: IconVariant;
8
+ }
9
+
10
+ declare const ToastIcons: {
11
+ info: react.MemoExoticComponent<(props: IconWrapperProps) => react_jsx_runtime.JSX.Element>;
12
+ success: react.MemoExoticComponent<(props: IconWrapperProps) => react_jsx_runtime.JSX.Element>;
13
+ warning: react.MemoExoticComponent<(props: IconWrapperProps) => react_jsx_runtime.JSX.Element>;
14
+ error: react.MemoExoticComponent<(props: IconWrapperProps) => react_jsx_runtime.JSX.Element>;
15
+ };
16
+
17
+ export { ToastIcons };
@@ -0,0 +1,14 @@
1
+ import { CheckCircleIcon } from "@impulse-ui-native/icon/icons/check-circle";
2
+ import { InfoIcon } from "@impulse-ui-native/icon/icons/info";
3
+ import { WarningIcon } from "@impulse-ui-native/icon/icons/warning";
4
+ import { XCircleIcon } from "@impulse-ui-native/icon/icons/x-circle";
5
+ const ToastIcons = {
6
+ info: InfoIcon,
7
+ success: CheckCircleIcon,
8
+ warning: WarningIcon,
9
+ error: XCircleIcon
10
+ };
11
+ export {
12
+ ToastIcons
13
+ };
14
+ //# sourceMappingURL=toast-icons.constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/constants/toast-icons.constants.ts"],"sourcesContent":["import { CheckCircleIcon } from \"@impulse-ui-native/icon/icons/check-circle\";\nimport { InfoIcon } from \"@impulse-ui-native/icon/icons/info\";\nimport { WarningIcon } from \"@impulse-ui-native/icon/icons/warning\";\nimport { XCircleIcon } from \"@impulse-ui-native/icon/icons/x-circle\";\n\nexport const ToastIcons = {\n info: InfoIcon,\n success: CheckCircleIcon,\n warning: WarningIcon,\n error: XCircleIcon,\n};\n"],"mappings":"AAAA,SAAS,uBAAuB;AAChC,SAAS,gBAAgB;AACzB,SAAS,mBAAmB;AAC5B,SAAS,mBAAmB;AAErB,MAAM,aAAa;AAAA,EACxB,MAAM;AAAA,EACN,SAAS;AAAA,EACT,SAAS;AAAA,EACT,OAAO;AACT;","names":[]}
@@ -0,0 +1,6 @@
1
+ declare const DefaultDuration = 4000;
2
+ declare const EnterDuration = 180;
3
+ declare const ExitDuration = 150;
4
+ declare const StackDuration = 220;
5
+
6
+ export { DefaultDuration, EnterDuration, ExitDuration, StackDuration };
@@ -0,0 +1,11 @@
1
+ const DefaultDuration = 4e3;
2
+ const EnterDuration = 180;
3
+ const ExitDuration = 150;
4
+ const StackDuration = 220;
5
+ export {
6
+ DefaultDuration,
7
+ EnterDuration,
8
+ ExitDuration,
9
+ StackDuration
10
+ };
11
+ //# sourceMappingURL=toast.constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/constants/toast.constants.ts"],"sourcesContent":["export const DefaultDuration = 4000;\nexport const EnterDuration = 180;\nexport const ExitDuration = 150;\nexport const StackDuration = 220;\n"],"mappings":"AAAO,MAAM,kBAAkB;AACxB,MAAM,gBAAgB;AACtB,MAAM,eAAe;AACrB,MAAM,gBAAgB;","names":[]}
@@ -0,0 +1,9 @@
1
+ import * as react from 'react';
2
+ import { ToastContextValue } from '../types/toast.types.mjs';
3
+ import '@impulse-ui-native/overlay';
4
+ import '@impulse-ui-native/primitives';
5
+ import '@impulse-ui-native/theme';
6
+
7
+ declare const ToastContext: react.Context<ToastContextValue | undefined>;
8
+
9
+ export { ToastContext };
@@ -0,0 +1,8 @@
1
+ import { createContext } from "react";
2
+ const ToastContext = createContext(
3
+ void 0
4
+ );
5
+ export {
6
+ ToastContext
7
+ };
8
+ //# sourceMappingURL=toast.context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/contexts/toast.context.ts"],"sourcesContent":["import { createContext } from \"react\";\n\nimport type { ToastContextValue } from \"../types\";\n\nexport const ToastContext = createContext<ToastContextValue | undefined>(\n undefined,\n);\n"],"mappings":"AAAA,SAAS,qBAAqB;AAIvB,MAAM,eAAe;AAAA,EAC1B;AACF;","names":[]}
@@ -0,0 +1,9 @@
1
+ import { ToastContextValue } from '../types/toast.types.mjs';
2
+ import 'react';
3
+ import '@impulse-ui-native/overlay';
4
+ import '@impulse-ui-native/primitives';
5
+ import '@impulse-ui-native/theme';
6
+
7
+ declare function useToastContext(): ToastContextValue;
8
+
9
+ export { useToastContext };
@@ -0,0 +1,13 @@
1
+ import { useContext } from "react";
2
+ import { ToastContext } from "../contexts/toast.context";
3
+ function useToastContext() {
4
+ const context = useContext(ToastContext);
5
+ if (!context) {
6
+ throw new Error("Toast children must be rendered inside Toast.Root");
7
+ }
8
+ return context;
9
+ }
10
+ export {
11
+ useToastContext
12
+ };
13
+ //# sourceMappingURL=use-toast-context.hook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/hooks/use-toast-context.hook.ts"],"sourcesContent":["import { useContext } from \"react\";\n\nimport { ToastContext } from \"../contexts/toast.context\";\n\nexport function useToastContext() {\n const context = useContext(ToastContext);\n\n if (!context) {\n throw new Error(\"Toast children must be rendered inside Toast.Root\");\n }\n\n return context;\n}\n"],"mappings":"AAAA,SAAS,kBAAkB;AAE3B,SAAS,oBAAoB;AAEtB,SAAS,kBAAkB;AAChC,QAAM,UAAU,WAAW,YAAY;AAEvC,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,mDAAmD;AAAA,EACrE;AAEA,SAAO;AACT;","names":[]}
@@ -0,0 +1,15 @@
1
+ import * as react_native_reanimated from 'react-native-reanimated';
2
+ import { ToastRootProps } from '../types/toast.types.mjs';
3
+ import 'react';
4
+ import '@impulse-ui-native/overlay';
5
+ import '@impulse-ui-native/primitives';
6
+ import '@impulse-ui-native/theme';
7
+
8
+ declare function useToastLifecycle(props: ToastRootProps, duration: number): {
9
+ progress: react_native_reanimated.SharedValue<number>;
10
+ close: () => void;
11
+ finished: boolean;
12
+ interactive: boolean;
13
+ };
14
+
15
+ export { useToastLifecycle };
@@ -0,0 +1,129 @@
1
+ import { useEffect, useRef, useState } from "react";
2
+ import {
3
+ cancelAnimation,
4
+ useSharedValue,
5
+ withTiming
6
+ } from "react-native-reanimated";
7
+ import { scheduleOnRN } from "react-native-worklets";
8
+ import { useEventCallback } from "@impulse-ui-native/core";
9
+ import { useOverlayContext } from "@impulse-ui-native/overlay";
10
+ import { EnterDuration, ExitDuration } from "../constants/toast.constants";
11
+ import { useToastTimer } from "./use-toast-timer.hook";
12
+ function useToastLifecycle(props, duration) {
13
+ const {
14
+ id,
15
+ open = true,
16
+ onOpen,
17
+ onOpenFinished,
18
+ onClose,
19
+ onCloseFinished
20
+ } = props;
21
+ const { store } = useOverlayContext();
22
+ const [entered, setEntered] = useState(false);
23
+ const [finished, setFinished] = useState(false);
24
+ const opened = useRef(false);
25
+ const closing = useRef(false);
26
+ const settled = useRef(false);
27
+ const transitionId = useRef(0);
28
+ const progress = useSharedValue(0);
29
+ const close = useEventCallback(() => store.close(id));
30
+ const notifyOpen = useEventCallback(() => onOpen?.(id));
31
+ const notifyEntered = useEventCallback(() => onOpenFinished?.(id));
32
+ const notifyClose = useEventCallback(() => onClose?.(id));
33
+ const finishClose = useEventCallback(() => {
34
+ if (settled.current) {
35
+ return;
36
+ }
37
+ settled.current = true;
38
+ setFinished(true);
39
+ onCloseFinished?.(id);
40
+ });
41
+ const finishTransition = useEventCallback(
42
+ (completedTransitionId, entering) => {
43
+ if (transitionId.current !== completedTransitionId || settled.current) {
44
+ return;
45
+ }
46
+ if (entering) {
47
+ setEntered(true);
48
+ notifyEntered();
49
+ } else {
50
+ finishClose();
51
+ }
52
+ }
53
+ );
54
+ useToastTimer(entered && open && !finished, duration, close);
55
+ useEffect(() => {
56
+ if (finished) {
57
+ return;
58
+ }
59
+ const currentTransitionId = ++transitionId.current;
60
+ if (!open) {
61
+ const firstClose = !closing.current;
62
+ closing.current = true;
63
+ if (!opened.current) {
64
+ try {
65
+ if (firstClose) {
66
+ notifyClose();
67
+ }
68
+ } finally {
69
+ finishClose();
70
+ }
71
+ return;
72
+ }
73
+ try {
74
+ if (firstClose) {
75
+ notifyClose();
76
+ }
77
+ } finally {
78
+ progress.value = withTiming(
79
+ 0,
80
+ { duration: ExitDuration },
81
+ (completed) => {
82
+ if (completed) {
83
+ scheduleOnRN(finishTransition, currentTransitionId, false);
84
+ }
85
+ }
86
+ );
87
+ }
88
+ return () => {
89
+ transitionId.current += 1;
90
+ cancelAnimation(progress);
91
+ };
92
+ }
93
+ const firstOpen = !opened.current;
94
+ opened.current = true;
95
+ try {
96
+ if (firstOpen) {
97
+ notifyOpen();
98
+ }
99
+ } finally {
100
+ progress.value = withTiming(
101
+ 1,
102
+ { duration: EnterDuration },
103
+ (completed) => {
104
+ if (completed) {
105
+ scheduleOnRN(finishTransition, currentTransitionId, true);
106
+ }
107
+ }
108
+ );
109
+ }
110
+ return () => {
111
+ transitionId.current += 1;
112
+ cancelAnimation(progress);
113
+ };
114
+ }, [
115
+ finishClose,
116
+ finishTransition,
117
+ finished,
118
+ notifyClose,
119
+ notifyEntered,
120
+ notifyOpen,
121
+ open,
122
+ progress
123
+ ]);
124
+ return { progress, close, finished, interactive: open && !finished };
125
+ }
126
+ export {
127
+ useToastLifecycle
128
+ };
129
+ //# sourceMappingURL=use-toast-lifecycle.hook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/hooks/use-toast-lifecycle.hook.ts"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\nimport {\n cancelAnimation,\n useSharedValue,\n withTiming,\n} from \"react-native-reanimated\";\nimport { scheduleOnRN } from \"react-native-worklets\";\n\nimport { useEventCallback } from \"@impulse-ui-native/core\";\nimport { useOverlayContext } from \"@impulse-ui-native/overlay\";\n\nimport type { ToastRootProps } from \"../types\";\nimport { EnterDuration, ExitDuration } from \"../constants/toast.constants\";\nimport { useToastTimer } from \"./use-toast-timer.hook\";\n\nexport function useToastLifecycle(props: ToastRootProps, duration: number) {\n const {\n id,\n open = true,\n onOpen,\n onOpenFinished,\n onClose,\n onCloseFinished,\n } = props;\n\n const { store } = useOverlayContext();\n\n const [entered, setEntered] = useState(false);\n const [finished, setFinished] = useState(false);\n\n const opened = useRef(false);\n const closing = useRef(false);\n const settled = useRef(false);\n const transitionId = useRef(0);\n\n const progress = useSharedValue(0);\n\n const close = useEventCallback(() => store.close(id));\n\n const notifyOpen = useEventCallback(() => onOpen?.(id));\n\n const notifyEntered = useEventCallback(() => onOpenFinished?.(id));\n\n const notifyClose = useEventCallback(() => onClose?.(id));\n\n const finishClose = useEventCallback(() => {\n if (settled.current) {\n return;\n }\n\n settled.current = true;\n\n setFinished(true);\n\n onCloseFinished?.(id);\n });\n\n const finishTransition = useEventCallback(\n (completedTransitionId: number, entering: boolean) => {\n if (transitionId.current !== completedTransitionId || settled.current) {\n return;\n }\n\n if (entering) {\n setEntered(true);\n\n notifyEntered();\n } else {\n finishClose();\n }\n },\n );\n\n useToastTimer(entered && open && !finished, duration, close);\n\n useEffect(() => {\n if (finished) {\n return;\n }\n\n const currentTransitionId = ++transitionId.current;\n\n if (!open) {\n const firstClose = !closing.current;\n\n closing.current = true;\n\n if (!opened.current) {\n try {\n if (firstClose) {\n notifyClose();\n }\n } finally {\n finishClose();\n }\n\n return;\n }\n\n try {\n if (firstClose) {\n notifyClose();\n }\n } finally {\n progress.value = withTiming(\n 0,\n { duration: ExitDuration },\n (completed) => {\n if (completed) {\n scheduleOnRN(finishTransition, currentTransitionId, false);\n }\n },\n );\n }\n\n return () => {\n transitionId.current += 1;\n\n cancelAnimation(progress);\n };\n }\n\n const firstOpen = !opened.current;\n\n opened.current = true;\n\n try {\n if (firstOpen) {\n notifyOpen();\n }\n } finally {\n progress.value = withTiming(\n 1,\n { duration: EnterDuration },\n (completed) => {\n if (completed) {\n scheduleOnRN(finishTransition, currentTransitionId, true);\n }\n },\n );\n }\n\n return () => {\n transitionId.current += 1;\n\n cancelAnimation(progress);\n };\n }, [\n finishClose,\n finishTransition,\n finished,\n notifyClose,\n notifyEntered,\n notifyOpen,\n open,\n progress,\n ]);\n\n return { progress, close, finished, interactive: open && !finished };\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,3 @@
1
+ declare function useToastTimer(active: boolean, duration: number, close: () => void): void;
2
+
3
+ export { useToastTimer };
@@ -0,0 +1,50 @@
1
+ import { useEffect } from "react";
2
+ import { AppState } from "react-native";
3
+ import { useEventCallback } from "@impulse-ui-native/core";
4
+ function useToastTimer(active, duration, close) {
5
+ const dismiss = useEventCallback(close);
6
+ useEffect(() => {
7
+ if (!active || !Number.isFinite(duration) || duration <= 0) {
8
+ return;
9
+ }
10
+ let remaining = duration;
11
+ let startedAt = 0;
12
+ let timeout;
13
+ const pause = () => {
14
+ if (timeout === void 0) {
15
+ return;
16
+ }
17
+ clearTimeout(timeout);
18
+ timeout = void 0;
19
+ remaining = Math.max(0, remaining - (Date.now() - startedAt));
20
+ };
21
+ const resume = () => {
22
+ if (timeout !== void 0) {
23
+ return;
24
+ }
25
+ startedAt = Date.now();
26
+ timeout = setTimeout(() => {
27
+ timeout = void 0;
28
+ dismiss();
29
+ }, remaining);
30
+ };
31
+ const subscription = AppState.addEventListener("change", (state) => {
32
+ if (state === "active") {
33
+ resume();
34
+ } else {
35
+ pause();
36
+ }
37
+ });
38
+ if (AppState.currentState === "active") {
39
+ resume();
40
+ }
41
+ return () => {
42
+ pause();
43
+ subscription.remove();
44
+ };
45
+ }, [active, dismiss, duration]);
46
+ }
47
+ export {
48
+ useToastTimer
49
+ };
50
+ //# sourceMappingURL=use-toast-timer.hook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/hooks/use-toast-timer.hook.ts"],"sourcesContent":["import { useEffect } from \"react\";\nimport { AppState } from \"react-native\";\n\nimport { useEventCallback } from \"@impulse-ui-native/core\";\n\nexport function useToastTimer(\n active: boolean,\n duration: number,\n close: () => void,\n) {\n const dismiss = useEventCallback(close);\n\n useEffect(() => {\n if (!active || !Number.isFinite(duration) || duration <= 0) {\n return;\n }\n\n let remaining = duration;\n let startedAt = 0;\n let timeout: ReturnType<typeof setTimeout> | undefined;\n\n const pause = () => {\n if (timeout === undefined) {\n return;\n }\n\n clearTimeout(timeout);\n\n timeout = undefined;\n remaining = Math.max(0, remaining - (Date.now() - startedAt));\n };\n\n const resume = () => {\n if (timeout !== undefined) {\n return;\n }\n\n startedAt = Date.now();\n timeout = setTimeout(() => {\n timeout = undefined;\n\n dismiss();\n }, remaining);\n };\n\n const subscription = AppState.addEventListener(\"change\", (state) => {\n if (state === \"active\") {\n resume();\n } else {\n pause();\n }\n });\n\n if (AppState.currentState === \"active\") {\n resume();\n }\n\n return () => {\n pause();\n subscription.remove();\n };\n }, [active, dismiss, duration]);\n}\n"],"mappings":"AAAA,SAAS,iBAAiB;AAC1B,SAAS,gBAAgB;AAEzB,SAAS,wBAAwB;AAE1B,SAAS,cACd,QACA,UACA,OACA;AACA,QAAM,UAAU,iBAAiB,KAAK;AAEtC,YAAU,MAAM;AACd,QAAI,CAAC,UAAU,CAAC,OAAO,SAAS,QAAQ,KAAK,YAAY,GAAG;AAC1D;AAAA,IACF;AAEA,QAAI,YAAY;AAChB,QAAI,YAAY;AAChB,QAAI;AAEJ,UAAM,QAAQ,MAAM;AAClB,UAAI,YAAY,QAAW;AACzB;AAAA,MACF;AAEA,mBAAa,OAAO;AAEpB,gBAAU;AACV,kBAAY,KAAK,IAAI,GAAG,aAAa,KAAK,IAAI,IAAI,UAAU;AAAA,IAC9D;AAEA,UAAM,SAAS,MAAM;AACnB,UAAI,YAAY,QAAW;AACzB;AAAA,MACF;AAEA,kBAAY,KAAK,IAAI;AACrB,gBAAU,WAAW,MAAM;AACzB,kBAAU;AAEV,gBAAQ;AAAA,MACV,GAAG,SAAS;AAAA,IACd;AAEA,UAAM,eAAe,SAAS,iBAAiB,UAAU,CAAC,UAAU;AAClE,UAAI,UAAU,UAAU;AACtB,eAAO;AAAA,MACT,OAAO;AACL,cAAM;AAAA,MACR;AAAA,IACF,CAAC;AAED,QAAI,SAAS,iBAAiB,UAAU;AACtC,aAAO;AAAA,IACT;AAEA,WAAO,MAAM;AACX,YAAM;AACN,mBAAa,OAAO;AAAA,IACtB;AAAA,EACF,GAAG,CAAC,QAAQ,SAAS,QAAQ,CAAC;AAChC;","names":[]}
@@ -0,0 +1,7 @@
1
+ export { Toast } from './components/index.mjs';
2
+ export { ToastActionProps, ToastCloseProps, ToastContentProps, ToastContextValue, ToastDescriptionProps, ToastIconProps, ToastPlacement, ToastProps, ToastRootProps, ToastTitleProps } from './types/toast.types.mjs';
3
+ import 'react/jsx-runtime';
4
+ import 'react';
5
+ import '@impulse-ui-native/overlay';
6
+ import '@impulse-ui-native/primitives';
7
+ import '@impulse-ui-native/theme';
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export * from "./components";
2
+ export * from "./types";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export * from \"./components\";\nexport * from \"./types\";\n"],"mappings":"AAAA,cAAc;AACd,cAAc;","names":[]}
@@ -0,0 +1,5 @@
1
+ export { ToastActionProps, ToastCloseProps, ToastContentProps, ToastContextValue, ToastDescriptionProps, ToastIconProps, ToastPlacement, ToastProps, ToastRootProps, ToastTitleProps } from './toast.types.mjs';
2
+ import 'react';
3
+ import '@impulse-ui-native/overlay';
4
+ import '@impulse-ui-native/primitives';
5
+ import '@impulse-ui-native/theme';
@@ -0,0 +1,2 @@
1
+ export * from "./toast.types";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/types/index.ts"],"sourcesContent":["export * from \"./toast.types\";\n"],"mappings":"AAAA,cAAc;","names":[]}
@@ -0,0 +1,35 @@
1
+ import { ReactNode } from 'react';
2
+ import { OverlayComponentProps } from '@impulse-ui-native/overlay';
3
+ import { ButtonProps, ViewProps, TextProps } from '@impulse-ui-native/primitives';
4
+ import { ToastTone } from '@impulse-ui-native/theme';
5
+
6
+ type ToastPlacement = "top" | "bottom";
7
+ interface ToastRootProps extends OverlayComponentProps {
8
+ placement?: ToastPlacement;
9
+ tone?: ToastTone;
10
+ /** Milliseconds after entry completes. Zero persists until dismissed. */
11
+ duration?: number;
12
+ }
13
+ interface ToastProps extends ToastRootProps {
14
+ description?: ReactNode;
15
+ action?: ReactNode;
16
+ actionProps?: Omit<ToastActionProps, "children">;
17
+ hideIcon?: boolean;
18
+ hideClose?: boolean;
19
+ }
20
+ type ToastContentProps = ViewProps;
21
+ type ToastTitleProps = TextProps;
22
+ type ToastDescriptionProps = TextProps;
23
+ type ToastIconProps = ViewProps;
24
+ interface ToastActionProps extends Omit<ButtonProps, "children" | "size" | "variant"> {
25
+ children?: ReactNode;
26
+ closeOnPress?: boolean;
27
+ }
28
+ type ToastCloseProps = Omit<ToastActionProps, "closeOnPress">;
29
+ interface ToastContextValue {
30
+ tone: ToastTone;
31
+ interactive: boolean;
32
+ close: () => void;
33
+ }
34
+
35
+ export type { ToastActionProps, ToastCloseProps, ToastContentProps, ToastContextValue, ToastDescriptionProps, ToastIconProps, ToastPlacement, ToastProps, ToastRootProps, ToastTitleProps };
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=toast.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
package/package.json CHANGED
@@ -1,6 +1,70 @@
1
1
  {
2
2
  "name": "@impulse-ui-native/toast",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "6.1.0",
4
+ "description": "Compound toast notifications for ImpulseUI Native.",
5
+ "keywords": [
6
+ "react-native",
7
+ "toast",
8
+ "notifications",
9
+ "components"
10
+ ],
11
+ "license": "MIT",
12
+ "source": "src/index.ts",
13
+ "module": "dist/index.js",
14
+ "types": "dist/index.d.mts",
15
+ "react-native": "src/index.ts",
16
+ "exports": {
17
+ ".": {
18
+ "types": "./dist/index.d.mts",
19
+ "react-native": "./src/index.ts",
20
+ "import": "./dist/index.js"
21
+ }
22
+ },
23
+ "files": [
24
+ "dist",
25
+ "README.md",
26
+ "LICENSE"
27
+ ],
28
+ "sideEffects": false,
29
+ "dependencies": {
30
+ "@impulse-ui-native/theme": "6.1.0",
31
+ "@impulse-ui-native/primitives": "6.1.0",
32
+ "@impulse-ui-native/overlay": "6.1.0",
33
+ "@impulse-ui-native/core": "6.1.0",
34
+ "@impulse-ui-native/icon": "6.1.0"
35
+ },
36
+ "devDependencies": {
37
+ "@types/react": "~19.2.14",
38
+ "eslint": "^9.38.0",
39
+ "prettier": "^3.6.2",
40
+ "react": "19.2.3",
41
+ "react-native": "0.86.2",
42
+ "react-native-reanimated": "4.5.1",
43
+ "react-native-worklets": "0.10.1",
44
+ "react-native-safe-area-context": "~5.7.0",
45
+ "typescript": "~6.0.3",
46
+ "react-native-svg": "15.15.4",
47
+ "@impulse-ui-native/eslint-config": "1.0.0",
48
+ "@impulse-ui-native/prettier-config": "1.0.0",
49
+ "@impulse-ui-native/tsconfig": "1.0.0"
50
+ },
51
+ "peerDependencies": {
52
+ "react": ">=18",
53
+ "react-native": ">=0.73",
54
+ "react-native-reanimated": ">=4.0.0",
55
+ "react-native-worklets": ">=0.5",
56
+ "react-native-safe-area-context": ">=5.0.0",
57
+ "react-native-svg": ">=13.9.0"
58
+ },
59
+ "publishConfig": {
60
+ "access": "public"
61
+ },
62
+ "prettier": "@impulse-ui-native/prettier-config",
63
+ "scripts": {
64
+ "build": "tsup --config tsup.config.ts",
65
+ "typecheck": "tsc -p tsconfig.json --noEmit",
66
+ "lint": "pnpm exec eslint . --fix",
67
+ "format": "prettier --write \"./**/*.{ts,tsx,js,jsx,json,md}\" --ignore-path ../../.prettierignore",
68
+ "test": "node --test tests/*.test.mjs"
69
+ }
6
70
  }