@nativetail/ui 0.0.1

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.
@@ -0,0 +1,101 @@
1
+ import { BlurView } from "expo-blur";
2
+ import { cn, Pressable, Text, useTw, View } from "@nativetail/core";
3
+ import { useEffect } from "react";
4
+ import { create } from "zustand";
5
+ import { useSafeAreaInsets } from "react-native-safe-area-context";
6
+ import { AnimatePresence } from "moti";
7
+ import { Blur } from "../blur";
8
+ type ToastType = {
9
+ message: string;
10
+ content?: string;
11
+ id: string;
12
+ timeout?: number;
13
+ position?: "top" | "bottom";
14
+ containerClassName?: string;
15
+ };
16
+ type InsertToastType = Omit<ToastType, "id">;
17
+ type ToastStore = {
18
+ toasts: ToastType[];
19
+ addToast: (toast: ToastType) => void;
20
+ removeToast: (id: string) => void;
21
+ };
22
+ const useToastState = create<ToastStore>((set) => ({
23
+ toasts: [],
24
+ addToast: (toast) => set((state) => ({ toasts: [...state.toasts, toast] })),
25
+ removeToast: (id) =>
26
+ set((state) => ({
27
+ toasts: state.toasts.filter((toast) => toast.id !== id),
28
+ })),
29
+ }));
30
+ let timeouts = new Map<string, NodeJS.Timeout>();
31
+ export const showToast = (toast: InsertToastType) => {
32
+ const id = Math.random().toString(36).substring(7);
33
+ useToastState.getState().addToast({ ...toast, id });
34
+ return id;
35
+ };
36
+ export function Toaster() {
37
+ const toasts = useToastState((state) => state.toasts);
38
+ return (
39
+ <AnimatePresence exitBeforeEnter>
40
+ {toasts.map((toast, index) => (
41
+ <Toast key={toast.id} index={index} {...toast} />
42
+ ))}
43
+ </AnimatePresence>
44
+ );
45
+ }
46
+
47
+ const Toast = (
48
+ toast: ToastType & {
49
+ index: number;
50
+ }
51
+ ) => {
52
+ const tw = useTw();
53
+ useEffect(() => {
54
+ const id = setTimeout(() => {
55
+ useToastState.getState().removeToast(toast.id);
56
+ }, toast.timeout || 5000);
57
+ timeouts.set(toast.id, id);
58
+ return () => {
59
+ clearTimeout(timeouts.get(toast.id)!);
60
+ timeouts.delete(toast.id);
61
+ };
62
+ }, [toast.id]);
63
+ const safeInsets = useSafeAreaInsets();
64
+ return (
65
+ <View
66
+ className={cn(
67
+ "absolute w-full top-0 left-0 items-center justify-center z-50 ",
68
+ toast.position === "top"
69
+ ? `top-[${safeInsets.top + 10}px]`
70
+ : `bottom-[${safeInsets.bottom + 10}px]`,
71
+ toast.containerClassName
72
+ )}
73
+ animated
74
+ >
75
+ <Pressable
76
+ onPress={() => {
77
+ useToastState.getState().removeToast(toast.id);
78
+ }}
79
+ className="w-full items-center justify-center active:scale-95 scale-100 px-4"
80
+ >
81
+ <View
82
+ className={cn(
83
+ `bg-card/95 border border-muted/15 px-6 py-3 in:opacity-0 opacity-100 in:-translate-y-16 out:-translate-y-16 out:opacity-0 in:scale-0 scale-100 out:scale-0 rounded-full overflow-hidden max-w-sm w-full `,
84
+ `translate-y-0`
85
+ )}
86
+ animated
87
+ >
88
+ <Blur
89
+ style={tw`absolute top-0 left-0 rounded-xl flex-1 bg-card/50 rounded-full`}
90
+ />
91
+ <Text className="font-medium text-[16px] text-foreground">
92
+ {toast.message}
93
+ </Text>
94
+ {toast.content && (
95
+ <Text className="text-sm text-muted">{toast.content}</Text>
96
+ )}
97
+ </View>
98
+ </Pressable>
99
+ </View>
100
+ );
101
+ };
package/src/index.ts ADDED
@@ -0,0 +1 @@
1
+ export * from "./components";
@@ -0,0 +1,25 @@
1
+ module.exports = {
2
+ theme: {
3
+ screens: {
4
+ sm: "380px",
5
+ md: "420px",
6
+ lg: "680px",
7
+ // or maybe name them after devices for `tablet:flex-row`
8
+ tablet: "1024px",
9
+ },
10
+ extend: {
11
+ colors: {
12
+ primary: "#43D386",
13
+ secondary: '#EBB461',
14
+ background: '#F2F2F2',
15
+ card: '#fff',
16
+ foreground: '#000',
17
+ muted: '#383737',
18
+ success: '#4CAF50',
19
+ danger: '#F44336',
20
+ warning: '#FFC107',
21
+ info: '#00BCD4',
22
+ },
23
+ },
24
+ },
25
+ };
package/tsconfig.json ADDED
@@ -0,0 +1,18 @@
1
+ {
2
+ "compilerOptions": {
3
+ "strict": false,
4
+ "esModuleInterop": true,
5
+ "noUncheckedIndexedAccess": true,
6
+ "noImplicitOverride": true,
7
+ "skipLibCheck": true,
8
+ "rootDir": "./",
9
+ "outDir": "./dist/esm",
10
+ "lib": ["ES2019"],
11
+ "target": "ES2019",
12
+ "declaration": true,
13
+ "moduleResolution": "node",
14
+ "jsx": "react-jsx",
15
+ "stripInternal": true
16
+ },
17
+ "exclude": ["./dist", "**/*.spec.ts"]
18
+ }