@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
@@ -0,0 +1,94 @@
1
+ import { type VariantProps, cva } from "class-variance-authority";
2
+ import type { LucideIcon } from "lucide-react-native";
3
+ import * as React from "react";
4
+ import { View, type ViewProps } from "react-native";
5
+ import { cn } from "../utils";
6
+ import { Text } from "./text";
7
+
8
+ const alertVariants = cva(
9
+ "relative bg-background w-full rounded-lg border border-border p-4 shadow shadow-foreground/10",
10
+ {
11
+ variants: {
12
+ variant: {
13
+ default: "",
14
+ destructive: "border-destructive"
15
+ }
16
+ },
17
+ defaultVariants: {
18
+ variant: "default"
19
+ }
20
+ }
21
+ );
22
+
23
+ const ICON_COLORS = {
24
+ default: "hsl(240 10% 3.9%)",
25
+ destructive: "hsl(0 84.2% 60.2%)"
26
+ } as const;
27
+
28
+ const Alert = React.forwardRef<
29
+ React.ElementRef<typeof View>,
30
+ ViewProps &
31
+ VariantProps<typeof alertVariants> & {
32
+ icon: LucideIcon;
33
+ iconSize?: number;
34
+ iconClassName?: ViewProps["className"];
35
+ }
36
+ >(
37
+ (
38
+ {
39
+ className,
40
+ variant,
41
+ children,
42
+ icon: Icon,
43
+ iconSize = 16,
44
+ iconClassName,
45
+ ...props
46
+ },
47
+ ref
48
+ ) => {
49
+ const iconColor = ICON_COLORS[variant ?? "default"];
50
+ return (
51
+ <View
52
+ ref={ref}
53
+ role="alert"
54
+ className={alertVariants({ variant, className })}
55
+ {...props}
56
+ >
57
+ <View className="absolute left-3.5 top-4 -translate-y-0.5">
58
+ <Icon size={iconSize} color={iconColor} />
59
+ </View>
60
+ {children}
61
+ </View>
62
+ );
63
+ }
64
+ );
65
+ Alert.displayName = "Alert";
66
+
67
+ const AlertTitle = React.forwardRef<
68
+ React.ElementRef<typeof Text>,
69
+ React.ComponentPropsWithoutRef<typeof Text>
70
+ >(({ className, ...props }, ref) => (
71
+ <Text
72
+ ref={ref}
73
+ className={cn(
74
+ "pl-7 mb-1 font-medium text-base leading-none tracking-tight text-foreground",
75
+ className
76
+ )}
77
+ {...props}
78
+ />
79
+ ));
80
+ AlertTitle.displayName = "AlertTitle";
81
+
82
+ const AlertDescription = React.forwardRef<
83
+ React.ElementRef<typeof Text>,
84
+ React.ComponentPropsWithoutRef<typeof Text>
85
+ >(({ className, ...props }, ref) => (
86
+ <Text
87
+ ref={ref}
88
+ className={cn("pl-7 text-sm leading-relaxed text-foreground", className)}
89
+ {...props}
90
+ />
91
+ ));
92
+ AlertDescription.displayName = "AlertDescription";
93
+
94
+ export { Alert, AlertDescription, AlertTitle };
@@ -0,0 +1,5 @@
1
+ import * as AspectRatioPrimitive from "@rn-primitives/aspect-ratio";
2
+
3
+ const AspectRatio = AspectRatioPrimitive.Root;
4
+
5
+ export { AspectRatio };
@@ -0,0 +1,47 @@
1
+ import * as AvatarPrimitive from "@rn-primitives/avatar";
2
+ import * as React from "react";
3
+ import { cn } from "../utils";
4
+
5
+ const Avatar = React.forwardRef<
6
+ AvatarPrimitive.RootRef,
7
+ AvatarPrimitive.RootProps
8
+ >(({ className, ...props }, ref) => (
9
+ <AvatarPrimitive.Root
10
+ ref={ref}
11
+ className={cn(
12
+ "relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full",
13
+ className
14
+ )}
15
+ {...props}
16
+ />
17
+ ));
18
+ Avatar.displayName = AvatarPrimitive.Root.displayName;
19
+
20
+ const AvatarImage = React.forwardRef<
21
+ AvatarPrimitive.ImageRef,
22
+ AvatarPrimitive.ImageProps
23
+ >(({ className, ...props }, ref) => (
24
+ <AvatarPrimitive.Image
25
+ ref={ref}
26
+ className={cn("aspect-square h-full w-full", className)}
27
+ {...props}
28
+ />
29
+ ));
30
+ AvatarImage.displayName = AvatarPrimitive.Image.displayName;
31
+
32
+ const AvatarFallback = React.forwardRef<
33
+ AvatarPrimitive.FallbackRef,
34
+ AvatarPrimitive.FallbackProps
35
+ >(({ className, ...props }, ref) => (
36
+ <AvatarPrimitive.Fallback
37
+ ref={ref}
38
+ className={cn(
39
+ "flex h-full w-full items-center justify-center rounded-full bg-muted",
40
+ className
41
+ )}
42
+ {...props}
43
+ />
44
+ ));
45
+ AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;
46
+
47
+ export { Avatar, AvatarFallback, AvatarImage };
@@ -0,0 +1,57 @@
1
+ import * as Slot from "@rn-primitives/slot";
2
+ import type { SlottableViewProps } from "@rn-primitives/types";
3
+ import { type VariantProps, cva } from "class-variance-authority";
4
+ import { View } from "react-native";
5
+ import { cn } from "../utils";
6
+ import { TextClassContext } from "./text";
7
+
8
+ const badgeVariants = cva(
9
+ "web:inline-flex items-center rounded-full border border-border px-2.5 py-0.5 web:transition-colors web:focus:outline-none web:focus:ring-2 web:focus:ring-ring web:focus:ring-offset-2",
10
+ {
11
+ variants: {
12
+ variant: {
13
+ default:
14
+ "border-transparent bg-primary web:hover:opacity-80 active:opacity-80",
15
+ secondary:
16
+ "border-transparent bg-secondary web:hover:opacity-80 active:opacity-80",
17
+ destructive:
18
+ "border-transparent bg-destructive web:hover:opacity-80 active:opacity-80",
19
+ outline: "text-foreground"
20
+ }
21
+ },
22
+ defaultVariants: {
23
+ variant: "default"
24
+ }
25
+ }
26
+ );
27
+
28
+ const badgeTextVariants = cva("text-xs font-semibold ", {
29
+ variants: {
30
+ variant: {
31
+ default: "text-primary-foreground",
32
+ secondary: "text-secondary-foreground",
33
+ destructive: "text-destructive-foreground",
34
+ outline: "text-foreground"
35
+ }
36
+ },
37
+ defaultVariants: {
38
+ variant: "default"
39
+ }
40
+ });
41
+
42
+ type BadgeProps = SlottableViewProps & VariantProps<typeof badgeVariants>;
43
+
44
+ function Badge({ className, variant, asChild, ...props }: BadgeProps) {
45
+ const Component = asChild ? Slot.View : View;
46
+ return (
47
+ <TextClassContext.Provider value={badgeTextVariants({ variant })}>
48
+ <Component
49
+ className={cn(badgeVariants({ variant }), className)}
50
+ {...props}
51
+ />
52
+ </TextClassContext.Provider>
53
+ );
54
+ }
55
+
56
+ export { Badge, badgeTextVariants, badgeVariants };
57
+ export type { BadgeProps };
@@ -0,0 +1,92 @@
1
+ import { type VariantProps, cva } from "class-variance-authority";
2
+ import * as React from "react";
3
+ import { Pressable } from "react-native";
4
+ import { cn } from "../utils";
5
+ import { TextClassContext } from "./text";
6
+
7
+ const buttonVariants = cva(
8
+ "group flex items-center justify-center rounded-md web:ring-offset-background web:transition-colors web:focus-visible:outline-none web:focus-visible:ring-2 web:focus-visible:ring-ring web:focus-visible:ring-offset-2",
9
+ {
10
+ variants: {
11
+ variant: {
12
+ default: "bg-primary web:hover:opacity-90 active:opacity-90",
13
+ destructive: "bg-destructive web:hover:opacity-90 active:opacity-90",
14
+ outline:
15
+ "border border-input bg-background web:hover:bg-accent web:hover:text-accent-foreground active:bg-accent",
16
+ secondary: "bg-secondary web:hover:opacity-80 active:opacity-80",
17
+ ghost:
18
+ "web:hover:bg-accent web:hover:text-accent-foreground active:bg-accent",
19
+ link: "web:underline-offset-4 web:hover:underline web:focus:underline"
20
+ },
21
+ size: {
22
+ default: "h-10 px-4 py-2 native:h-12 native:px-5 native:py-3",
23
+ sm: "h-9 rounded-md px-3",
24
+ lg: "h-11 rounded-md px-8 native:h-14",
25
+ icon: "h-10 w-10"
26
+ }
27
+ },
28
+ defaultVariants: {
29
+ variant: "default",
30
+ size: "default"
31
+ }
32
+ }
33
+ );
34
+
35
+ const buttonTextVariants = cva(
36
+ "web:whitespace-nowrap text-sm native:text-base font-medium text-foreground web:transition-colors",
37
+ {
38
+ variants: {
39
+ variant: {
40
+ default: "text-primary-foreground",
41
+ destructive: "text-destructive-foreground",
42
+ outline: "group-active:text-accent-foreground",
43
+ secondary:
44
+ "text-secondary-foreground group-active:text-secondary-foreground",
45
+ ghost: "group-active:text-accent-foreground",
46
+ link: "text-primary group-active:underline"
47
+ },
48
+ size: {
49
+ default: "",
50
+ sm: "",
51
+ lg: "native:text-lg",
52
+ icon: ""
53
+ }
54
+ },
55
+ defaultVariants: {
56
+ variant: "default",
57
+ size: "default"
58
+ }
59
+ }
60
+ );
61
+
62
+ type ButtonProps = React.ComponentPropsWithoutRef<typeof Pressable> &
63
+ VariantProps<typeof buttonVariants>;
64
+
65
+ const Button = React.forwardRef<
66
+ React.ElementRef<typeof Pressable>,
67
+ ButtonProps
68
+ >(({ className, variant, size, ...props }, ref) => {
69
+ return (
70
+ <TextClassContext.Provider
71
+ value={buttonTextVariants({
72
+ variant,
73
+ size,
74
+ className: "web:pointer-events-none"
75
+ })}
76
+ >
77
+ <Pressable
78
+ className={cn(
79
+ props.disabled && "opacity-50 web:pointer-events-none",
80
+ buttonVariants({ variant, size, className })
81
+ )}
82
+ ref={ref}
83
+ role="button"
84
+ {...props}
85
+ />
86
+ </TextClassContext.Provider>
87
+ );
88
+ });
89
+ Button.displayName = "Button";
90
+
91
+ export { Button, buttonTextVariants, buttonVariants };
92
+ export type { ButtonProps };
@@ -0,0 +1,86 @@
1
+ import type { TextRef, ViewRef } from "@rn-primitives/types";
2
+ import * as React from "react";
3
+ import { Text, type TextProps, View, type ViewProps } from "react-native";
4
+ import { cn } from "../utils";
5
+ import { TextClassContext } from "./text";
6
+
7
+ const Card = React.forwardRef<ViewRef, ViewProps>(
8
+ ({ className, ...props }, ref) => (
9
+ <View
10
+ ref={ref}
11
+ className={cn(
12
+ "rounded-lg border border-border bg-card shadow-sm shadow-foreground/10",
13
+ className
14
+ )}
15
+ {...props}
16
+ />
17
+ )
18
+ );
19
+ Card.displayName = "Card";
20
+
21
+ const CardHeader = React.forwardRef<ViewRef, ViewProps>(
22
+ ({ className, ...props }, ref) => (
23
+ <View
24
+ ref={ref}
25
+ className={cn("flex flex-col space-y-1.5 p-6", className)}
26
+ {...props}
27
+ />
28
+ )
29
+ );
30
+ CardHeader.displayName = "CardHeader";
31
+
32
+ const CardTitle = React.forwardRef<TextRef, TextProps>(
33
+ ({ className, ...props }, ref) => (
34
+ <Text
35
+ role="heading"
36
+ aria-level={3}
37
+ ref={ref}
38
+ className={cn(
39
+ "text-2xl text-card-foreground font-semibold leading-none tracking-tight",
40
+ className
41
+ )}
42
+ {...props}
43
+ />
44
+ )
45
+ );
46
+ CardTitle.displayName = "CardTitle";
47
+
48
+ const CardDescription = React.forwardRef<TextRef, TextProps>(
49
+ ({ className, ...props }, ref) => (
50
+ <Text
51
+ ref={ref}
52
+ className={cn("text-sm text-muted-foreground", className)}
53
+ {...props}
54
+ />
55
+ )
56
+ );
57
+ CardDescription.displayName = "CardDescription";
58
+
59
+ const CardContent = React.forwardRef<ViewRef, ViewProps>(
60
+ ({ className, ...props }, ref) => (
61
+ <TextClassContext.Provider value="text-card-foreground">
62
+ <View ref={ref} className={cn("p-6 pt-0", className)} {...props} />
63
+ </TextClassContext.Provider>
64
+ )
65
+ );
66
+ CardContent.displayName = "CardContent";
67
+
68
+ const CardFooter = React.forwardRef<ViewRef, ViewProps>(
69
+ ({ className, ...props }, ref) => (
70
+ <View
71
+ ref={ref}
72
+ className={cn("flex flex-row items-center p-6 pt-0", className)}
73
+ {...props}
74
+ />
75
+ )
76
+ );
77
+ CardFooter.displayName = "CardFooter";
78
+
79
+ export {
80
+ Card,
81
+ CardContent,
82
+ CardDescription,
83
+ CardFooter,
84
+ CardHeader,
85
+ CardTitle
86
+ };
@@ -0,0 +1,35 @@
1
+ import * as CheckboxPrimitive from "@rn-primitives/checkbox";
2
+ import { Check } from "lucide-react-native";
3
+ import * as React from "react";
4
+ import { Platform } from "react-native";
5
+ import { cn } from "../utils";
6
+
7
+ const Checkbox = React.forwardRef<
8
+ CheckboxPrimitive.RootRef,
9
+ CheckboxPrimitive.RootProps
10
+ >(({ className, ...props }, ref) => {
11
+ return (
12
+ <CheckboxPrimitive.Root
13
+ ref={ref}
14
+ className={cn(
15
+ "web:peer h-4 w-4 native:h-[20] native:w-[20] shrink-0 rounded-sm native:rounded border border-primary web:ring-offset-background web:focus-visible:outline-none web:focus-visible:ring-2 web:focus-visible:ring-ring web:focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
16
+ props.checked && "bg-primary",
17
+ className
18
+ )}
19
+ {...props}
20
+ >
21
+ <CheckboxPrimitive.Indicator
22
+ className={cn("items-center justify-center h-full w-full")}
23
+ >
24
+ <Check
25
+ size={12}
26
+ strokeWidth={Platform.OS === "web" ? 2.5 : 3.5}
27
+ className="text-primary-foreground"
28
+ />
29
+ </CheckboxPrimitive.Indicator>
30
+ </CheckboxPrimitive.Root>
31
+ );
32
+ });
33
+ Checkbox.displayName = CheckboxPrimitive.Root.displayName;
34
+
35
+ export { Checkbox };
@@ -0,0 +1,9 @@
1
+ import * as CollapsiblePrimitive from "@rn-primitives/collapsible";
2
+
3
+ const Collapsible = CollapsiblePrimitive.Root;
4
+
5
+ const CollapsibleTrigger = CollapsiblePrimitive.Trigger;
6
+
7
+ const CollapsibleContent = CollapsiblePrimitive.Content;
8
+
9
+ export { Collapsible, CollapsibleTrigger, CollapsibleContent };
@@ -0,0 +1,255 @@
1
+ import * as ContextMenuPrimitive from "@rn-primitives/context-menu";
2
+ import {
3
+ Check,
4
+ ChevronDown,
5
+ ChevronRight,
6
+ ChevronUp
7
+ } from "lucide-react-native";
8
+ import * as React from "react";
9
+ import {
10
+ Platform,
11
+ type StyleProp,
12
+ StyleSheet,
13
+ Text,
14
+ type TextProps,
15
+ View,
16
+ type ViewProps,
17
+ type ViewStyle
18
+ } from "react-native";
19
+ import { cn } from "../utils";
20
+ import { TextClassContext } from "./text";
21
+
22
+ const ContextMenu = ContextMenuPrimitive.Root;
23
+ const ContextMenuTrigger = ContextMenuPrimitive.Trigger;
24
+ const ContextMenuGroup = ContextMenuPrimitive.Group;
25
+ const ContextMenuSub = ContextMenuPrimitive.Sub;
26
+ const ContextMenuRadioGroup = ContextMenuPrimitive.RadioGroup;
27
+
28
+ const ContextMenuSubTrigger = React.forwardRef<
29
+ ContextMenuPrimitive.SubTriggerRef,
30
+ ContextMenuPrimitive.SubTriggerProps & {
31
+ inset?: boolean;
32
+ }
33
+ >(({ className, inset, children, ...props }, ref) => {
34
+ const { open } = ContextMenuPrimitive.useSubContext();
35
+ const Icon =
36
+ Platform.OS === "web" ? ChevronRight : open ? ChevronUp : ChevronDown;
37
+ return (
38
+ <TextClassContext.Provider
39
+ value={cn(
40
+ "select-none text-sm native:text-lg text-primary",
41
+ open && "native:text-accent-foreground"
42
+ )}
43
+ >
44
+ <ContextMenuPrimitive.SubTrigger
45
+ ref={ref}
46
+ className={cn(
47
+ "flex flex-row web:cursor-default web:select-none items-center gap-2 web:focus:bg-accent active:bg-accent web:hover:bg-accent rounded-sm px-2 py-1.5 native:py-2 web:outline-none",
48
+ open && "bg-accent",
49
+ inset && "pl-8",
50
+ className
51
+ )}
52
+ {...props}
53
+ >
54
+ <>{children}</>
55
+ <Icon size={18} className="ml-auto text-foreground" />
56
+ </ContextMenuPrimitive.SubTrigger>
57
+ </TextClassContext.Provider>
58
+ );
59
+ });
60
+ ContextMenuSubTrigger.displayName = ContextMenuPrimitive.SubTrigger.displayName;
61
+
62
+ const ContextMenuSubContent = React.forwardRef<
63
+ ContextMenuPrimitive.SubContentRef,
64
+ ContextMenuPrimitive.SubContentProps
65
+ >(({ className, ...props }, ref) => {
66
+ const { open } = ContextMenuPrimitive.useSubContext();
67
+ return (
68
+ <ContextMenuPrimitive.SubContent
69
+ ref={ref}
70
+ className={cn(
71
+ "z-50 min-w-[8rem] overflow-hidden rounded-md border mt-1 border-border bg-popover p-1 shadow-md shadow-foreground/5 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
72
+ open
73
+ ? "web:animate-in web:fade-in-0 web:zoom-in-95"
74
+ : "web:animate-out web:fade-out-0 web:zoom-out",
75
+ className
76
+ )}
77
+ {...props}
78
+ />
79
+ );
80
+ });
81
+ ContextMenuSubContent.displayName = "ContextMenuSubContent";
82
+
83
+ const ContextMenuContent = React.forwardRef<
84
+ ContextMenuPrimitive.ContentRef,
85
+ ContextMenuPrimitive.ContentProps & {
86
+ overlayStyle?: StyleProp<ViewStyle>;
87
+ overlayClassName?: ViewProps["className"];
88
+ portalHost?: string;
89
+ }
90
+ >(
91
+ (
92
+ { className, overlayClassName, overlayStyle, portalHost, ...props },
93
+ ref
94
+ ) => {
95
+ const { open } = ContextMenuPrimitive.useRootContext();
96
+ return (
97
+ <ContextMenuPrimitive.Portal hostName={portalHost}>
98
+ <ContextMenuPrimitive.Overlay
99
+ style={
100
+ overlayStyle
101
+ ? StyleSheet.flatten([
102
+ Platform.OS !== "web" ? StyleSheet.absoluteFill : undefined,
103
+ overlayStyle
104
+ ])
105
+ : Platform.OS !== "web"
106
+ ? StyleSheet.absoluteFill
107
+ : undefined
108
+ }
109
+ className={overlayClassName}
110
+ >
111
+ <ContextMenuPrimitive.Content
112
+ ref={ref}
113
+ className={cn(
114
+ "z-50 min-w-[8rem] overflow-hidden rounded-md border border-border bg-popover p-1 shadow-md shadow-foreground/5 web:data-[side=bottom]:slide-in-from-top-2 web:data-[side=left]:slide-in-from-right-2 web:data-[side=right]:slide-in-from-left-2 web:data-[side=top]:slide-in-from-bottom-2",
115
+ open
116
+ ? "web:animate-in web:fade-in-0 web:zoom-in-95"
117
+ : "web:animate-out web:fade-out-0 web:zoom-out-95",
118
+ className
119
+ )}
120
+ {...props}
121
+ />
122
+ </ContextMenuPrimitive.Overlay>
123
+ </ContextMenuPrimitive.Portal>
124
+ );
125
+ }
126
+ );
127
+ ContextMenuContent.displayName = ContextMenuPrimitive.Content.displayName;
128
+
129
+ const ContextMenuItem = React.forwardRef<
130
+ ContextMenuPrimitive.ItemRef,
131
+ ContextMenuPrimitive.ItemProps & {
132
+ inset?: boolean;
133
+ }
134
+ >(({ className, inset, ...props }, ref) => (
135
+ <TextClassContext.Provider value="select-none text-sm native:text-lg text-popover-foreground web:group-focus:text-accent-foreground">
136
+ <ContextMenuPrimitive.Item
137
+ ref={ref}
138
+ className={cn(
139
+ "relative flex flex-row web:cursor-default items-center gap-2 rounded-sm px-2 py-1.5 native:py-2 web:outline-none web:focus:bg-accent active:bg-accent web:hover:bg-accent group",
140
+ inset && "pl-8",
141
+ props.disabled && "opacity-50 web:pointer-events-none",
142
+ className
143
+ )}
144
+ {...props}
145
+ />
146
+ </TextClassContext.Provider>
147
+ ));
148
+ ContextMenuItem.displayName = ContextMenuPrimitive.Item.displayName;
149
+
150
+ const ContextMenuCheckboxItem = React.forwardRef<
151
+ ContextMenuPrimitive.CheckboxItemRef,
152
+ ContextMenuPrimitive.CheckboxItemProps
153
+ >(({ className, children, ...props }, ref) => (
154
+ <ContextMenuPrimitive.CheckboxItem
155
+ ref={ref}
156
+ className={cn(
157
+ "relative flex flex-row web:cursor-default items-center web:group rounded-sm py-1.5 native:py-2 pl-8 pr-2 web:outline-none web:focus:bg-accent active:bg-accent",
158
+ props.disabled && "web:pointer-events-none opacity-50",
159
+ className
160
+ )}
161
+ {...props}
162
+ >
163
+ <View className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
164
+ <ContextMenuPrimitive.ItemIndicator>
165
+ <Check size={14} strokeWidth={3} className="text-foreground" />
166
+ </ContextMenuPrimitive.ItemIndicator>
167
+ </View>
168
+ <>{children}</>
169
+ </ContextMenuPrimitive.CheckboxItem>
170
+ ));
171
+ ContextMenuCheckboxItem.displayName =
172
+ ContextMenuPrimitive.CheckboxItem.displayName;
173
+
174
+ const ContextMenuRadioItem = React.forwardRef<
175
+ ContextMenuPrimitive.RadioItemRef,
176
+ ContextMenuPrimitive.RadioItemProps
177
+ >(({ className, children, ...props }, ref) => (
178
+ <ContextMenuPrimitive.RadioItem
179
+ ref={ref}
180
+ className={cn(
181
+ "relative flex flex-row web:cursor-default web:group items-center rounded-sm py-1.5 native:py-2 pl-8 pr-2 web:outline-none web:focus:bg-accent active:bg-accent",
182
+ props.disabled && "web:pointer-events-none opacity-50",
183
+ className
184
+ )}
185
+ {...props}
186
+ >
187
+ <View className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
188
+ <ContextMenuPrimitive.ItemIndicator>
189
+ <View className="bg-foreground h-2 w-2 rounded-full" />
190
+ </ContextMenuPrimitive.ItemIndicator>
191
+ </View>
192
+ <>{children}</>
193
+ </ContextMenuPrimitive.RadioItem>
194
+ ));
195
+ ContextMenuRadioItem.displayName = ContextMenuPrimitive.RadioItem.displayName;
196
+
197
+ const ContextMenuLabel = React.forwardRef<
198
+ ContextMenuPrimitive.LabelRef,
199
+ ContextMenuPrimitive.LabelProps & {
200
+ inset?: boolean;
201
+ }
202
+ >(({ className, inset, ...props }, ref) => (
203
+ <ContextMenuPrimitive.Label
204
+ ref={ref}
205
+ className={cn(
206
+ "px-2 py-1.5 text-sm native:text-base font-semibold text-foreground web:cursor-default",
207
+ inset && "pl-8",
208
+ className
209
+ )}
210
+ {...props}
211
+ />
212
+ ));
213
+ ContextMenuLabel.displayName = ContextMenuPrimitive.Label.displayName;
214
+
215
+ const ContextMenuSeparator = React.forwardRef<
216
+ ContextMenuPrimitive.SeparatorRef,
217
+ ContextMenuPrimitive.SeparatorProps
218
+ >(({ className, ...props }, ref) => (
219
+ <ContextMenuPrimitive.Separator
220
+ ref={ref}
221
+ className={cn("-mx-1 my-1 h-px bg-border", className)}
222
+ {...props}
223
+ />
224
+ ));
225
+ ContextMenuSeparator.displayName = ContextMenuPrimitive.Separator.displayName;
226
+
227
+ const ContextMenuShortcut = ({ className, ...props }: TextProps) => {
228
+ return (
229
+ <Text
230
+ className={cn(
231
+ "ml-auto text-xs native:text-sm tracking-widest text-muted-foreground",
232
+ className
233
+ )}
234
+ {...props}
235
+ />
236
+ );
237
+ };
238
+ ContextMenuShortcut.displayName = "ContextMenuShortcut";
239
+
240
+ export {
241
+ ContextMenu,
242
+ ContextMenuCheckboxItem,
243
+ ContextMenuContent,
244
+ ContextMenuGroup,
245
+ ContextMenuItem,
246
+ ContextMenuLabel,
247
+ ContextMenuRadioGroup,
248
+ ContextMenuRadioItem,
249
+ ContextMenuSeparator,
250
+ ContextMenuShortcut,
251
+ ContextMenuSub,
252
+ ContextMenuSubContent,
253
+ ContextMenuSubTrigger,
254
+ ContextMenuTrigger
255
+ };