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.
- package/README.md +233 -0
- package/example/.claude/settings.json +5 -0
- package/example/.vscode/extensions.json +1 -0
- package/example/.vscode/settings.json +7 -0
- package/example/AGENTS.md +3 -0
- package/example/CLAUDE.md +1 -0
- package/example/app.json +44 -0
- package/example/assets/expo.icon/Assets/expo-symbol 2.svg +3 -0
- package/example/assets/expo.icon/Assets/grid.png +0 -0
- package/example/assets/expo.icon/icon.json +40 -0
- package/example/assets/images/android-icon-background.png +0 -0
- package/example/assets/images/android-icon-foreground.png +0 -0
- package/example/assets/images/android-icon-monochrome.png +0 -0
- package/example/assets/images/expo-badge-white.png +0 -0
- package/example/assets/images/expo-badge.png +0 -0
- package/example/assets/images/expo-logo.png +0 -0
- package/example/assets/images/favicon.png +0 -0
- package/example/assets/images/icon.png +0 -0
- package/example/assets/images/logo-glow.png +0 -0
- package/example/assets/images/react-logo.png +0 -0
- package/example/assets/images/react-logo@2x.png +0 -0
- package/example/assets/images/react-logo@3x.png +0 -0
- package/example/assets/images/splash-icon.png +0 -0
- package/example/assets/images/tabIcons/explore.png +0 -0
- package/example/assets/images/tabIcons/explore@2x.png +0 -0
- package/example/assets/images/tabIcons/explore@3x.png +0 -0
- package/example/assets/images/tabIcons/home.png +0 -0
- package/example/assets/images/tabIcons/home@2x.png +0 -0
- package/example/assets/images/tabIcons/home@3x.png +0 -0
- package/example/assets/images/tutorial-web.png +0 -0
- package/example/metro.config.js +24 -0
- package/example/package.json +46 -0
- package/example/scripts/reset-project.js +114 -0
- package/example/src/app/_layout.tsx +63 -0
- package/example/src/app/explore.tsx +181 -0
- package/example/src/app/index.tsx +641 -0
- package/example/src/components/animated-icon.module.css +6 -0
- package/example/src/components/animated-icon.tsx +132 -0
- package/example/src/components/animated-icon.web.tsx +108 -0
- package/example/src/components/app-tabs.tsx +33 -0
- package/example/src/components/app-tabs.web.tsx +116 -0
- package/example/src/components/external-link.tsx +25 -0
- package/example/src/components/hint-row.tsx +35 -0
- package/example/src/components/themed-text.tsx +73 -0
- package/example/src/components/themed-view.tsx +16 -0
- package/example/src/components/ui/collapsible.tsx +65 -0
- package/example/src/components/web-badge.tsx +44 -0
- package/example/src/constants/theme.ts +66 -0
- package/example/src/global.css +9 -0
- package/example/src/hooks/use-color-scheme.ts +1 -0
- package/example/src/hooks/use-color-scheme.web.ts +21 -0
- package/example/src/hooks/use-theme.ts +14 -0
- package/example/tsconfig.json +35 -0
- package/lib/components/ActionableSnackbar.d.ts +7 -0
- package/lib/components/ActionableSnackbar.js +96 -0
- package/lib/components/BeautifulSnackbar.d.ts +11 -0
- package/lib/components/BeautifulSnackbar.js +189 -0
- package/lib/components/StandardSnackbar.d.ts +7 -0
- package/lib/components/StandardSnackbar.js +65 -0
- package/lib/constants.d.ts +7 -0
- package/lib/constants.js +20 -0
- package/lib/index.d.ts +5 -0
- package/lib/index.js +11 -0
- package/lib/manager.d.ts +58 -0
- package/lib/manager.js +107 -0
- package/lib/types.d.ts +25 -0
- package/lib/types.js +2 -0
- package/lib/useSnackbarAnimation.d.ts +14 -0
- package/lib/useSnackbarAnimation.js +118 -0
- package/package.json +33 -0
- package/src/components/ActionableSnackbar.tsx +109 -0
- package/src/components/BeautifulSnackbar.tsx +203 -0
- package/src/components/StandardSnackbar.tsx +70 -0
- package/src/constants.ts +20 -0
- package/src/index.ts +5 -0
- package/src/manager.ts +151 -0
- package/src/types.ts +27 -0
- package/src/useSnackbarAnimation.ts +145 -0
- package/tsconfig.json +23 -0
|
@@ -0,0 +1,641 @@
|
|
|
1
|
+
import React, { useEffect, useState } from "react";
|
|
2
|
+
import {
|
|
3
|
+
Platform,
|
|
4
|
+
StyleSheet,
|
|
5
|
+
Switch,
|
|
6
|
+
Text,
|
|
7
|
+
TextInput,
|
|
8
|
+
TouchableOpacity,
|
|
9
|
+
View,
|
|
10
|
+
useColorScheme,
|
|
11
|
+
ScrollView,
|
|
12
|
+
} from "react-native";
|
|
13
|
+
import { SafeAreaView } from "react-native-safe-area-context";
|
|
14
|
+
import { snackbar } from "beautiful-snackbar";
|
|
15
|
+
|
|
16
|
+
import { ThemedText } from "@/components/themed-text";
|
|
17
|
+
import { ThemedView } from "@/components/themed-view";
|
|
18
|
+
import { Colors, Spacing, MaxContentWidth } from "@/constants/theme";
|
|
19
|
+
|
|
20
|
+
export default function HomeScreen() {
|
|
21
|
+
const scheme = useColorScheme();
|
|
22
|
+
const colors = Colors[scheme === "dark" ? "dark" : "light"];
|
|
23
|
+
const [avoidKeyboard, setAvoidKeyboard] = useState(
|
|
24
|
+
snackbar.getAvoidKeyboard(),
|
|
25
|
+
);
|
|
26
|
+
const [globalPosition, setGlobalPosition] = useState(snackbar.getPosition());
|
|
27
|
+
const [globalAnimation, setGlobalAnimation] = useState(
|
|
28
|
+
snackbar.getAnimationType(),
|
|
29
|
+
);
|
|
30
|
+
const [globalBottomOffset, setGlobalBottomOffset] = useState(
|
|
31
|
+
snackbar.getBottomOffset(),
|
|
32
|
+
);
|
|
33
|
+
const [globalTopOffset, setGlobalTopOffset] = useState(
|
|
34
|
+
snackbar.getTopOffset(),
|
|
35
|
+
);
|
|
36
|
+
const [inputText, setInputText] = useState("");
|
|
37
|
+
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
return snackbar.registerConfigListener((config) => {
|
|
40
|
+
setAvoidKeyboard(config.avoidKeyboard);
|
|
41
|
+
setGlobalPosition(config.position);
|
|
42
|
+
setGlobalAnimation(config.animationType);
|
|
43
|
+
setGlobalBottomOffset(config.bottomOffset);
|
|
44
|
+
setGlobalTopOffset(config.topOffset);
|
|
45
|
+
});
|
|
46
|
+
}, []);
|
|
47
|
+
|
|
48
|
+
const handleToggleAvoidKeyboard = (value: boolean) => {
|
|
49
|
+
snackbar.setAvoidKeyboard(value);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const handleSetPosition = (value: "top" | "bottom") => {
|
|
53
|
+
snackbar.setPosition(value);
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const handleSetAnimation = (value: "slide" | "fade" | "scale") => {
|
|
57
|
+
snackbar.setAnimationType(value);
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const handleSetBottomOffset = (value: number) => {
|
|
61
|
+
snackbar.setBottomOffset(value);
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const handleSetTopOffset = (value: number) => {
|
|
65
|
+
snackbar.setTopOffset(value);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const triggerSuccess = () => {
|
|
69
|
+
snackbar.show({
|
|
70
|
+
message: "Success: Your profile has been updated successfully.",
|
|
71
|
+
backgroundColor: "#10B981",
|
|
72
|
+
duration: "short",
|
|
73
|
+
});
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const triggerError = () => {
|
|
77
|
+
snackbar.show({
|
|
78
|
+
message:
|
|
79
|
+
"Error: Failed to upload photo. Please check your internet connection.",
|
|
80
|
+
backgroundColor: "#EF4444",
|
|
81
|
+
duration: "long",
|
|
82
|
+
});
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const triggerWarning = () => {
|
|
86
|
+
snackbar.show({
|
|
87
|
+
message: "Warning: Your storage is 90% full. Upgrade to get more space.",
|
|
88
|
+
backgroundColor: "#F59E0B",
|
|
89
|
+
duration: "long",
|
|
90
|
+
});
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const triggerInfo = () => {
|
|
94
|
+
snackbar.show({
|
|
95
|
+
message: "Info: Version 2.0 is now live with exciting new features.",
|
|
96
|
+
backgroundColor: "#3B82F6",
|
|
97
|
+
duration: "medium",
|
|
98
|
+
});
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const triggerActionable = () => {
|
|
102
|
+
snackbar.show({
|
|
103
|
+
message: "Message Deleted: Your message has been permanently deleted.",
|
|
104
|
+
backgroundColor: "#1E293B",
|
|
105
|
+
actionColor: "#818CF8",
|
|
106
|
+
duration: "long",
|
|
107
|
+
actionLabel: "Undo",
|
|
108
|
+
onActionPress: () => {
|
|
109
|
+
snackbar.show({
|
|
110
|
+
message: "Action Restored: Deletion canceled.",
|
|
111
|
+
backgroundColor: "#10B981",
|
|
112
|
+
duration: "short",
|
|
113
|
+
});
|
|
114
|
+
},
|
|
115
|
+
});
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
const triggerInfinite = () => {
|
|
119
|
+
snackbar.show({
|
|
120
|
+
message:
|
|
121
|
+
"Offline: You are now browsing in offline mode. Pull to refresh.",
|
|
122
|
+
backgroundColor: "#1E293B",
|
|
123
|
+
actionColor: "#F59E0B",
|
|
124
|
+
duration: "infinite",
|
|
125
|
+
actionLabel: "Dismiss",
|
|
126
|
+
onActionPress: () => {
|
|
127
|
+
// Just closes itself automatically when action is pressed
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
const triggerCustomCard = () => {
|
|
133
|
+
snackbar.show({
|
|
134
|
+
type: "customCard",
|
|
135
|
+
message: "Premium Feature Unlocked!",
|
|
136
|
+
data: {
|
|
137
|
+
subtitle: "Enjoy unlimited ad-free streaming and offline play.",
|
|
138
|
+
badge: "PRO",
|
|
139
|
+
},
|
|
140
|
+
duration: "medium",
|
|
141
|
+
});
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const triggerCustomOffset = () => {
|
|
145
|
+
snackbar.show({
|
|
146
|
+
message: "Custom Offset: Floating high at 120px!",
|
|
147
|
+
backgroundColor: "#4f46e5",
|
|
148
|
+
bottomOffset: 120,
|
|
149
|
+
duration: "short",
|
|
150
|
+
});
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
const triggerMultiple = () => {
|
|
154
|
+
triggerSuccess();
|
|
155
|
+
setTimeout(() => triggerInfo(), 300);
|
|
156
|
+
setTimeout(() => triggerWarning(), 600);
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
return (
|
|
160
|
+
<ThemedView style={styles.container}>
|
|
161
|
+
<SafeAreaView style={styles.safeArea} edges={["top", "left", "right"]}>
|
|
162
|
+
<ScrollView
|
|
163
|
+
contentContainerStyle={styles.scrollContent}
|
|
164
|
+
showsVerticalScrollIndicator={false}
|
|
165
|
+
>
|
|
166
|
+
{/* Header */}
|
|
167
|
+
<View style={styles.header}>
|
|
168
|
+
<Text style={[styles.glowText, { color: colors.text }]}>
|
|
169
|
+
Beautiful Snackbar
|
|
170
|
+
</Text>
|
|
171
|
+
<ThemedText type="small" style={styles.subtitle}>
|
|
172
|
+
A highly customizable, animated notification system.
|
|
173
|
+
</ThemedText>
|
|
174
|
+
</View>
|
|
175
|
+
|
|
176
|
+
{/* Configuration Card */}
|
|
177
|
+
<View
|
|
178
|
+
style={[styles.card, { backgroundColor: colors.backgroundElement }]}
|
|
179
|
+
>
|
|
180
|
+
{/* Avoid Keyboard switch */}
|
|
181
|
+
<View style={styles.settingRow}>
|
|
182
|
+
<View style={styles.settingTextContainer}>
|
|
183
|
+
<Text style={[styles.settingTitle, { color: colors.text }]}>
|
|
184
|
+
Avoid Keyboard
|
|
185
|
+
</Text>
|
|
186
|
+
<Text
|
|
187
|
+
style={[styles.settingDesc, { color: colors.textSecondary }]}
|
|
188
|
+
>
|
|
189
|
+
If enabled, bottom snackbars slide up above the soft keyboard.
|
|
190
|
+
</Text>
|
|
191
|
+
</View>
|
|
192
|
+
<Switch
|
|
193
|
+
value={avoidKeyboard}
|
|
194
|
+
onValueChange={handleToggleAvoidKeyboard}
|
|
195
|
+
trackColor={{ false: "#767577", true: "#4ade80" }}
|
|
196
|
+
thumbColor={Platform.OS === "ios" ? undefined : "#f4f3f4"}
|
|
197
|
+
/>
|
|
198
|
+
</View>
|
|
199
|
+
|
|
200
|
+
{/* Position segmented control */}
|
|
201
|
+
<View style={[styles.settingRow, { marginTop: Spacing.three }]}>
|
|
202
|
+
<View style={styles.settingTextContainer}>
|
|
203
|
+
<Text style={[styles.settingTitle, { color: colors.text }]}>
|
|
204
|
+
Global Position
|
|
205
|
+
</Text>
|
|
206
|
+
<Text
|
|
207
|
+
style={[styles.settingDesc, { color: colors.textSecondary }]}
|
|
208
|
+
>
|
|
209
|
+
Configure where notifications render on the screen.
|
|
210
|
+
</Text>
|
|
211
|
+
</View>
|
|
212
|
+
<View
|
|
213
|
+
style={[
|
|
214
|
+
styles.segmentContainer,
|
|
215
|
+
{ backgroundColor: colors.backgroundSelected },
|
|
216
|
+
]}
|
|
217
|
+
>
|
|
218
|
+
{(["top", "bottom"] as const).map((pos) => (
|
|
219
|
+
<TouchableOpacity
|
|
220
|
+
key={pos}
|
|
221
|
+
style={[
|
|
222
|
+
styles.segmentBtn,
|
|
223
|
+
globalPosition === pos && { backgroundColor: "#6d28d9" },
|
|
224
|
+
]}
|
|
225
|
+
onPress={() => handleSetPosition(pos)}
|
|
226
|
+
>
|
|
227
|
+
<Text
|
|
228
|
+
style={[
|
|
229
|
+
styles.segmentBtnText,
|
|
230
|
+
{
|
|
231
|
+
color:
|
|
232
|
+
globalPosition === pos
|
|
233
|
+
? "#ffffff"
|
|
234
|
+
: colors.textSecondary,
|
|
235
|
+
},
|
|
236
|
+
{ textTransform: "capitalize" },
|
|
237
|
+
]}
|
|
238
|
+
>
|
|
239
|
+
{pos}
|
|
240
|
+
</Text>
|
|
241
|
+
</TouchableOpacity>
|
|
242
|
+
))}
|
|
243
|
+
</View>
|
|
244
|
+
</View>
|
|
245
|
+
|
|
246
|
+
{/* Animation Type segmented control */}
|
|
247
|
+
<View style={[styles.settingRow, { marginTop: Spacing.three }]}>
|
|
248
|
+
<View style={styles.settingTextContainer}>
|
|
249
|
+
<Text style={[styles.settingTitle, { color: colors.text }]}>
|
|
250
|
+
Animation Type
|
|
251
|
+
</Text>
|
|
252
|
+
<Text
|
|
253
|
+
style={[styles.settingDesc, { color: colors.textSecondary }]}
|
|
254
|
+
>
|
|
255
|
+
Transition preset style for snackbars.
|
|
256
|
+
</Text>
|
|
257
|
+
</View>
|
|
258
|
+
<View
|
|
259
|
+
style={[
|
|
260
|
+
styles.segmentContainer,
|
|
261
|
+
{ backgroundColor: colors.backgroundSelected },
|
|
262
|
+
]}
|
|
263
|
+
>
|
|
264
|
+
{(["slide", "fade", "scale"] as const).map((anim) => (
|
|
265
|
+
<TouchableOpacity
|
|
266
|
+
key={anim}
|
|
267
|
+
style={[
|
|
268
|
+
styles.segmentBtn,
|
|
269
|
+
globalAnimation === anim && {
|
|
270
|
+
backgroundColor: "#6d28d9",
|
|
271
|
+
},
|
|
272
|
+
]}
|
|
273
|
+
onPress={() => handleSetAnimation(anim)}
|
|
274
|
+
>
|
|
275
|
+
<Text
|
|
276
|
+
style={[
|
|
277
|
+
styles.segmentBtnText,
|
|
278
|
+
{
|
|
279
|
+
color:
|
|
280
|
+
globalAnimation === anim
|
|
281
|
+
? "#ffffff"
|
|
282
|
+
: colors.textSecondary,
|
|
283
|
+
},
|
|
284
|
+
{ textTransform: "capitalize" },
|
|
285
|
+
]}
|
|
286
|
+
>
|
|
287
|
+
{anim}
|
|
288
|
+
</Text>
|
|
289
|
+
</TouchableOpacity>
|
|
290
|
+
))}
|
|
291
|
+
</View>
|
|
292
|
+
</View>
|
|
293
|
+
|
|
294
|
+
{/* Bottom Offset segmented control */}
|
|
295
|
+
<View style={[styles.settingRow, { marginTop: Spacing.three }]}>
|
|
296
|
+
<View style={styles.settingTextContainer}>
|
|
297
|
+
<Text style={[styles.settingTitle, { color: colors.text }]}>
|
|
298
|
+
Bottom Offset
|
|
299
|
+
</Text>
|
|
300
|
+
<Text
|
|
301
|
+
style={[styles.settingDesc, { color: colors.textSecondary }]}
|
|
302
|
+
>
|
|
303
|
+
Adjust default spacing from bottom/keyboard.
|
|
304
|
+
</Text>
|
|
305
|
+
</View>
|
|
306
|
+
<View
|
|
307
|
+
style={[
|
|
308
|
+
styles.segmentContainer,
|
|
309
|
+
{ backgroundColor: colors.backgroundSelected },
|
|
310
|
+
]}
|
|
311
|
+
>
|
|
312
|
+
{([16, 24, 40, 60] as const).map((offsetVal) => (
|
|
313
|
+
<TouchableOpacity
|
|
314
|
+
key={offsetVal}
|
|
315
|
+
style={[
|
|
316
|
+
styles.segmentBtn,
|
|
317
|
+
globalBottomOffset === offsetVal && {
|
|
318
|
+
backgroundColor: "#6d28d9",
|
|
319
|
+
},
|
|
320
|
+
]}
|
|
321
|
+
onPress={() => handleSetBottomOffset(offsetVal)}
|
|
322
|
+
>
|
|
323
|
+
<Text
|
|
324
|
+
style={[
|
|
325
|
+
styles.segmentBtnText,
|
|
326
|
+
{
|
|
327
|
+
color:
|
|
328
|
+
globalBottomOffset === offsetVal
|
|
329
|
+
? "#ffffff"
|
|
330
|
+
: colors.textSecondary,
|
|
331
|
+
},
|
|
332
|
+
]}
|
|
333
|
+
>
|
|
334
|
+
{offsetVal}px
|
|
335
|
+
</Text>
|
|
336
|
+
</TouchableOpacity>
|
|
337
|
+
))}
|
|
338
|
+
</View>
|
|
339
|
+
</View>
|
|
340
|
+
|
|
341
|
+
{/* Top Offset segmented control */}
|
|
342
|
+
<View style={[styles.settingRow, { marginTop: Spacing.three }]}>
|
|
343
|
+
<View style={styles.settingTextContainer}>
|
|
344
|
+
<Text style={[styles.settingTitle, { color: colors.text }]}>
|
|
345
|
+
Top Offset
|
|
346
|
+
</Text>
|
|
347
|
+
<Text
|
|
348
|
+
style={[styles.settingDesc, { color: colors.textSecondary }]}
|
|
349
|
+
>
|
|
350
|
+
Adjust default spacing from top of screen.
|
|
351
|
+
</Text>
|
|
352
|
+
</View>
|
|
353
|
+
<View
|
|
354
|
+
style={[
|
|
355
|
+
styles.segmentContainer,
|
|
356
|
+
{ backgroundColor: colors.backgroundSelected },
|
|
357
|
+
]}
|
|
358
|
+
>
|
|
359
|
+
{([24, 40, 60, 80] as const).map((offsetVal) => (
|
|
360
|
+
<TouchableOpacity
|
|
361
|
+
key={offsetVal}
|
|
362
|
+
style={[
|
|
363
|
+
styles.segmentBtn,
|
|
364
|
+
globalTopOffset === offsetVal && {
|
|
365
|
+
backgroundColor: "#6d28d9",
|
|
366
|
+
},
|
|
367
|
+
]}
|
|
368
|
+
onPress={() => handleSetTopOffset(offsetVal)}
|
|
369
|
+
>
|
|
370
|
+
<Text
|
|
371
|
+
style={[
|
|
372
|
+
styles.segmentBtnText,
|
|
373
|
+
{
|
|
374
|
+
color:
|
|
375
|
+
globalTopOffset === offsetVal
|
|
376
|
+
? "#ffffff"
|
|
377
|
+
: colors.textSecondary,
|
|
378
|
+
},
|
|
379
|
+
]}
|
|
380
|
+
>
|
|
381
|
+
{offsetVal}px
|
|
382
|
+
</Text>
|
|
383
|
+
</TouchableOpacity>
|
|
384
|
+
))}
|
|
385
|
+
</View>
|
|
386
|
+
</View>
|
|
387
|
+
</View>
|
|
388
|
+
|
|
389
|
+
{/* Actions grid */}
|
|
390
|
+
<Text style={[styles.sectionTitle, { color: colors.text }]}>
|
|
391
|
+
Standard Types
|
|
392
|
+
</Text>
|
|
393
|
+
<View style={styles.grid}>
|
|
394
|
+
<TouchableOpacity
|
|
395
|
+
style={[styles.btn, styles.successBtn]}
|
|
396
|
+
onPress={triggerSuccess}
|
|
397
|
+
>
|
|
398
|
+
<Text style={styles.btnText}>Success Toast</Text>
|
|
399
|
+
</TouchableOpacity>
|
|
400
|
+
|
|
401
|
+
<TouchableOpacity
|
|
402
|
+
style={[styles.btn, styles.errorBtn]}
|
|
403
|
+
onPress={triggerError}
|
|
404
|
+
>
|
|
405
|
+
<Text style={styles.btnText}>Error Toast</Text>
|
|
406
|
+
</TouchableOpacity>
|
|
407
|
+
|
|
408
|
+
<TouchableOpacity
|
|
409
|
+
style={[styles.btn, styles.warningBtn]}
|
|
410
|
+
onPress={triggerWarning}
|
|
411
|
+
>
|
|
412
|
+
<Text style={styles.btnText}>Warning Toast</Text>
|
|
413
|
+
</TouchableOpacity>
|
|
414
|
+
|
|
415
|
+
<TouchableOpacity
|
|
416
|
+
style={[styles.btn, styles.infoBtn]}
|
|
417
|
+
onPress={triggerInfo}
|
|
418
|
+
>
|
|
419
|
+
<Text style={styles.btnText}>Info Toast</Text>
|
|
420
|
+
</TouchableOpacity>
|
|
421
|
+
</View>
|
|
422
|
+
|
|
423
|
+
{/* Actionable & Advanced */}
|
|
424
|
+
<Text style={[styles.sectionTitle, { color: colors.text }]}>
|
|
425
|
+
Advanced Interactions
|
|
426
|
+
</Text>
|
|
427
|
+
<View style={styles.grid}>
|
|
428
|
+
<TouchableOpacity
|
|
429
|
+
style={[styles.btn, styles.actionBtn]}
|
|
430
|
+
onPress={triggerActionable}
|
|
431
|
+
>
|
|
432
|
+
<Text style={styles.btnText}>With Action Button</Text>
|
|
433
|
+
</TouchableOpacity>
|
|
434
|
+
|
|
435
|
+
<TouchableOpacity
|
|
436
|
+
style={[styles.btn, styles.infiniteBtn]}
|
|
437
|
+
onPress={triggerInfinite}
|
|
438
|
+
>
|
|
439
|
+
<Text style={styles.btnText}>Infinite Banner</Text>
|
|
440
|
+
</TouchableOpacity>
|
|
441
|
+
|
|
442
|
+
<TouchableOpacity
|
|
443
|
+
style={[styles.btn, styles.multiBtn]}
|
|
444
|
+
onPress={triggerCustomCard}
|
|
445
|
+
>
|
|
446
|
+
<Text style={styles.btnText}>Custom UI Toast</Text>
|
|
447
|
+
</TouchableOpacity>
|
|
448
|
+
|
|
449
|
+
<TouchableOpacity
|
|
450
|
+
style={[styles.btn, { backgroundColor: "#8b5cf6" }]}
|
|
451
|
+
onPress={triggerCustomOffset}
|
|
452
|
+
>
|
|
453
|
+
<Text style={styles.btnText}>Custom Offset</Text>
|
|
454
|
+
</TouchableOpacity>
|
|
455
|
+
|
|
456
|
+
<TouchableOpacity
|
|
457
|
+
style={[styles.btn, { backgroundColor: "#06b6d4" }]}
|
|
458
|
+
onPress={triggerMultiple}
|
|
459
|
+
>
|
|
460
|
+
<Text style={styles.btnText}>Queue Demo</Text>
|
|
461
|
+
</TouchableOpacity>
|
|
462
|
+
</View>
|
|
463
|
+
|
|
464
|
+
{/* Test area */}
|
|
465
|
+
<View
|
|
466
|
+
style={[
|
|
467
|
+
styles.card,
|
|
468
|
+
{
|
|
469
|
+
backgroundColor: colors.backgroundElement,
|
|
470
|
+
marginTop: Spacing.four,
|
|
471
|
+
},
|
|
472
|
+
]}
|
|
473
|
+
>
|
|
474
|
+
<Text
|
|
475
|
+
style={[
|
|
476
|
+
styles.settingTitle,
|
|
477
|
+
{ color: colors.text, marginBottom: Spacing.one },
|
|
478
|
+
]}
|
|
479
|
+
>
|
|
480
|
+
Keyboard Offset Test
|
|
481
|
+
</Text>
|
|
482
|
+
<Text
|
|
483
|
+
style={[
|
|
484
|
+
styles.settingDesc,
|
|
485
|
+
{ color: colors.textSecondary, marginBottom: Spacing.two },
|
|
486
|
+
]}
|
|
487
|
+
>
|
|
488
|
+
Tap the input field below to raise the keyboard. Observe how the
|
|
489
|
+
active snackbars dynamically float above it.
|
|
490
|
+
</Text>
|
|
491
|
+
<TextInput
|
|
492
|
+
style={[
|
|
493
|
+
styles.textInput,
|
|
494
|
+
{
|
|
495
|
+
backgroundColor: colors.background,
|
|
496
|
+
color: colors.text,
|
|
497
|
+
borderColor: colors.backgroundSelected,
|
|
498
|
+
},
|
|
499
|
+
]}
|
|
500
|
+
placeholder="Tap here to open keyboard..."
|
|
501
|
+
placeholderTextColor={colors.textSecondary}
|
|
502
|
+
value={inputText}
|
|
503
|
+
onChangeText={setInputText}
|
|
504
|
+
/>
|
|
505
|
+
</View>
|
|
506
|
+
</ScrollView>
|
|
507
|
+
</SafeAreaView>
|
|
508
|
+
</ThemedView>
|
|
509
|
+
);
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
const styles = StyleSheet.create({
|
|
513
|
+
container: {
|
|
514
|
+
flex: 1,
|
|
515
|
+
},
|
|
516
|
+
safeArea: {
|
|
517
|
+
flex: 1,
|
|
518
|
+
alignSelf: "center",
|
|
519
|
+
width: "100%",
|
|
520
|
+
maxWidth: MaxContentWidth,
|
|
521
|
+
},
|
|
522
|
+
scrollContent: {
|
|
523
|
+
paddingHorizontal: Spacing.three,
|
|
524
|
+
paddingTop: Spacing.four,
|
|
525
|
+
paddingBottom: Spacing.seven,
|
|
526
|
+
},
|
|
527
|
+
header: {
|
|
528
|
+
alignItems: "center",
|
|
529
|
+
marginBottom: Spacing.five,
|
|
530
|
+
},
|
|
531
|
+
glowText: {
|
|
532
|
+
fontSize: 28,
|
|
533
|
+
fontWeight: "bold",
|
|
534
|
+
letterSpacing: -0.5,
|
|
535
|
+
textAlign: "center",
|
|
536
|
+
},
|
|
537
|
+
subtitle: {
|
|
538
|
+
textAlign: "center",
|
|
539
|
+
marginTop: Spacing.one,
|
|
540
|
+
opacity: 0.8,
|
|
541
|
+
},
|
|
542
|
+
sectionTitle: {
|
|
543
|
+
fontSize: 16,
|
|
544
|
+
fontWeight: "700",
|
|
545
|
+
marginTop: Spacing.four,
|
|
546
|
+
marginBottom: Spacing.two,
|
|
547
|
+
},
|
|
548
|
+
card: {
|
|
549
|
+
borderRadius: 16,
|
|
550
|
+
padding: Spacing.three,
|
|
551
|
+
shadowColor: "#000",
|
|
552
|
+
shadowOffset: { width: 0, height: 2 },
|
|
553
|
+
shadowOpacity: 0.05,
|
|
554
|
+
shadowRadius: 8,
|
|
555
|
+
elevation: 2,
|
|
556
|
+
},
|
|
557
|
+
settingRow: {
|
|
558
|
+
flexDirection: "row",
|
|
559
|
+
alignItems: "center",
|
|
560
|
+
justifyContent: "space-between",
|
|
561
|
+
},
|
|
562
|
+
settingTextContainer: {
|
|
563
|
+
flex: 1,
|
|
564
|
+
paddingRight: Spacing.three,
|
|
565
|
+
},
|
|
566
|
+
settingTitle: {
|
|
567
|
+
fontSize: 16,
|
|
568
|
+
fontWeight: "600",
|
|
569
|
+
},
|
|
570
|
+
settingDesc: {
|
|
571
|
+
fontSize: 13,
|
|
572
|
+
marginTop: 2,
|
|
573
|
+
lineHeight: 18,
|
|
574
|
+
},
|
|
575
|
+
grid: {
|
|
576
|
+
flexDirection: "row",
|
|
577
|
+
flexWrap: "wrap",
|
|
578
|
+
gap: Spacing.two,
|
|
579
|
+
},
|
|
580
|
+
btn: {
|
|
581
|
+
flexGrow: 1,
|
|
582
|
+
flexShrink: 0,
|
|
583
|
+
flexBasis: "45%",
|
|
584
|
+
height: 52,
|
|
585
|
+
borderRadius: 12,
|
|
586
|
+
justifyContent: "center",
|
|
587
|
+
alignItems: "center",
|
|
588
|
+
shadowColor: "#000",
|
|
589
|
+
shadowOffset: { width: 0, height: 1 },
|
|
590
|
+
shadowOpacity: 0.1,
|
|
591
|
+
shadowRadius: 2,
|
|
592
|
+
elevation: 1,
|
|
593
|
+
},
|
|
594
|
+
btnText: {
|
|
595
|
+
color: "#ffffff",
|
|
596
|
+
fontSize: 14,
|
|
597
|
+
fontWeight: "600",
|
|
598
|
+
},
|
|
599
|
+
successBtn: {
|
|
600
|
+
backgroundColor: "#10b981",
|
|
601
|
+
},
|
|
602
|
+
errorBtn: {
|
|
603
|
+
backgroundColor: "#ef4444",
|
|
604
|
+
},
|
|
605
|
+
warningBtn: {
|
|
606
|
+
backgroundColor: "#f59e0b",
|
|
607
|
+
},
|
|
608
|
+
infoBtn: {
|
|
609
|
+
backgroundColor: "#3b82f6",
|
|
610
|
+
},
|
|
611
|
+
actionBtn: {
|
|
612
|
+
backgroundColor: "#6366f1",
|
|
613
|
+
},
|
|
614
|
+
infiniteBtn: {
|
|
615
|
+
backgroundColor: "#a855f7",
|
|
616
|
+
},
|
|
617
|
+
multiBtn: {
|
|
618
|
+
backgroundColor: "#14b8a6",
|
|
619
|
+
},
|
|
620
|
+
textInput: {
|
|
621
|
+
height: 48,
|
|
622
|
+
borderRadius: 8,
|
|
623
|
+
borderWidth: 1,
|
|
624
|
+
paddingHorizontal: Spacing.three,
|
|
625
|
+
fontSize: 14,
|
|
626
|
+
},
|
|
627
|
+
segmentContainer: {
|
|
628
|
+
flexDirection: "row",
|
|
629
|
+
borderRadius: 8,
|
|
630
|
+
padding: 3,
|
|
631
|
+
},
|
|
632
|
+
segmentBtn: {
|
|
633
|
+
paddingHorizontal: 12,
|
|
634
|
+
paddingVertical: 6,
|
|
635
|
+
borderRadius: 6,
|
|
636
|
+
},
|
|
637
|
+
segmentBtnText: {
|
|
638
|
+
fontSize: 12,
|
|
639
|
+
fontWeight: "700",
|
|
640
|
+
},
|
|
641
|
+
});
|