beautiful-snackbar 1.0.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 (79) hide show
  1. package/README.md +233 -0
  2. package/example/.claude/settings.json +5 -0
  3. package/example/.vscode/extensions.json +1 -0
  4. package/example/.vscode/settings.json +7 -0
  5. package/example/AGENTS.md +3 -0
  6. package/example/CLAUDE.md +1 -0
  7. package/example/app.json +44 -0
  8. package/example/assets/expo.icon/Assets/expo-symbol 2.svg +3 -0
  9. package/example/assets/expo.icon/Assets/grid.png +0 -0
  10. package/example/assets/expo.icon/icon.json +40 -0
  11. package/example/assets/images/android-icon-background.png +0 -0
  12. package/example/assets/images/android-icon-foreground.png +0 -0
  13. package/example/assets/images/android-icon-monochrome.png +0 -0
  14. package/example/assets/images/expo-badge-white.png +0 -0
  15. package/example/assets/images/expo-badge.png +0 -0
  16. package/example/assets/images/expo-logo.png +0 -0
  17. package/example/assets/images/favicon.png +0 -0
  18. package/example/assets/images/icon.png +0 -0
  19. package/example/assets/images/logo-glow.png +0 -0
  20. package/example/assets/images/react-logo.png +0 -0
  21. package/example/assets/images/react-logo@2x.png +0 -0
  22. package/example/assets/images/react-logo@3x.png +0 -0
  23. package/example/assets/images/splash-icon.png +0 -0
  24. package/example/assets/images/tabIcons/explore.png +0 -0
  25. package/example/assets/images/tabIcons/explore@2x.png +0 -0
  26. package/example/assets/images/tabIcons/explore@3x.png +0 -0
  27. package/example/assets/images/tabIcons/home.png +0 -0
  28. package/example/assets/images/tabIcons/home@2x.png +0 -0
  29. package/example/assets/images/tabIcons/home@3x.png +0 -0
  30. package/example/assets/images/tutorial-web.png +0 -0
  31. package/example/metro.config.js +24 -0
  32. package/example/package.json +46 -0
  33. package/example/scripts/reset-project.js +114 -0
  34. package/example/src/app/_layout.tsx +63 -0
  35. package/example/src/app/explore.tsx +181 -0
  36. package/example/src/app/index.tsx +641 -0
  37. package/example/src/components/animated-icon.module.css +6 -0
  38. package/example/src/components/animated-icon.tsx +132 -0
  39. package/example/src/components/animated-icon.web.tsx +108 -0
  40. package/example/src/components/app-tabs.tsx +33 -0
  41. package/example/src/components/app-tabs.web.tsx +116 -0
  42. package/example/src/components/external-link.tsx +25 -0
  43. package/example/src/components/hint-row.tsx +35 -0
  44. package/example/src/components/themed-text.tsx +73 -0
  45. package/example/src/components/themed-view.tsx +16 -0
  46. package/example/src/components/ui/collapsible.tsx +65 -0
  47. package/example/src/components/web-badge.tsx +44 -0
  48. package/example/src/constants/theme.ts +66 -0
  49. package/example/src/global.css +9 -0
  50. package/example/src/hooks/use-color-scheme.ts +1 -0
  51. package/example/src/hooks/use-color-scheme.web.ts +21 -0
  52. package/example/src/hooks/use-theme.ts +14 -0
  53. package/example/tsconfig.json +35 -0
  54. package/lib/components/ActionableSnackbar.d.ts +7 -0
  55. package/lib/components/ActionableSnackbar.js +96 -0
  56. package/lib/components/BeautifulSnackbar.d.ts +11 -0
  57. package/lib/components/BeautifulSnackbar.js +189 -0
  58. package/lib/components/StandardSnackbar.d.ts +7 -0
  59. package/lib/components/StandardSnackbar.js +65 -0
  60. package/lib/constants.d.ts +7 -0
  61. package/lib/constants.js +20 -0
  62. package/lib/index.d.ts +5 -0
  63. package/lib/index.js +11 -0
  64. package/lib/manager.d.ts +58 -0
  65. package/lib/manager.js +107 -0
  66. package/lib/types.d.ts +25 -0
  67. package/lib/types.js +2 -0
  68. package/lib/useSnackbarAnimation.d.ts +14 -0
  69. package/lib/useSnackbarAnimation.js +118 -0
  70. package/package.json +33 -0
  71. package/src/components/ActionableSnackbar.tsx +109 -0
  72. package/src/components/BeautifulSnackbar.tsx +203 -0
  73. package/src/components/StandardSnackbar.tsx +70 -0
  74. package/src/constants.ts +20 -0
  75. package/src/index.ts +5 -0
  76. package/src/manager.ts +151 -0
  77. package/src/types.ts +27 -0
  78. package/src/useSnackbarAnimation.ts +145 -0
  79. package/tsconfig.json +23 -0
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Below are the colors that are used in the app. The colors are defined in the light and dark mode.
3
+ * There are many other ways to style your app. For example, [Nativewind](https://www.nativewind.dev/), [Tamagui](https://tamagui.dev/), [unistyles](https://reactnativeunistyles.vercel.app), etc.
4
+ */
5
+
6
+ import '@/global.css';
7
+
8
+ import { Platform } from 'react-native';
9
+
10
+ export const Colors = {
11
+ light: {
12
+ text: '#000000',
13
+ background: '#ffffff',
14
+ backgroundElement: '#F0F0F3',
15
+ backgroundSelected: '#E0E1E6',
16
+ textSecondary: '#60646C',
17
+ },
18
+ dark: {
19
+ text: '#ffffff',
20
+ background: '#000000',
21
+ backgroundElement: '#212225',
22
+ backgroundSelected: '#2E3135',
23
+ textSecondary: '#B0B4BA',
24
+ },
25
+ } as const;
26
+
27
+ export type ThemeColor = keyof typeof Colors.light & keyof typeof Colors.dark;
28
+
29
+ export const Fonts = Platform.select({
30
+ ios: {
31
+ /** iOS `UIFontDescriptorSystemDesignDefault` */
32
+ sans: 'system-ui',
33
+ /** iOS `UIFontDescriptorSystemDesignSerif` */
34
+ serif: 'ui-serif',
35
+ /** iOS `UIFontDescriptorSystemDesignRounded` */
36
+ rounded: 'ui-rounded',
37
+ /** iOS `UIFontDescriptorSystemDesignMonospaced` */
38
+ mono: 'ui-monospace',
39
+ },
40
+ default: {
41
+ sans: 'normal',
42
+ serif: 'serif',
43
+ rounded: 'normal',
44
+ mono: 'monospace',
45
+ },
46
+ web: {
47
+ sans: 'var(--font-display)',
48
+ serif: 'var(--font-serif)',
49
+ rounded: 'var(--font-rounded)',
50
+ mono: 'var(--font-mono)',
51
+ },
52
+ });
53
+
54
+ export const Spacing = {
55
+ half: 2,
56
+ one: 4,
57
+ two: 8,
58
+ three: 16,
59
+ four: 24,
60
+ five: 32,
61
+ six: 64,
62
+ seven: 120,
63
+ } as const;
64
+
65
+ export const BottomTabInset = Platform.select({ ios: 50, android: 80 }) ?? 0;
66
+ export const MaxContentWidth = 800;
@@ -0,0 +1,9 @@
1
+ :root {
2
+ --font-display:
3
+ Spline Sans, Inter, ui-sans-serif, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji,
4
+ Segoe UI Symbol, Noto Color Emoji;
5
+ --font-mono:
6
+ ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace;
7
+ --font-rounded: 'SF Pro Rounded', 'Hiragino Maru Gothic ProN', Meiryo, 'MS PGothic', sans-serif;
8
+ --font-serif: Georgia, 'Times New Roman', serif;
9
+ }
@@ -0,0 +1 @@
1
+ export { useColorScheme } from 'react-native';
@@ -0,0 +1,21 @@
1
+ import { useEffect, useState } from 'react';
2
+ import { useColorScheme as useRNColorScheme } from 'react-native';
3
+
4
+ /**
5
+ * To support static rendering, this value needs to be re-calculated on the client side for web
6
+ */
7
+ export function useColorScheme() {
8
+ const [hasHydrated, setHasHydrated] = useState(false);
9
+
10
+ useEffect(() => {
11
+ setHasHydrated(true);
12
+ }, []);
13
+
14
+ const colorScheme = useRNColorScheme();
15
+
16
+ if (hasHydrated) {
17
+ return colorScheme;
18
+ }
19
+
20
+ return 'light';
21
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Learn more about light and dark modes:
3
+ * https://docs.expo.dev/guides/color-schemes/
4
+ */
5
+
6
+ import { Colors } from '@/constants/theme';
7
+ import { useColorScheme } from '@/hooks/use-color-scheme';
8
+
9
+ export function useTheme() {
10
+ const scheme = useColorScheme();
11
+ const theme = scheme === 'unspecified' ? 'light' : scheme;
12
+
13
+ return Colors[theme];
14
+ }
@@ -0,0 +1,35 @@
1
+ {
2
+ "extends": "expo/tsconfig.base",
3
+ "compilerOptions": {
4
+ "strict": true,
5
+ "jsx": "react-native",
6
+ "baseUrl": ".",
7
+ "paths": {
8
+ "@/*": [
9
+ "./src/*"
10
+ ],
11
+ "@/assets/*": [
12
+ "./assets/*"
13
+ ],
14
+ "beautiful-snackbar": [
15
+ "../src/index.ts"
16
+ ],
17
+ "react": [
18
+ "node_modules/react",
19
+ "node_modules/@types/react"
20
+ ],
21
+ "react-native": [
22
+ "node_modules/react-native",
23
+ "node_modules/@types/react-native"
24
+ ]
25
+ }
26
+ },
27
+ "include": [
28
+ "**/*.ts",
29
+ "**/*.tsx",
30
+ ".expo/types/**/*.ts",
31
+ "expo-env.d.ts",
32
+ "../src/**/*.ts",
33
+ "../src/**/*.tsx"
34
+ ]
35
+ }
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ import { SnackbarItem } from '../manager';
3
+ interface ActionableSnackbarProps {
4
+ item: SnackbarItem;
5
+ }
6
+ export declare const ActionableSnackbar: ({ item }: ActionableSnackbarProps) => React.JSX.Element;
7
+ export {};
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ActionableSnackbar = void 0;
7
+ const react_1 = __importDefault(require("react"));
8
+ const react_native_1 = require("react-native");
9
+ const manager_1 = require("../manager");
10
+ const useSnackbarAnimation_1 = require("../useSnackbarAnimation");
11
+ const ActionableSnackbar = ({ item }) => {
12
+ const { animStyle } = (0, useSnackbarAnimation_1.useSnackbarAnimation)(item);
13
+ const customContainerStyle = [
14
+ styles.wrap,
15
+ item.backgroundColor ? { backgroundColor: item.backgroundColor } : null,
16
+ item.containerStyle,
17
+ ];
18
+ const customMessageStyle = [
19
+ styles.message,
20
+ item.textColor ? { color: item.textColor } : null,
21
+ item.messageStyle,
22
+ ];
23
+ const customActionStyle = [
24
+ styles.actionText,
25
+ item.actionColor ? { color: item.actionColor } : null,
26
+ item.actionStyle,
27
+ ];
28
+ const isTop = (item.position || manager_1.snackbar.getPosition()) === 'top';
29
+ const positionStyle = isTop ? { top: 0 } : { bottom: 0 };
30
+ const handleActionPress = () => {
31
+ item.onActionPress?.();
32
+ item.onDismissRequested?.();
33
+ };
34
+ return (<react_native_1.Animated.View style={[styles.outer, positionStyle, animStyle]}>
35
+ <react_native_1.View style={customContainerStyle}>
36
+ <react_native_1.TouchableOpacity activeOpacity={1} style={styles.contentArea}>
37
+ {item.icon && <react_native_1.View style={styles.iconWrap}>{item.icon}</react_native_1.View>}
38
+ <react_native_1.Text numberOfLines={2} style={customMessageStyle}>
39
+ {item.message}
40
+ </react_native_1.Text>
41
+ </react_native_1.TouchableOpacity>
42
+ {item.actionLabel && (<react_native_1.TouchableOpacity onPress={handleActionPress} style={styles.actionBtn} activeOpacity={0.7}>
43
+ <react_native_1.Text style={customActionStyle}>
44
+ {item.actionLabel}
45
+ </react_native_1.Text>
46
+ </react_native_1.TouchableOpacity>)}
47
+ </react_native_1.View>
48
+ </react_native_1.Animated.View>);
49
+ };
50
+ exports.ActionableSnackbar = ActionableSnackbar;
51
+ const styles = react_native_1.StyleSheet.create({
52
+ outer: {
53
+ width: '100%',
54
+ position: 'absolute',
55
+ },
56
+ wrap: {
57
+ paddingVertical: 14,
58
+ paddingHorizontal: 16,
59
+ marginHorizontal: 16,
60
+ backgroundColor: '#1E293B',
61
+ flexDirection: 'row',
62
+ alignItems: 'center',
63
+ justifyContent: 'space-between',
64
+ borderRadius: 10,
65
+ shadowColor: '#000',
66
+ shadowOffset: { width: 0, height: 4 },
67
+ shadowOpacity: 0.15,
68
+ shadowRadius: 6,
69
+ elevation: 4,
70
+ },
71
+ contentArea: {
72
+ flexDirection: 'row',
73
+ alignItems: 'center',
74
+ flex: 1,
75
+ paddingRight: 12,
76
+ },
77
+ iconWrap: {
78
+ marginRight: 10,
79
+ justifyContent: 'center',
80
+ alignItems: 'center',
81
+ },
82
+ message: {
83
+ color: '#F8FAFC',
84
+ fontSize: 14,
85
+ fontWeight: '600',
86
+ flexShrink: 1,
87
+ },
88
+ actionBtn: {
89
+ justifyContent: 'center',
90
+ },
91
+ actionText: {
92
+ color: '#10B981', // Emerald 500
93
+ fontSize: 14,
94
+ fontWeight: '700',
95
+ },
96
+ });
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import { SnackbarItem } from '../manager';
3
+ export interface BeautifulSnackbarProps {
4
+ navigation?: any;
5
+ avoidKeyboard?: boolean;
6
+ templates?: Record<string, React.ComponentType<{
7
+ item: SnackbarItem;
8
+ dismiss?: () => void;
9
+ }>>;
10
+ }
11
+ export declare const BeautifulSnackbar: ({ navigation, avoidKeyboard: propAvoidKeyboard, templates, }: BeautifulSnackbarProps) => React.JSX.Element;
@@ -0,0 +1,189 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.BeautifulSnackbar = void 0;
37
+ const react_1 = __importStar(require("react"));
38
+ const react_native_1 = require("react-native");
39
+ const react_native_safe_area_context_1 = require("react-native-safe-area-context");
40
+ const manager_1 = require("../manager");
41
+ const StandardSnackbar_1 = require("./StandardSnackbar");
42
+ const ActionableSnackbar_1 = require("./ActionableSnackbar");
43
+ const useSnackbarAnimation_1 = require("../useSnackbarAnimation");
44
+ const CustomTemplateWrapper = ({ item, Template, }) => {
45
+ const { animStyle } = (0, useSnackbarAnimation_1.useSnackbarAnimation)(item);
46
+ const isTop = (item.position || manager_1.snackbar.getPosition()) === 'top';
47
+ const positionStyle = isTop ? { top: 0 } : { bottom: 0 };
48
+ const dismiss = (0, react_1.useCallback)(() => {
49
+ item.onDismissRequested?.();
50
+ }, [item]);
51
+ return (<react_native_1.Animated.View style={[styles.customOuter, positionStyle, animStyle]}>
52
+ <Template item={item} dismiss={dismiss}/>
53
+ </react_native_1.Animated.View>);
54
+ };
55
+ const BeautifulSnackbar = ({ navigation, avoidKeyboard: propAvoidKeyboard, templates, }) => {
56
+ const [activeItems, setActiveItems] = (0, react_1.useState)([]);
57
+ const [avoidKeyboard, setAvoidKeyboard] = (0, react_1.useState)(manager_1.snackbar.getAvoidKeyboard());
58
+ const [globalPosition, setGlobalPosition] = (0, react_1.useState)(manager_1.snackbar.getPosition());
59
+ const [keyboardOffset] = (0, react_1.useState)(() => new react_native_1.Animated.Value(0));
60
+ const insets = (0, react_native_safe_area_context_1.useSafeAreaInsets)();
61
+ const bottomInset = insets.bottom;
62
+ (0, react_1.useEffect)(() => {
63
+ manager_1.snackbar.registerListener(setActiveItems);
64
+ const unregisterConfig = manager_1.snackbar.registerConfigListener((config) => {
65
+ setAvoidKeyboard(config.avoidKeyboard);
66
+ setGlobalPosition(config.position);
67
+ });
68
+ return () => {
69
+ manager_1.snackbar.unregisterListener();
70
+ unregisterConfig();
71
+ };
72
+ }, []);
73
+ // Prioritize prop value if specified, otherwise fall back to manager configuration
74
+ const finalAvoidKeyboard = propAvoidKeyboard !== undefined ? propAvoidKeyboard : avoidKeyboard;
75
+ (0, react_1.useEffect)(() => {
76
+ if (!finalAvoidKeyboard) {
77
+ react_native_1.Animated.timing(keyboardOffset, {
78
+ toValue: 0,
79
+ duration: 200,
80
+ useNativeDriver: true,
81
+ }).start();
82
+ return;
83
+ }
84
+ const showEvent = react_native_1.Platform.OS === 'ios' ? 'keyboardWillShow' : 'keyboardDidShow';
85
+ const hideEvent = react_native_1.Platform.OS === 'ios' ? 'keyboardWillHide' : 'keyboardDidHide';
86
+ const showSubscription = react_native_1.Keyboard.addListener(showEvent, (e) => {
87
+ const targetOffset = Math.max(0, e.endCoordinates.height - bottomInset);
88
+ react_native_1.Animated.timing(keyboardOffset, {
89
+ toValue: targetOffset,
90
+ duration: e.duration || 250,
91
+ useNativeDriver: true,
92
+ }).start();
93
+ });
94
+ const hideSubscription = react_native_1.Keyboard.addListener(hideEvent, (e) => {
95
+ react_native_1.Animated.timing(keyboardOffset, {
96
+ toValue: 0,
97
+ duration: e.duration || 250,
98
+ useNativeDriver: true,
99
+ }).start();
100
+ });
101
+ return () => {
102
+ showSubscription.remove();
103
+ hideSubscription.remove();
104
+ };
105
+ }, [finalAvoidKeyboard, keyboardOffset, bottomInset]);
106
+ const handleNavigationStateChange = (0, react_1.useCallback)(() => {
107
+ activeItems.forEach((item) => {
108
+ if (item.dismissOnNavigation) {
109
+ item.onDismissRequested?.();
110
+ }
111
+ });
112
+ }, [activeItems]);
113
+ (0, react_1.useEffect)(() => {
114
+ let cleanup;
115
+ if (navigation && typeof navigation.addListener === 'function') {
116
+ try {
117
+ const isReady = typeof navigation.isReady === 'function' ? navigation.isReady() : true;
118
+ if (isReady) {
119
+ cleanup = navigation.addListener('state', handleNavigationStateChange);
120
+ }
121
+ }
122
+ catch (e) {
123
+ console.warn('BeautifulSnackbar failed to bind navigation listener:', e);
124
+ }
125
+ }
126
+ return cleanup;
127
+ }, [handleNavigationStateChange, navigation]);
128
+ const renderItem = (item) => {
129
+ // Custom template checks
130
+ if (item.type && templates && templates[item.type]) {
131
+ const TemplateComponent = templates[item.type];
132
+ return (<CustomTemplateWrapper key={item.id} item={item} Template={TemplateComponent}/>);
133
+ }
134
+ if (item.actionLabel && item.onActionPress) {
135
+ return <ActionableSnackbar_1.ActionableSnackbar key={item.id} item={item}/>;
136
+ }
137
+ return <StandardSnackbar_1.StandardSnackbar key={item.id} item={item}/>;
138
+ };
139
+ const topItems = activeItems.filter((item) => (item.position || globalPosition) === 'top');
140
+ const bottomItems = activeItems.filter((item) => (item.position || globalPosition) === 'bottom');
141
+ return (<react_native_1.View style={styles.rootContainer} pointerEvents="box-none">
142
+ <react_native_1.View style={styles.topContainer} pointerEvents="box-none">
143
+ {topItems.map(renderItem)}
144
+ </react_native_1.View>
145
+ <react_native_1.Animated.View style={[
146
+ styles.bottomContainer,
147
+ {
148
+ transform: [
149
+ {
150
+ translateY: keyboardOffset.interpolate({
151
+ inputRange: [0, 1000],
152
+ outputRange: [0, -1000],
153
+ }),
154
+ },
155
+ ],
156
+ },
157
+ ]} pointerEvents="box-none">
158
+ {bottomItems.map(renderItem)}
159
+ </react_native_1.Animated.View>
160
+ </react_native_1.View>);
161
+ };
162
+ exports.BeautifulSnackbar = BeautifulSnackbar;
163
+ const styles = react_native_1.StyleSheet.create({
164
+ rootContainer: {
165
+ position: 'absolute',
166
+ bottom: 0,
167
+ left: 0,
168
+ right: 0,
169
+ top: 0,
170
+ },
171
+ topContainer: {
172
+ position: 'absolute',
173
+ top: 0,
174
+ left: 0,
175
+ right: 0,
176
+ justifyContent: 'flex-start',
177
+ },
178
+ bottomContainer: {
179
+ position: 'absolute',
180
+ bottom: 0,
181
+ left: 0,
182
+ right: 0,
183
+ justifyContent: 'flex-end',
184
+ },
185
+ customOuter: {
186
+ width: '100%',
187
+ position: 'absolute',
188
+ },
189
+ });
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ import { SnackbarItem } from '../manager';
3
+ interface StandardSnackbarProps {
4
+ item: SnackbarItem;
5
+ }
6
+ export declare const StandardSnackbar: ({ item }: StandardSnackbarProps) => React.JSX.Element;
7
+ export {};
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.StandardSnackbar = void 0;
7
+ const react_1 = __importDefault(require("react"));
8
+ const react_native_1 = require("react-native");
9
+ const manager_1 = require("../manager");
10
+ const useSnackbarAnimation_1 = require("../useSnackbarAnimation");
11
+ const StandardSnackbar = ({ item }) => {
12
+ const { animStyle } = (0, useSnackbarAnimation_1.useSnackbarAnimation)(item);
13
+ const customContainerStyle = [
14
+ styles.wrap,
15
+ item.backgroundColor ? { backgroundColor: item.backgroundColor } : null,
16
+ item.containerStyle,
17
+ ];
18
+ const customMessageStyle = [
19
+ styles.message,
20
+ item.textColor ? { color: item.textColor } : null,
21
+ item.messageStyle,
22
+ ];
23
+ const isTop = (item.position || manager_1.snackbar.getPosition()) === 'top';
24
+ const positionStyle = isTop ? { top: 0 } : { bottom: 0 };
25
+ return (<react_native_1.Animated.View style={[styles.outer, positionStyle, animStyle]}>
26
+ <react_native_1.View style={customContainerStyle}>
27
+ {item.icon && <react_native_1.View style={styles.iconWrap}>{item.icon}</react_native_1.View>}
28
+ <react_native_1.Text numberOfLines={2} style={customMessageStyle}>
29
+ {item.message}
30
+ </react_native_1.Text>
31
+ </react_native_1.View>
32
+ </react_native_1.Animated.View>);
33
+ };
34
+ exports.StandardSnackbar = StandardSnackbar;
35
+ const styles = react_native_1.StyleSheet.create({
36
+ outer: {
37
+ width: '100%',
38
+ position: 'absolute',
39
+ },
40
+ wrap: {
41
+ paddingVertical: 14,
42
+ paddingHorizontal: 16,
43
+ marginHorizontal: 16,
44
+ backgroundColor: '#1E293B',
45
+ flexDirection: 'row',
46
+ alignItems: 'center',
47
+ borderRadius: 10,
48
+ shadowColor: '#000',
49
+ shadowOffset: { width: 0, height: 4 },
50
+ shadowOpacity: 0.15,
51
+ shadowRadius: 6,
52
+ elevation: 4,
53
+ },
54
+ iconWrap: {
55
+ marginRight: 10,
56
+ justifyContent: 'center',
57
+ alignItems: 'center',
58
+ },
59
+ message: {
60
+ color: '#F8FAFC',
61
+ fontSize: 14,
62
+ fontWeight: '600',
63
+ flexShrink: 1,
64
+ },
65
+ });
@@ -0,0 +1,7 @@
1
+ import { SnackbarDuration } from './types';
2
+ export declare const DURATION_SHORT = 1500;
3
+ export declare const DURATION_MEDIUM = 2200;
4
+ export declare const DURATION_LONG = 3200;
5
+ export declare const DEFAULT_HEIGHT_LIMIT = 90;
6
+ export declare const TRANSITION_SPEED = 200;
7
+ export declare const getDurationMs: (duration?: SnackbarDuration) => number;
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getDurationMs = exports.TRANSITION_SPEED = exports.DEFAULT_HEIGHT_LIMIT = exports.DURATION_LONG = exports.DURATION_MEDIUM = exports.DURATION_SHORT = void 0;
4
+ exports.DURATION_SHORT = 1500;
5
+ exports.DURATION_MEDIUM = 2200;
6
+ exports.DURATION_LONG = 3200;
7
+ exports.DEFAULT_HEIGHT_LIMIT = 90;
8
+ exports.TRANSITION_SPEED = 200;
9
+ const getDurationMs = (duration) => {
10
+ switch (duration) {
11
+ case 'long':
12
+ return exports.DURATION_LONG;
13
+ case 'medium':
14
+ return exports.DURATION_MEDIUM;
15
+ case 'short':
16
+ default:
17
+ return exports.DURATION_SHORT;
18
+ }
19
+ };
20
+ exports.getDurationMs = getDurationMs;
package/lib/index.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ export { BeautifulSnackbar } from './components/BeautifulSnackbar';
2
+ export { snackbar, SnackbarManager, SnackbarItem } from './manager';
3
+ export { useSnackbarAnimation } from './useSnackbarAnimation';
4
+ export type { SnackbarOptions, SnackbarDuration, SnackbarPosition, SnackbarAnimationType } from './types';
5
+ export type { BeautifulSnackbarProps } from './components/BeautifulSnackbar';
package/lib/index.js ADDED
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useSnackbarAnimation = exports.SnackbarItem = exports.SnackbarManager = exports.snackbar = exports.BeautifulSnackbar = void 0;
4
+ var BeautifulSnackbar_1 = require("./components/BeautifulSnackbar");
5
+ Object.defineProperty(exports, "BeautifulSnackbar", { enumerable: true, get: function () { return BeautifulSnackbar_1.BeautifulSnackbar; } });
6
+ var manager_1 = require("./manager");
7
+ Object.defineProperty(exports, "snackbar", { enumerable: true, get: function () { return manager_1.snackbar; } });
8
+ Object.defineProperty(exports, "SnackbarManager", { enumerable: true, get: function () { return manager_1.SnackbarManager; } });
9
+ Object.defineProperty(exports, "SnackbarItem", { enumerable: true, get: function () { return manager_1.SnackbarItem; } });
10
+ var useSnackbarAnimation_1 = require("./useSnackbarAnimation");
11
+ Object.defineProperty(exports, "useSnackbarAnimation", { enumerable: true, get: function () { return useSnackbarAnimation_1.useSnackbarAnimation; } });
@@ -0,0 +1,58 @@
1
+ import { ViewStyle, TextStyle } from 'react-native';
2
+ import React from 'react';
3
+ import { SnackbarOptions, SnackbarDuration, SnackbarPosition, SnackbarAnimationType } from './types';
4
+ export interface SnackbarConfig {
5
+ avoidKeyboard: boolean;
6
+ position: SnackbarPosition;
7
+ animationType: SnackbarAnimationType;
8
+ bottomOffset: number;
9
+ topOffset: number;
10
+ }
11
+ export declare class SnackbarItem {
12
+ id: string;
13
+ message: string;
14
+ messageStyle?: TextStyle;
15
+ containerStyle?: ViewStyle;
16
+ actionLabel?: string;
17
+ actionStyle?: TextStyle;
18
+ onActionPress?: () => void;
19
+ icon?: React.ReactNode;
20
+ duration: SnackbarDuration;
21
+ position?: SnackbarPosition;
22
+ animationType?: SnackbarAnimationType;
23
+ bottomOffset?: number;
24
+ topOffset?: number;
25
+ dismissOnNavigation: boolean;
26
+ backgroundColor?: string;
27
+ textColor?: string;
28
+ actionColor?: string;
29
+ type?: string;
30
+ data?: any;
31
+ onShowRequested: () => void;
32
+ onHideRequested: () => void;
33
+ onDismissRequested?: () => void;
34
+ constructor(options: SnackbarOptions, id: string);
35
+ }
36
+ export declare class SnackbarManager {
37
+ private stateListener?;
38
+ private configListeners;
39
+ private activeItems;
40
+ private counter;
41
+ private config;
42
+ registerListener(listener: (items: SnackbarItem[]) => void): void;
43
+ unregisterListener(): void;
44
+ registerConfigListener(listener: (config: SnackbarConfig) => void): () => void;
45
+ setAvoidKeyboard(val: boolean): void;
46
+ getAvoidKeyboard(): boolean;
47
+ setPosition(val: SnackbarPosition): void;
48
+ getPosition(): SnackbarPosition;
49
+ setAnimationType(val: SnackbarAnimationType): void;
50
+ getAnimationType(): SnackbarAnimationType;
51
+ setBottomOffset(val: number): void;
52
+ getBottomOffset(): number;
53
+ setTopOffset(val: number): void;
54
+ getTopOffset(): number;
55
+ show(options: SnackbarOptions): SnackbarItem;
56
+ dismiss(item: SnackbarItem): void;
57
+ }
58
+ export declare const snackbar: SnackbarManager;