@gv-tech/ui-native 2.23.3 → 2.25.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 (67) hide show
  1. package/dist/__contracts.d.ts +2 -0
  2. package/dist/__contracts.d.ts.map +1 -0
  3. package/dist/accordion.d.ts +4 -4
  4. package/dist/accordion.d.ts.map +1 -1
  5. package/dist/alert-dialog.d.ts +6 -6
  6. package/dist/alert-dialog.d.ts.map +1 -1
  7. package/dist/avatar.d.ts +3 -3
  8. package/dist/avatar.d.ts.map +1 -1
  9. package/dist/button.d.ts +2 -2
  10. package/dist/button.d.ts.map +1 -1
  11. package/dist/calendar.d.ts +111 -1
  12. package/dist/calendar.d.ts.map +1 -1
  13. package/dist/combobox.d.ts +17 -10
  14. package/dist/combobox.d.ts.map +1 -1
  15. package/dist/dialog.d.ts +4 -4
  16. package/dist/dialog.d.ts.map +1 -1
  17. package/dist/drawer.d.ts +1 -1
  18. package/dist/drawer.d.ts.map +1 -1
  19. package/dist/form.d.ts +3 -1
  20. package/dist/form.d.ts.map +1 -1
  21. package/dist/hooks/use-theme.d.ts +1 -1
  22. package/dist/sheet.d.ts +4 -4
  23. package/dist/sheet.d.ts.map +1 -1
  24. package/dist/theme-toggle.d.ts.map +1 -1
  25. package/dist/tooltip.d.ts +1 -1
  26. package/dist/tooltip.d.ts.map +1 -1
  27. package/dist/ui-native.cjs +2 -2
  28. package/dist/ui-native.esm.js +1086 -945
  29. package/package.json +2 -1
  30. package/src/__contracts.ts +880 -0
  31. package/src/accordion.tsx +10 -10
  32. package/src/alert-dialog.tsx +12 -12
  33. package/src/alert.tsx +3 -3
  34. package/src/avatar.tsx +6 -6
  35. package/src/button.tsx +5 -1
  36. package/src/calendar.tsx +52 -3
  37. package/src/card.tsx +6 -6
  38. package/src/carousel.tsx +2 -2
  39. package/src/checkbox.tsx +1 -1
  40. package/src/combobox.tsx +190 -27
  41. package/src/context-menu.tsx +9 -9
  42. package/src/dialog.tsx +76 -29
  43. package/src/drawer.tsx +12 -12
  44. package/src/dropdown-menu.tsx +11 -11
  45. package/src/form.tsx +6 -6
  46. package/src/hover-card.tsx +1 -1
  47. package/src/input.tsx +1 -1
  48. package/src/label.tsx +1 -1
  49. package/src/menubar.tsx +17 -17
  50. package/src/navigation-menu.tsx +8 -8
  51. package/src/popover.tsx +4 -4
  52. package/src/progress.tsx +1 -1
  53. package/src/radio-group.tsx +2 -2
  54. package/src/search.tsx +1 -1
  55. package/src/select.tsx +7 -7
  56. package/src/separator.tsx +1 -1
  57. package/src/sheet.tsx +4 -4
  58. package/src/switch.tsx +1 -1
  59. package/src/table.tsx +8 -8
  60. package/src/tabs.tsx +4 -4
  61. package/src/text.tsx +1 -1
  62. package/src/textarea.tsx +1 -1
  63. package/src/theme-toggle.tsx +16 -13
  64. package/src/toast.tsx +5 -5
  65. package/src/toggle-group.tsx +2 -2
  66. package/src/toggle.tsx +1 -1
  67. package/src/tooltip.tsx +2 -2
