@nativetail/ui 0.1.2 → 0.1.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nativetail/ui",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "",
5
5
  "main": "src/index.ts",
6
6
  "scripts": {},
@@ -27,24 +27,25 @@
27
27
  },
28
28
  "dependencies": {
29
29
  "@hookform/resolvers": "^3.6.0",
30
- "@nativetail/core": "^0.0.2",
30
+ "@nativetail/core": "^0.0.5",
31
31
  "@shopify/flash-list": "^1.7.0",
32
32
  "countries-list": "^3.1.0",
33
33
  "expo-blur": "^13.0.2",
34
34
  "expo-linear-gradient": "~13.0.2",
35
+ "lucide-react-native": "^0.427.0",
35
36
  "moti": "^0.29.0",
36
37
  "react": "18.2.0",
37
38
  "react-hook-form": "^7.51.0",
38
39
  "react-native": "0.74.3",
39
40
  "react-native-actions-sheet": "^0.9.6",
40
41
  "react-native-gesture-handler": "^2.17.1",
42
+ "react-native-mask-text": "^0.14.2",
41
43
  "react-native-reanimated": "~3.10.1",
42
44
  "react-native-safe-area-context": "4.10.1",
43
45
  "tailwind-merge": "^2.3.0",
44
46
  "zustand": "^4.5.2"
45
47
  },
46
48
  "devDependencies": {
47
- "metro-react-native-babel-preset": "^0.77.0",
48
49
  "tailwindcss": "^3.4.4"
49
50
  },
50
51
  "private": false
