@impulse-ui-native/toast 8.1.0 → 8.3.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.
package/README.md CHANGED
@@ -114,3 +114,10 @@ Use the Toast stories in the on-device Storybook host to verify rendering, touch
114
114
  Toast uses the shared useOverlayLifecycle hook from the overlay package.
115
115
  onStatusChange(id, status) reports opening, open, closing, and closed.
116
116
  The duration timer starts when status reaches open.
117
+
118
+ ## Theme motion and action typography
119
+
120
+ `components.toast.enterDuration`, `exitDuration`, and `stackDuration` configure
121
+ the transitions (180 ms, 150 ms, and 220 ms by default).
122
+ `actionFontWeight` defaults to the primitive theme semi-bold weight. The
123
+ `duration` prop still controls auto-dismiss independently of animation timing.
@@ -3,7 +3,7 @@ import { memo, useMemo } from "react";
3
3
  import { StyleSheet } from "react-native";
4
4
  import { useEventCallback } from "@impulse-ui-native/core";
5
5
  import { Pressable, Typography } from "@impulse-ui-native/primitives";
6
- import { useThemedStyles } from "@impulse-ui-native/theme";
6
+ import { useComponentsTokens, useThemedStyles } from "@impulse-ui-native/theme";
7
7
  import { useToastContext } from "../hooks/use-toast-context.hook";
