linked-data-browser 0.0.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/.eslintrc.js +13 -0
- package/.ldo/profile.context.ts +459 -0
- package/.ldo/profile.schema.ts +751 -0
- package/.ldo/profile.shapeTypes.ts +71 -0
- package/.ldo/profile.typings.ts +295 -0
- package/.prettierignore +6 -0
- package/.prettierrc +10 -0
- package/.shapes/profile.shex +121 -0
- package/README.md +3 -0
- package/app/index.tsx +25 -0
- package/app.json +37 -0
- package/assets/images/adaptive-icon.png +0 -0
- package/assets/images/favicon.png +0 -0
- package/assets/images/icon.png +0 -0
- package/assets/images/splash.png +0 -0
- package/babel.config.js +6 -0
- package/components/DataBrowser.tsx +57 -0
- package/components/ResourceView.tsx +14 -0
- package/components/TargetResourceProvider.tsx +128 -0
- package/components/ThemeProvider.tsx +123 -0
- package/components/nav/DialogProvider.tsx +140 -0
- package/components/nav/Layout.tsx +118 -0
- package/components/nav/header/AddressBox.tsx +126 -0
- package/components/nav/header/AvatarMenu.tsx +62 -0
- package/components/nav/header/Header.tsx +28 -0
- package/components/nav/header/SignInMenu.tsx +126 -0
- package/components/nav/header/ThemeToggleMenu.tsx +34 -0
- package/components/nav/header/ViewMenu.tsx +88 -0
- package/components/nav/useValidView.tsx +51 -0
- package/components/nav/utilityResourceViews/ErrorMessageResourceView.tsx +26 -0
- package/components/ui/avatar.tsx +53 -0
- package/components/ui/button.tsx +88 -0
- package/components/ui/card.tsx +101 -0
- package/components/ui/dialog.tsx +159 -0
- package/components/ui/dropdown-menu.tsx +275 -0
- package/components/ui/input.tsx +25 -0
- package/components/ui/label.tsx +34 -0
- package/components/ui/navigation-menu.tsx +200 -0
- package/components/ui/popover.tsx +45 -0
- package/components/ui/progress.tsx +79 -0
- package/components/ui/radio-group.tsx +59 -0
- package/components/ui/separator.tsx +27 -0
- package/components/ui/switch.tsx +105 -0
- package/components/ui/text.tsx +30 -0
- package/components/ui/tooltip.tsx +46 -0
- package/components.json +7 -0
- package/global.css +61 -0
- package/index.js +12 -0
- package/lib/android-navigation-bar.ts +11 -0
- package/lib/constants.ts +18 -0
- package/lib/icons/ArrowRight.tsx +4 -0
- package/lib/icons/Check.tsx +4 -0
- package/lib/icons/ChevronDown.tsx +4 -0
- package/lib/icons/ChevronRight.tsx +4 -0
- package/lib/icons/ChevronUp.tsx +4 -0
- package/lib/icons/ChevronsRight.tsx +4 -0
- package/lib/icons/CircleSlash.tsx +4 -0
- package/lib/icons/CircleX.tsx +4 -0
- package/lib/icons/Code.tsx +4 -0
- package/lib/icons/EllipsisVertical.tsx +4 -0
- package/lib/icons/EyeOff.tsx +4 -0
- package/lib/icons/File.tsx +4 -0
- package/lib/icons/Folder.tsx +4 -0
- package/lib/icons/Folders.tsx +4 -0
- package/lib/icons/Info.tsx +4 -0
- package/lib/icons/MonitorSmartphone.tsx +4 -0
- package/lib/icons/MoonStar.tsx +4 -0
- package/lib/icons/OctagonX.tsx +4 -0
- package/lib/icons/RefreshCw.tsx +4 -0
- package/lib/icons/ShieldX.tsx +4 -0
- package/lib/icons/Sun.tsx +4 -0
- package/lib/icons/TextCursorInput.tsx +4 -0
- package/lib/icons/Trash.tsx +4 -0
- package/lib/icons/ViewIcon.tsx +4 -0
- package/lib/icons/X.tsx +4 -0
- package/lib/icons/iconWithClassName.ts +14 -0
- package/lib/utils.ts +6 -0
- package/metro.config.js +6 -0
- package/nativewind-env.d.ts +1 -0
- package/package.json +89 -0
- package/resourceViews/Container/ContainerConfig.tsx +13 -0
- package/resourceViews/Container/ContainerView.tsx +148 -0
- package/resourceViews/RawCode/RawCodeConfig.tsx +11 -0
- package/resourceViews/RawCode/RawCodeEditor.tsx +37 -0
- package/resourceViews/RawCode/RawCodeView.tsx +67 -0
- package/scripts/adjust-server-paths.js +37 -0
- package/scripts/adjust-standalone-paths.js +28 -0
- package/tailwind.config.js +69 -0
- package/test-server/server-config.json +75 -0
- package/test-server/solid-css-seed.json +11 -0
- package/tsconfig.json +19 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import * as DialogPrimitive from '@rn-primitives/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 { X } from '~/lib/icons/X';
|
|
6
|
+
import { cn } from '~/lib/utils';
|
|
7
|
+
|
|
8
|
+
const Dialog = DialogPrimitive.Root;
|
|
9
|
+
|
|
10
|
+
const DialogTrigger = DialogPrimitive.Trigger;
|
|
11
|
+
|
|
12
|
+
const DialogPortal = DialogPrimitive.Portal;
|
|
13
|
+
|
|
14
|
+
const DialogClose = DialogPrimitive.Close;
|
|
15
|
+
|
|
16
|
+
function DialogOverlayWeb({
|
|
17
|
+
className,
|
|
18
|
+
...props
|
|
19
|
+
}: DialogPrimitive.OverlayProps & {
|
|
20
|
+
ref?: React.RefObject<DialogPrimitive.OverlayRef>;
|
|
21
|
+
}) {
|
|
22
|
+
const { open } = DialogPrimitive.useRootContext();
|
|
23
|
+
return (
|
|
24
|
+
<DialogPrimitive.Overlay
|
|
25
|
+
className={cn(
|
|
26
|
+
'bg-black/80 flex justify-center items-center p-2 absolute top-0 right-0 bottom-0 left-0',
|
|
27
|
+
open ? 'web:animate-in web:fade-in-0' : 'web:animate-out web:fade-out-0',
|
|
28
|
+
className
|
|
29
|
+
)}
|
|
30
|
+
{...props}
|
|
31
|
+
/>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function DialogOverlayNative({
|
|
36
|
+
className,
|
|
37
|
+
children,
|
|
38
|
+
...props
|
|
39
|
+
}: DialogPrimitive.OverlayProps & {
|
|
40
|
+
ref?: React.RefObject<DialogPrimitive.OverlayRef>;
|
|
41
|
+
children?: React.ReactNode;
|
|
42
|
+
}) {
|
|
43
|
+
return (
|
|
44
|
+
<DialogPrimitive.Overlay
|
|
45
|
+
style={StyleSheet.absoluteFill}
|
|
46
|
+
className={cn('flex bg-black/80 justify-center items-center p-2', className)}
|
|
47
|
+
{...props}
|
|
48
|
+
>
|
|
49
|
+
<Animated.View entering={FadeIn.duration(150)} exiting={FadeOut.duration(150)}>
|
|
50
|
+
{children}
|
|
51
|
+
</Animated.View>
|
|
52
|
+
</DialogPrimitive.Overlay>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const DialogOverlay = Platform.select({
|
|
57
|
+
web: DialogOverlayWeb,
|
|
58
|
+
default: DialogOverlayNative,
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
function DialogContent({
|
|
62
|
+
className,
|
|
63
|
+
children,
|
|
64
|
+
portalHost,
|
|
65
|
+
...props
|
|
66
|
+
}: DialogPrimitive.ContentProps & {
|
|
67
|
+
ref?: React.RefObject<DialogPrimitive.ContentRef>;
|
|
68
|
+
className?: string;
|
|
69
|
+
portalHost?: string;
|
|
70
|
+
}) {
|
|
71
|
+
const { open } = DialogPrimitive.useRootContext();
|
|
72
|
+
return (
|
|
73
|
+
<DialogPortal hostName={portalHost}>
|
|
74
|
+
<DialogOverlay>
|
|
75
|
+
<DialogPrimitive.Content
|
|
76
|
+
className={cn(
|
|
77
|
+
'max-w-lg gap-4 border border-border web:cursor-default bg-background p-6 shadow-lg web:duration-200 rounded-lg',
|
|
78
|
+
open
|
|
79
|
+
? 'web:animate-in web:fade-in-0 web:zoom-in-95'
|
|
80
|
+
: 'web:animate-out web:fade-out-0 web:zoom-out-95',
|
|
81
|
+
className
|
|
82
|
+
)}
|
|
83
|
+
{...props}
|
|
84
|
+
>
|
|
85
|
+
{children}
|
|
86
|
+
<DialogPrimitive.Close
|
|
87
|
+
className={
|
|
88
|
+
'absolute right-4 top-4 p-0.5 web:group rounded-sm opacity-70 web:ring-offset-background web:transition-opacity web:hover:opacity-100 web:focus:outline-none web:focus:ring-2 web:focus:ring-ring web:focus:ring-offset-2 web:disabled:pointer-events-none'
|
|
89
|
+
}
|
|
90
|
+
>
|
|
91
|
+
<X
|
|
92
|
+
size={Platform.OS === 'web' ? 16 : 18}
|
|
93
|
+
className={cn('text-muted-foreground', open && 'text-accent-foreground')}
|
|
94
|
+
/>
|
|
95
|
+
</DialogPrimitive.Close>
|
|
96
|
+
</DialogPrimitive.Content>
|
|
97
|
+
</DialogOverlay>
|
|
98
|
+
</DialogPortal>
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function DialogHeader({ className, ...props }: ViewProps) {
|
|
103
|
+
return (
|
|
104
|
+
<View className={cn('flex flex-col gap-1.5 text-center sm:text-left', className)} {...props} />
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function DialogFooter({ className, ...props }: ViewProps) {
|
|
109
|
+
return (
|
|
110
|
+
<View
|
|
111
|
+
className={cn('flex flex-col-reverse sm:flex-row sm:justify-end gap-2', className)}
|
|
112
|
+
{...props}
|
|
113
|
+
/>
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function DialogTitle({
|
|
118
|
+
className,
|
|
119
|
+
...props
|
|
120
|
+
}: DialogPrimitive.TitleProps & {
|
|
121
|
+
ref?: React.RefObject<DialogPrimitive.TitleRef>;
|
|
122
|
+
}) {
|
|
123
|
+
return (
|
|
124
|
+
<DialogPrimitive.Title
|
|
125
|
+
className={cn(
|
|
126
|
+
'text-lg native:text-xl text-foreground font-semibold leading-none tracking-tight',
|
|
127
|
+
className
|
|
128
|
+
)}
|
|
129
|
+
{...props}
|
|
130
|
+
/>
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function DialogDescription({
|
|
135
|
+
className,
|
|
136
|
+
...props
|
|
137
|
+
}: DialogPrimitive.DescriptionProps & {
|
|
138
|
+
ref?: React.RefObject<DialogPrimitive.DescriptionRef>;
|
|
139
|
+
}) {
|
|
140
|
+
return (
|
|
141
|
+
<DialogPrimitive.Description
|
|
142
|
+
className={cn('text-sm native:text-base text-muted-foreground', className)}
|
|
143
|
+
{...props}
|
|
144
|
+
/>
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export {
|
|
149
|
+
Dialog,
|
|
150
|
+
DialogClose,
|
|
151
|
+
DialogContent,
|
|
152
|
+
DialogDescription,
|
|
153
|
+
DialogFooter,
|
|
154
|
+
DialogHeader,
|
|
155
|
+
DialogOverlay,
|
|
156
|
+
DialogPortal,
|
|
157
|
+
DialogTitle,
|
|
158
|
+
DialogTrigger,
|
|
159
|
+
};
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
import * as DropdownMenuPrimitive from '@rn-primitives/dropdown-menu';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import {
|
|
4
|
+
Platform,
|
|
5
|
+
type StyleProp,
|
|
6
|
+
StyleSheet,
|
|
7
|
+
Text,
|
|
8
|
+
type TextProps,
|
|
9
|
+
View,
|
|
10
|
+
type ViewStyle,
|
|
11
|
+
} from 'react-native';
|
|
12
|
+
import { Check } from '~/lib/icons/Check';
|
|
13
|
+
import { ChevronDown } from '~/lib/icons/ChevronDown';
|
|
14
|
+
import { ChevronRight } from '~/lib/icons/ChevronRight';
|
|
15
|
+
import { ChevronUp } from '~/lib/icons/ChevronUp';
|
|
16
|
+
import { cn } from '~/lib/utils';
|
|
17
|
+
import { TextClassContext } from '~/components/ui/text';
|
|
18
|
+
|
|
19
|
+
const DropdownMenu = DropdownMenuPrimitive.Root;
|
|
20
|
+
|
|
21
|
+
const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
|
|
22
|
+
|
|
23
|
+
const DropdownMenuGroup = DropdownMenuPrimitive.Group;
|
|
24
|
+
|
|
25
|
+
const DropdownMenuPortal = DropdownMenuPrimitive.Portal;
|
|
26
|
+
|
|
27
|
+
const DropdownMenuSub = DropdownMenuPrimitive.Sub;
|
|
28
|
+
|
|
29
|
+
const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;
|
|
30
|
+
|
|
31
|
+
function DropdownMenuSubTrigger({
|
|
32
|
+
className,
|
|
33
|
+
inset,
|
|
34
|
+
children,
|
|
35
|
+
...props
|
|
36
|
+
}: DropdownMenuPrimitive.SubTriggerProps & {
|
|
37
|
+
ref?: React.RefObject<DropdownMenuPrimitive.SubTriggerRef>;
|
|
38
|
+
className?: string;
|
|
39
|
+
inset?: boolean;
|
|
40
|
+
children?: React.ReactNode;
|
|
41
|
+
}) {
|
|
42
|
+
const { open } = DropdownMenuPrimitive.useSubContext();
|
|
43
|
+
const Icon =
|
|
44
|
+
Platform.OS === 'web' ? ChevronRight : open ? ChevronUp : ChevronDown;
|
|
45
|
+
return (
|
|
46
|
+
<TextClassContext.Provider
|
|
47
|
+
value={cn(
|
|
48
|
+
'select-none text-sm native:text-lg text-primary',
|
|
49
|
+
open && 'native:text-accent-foreground',
|
|
50
|
+
)}
|
|
51
|
+
>
|
|
52
|
+
<DropdownMenuPrimitive.SubTrigger
|
|
53
|
+
className={cn(
|
|
54
|
+
'flex flex-row web:cursor-default web:select-none gap-2 items-center web:focus:bg-accent web:hover:bg-accent active:bg-accent rounded-sm px-2 py-1.5 native:py-2 web:outline-none',
|
|
55
|
+
open && 'bg-accent',
|
|
56
|
+
inset && 'pl-8',
|
|
57
|
+
className,
|
|
58
|
+
)}
|
|
59
|
+
{...props}
|
|
60
|
+
>
|
|
61
|
+
{children}
|
|
62
|
+
<Icon size={18} className="ml-auto text-foreground" />
|
|
63
|
+
</DropdownMenuPrimitive.SubTrigger>
|
|
64
|
+
</TextClassContext.Provider>
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function DropdownMenuSubContent({
|
|
69
|
+
className,
|
|
70
|
+
...props
|
|
71
|
+
}: DropdownMenuPrimitive.SubContentProps & {
|
|
72
|
+
ref?: React.RefObject<DropdownMenuPrimitive.SubContentRef>;
|
|
73
|
+
}) {
|
|
74
|
+
const { open } = DropdownMenuPrimitive.useSubContext();
|
|
75
|
+
return (
|
|
76
|
+
<DropdownMenuPrimitive.SubContent
|
|
77
|
+
className={cn(
|
|
78
|
+
'z-50 min-w-[8rem] overflow-hidden rounded-md border border-border mt-1 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',
|
|
79
|
+
open
|
|
80
|
+
? 'web:animate-in web:fade-in-0 web:zoom-in-95'
|
|
81
|
+
: 'web:animate-out web:fade-out-0 web:zoom-out',
|
|
82
|
+
className,
|
|
83
|
+
)}
|
|
84
|
+
{...props}
|
|
85
|
+
/>
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function DropdownMenuContent({
|
|
90
|
+
className,
|
|
91
|
+
overlayClassName,
|
|
92
|
+
overlayStyle,
|
|
93
|
+
portalHost,
|
|
94
|
+
...props
|
|
95
|
+
}: DropdownMenuPrimitive.ContentProps & {
|
|
96
|
+
ref?: React.RefObject<DropdownMenuPrimitive.ContentRef>;
|
|
97
|
+
overlayStyle?: StyleProp<ViewStyle>;
|
|
98
|
+
overlayClassName?: string;
|
|
99
|
+
portalHost?: string;
|
|
100
|
+
}) {
|
|
101
|
+
const { open } = DropdownMenuPrimitive.useRootContext();
|
|
102
|
+
return (
|
|
103
|
+
<DropdownMenuPrimitive.Portal hostName={portalHost}>
|
|
104
|
+
<DropdownMenuPrimitive.Overlay
|
|
105
|
+
style={
|
|
106
|
+
overlayStyle
|
|
107
|
+
? StyleSheet.flatten([
|
|
108
|
+
Platform.OS !== 'web' ? StyleSheet.absoluteFill : undefined,
|
|
109
|
+
overlayStyle as typeof StyleSheet.absoluteFill,
|
|
110
|
+
])
|
|
111
|
+
: Platform.OS !== 'web'
|
|
112
|
+
? StyleSheet.absoluteFill
|
|
113
|
+
: undefined
|
|
114
|
+
}
|
|
115
|
+
className={overlayClassName}
|
|
116
|
+
>
|
|
117
|
+
<DropdownMenuPrimitive.Content
|
|
118
|
+
className={cn(
|
|
119
|
+
'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',
|
|
120
|
+
open
|
|
121
|
+
? 'web:animate-in web:fade-in-0 web:zoom-in-95'
|
|
122
|
+
: 'web:animate-out web:fade-out-0 web:zoom-out-95',
|
|
123
|
+
className,
|
|
124
|
+
)}
|
|
125
|
+
{...props}
|
|
126
|
+
/>
|
|
127
|
+
</DropdownMenuPrimitive.Overlay>
|
|
128
|
+
</DropdownMenuPrimitive.Portal>
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function DropdownMenuItem({
|
|
133
|
+
className,
|
|
134
|
+
inset,
|
|
135
|
+
...props
|
|
136
|
+
}: DropdownMenuPrimitive.ItemProps & {
|
|
137
|
+
ref?: React.RefObject<DropdownMenuPrimitive.ItemRef>;
|
|
138
|
+
className?: string;
|
|
139
|
+
inset?: boolean;
|
|
140
|
+
}) {
|
|
141
|
+
return (
|
|
142
|
+
<TextClassContext.Provider value="select-none text-sm native:text-lg text-popover-foreground web:group-focus:text-accent-foreground">
|
|
143
|
+
<DropdownMenuPrimitive.Item
|
|
144
|
+
className={cn(
|
|
145
|
+
'relative flex flex-row web:cursor-default gap-2 items-center 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',
|
|
146
|
+
inset && 'pl-8',
|
|
147
|
+
props.disabled && 'opacity-50 web:pointer-events-none',
|
|
148
|
+
className,
|
|
149
|
+
)}
|
|
150
|
+
{...props}
|
|
151
|
+
/>
|
|
152
|
+
</TextClassContext.Provider>
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function DropdownMenuCheckboxItem({
|
|
157
|
+
className,
|
|
158
|
+
children,
|
|
159
|
+
checked,
|
|
160
|
+
...props
|
|
161
|
+
}: DropdownMenuPrimitive.CheckboxItemProps & {
|
|
162
|
+
ref?: React.RefObject<DropdownMenuPrimitive.CheckboxItemRef>;
|
|
163
|
+
children?: React.ReactNode;
|
|
164
|
+
}) {
|
|
165
|
+
return (
|
|
166
|
+
<DropdownMenuPrimitive.CheckboxItem
|
|
167
|
+
className={cn(
|
|
168
|
+
'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',
|
|
169
|
+
props.disabled && 'web:pointer-events-none opacity-50',
|
|
170
|
+
className,
|
|
171
|
+
)}
|
|
172
|
+
checked={checked}
|
|
173
|
+
{...props}
|
|
174
|
+
>
|
|
175
|
+
<View className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
|
176
|
+
<DropdownMenuPrimitive.ItemIndicator>
|
|
177
|
+
<Check size={14} strokeWidth={3} className="text-foreground" />
|
|
178
|
+
</DropdownMenuPrimitive.ItemIndicator>
|
|
179
|
+
</View>
|
|
180
|
+
{children}
|
|
181
|
+
</DropdownMenuPrimitive.CheckboxItem>
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function DropdownMenuRadioItem({
|
|
186
|
+
className,
|
|
187
|
+
children,
|
|
188
|
+
...props
|
|
189
|
+
}: DropdownMenuPrimitive.RadioItemProps & {
|
|
190
|
+
ref?: React.RefObject<DropdownMenuPrimitive.RadioItemRef>;
|
|
191
|
+
children?: React.ReactNode;
|
|
192
|
+
}) {
|
|
193
|
+
return (
|
|
194
|
+
<DropdownMenuPrimitive.RadioItem
|
|
195
|
+
className={cn(
|
|
196
|
+
'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',
|
|
197
|
+
props.disabled && 'web:pointer-events-none opacity-50',
|
|
198
|
+
className,
|
|
199
|
+
)}
|
|
200
|
+
{...props}
|
|
201
|
+
>
|
|
202
|
+
<View className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
|
203
|
+
<DropdownMenuPrimitive.ItemIndicator>
|
|
204
|
+
<View className="bg-foreground h-2 w-2 rounded-full" />
|
|
205
|
+
</DropdownMenuPrimitive.ItemIndicator>
|
|
206
|
+
</View>
|
|
207
|
+
{children}
|
|
208
|
+
</DropdownMenuPrimitive.RadioItem>
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function DropdownMenuLabel({
|
|
213
|
+
className,
|
|
214
|
+
inset,
|
|
215
|
+
...props
|
|
216
|
+
}: DropdownMenuPrimitive.LabelProps & {
|
|
217
|
+
ref?: React.RefObject<DropdownMenuPrimitive.LabelRef>;
|
|
218
|
+
className?: string;
|
|
219
|
+
inset?: boolean;
|
|
220
|
+
}) {
|
|
221
|
+
return (
|
|
222
|
+
<DropdownMenuPrimitive.Label
|
|
223
|
+
className={cn(
|
|
224
|
+
'px-2 py-1.5 text-sm native:text-base font-semibold text-foreground web:cursor-default',
|
|
225
|
+
inset && 'pl-8',
|
|
226
|
+
className,
|
|
227
|
+
)}
|
|
228
|
+
{...props}
|
|
229
|
+
/>
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function DropdownMenuSeparator({
|
|
234
|
+
className,
|
|
235
|
+
...props
|
|
236
|
+
}: DropdownMenuPrimitive.SeparatorProps & {
|
|
237
|
+
ref?: React.RefObject<DropdownMenuPrimitive.SeparatorRef>;
|
|
238
|
+
}) {
|
|
239
|
+
return (
|
|
240
|
+
<DropdownMenuPrimitive.Separator
|
|
241
|
+
className={cn('-mx-1 my-1 h-px bg-border', className)}
|
|
242
|
+
{...props}
|
|
243
|
+
/>
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function DropdownMenuShortcut({ className, ...props }: TextProps) {
|
|
248
|
+
return (
|
|
249
|
+
<Text
|
|
250
|
+
className={cn(
|
|
251
|
+
'ml-auto text-xs native:text-sm tracking-widest text-muted-foreground',
|
|
252
|
+
className,
|
|
253
|
+
)}
|
|
254
|
+
{...props}
|
|
255
|
+
/>
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
export {
|
|
260
|
+
DropdownMenu,
|
|
261
|
+
DropdownMenuCheckboxItem,
|
|
262
|
+
DropdownMenuContent,
|
|
263
|
+
DropdownMenuGroup,
|
|
264
|
+
DropdownMenuItem,
|
|
265
|
+
DropdownMenuLabel,
|
|
266
|
+
DropdownMenuPortal,
|
|
267
|
+
DropdownMenuRadioGroup,
|
|
268
|
+
DropdownMenuRadioItem,
|
|
269
|
+
DropdownMenuSeparator,
|
|
270
|
+
DropdownMenuShortcut,
|
|
271
|
+
DropdownMenuSub,
|
|
272
|
+
DropdownMenuSubContent,
|
|
273
|
+
DropdownMenuSubTrigger,
|
|
274
|
+
DropdownMenuTrigger,
|
|
275
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { TextInput, type TextInputProps } from 'react-native';
|
|
3
|
+
import { cn } from '~/lib/utils';
|
|
4
|
+
|
|
5
|
+
function Input({
|
|
6
|
+
className,
|
|
7
|
+
placeholderClassName,
|
|
8
|
+
...props
|
|
9
|
+
}: TextInputProps & {
|
|
10
|
+
ref?: React.RefObject<TextInput>;
|
|
11
|
+
}) {
|
|
12
|
+
return (
|
|
13
|
+
<TextInput
|
|
14
|
+
className={cn(
|
|
15
|
+
'web:flex h-10 native:h-12 web:w-full rounded-md border border-input bg-background px-3 web:py-2 text-base lg:text-sm native:text-lg native:leading-[1.25] text-foreground placeholder:text-muted-foreground web:ring-offset-background file:border-0 file:bg-transparent file:font-medium web:focus-visible:outline-none web:focus-visible:ring-2 web:focus-visible:ring-ring web:focus-visible:ring-offset-2',
|
|
16
|
+
props.editable === false && 'opacity-50 web:cursor-not-allowed',
|
|
17
|
+
className,
|
|
18
|
+
)}
|
|
19
|
+
placeholderClassName={cn('text-muted-foreground', placeholderClassName)}
|
|
20
|
+
{...props}
|
|
21
|
+
/>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export { Input };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import * as LabelPrimitive from '@rn-primitives/label';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { cn } from '~/lib/utils';
|
|
4
|
+
|
|
5
|
+
function Label({
|
|
6
|
+
className,
|
|
7
|
+
onPress,
|
|
8
|
+
onLongPress,
|
|
9
|
+
onPressIn,
|
|
10
|
+
onPressOut,
|
|
11
|
+
...props
|
|
12
|
+
}: LabelPrimitive.TextProps & {
|
|
13
|
+
ref?: React.RefObject<LabelPrimitive.TextRef>;
|
|
14
|
+
}) {
|
|
15
|
+
return (
|
|
16
|
+
<LabelPrimitive.Root
|
|
17
|
+
className="web:cursor-default"
|
|
18
|
+
onPress={onPress}
|
|
19
|
+
onLongPress={onLongPress}
|
|
20
|
+
onPressIn={onPressIn}
|
|
21
|
+
onPressOut={onPressOut}
|
|
22
|
+
>
|
|
23
|
+
<LabelPrimitive.Text
|
|
24
|
+
className={cn(
|
|
25
|
+
'text-sm text-foreground native:text-base font-medium leading-none web:peer-disabled:cursor-not-allowed web:peer-disabled:opacity-70',
|
|
26
|
+
className,
|
|
27
|
+
)}
|
|
28
|
+
{...props}
|
|
29
|
+
/>
|
|
30
|
+
</LabelPrimitive.Root>
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export { Label };
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import * as NavigationMenuPrimitive from '@rn-primitives/navigation-menu';
|
|
2
|
+
import { cva } from 'class-variance-authority';
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { Platform, View } from 'react-native';
|
|
5
|
+
import Animated, {
|
|
6
|
+
Extrapolation,
|
|
7
|
+
FadeInLeft,
|
|
8
|
+
FadeOutLeft,
|
|
9
|
+
interpolate,
|
|
10
|
+
useAnimatedStyle,
|
|
11
|
+
useDerivedValue,
|
|
12
|
+
withTiming,
|
|
13
|
+
} from 'react-native-reanimated';
|
|
14
|
+
import { ChevronDown } from '~/lib/icons/ChevronDown';
|
|
15
|
+
import { cn } from '~/lib/utils';
|
|
16
|
+
|
|
17
|
+
function NavigationMenu({
|
|
18
|
+
className,
|
|
19
|
+
children,
|
|
20
|
+
...props
|
|
21
|
+
}: NavigationMenuPrimitive.RootProps & {
|
|
22
|
+
ref?: React.RefObject<NavigationMenuPrimitive.RootRef>;
|
|
23
|
+
}) {
|
|
24
|
+
return (
|
|
25
|
+
<NavigationMenuPrimitive.Root
|
|
26
|
+
className={cn(
|
|
27
|
+
'relative z-10 flex flex-row max-w-max items-center justify-center',
|
|
28
|
+
className,
|
|
29
|
+
)}
|
|
30
|
+
{...props}
|
|
31
|
+
>
|
|
32
|
+
{children}
|
|
33
|
+
{Platform.OS === 'web' && <NavigationMenuViewport />}
|
|
34
|
+
</NavigationMenuPrimitive.Root>
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function NavigationMenuList({
|
|
39
|
+
className,
|
|
40
|
+
...props
|
|
41
|
+
}: NavigationMenuPrimitive.ListProps & {
|
|
42
|
+
ref?: React.RefObject<NavigationMenuPrimitive.ListRef>;
|
|
43
|
+
}) {
|
|
44
|
+
return (
|
|
45
|
+
<NavigationMenuPrimitive.List
|
|
46
|
+
className={cn(
|
|
47
|
+
'web:group flex flex-1 flex-row web:list-none items-center justify-center gap-1',
|
|
48
|
+
className,
|
|
49
|
+
)}
|
|
50
|
+
{...props}
|
|
51
|
+
/>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const NavigationMenuItem = NavigationMenuPrimitive.Item;
|
|
56
|
+
|
|
57
|
+
const navigationMenuTriggerStyle = cva(
|
|
58
|
+
'web:group web:inline-flex flex-row h-10 native:h-12 native:px-3 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium web:transition-colors web:hover:bg-accent active:bg-accent web:hover:text-accent-foreground web:focus:bg-accent web:focus:text-accent-foreground web:focus:outline-none web:disabled:pointer-events-none disabled:opacity-50 web:data-[active]:bg-accent/50 web:data-[state=open]:bg-accent/50',
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
function NavigationMenuTrigger({
|
|
62
|
+
className,
|
|
63
|
+
children,
|
|
64
|
+
...props
|
|
65
|
+
}: Omit<NavigationMenuPrimitive.TriggerProps, 'children'> & {
|
|
66
|
+
children?: React.ReactNode;
|
|
67
|
+
ref?: React.RefObject<NavigationMenuPrimitive.TriggerRef>;
|
|
68
|
+
}) {
|
|
69
|
+
const { value } = NavigationMenuPrimitive.useRootContext();
|
|
70
|
+
const { value: itemValue } = NavigationMenuPrimitive.useItemContext();
|
|
71
|
+
|
|
72
|
+
const progress = useDerivedValue(() =>
|
|
73
|
+
value === itemValue
|
|
74
|
+
? withTiming(1, { duration: 250 })
|
|
75
|
+
: withTiming(0, { duration: 200 }),
|
|
76
|
+
);
|
|
77
|
+
const chevronStyle = useAnimatedStyle(() => ({
|
|
78
|
+
transform: [{ rotate: `${progress.value * 180}deg` }],
|
|
79
|
+
opacity: interpolate(progress.value, [0, 1], [1, 0.8], Extrapolation.CLAMP),
|
|
80
|
+
}));
|
|
81
|
+
|
|
82
|
+
return (
|
|
83
|
+
<NavigationMenuPrimitive.Trigger
|
|
84
|
+
className={cn(
|
|
85
|
+
navigationMenuTriggerStyle(),
|
|
86
|
+
'web:group gap-1.5',
|
|
87
|
+
value === itemValue && 'bg-accent',
|
|
88
|
+
className,
|
|
89
|
+
)}
|
|
90
|
+
{...props}
|
|
91
|
+
>
|
|
92
|
+
{children}
|
|
93
|
+
<Animated.View style={chevronStyle}>
|
|
94
|
+
<ChevronDown
|
|
95
|
+
size={12}
|
|
96
|
+
className={cn(
|
|
97
|
+
'relative text-foreground h-3 w-3 web:transition web:duration-200',
|
|
98
|
+
)}
|
|
99
|
+
aria-hidden={true}
|
|
100
|
+
/>
|
|
101
|
+
</Animated.View>
|
|
102
|
+
</NavigationMenuPrimitive.Trigger>
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function NavigationMenuContent({
|
|
107
|
+
className,
|
|
108
|
+
children,
|
|
109
|
+
portalHost,
|
|
110
|
+
...props
|
|
111
|
+
}: NavigationMenuPrimitive.ContentProps & {
|
|
112
|
+
portalHost?: string;
|
|
113
|
+
ref?: React.RefObject<NavigationMenuPrimitive.ContentRef>;
|
|
114
|
+
}) {
|
|
115
|
+
const { value } = NavigationMenuPrimitive.useRootContext();
|
|
116
|
+
const { value: itemValue } = NavigationMenuPrimitive.useItemContext();
|
|
117
|
+
return (
|
|
118
|
+
<NavigationMenuPrimitive.Portal hostName={portalHost}>
|
|
119
|
+
<NavigationMenuPrimitive.Content
|
|
120
|
+
className={cn(
|
|
121
|
+
'w-full native:border native:border-border native:rounded-lg native:shadow-lg native:bg-popover native:text-popover-foreground native:overflow-hidden',
|
|
122
|
+
value === itemValue
|
|
123
|
+
? 'web:animate-in web:fade-in web:slide-in-from-right-20'
|
|
124
|
+
: 'web:animate-out web:fade-out web:slide-out-to-left-20',
|
|
125
|
+
className,
|
|
126
|
+
)}
|
|
127
|
+
{...props}
|
|
128
|
+
>
|
|
129
|
+
<Animated.View
|
|
130
|
+
entering={Platform.OS !== 'web' ? FadeInLeft : undefined}
|
|
131
|
+
exiting={Platform.OS !== 'web' ? FadeOutLeft : undefined}
|
|
132
|
+
>
|
|
133
|
+
{children}
|
|
134
|
+
</Animated.View>
|
|
135
|
+
</NavigationMenuPrimitive.Content>
|
|
136
|
+
</NavigationMenuPrimitive.Portal>
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const NavigationMenuLink = NavigationMenuPrimitive.Link;
|
|
141
|
+
|
|
142
|
+
function NavigationMenuViewport({
|
|
143
|
+
className,
|
|
144
|
+
...props
|
|
145
|
+
}: NavigationMenuPrimitive.ViewportProps & {
|
|
146
|
+
ref?: React.RefObject<NavigationMenuPrimitive.ViewportRef>;
|
|
147
|
+
}) {
|
|
148
|
+
return (
|
|
149
|
+
<View className={cn('fixed right-0 top-12 mr-2 ml-2 flex justify-center')}>
|
|
150
|
+
<View
|
|
151
|
+
className={cn(
|
|
152
|
+
'web:origin-top-center relative mt-1.5 web:h-[var(--radix-navigation-menu-viewport-height)] w-full overflow-hidden rounded-md border border-border bg-popover text-popover-foreground shadow-lg web:animate-in web:zoom-in-90',
|
|
153
|
+
className,
|
|
154
|
+
)}
|
|
155
|
+
{...props}
|
|
156
|
+
>
|
|
157
|
+
<NavigationMenuPrimitive.Viewport />
|
|
158
|
+
</View>
|
|
159
|
+
</View>
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function NavigationMenuIndicator({
|
|
164
|
+
ref,
|
|
165
|
+
className,
|
|
166
|
+
...props
|
|
167
|
+
}: NavigationMenuPrimitive.IndicatorProps & {
|
|
168
|
+
ref?: React.RefObject<NavigationMenuPrimitive.IndicatorRef>;
|
|
169
|
+
}) {
|
|
170
|
+
const { value } = NavigationMenuPrimitive.useRootContext();
|
|
171
|
+
const { value: itemValue } = NavigationMenuPrimitive.useItemContext();
|
|
172
|
+
|
|
173
|
+
return (
|
|
174
|
+
<NavigationMenuPrimitive.Indicator
|
|
175
|
+
ref={ref}
|
|
176
|
+
className={cn(
|
|
177
|
+
'top-full z-[1] flex h-1.5 items-end justify-center overflow-hidden',
|
|
178
|
+
value === itemValue
|
|
179
|
+
? 'web:animate-in web:fade-in'
|
|
180
|
+
: 'web:animate-out web:fade-out',
|
|
181
|
+
className,
|
|
182
|
+
)}
|
|
183
|
+
{...props}
|
|
184
|
+
>
|
|
185
|
+
<View className="relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm bg-border shadow-md shadow-foreground/5" />
|
|
186
|
+
</NavigationMenuPrimitive.Indicator>
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export {
|
|
191
|
+
NavigationMenu,
|
|
192
|
+
NavigationMenuContent,
|
|
193
|
+
NavigationMenuIndicator,
|
|
194
|
+
NavigationMenuItem,
|
|
195
|
+
NavigationMenuLink,
|
|
196
|
+
NavigationMenuList,
|
|
197
|
+
NavigationMenuTrigger,
|
|
198
|
+
navigationMenuTriggerStyle,
|
|
199
|
+
NavigationMenuViewport,
|
|
200
|
+
};
|