@@ -86,7 +86,7 @@ const ActionSheetItem = ({
86
86
  <Button
87
87
  variant="link"
88
88
  className={cn(
89
- "w-full items-center opacity-100 active:opacity-50 text-[16px] h-14 text-blue-500 rounded-none border-b ",
89
+ "w-full items-center opacity-100 active:opacity-50 text-sm h-14 text-blue-500 rounded-none border-b ",
90
90
  last ? "border-transparent" : "border-muted/15",
91
91
  className
92
92
  )}
@@ -1,4 +1,4 @@
1
- import { Text, View } from "@nativetail/core";
1
+ import { cn, Text, View } from "@nativetail/core";
2
2
  import { forwardRef } from "react";
3
3
  import { Button } from "../button";
4
4
  import { Dialog, DialogMethods } from "../dialog";
@@ -10,11 +10,26 @@ export type AlertDialogProps = {
10
10
  title?: string;
11
11
  description?: string;
12
12
  useBlur?: boolean;
13
+ confirmClassName?: string;
14
+ cancelClassName?: string;
15
+ confirmText?: string;
16
+ cancelText?: string;
13
17
  };
14
18
  export type AlertDialogRef = DialogMethods;
15
19
  export const AlertDialog = forwardRef<DialogMethods, AlertDialogProps>(
16
20
  function AlertDialog(
17
- { containerClassName, onConfirm, title, description, useBlur, onCancel },
21
+ {
22
+ containerClassName,
23
+ onConfirm,
24
+ confirmText = "Confirm",
25
+ cancelText = "Cancel",
26
+ cancelClassName,
27
+ confirmClassName,
28
+ title,
29
+ description,
30
+ useBlur,
31
+ onCancel,
32
+ },
18
33
  ref
19
34
  ) {
20
35
  return (
@@ -39,17 +54,23 @@ export const AlertDialog = forwardRef<DialogMethods, AlertDialogProps>(
39
54
  <View className="flex-row items-center border-t border-muted/15">
40
55
  <Button
41
56
  variant="link"
42
- className="flex-1 active:opacity-75 text-foreground rounded-none"
57
+ className={cn(
58
+ "flex-1 active:opacity-75 text-foreground rounded-none",
59
+ cancelClassName
60
+ )}
43
61
  onPress={onCancel}
44
62
  >
45
- Cancel
63
+ {cancelText}
46
64
  </Button>
47
65
  <Button
48
66
  variant="link"
49
- className="flex-1 border active:opacity-75 border-transparent rounded-none border-l-muted/15"
67
+ className={cn(
68
+ "flex-1 border active:opacity-75 border-transparent rounded-none border-l-muted/15",
69
+ cancelClassName
70
+ )}
50
71
  onPress={onConfirm}
51
72
  >
52
- Confirm
73
+ {confirmText}
53
74
  </Button>
54
75
  </View>
55
76
  </Dialog>
@@ -8,6 +8,7 @@ import {
8
8
  mergeClasses,
9
9
  Pressable,
10
10
  separateClasses,
11
+ useColor,
11
12
  useTw,
12
13
  VariantProps,
13
14
  } from "@nativetail/core";
@@ -15,11 +16,11 @@ import { MotiPressableProps } from "moti/interactions";
15
16
  import { useComponentTheme } from "../../utils/component-theme";
16
17
 
17
18
  const buttonVariants = cva(
18
- "flex-row gap-2 items-center justify-center rounded text-sm font-medium hover:opacity-90 active:opacity-80 opacity-100 select-none",
19
+ "flex-row gap-2 items-center justify-center rounded text-sm font-medium hover:opacity-90 active:opacity-50 duration-30 opacity-100 select-none",
19
20
  {
20
21
  variants: {
21
22
  variant: {
22
- default: "bg-primary text-foreground ",
23
+ default: "bg-primary text-primary-foreground ",
23
24
  destructive: "bg-red-500 text-foreground ",
24
25
  outline: "border border-muted/15 text-foreground bg-black/0 ",
25
26
  secondary: "bg-secondary text-foreground ",
@@ -84,9 +85,10 @@ export type ButtonProps = MotiPressableProps &
84
85
  const Button = (passedProps: ButtonProps) => {
85
86
  const componentTheme = useComponentTheme();
86
87
  const buttonProps = componentTheme?.Button || {};
87
- const {
88
+ let {
88
89
  text,
89
90
  children,
91
+
90
92
  isLoading,
91
93
  disabled,
92
94
  variant,
@@ -101,6 +103,7 @@ const Button = (passedProps: ButtonProps) => {
101
103
  ...buttonProps,
102
104
  ...passedProps,
103
105
  };
106
+ children = children || text;
104
107
  const tw = useTw();
105
108
  const className = cn(buttonProps.className, passedProps.className);
106
109
 
@@ -128,24 +131,26 @@ const Button = (passedProps: ButtonProps) => {
128
131
  const { textClasses } = separateClasses(variantClass);
129
132
 
130
133
  return (
131
- <Pressable
132
- disabled={disabled || loading}
133
- className={variantClass}
134
- {...props}
135
- >
136
- {leftElement}
137
- {loading && (
138
- <ActivityIndicator
139
- className={mergeClasses(
140
- "mr-2 h-5 w-5 text-foreground ",
141
- textClasses,
142
- loadingIndicatorClassName
143
- )}
144
- />
145
- )}
146
- {children}
147
- {rightElement}
148
- </Pressable>
134
+ <>
135
+ <Pressable
136
+ disabled={disabled || loading}
137
+ className={variantClass}
138
+ {...props}
139
+ >
140
+ {leftElement}
141
+ {loading && (
142
+ <ActivityIndicator
143
+ className={mergeClasses(
144
+ "mr-2 h-5 w-5 text-primary-foreground ",
145
+ textClasses,
146
+ loadingIndicatorClassName
147
+ )}
148
+ />
149
+ )}
150
+ {children}
151
+ {rightElement}
152
+ </Pressable>
153
+ </>
149
154
  );
150
155
  };
151
156
  export { Button };
@@ -0,0 +1,72 @@
1
+ import { cn, Text, useTw, View } from "@nativetail/core";
2
+ import { Pressable } from "react-native";
3
+ import { Button, ButtonProps } from "../button";
4
+
5
+ type CardProps = {
6
+ renderHeader?: () => React.ReactNode;
7
+ title?: string;
8
+ subtitle?: string;
9
+ description?: string;
10
+ titleClassname?: string;
11
+ subtitleClassName?: string;
12
+ descriptionClassName?: string;
13
+ containerClassName?: string;
14
+ contentClassName?: string;
15
+ buttonProps?: ButtonProps;
16
+ onPress?: () => void;
17
+ renderFooter?: () => React.ReactNode;
18
+ renderContent?: () => React.ReactNode;
19
+ };
20
+ export function Card({
21
+ description,
22
+ descriptionClassName,
23
+ renderHeader,
24
+ subtitle,
25
+ subtitleClassName,
26
+ title,
27
+ titleClassname,
28
+ contentClassName,
29
+ buttonProps,
30
+ onPress,
31
+ renderFooter,
32
+ containerClassName,
33
+ ...props
34
+ }: CardProps) {
35
+ const tw = useTw();
36
+ const renderContent = () => {
37
+ if (props.renderContent) {
38
+ return props.renderContent();
39
+ }
40
+ return (
41
+ <View className={cn("p-1 gap-1", contentClassName)}>
42
+ <Text className={cn("text-lg font-medium", titleClassname)}>
43
+ {title}
44
+ </Text>
45
+ <Text className={cn("text-sm ", subtitleClassName)}>{subtitle}</Text>
46
+ <Text
47
+ className={cn(
48
+ "text-xs text-muted tracking-widest",
49
+ descriptionClassName
50
+ )}
51
+ >
52
+ {description}
53
+ </Text>
54
+ {buttonProps && <Button {...buttonProps} />}
55
+ </View>
56
+ );
57
+ };
58
+ return (
59
+ <Pressable
60
+ style={tw.style(
61
+ "bg-card p-3 rounded-xl border border-muted/15",
62
+ containerClassName
63
+ )}
64
+ onPress={onPress}
65
+ disabled={!onPress}
66
+ >
67
+ {renderHeader && renderHeader()}
68
+ {renderContent()}
69
+ {renderFooter && renderFooter()}
70
+ </Pressable>
71
+ );
72
+ }
@@ -0,0 +1,3 @@
1
+ export * from "./card";
2
+ export * from "./stat-card";
3
+ export * from "./info-card";
@@ -0,0 +1,113 @@
1
+ import { cn, Pressable, Text, useColor, View } from "@nativetail/core";
2
+ import { EllipsisVertical } from "lucide-react-native";
3
+ import { useRef } from "react";
4
+ import {
5
+ ActionSheet,
6
+ ActionSheetProps,
7
+ ActionSheetRef,
8
+ } from "../actions-sheet";
9
+
10
+ type InfoCardProps = {
11
+ containerClassname?: string;
12
+ renderIcon?: () => React.ReactNode;
13
+ renderContent?: () => React.ReactNode;
14
+ contentClassName?: string;
15
+ title?: string;
16
+ subtitle?: string;
17
+ titleClassname?: string;
18
+ subtitleClassName?: string;
19
+ description?: string;
20
+ descriptionClassName?: string;
21
+ actions?: ActionSheetProps["options"];
22
+ renderRight?: () => React.ReactNode;
23
+ onPress?: () => void;
24
+ dotsClassname?: string;
25
+ textContentClassname?: string;
26
+ };
27
+ export function InfoCard({
28
+ containerClassname,
29
+ renderIcon,
30
+ subtitle,
31
+ title,
32
+ titleClassname,
33
+ subtitleClassName,
34
+ description,
35
+ descriptionClassName,
36
+ actions,
37
+ onPress,
38
+ dotsClassname,
39
+ contentClassName,
40
+ textContentClassname,
41
+ ...props
42
+ }: InfoCardProps) {
43
+ const actionSheetRef = useRef<ActionSheetRef>(null);
44
+ const renderRight = () => {
45
+ if (props.renderRight) {
46
+ return props.renderRight();
47
+ }
48
+ if (actions)
49
+ return (
50
+ <View className="flex-row gap-1">
51
+ <>
52
+ <Pressable
53
+ className={cn(
54
+ "p-1.5 w-7 h-7 items-center justify-center border rounded-full border-muted/15 active:scale-95 scale-100",
55
+ dotsClassname
56
+ )}
57
+ onPress={() => {
58
+ actionSheetRef.current?.show();
59
+ }}
60
+ >
61
+ <EllipsisVertical color={useColor("foreground")} />
62
+ </Pressable>
63
+ <ActionSheet
64
+ onCancel={() => {
65
+ actionSheetRef.current?.hide();
66
+ }}
67
+ options={actions.map((action) => ({
68
+ ...action,
69
+ onPress: () => {
70
+ actionSheetRef.current?.hide();
71
+ action.onPress();
72
+ },
73
+ }))}
74
+ ref={actionSheetRef}
75
+ />
76
+ </>
77
+ </View>
78
+ );
79
+ };
80
+ const renderContent = () => {
81
+ if (props.renderContent) {
82
+ return props.renderContent();
83
+ }
84
+ return (
85
+ <View className={textContentClassname}>
86
+ <Text className={cn("text-sm font-medium", titleClassname)}>
87
+ {title}
88
+ </Text>
89
+ <Text className={cn("text-[13px] text-muted", subtitleClassName)}>
90
+ {subtitle}
91
+ </Text>
92
+ <Text className={cn("text-xs text-muted/65", descriptionClassName)}>
93
+ {description}
94
+ </Text>
95
+ </View>
96
+ );
97
+ };
98
+ return (
99
+ <Pressable
100
+ className={cn(
101
+ "flex-row items-center w-full justify-between ",
102
+ containerClassname
103
+ )}
104
+ disabled={!onPress}
105
+ >
106
+ <View className={cn("flex-row gap-2 items-center p-2", contentClassName)}>
107
+ {renderIcon && renderIcon()}
108
+ {renderContent()}
109
+ </View>
110
+ {renderRight()}
111
+ </Pressable>
112
+ );
113
+ }
@@ -0,0 +1,46 @@
1
+ import { cn, View } from "@nativetail/core";
2
+
3
+ type StatCardProps = {
4
+ renderIcon?: () => React.ReactNode;
5
+ renderTitle?: () => React.ReactNode;
6
+ renderValue?: () => React.ReactNode;
7
+ title?: string;
8
+ value?: string;
9
+ Icon?: React.ReactNode;
10
+ containerClassName?: string;
11
+ };
12
+ export function StatCard(props: StatCardProps) {
13
+ const renderIcon = () => {
14
+ if (props.Icon) return <View className="mb-2">{props.Icon}</View>;
15
+ if (!props.renderIcon) return null;
16
+ return props.renderIcon();
17
+ };
18
+ const renderTitle = () => {
19
+ if (!props.renderTitle)
20
+ return <View className="text-xs text-muted/80">{props.title}</View>;
21
+ return props.renderTitle();
22
+ };
23
+ const renderValue = () => {
24
+ if (!props.renderValue)
25
+ return (
26
+ <View className="text-xl font-medium text-foreground">
27
+ {props.value}
28
+ </View>
29
+ );
30
+ return props.renderValue();
31
+ };
32
+ return (
33
+ <View
34
+ className={cn(
35
+ "p-3 rounded-xl gap-0.5 bg-card border justify-between border-muted/15",
36
+ props.containerClassName
37
+ )}
38
+ >
39
+ {renderIcon()}
40
+ <View className="gap-0.5">
41
+ {renderValue()}
42
+ {renderTitle()}
43
+ </View>
44
+ </View>
45
+ );
46
+ }
@@ -0,0 +1,43 @@
1
+ import { cn, Pressable, useColor } from "@nativetail/core";
2
+ import { CheckIcon } from "lucide-react-native";
3
+
4
+ type CheckProps = {
5
+ checked: boolean;
6
+ onChange: (checked: boolean) => void;
7
+ className?: string;
8
+ activeClassName?: string;
9
+ inactiveCheckColor?: string;
10
+ activeCheckColor?: string;
11
+ };
12
+ export function Check({
13
+ checked,
14
+ onChange,
15
+ className,
16
+ activeClassName,
17
+ inactiveCheckColor,
18
+ activeCheckColor,
19
+ ...props
20
+ }: CheckProps) {
21
+ return (
22
+ <Pressable
23
+ className={cn(
24
+ "border w-6 h-6 p-1 items-center justify-center rounded-lg border-muted/15 bg-card",
25
+ className,
26
+ checked ? "bg-primary " + activeClassName : ""
27
+ )}
28
+ aria-checked={checked}
29
+ accessibilityRole="switch"
30
+ aria-label="Check"
31
+ {...props}
32
+ onPress={() => onChange(!checked)}
33
+ >
34
+ <CheckIcon
35
+ color={useColor(
36
+ checked
37
+ ? activeCheckColor || "card"
38
+ : inactiveCheckColor || "primary/35"
39
+ )}
40
+ />
41
+ </Pressable>
42
+ );
43
+ }
@@ -0,0 +1,23 @@
1
+ type CollapsibleProps = {
2
+ onChange: (checked: boolean) => void;
3
+ className?: string;
4
+ };
5
+ function CollapsibleRoot({ onChange, className, ...props }: CollapsibleProps) {
6
+ return <></>;
7
+ }
8
+ type CollapsibleTriggerProps = {};
9
+
10
+ const CollapsibleTrigger = ({ ...props }: CollapsibleTriggerProps) => {
11
+ return <></>;
12
+ };
13
+ type CollapsibleContentProps = {};
14
+
15
+ const CollapsibleContent = ({ ...props }: CollapsibleContentProps) => {
16
+ return <></>;
17
+ };
18
+
19
+ export const Collapsible = {
20
+ Trigger: CollapsibleTrigger,
21
+ Content: CollapsibleContent,
22
+ Root: CollapsibleRoot,
23
+ };
@@ -1,6 +1,6 @@
1
- import { TextInput, View, cn, useTw } from "@nativetail/core";
1
+ import { TextInput, View, cn, useColor, useTw } from "@nativetail/core";
2
+ import { Minus, Plus } from "lucide-react-native";
2
3
  import { useCallback, useRef } from "react";
3
- import { Iconify } from "react-native-iconify";
4
4
  import { Button } from "../button";
5
5
  export type CounterProps = {
6
6
  value: number;
@@ -48,11 +48,7 @@ export function Counter({
48
48
  )}
49
49
  >
50
50
  <CounterButton disabled={!!(min && value <= min)} onPress={decrement}>
51
- <Iconify
52
- icon="ic:round-minus"
53
- size={15}
54
- color={tw.color("foreground")}
55
- />
51
+ <Minus size={15} color={useColor("foreground")} />
56
52
  </CounterButton>
57
53
  <View className="flex-1 h-full">
58
54
  <TextInput
@@ -62,11 +58,7 @@ export function Counter({
62
58
  />
63
59
  </View>
64
60
  <CounterButton disabled={!!(max && value >= max)} onPress={increment}>
65
- <Iconify
66
- icon="ic:round-plus"
67
- size={15}
68
- color={tw.color("foreground")}
69
- />
61
+ <Plus size={15} color={useColor("foreground")} />
70
62
  </CounterButton>
71
63
  </View>
72
64
  );
@@ -14,3 +14,7 @@ export * from "./progress";
14
14
  export * from "./counter";
15
15
  export * from "./tabs";
16
16
  export * from "./form-builder";
17
+ export * from "./check";
18
+ export * from "./card";
19
+ export * from "./indicator";
20
+ export * from "./loader-dialog";
@@ -0,0 +1,15 @@
1
+ import { cn, View } from "@nativetail/core";
2
+
3
+ type IndicatorProps = {
4
+ className?: string;
5
+ size?: number;
6
+ color?: string;
7
+ Icon?: React.ReactNode;
8
+ };
9
+ export function Indicator({ className, size, color, Icon }: IndicatorProps) {
10
+ return (
11
+ <View className={cn("w-4 h-4 rounded-full bg-primary", className)}>
12
+ {Icon}
13
+ </View>
14
+ );
15
+ }
@@ -8,6 +8,7 @@ import { Input, InputProps } from "./input";
8
8
 
9
9
  import { countries, ICountry } from "countries-list";
10
10
  import { FloatingInput } from "./floating-input";
11
+ import { ChevronDown } from "lucide-react-native";
11
12
  type CountryType = ICountry & {
12
13
  code: string;
13
14
  };
@@ -97,7 +98,7 @@ const SelectCountry = ({
97
98
  <Text>
98
99
  <Text className="mr-1">{flag}</Text>+{selectedCountry.phone?.[0]}
99
100
  </Text>
100
- <Iconify icon="mingcute:down-line" size={24} color="gray" />
101
+ <ChevronDown size={24} color="gray" />
101
102
  </Pressable>
102
103
  <CountryBottomSheet
103
104
  selectedCountry={selectedCountry}
@@ -1,5 +1,5 @@
1
- import { Pressable, useTw } from "@nativetail/core";
2
- import { Iconify } from "react-native-iconify";
1
+ import { Pressable, useColor } from "@nativetail/core";
2
+ import { Eye, EyeOff } from "lucide-react-native";
3
3
 
4
4
  export default function ShowPassword({
5
5
  showPassword,
@@ -8,24 +8,15 @@ export default function ShowPassword({
8
8
  showPassword: boolean;
9
9
  setShowPassword: (showPassword: boolean) => void;
10
10
  }) {
11
- const tw = useTw();
12
11
  return (
13
12
  <Pressable
14
13
  onPress={() => setShowPassword(!showPassword)}
15
14
  className="absolute right-2 bottom-2"
16
15
  >
17
16
  {showPassword ? (
18
- <Iconify
19
- icon="solar:eye-linear"
20
- size={20}
21
- color={tw.color("foreground")}
22
- />
17
+ <Eye size={20} color={useColor("foreground")} />
23
18
  ) : (
24
- <Iconify
25
- icon="solar:eye-closed-linear"
26
- size={20}
27
- color={tw.color("foreground")}
28
- />
19
+ <EyeOff size={20} color={useColor("foreground")} />
29
20
  )}
30
21
  </Pressable>
31
22
  );
@@ -0,0 +1,35 @@
1
+ import { ActivityIndicator, cn, useColor } from "@nativetail/core";
2
+ import { forwardRef } from "react";
3
+ import { Dialog, DialogMethods, DialogProps } from "../dialog";
4
+
5
+ export type LoaderProps = Omit<DialogProps, "children"> & {
6
+ activityIndicatorProps?: React.ComponentProps<typeof ActivityIndicator>;
7
+ children?: React.ReactNode;
8
+ };
9
+
10
+ export const Loader = forwardRef<DialogMethods, LoaderProps>(function Loader(
11
+ { ...props },
12
+ ref
13
+ ) {
14
+ return (
15
+ <Dialog
16
+ ref={ref}
17
+ closable={false}
18
+ {...props}
19
+ contentClassName={cn(
20
+ "items-center justify-center p-4 w-24 h-24",
21
+ props?.contentClassName
22
+ )}
23
+ >
24
+ {props?.children || (
25
+ <ActivityIndicator
26
+ size="large"
27
+ color={useColor("primary")}
28
+ {...props?.activityIndicatorProps}
29
+ />
30
+ )}
31
+ </Dialog>
32
+ );
33
+ });
34
+
35
+ export type Loader = DialogMethods;
@@ -3,6 +3,7 @@ import {
3
3
  Pressable,
4
4
  PressableProps,
5
5
  Text,
6
+ useColor,
6
7
  useTw,
7
8
  View,
8
9
  } from "@nativetail/core";
@@ -10,6 +11,7 @@ import { Dropdown } from "../dropdown";
10
11
  import { memo, useCallback, useMemo } from "react";
11
12
  import { Iconify } from "react-native-iconify";
12
13
  import { Control, Controller, Path } from "react-hook-form";
14
+ import { CheckCheck, CheckIcon, ChevronDown } from "lucide-react-native";
13
15
 
14
16
  export type MultiSelectProps<T = Record<string, any>> = PressableProps & {
15
17
  containerClassName?: string;
@@ -150,11 +152,7 @@ const SelectTrigger = memo(
150
152
  {selectedOptions.length == 0 && placeholder && (
151
153
  <Text className="text-muted">{placeholder}</Text>
152
154
  )}
153
- <Iconify
154
- icon="solar:alt-arrow-down-outline"
155
- size={20}
156
- color={tw.color("foreground")}
157
- />
155
+ <ChevronDown size={20} color={useColor("foreground")} />
158
156
  </Dropdown.Trigger>
159
157
 
160
158
  {error && <Text className="text-sm text-danger">{error}</Text>}
@@ -195,13 +193,7 @@ const SelectItem = memo(
195
193
  <Text className="text-sm text-foreground">{label}</Text>
196
194
  {icon}
197
195
  </View>
198
- {isActive && (
199
- <Iconify
200
- icon="lucide:check"
201
- size={16}
202
- color={tw.color("foreground")}
203
- />
204
- )}
196
+ {isActive && <CheckIcon size={16} color={useColor("foreground")} />}
205
197
  </Dropdown.Item>
206
198
  );
207
199
  }
@@ -1,8 +1,15 @@
1
- import { cn, PressableProps, Text, useTw, View } from "@nativetail/core";
2
- import { Dropdown } from "../dropdown";
1
+ import {
2
+ cn,
3
+ PressableProps,
4
+ Text,
5
+ useColor,
6
+ useTw,
7
+ View,
8
+ } from "@nativetail/core";
9
+ import { CheckCheck, CheckIcon, ChevronDown } from "lucide-react-native";
3
10
  import { memo, useCallback, useMemo } from "react";
4
- import { Iconify } from "react-native-iconify";
5
11
  import { Control, Controller, Path } from "react-hook-form";
12
+ import { Dropdown } from "../dropdown";
6
13
 
7
14
  export type SelectProps<T = Record<string, any>> = PressableProps & {
8
15
  containerClassName?: string;
@@ -124,11 +131,7 @@ const SelectTrigger = memo(
124
131
  {!selectedOption && placeholder && (
125
132
  <Text className="text-muted">{placeholder}</Text>
126
133
  )}
127
- <Iconify
128
- icon="solar:alt-arrow-down-outline"
129
- size={20}
130
- color={tw.color("foreground")}
131
- />
134
+ <ChevronDown size={20} color={useColor("foreground")} />
132
135
  </Dropdown.Trigger>
133
136
  {error && <Text className="text-sm text-danger">{error}</Text>}
134
137
  </>
@@ -167,13 +170,7 @@ const SelectItem = memo(
167
170
  <Text className="text-sm text-foreground">{label}</Text>
168
171
  {icon}
169
172
  </View>
170
- {isActive && (
171
- <Iconify
172
- icon="lucide:check"
173
- size={16}
174
- color={tw.color("foreground")}
175
- />
176
- )}
173
+ {isActive && <CheckIcon size={16} color={useColor("foreground")} />}
177
174
  </Dropdown.Item>
178
175
  );
179
176
  }
@@ -8,7 +8,7 @@ import {
8
8
  } from "@nativetail/core";
9
9
 
10
10
  const switchVariants = cva(
11
- "rounded-full bg-card justify-center border p-0.5 items-start",
11
+ "rounded-full bg-card justify-center border border-muted/15 p-0.5 items-start",
12
12
  {
13
13
  variants: {
14
14
  size: {
@@ -51,7 +51,7 @@ export function Switch({
51
51
  <Pressable
52
52
  className={cn(
53
53
  className,
54
- checked ? "bg-primary/35 " + containerActiveClass : ""
54
+ checked ? "bg-primary " + containerActiveClass : ""
55
55
  )}
56
56
  aria-checked={checked}
57
57
  accessibilityRole="switch"
@@ -63,6 +63,7 @@ export function Switch({
63
63
  className={cn(
64
64
  `rounded-full bg-primary aspect-square h-full`,
65
65
  indicatorClassName,
66
+ checked ? "bg-card" : "",
66
67
  x
67
68
  )}
68
69
  animated
@@ -1,8 +1,13 @@
1
- import { cn, Pressable, Text, useTw, View } from "@nativetail/core";
1
+ import { cn, Pressable, Text, useColor, useTw, View } from "@nativetail/core";
2
+ import {
3
+ CheckCircle2,
4
+ Info,
5
+ OctagonAlert,
6
+ OctagonX,
7
+ } from "lucide-react-native";
2
8
  import { AnimatePresence } from "moti";
3
9
  import { useCallback, useEffect, useState } from "react";
4
10
  import { Modal } from "react-native";
5
- import { Iconify } from "react-native-iconify";
6
11
  import { useSafeAreaInsets } from "react-native-safe-area-context";
7
12
  import { create } from "zustand";
8
13
  type ToastType = {
@@ -50,7 +55,6 @@ const useToastState = create<ToastStore>((set) => ({
50
55
  let timeouts = new Map<string, NodeJS.Timeout>();
51
56
  export const showToast = (toast: InsertToastType) => {
52
57
  const id = Math.random().toString(36).substring(7);
53
- console.log(id);
54
58
  useToastState.getState().addToast({ ...toast, id });
55
59
  return id;
56
60
  };
@@ -108,8 +112,8 @@ const Toast = (
108
112
  className={cn(
109
113
  "absolute w-full h-full bg-black/15 left-0 justify-start z-50 gap-2",
110
114
  toast.position.includes("top")
111
- ? `pt-[${safeInsets.top + 10}px]`
112
- : `pb-[${safeInsets.bottom + 10}px]`
115
+ ? `pt-[${safeInsets.top + 10}px] top-0`
116
+ : `pb-[${safeInsets.bottom + 10}px] bottom-0 justify-end`
113
117
  )}
114
118
  onPress={close}
115
119
  >
@@ -140,30 +144,10 @@ const BaseToast = (
140
144
  }, [toast.id]);
141
145
 
142
146
  const Icons = {
143
- success: (
144
- <Iconify
145
- icon="lets-icons:check-fill"
146
- size={20}
147
- color={tw.color("success")}
148
- />
149
- ),
150
- danger: (
151
- <Iconify icon="uis:times-circle" size={20} color={tw.color("danger")} />
152
- ),
153
- info: (
154
- <Iconify
155
- icon="fluent:info-16-filled"
156
- size={20}
157
- color={tw.color("info")}
158
- />
159
- ),
160
- warning: (
161
- <Iconify
162
- icon="fluent:warning-16-filled"
163
- size={20}
164
- color={tw.color("warning")}
165
- />
166
- ),
147
+ success: <CheckCircle2 size={20} color={useColor("success")} />,
148
+ danger: <OctagonX size={20} color={useColor("danger")} />,
149
+ info: <Info size={20} color={useColor("info")} />,
150
+ warning: <OctagonAlert size={20} color={useColor("warning")} />,
167
151
  };
168
152
 
169
153
  const Icon = toast.icon || Icons[toast.type];
@@ -1,3 +1,4 @@
1
+
1
2
  module.exports = {
2
3
  theme: {
3
4
  screens: {
@@ -9,7 +10,10 @@ module.exports = {
9
10
  },
10
11
  extend: {
11
12
  colors: {
12
- primary: "#43D386",
13
+ primary: {
14
+ DEFAULT: "#43D386",
15
+ foreground: "#000",
16
+ },
13
17
  secondary: '#EBB461',
14
18
  background: '#F2F2F2',
15
19
  card: '#fff',
@@ -26,4 +30,4 @@ module.exports = {
26
30
  }
27
31
  },
28
32
  },
29
- };
33
+ };