8
8
  const ToastAction = memo(function ToastAction2({
9
9
  children,
@@ -15,6 +15,7 @@ const ToastAction = memo(function ToastAction2({
15
15
  ...props
16
16
  }) {
17
17
  const { interactive, close } = useToastContext();
18
+ const tokens = useComponentsTokens().toast;
18
19
  const blocked = disabled === true || loading === true || !interactive;
19
20
  const styles = useThemedStyles(themedStyles, { blocked }, [blocked]);
20
21
  const actionStyle = useMemo(
@@ -38,7 +39,14 @@ const ToastAction = memo(function ToastAction2({
38
39
  disabled: blocked,
39
40
  onPress: handlePress,
40
41
  style: actionStyle,
41
- children: typeof children === "string" ? /* @__PURE__ */ jsx(Typography.Label, { style: styles.label, children }) : children
42
+ children: typeof children === "string" ? /* @__PURE__ */ jsx(
43
+ Typography.Label,
44
+ {
45
+ fontWeight: tokens.actionFontWeight,
46
+ style: styles.label,
47
+ children
48
+ }
49
+ ) : children
42
50
  }
43
51
  );
44
52
  });
@@ -53,8 +61,7 @@ function themedStyles(theme, { blocked }) {
53
61
  paddingHorizontal: tokens.gap
54
62
  },
55
63
  label: {
56
- color: blocked ? tokens.disabledColor : tokens.actionColor,
57
- fontWeight: "600"
64
+ color: blocked ? tokens.disabledColor : tokens.actionColor
58
65
  }
59
66
  });
60
67
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/toast-action.tsx"],"sourcesContent":["import type { GestureResponderEvent } from \"react-native\";\nimport { memo, useMemo } from \"react\";\nimport { StyleSheet } from \"react-native\";\n\nimport type { AppTheme } from \"@impulse-ui-native/theme\";\nimport { useEventCallback } from \"@impulse-ui-native/core\";\nimport { Pressable, Typography } from \"@impulse-ui-native/primitives\";\nimport { useThemedStyles } from \"@impulse-ui-native/theme\";\n\nimport type { ToastActionProps } from \"../types\";\nimport type { ToastActionThemeProps } from \"../types/toast-theme.types\";\nimport { useToastContext } from \"../hooks/use-toast-context.hook\";\n\nexport const ToastAction = memo(function ToastAction({\n children,\n closeOnPress = true,\n onPress,\n disabled,\n loading,\n style,\n ...props\n}: ToastActionProps) {\n const { interactive, close } = useToastContext();\n\n const blocked = disabled === true || loading === true || !interactive;\n\n const styles = useThemedStyles(themedStyles, { blocked }, [blocked]);\n\n const actionStyle = useMemo(\n () => [styles.action, style],\n [styles.action, style],\n );\n\n const handlePress = useEventCallback((event: GestureResponderEvent) => {\n if (blocked) {\n return;\n }\n\n onPress?.(event);\n\n if (closeOnPress) {\n close();\n }\n });\n\n return (\n <Pressable\n hitSlop={styles.action.paddingHorizontal}\n {...props}\n disabled={blocked}\n onPress={handlePress}\n style={actionStyle}\n >\n {typeof children === \"string\" ? (\n <Typography.Label style={styles.label}>{children}</Typography.Label>\n ) : (\n children\n )}\n </Pressable>\n );\n});\n\nfunction themedStyles(theme: AppTheme, { blocked }: ToastActionThemeProps) {\n const tokens = theme.components.toast;\n\n return StyleSheet.create({\n action: {\n minHeight: tokens.actionMinSize,\n minWidth: tokens.actionMinSize,\n alignItems: \"center\",\n justifyContent: \"center\",\n paddingHorizontal: tokens.gap,\n },\n label: {\n color: blocked ? tokens.disabledColor : tokens.actionColor,\n fontWeight: \"600\",\n },\n });\n}\n"],"mappings":"AAsDQ;AArDR,SAAS,MAAM,eAAe;AAC9B,SAAS,kBAAkB;AAG3B,SAAS,wBAAwB;AACjC,SAAS,WAAW,kBAAkB;AACtC,SAAS,uBAAuB;AAIhC,SAAS,uBAAuB;AAEzB,MAAM,cAAc,KAAK,SAASA,aAAY;AAAA,EACnD;AAAA,EACA,eAAe;AAAA,EACf;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAqB;AACnB,QAAM,EAAE,aAAa,MAAM,IAAI,gBAAgB;AAE/C,QAAM,UAAU,aAAa,QAAQ,YAAY,QAAQ,CAAC;AAE1D,QAAM,SAAS,gBAAgB,cAAc,EAAE,QAAQ,GAAG,CAAC,OAAO,CAAC;AAEnE,QAAM,cAAc;AAAA,IAClB,MAAM,CAAC,OAAO,QAAQ,KAAK;AAAA,IAC3B,CAAC,OAAO,QAAQ,KAAK;AAAA,EACvB;AAEA,QAAM,cAAc,iBAAiB,CAAC,UAAiC;AACrE,QAAI,SAAS;AACX;AAAA,IACF;AAEA,cAAU,KAAK;AAEf,QAAI,cAAc;AAChB,YAAM;AAAA,IACR;AAAA,EACF,CAAC;AAED,SACE;AAAA,IAAC;AAAA;AAAA,MACC,SAAS,OAAO,OAAO;AAAA,MACtB,GAAG;AAAA,MACJ,UAAU;AAAA,MACV,SAAS;AAAA,MACT,OAAO;AAAA,MAEN,iBAAO,aAAa,WACnB,oBAAC,WAAW,OAAX,EAAiB,OAAO,OAAO,OAAQ,UAAS,IAEjD;AAAA;AAAA,EAEJ;AAEJ,CAAC;AAED,SAAS,aAAa,OAAiB,EAAE,QAAQ,GAA0B;AACzE,QAAM,SAAS,MAAM,WAAW;AAEhC,SAAO,WAAW,OAAO;AAAA,IACvB,QAAQ;AAAA,MACN,WAAW,OAAO;AAAA,MAClB,UAAU,OAAO;AAAA,MACjB,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,mBAAmB,OAAO;AAAA,IAC5B;AAAA,IACA,OAAO;AAAA,MACL,OAAO,UAAU,OAAO,gBAAgB,OAAO;AAAA,MAC/C,YAAY;AAAA,IACd;AAAA,EACF,CAAC;AACH;","names":["ToastAction"]}
1
+ {"version":3,"sources":["../../src/components/toast-action.tsx"],"sourcesContent":["import type { GestureResponderEvent } from \"react-native\";\nimport { memo, useMemo } from \"react\";\nimport { StyleSheet } from \"react-native\";\n\nimport type { AppTheme } from \"@impulse-ui-native/theme\";\nimport { useEventCallback } from \"@impulse-ui-native/core\";\nimport { Pressable, Typography } from \"@impulse-ui-native/primitives\";\nimport { useComponentsTokens, useThemedStyles } from \"@impulse-ui-native/theme\";\n\nimport type { ToastActionProps } from \"../types\";\nimport type { ToastActionThemeProps } from \"../types/toast-theme.types\";\nimport { useToastContext } from \"../hooks/use-toast-context.hook\";\n\nexport const ToastAction = memo(function ToastAction({\n children,\n closeOnPress = true,\n onPress,\n disabled,\n loading,\n style,\n ...props\n}: ToastActionProps) {\n const { interactive, close } = useToastContext();\n const tokens = useComponentsTokens().toast;\n\n const blocked = disabled === true || loading === true || !interactive;\n\n const styles = useThemedStyles(themedStyles, { blocked }, [blocked]);\n\n const actionStyle = useMemo(\n () => [styles.action, style],\n [styles.action, style],\n );\n\n const handlePress = useEventCallback((event: GestureResponderEvent) => {\n if (blocked) {\n return;\n }\n\n onPress?.(event);\n\n if (closeOnPress) {\n close();\n }\n });\n\n return (\n <Pressable\n hitSlop={styles.action.paddingHorizontal}\n {...props}\n disabled={blocked}\n onPress={handlePress}\n style={actionStyle}\n >\n {typeof children === \"string\" ? (\n <Typography.Label\n fontWeight={tokens.actionFontWeight}\n style={styles.label}\n >\n {children}\n </Typography.Label>\n ) : (\n children\n )}\n </Pressable>\n );\n});\n\nfunction themedStyles(theme: AppTheme, { blocked }: ToastActionThemeProps) {\n const tokens = theme.components.toast;\n\n return StyleSheet.create({\n action: {\n minHeight: tokens.actionMinSize,\n minWidth: tokens.actionMinSize,\n alignItems: \"center\",\n justifyContent: \"center\",\n paddingHorizontal: tokens.gap,\n },\n label: {\n color: blocked ? tokens.disabledColor : tokens.actionColor,\n },\n });\n}\n"],"mappings":"AAuDQ;AAtDR,SAAS,MAAM,eAAe;AAC9B,SAAS,kBAAkB;AAG3B,SAAS,wBAAwB;AACjC,SAAS,WAAW,kBAAkB;AACtC,SAAS,qBAAqB,uBAAuB;AAIrD,SAAS,uBAAuB;AAEzB,MAAM,cAAc,KAAK,SAASA,aAAY;AAAA,EACnD;AAAA,EACA,eAAe;AAAA,EACf;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAqB;AACnB,QAAM,EAAE,aAAa,MAAM,IAAI,gBAAgB;AAC/C,QAAM,SAAS,oBAAoB,EAAE;AAErC,QAAM,UAAU,aAAa,QAAQ,YAAY,QAAQ,CAAC;AAE1D,QAAM,SAAS,gBAAgB,cAAc,EAAE,QAAQ,GAAG,CAAC,OAAO,CAAC;AAEnE,QAAM,cAAc;AAAA,IAClB,MAAM,CAAC,OAAO,QAAQ,KAAK;AAAA,IAC3B,CAAC,OAAO,QAAQ,KAAK;AAAA,EACvB;AAEA,QAAM,cAAc,iBAAiB,CAAC,UAAiC;AACrE,QAAI,SAAS;AACX;AAAA,IACF;AAEA,cAAU,KAAK;AAEf,QAAI,cAAc;AAChB,YAAM;AAAA,IACR;AAAA,EACF,CAAC;AAED,SACE;AAAA,IAAC;AAAA;AAAA,MACC,SAAS,OAAO,OAAO;AAAA,MACtB,GAAG;AAAA,MACJ,UAAU;AAAA,MACV,SAAS;AAAA,MACT,OAAO;AAAA,MAEN,iBAAO,aAAa,WACnB;AAAA,QAAC,WAAW;AAAA,QAAX;AAAA,UACC,YAAY,OAAO;AAAA,UACnB,OAAO,OAAO;AAAA,UAEb;AAAA;AAAA,MACH,IAEA;AAAA;AAAA,EAEJ;AAEJ,CAAC;AAED,SAAS,aAAa,OAAiB,EAAE,QAAQ,GAA0B;AACzE,QAAM,SAAS,MAAM,WAAW;AAEhC,SAAO,WAAW,OAAO;AAAA,IACvB,QAAQ;AAAA,MACN,WAAW,OAAO;AAAA,MAClB,UAAU,OAAO;AAAA,MACjB,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,mBAAmB,OAAO;AAAA,IAC5B;AAAA,IACA,OAAO;AAAA,MACL,OAAO,UAAU,OAAO,gBAAgB,OAAO;AAAA,IACjD;AAAA,EACF,CAAC;AACH;","names":["ToastAction"]}
@@ -10,7 +10,7 @@ import Animated, {
10
10
  import { useSafeAreaInsets } from "react-native-safe-area-context";
11
11
  import { OverlayOrder, useOverlayLayer } from "@impulse-ui-native/overlay";
12
12
  import { useComponentsTokens, useThemedStyles } from "@impulse-ui-native/theme";
13
- import { DefaultDuration, StackDuration } from "../constants/toast.constants";
13
+ import { DefaultDuration } from "../constants/toast.constants";
14
14
  import { ToastContext } from "../contexts/toast.context";
15
15
  import { useToastLifecycle } from "../hooks/use-toast-lifecycle.hook";
16
16
  const ToastRoot = memo(function ToastRoot2(props) {
@@ -66,9 +66,11 @@ const ToastRoot = memo(function ToastRoot2(props) {
66
66
  [styles.container, insets, tokens, placement, layer, animatedStyle]
67
67
  );
68
68
  useEffect(() => {
69
- animatedDepth.value = withTiming(stackDepth, { duration: StackDuration });
69
+ animatedDepth.value = withTiming(stackDepth, {
70
+ duration: tokens.stackDuration
71
+ });
70
72
  return () => cancelAnimation(animatedDepth);
71
- }, [animatedDepth, stackDepth]);
73
+ }, [animatedDepth, stackDepth, tokens.stackDuration]);
72
74
  if (!lifecycle.mounted) {
73
75
  return null;
74
76
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/toast-root.tsx"],"sourcesContent":["import { memo, useEffect, useMemo } from \"react\";\nimport { StyleSheet } from \"react-native\";\nimport Animated, {\n cancelAnimation,\n useAnimatedStyle,\n useSharedValue,\n withTiming,\n} from \"react-native-reanimated\";\nimport { useSafeAreaInsets } from \"react-native-safe-area-context\";\n\nimport type { AppTheme } from \"@impulse-ui-native/theme\";\nimport { OverlayOrder, useOverlayLayer } from \"@impulse-ui-native/overlay\";\nimport { useComponentsTokens, useThemedStyles } from \"@impulse-ui-native/theme\";\n\nimport type { ToastRootProps } from \"../types\";\nimport { DefaultDuration, StackDuration } from \"../constants/toast.constants\";\nimport { ToastContext } from \"../contexts/toast.context\";\nimport { useToastLifecycle } from \"../hooks/use-toast-lifecycle.hook\";\n\nexport const ToastRoot = memo(function ToastRoot(props: ToastRootProps) {\n const {\n id,\n children,\n placement = \"bottom\",\n tone = \"success\",\n duration = DefaultDuration,\n layer = 0,\n } = props;\n\n const insets = useSafeAreaInsets();\n\n const tokens = useComponentsTokens().toast;\n\n const lifecycle = useToastLifecycle(props, duration);\n const toastLayer = useOverlayLayer(id, undefined, OverlayOrder.NewestFirst);\n const styles = useThemedStyles(themedStyles);\n const { progress } = lifecycle;\n const edgeOffset = tokens.edgeOffset;\n const stackDepth = Math.min(\n Math.max(0, toastLayer),\n Math.max(0, tokens.stackLimit - 1),\n );\n const animatedDepth = useSharedValue(stackDepth);\n const animatedStyle = useAnimatedStyle(() => ({\n opacity: progress.value,\n transform: [\n {\n translateY:\n (1 - progress.value) *\n (placement === \"top\" ? -edgeOffset : edgeOffset) +\n animatedDepth.value * tokens.gap,\n },\n { scale: Math.max(0, 1 - animatedDepth.value * tokens.stackScaleStep) },\n ],\n }));\n\n const context = useMemo(\n () => ({\n tone,\n interactive: lifecycle.interactive,\n close: lifecycle.close,\n }),\n [tone, lifecycle.interactive, lifecycle.close],\n );\n const containerStyle = useMemo(\n () => [\n styles.container,\n {\n left: insets.left + tokens.edgeOffset,\n right: insets.right + tokens.edgeOffset,\n [placement]:\n insets[placement] +\n (placement === \"top\" ? tokens.topOffset : tokens.edgeOffset),\n transformOrigin: \"center top\",\n zIndex: tokens.zIndexBase + layer,\n },\n animatedStyle,\n ],\n [styles.container, insets, tokens, placement, layer, animatedStyle],\n );\n\n useEffect(() => {\n animatedDepth.value = withTiming(stackDepth, { duration: StackDuration });\n\n return () => cancelAnimation(animatedDepth);\n }, [animatedDepth, stackDepth]);\n\n if (!lifecycle.mounted) {\n return null;\n }\n\n return (\n <ToastContext.Provider value={context}>\n <Animated.View\n pointerEvents={lifecycle.interactive ? \"auto\" : \"none\"}\n style={containerStyle}\n >\n {children}\n </Animated.View>\n </ToastContext.Provider>\n );\n});\n\nfunction themedStyles(theme: AppTheme) {\n const tokens = theme.components.toast;\n\n return StyleSheet.create({\n container: {\n position: \"absolute\",\n flexDirection: \"row\",\n alignItems: \"center\",\n gap: tokens.gap,\n padding: tokens.padding,\n borderRadius: tokens.borderRadius,\n borderWidth: tokens.borderWidth,\n borderColor: tokens.borderColor,\n backgroundColor: tokens.backgroundColor,\n },\n });\n}\n"],"mappings":"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","names":["ToastRoot"]}
1
+ {"version":3,"sources":["../../src/components/toast-root.tsx"],"sourcesContent":["import { memo, useEffect, useMemo } from \"react\";\nimport { StyleSheet } from \"react-native\";\nimport Animated, {\n cancelAnimation,\n useAnimatedStyle,\n useSharedValue,\n withTiming,\n} from \"react-native-reanimated\";\nimport { useSafeAreaInsets } from \"react-native-safe-area-context\";\n\nimport type { AppTheme } from \"@impulse-ui-native/theme\";\nimport { OverlayOrder, useOverlayLayer } from \"@impulse-ui-native/overlay\";\nimport { useComponentsTokens, useThemedStyles } from \"@impulse-ui-native/theme\";\n\nimport type { ToastRootProps } from \"../types\";\nimport { DefaultDuration } from \"../constants/toast.constants\";\nimport { ToastContext } from \"../contexts/toast.context\";\nimport { useToastLifecycle } from \"../hooks/use-toast-lifecycle.hook\";\n\nexport const ToastRoot = memo(function ToastRoot(props: ToastRootProps) {\n const {\n id,\n children,\n placement = \"bottom\",\n tone = \"success\",\n duration = DefaultDuration,\n layer = 0,\n } = props;\n\n const insets = useSafeAreaInsets();\n\n const tokens = useComponentsTokens().toast;\n\n const lifecycle = useToastLifecycle(props, duration);\n const toastLayer = useOverlayLayer(id, undefined, OverlayOrder.NewestFirst);\n const styles = useThemedStyles(themedStyles);\n const { progress } = lifecycle;\n const edgeOffset = tokens.edgeOffset;\n const stackDepth = Math.min(\n Math.max(0, toastLayer),\n Math.max(0, tokens.stackLimit - 1),\n );\n const animatedDepth = useSharedValue(stackDepth);\n const animatedStyle = useAnimatedStyle(() => ({\n opacity: progress.value,\n transform: [\n {\n translateY:\n (1 - progress.value) *\n (placement === \"top\" ? -edgeOffset : edgeOffset) +\n animatedDepth.value * tokens.gap,\n },\n { scale: Math.max(0, 1 - animatedDepth.value * tokens.stackScaleStep) },\n ],\n }));\n\n const context = useMemo(\n () => ({\n tone,\n interactive: lifecycle.interactive,\n close: lifecycle.close,\n }),\n [tone, lifecycle.interactive, lifecycle.close],\n );\n const containerStyle = useMemo(\n () => [\n styles.container,\n {\n left: insets.left + tokens.edgeOffset,\n right: insets.right + tokens.edgeOffset,\n [placement]:\n insets[placement] +\n (placement === \"top\" ? tokens.topOffset : tokens.edgeOffset),\n transformOrigin: \"center top\",\n zIndex: tokens.zIndexBase + layer,\n },\n animatedStyle,\n ],\n [styles.container, insets, tokens, placement, layer, animatedStyle],\n );\n\n useEffect(() => {\n animatedDepth.value = withTiming(stackDepth, {\n duration: tokens.stackDuration,\n });\n\n return () => cancelAnimation(animatedDepth);\n }, [animatedDepth, stackDepth, tokens.stackDuration]);\n\n if (!lifecycle.mounted) {\n return null;\n }\n\n return (\n <ToastContext.Provider value={context}>\n <Animated.View\n pointerEvents={lifecycle.interactive ? \"auto\" : \"none\"}\n style={containerStyle}\n >\n {children}\n </Animated.View>\n </ToastContext.Provider>\n );\n});\n\nfunction themedStyles(theme: AppTheme) {\n const tokens = theme.components.toast;\n\n return StyleSheet.create({\n container: {\n position: \"absolute\",\n flexDirection: \"row\",\n alignItems: \"center\",\n gap: tokens.gap,\n padding: tokens.padding,\n borderRadius: tokens.borderRadius,\n borderWidth: tokens.borderWidth,\n borderColor: tokens.borderColor,\n backgroundColor: tokens.backgroundColor,\n },\n });\n}\n"],"mappings":"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","names":["ToastRoot"]}
@@ -1,6 +1,3 @@
1
1
  declare const DefaultDuration = 4000;
2
- declare const EnterDuration = 180;
3
- declare const ExitDuration = 150;
4
- declare const StackDuration = 220;
5
2
 
6
- export { DefaultDuration, EnterDuration, ExitDuration, StackDuration };
3
+ export { DefaultDuration };
@@ -1,11 +1,5 @@
1
1
  const DefaultDuration = 4e3;
2
- const EnterDuration = 180;
3
- const ExitDuration = 150;
4
- const StackDuration = 220;
5
2
  export {
6
- DefaultDuration,
7
- EnterDuration,
8
- ExitDuration,
9
- StackDuration
3
+ DefaultDuration
10
4
  };
11
5
  //# sourceMappingURL=toast.constants.js.map
@@ -1 +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":[]}
1
+ {"version":3,"sources":["../../src/constants/toast.constants.ts"],"sourcesContent":["export const DefaultDuration = 4000;\n"],"mappings":"AAAO,MAAM,kBAAkB;","names":[]}
@@ -10,15 +10,16 @@ import {
10
10
  useOverlayContext,
11
11
  useOverlayLifecycle
12
12
  } from "@impulse-ui-native/overlay";
13
- import { EnterDuration, ExitDuration } from "../constants/toast.constants";
13
+ import { useComponentsTokens } from "@impulse-ui-native/theme";
14
14
  function useToastLifecycle(props, duration) {
15
15
  const { id, open = true } = props;
16
16
  const { store } = useOverlayContext();
17
+ const tokens = useComponentsTokens().toast;
17
18
  const progress = useSharedValue(0);
18
19
  const enter = useEventCallback(
19
20
  (transitionId, complete) => {
20
21
  progress.set(
21
- withTiming(1, { duration: EnterDuration }, (finished) => {
22
+ withTiming(1, { duration: tokens.enterDuration }, (finished) => {
22
23
  if (finished) {
23
24
  scheduleOnRN(complete, transitionId);
24
25
  }
@@ -29,7 +30,7 @@ function useToastLifecycle(props, duration) {
29
30
  const exit = useEventCallback(
30
31
  (transitionId, complete) => {
31
32
  progress.set(
32
- withTiming(0, { duration: ExitDuration }, (finished) => {
33
+ withTiming(0, { duration: tokens.exitDuration }, (finished) => {
33
34
  if (finished) {
34
35
  scheduleOnRN(complete, transitionId);
35
36
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/hooks/use-toast-lifecycle.hook.ts"],"sourcesContent":["import { useEffect, useMemo } from \"react\";\nimport {\n cancelAnimation,\n useSharedValue,\n withTiming,\n} from \"react-native-reanimated\";\nimport { scheduleOnRN } from \"react-native-worklets\";\n\nimport type { OverlayTransitionHandler } from \"@impulse-ui-native/overlay\";\nimport { useEventCallback, useTimer } from \"@impulse-ui-native/core\";\nimport {\n useOverlayContext,\n useOverlayLifecycle,\n} from \"@impulse-ui-native/overlay\";\n\nimport type { ToastRootProps } from \"../types\";\nimport { EnterDuration, ExitDuration } from \"../constants/toast.constants\";\n\nexport function useToastLifecycle(props: ToastRootProps, duration: number) {\n const { id, open = true } = props;\n const { store } = useOverlayContext();\n\n const progress = useSharedValue(0);\n\n const enter = useEventCallback<OverlayTransitionHandler>(\n (transitionId, complete) => {\n progress.set(\n withTiming(1, { duration: EnterDuration }, (finished) => {\n if (finished) {\n scheduleOnRN(complete, transitionId);\n }\n }),\n );\n },\n );\n const exit = useEventCallback<OverlayTransitionHandler>(\n (transitionId, complete) => {\n progress.set(\n withTiming(0, { duration: ExitDuration }, (finished) => {\n if (finished) {\n scheduleOnRN(complete, transitionId);\n }\n }),\n );\n },\n );\n\n const options = useMemo(\n () => ({ onEnter: enter, onExit: exit }),\n [enter, exit],\n );\n const lifecycleProps = useMemo(() => ({ ...props, open }), [props, open]);\n const lifecycle = useOverlayLifecycle(lifecycleProps, options);\n const close = useEventCallback(() => store.close(id));\n\n useTimer({\n enabled: lifecycle.status === \"open\" && open,\n duration,\n callback: close,\n pauseOnBackground: true,\n });\n\n useEffect(() => () => cancelAnimation(progress), [progress]);\n\n return useMemo(\n () => ({ ...lifecycle, progress, close }),\n [lifecycle, progress, close],\n );\n}\n"],"mappings":"AAAA,SAAS,WAAW,eAAe;AACnC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,oBAAoB;AAG7B,SAAS,kBAAkB,gBAAgB;AAC3C;AAAA,EACE;AAAA,EACA;AAAA,OACK;AAGP,SAAS,eAAe,oBAAoB;AAErC,SAAS,kBAAkB,OAAuB,UAAkB;AACzE,QAAM,EAAE,IAAI,OAAO,KAAK,IAAI;AAC5B,QAAM,EAAE,MAAM,IAAI,kBAAkB;AAEpC,QAAM,WAAW,eAAe,CAAC;AAEjC,QAAM,QAAQ;AAAA,IACZ,CAAC,cAAc,aAAa;AAC1B,eAAS;AAAA,QACP,WAAW,GAAG,EAAE,UAAU,cAAc,GAAG,CAAC,aAAa;AACvD,cAAI,UAAU;AACZ,yBAAa,UAAU,YAAY;AAAA,UACrC;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACA,QAAM,OAAO;AAAA,IACX,CAAC,cAAc,aAAa;AAC1B,eAAS;AAAA,QACP,WAAW,GAAG,EAAE,UAAU,aAAa,GAAG,CAAC,aAAa;AACtD,cAAI,UAAU;AACZ,yBAAa,UAAU,YAAY;AAAA,UACrC;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA,QAAM,UAAU;AAAA,IACd,OAAO,EAAE,SAAS,OAAO,QAAQ,KAAK;AAAA,IACtC,CAAC,OAAO,IAAI;AAAA,EACd;AACA,QAAM,iBAAiB,QAAQ,OAAO,EAAE,GAAG,OAAO,KAAK,IAAI,CAAC,OAAO,IAAI,CAAC;AACxE,QAAM,YAAY,oBAAoB,gBAAgB,OAAO;AAC7D,QAAM,QAAQ,iBAAiB,MAAM,MAAM,MAAM,EAAE,CAAC;AAEpD,WAAS;AAAA,IACP,SAAS,UAAU,WAAW,UAAU;AAAA,IACxC;AAAA,IACA,UAAU;AAAA,IACV,mBAAmB;AAAA,EACrB,CAAC;AAED,YAAU,MAAM,MAAM,gBAAgB,QAAQ,GAAG,CAAC,QAAQ,CAAC;AAE3D,SAAO;AAAA,IACL,OAAO,EAAE,GAAG,WAAW,UAAU,MAAM;AAAA,IACvC,CAAC,WAAW,UAAU,KAAK;AAAA,EAC7B;AACF;","names":[]}
1
+ {"version":3,"sources":["../../src/hooks/use-toast-lifecycle.hook.ts"],"sourcesContent":["import { useEffect, useMemo } from \"react\";\nimport {\n cancelAnimation,\n useSharedValue,\n withTiming,\n} from \"react-native-reanimated\";\nimport { scheduleOnRN } from \"react-native-worklets\";\n\nimport type { OverlayTransitionHandler } from \"@impulse-ui-native/overlay\";\nimport { useEventCallback, useTimer } from \"@impulse-ui-native/core\";\nimport {\n useOverlayContext,\n useOverlayLifecycle,\n} from \"@impulse-ui-native/overlay\";\nimport { useComponentsTokens } from \"@impulse-ui-native/theme\";\n\nimport type { ToastRootProps } from \"../types\";\n\nexport function useToastLifecycle(props: ToastRootProps, duration: number) {\n const { id, open = true } = props;\n const { store } = useOverlayContext();\n const tokens = useComponentsTokens().toast;\n\n const progress = useSharedValue(0);\n\n const enter = useEventCallback<OverlayTransitionHandler>(\n (transitionId, complete) => {\n progress.set(\n withTiming(1, { duration: tokens.enterDuration }, (finished) => {\n if (finished) {\n scheduleOnRN(complete, transitionId);\n }\n }),\n );\n },\n );\n const exit = useEventCallback<OverlayTransitionHandler>(\n (transitionId, complete) => {\n progress.set(\n withTiming(0, { duration: tokens.exitDuration }, (finished) => {\n if (finished) {\n scheduleOnRN(complete, transitionId);\n }\n }),\n );\n },\n );\n\n const options = useMemo(\n () => ({ onEnter: enter, onExit: exit }),\n [enter, exit],\n );\n const lifecycleProps = useMemo(() => ({ ...props, open }), [props, open]);\n const lifecycle = useOverlayLifecycle(lifecycleProps, options);\n const close = useEventCallback(() => store.close(id));\n\n useTimer({\n enabled: lifecycle.status === \"open\" && open,\n duration,\n callback: close,\n pauseOnBackground: true,\n });\n\n useEffect(() => () => cancelAnimation(progress), [progress]);\n\n return useMemo(\n () => ({ ...lifecycle, progress, close }),\n [lifecycle, progress, close],\n );\n}\n"],"mappings":"AAAA,SAAS,WAAW,eAAe;AACnC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,oBAAoB;AAG7B,SAAS,kBAAkB,gBAAgB;AAC3C;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP,SAAS,2BAA2B;AAI7B,SAAS,kBAAkB,OAAuB,UAAkB;AACzE,QAAM,EAAE,IAAI,OAAO,KAAK,IAAI;AAC5B,QAAM,EAAE,MAAM,IAAI,kBAAkB;AACpC,QAAM,SAAS,oBAAoB,EAAE;AAErC,QAAM,WAAW,eAAe,CAAC;AAEjC,QAAM,QAAQ;AAAA,IACZ,CAAC,cAAc,aAAa;AAC1B,eAAS;AAAA,QACP,WAAW,GAAG,EAAE,UAAU,OAAO,cAAc,GAAG,CAAC,aAAa;AAC9D,cAAI,UAAU;AACZ,yBAAa,UAAU,YAAY;AAAA,UACrC;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACA,QAAM,OAAO;AAAA,IACX,CAAC,cAAc,aAAa;AAC1B,eAAS;AAAA,QACP,WAAW,GAAG,EAAE,UAAU,OAAO,aAAa,GAAG,CAAC,aAAa;AAC7D,cAAI,UAAU;AACZ,yBAAa,UAAU,YAAY;AAAA,UACrC;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA,QAAM,UAAU;AAAA,IACd,OAAO,EAAE,SAAS,OAAO,QAAQ,KAAK;AAAA,IACtC,CAAC,OAAO,IAAI;AAAA,EACd;AACA,QAAM,iBAAiB,QAAQ,OAAO,EAAE,GAAG,OAAO,KAAK,IAAI,CAAC,OAAO,IAAI,CAAC;AACxE,QAAM,YAAY,oBAAoB,gBAAgB,OAAO;AAC7D,QAAM,QAAQ,iBAAiB,MAAM,MAAM,MAAM,EAAE,CAAC;AAEpD,WAAS;AAAA,IACP,SAAS,UAAU,WAAW,UAAU;AAAA,IACxC;AAAA,IACA,UAAU;AAAA,IACV,mBAAmB;AAAA,EACrB,CAAC;AAED,YAAU,MAAM,MAAM,gBAAgB,QAAQ,GAAG,CAAC,QAAQ,CAAC;AAE3D,SAAO;AAAA,IACL,OAAO,EAAE,GAAG,WAAW,UAAU,MAAM;AAAA,IACvC,CAAC,WAAW,UAAU,KAAK;AAAA,EAC7B;AACF;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@impulse-ui-native/toast",
3
- "version": "8.1.0",
3
+ "version": "8.3.0",
4
4
  "description": "Compound toast notifications for ImpulseUI Native.",
5
5
  "keywords": [
6
6
  "react-native",
@@ -27,11 +27,11 @@
27
27
  ],
28
28
  "sideEffects": false,
29
29
  "dependencies": {
30
- "@impulse-ui-native/theme": "8.1.0",
31
- "@impulse-ui-native/primitives": "8.1.0",
32
- "@impulse-ui-native/overlay": "8.1.0",
33
- "@impulse-ui-native/icon": "8.1.0",
34
- "@impulse-ui-native/core": "8.1.0"
30
+ "@impulse-ui-native/theme": "8.3.0",
31
+ "@impulse-ui-native/primitives": "8.3.0",
32
+ "@impulse-ui-native/core": "8.3.0",
33
+ "@impulse-ui-native/overlay": "8.3.0",
34
+ "@impulse-ui-native/icon": "8.3.0"
35
35
  },
36
36
  "devDependencies": {
37
37
  "@types/react": "~19.2.14",