@gv-tech/ui-native 2.6.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.
- package/package.json +80 -0
- package/src/accordion.tsx +93 -0
- package/src/alert-dialog.tsx +123 -0
- package/src/alert.tsx +50 -0
- package/src/aspect-ratio.tsx +9 -0
- package/src/avatar.tsx +38 -0
- package/src/badge.tsx +51 -0
- package/src/breadcrumb.tsx +9 -0
- package/src/button.tsx +75 -0
- package/src/calendar.tsx +9 -0
- package/src/card.tsx +56 -0
- package/src/carousel.tsx +9 -0
- package/src/chart.tsx +9 -0
- package/src/checkbox.tsx +31 -0
- package/src/collapsible.tsx +15 -0
- package/src/command.tsx +9 -0
- package/src/context-menu.tsx +9 -0
- package/src/dialog.tsx +121 -0
- package/src/drawer.tsx +9 -0
- package/src/dropdown-menu.tsx +9 -0
- package/src/form.tsx +9 -0
- package/src/hover-card.tsx +9 -0
- package/src/index.ts +209 -0
- package/src/input.tsx +27 -0
- package/src/label.tsx +29 -0
- package/src/lib/render-native.tsx +17 -0
- package/src/lib/utils.ts +6 -0
- package/src/menubar.tsx +9 -0
- package/src/nativewind-env.d.ts +1 -0
- package/src/navigation-menu.tsx +9 -0
- package/src/pagination.tsx +9 -0
- package/src/popover.tsx +9 -0
- package/src/progress.tsx +9 -0
- package/src/radio-group.tsx +42 -0
- package/src/resizable.tsx +25 -0
- package/src/scroll-area.tsx +9 -0
- package/src/search.tsx +17 -0
- package/src/select.tsx +229 -0
- package/src/separator.tsx +20 -0
- package/src/sheet.tsx +127 -0
- package/src/skeleton.tsx +31 -0
- package/src/slider.tsx +9 -0
- package/src/sonner.tsx +9 -0
- package/src/switch.tsx +34 -0
- package/src/table.tsx +73 -0
- package/src/tabs.tsx +74 -0
- package/src/text.tsx +43 -0
- package/src/textarea.tsx +29 -0
- package/src/theme-provider.tsx +6 -0
- package/src/theme-toggle.tsx +11 -0
- package/src/toast.tsx +88 -0
- package/src/toaster.tsx +9 -0
- package/src/toggle-group.tsx +78 -0
- package/src/toggle.tsx +35 -0
- package/src/tooltip.tsx +44 -0
package/src/select.tsx
ADDED
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import {
|
|
2
|
+
SelectBaseProps,
|
|
3
|
+
SelectContentBaseProps,
|
|
4
|
+
SelectGroupBaseProps,
|
|
5
|
+
SelectItemBaseProps,
|
|
6
|
+
SelectLabelBaseProps,
|
|
7
|
+
SelectScrollDownButtonBaseProps,
|
|
8
|
+
SelectScrollUpButtonBaseProps,
|
|
9
|
+
SelectSeparatorBaseProps,
|
|
10
|
+
SelectTriggerBaseProps,
|
|
11
|
+
SelectValueBaseProps,
|
|
12
|
+
} from '@gv-tech/ui-core';
|
|
13
|
+
import * as SelectPrimitive from '@rn-primitives/select';
|
|
14
|
+
import { Check, ChevronDown, ChevronUp } from 'lucide-react-native';
|
|
15
|
+
import * as React from 'react';
|
|
16
|
+
import { Platform, StyleSheet, View, type ViewStyle } from 'react-native';
|
|
17
|
+
import Animated from 'react-native-reanimated';
|
|
18
|
+
|
|
19
|
+
import { cn } from './lib/utils';
|
|
20
|
+
|
|
21
|
+
export interface SelectProps
|
|
22
|
+
extends
|
|
23
|
+
Omit<
|
|
24
|
+
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Root>,
|
|
25
|
+
'value' | 'defaultValue' | 'onValueChange' | 'disabled'
|
|
26
|
+
>,
|
|
27
|
+
SelectBaseProps {}
|
|
28
|
+
|
|
29
|
+
const Select = SelectPrimitive.Root;
|
|
30
|
+
|
|
31
|
+
export interface SelectGroupProps
|
|
32
|
+
extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Group>, SelectGroupBaseProps {}
|
|
33
|
+
|
|
34
|
+
const SelectGroup = SelectPrimitive.Group;
|
|
35
|
+
|
|
36
|
+
export interface SelectValueProps
|
|
37
|
+
extends Omit<React.ComponentPropsWithoutRef<typeof SelectPrimitive.Value>, 'placeholder'>, SelectValueBaseProps {}
|
|
38
|
+
|
|
39
|
+
const SelectValue = SelectPrimitive.Value;
|
|
40
|
+
|
|
41
|
+
export interface SelectTriggerProps
|
|
42
|
+
extends
|
|
43
|
+
Omit<React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>, 'children' | 'disabled'>,
|
|
44
|
+
SelectTriggerBaseProps {}
|
|
45
|
+
|
|
46
|
+
const SelectTrigger = React.forwardRef<React.ElementRef<typeof SelectPrimitive.Trigger>, SelectTriggerProps>(
|
|
47
|
+
({ className, children, ...props }, ref) => (
|
|
48
|
+
<SelectPrimitive.Trigger
|
|
49
|
+
ref={ref}
|
|
50
|
+
className={cn(
|
|
51
|
+
'flex flex-row h-10 native:h-12 items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm text-muted-foreground web:ring-offset-background web:focus:outline-none web:focus:ring-2 web:focus:ring-ring web:focus:ring-offset-2 [&>span]:line-clamp-1',
|
|
52
|
+
props.disabled && 'web:cursor-not-allowed opacity-50',
|
|
53
|
+
className,
|
|
54
|
+
)}
|
|
55
|
+
{...props}
|
|
56
|
+
>
|
|
57
|
+
<>{children}</>
|
|
58
|
+
<ChevronDown size={16} aria-hidden={true} className="text-foreground opacity-50" />
|
|
59
|
+
</SelectPrimitive.Trigger>
|
|
60
|
+
),
|
|
61
|
+
);
|
|
62
|
+
SelectTrigger.displayName = SelectPrimitive.Trigger?.displayName || 'SelectTrigger';
|
|
63
|
+
|
|
64
|
+
export interface SelectScrollUpButtonProps
|
|
65
|
+
extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>, SelectScrollUpButtonBaseProps {}
|
|
66
|
+
|
|
67
|
+
const SelectScrollUpButton = React.forwardRef<
|
|
68
|
+
React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,
|
|
69
|
+
SelectScrollUpButtonProps
|
|
70
|
+
>(({ className, ...props }, ref) => (
|
|
71
|
+
<SelectPrimitive.ScrollUpButton
|
|
72
|
+
// @ts-expect-error TODO: fix type
|
|
73
|
+
ref={ref}
|
|
74
|
+
className={cn('flex cursor-default items-center justify-center py-1', className)}
|
|
75
|
+
{...props}
|
|
76
|
+
>
|
|
77
|
+
<ChevronUp size={14} className="text-foreground" />
|
|
78
|
+
</SelectPrimitive.ScrollUpButton>
|
|
79
|
+
));
|
|
80
|
+
SelectScrollUpButton.displayName =
|
|
81
|
+
((SelectPrimitive.ScrollUpButton as unknown as Record<string, unknown>)?.displayName as string | undefined) ||
|
|
82
|
+
'SelectScrollUpButton';
|
|
83
|
+
|
|
84
|
+
export interface SelectScrollDownButtonProps
|
|
85
|
+
extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>, SelectScrollDownButtonBaseProps {}
|
|
86
|
+
|
|
87
|
+
const SelectScrollDownButton = React.forwardRef<
|
|
88
|
+
React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,
|
|
89
|
+
SelectScrollDownButtonProps
|
|
90
|
+
>(({ className, ...props }, ref) => (
|
|
91
|
+
<SelectPrimitive.ScrollDownButton
|
|
92
|
+
// @ts-expect-error TODO: fix type
|
|
93
|
+
ref={ref}
|
|
94
|
+
className={cn('flex cursor-default items-center justify-center py-1', className)}
|
|
95
|
+
{...props}
|
|
96
|
+
>
|
|
97
|
+
<ChevronDown size={14} className="text-foreground" />
|
|
98
|
+
</SelectPrimitive.ScrollDownButton>
|
|
99
|
+
));
|
|
100
|
+
|
|
101
|
+
SelectScrollDownButton.displayName =
|
|
102
|
+
((SelectPrimitive.ScrollDownButton as unknown as Record<string, unknown>)?.displayName as string | undefined) ||
|
|
103
|
+
'SelectScrollDownButton';
|
|
104
|
+
|
|
105
|
+
export interface SelectContentProps
|
|
106
|
+
extends Omit<React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>, 'position'>, SelectContentBaseProps {
|
|
107
|
+
portalHost?: string;
|
|
108
|
+
overlayClassName?: string;
|
|
109
|
+
overlayStyle?: ViewStyle;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const SelectContent = React.forwardRef<React.ElementRef<typeof SelectPrimitive.Content>, SelectContentProps>(
|
|
113
|
+
({ className, children, position = 'popper', portalHost, overlayClassName, overlayStyle, ...props }, ref) => {
|
|
114
|
+
const { open } = SelectPrimitive.useRootContext();
|
|
115
|
+
|
|
116
|
+
return (
|
|
117
|
+
<SelectPrimitive.Portal hostName={portalHost}>
|
|
118
|
+
<SelectPrimitive.Overlay style={Platform.OS !== 'web' ? StyleSheet.absoluteFill : undefined} asChild>
|
|
119
|
+
<Animated.View className={overlayClassName} style={overlayStyle} />
|
|
120
|
+
</SelectPrimitive.Overlay>
|
|
121
|
+
<SelectPrimitive.Content
|
|
122
|
+
ref={ref}
|
|
123
|
+
className={cn(
|
|
124
|
+
'relative z-50 max-h-96 min-w-[8rem] rounded-md border border-border bg-popover shadow-md 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',
|
|
125
|
+
position === 'popper' &&
|
|
126
|
+
'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',
|
|
127
|
+
open ? 'web:zoom-in-95 web:animate-in web:fade-in-0' : 'web:zoom-out-95 web:animate-out web:fade-out-0',
|
|
128
|
+
className,
|
|
129
|
+
)}
|
|
130
|
+
position={position}
|
|
131
|
+
{...props}
|
|
132
|
+
>
|
|
133
|
+
<SelectScrollUpButton />
|
|
134
|
+
<SelectPrimitive.Viewport
|
|
135
|
+
className={cn(
|
|
136
|
+
'p-1',
|
|
137
|
+
position === 'popper' &&
|
|
138
|
+
'h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]',
|
|
139
|
+
)}
|
|
140
|
+
>
|
|
141
|
+
{children}
|
|
142
|
+
</SelectPrimitive.Viewport>
|
|
143
|
+
<SelectScrollDownButton />
|
|
144
|
+
</SelectPrimitive.Content>
|
|
145
|
+
</SelectPrimitive.Portal>
|
|
146
|
+
);
|
|
147
|
+
},
|
|
148
|
+
);
|
|
149
|
+
SelectContent.displayName = SelectPrimitive.Content?.displayName || 'SelectContent';
|
|
150
|
+
|
|
151
|
+
export interface SelectLabelProps
|
|
152
|
+
extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>, SelectLabelBaseProps {}
|
|
153
|
+
|
|
154
|
+
const SelectLabel = React.forwardRef<React.ElementRef<typeof SelectPrimitive.Label>, SelectLabelProps>(
|
|
155
|
+
({ className, ...props }, ref) => (
|
|
156
|
+
<SelectPrimitive.Label
|
|
157
|
+
ref={ref}
|
|
158
|
+
className={cn('py-1.5 pl-8 pr-2 text-sm font-semibold text-popover-foreground', className)}
|
|
159
|
+
{...props}
|
|
160
|
+
/>
|
|
161
|
+
),
|
|
162
|
+
);
|
|
163
|
+
SelectLabel.displayName = SelectPrimitive.Label?.displayName || 'SelectLabel';
|
|
164
|
+
|
|
165
|
+
export interface SelectItemProps
|
|
166
|
+
extends
|
|
167
|
+
Omit<React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>, 'children' | 'disabled' | 'label'>,
|
|
168
|
+
SelectItemBaseProps {
|
|
169
|
+
label?: string;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const SelectItem = React.forwardRef<React.ElementRef<typeof SelectPrimitive.Item>, SelectItemProps>(
|
|
173
|
+
({ className, children, label, ...props }, ref) => {
|
|
174
|
+
const itemLabel = label || (typeof children === 'string' ? children : '');
|
|
175
|
+
return (
|
|
176
|
+
<SelectPrimitive.Item
|
|
177
|
+
ref={ref}
|
|
178
|
+
label={itemLabel}
|
|
179
|
+
className={cn(
|
|
180
|
+
'relative flex w-full cursor-default select-none flex-row items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none web:hover:bg-accent/50 web:focus:bg-accent web:focus:text-accent-foreground web:hover:text-accent-foreground data-[disabled]:opacity-50',
|
|
181
|
+
props.disabled && 'web:pointer-events-none',
|
|
182
|
+
className,
|
|
183
|
+
)}
|
|
184
|
+
{...props}
|
|
185
|
+
>
|
|
186
|
+
<View
|
|
187
|
+
className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center"
|
|
188
|
+
{...({} as Record<string, unknown>)}
|
|
189
|
+
>
|
|
190
|
+
<SelectPrimitive.ItemIndicator>
|
|
191
|
+
<Check size={14} strokeWidth={3} className="text-popover-foreground" {...({} as Record<string, unknown>)} />
|
|
192
|
+
</SelectPrimitive.ItemIndicator>
|
|
193
|
+
</View>
|
|
194
|
+
{/* @ts-expect-error TODO: fix type */}
|
|
195
|
+
<SelectPrimitive.ItemText className="text-sm text-popover-foreground native:text-base">
|
|
196
|
+
{children}
|
|
197
|
+
</SelectPrimitive.ItemText>
|
|
198
|
+
</SelectPrimitive.Item>
|
|
199
|
+
);
|
|
200
|
+
},
|
|
201
|
+
);
|
|
202
|
+
SelectItem.displayName = SelectPrimitive.Item?.displayName || 'SelectItem';
|
|
203
|
+
|
|
204
|
+
export interface SelectSeparatorProps
|
|
205
|
+
extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>, SelectSeparatorBaseProps {}
|
|
206
|
+
|
|
207
|
+
const SelectSeparator = React.forwardRef<React.ElementRef<typeof SelectPrimitive.Separator>, SelectSeparatorProps>(
|
|
208
|
+
({ className, ...props }, ref) => (
|
|
209
|
+
<SelectPrimitive.Separator
|
|
210
|
+
ref={ref}
|
|
211
|
+
className={cn('-mx-1 my-1 h-px bg-muted', className)}
|
|
212
|
+
{...(props as Record<string, unknown>)}
|
|
213
|
+
/>
|
|
214
|
+
),
|
|
215
|
+
);
|
|
216
|
+
SelectSeparator.displayName = SelectPrimitive.Separator?.displayName || 'SelectSeparator';
|
|
217
|
+
|
|
218
|
+
export {
|
|
219
|
+
Select,
|
|
220
|
+
SelectContent,
|
|
221
|
+
SelectGroup,
|
|
222
|
+
SelectItem,
|
|
223
|
+
SelectLabel,
|
|
224
|
+
SelectScrollDownButton,
|
|
225
|
+
SelectScrollUpButton,
|
|
226
|
+
SelectSeparator,
|
|
227
|
+
SelectTrigger,
|
|
228
|
+
SelectValue,
|
|
229
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as SeparatorPrimitive from '@rn-primitives/separator';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
|
|
4
|
+
import { cn } from './lib/utils';
|
|
5
|
+
|
|
6
|
+
const Separator = React.forwardRef<
|
|
7
|
+
React.ElementRef<typeof SeparatorPrimitive.Root>,
|
|
8
|
+
React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>
|
|
9
|
+
>(({ className, orientation = 'horizontal', decorative = true, ...props }, ref) => (
|
|
10
|
+
<SeparatorPrimitive.Root
|
|
11
|
+
ref={ref}
|
|
12
|
+
decorative={decorative}
|
|
13
|
+
orientation={orientation}
|
|
14
|
+
className={cn('shrink-0 bg-border', orientation === 'horizontal' ? 'h-[1px] w-full' : 'h-full w-[1px]', className)}
|
|
15
|
+
{...props}
|
|
16
|
+
/>
|
|
17
|
+
));
|
|
18
|
+
Separator.displayName = SeparatorPrimitive.Root?.displayName || 'Separator';
|
|
19
|
+
|
|
20
|
+
export { Separator };
|
package/src/sheet.tsx
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import * as DialogPrimitive from '@rn-primitives/dialog';
|
|
2
|
+
import { X } from 'lucide-react-native';
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { Platform, StyleSheet, View, type ViewStyle } from 'react-native';
|
|
5
|
+
import Animated, { FadeIn, FadeOut, SlideInRight, SlideOutRight } from 'react-native-reanimated';
|
|
6
|
+
|
|
7
|
+
import { type DialogContentProps } from './dialog';
|
|
8
|
+
import { cn } from './lib/utils';
|
|
9
|
+
import { Text } from './text';
|
|
10
|
+
|
|
11
|
+
const Sheet = DialogPrimitive.Root;
|
|
12
|
+
|
|
13
|
+
const SheetTrigger = DialogPrimitive.Trigger;
|
|
14
|
+
|
|
15
|
+
const SheetClose = DialogPrimitive.Close;
|
|
16
|
+
|
|
17
|
+
const SheetPortal = DialogPrimitive.Portal;
|
|
18
|
+
|
|
19
|
+
const SheetOverlay = React.forwardRef<
|
|
20
|
+
React.ElementRef<typeof DialogPrimitive.Overlay>,
|
|
21
|
+
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
|
|
22
|
+
>(({ className, ...props }, ref) => {
|
|
23
|
+
return (
|
|
24
|
+
<DialogPrimitive.Overlay
|
|
25
|
+
style={Platform.OS !== 'web' ? StyleSheet.absoluteFill : undefined}
|
|
26
|
+
asChild
|
|
27
|
+
ref={ref}
|
|
28
|
+
{...props}
|
|
29
|
+
>
|
|
30
|
+
<Animated.View
|
|
31
|
+
entering={FadeIn.duration(150)}
|
|
32
|
+
exiting={FadeOut.duration(150)}
|
|
33
|
+
className={cn('absolute inset-0 z-50 bg-black/80 web:cursor-default', className)}
|
|
34
|
+
/>
|
|
35
|
+
</DialogPrimitive.Overlay>
|
|
36
|
+
);
|
|
37
|
+
});
|
|
38
|
+
SheetOverlay.displayName = DialogPrimitive.Overlay?.displayName || 'SheetOverlay';
|
|
39
|
+
|
|
40
|
+
const SheetContent = React.forwardRef<
|
|
41
|
+
React.ElementRef<typeof DialogPrimitive.Content>,
|
|
42
|
+
DialogContentProps & {
|
|
43
|
+
side?: 'top' | 'right' | 'bottom' | 'left';
|
|
44
|
+
overlayClassName?: string;
|
|
45
|
+
overlayStyle?: ViewStyle;
|
|
46
|
+
}
|
|
47
|
+
>(({ className, children, side = 'right', overlayClassName, overlayStyle, ...props }, ref) => {
|
|
48
|
+
const isWeb = Platform.OS === 'web';
|
|
49
|
+
// TODO: Add support for other sides
|
|
50
|
+
const entering = isWeb ? undefined : SlideInRight;
|
|
51
|
+
const exiting = isWeb ? undefined : SlideOutRight;
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<SheetPortal>
|
|
55
|
+
<SheetOverlay className={overlayClassName} style={overlayStyle} />
|
|
56
|
+
<DialogPrimitive.Content ref={ref} asChild {...props}>
|
|
57
|
+
<Animated.View
|
|
58
|
+
entering={entering}
|
|
59
|
+
exiting={exiting}
|
|
60
|
+
className={cn(
|
|
61
|
+
'absolute z-50 h-full w-3/4 gap-4 bg-background p-6 shadow-lg web:cursor-default web:duration-200 web:ease-in-out',
|
|
62
|
+
side === 'right' &&
|
|
63
|
+
'right-0 top-0 border-l border-border data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right',
|
|
64
|
+
side === 'left' &&
|
|
65
|
+
'left-0 top-0 border-r border-border data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left',
|
|
66
|
+
side === 'top' &&
|
|
67
|
+
'top-0 w-full border-b border-border data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top',
|
|
68
|
+
side === 'bottom' &&
|
|
69
|
+
'bottom-0 w-full border-t border-border data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom',
|
|
70
|
+
className,
|
|
71
|
+
)}
|
|
72
|
+
>
|
|
73
|
+
{children}
|
|
74
|
+
<DialogPrimitive.Close
|
|
75
|
+
className={cn(
|
|
76
|
+
'absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary',
|
|
77
|
+
'web:absolute web:right-4 web:top-4',
|
|
78
|
+
)}
|
|
79
|
+
>
|
|
80
|
+
<X size={24} className="text-muted-foreground" />
|
|
81
|
+
<Text className="sr-only">Close</Text>
|
|
82
|
+
</DialogPrimitive.Close>
|
|
83
|
+
</Animated.View>
|
|
84
|
+
</DialogPrimitive.Content>
|
|
85
|
+
</SheetPortal>
|
|
86
|
+
);
|
|
87
|
+
});
|
|
88
|
+
SheetContent.displayName = DialogPrimitive.Content?.displayName || 'SheetContent';
|
|
89
|
+
|
|
90
|
+
const SheetHeader = ({ className, ...props }: React.ComponentPropsWithoutRef<typeof View>) => (
|
|
91
|
+
<View className={cn('flex flex-col space-y-2 text-center sm:text-left', className)} {...props} />
|
|
92
|
+
);
|
|
93
|
+
SheetHeader.displayName = 'SheetHeader';
|
|
94
|
+
|
|
95
|
+
const SheetFooter = ({ className, ...props }: React.ComponentPropsWithoutRef<typeof View>) => (
|
|
96
|
+
<View className={cn('flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2', className)} {...props} />
|
|
97
|
+
);
|
|
98
|
+
SheetFooter.displayName = 'SheetFooter';
|
|
99
|
+
|
|
100
|
+
const SheetTitle = React.forwardRef<
|
|
101
|
+
React.ElementRef<typeof DialogPrimitive.Title>,
|
|
102
|
+
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
|
|
103
|
+
>(({ className, ...props }, ref) => (
|
|
104
|
+
<DialogPrimitive.Title ref={ref} className={cn('text-lg font-semibold text-foreground', className)} {...props} />
|
|
105
|
+
));
|
|
106
|
+
SheetTitle.displayName = DialogPrimitive.Title?.displayName || 'SheetTitle';
|
|
107
|
+
|
|
108
|
+
const SheetDescription = React.forwardRef<
|
|
109
|
+
React.ElementRef<typeof DialogPrimitive.Description>,
|
|
110
|
+
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>
|
|
111
|
+
>(({ className, ...props }, ref) => (
|
|
112
|
+
<DialogPrimitive.Description ref={ref} className={cn('text-sm text-muted-foreground', className)} {...props} />
|
|
113
|
+
));
|
|
114
|
+
SheetDescription.displayName = DialogPrimitive.Description?.displayName || 'SheetDescription';
|
|
115
|
+
|
|
116
|
+
export {
|
|
117
|
+
Sheet,
|
|
118
|
+
SheetClose,
|
|
119
|
+
SheetContent,
|
|
120
|
+
SheetDescription,
|
|
121
|
+
SheetFooter,
|
|
122
|
+
SheetHeader,
|
|
123
|
+
SheetOverlay,
|
|
124
|
+
SheetPortal,
|
|
125
|
+
SheetTitle,
|
|
126
|
+
SheetTrigger,
|
|
127
|
+
};
|
package/src/skeleton.tsx
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { View } from 'react-native';
|
|
3
|
+
import Animated, {
|
|
4
|
+
useAnimatedStyle,
|
|
5
|
+
useSharedValue,
|
|
6
|
+
withRepeat,
|
|
7
|
+
withSequence,
|
|
8
|
+
withTiming,
|
|
9
|
+
} from 'react-native-reanimated';
|
|
10
|
+
|
|
11
|
+
import { cn } from './lib/utils';
|
|
12
|
+
|
|
13
|
+
function Skeleton({ className, ...props }: React.ComponentPropsWithoutRef<typeof View>) {
|
|
14
|
+
const opacity = useSharedValue(0.5);
|
|
15
|
+
|
|
16
|
+
React.useEffect(() => {
|
|
17
|
+
opacity.value = withRepeat(
|
|
18
|
+
withSequence(withTiming(0.2, { duration: 500 }), withTiming(0.5, { duration: 500 })),
|
|
19
|
+
-1,
|
|
20
|
+
true,
|
|
21
|
+
);
|
|
22
|
+
}, []);
|
|
23
|
+
|
|
24
|
+
const animatedStyle = useAnimatedStyle(() => ({
|
|
25
|
+
opacity: opacity.value,
|
|
26
|
+
}));
|
|
27
|
+
|
|
28
|
+
return <Animated.View className={cn('rounded-md bg-muted', className)} style={animatedStyle} {...props} />;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export { Skeleton };
|
package/src/slider.tsx
ADDED
package/src/sonner.tsx
ADDED
package/src/switch.tsx
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { SwitchBaseProps } from '@gv-tech/ui-core';
|
|
2
|
+
import * as SwitchPrimitive from '@rn-primitives/switch';
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
|
|
5
|
+
import { cn } from './lib/utils';
|
|
6
|
+
|
|
7
|
+
export interface SwitchProps
|
|
8
|
+
extends
|
|
9
|
+
Omit<React.ComponentPropsWithoutRef<typeof SwitchPrimitive.Root>, 'checked' | 'onCheckedChange'>,
|
|
10
|
+
SwitchBaseProps {}
|
|
11
|
+
|
|
12
|
+
const Switch = React.forwardRef<React.ElementRef<typeof SwitchPrimitive.Root>, SwitchProps>(
|
|
13
|
+
({ className, checked, onCheckedChange, ...props }, ref) => (
|
|
14
|
+
<SwitchPrimitive.Root
|
|
15
|
+
className={cn(
|
|
16
|
+
'peer inline-flex h-6 w-11 shrink-0 cursor-pointer flex-row items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input',
|
|
17
|
+
className,
|
|
18
|
+
)}
|
|
19
|
+
{...props}
|
|
20
|
+
checked={checked ?? false}
|
|
21
|
+
onCheckedChange={onCheckedChange || (() => {})}
|
|
22
|
+
ref={ref}
|
|
23
|
+
>
|
|
24
|
+
<SwitchPrimitive.Thumb
|
|
25
|
+
className={cn(
|
|
26
|
+
'pointer-events-none block h-5 w-5 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0',
|
|
27
|
+
)}
|
|
28
|
+
/>
|
|
29
|
+
</SwitchPrimitive.Root>
|
|
30
|
+
),
|
|
31
|
+
);
|
|
32
|
+
Switch.displayName = SwitchPrimitive.Root?.displayName || 'Switch';
|
|
33
|
+
|
|
34
|
+
export { Switch };
|
package/src/table.tsx
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { View } from 'react-native';
|
|
3
|
+
|
|
4
|
+
import { cn } from './lib/utils';
|
|
5
|
+
import { Text } from './text';
|
|
6
|
+
|
|
7
|
+
const Table = React.forwardRef<React.ElementRef<typeof View>, React.ComponentPropsWithoutRef<typeof View>>(
|
|
8
|
+
({ className, ...props }, ref) => (
|
|
9
|
+
<View ref={ref} className={cn('w-full caption-bottom text-sm', className)} {...props} />
|
|
10
|
+
),
|
|
11
|
+
);
|
|
12
|
+
Table.displayName = 'Table';
|
|
13
|
+
|
|
14
|
+
const TableHeader = React.forwardRef<React.ElementRef<typeof View>, React.ComponentPropsWithoutRef<typeof View>>(
|
|
15
|
+
({ className, ...props }, ref) => <View ref={ref} className={cn('border-b border-border', className)} {...props} />,
|
|
16
|
+
);
|
|
17
|
+
TableHeader.displayName = 'TableHeader';
|
|
18
|
+
|
|
19
|
+
const TableBody = React.forwardRef<React.ElementRef<typeof View>, React.ComponentPropsWithoutRef<typeof View>>(
|
|
20
|
+
({ className, ...props }, ref) => <View ref={ref} className={cn('flex-1', className)} {...props} />,
|
|
21
|
+
);
|
|
22
|
+
TableBody.displayName = 'TableBody';
|
|
23
|
+
|
|
24
|
+
const TableFooter = React.forwardRef<React.ElementRef<typeof View>, React.ComponentPropsWithoutRef<typeof View>>(
|
|
25
|
+
({ className, ...props }, ref) => (
|
|
26
|
+
<View ref={ref} className={cn('bg-muted/50 font-medium [&>tr]:last:border-b-0', className)} {...props} />
|
|
27
|
+
),
|
|
28
|
+
);
|
|
29
|
+
TableFooter.displayName = 'TableFooter';
|
|
30
|
+
|
|
31
|
+
const TableRow = React.forwardRef<React.ElementRef<typeof View>, React.ComponentPropsWithoutRef<typeof View>>(
|
|
32
|
+
({ className, ...props }, ref) => (
|
|
33
|
+
<View
|
|
34
|
+
ref={ref}
|
|
35
|
+
className={cn(
|
|
36
|
+
'flex-row border-b border-border transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted',
|
|
37
|
+
className,
|
|
38
|
+
)}
|
|
39
|
+
{...props}
|
|
40
|
+
/>
|
|
41
|
+
),
|
|
42
|
+
);
|
|
43
|
+
TableRow.displayName = 'TableRow';
|
|
44
|
+
|
|
45
|
+
const TableHead = React.forwardRef<React.ElementRef<typeof Text>, React.ComponentPropsWithoutRef<typeof Text>>(
|
|
46
|
+
({ className, ...props }, ref) => (
|
|
47
|
+
<Text
|
|
48
|
+
ref={ref}
|
|
49
|
+
className={cn(
|
|
50
|
+
'h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0',
|
|
51
|
+
className,
|
|
52
|
+
)}
|
|
53
|
+
{...props}
|
|
54
|
+
/>
|
|
55
|
+
),
|
|
56
|
+
);
|
|
57
|
+
TableHead.displayName = 'TableHead';
|
|
58
|
+
|
|
59
|
+
const TableCell = React.forwardRef<React.ElementRef<typeof Text>, React.ComponentPropsWithoutRef<typeof Text>>(
|
|
60
|
+
({ className, ...props }, ref) => (
|
|
61
|
+
<Text ref={ref} className={cn('p-4 align-middle [&:has([role=checkbox])]:pr-0', className)} {...props} />
|
|
62
|
+
),
|
|
63
|
+
);
|
|
64
|
+
TableCell.displayName = 'TableCell';
|
|
65
|
+
|
|
66
|
+
const TableCaption = React.forwardRef<React.ElementRef<typeof Text>, React.ComponentPropsWithoutRef<typeof Text>>(
|
|
67
|
+
({ className, ...props }, ref) => (
|
|
68
|
+
<Text ref={ref} className={cn('mt-4 text-sm text-muted-foreground', className)} {...props} />
|
|
69
|
+
),
|
|
70
|
+
);
|
|
71
|
+
TableCaption.displayName = 'TableCaption';
|
|
72
|
+
|
|
73
|
+
export { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow };
|
package/src/tabs.tsx
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { TabsBaseProps, TabsContentBaseProps, TabsListBaseProps, TabsTriggerBaseProps } from '@gv-tech/ui-core';
|
|
2
|
+
import * as TabsPrimitive from '@rn-primitives/tabs';
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
|
|
5
|
+
import { cn } from './lib/utils';
|
|
6
|
+
import { TextClassContext } from './text';
|
|
7
|
+
|
|
8
|
+
const Tabs = TabsPrimitive.Root;
|
|
9
|
+
|
|
10
|
+
export interface TabsProps
|
|
11
|
+
extends Omit<React.ComponentPropsWithoutRef<typeof TabsPrimitive.Root>, 'onValueChange' | 'value'>, TabsBaseProps {}
|
|
12
|
+
export interface TabsListProps extends React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>, TabsListBaseProps {}
|
|
13
|
+
export interface TabsTriggerProps
|
|
14
|
+
extends
|
|
15
|
+
Omit<React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>, 'children' | 'disabled'>,
|
|
16
|
+
TabsTriggerBaseProps {}
|
|
17
|
+
export interface TabsContentProps
|
|
18
|
+
extends React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>, TabsContentBaseProps {}
|
|
19
|
+
|
|
20
|
+
const TabsList = React.forwardRef<React.ElementRef<typeof TabsPrimitive.List>, TabsListProps>(
|
|
21
|
+
({ className, ...props }, ref) => (
|
|
22
|
+
<TabsPrimitive.List
|
|
23
|
+
ref={ref}
|
|
24
|
+
className={cn(
|
|
25
|
+
'h-10 inline-flex flex-row items-center justify-center rounded-md bg-muted p-1 text-muted-foreground',
|
|
26
|
+
className,
|
|
27
|
+
)}
|
|
28
|
+
{...props}
|
|
29
|
+
/>
|
|
30
|
+
),
|
|
31
|
+
);
|
|
32
|
+
TabsList.displayName = TabsPrimitive.List?.displayName || 'TabsList';
|
|
33
|
+
|
|
34
|
+
const TabsTrigger = React.forwardRef<React.ElementRef<typeof TabsPrimitive.Trigger>, TabsTriggerProps>(
|
|
35
|
+
({ className, ...props }, ref) => {
|
|
36
|
+
const { value } = TabsPrimitive.useRootContext();
|
|
37
|
+
return (
|
|
38
|
+
<TextClassContext.Provider
|
|
39
|
+
value={cn(
|
|
40
|
+
'text-sm native:text-base font-medium text-muted-foreground web:transition-all',
|
|
41
|
+
value === props.value && 'text-foreground',
|
|
42
|
+
)}
|
|
43
|
+
>
|
|
44
|
+
<TabsPrimitive.Trigger
|
|
45
|
+
ref={ref}
|
|
46
|
+
className={cn(
|
|
47
|
+
'inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',
|
|
48
|
+
props.disabled && 'opacity-50',
|
|
49
|
+
value === props.value && 'bg-background shadow-sm shadow-foreground/10',
|
|
50
|
+
className,
|
|
51
|
+
)}
|
|
52
|
+
{...props}
|
|
53
|
+
/>
|
|
54
|
+
</TextClassContext.Provider>
|
|
55
|
+
);
|
|
56
|
+
},
|
|
57
|
+
);
|
|
58
|
+
TabsTrigger.displayName = TabsPrimitive.Trigger?.displayName || 'TabsTrigger';
|
|
59
|
+
|
|
60
|
+
const TabsContent = React.forwardRef<React.ElementRef<typeof TabsPrimitive.Content>, TabsContentProps>(
|
|
61
|
+
({ className, ...props }, ref) => (
|
|
62
|
+
<TabsPrimitive.Content
|
|
63
|
+
ref={ref}
|
|
64
|
+
className={cn(
|
|
65
|
+
'mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',
|
|
66
|
+
className,
|
|
67
|
+
)}
|
|
68
|
+
{...props}
|
|
69
|
+
/>
|
|
70
|
+
),
|
|
71
|
+
);
|
|
72
|
+
TabsContent.displayName = TabsPrimitive.Content?.displayName || 'TabsContent';
|
|
73
|
+
|
|
74
|
+
export { Tabs, TabsContent, TabsList, TabsTrigger };
|
package/src/text.tsx
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { cva, type VariantProps } from 'class-variance-authority';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { Text as RNText } from 'react-native';
|
|
4
|
+
|
|
5
|
+
import type { TextBaseProps } from '@gv-tech/ui-core';
|
|
6
|
+
import { cn } from './lib/utils';
|
|
7
|
+
|
|
8
|
+
const TextClassContext = React.createContext<string | undefined>(undefined);
|
|
9
|
+
|
|
10
|
+
const textVariants = cva('text-foreground', {
|
|
11
|
+
variants: {
|
|
12
|
+
variant: {
|
|
13
|
+
h1: 'text-4xl font-extrabold tracking-tight',
|
|
14
|
+
h2: 'text-3xl font-semibold tracking-tight',
|
|
15
|
+
h3: 'text-2xl font-semibold tracking-tight',
|
|
16
|
+
h4: 'text-xl font-semibold tracking-tight',
|
|
17
|
+
body: 'text-base leading-7',
|
|
18
|
+
bodySmall: 'text-sm leading-6',
|
|
19
|
+
caption: 'text-xs text-muted-foreground',
|
|
20
|
+
label: 'text-sm font-medium',
|
|
21
|
+
overline: 'text-xs font-semibold uppercase tracking-widest text-muted-foreground',
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
defaultVariants: {
|
|
25
|
+
variant: 'body',
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
export interface TextProps
|
|
30
|
+
extends React.ComponentPropsWithoutRef<typeof RNText>, VariantProps<typeof textVariants>, TextBaseProps {}
|
|
31
|
+
|
|
32
|
+
const Text = React.forwardRef<React.ElementRef<typeof RNText>, TextProps>(
|
|
33
|
+
({ className, variant = 'body', children, ...props }, ref) => {
|
|
34
|
+
return (
|
|
35
|
+
<RNText ref={ref} className={cn(textVariants({ variant, className }))} {...props}>
|
|
36
|
+
{children}
|
|
37
|
+
</RNText>
|
|
38
|
+
);
|
|
39
|
+
},
|
|
40
|
+
);
|
|
41
|
+
Text.displayName = 'Text';
|
|
42
|
+
|
|
43
|
+
export { Text, TextClassContext, textVariants };
|