@munchi_oy/native-ui 0.1.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 (83) hide show
  1. package/dist/index.d.mts +568 -0
  2. package/dist/index.d.ts +568 -0
  3. package/dist/index.js +1 -0
  4. package/dist/index.mjs +1 -0
  5. package/global.css +53 -0
  6. package/nativewind-env.d.ts +2 -0
  7. package/package.json +88 -0
  8. package/src/MAlert.tsx +38 -0
  9. package/src/MAnimation.tsx +55 -0
  10. package/src/MAvatar.tsx +111 -0
  11. package/src/MBadge.tsx +72 -0
  12. package/src/MButton.tsx +90 -0
  13. package/src/MCard.tsx +15 -0
  14. package/src/MChevron.tsx +47 -0
  15. package/src/MConfirmation.tsx +68 -0
  16. package/src/MCountDown.tsx +120 -0
  17. package/src/MDateTimePicker.tsx +124 -0
  18. package/src/MDivider.tsx +69 -0
  19. package/src/MDrawerRightPanel.tsx +187 -0
  20. package/src/MDropdown.tsx +277 -0
  21. package/src/MInput.tsx +162 -0
  22. package/src/MLabel.tsx +3 -0
  23. package/src/MLucideIcon.tsx +21 -0
  24. package/src/MModal.tsx +287 -0
  25. package/src/MNativeAlert.tsx +33 -0
  26. package/src/MNumpad.tsx +520 -0
  27. package/src/MPicker.tsx +150 -0
  28. package/src/MPinPadKeys.tsx +104 -0
  29. package/src/MPortal.tsx +4 -0
  30. package/src/MProgressBar.tsx +74 -0
  31. package/src/MRadioGroup.tsx +4 -0
  32. package/src/MRequiredLabel.tsx +21 -0
  33. package/src/MResponsiveContainer.tsx +74 -0
  34. package/src/MSearch.tsx +138 -0
  35. package/src/MSelector.tsx +48 -0
  36. package/src/MSkeleton.tsx +3 -0
  37. package/src/MSwitch.tsx +13 -0
  38. package/src/MTable.tsx +17 -0
  39. package/src/MTabs.tsx +198 -0
  40. package/src/MText.tsx +51 -0
  41. package/src/MTimerUp.tsx +88 -0
  42. package/src/MToggle.tsx +51 -0
  43. package/src/constants.ts +19 -0
  44. package/src/hooks/useColorScheme.tsx +12 -0
  45. package/src/hooks/useIconColors.ts +19 -0
  46. package/src/index.ts +124 -0
  47. package/src/primitives/accordion.tsx +143 -0
  48. package/src/primitives/alert-dialog.tsx +181 -0
  49. package/src/primitives/alert.tsx +94 -0
  50. package/src/primitives/aspect-ratio.tsx +5 -0
  51. package/src/primitives/avatar.tsx +47 -0
  52. package/src/primitives/badge.tsx +57 -0
  53. package/src/primitives/button.tsx +92 -0
  54. package/src/primitives/card.tsx +86 -0
  55. package/src/primitives/checkbox.tsx +35 -0
  56. package/src/primitives/collapsible.tsx +9 -0
  57. package/src/primitives/context-menu.tsx +255 -0
  58. package/src/primitives/dialog.tsx +166 -0
  59. package/src/primitives/dropdown-menu.tsx +264 -0
  60. package/src/primitives/hover-card.tsx +45 -0
  61. package/src/primitives/input.tsx +25 -0
  62. package/src/primitives/label.tsx +33 -0
  63. package/src/primitives/menubar.tsx +266 -0
  64. package/src/primitives/navigation-menu.tsx +192 -0
  65. package/src/primitives/popover.tsx +46 -0
  66. package/src/primitives/progress.tsx +82 -0
  67. package/src/primitives/radio-group.tsx +42 -0
  68. package/src/primitives/select.tsx +192 -0
  69. package/src/primitives/separator.tsx +28 -0
  70. package/src/primitives/skeleton.tsx +39 -0
  71. package/src/primitives/switch.tsx +102 -0
  72. package/src/primitives/table.tsx +107 -0
  73. package/src/primitives/tabs.tsx +66 -0
  74. package/src/primitives/text.tsx +28 -0
  75. package/src/primitives/textarea.tsx +39 -0
  76. package/src/primitives/toggle-group.tsx +89 -0
  77. package/src/primitives/toggle.tsx +91 -0
  78. package/src/primitives/tooltip.tsx +40 -0
  79. package/src/primitives/typography.tsx +214 -0
  80. package/src/theme.ts +43 -0
  81. package/src/tokens.ts +7 -0
  82. package/src/utils.ts +14 -0
  83. package/tailwind.config.ts +112 -0