package/src/accordion.tsx CHANGED
@@ -13,9 +13,9 @@ import Animated, {
13
13
  import { cn } from './lib/utils';
14
14
 
15
15
  const Accordion: React.ForwardRefExoticComponent<
16
- AccordionProps & React.RefAttributes<React.ElementRef<typeof AccordionPrimitive.Root>>
16
+ AccordionProps & React.RefAttributes<React.ComponentRef<typeof AccordionPrimitive.Root>>
17
17
  > = React.forwardRef<
18
- React.ElementRef<typeof AccordionPrimitive.Root>,
18
+ React.ComponentRef<typeof AccordionPrimitive.Root>,
19
19
  React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Root>
20
20
  >(({ className, ...props }, ref) => {
21
21
  return <AccordionPrimitive.Root ref={ref} className={cn('web:gap-0', className)} {...props} />;
@@ -23,9 +23,9 @@ const Accordion: React.ForwardRefExoticComponent<
23
23
  Accordion.displayName = AccordionPrimitive.Root?.displayName || 'Accordion';
24
24
 
25
25
  const AccordionItem: React.ForwardRefExoticComponent<
26
- AccordionItemProps & React.RefAttributes<React.ElementRef<typeof AccordionPrimitive.Item>>
26
+ AccordionItemProps & React.RefAttributes<React.ComponentRef<typeof AccordionPrimitive.Item>>
27
27
  > = React.forwardRef<
28
- React.ElementRef<typeof AccordionPrimitive.Item>,
28
+ React.ComponentRef<typeof AccordionPrimitive.Item>,
29
29
  React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>
30
30
  >(({ className, ...props }, ref) => {
31
31
  return (
@@ -35,9 +35,9 @@ const AccordionItem: React.ForwardRefExoticComponent<
35
35
  AccordionItem.displayName = AccordionPrimitive.Item?.displayName || 'AccordionItem';
36
36
 
37
37
  const AccordionHeader: React.ForwardRefExoticComponent<
38
- AccordionHeaderProps & React.RefAttributes<React.ElementRef<typeof AccordionPrimitive.Header>>
38
+ AccordionHeaderProps & React.RefAttributes<React.ComponentRef<typeof AccordionPrimitive.Header>>
39
39
  > = React.forwardRef<
40
- React.ElementRef<typeof AccordionPrimitive.Header>,
40
+ React.ComponentRef<typeof AccordionPrimitive.Header>,
41
41
  React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Header>
42
42
  >(({ className, ...props }, ref) => {
43
43
  return <AccordionPrimitive.Header ref={ref} className={cn('flex flex-row', className)} {...props} />;
@@ -45,9 +45,9 @@ const AccordionHeader: React.ForwardRefExoticComponent<
45
45
  AccordionHeader.displayName = AccordionPrimitive.Header?.displayName || 'AccordionHeader';
46
46
 
47
47
  const AccordionTrigger: React.ForwardRefExoticComponent<
48
- AccordionTriggerProps & React.RefAttributes<React.ElementRef<typeof AccordionPrimitive.Trigger>>
48
+ AccordionTriggerProps & React.RefAttributes<React.ComponentRef<typeof AccordionPrimitive.Trigger>>
49
49
  > = React.forwardRef<
50
- React.ElementRef<typeof AccordionPrimitive.Trigger>,
50
+ React.ComponentRef<typeof AccordionPrimitive.Trigger>,
51
51
  React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>
52
52
  >(({ className, children, ...props }, ref) => {
53
53
  const { isExpanded } = AccordionPrimitive.useItemContext();
@@ -80,9 +80,9 @@ const AccordionTrigger: React.ForwardRefExoticComponent<
80
80
  AccordionTrigger.displayName = AccordionPrimitive.Trigger?.displayName || 'AccordionTrigger';
81
81
 
82
82
  const AccordionContent: React.ForwardRefExoticComponent<
83
- AccordionContentProps & React.RefAttributes<React.ElementRef<typeof AccordionPrimitive.Content>>
83
+ AccordionContentProps & React.RefAttributes<React.ComponentRef<typeof AccordionPrimitive.Content>>
84
84
  > = React.forwardRef<
85
- React.ElementRef<typeof AccordionPrimitive.Content>,
85
+ React.ComponentRef<typeof AccordionPrimitive.Content>,
86
86
  React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>
87
87
  >(({ className, children, ...props }, ref) => {
88
88
  return (
@@ -13,9 +13,9 @@ const AlertDialogTrigger = AlertDialogPrimitive.Trigger;
13
13
  const AlertDialogPortal = AlertDialogPrimitive.Portal;
14
14
 
15
15
  const AlertDialogOverlay: React.ForwardRefExoticComponent<
16
- AlertDialogOverlayProps & React.RefAttributes<React.ElementRef<typeof AlertDialogPrimitive.Overlay>>
16
+ AlertDialogOverlayProps & React.RefAttributes<React.ComponentRef<typeof AlertDialogPrimitive.Overlay>>
17
17
  > = React.forwardRef<
18
- React.ElementRef<typeof AlertDialogPrimitive.Overlay>,
18
+ React.ComponentRef<typeof AlertDialogPrimitive.Overlay>,
19
19
  React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>
20
20
  >(({ className, ...props }, ref) => {
21
21
  return (
@@ -31,9 +31,9 @@ const AlertDialogOverlay: React.ForwardRefExoticComponent<
31
31
  AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay?.displayName || 'AlertDialogOverlay';
32
32
 
33
33
  const AlertDialogContent: React.ForwardRefExoticComponent<
34
- AlertDialogContentProps & React.RefAttributes<React.ElementRef<typeof AlertDialogPrimitive.Content>>
34
+ AlertDialogContentProps & React.RefAttributes<React.ComponentRef<typeof AlertDialogPrimitive.Content>>
35
35
  > = React.forwardRef<
36
- React.ElementRef<typeof AlertDialogPrimitive.Content>,
36
+ React.ComponentRef<typeof AlertDialogPrimitive.Content>,
37
37
  React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content> & {
38
38
  portalHost?: string;
39
39
  overlayClassName?: string;
@@ -69,9 +69,9 @@ const AlertDialogFooter = ({ className, ...props }: React.ComponentPropsWithoutR
69
69
  AlertDialogFooter.displayName = 'AlertDialogFooter';
70
70
 
71
71
  const AlertDialogTitle: React.ForwardRefExoticComponent<
72
- AlertDialogTitleProps & React.RefAttributes<React.ElementRef<typeof AlertDialogPrimitive.Title>>
72
+ AlertDialogTitleProps & React.RefAttributes<React.ComponentRef<typeof AlertDialogPrimitive.Title>>
73
73
  > = React.forwardRef<
74
- React.ElementRef<typeof AlertDialogPrimitive.Title>,
74
+ React.ComponentRef<typeof AlertDialogPrimitive.Title>,
75
75
  React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>
76
76
  >(({ className, ...props }, ref) => (
77
77
  <AlertDialogPrimitive.Title
@@ -83,9 +83,9 @@ const AlertDialogTitle: React.ForwardRefExoticComponent<
83
83
  AlertDialogTitle.displayName = AlertDialogPrimitive.Title?.displayName || 'AlertDialogTitle';
84
84
 
85
85
  const AlertDialogDescription: React.ForwardRefExoticComponent<
86
- AlertDialogDescriptionProps & React.RefAttributes<React.ElementRef<typeof AlertDialogPrimitive.Description>>
86
+ AlertDialogDescriptionProps & React.RefAttributes<React.ComponentRef<typeof AlertDialogPrimitive.Description>>
87
87
  > = React.forwardRef<
88
- React.ElementRef<typeof AlertDialogPrimitive.Description>,
88
+ React.ComponentRef<typeof AlertDialogPrimitive.Description>,
89
89
  React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>
90
90
  >(({ className, ...props }, ref) => (
91
91
  <AlertDialogPrimitive.Description
@@ -97,9 +97,9 @@ const AlertDialogDescription: React.ForwardRefExoticComponent<
97
97
  AlertDialogDescription.displayName = AlertDialogPrimitive.Description?.displayName || 'AlertDialogDescription';
98
98
 
99
99
  const AlertDialogAction: React.ForwardRefExoticComponent<
100
- AlertDialogActionProps & React.RefAttributes<React.ElementRef<typeof AlertDialogPrimitive.Action>>
100
+ AlertDialogActionProps & React.RefAttributes<React.ComponentRef<typeof AlertDialogPrimitive.Action>>
101
101
  > = React.forwardRef<
102
- React.ElementRef<typeof AlertDialogPrimitive.Action>,
102
+ React.ComponentRef<typeof AlertDialogPrimitive.Action>,
103
103
  React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action>
104
104
  >(({ className, ...props }, ref) => (
105
105
  <AlertDialogPrimitive.Action ref={ref} className={cn(buttonVariants(), className)} {...props} />
@@ -107,9 +107,9 @@ const AlertDialogAction: React.ForwardRefExoticComponent<
107
107
  AlertDialogAction.displayName = AlertDialogPrimitive.Action?.displayName || 'AlertDialogAction';
108
108
 
109
109
  const AlertDialogCancel: React.ForwardRefExoticComponent<
110
- AlertDialogCancelProps & React.RefAttributes<React.ElementRef<typeof AlertDialogPrimitive.Cancel>>
110
+ AlertDialogCancelProps & React.RefAttributes<React.ComponentRef<typeof AlertDialogPrimitive.Cancel>>
111
111
  > = React.forwardRef<
112
- React.ElementRef<typeof AlertDialogPrimitive.Cancel>,
112
+ React.ComponentRef<typeof AlertDialogPrimitive.Cancel>,
113
113
  React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel>
114
114
  >(({ className, ...props }, ref) => (
115
115
  <AlertDialogPrimitive.Cancel
package/src/alert.tsx CHANGED
@@ -20,7 +20,7 @@ const alertVariants = cva('relative w-full rounded-lg border p-4', {
20
20
  });
21
21
 
22
22
  const Alert = React.forwardRef<
23
- React.ElementRef<typeof View>,
23
+ React.ComponentRef<typeof View>,
24
24
  React.ComponentPropsWithoutRef<typeof View> & VariantProps<typeof alertVariants>
25
25
  >(({ className, variant, children, ...props }, ref) => (
26
26
  <View ref={ref} className={cn(alertVariants({ variant }), className)} {...props}>
@@ -29,7 +29,7 @@ const Alert = React.forwardRef<
29
29
  ));
30
30
  Alert.displayName = 'Alert';
31
31
 
32
- const AlertTitle = React.forwardRef<React.ElementRef<typeof Text>, React.ComponentPropsWithoutRef<typeof Text>>(
32
+ const AlertTitle = React.forwardRef<React.ComponentRef<typeof Text>, React.ComponentPropsWithoutRef<typeof Text>>(
33
33
  ({ className, ...props }, ref) => (
34
34
  <Text
35
35
  ref={ref}
@@ -40,7 +40,7 @@ const AlertTitle = React.forwardRef<React.ElementRef<typeof Text>, React.Compone
40
40
  );
41
41
  AlertTitle.displayName = 'AlertTitle';
42
42
 
43
- const AlertDescription = React.forwardRef<React.ElementRef<typeof Text>, React.ComponentPropsWithoutRef<typeof Text>>(
43
+ const AlertDescription = React.forwardRef<React.ComponentRef<typeof Text>, React.ComponentPropsWithoutRef<typeof Text>>(
44
44
  ({ className, ...props }, ref) => (
45
45
  <Text ref={ref} className={cn('text-muted-foreground text-sm leading-relaxed', className)} {...props} />
46
46
  ),
package/src/avatar.tsx CHANGED
@@ -4,9 +4,9 @@ import * as React from 'react';
4
4
  import { cn } from './lib/utils';
5
5
 
6
6
  const Avatar: React.ForwardRefExoticComponent<
7
- AvatarProps & React.RefAttributes<React.ElementRef<typeof AvatarPrimitive.Root>>
7
+ AvatarProps & React.RefAttributes<React.ComponentRef<typeof AvatarPrimitive.Root>>
8
8
  > = React.forwardRef<
9
- React.ElementRef<typeof AvatarPrimitive.Root>,
9
+ React.ComponentRef<typeof AvatarPrimitive.Root>,
10
10
  React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>
11
11
  >(({ className, ...props }, ref) => (
12
12
  <AvatarPrimitive.Root
@@ -18,9 +18,9 @@ const Avatar: React.ForwardRefExoticComponent<
18
18
  Avatar.displayName = AvatarPrimitive.Root?.displayName || 'Avatar';
19
19
 
20
20
  const AvatarImage: React.ForwardRefExoticComponent<
21
- AvatarImageProps & React.RefAttributes<React.ElementRef<typeof AvatarPrimitive.Image>>
21
+ AvatarImageProps & React.RefAttributes<React.ComponentRef<typeof AvatarPrimitive.Image>>
22
22
  > = React.forwardRef<
23
- React.ElementRef<typeof AvatarPrimitive.Image>,
23
+ React.ComponentRef<typeof AvatarPrimitive.Image>,
24
24
  React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>
25
25
  >(({ className, ...props }, ref) => (
26
26
  <AvatarPrimitive.Image ref={ref} className={cn('aspect-square h-full w-full', className)} {...props} />
@@ -28,9 +28,9 @@ const AvatarImage: React.ForwardRefExoticComponent<
28
28
  AvatarImage.displayName = AvatarPrimitive.Image?.displayName || 'AvatarImage';
29
29
 
30
30
  const AvatarFallback: React.ForwardRefExoticComponent<
31
- AvatarFallbackProps & React.RefAttributes<React.ElementRef<typeof AvatarPrimitive.Fallback>>
31
+ AvatarFallbackProps & React.RefAttributes<React.ComponentRef<typeof AvatarPrimitive.Fallback>>
32
32
  > = React.forwardRef<
33
- React.ElementRef<typeof AvatarPrimitive.Fallback>,
33
+ React.ComponentRef<typeof AvatarPrimitive.Fallback>,
34
34
  React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>
35
35
  >(({ className, ...props }, ref) => (
36
36
  <AvatarPrimitive.Fallback
package/src/button.tsx CHANGED
@@ -20,9 +20,13 @@ const buttonVariants = cva(
20
20
  },
21
21
  size: {
22
22
  default: 'h-10 px-4 py-2',
23
+ xs: 'h-7 px-2',
23
24
  sm: 'h-9 px-3',
24
25
  lg: 'h-12 px-8',
25
26
  icon: 'h-10 w-10',
27
+ 'icon-xs': 'h-7 w-7',
28
+ 'icon-sm': 'h-9 w-9',
29
+ 'icon-lg': 'h-12 w-12',
26
30
  },
27
31
  },
28
32
  defaultVariants: {
@@ -50,7 +54,7 @@ const buttonTextVariants = cva('text-sm font-medium', {
50
54
 
51
55
  export interface ButtonProps extends ButtonBaseProps {
52
56
  variant?: 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link' | null;
53
- size?: 'default' | 'sm' | 'lg' | 'icon' | null;
57
+ size?: 'default' | 'xs' | 'sm' | 'lg' | 'icon' | 'icon-xs' | 'icon-sm' | 'icon-lg' | null;
54
58
  onPress?: () => void;
55
59
  }
56
60
 
package/src/calendar.tsx CHANGED
@@ -1,7 +1,56 @@
1
1
  import type { CalendarBaseProps } from '@gv-tech/ui-core';
2
+ import DateTimePicker from '@react-native-community/datetimepicker';
2
3
  import * as React from 'react';
3
4
  import { View } from 'react-native';
5
+ import { cn } from './lib/utils';
4
6
 
5
- export const Calendar: React.FC<CalendarBaseProps> = ({ className }) => {
6
- return <View className={className} />;
7
- };
7
+ export type CalendarProps = Omit<
8
+ React.ComponentProps<typeof DateTimePicker>,
9
+ 'value' | 'className' | 'display' | 'minuteInterval'
10
+ > &
11
+ CalendarBaseProps & {
12
+ value?: Date;
13
+ onChange?: (event: unknown, date?: Date) => void;
14
+ };
15
+
16
+ export const Calendar = React.forwardRef<View, CalendarProps>(
17
+ ({ className, value, onChange, showOutsideDays, ...props }, ref) => {
18
+ // If no value is provided, default to current date so the picker doesn't crash
19
+ const [date, setDate] = React.useState<Date>(value || new Date());
20
+
21
+ // Sync internal state if external value changes
22
+ React.useEffect(() => {
23
+ if (value) {
24
+ setDate(value);
25
+ }
26
+ }, [value]);
27
+
28
+ const handleValueChange = (event: unknown, selectedDate: Date) => {
29
+ setDate(selectedDate);
30
+ if (onChange) {
31
+ onChange(event, selectedDate);
32
+ }
33
+ };
34
+
35
+ const handleDismiss = () => {
36
+ if (onChange) {
37
+ onChange({ type: 'dismissed' }, date);
38
+ }
39
+ };
40
+
41
+ return (
42
+ <View ref={ref} className={cn('bg-background overflow-hidden rounded-md', className)}>
43
+ <DateTimePicker
44
+ value={date}
45
+ mode="date"
46
+ display="inline"
47
+ onValueChange={handleValueChange}
48
+ onDismiss={handleDismiss}
49
+ {...props}
50
+ />
51
+ </View>
52
+ );
53
+ },
54
+ );
55
+
56
+ Calendar.displayName = 'Calendar';
package/src/card.tsx CHANGED
@@ -7,19 +7,19 @@ import { cn } from './lib/utils';
7
7
 
8
8
  export interface CardProps extends React.ComponentPropsWithoutRef<typeof View>, CardBaseProps {}
9
9
 
10
- const Card = React.forwardRef<React.ElementRef<typeof View>, CardProps>(({ className, ...props }, ref) => (
10
+ const Card = React.forwardRef<React.ComponentRef<typeof View>, CardProps>(({ className, ...props }, ref) => (
11
11
  <View ref={ref} className={cn('border-border bg-card rounded-xl border shadow-sm', className)} {...props} />
12
12
  ));
13
13
  Card.displayName = 'Card';
14
14
 
15
- const CardHeader = React.forwardRef<React.ElementRef<typeof View>, React.ComponentPropsWithoutRef<typeof View>>(
15
+ const CardHeader = React.forwardRef<React.ComponentRef<typeof View>, React.ComponentPropsWithoutRef<typeof View>>(
16
16
  ({ className, ...props }, ref) => (
17
17
  <View ref={ref} className={cn('flex flex-col space-y-1.5 p-6', className)} {...props} />
18
18
  ),
19
19
  );
20
20
  CardHeader.displayName = 'CardHeader';
21
21
 
22
- const CardTitle = React.forwardRef<React.ElementRef<typeof Text>, React.ComponentPropsWithoutRef<typeof Text>>(
22
+ const CardTitle = React.forwardRef<React.ComponentRef<typeof Text>, React.ComponentPropsWithoutRef<typeof Text>>(
23
23
  ({ className, ...props }, ref) => (
24
24
  <Text
25
25
  ref={ref}
@@ -30,14 +30,14 @@ const CardTitle = React.forwardRef<React.ElementRef<typeof Text>, React.Componen
30
30
  );
31
31
  CardTitle.displayName = 'CardTitle';
32
32
 
33
- const CardDescription = React.forwardRef<React.ElementRef<typeof Text>, React.ComponentPropsWithoutRef<typeof Text>>(
33
+ const CardDescription = React.forwardRef<React.ComponentRef<typeof Text>, React.ComponentPropsWithoutRef<typeof Text>>(
34
34
  ({ className, ...props }, ref) => (
35
35
  <Text ref={ref} className={cn('text-muted-foreground text-sm', className)} {...props} />
36
36
  ),
37
37
  );
38
38
  CardDescription.displayName = 'CardDescription';
39
39
 
40
- const CardContent = React.forwardRef<React.ElementRef<typeof View>, React.ComponentPropsWithoutRef<typeof View>>(
40
+ const CardContent = React.forwardRef<React.ComponentRef<typeof View>, React.ComponentPropsWithoutRef<typeof View>>(
41
41
  ({ className, ...props }, ref) => (
42
42
  <View ref={ref} className={cn('p-6 pt-0', className)} {...props}>
43
43
  {wrapTextChildren(props.children, Text, { className: 'text-sm text-card-foreground' })}
@@ -46,7 +46,7 @@ const CardContent = React.forwardRef<React.ElementRef<typeof View>, React.Compon
46
46
  );
47
47
  CardContent.displayName = 'CardContent';
48
48
 
49
- const CardFooter = React.forwardRef<React.ElementRef<typeof View>, React.ComponentPropsWithoutRef<typeof View>>(
49
+ const CardFooter = React.forwardRef<React.ComponentRef<typeof View>, React.ComponentPropsWithoutRef<typeof View>>(
50
50
  ({ className, ...props }, ref) => (
51
51
  <View ref={ref} className={cn('flex flex-row items-center p-6 pt-0', className)} {...props} />
52
52
  ),
package/src/carousel.tsx CHANGED
@@ -151,7 +151,7 @@ export const CarouselItem = React.forwardRef<View, CarouselItemBaseProps>(({ chi
151
151
  });
152
152
  CarouselItem.displayName = 'CarouselItem';
153
153
 
154
- export const CarouselPrevious = React.forwardRef<React.ElementRef<typeof Button>, CarouselPreviousBaseProps>(
154
+ export const CarouselPrevious = React.forwardRef<React.ComponentRef<typeof Button>, CarouselPreviousBaseProps>(
155
155
  ({ className, variant = 'outline', size = 'icon', ...props }, ref) => {
156
156
  const { orientation, scrollPrev, canScrollPrev } = useCarousel();
157
157
 
@@ -178,7 +178,7 @@ export const CarouselPrevious = React.forwardRef<React.ElementRef<typeof Button>
178
178
  );
179
179
  CarouselPrevious.displayName = 'CarouselPrevious';
180
180
 
181
- export const CarouselNext = React.forwardRef<React.ElementRef<typeof Button>, CarouselNextBaseProps>(
181
+ export const CarouselNext = React.forwardRef<React.ComponentRef<typeof Button>, CarouselNextBaseProps>(
182
182
  ({ className, variant = 'outline', size = 'icon', ...props }, ref) => {
183
183
  const { orientation, scrollNext, canScrollNext } = useCarousel();
184
184
 
package/src/checkbox.tsx CHANGED
@@ -6,7 +6,7 @@ import { Platform } from 'react-native';
6
6
  import { cn } from './lib/utils';
7
7
 
8
8
  const Checkbox = React.forwardRef<
9
- React.ElementRef<typeof CheckboxPrimitive.Root>,
9
+ React.ComponentRef<typeof CheckboxPrimitive.Root>,
10
10
  React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>
11
11
  >(({ className, ...props }, ref) => {
12
12
  return (
package/src/combobox.tsx CHANGED
@@ -15,37 +15,126 @@ import type {
15
15
  ComboboxTriggerBaseProps,
16
16
  ComboboxValueBaseProps,
17
17
  } from '@gv-tech/ui-core';
18
+ import { Check, ChevronDown, X } from 'lucide-react-native';
18
19
  import * as React from 'react';
19
- import { Text, View } from 'react-native';
20
+ import { Pressable, TextInput, View } from 'react-native';
21
+ import { Dialog, DialogContent, DialogTrigger } from './dialog';
22
+ import { wrapTextChildren } from './lib/render-native';
20
23
  import { cn } from './lib/utils';
24
+ import { Text } from './text';
25
+
26
+ // Context to share state across compound components
27
+ const ComboboxContext = React.createContext<{
28
+ open: boolean;
29
+ setOpen: (open: boolean) => void;
30
+ value: string;
31
+ setValue: (value: string) => void;
32
+ searchQuery: string;
33
+ setSearchQuery: (query: string) => void;
34
+ } | null>(null);
35
+
36
+ function useCombobox() {
37
+ const context = React.useContext(ComboboxContext);
38
+ if (!context) {
39
+ throw new Error('Combobox components must be rendered within a Combobox provider');
40
+ }
41
+ return context;
42
+ }
43
+
44
+ export interface ComboboxProps extends React.ComponentProps<typeof View> {
45
+ value?: string;
46
+ onValueChange?: (value: string) => void;
47
+ }
48
+
49
+ function Combobox({ className, value: controlledValue, onValueChange, ...props }: ComboboxProps) {
50
+ const [open, setOpen] = React.useState(false);
51
+ const [internalValue, setInternalValue] = React.useState(controlledValue || '');
52
+ const [searchQuery, setSearchQuery] = React.useState('');
53
+
54
+ const value = controlledValue !== undefined ? controlledValue : internalValue;
55
+ const setValue = (newValue: string) => {
56
+ setInternalValue(newValue);
57
+ onValueChange?.(newValue);
58
+ setOpen(false);
59
+ };
21
60
 
22
- function Combobox({ className, ...props }: React.ComponentProps<typeof View>) {
23
61
  return (
24
- <View className={cn('border-destructive/50 rounded-md border border-dashed p-4', className)} {...props}>
25
- <Text className="text-destructive font-mono text-xs">Combobox (Not Implemented)</Text>
26
- </View>
62
+ <ComboboxContext.Provider value={{ open, setOpen, value, setValue, searchQuery, setSearchQuery }}>
63
+ <Dialog open={open} onOpenChange={setOpen}>
64
+ <View className={cn('relative', className)} {...props} />
65
+ </Dialog>
66
+ </ComboboxContext.Provider>
27
67
  );
28
68
  }
29
69
 
30
- function ComboboxValue({ className, ...props }: React.ComponentProps<typeof View> & ComboboxValueBaseProps) {
31
- return <View className={className} {...props} />;
70
+ function ComboboxValue({ className, children, ...props }: React.ComponentProps<typeof View> & ComboboxValueBaseProps) {
71
+ const { value } = useCombobox();
72
+ return (
73
+ <View className={className} {...props}>
74
+ <Text className="text-sm">{children || value || 'Select an item...'}</Text>
75
+ </View>
76
+ );
32
77
  }
33
78
 
34
- function ComboboxTrigger({ className, ...props }: React.ComponentProps<typeof View> & ComboboxTriggerBaseProps) {
35
- return <View className={className} {...props} />;
79
+ function ComboboxTrigger({
80
+ className,
81
+ children,
82
+ ...props
83
+ }: React.ComponentProps<typeof Pressable> & ComboboxTriggerBaseProps) {
84
+ return (
85
+ <DialogTrigger asChild>
86
+ <Pressable
87
+ className={cn(
88
+ 'border-input bg-background text-foreground flex h-10 w-full flex-row items-center justify-between rounded-md border px-3 py-2 text-sm',
89
+ className,
90
+ )}
91
+ {...props}
92
+ >
93
+ <View className="flex-1 flex-row items-center">{wrapTextChildren(children, Text)}</View>
94
+ <ChevronDown size={16} className="text-muted-foreground opacity-50" />
95
+ </Pressable>
96
+ </DialogTrigger>
97
+ );
36
98
  }
37
99
 
38
- function ComboboxClear({ className, ...props }: React.ComponentProps<typeof View> & ComboboxClearBaseProps) {
39
- return <View className={className} {...props} />;
100
+ function ComboboxClear({
101
+ className,
102
+ children,
103
+ ...props
104
+ }: React.ComponentProps<typeof Pressable> & ComboboxClearBaseProps) {
105
+ const { setValue } = useCombobox();
106
+ return (
107
+ <Pressable
108
+ className={cn('flex items-center justify-center p-1', className)}
109
+ onPress={() => setValue('')}
110
+ {...props}
111
+ >
112
+ {children || <X size={14} className="text-muted-foreground" />}
113
+ </Pressable>
114
+ );
40
115
  }
41
116
 
42
117
  function ComboboxInput({
43
118
  className,
44
119
  showClear,
45
120
  showTrigger,
121
+ placeholder = 'Search...',
46
122
  ...props
47
- }: React.ComponentProps<typeof View> & ComboboxInputBaseProps) {
48
- return <View className={className} {...props} />;
123
+ }: React.ComponentProps<typeof TextInput> & ComboboxInputBaseProps) {
124
+ const { searchQuery, setSearchQuery } = useCombobox();
125
+ return (
126
+ <View className="border-border flex flex-row items-center border-b px-3">
127
+ <TextInput
128
+ className={cn('flex h-12 w-full rounded-md bg-transparent py-3 text-sm outline-none', className)}
129
+ placeholder={placeholder}
130
+ placeholderTextColor="#a1a1aa"
131
+ value={searchQuery}
132
+ onChangeText={setSearchQuery}
133
+ autoFocus
134
+ {...props}
135
+ />
136
+ </View>
137
+ );
49
138
  }
50
139
 
51
140
  function ComboboxContent({
@@ -57,47 +146,121 @@ function ComboboxContent({
57
146
  anchor,
58
147
  ...props
59
148
  }: React.ComponentProps<typeof View> & ComboboxContentBaseProps) {
60
- return <View className={className} {...props} />;
149
+ return (
150
+ <DialogContent className="p-0">
151
+ <View
152
+ className={cn('bg-popover flex max-h-96 w-full flex-col overflow-hidden rounded-md', className)}
153
+ {...props}
154
+ />
155
+ </DialogContent>
156
+ );
61
157
  }
62
158
 
63
159
  function ComboboxList({ className, ...props }: React.ComponentProps<typeof View> & ComboboxListBaseProps) {
64
- return <View className={className} {...props} />;
160
+ return <View className={cn('max-h-[300px] overflow-hidden', className)} {...props} />;
65
161
  }
66
162
 
67
- function ComboboxItem({ className, ...props }: React.ComponentProps<typeof View> & ComboboxItemBaseProps) {
68
- return <View className={className} {...props} />;
163
+ export type ComboboxItemProps = React.ComponentProps<typeof Pressable> &
164
+ ComboboxItemBaseProps & {
165
+ value: string;
166
+ };
167
+
168
+ function ComboboxItem({ className, children, value: itemValue, ...props }: ComboboxItemProps) {
169
+ const { value, setValue, searchQuery } = useCombobox();
170
+
171
+ // Basic filtering mechanism
172
+ const textContent = React.Children.toArray(children).join('').toLowerCase();
173
+ if (
174
+ searchQuery &&
175
+ !textContent.includes(searchQuery.toLowerCase()) &&
176
+ !itemValue.toLowerCase().includes(searchQuery.toLowerCase())
177
+ ) {
178
+ return null;
179
+ }
180
+
181
+ const isSelected = value === itemValue;
182
+
183
+ return (
184
+ <Pressable
185
+ className={cn(
186
+ 'active:bg-accent relative flex w-full flex-row items-center rounded-sm py-2.5 pr-8 pl-2 text-sm outline-none',
187
+ isSelected && 'bg-accent',
188
+ className,
189
+ )}
190
+ onPress={() => setValue(itemValue)}
191
+ {...props}
192
+ >
193
+ <View className="flex-1">
194
+ {wrapTextChildren(children, Text, { className: isSelected ? 'font-semibold' : '' })}
195
+ </View>
196
+ {isSelected && (
197
+ <View className="absolute right-2 flex h-3.5 w-3.5 items-center justify-center">
198
+ <Check size={16} className="text-foreground" />
199
+ </View>
200
+ )}
201
+ </Pressable>
202
+ );
69
203
  }
70
204
 
71
205
  function ComboboxGroup({ className, ...props }: React.ComponentProps<typeof View> & ComboboxGroupBaseProps) {
72
- return <View className={className} {...props} />;
206
+ return <View className={cn('text-foreground overflow-hidden p-1', className)} {...props} />;
73
207
  }
74
208
 
75
209
  function ComboboxLabel({ className, ...props }: React.ComponentProps<typeof View> & ComboboxLabelBaseProps) {
76
- return <View className={className} {...props} />;
210
+ return <View className={cn('text-muted-foreground px-2 py-1.5 text-xs font-semibold', className)} {...props} />;
77
211
  }
78
212
 
79
213
  function ComboboxCollection({ className, ...props }: React.ComponentProps<typeof View> & ComboboxCollectionBaseProps) {
80
214
  return <View className={className} {...props} />;
81
215
  }
82
216
 
83
- function ComboboxEmpty({ className, ...props }: React.ComponentProps<typeof View> & ComboboxEmptyBaseProps) {
84
- return <View className={className} {...props} />;
217
+ function ComboboxEmpty({ className, children, ...props }: React.ComponentProps<typeof View> & ComboboxEmptyBaseProps) {
218
+ const { searchQuery } = useCombobox();
219
+
220
+ if (!searchQuery) {
221
+ return null;
222
+ }
223
+
224
+ return (
225
+ <View className={cn('py-6 text-center text-sm', className)} {...props}>
226
+ <Text className="text-muted-foreground text-center">{children || 'No results found.'}</Text>
227
+ </View>
228
+ );
85
229
  }
86
230
 
87
231
  function ComboboxSeparator({ className, ...props }: React.ComponentProps<typeof View> & ComboboxSeparatorBaseProps) {
88
- return <View className={className} {...props} />;
232
+ return <View className={cn('bg-muted -mx-1 h-px', className)} {...props} />;
89
233
  }
90
234
 
91
235
  function ComboboxChips({ className, ...props }: React.ComponentProps<typeof View> & ComboboxChipsBaseProps) {
92
- return <View className={className} {...props} />;
236
+ return <View className={cn('flex flex-row flex-wrap gap-1', className)} {...props} />;
93
237
  }
94
238
 
95
- function ComboboxChip({ className, showRemove, ...props }: React.ComponentProps<typeof View> & ComboboxChipBaseProps) {
96
- return <View className={className} {...props} />;
239
+ function ComboboxChip({
240
+ className,
241
+ showRemove,
242
+ children,
243
+ ...props
244
+ }: React.ComponentProps<typeof View> & ComboboxChipBaseProps) {
245
+ return (
246
+ <View
247
+ className={cn(
248
+ 'bg-secondary text-secondary-foreground flex flex-row items-center rounded-md px-2 py-1',
249
+ className,
250
+ )}
251
+ {...props}
252
+ >
253
+ {wrapTextChildren(children, Text, { className: 'text-xs' })}
254
+ {showRemove && <X size={12} className="ml-1 opacity-50" />}
255
+ </View>
256
+ );
97
257
  }
98
258
 
99
- function ComboboxChipsInput({ className, ...props }: React.ComponentProps<typeof View> & ComboboxChipsInputBaseProps) {
100
- return <View className={className} {...props} />;
259
+ function ComboboxChipsInput({
260
+ className,
261
+ ...props
262
+ }: React.ComponentProps<typeof TextInput> & ComboboxChipsInputBaseProps) {
263
+ return <TextInput className={cn('flex-1 bg-transparent px-2 py-1 outline-none', className)} {...props} />;
101
264
  }
102
265
 
103
266
  function useComboboxAnchor() {