package/src/MText.tsx ADDED
@@ -0,0 +1,51 @@
1
+ import { type VariantProps, cva } from "class-variance-authority";
2
+ import React from "react";
3
+ import { Text, type TextProps } from "react-native";
4
+ import { cn } from "./utils";
5
+
6
+ const mTextVariants = cva("text-base text-foreground", {
7
+ variants: {
8
+ variant: {
9
+ default: "font-munchi"
10
+ },
11
+ size: {
12
+ xs: "text-xs",
13
+ sm: "text-sm",
14
+ base: "text-base",
15
+ lg: "text-lg",
16
+ xl: "text-xl",
17
+ "2xl": "text-2xl",
18
+ "3xl": "text-3xl",
19
+ "4xl": "text-4xl"
20
+ }
21
+ },
22
+ defaultVariants: {
23
+ variant: "default",
24
+ size: "base"
25
+ }
26
+ });
27
+
28
+ export interface MTextProps
29
+ extends Omit<TextProps, "allowFontScaling">,
30
+ VariantProps<typeof mTextVariants> {
31
+ children: React.ReactNode;
32
+ }
33
+
34
+ const MText = React.forwardRef<Text, MTextProps>(
35
+ ({ className, variant, size, children, ...props }, ref) => {
36
+ return (
37
+ <Text
38
+ ref={ref}
39
+ className={cn(mTextVariants({ variant, size }), className)}
40
+ {...props}
41
+ allowFontScaling={false}
42
+ >
43
+ {children}
44
+ </Text>
45
+ );
46
+ }
47
+ );
48
+
49
+ MText.displayName = "MText";
50
+
51
+ export { MText };
@@ -0,0 +1,88 @@
1
+ import dayjs from "dayjs";
2
+ import type React from "react";
3
+ import { useEffect, useMemo, useState } from "react";
4
+ import { Text, type TextProps, View, type ViewProps } from "react-native";
5
+ import { cn } from "./utils";
6
+
7
+ export interface MTimerUpProps extends Pick<ViewProps, "className"> {
8
+ date: string | number | Date;
9
+ textClassName?: TextProps["className"];
10
+ }
11
+
12
+ const formatElapsedTime = (
13
+ now: dayjs.Dayjs,
14
+ targetDate: dayjs.Dayjs
15
+ ): string => {
16
+ const totalMinutes = now.diff(targetDate, "minute");
17
+
18
+ if (totalMinutes < 1) {
19
+ return "0m";
20
+ }
21
+
22
+ const days = Math.floor(totalMinutes / 1440);
23
+ const remainingMinutes = totalMinutes % 1440;
24
+ const hours = Math.floor(remainingMinutes / 60);
25
+ const minutes = remainingMinutes % 60;
26
+
27
+ let result = "";
28
+ if (days > 0) result += `${days}d `;
29
+ if (hours > 0 || days > 0) result += `${hours}h `;
30
+ result += `${minutes}m`;
31
+
32
+ return result.trim();
33
+ };
34
+
35
+ export const MTimerUp: React.FC<MTimerUpProps> = ({
36
+ date,
37
+ className = "",
38
+ textClassName = ""
39
+ }) => {
40
+ const targetDate = useMemo(() => dayjs(date), [date]);
41
+ const [now, setNow] = useState(() => dayjs());
42
+
43
+ useEffect(() => {
44
+ const nextTick = () => {
45
+ const currentTime = dayjs();
46
+ const nextMinute = currentTime.add(1, "minute").startOf("minute");
47
+ const delay = nextMinute.diff(currentTime);
48
+
49
+ return setTimeout(
50
+ () => {
51
+ setNow(dayjs());
52
+ },
53
+ delay > 0 ? delay : 60000
54
+ );
55
+ };
56
+
57
+ const timerId = nextTick();
58
+ return () => clearTimeout(timerId);
59
+ }, [now]);
60
+
61
+ const formattedDuration = useMemo(
62
+ () => formatElapsedTime(now, targetDate),
63
+ [now, targetDate]
64
+ );
65
+
66
+ return (
67
+ <View
68
+ className={cn(
69
+ "rounded-md flex items-center justify-center bg-muted border border-border/60",
70
+ "dark:border-white/20 dark:bg-white/12",
71
+ className
72
+ )}
73
+ >
74
+ <Text
75
+ className={cn(
76
+ "font-munchi-semibold text-foreground dark:text-neutral-200",
77
+ textClassName
78
+ )}
79
+ >
80
+ {formattedDuration}
81
+ </Text>
82
+ </View>
83
+ );
84
+ };
85
+
86
+ MTimerUp.displayName = "MTimerUp";
87
+
88
+ export default MTimerUp;
@@ -0,0 +1,51 @@
1
+ import { Pressable, Text, View } from "react-native";
2
+ import { cn } from "./utils";
3
+
4
+ export interface MToggleOption<T> {
5
+ key: T;
6
+ label: string;
7
+ disabled?: boolean;
8
+ }
9
+
10
+ export interface MToggleProps<T> {
11
+ options: MToggleOption<T>[];
12
+ selectedKey: T;
13
+ onSelect: (key: T) => void;
14
+ }
15
+
16
+ export const MToggle = <T,>({
17
+ options,
18
+ selectedKey,
19
+ onSelect
20
+ }: MToggleProps<T>) => {
21
+ return (
22
+ <View className="flex flex-row gap-4 w-full items-center justify-between">
23
+ {options.map((option) => (
24
+ <Pressable
25
+ key={String(option.key)}
26
+ className={cn(
27
+ "flex-1 rounded-lg py-4",
28
+ selectedKey === option.key ? "bg-primary" : "bg-muted"
29
+ )}
30
+ onPress={() => onSelect(option.key)}
31
+ disabled={option.disabled}
32
+ >
33
+ <Text
34
+ className={cn(
35
+ "text-center font-munchi",
36
+ selectedKey === option.key
37
+ ? "text-primary-foreground"
38
+ : "text-muted-foreground"
39
+ )}
40
+ >
41
+ {option.label}
42
+ </Text>
43
+ </Pressable>
44
+ ))}
45
+ </View>
46
+ );
47
+ };
48
+
49
+ MToggle.displayName = "MToggle";
50
+
51
+ export default MToggle;
@@ -0,0 +1,19 @@
1
+ import { darkVars, lightVars } from "./theme";
2
+
3
+ type CssVars = Record<string, string>;
4
+
5
+ const hsl = (vars: CssVars, key: string) => `hsl(${vars[key]})`;
6
+
7
+ const makeNavTheme = (vars: CssVars) => ({
8
+ background: hsl(vars, "--background"),
9
+ border: hsl(vars, "--border"),
10
+ card: hsl(vars, "--card"),
11
+ notification: hsl(vars, "--destructive"),
12
+ primary: hsl(vars, "--primary"),
13
+ text: hsl(vars, "--foreground")
14
+ });
15
+
16
+ export const NAV_THEME = {
17
+ light: makeNavTheme(lightVars),
18
+ dark: makeNavTheme(darkVars)
19
+ } as const;
@@ -0,0 +1,12 @@
1
+ import { useColorScheme as useNativewindColorScheme } from "nativewind";
2
+
3
+ export function useColorScheme() {
4
+ const { colorScheme, setColorScheme, toggleColorScheme } =
5
+ useNativewindColorScheme();
6
+ return {
7
+ colorScheme: colorScheme ?? "light",
8
+ isDarkColorScheme: colorScheme === "dark",
9
+ setColorScheme,
10
+ toggleColorScheme
11
+ };
12
+ }
@@ -0,0 +1,19 @@
1
+ import { NAV_THEME } from "../constants";
2
+ import { useColorScheme } from "./useColorScheme";
3
+
4
+ /** Icon `color` values aligned with `NAV_THEME` + semantic muted text (matches `global.css` muted-foreground). */
5
+ export function useIconColors() {
6
+ const { colorScheme } = useColorScheme();
7
+ const scheme = colorScheme === "dark" ? "dark" : "light";
8
+ const t = NAV_THEME[scheme];
9
+ return {
10
+ foreground: t.text,
11
+ muted: scheme === "dark" ? "hsl(240 5% 64.9%)" : "hsl(240 3.8% 46.1%)",
12
+ primary: t.primary,
13
+ destructive: t.notification,
14
+ /** For icons/spinners on `bg-destructive` (matches `--destructive-foreground`). */
15
+ onDestructive: "hsl(0 0% 100%)",
16
+ /** For icons/spinners on `bg-primary` (matches `--primary-foreground`). */
17
+ onPrimary: scheme === "dark" ? "hsl(240 5.9% 10%)" : "hsl(0 0% 98%)"
18
+ };
19
+ }
package/src/index.ts ADDED
@@ -0,0 +1,124 @@
1
+ export { cn } from "./utils";
2
+ export { useColorScheme } from "./hooks/useColorScheme";
3
+ export { useIconColors } from "./hooks/useIconColors";
4
+ export { NAV_THEME } from "./constants";
5
+ export { typography } from "./tokens";
6
+ export { lightVars, darkVars } from "./theme";
7
+ export type { TypographyToken } from "./tokens";
8
+
9
+ export { MAlert } from "./MAlert";
10
+ export type { MAlertProps } from "./MAlert";
11
+
12
+ export { MAnimation } from "./MAnimation";
13
+ export type { MAnimationProps } from "./MAnimation";
14
+
15
+ export { MAvatar } from "./MAvatar";
16
+ export type { MAvatarProps } from "./MAvatar";
17
+
18
+ export { MBadge } from "./MBadge";
19
+ export type { MBadgeProps } from "./MBadge";
20
+
21
+ export { MButton, buttonVariants } from "./MButton";
22
+ export type { MButtonProps } from "./MButton";
23
+
24
+ export { MChevron } from "./MChevron";
25
+ export type { MChevronProps } from "./MChevron";
26
+
27
+ export { MDateTimePicker } from "./MDateTimePicker";
28
+ export type { CalendarProps } from "./MDateTimePicker";
29
+
30
+ export { MDivider } from "./MDivider";
31
+ export type { MDividerProps } from "./MDivider";
32
+
33
+ export { MLucideIcon } from "./MLucideIcon";
34
+ export type { MLucideIconProps, IconName } from "./MLucideIcon";
35
+
36
+ export { MPicker } from "./MPicker";
37
+ export type { MPickerProps, PickerItem } from "./MPicker";
38
+
39
+ export { MProgressBar } from "./MProgressBar";
40
+ export type { MProgressBarProps } from "./MProgressBar";
41
+
42
+ export { MResponsiveContainer } from "./MResponsiveContainer";
43
+
44
+ export { MText } from "./MText";
45
+ export type { MTextProps } from "./MText";
46
+
47
+ export { MRequiredLabel } from "./MRequiredLabel";
48
+
49
+ export {
50
+ MModal,
51
+ ModalHeight,
52
+ ModalScrollContext,
53
+ ModalContent
54
+ } from "./MModal";
55
+ export type { MModalProps } from "./MModal";
56
+
57
+ export { MDrawerRightPanel } from "./MDrawerRightPanel";
58
+ export type { MDrawerRightPanelProps } from "./MDrawerRightPanel";
59
+
60
+ export { MNativeAlert } from "./MNativeAlert";
61
+ export type { MNativeAlertProps } from "./MNativeAlert";
62
+
63
+ export { MCountDown } from "./MCountDown";
64
+ export type { MCountDownProps } from "./MCountDown";
65
+
66
+ export { MDropdown } from "./MDropdown";
67
+ export type { MDropdownProps } from "./MDropdown";
68
+
69
+ export { MSearch } from "./MSearch";
70
+ export type { MSearchProps } from "./MSearch";
71
+
72
+ export { MSelector } from "./MSelector";
73
+ export type { MSelectorProps } from "./MSelector";
74
+
75
+ export { MToggle } from "./MToggle";
76
+ export type { MToggleProps, MToggleOption } from "./MToggle";
77
+
78
+ export { MConfirmation } from "./MConfirmation";
79
+ export type { MConfirmationProps } from "./MConfirmation";
80
+
81
+ export { MPinPadKeys } from "./MPinPadKeys";
82
+ export type { MPinPadKeysProps } from "./MPinPadKeys";
83
+
84
+ export { MNumpad, NumpadMode, getDecimalSeparator } from "./MNumpad";
85
+ export type { MNumpadProps } from "./MNumpad";
86
+
87
+ export { MTabs } from "./MTabs";
88
+ export type { MTabsProps, Tab } from "./MTabs";
89
+
90
+ export { MTimerUp } from "./MTimerUp";
91
+ export type { MTimerUpProps } from "./MTimerUp";
92
+
93
+ export {
94
+ MCard,
95
+ MCardContent,
96
+ MCardDescription,
97
+ MCardFooter,
98
+ MCardHeader,
99
+ MCardTitle
100
+ } from "./MCard";
101
+
102
+ export { MSkeleton } from "./MSkeleton";
103
+
104
+ export { MSwitch } from "./MSwitch";
105
+ export type { MSwitchProps } from "./MSwitch";
106
+
107
+ export {
108
+ MTable,
109
+ MTableBody,
110
+ MTableCell,
111
+ MTableFooter,
112
+ MTableHead,
113
+ MTableHeader,
114
+ MTableRow
115
+ } from "./MTable";
116
+
117
+ export { MPortal, MPortalHost } from "./MPortal";
118
+
119
+ export { MInput } from "./MInput";
120
+ export type { MInputProps } from "./MInput";
121
+
122
+ export { MLabel } from "./MLabel";
123
+
124
+ export { MRadioGroup, MRadioGroupItem } from "./MRadioGroup";
@@ -0,0 +1,143 @@
1
+ import * as AccordionPrimitive from "@rn-primitives/accordion";
2
+ import { ChevronDown } from "lucide-react-native";
3
+ import * as React from "react";
4
+ import { Platform, Pressable, View, type ViewProps } from "react-native";
5
+ import Animated, {
6
+ Extrapolation,
7
+ FadeIn,
8
+ FadeOutUp,
9
+ LayoutAnimationConfig,
10
+ LinearTransition,
11
+ interpolate,
12
+ useAnimatedStyle,
13
+ useDerivedValue,
14
+ withTiming
15
+ } from "react-native-reanimated";
16
+ import { cn } from "../utils";
17
+ import { TextClassContext } from "./text";
18
+
19
+ const Accordion = React.forwardRef<
20
+ AccordionPrimitive.RootRef,
21
+ AccordionPrimitive.RootProps
22
+ >(({ children, ...props }, ref) => {
23
+ return (
24
+ <LayoutAnimationConfig skipEntering>
25
+ <AccordionPrimitive.Root
26
+ ref={ref}
27
+ {...props}
28
+ asChild={Platform.OS !== "web"}
29
+ >
30
+ <Animated.View layout={LinearTransition.duration(200)}>
31
+ {children}
32
+ </Animated.View>
33
+ </AccordionPrimitive.Root>
34
+ </LayoutAnimationConfig>
35
+ );
36
+ });
37
+
38
+ Accordion.displayName = AccordionPrimitive.Root.displayName;
39
+
40
+ const AccordionItem = React.forwardRef<
41
+ AccordionPrimitive.ItemRef,
42
+ AccordionPrimitive.ItemProps
43
+ >(({ className, value, ...props }, ref) => {
44
+ return (
45
+ <Animated.View
46
+ className={"overflow-hidden"}
47
+ layout={LinearTransition.duration(200)}
48
+ >
49
+ <AccordionPrimitive.Item
50
+ ref={ref}
51
+ className={cn("border-b border-border", className)}
52
+ value={value}
53
+ {...props}
54
+ />
55
+ </Animated.View>
56
+ );
57
+ });
58
+ AccordionItem.displayName = AccordionPrimitive.Item.displayName;
59
+
60
+ const Trigger = Platform.OS === "web" ? View : Pressable;
61
+
62
+ const AccordionTrigger = React.forwardRef<
63
+ AccordionPrimitive.TriggerRef,
64
+ AccordionPrimitive.TriggerProps
65
+ >(({ className, children, ...props }, ref) => {
66
+ const { isExpanded } = AccordionPrimitive.useItemContext();
67
+
68
+ const progress = useDerivedValue(() =>
69
+ isExpanded
70
+ ? withTiming(1, { duration: 250 })
71
+ : withTiming(0, { duration: 200 })
72
+ );
73
+ const chevronStyle = useAnimatedStyle(() => ({
74
+ transform: [{ rotate: `${progress.value * 180}deg` }],
75
+ opacity: interpolate(progress.value, [0, 1], [1, 0.8], Extrapolation.CLAMP)
76
+ }));
77
+
78
+ return (
79
+ <TextClassContext.Provider value="native:text-lg font-medium web:group-hover:underline">
80
+ <AccordionPrimitive.Header className="flex">
81
+ <AccordionPrimitive.Trigger ref={ref} {...props} asChild>
82
+ <Trigger
83
+ className={cn(
84
+ "flex flex-row web:flex-1 items-center justify-between py-4 web:transition-all group web:focus-visible:outline-none web:focus-visible:ring-1 web:focus-visible:ring-muted-foreground",
85
+ className
86
+ )}
87
+ >
88
+ <>{children}</>
89
+ <Animated.View style={chevronStyle}>
90
+ <ChevronDown size={18} className={"text-foreground shrink-0"} />
91
+ </Animated.View>
92
+ </Trigger>
93
+ </AccordionPrimitive.Trigger>
94
+ </AccordionPrimitive.Header>
95
+ </TextClassContext.Provider>
96
+ );
97
+ });
98
+ AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName;
99
+
100
+ const AccordionContent = React.forwardRef<
101
+ AccordionPrimitive.ContentRef,
102
+ AccordionPrimitive.ContentProps
103
+ >(({ className, children, ...props }, ref) => {
104
+ const { isExpanded } = AccordionPrimitive.useItemContext();
105
+ return (
106
+ <TextClassContext.Provider value="native:text-lg">
107
+ <AccordionPrimitive.Content
108
+ className={cn(
109
+ "overflow-hidden text-sm web:transition-all",
110
+ isExpanded ? "web:animate-accordion-down" : "web:animate-accordion-up"
111
+ )}
112
+ ref={ref}
113
+ {...props}
114
+ >
115
+ <InnerContent className={cn("pb-4", className)}>
116
+ {children}
117
+ </InnerContent>
118
+ </AccordionPrimitive.Content>
119
+ </TextClassContext.Provider>
120
+ );
121
+ });
122
+
123
+ function InnerContent({
124
+ children,
125
+ className
126
+ }: React.PropsWithChildren<Pick<ViewProps, "className">>) {
127
+ if (Platform.OS === "web") {
128
+ return <View className={cn("pb-4", className)}>{children}</View>;
129
+ }
130
+ return (
131
+ <Animated.View
132
+ entering={FadeIn}
133
+ exiting={FadeOutUp.duration(200)}
134
+ className={cn("pb-4", className)}
135
+ >
136
+ {children}
137
+ </Animated.View>
138
+ );
139
+ }
140
+
141
+ AccordionContent.displayName = AccordionPrimitive.Content.displayName;
142
+
143
+ export { Accordion, AccordionContent, AccordionItem, AccordionTrigger };
@@ -0,0 +1,181 @@
1
+ import * as AlertDialogPrimitive from "@rn-primitives/alert-dialog";
2
+ import * as React from "react";
3
+ import { Platform, StyleSheet, View, type ViewProps } from "react-native";
4
+ import Animated, { FadeIn, FadeOut } from "react-native-reanimated";
5
+ import { cn } from "../utils";
6
+ import { buttonTextVariants, buttonVariants } from "./button";
7
+ import { TextClassContext } from "./text";
8
+
9
+ const AlertDialog = AlertDialogPrimitive.Root;
10
+
11
+ const AlertDialogTrigger = AlertDialogPrimitive.Trigger;
12
+
13
+ const AlertDialogPortal = AlertDialogPrimitive.Portal;
14
+
15
+ const AlertDialogOverlayWeb = React.forwardRef<
16
+ AlertDialogPrimitive.OverlayRef,
17
+ AlertDialogPrimitive.OverlayProps
18
+ >(({ className, ...props }, ref) => {
19
+ const { open } = AlertDialogPrimitive.useRootContext();
20
+ return (
21
+ <AlertDialogPrimitive.Overlay
22
+ className={cn(
23
+ "z-50 bg-black/80 flex justify-center items-center p-2 absolute top-0 right-0 bottom-0 left-0",
24
+ open
25
+ ? "web:animate-in web:fade-in-0"
26
+ : "web:animate-out web:fade-out-0",
27
+ className
28
+ )}
29
+ {...props}
30
+ ref={ref}
31
+ />
32
+ );
33
+ });
34
+
35
+ AlertDialogOverlayWeb.displayName = "AlertDialogOverlayWeb";
36
+
37
+ const AlertDialogOverlayNative = React.forwardRef<
38
+ AlertDialogPrimitive.OverlayRef,
39
+ AlertDialogPrimitive.OverlayProps
40
+ >(({ className, children, ...props }, ref) => {
41
+ return (
42
+ <AlertDialogPrimitive.Overlay
43
+ style={StyleSheet.absoluteFill}
44
+ className={cn(
45
+ "z-50 bg-black/80 flex justify-center items-center p-2",
46
+ className
47
+ )}
48
+ {...props}
49
+ ref={ref}
50
+ asChild
51
+ >
52
+ <Animated.View
53
+ entering={FadeIn.duration(150)}
54
+ exiting={FadeOut.duration(150)}
55
+ >
56
+ {children}
57
+ </Animated.View>
58
+ </AlertDialogPrimitive.Overlay>
59
+ );
60
+ });
61
+
62
+ AlertDialogOverlayNative.displayName = "AlertDialogOverlayNative";
63
+
64
+ const AlertDialogOverlay = Platform.select({
65
+ web: AlertDialogOverlayWeb,
66
+ default: AlertDialogOverlayNative
67
+ });
68
+
69
+ const AlertDialogContent = React.forwardRef<
70
+ AlertDialogPrimitive.ContentRef,
71
+ AlertDialogPrimitive.ContentProps & { portalHost?: string }
72
+ >(({ className, portalHost, ...props }, ref) => {
73
+ const { open } = AlertDialogPrimitive.useRootContext();
74
+
75
+ return (
76
+ <AlertDialogPortal hostName={portalHost}>
77
+ <AlertDialogOverlay>
78
+ <AlertDialogPrimitive.Content
79
+ ref={ref}
80
+ className={cn(
81
+ "z-50 max-w-lg gap-4 border border-border bg-background p-6 shadow-lg shadow-foreground/10 web:duration-200 rounded-lg",
82
+ open
83
+ ? "web:animate-in web:fade-in-0 web:zoom-in-95"
84
+ : "web:animate-out web:fade-out-0 web:zoom-out-95",
85
+ className
86
+ )}
87
+ {...props}
88
+ />
89
+ </AlertDialogOverlay>
90
+ </AlertDialogPortal>
91
+ );
92
+ });
93
+ AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName;
94
+
95
+ const AlertDialogHeader = ({ className, ...props }: ViewProps) => (
96
+ <View className={cn("flex flex-col gap-2", className)} {...props} />
97
+ );
98
+ AlertDialogHeader.displayName = "AlertDialogHeader";
99
+
100
+ const AlertDialogFooter = ({ className, ...props }: ViewProps) => (
101
+ <View
102
+ className={cn(
103
+ "flex flex-col-reverse sm:flex-row sm:justify-end gap-2",
104
+ className
105
+ )}
106
+ {...props}
107
+ />
108
+ );
109
+ AlertDialogFooter.displayName = "AlertDialogFooter";
110
+
111
+ const AlertDialogTitle = React.forwardRef<
112
+ AlertDialogPrimitive.TitleRef,
113
+ AlertDialogPrimitive.TitleProps
114
+ >(({ className, ...props }, ref) => (
115
+ <AlertDialogPrimitive.Title
116
+ ref={ref}
117
+ className={cn(
118
+ "text-lg native:text-xl text-foreground font-semibold",
119
+ className
120
+ )}
121
+ {...props}
122
+ />
123
+ ));
124
+ AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName;
125
+
126
+ const AlertDialogDescription = React.forwardRef<
127
+ AlertDialogPrimitive.DescriptionRef,
128
+ AlertDialogPrimitive.DescriptionProps
129
+ >(({ className, ...props }, ref) => (
130
+ <AlertDialogPrimitive.Description
131
+ ref={ref}
132
+ className={cn("text-sm native:text-base text-muted-foreground", className)}
133
+ {...props}
134
+ />
135
+ ));
136
+ AlertDialogDescription.displayName =
137
+ AlertDialogPrimitive.Description.displayName;
138
+
139
+ const AlertDialogAction = React.forwardRef<
140
+ AlertDialogPrimitive.ActionRef,
141
+ AlertDialogPrimitive.ActionProps
142
+ >(({ className, ...props }, ref) => (
143
+ <TextClassContext.Provider value={buttonTextVariants({ className })}>
144
+ <AlertDialogPrimitive.Action
145
+ ref={ref}
146
+ className={cn(buttonVariants(), className)}
147
+ {...props}
148
+ />
149
+ </TextClassContext.Provider>
150
+ ));
151
+ AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName;
152
+
153
+ const AlertDialogCancel = React.forwardRef<
154
+ AlertDialogPrimitive.CancelRef,
155
+ AlertDialogPrimitive.CancelProps
156
+ >(({ className, ...props }, ref) => (
157
+ <TextClassContext.Provider
158
+ value={buttonTextVariants({ className, variant: "outline" })}
159
+ >
160
+ <AlertDialogPrimitive.Cancel
161
+ ref={ref}
162
+ className={cn(buttonVariants({ variant: "outline", className }))}
163
+ {...props}
164
+ />
165
+ </TextClassContext.Provider>
166
+ ));
167
+ AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName;
168
+
169
+ export {
170
+ AlertDialog,
171
+ AlertDialogAction,
172
+ AlertDialogCancel,
173
+ AlertDialogContent,
174
+ AlertDialogDescription,
175
+ AlertDialogFooter,
176
+ AlertDialogHeader,
177
+ AlertDialogOverlay,
178
+ AlertDialogPortal,
179
+ AlertDialogTitle,
180
+ AlertDialogTrigger
181
+ };