linked-data-browser 0.0.6 → 0.0.8-alpha.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 (103) hide show
  1. package/.env +2 -0
  2. package/.eslintrc.js +1 -0
  3. package/.ldo/profile.shapeTypes.ts +18 -18
  4. package/.ldo/profile.typings.ts +17 -17
  5. package/app/index.tsx +3 -0
  6. package/babel.config.js +9 -1
  7. package/components/DataBrowser.tsx +9 -19
  8. package/components/DataBrowserContext.ts +24 -0
  9. package/components/TargetResourceProvider.tsx +1 -1
  10. package/components/ThemeProvider.tsx +2 -4
  11. package/components/common/LoadingBar.tsx +11 -1
  12. package/components/common/ProfileAvatar.tsx +6 -9
  13. package/components/nav/Layout.tsx +20 -4
  14. package/components/nav/header/AddressBox.tsx +104 -48
  15. package/components/nav/header/AvatarMenu.tsx +44 -12
  16. package/components/nav/header/Header.tsx +26 -19
  17. package/components/nav/header/SignInMenu.tsx +63 -36
  18. package/components/nav/header/ThemeToggleMenu.tsx +21 -9
  19. package/components/nav/header/ViewMenu.tsx +79 -71
  20. package/components/sharing/AccessDropdown.tsx +18 -7
  21. package/components/sharing/CopyLink.tsx +15 -3
  22. package/components/sharing/PermissionRow.tsx +17 -2
  23. package/components/sharing/SharingModal.tsx +30 -3
  24. package/components/sharing/WacRuleForm.tsx +12 -3
  25. package/components/sharing/agentPermissions/AgentInformation.tsx +18 -6
  26. package/components/sharing/agentPermissions/AgentInput.tsx +21 -6
  27. package/components/sharing/agentPermissions/AgentPermissionRow.tsx +24 -6
  28. package/components/ui/accordion.tsx +1 -1
  29. package/components/ui/alert.tsx +62 -46
  30. package/components/ui/avatar.tsx +38 -13
  31. package/components/ui/badge.tsx +63 -48
  32. package/components/ui/button.tsx +226 -108
  33. package/components/ui/card.tsx +53 -38
  34. package/components/ui/checkbox.tsx +53 -16
  35. package/components/ui/context-menu.tsx +4 -4
  36. package/components/ui/dialog.tsx +116 -65
  37. package/components/ui/dropdown-menu.tsx +304 -105
  38. package/components/ui/icon.tsx +23 -0
  39. package/components/ui/input-dropdown.tsx +42 -5
  40. package/components/ui/input.tsx +85 -22
  41. package/components/ui/label.tsx +16 -7
  42. package/components/ui/menubar.tsx +4 -4
  43. package/components/ui/navigation-menu.tsx +157 -90
  44. package/components/ui/progress.tsx +38 -24
  45. package/components/ui/select.tsx +139 -67
  46. package/components/ui/separator.tsx +22 -7
  47. package/components/ui/skeleton.tsx +14 -11
  48. package/components/ui/switch.tsx +82 -37
  49. package/components/ui/table.tsx +57 -35
  50. package/components/ui/tabs.tsx +66 -35
  51. package/components/ui/text.tsx +221 -30
  52. package/components/ui/textarea.tsx +34 -10
  53. package/components/ui/typography.tsx +94 -65
  54. package/components/useViewContext.tsx +8 -8
  55. package/global.css +93 -3
  56. package/metro.config.js +21 -3
  57. package/package.json +6 -9
  58. package/resourceViews/Container/ContainerConfig.tsx +1 -1
  59. package/resourceViews/Container/ContainerView.tsx +63 -25
  60. package/resourceViews/Profile/ProfileConfig.tsx +3 -3
  61. package/resourceViews/Profile/ProfileKnows.tsx +20 -11
  62. package/resourceViews/Profile/ProfileView.tsx +23 -6
  63. package/resourceViews/RawCode/RawCodeConfig.tsx +1 -1
  64. package/resourceViews/RawCode/RawCodeView.tsx +20 -6
  65. package/components.json +0 -7
  66. package/lib/icons/ArrowRight.tsx +0 -4
  67. package/lib/icons/Check.tsx +0 -4
  68. package/lib/icons/ChevronDown.tsx +0 -4
  69. package/lib/icons/ChevronRight.tsx +0 -4
  70. package/lib/icons/ChevronUp.tsx +0 -4
  71. package/lib/icons/ChevronsRight.tsx +0 -4
  72. package/lib/icons/CircleSlash.tsx +0 -4
  73. package/lib/icons/CircleX.tsx +0 -4
  74. package/lib/icons/Code.tsx +0 -4
  75. package/lib/icons/EllipsisVertical.tsx +0 -4
  76. package/lib/icons/EyeOff.tsx +0 -4
  77. package/lib/icons/File.tsx +0 -4
  78. package/lib/icons/Fingerprint.tsx +0 -4
  79. package/lib/icons/Folder.tsx +0 -4
  80. package/lib/icons/Folders.tsx +0 -4
  81. package/lib/icons/Info.tsx +0 -4
  82. package/lib/icons/Link.tsx +0 -4
  83. package/lib/icons/Loader.tsx +0 -4
  84. package/lib/icons/LogOut.tsx +0 -4
  85. package/lib/icons/MonitorSmartphone.tsx +0 -4
  86. package/lib/icons/MoonStar.tsx +0 -4
  87. package/lib/icons/OctagonX.tsx +0 -4
  88. package/lib/icons/Plus.tsx +0 -4
  89. package/lib/icons/RefreshCw.tsx +0 -4
  90. package/lib/icons/Save.tsx +0 -4
  91. package/lib/icons/ShieldX.tsx +0 -4
  92. package/lib/icons/Sun.tsx +0 -4
  93. package/lib/icons/TextCursorInput.tsx +0 -4
  94. package/lib/icons/Trash.tsx +0 -4
  95. package/lib/icons/User.tsx +0 -4
  96. package/lib/icons/UserPlus.tsx +0 -4
  97. package/lib/icons/Users.tsx +0 -4
  98. package/lib/icons/ViewIcon.tsx +0 -4
  99. package/lib/icons/X.tsx +0 -4
  100. package/lib/icons/iconWithClassName.ts +0 -14
  101. package/lib/utils.ts +0 -6
  102. package/nativewind-env.d.ts +0 -1
  103. package/tailwind.config.js +0 -69
@@ -8,6 +8,8 @@ import React, {
8
8
  useMemo,
9
9
  useState,
10
10
  } from 'react';
11
+ import { StyleSheet, useWindowDimensions } from 'react-native';
12
+ import { useTheme } from '@react-navigation/native';
11
13
  import {
12
14
  Dialog,
13
15
  DialogContent,
@@ -50,6 +52,7 @@ export const SharingModalProvider: FunctionComponent<PropsWithChildren<{}>> = ({
50
52
  children,
51
53
  }) => {
52
54
  const { targetResource } = useViewContext();
55
+ const { colors } = useTheme();
53
56
  const [isOpen, setIsOpen] = useState(false);
54
57
  const [wacResult, setWacResult] = useState<
55
58
  | GetWacRuleError<SolidLeaf | SolidContainer>
@@ -62,6 +65,7 @@ export const SharingModalProvider: FunctionComponent<PropsWithChildren<{}>> = ({
62
65
  authenticated: { read: false, write: false, append: false, control: false },
63
66
  agent: {},
64
67
  });
68
+ const { width, height } = useWindowDimensions();
65
69
 
66
70
  useEffect(() => {
67
71
  if (
@@ -116,17 +120,26 @@ export const SharingModalProvider: FunctionComponent<PropsWithChildren<{}>> = ({
116
120
  return (
117
121
  <sharingModalContext.Provider value={context}>
118
122
  <Dialog open={isOpen} onOpenChange={(value) => setIsOpen(value)}>
119
- <DialogContent className="sm:w-[640px] w-[95vw] h-[95vh]">
123
+ <DialogContent
124
+ style={{
125
+ width: width > 640 ? 640 : width * 0.95,
126
+ height: height * 0.95,
127
+ }}
128
+ >
120
129
  <LoadingBar isLoading={isLoading} />
121
130
  <DialogHeader>
122
131
  <DialogTitle>Resource Sharing Preferences</DialogTitle>
123
132
  </DialogHeader>
124
- <ScrollView className="flex-1 border-border border-b border-t pt-2 pb-2 ml-[-24px] mr-[-24px] pl-6 pr-6">
133
+ <ScrollView
134
+ style={[{ borderColor: colors.border }, styles.scrollView]}
135
+ >
125
136
  {(() => {
126
137
  if (!wacResult) return <></>;
127
138
  if (wacResult.isError) {
128
139
  return (
129
- <Text className="color-red-800">{wacResult.message}</Text>
140
+ <Text style={{ color: colors.notification }}>
141
+ {wacResult.message}
142
+ </Text>
130
143
  );
131
144
  }
132
145
  return (
@@ -147,3 +160,17 @@ export const SharingModalProvider: FunctionComponent<PropsWithChildren<{}>> = ({
147
160
  </sharingModalContext.Provider>
148
161
  );
149
162
  };
163
+
164
+ const styles = StyleSheet.create({
165
+ scrollView: {
166
+ flex: 1,
167
+ borderTopWidth: 1,
168
+ borderBottomWidth: 1,
169
+ paddingTop: 8,
170
+ paddingBottom: 8,
171
+ marginLeft: -24,
172
+ marginRight: -24,
173
+ paddingLeft: 24,
174
+ paddingRight: 24,
175
+ },
176
+ });
@@ -1,12 +1,13 @@
1
1
  import React from 'react';
2
+ import { StyleSheet } from 'react-native';
2
3
  import { Separator } from '../ui/separator';
3
4
  import { FunctionComponent } from 'react';
4
5
  import { AgentPermissions } from './agentPermissions/AgentPermissions';
5
6
  import { WacRule } from '@ldo/connected-solid';
6
7
  import { View } from 'react-native';
7
8
  import { PermissionRow } from './PermissionRow';
8
- import { Users } from '../../lib/icons/Users';
9
- import { Fingerprint } from '../../lib/icons/Fingerprint';
9
+ import { Users } from 'lucide-react-native';
10
+ import { Fingerprint } from 'lucide-react-native';
10
11
 
11
12
  interface WacRuleFormProps {
12
13
  value: WacRule;
@@ -18,7 +19,7 @@ export const WacRuleForm: FunctionComponent<WacRuleFormProps> = ({
18
19
  onChange,
19
20
  }) => {
20
21
  return (
21
- <View className="gap-4 mt-2 mb-2">
22
+ <View style={styles.container}>
22
23
  <PermissionRow
23
24
  displayName="Public Access"
24
25
  Icon={Users}
@@ -42,3 +43,11 @@ export const WacRuleForm: FunctionComponent<WacRuleFormProps> = ({
42
43
  </View>
43
44
  );
44
45
  };
46
+
47
+ const styles = StyleSheet.create({
48
+ container: {
49
+ gap: 16,
50
+ marginTop: 8,
51
+ marginBottom: 8,
52
+ },
53
+ });
@@ -1,7 +1,7 @@
1
- import { SolidProfileShapeShapeType } from '../../../.ldo/profile.shapeTypes';
1
+ import { SolidProfileShapeType } from '../../../.ldo/profile.shapeTypes';
2
2
  import { useResource, useSolidAuth, useSubject } from '@ldo/solid-react';
3
3
  import React, { FunctionComponent, ReactNode } from 'react';
4
- import { View } from 'react-native';
4
+ import { View, StyleSheet } from 'react-native';
5
5
  import { ProfileAvatar } from '../../common/ProfileAvatar';
6
6
  import { Text } from '../../ui/text';
7
7
 
@@ -16,12 +16,12 @@ export const AgentInformation: FunctionComponent<AgentInformationProps> = ({
16
16
  }) => {
17
17
  const { session } = useSolidAuth();
18
18
  useResource(webId);
19
- const agentProfile = useSubject(SolidProfileShapeShapeType, webId);
19
+ const agentProfile = useSubject(SolidProfileShapeType, webId);
20
20
 
21
21
  return (
22
- <View className="flex-row gap-4 flex-1 items-center">
22
+ <View style={styles.container}>
23
23
  <ProfileAvatar profile={agentProfile} />
24
- <View className="flex-1">
24
+ <View style={styles.textContainer}>
25
25
  <Text>
26
26
  {agentProfile['@id'] === session.webId
27
27
  ? 'You'
@@ -31,7 +31,19 @@ export const AgentInformation: FunctionComponent<AgentInformationProps> = ({
31
31
  {webId}
32
32
  </Text>
33
33
  </View>
34
- {accessoryRight && <View>{accessoryRight}</View>}
34
+ {accessoryRight}
35
35
  </View>
36
36
  );
37
37
  };
38
+
39
+ const styles = StyleSheet.create({
40
+ container: {
41
+ flexDirection: 'row',
42
+ gap: 16,
43
+ flex: 1,
44
+ alignItems: 'center',
45
+ },
46
+ textContainer: {
47
+ flex: 1,
48
+ },
49
+ });
@@ -1,12 +1,14 @@
1
1
  import React, { useCallback, useMemo, useState } from 'react';
2
+ import { StyleSheet } from 'react-native';
3
+ import { useTheme } from '@react-navigation/native';
2
4
  import { FunctionComponent } from 'react';
3
5
  import { Pressable } from 'react-native';
4
6
  import { useLinkQuery, useSolidAuth } from '@ldo/solid-react';
5
- import { SolidProfileShapeShapeType } from '../../../.ldo/profile.shapeTypes';
7
+ import { SolidProfileShapeType } from '../../../.ldo/profile.shapeTypes';
6
8
  import { AgentInformation } from './AgentInformation';
7
9
  import { InputDropdown } from '../../ui/input-dropdown';
8
10
  import { useContactFilter } from './useContactFilter';
9
- import { Plus } from '../../../lib/icons/Plus';
11
+ import { Plus } from 'lucide-react-native';
10
12
 
11
13
  interface AgentInputProps {
12
14
  onAddAgent: (webId: string) => void;
@@ -19,9 +21,14 @@ const ContactDropdownItem: FunctionComponent<{
19
21
  webId: string;
20
22
  onSelect: (webId: string) => void;
21
23
  }> = ({ webId, onSelect }) => {
24
+ const { colors } = useTheme();
22
25
  return (
23
26
  <Pressable
24
- className="p-2 border-b border-border last:border-b-0 hover:bg-accent active:bg-accent cursor-pointer"
27
+ style={({ hovered }) => [
28
+ styles.dropdownItem,
29
+ { borderBottomColor: colors.border },
30
+ hovered && { backgroundColor: colors.border },
31
+ ]}
25
32
  onPress={() => onSelect(webId)}
26
33
  >
27
34
  <AgentInformation webId={webId} />
@@ -46,7 +53,7 @@ export const AgentInput: FunctionComponent<AgentInputProps> = ({
46
53
 
47
54
  // Get current user's profile to access their "knows" list
48
55
  const currentUserProfile = useLinkQuery(
49
- SolidProfileShapeShapeType,
56
+ SolidProfileShapeType,
50
57
  session.webId!,
51
58
  session.webId!,
52
59
  friendsLinkQuery,
@@ -115,12 +122,20 @@ export const AgentInput: FunctionComponent<AgentInputProps> = ({
115
122
  renderItem={renderContactItem}
116
123
  filterItems={filterContacts}
117
124
  buttonRight={{
118
- iconRight: <Plus />,
125
+ iconRight: Plus,
119
126
  onPress: handleInputSubmit,
120
127
  variant: 'secondary',
121
128
  }}
122
129
  onItemSelect={handleContactSelect}
123
- className={className}
130
+ style={className ? { zIndex: 999 } : undefined}
124
131
  />
125
132
  );
126
133
  };
134
+
135
+ const styles = StyleSheet.create({
136
+ dropdownItem: {
137
+ padding: 8,
138
+ borderBottomWidth: 1,
139
+ // hover and active states handled by Pressable
140
+ },
141
+ });
@@ -1,12 +1,12 @@
1
1
  import React from 'react';
2
+ import { StyleSheet } from 'react-native';
2
3
  import { AccessModeList } from '@ldo/connected-solid';
3
- import { Text } from '../../ui/text';
4
4
  import { FunctionComponent } from 'react';
5
5
  import { AgentInformation } from './AgentInformation';
6
6
  import { AccessDropdown } from '../AccessDropdown';
7
7
  import { View } from 'react-native';
8
8
  import { Button } from '../../ui/button';
9
- import { Trash } from '../../../lib/icons/Trash';
9
+ import { Trash } from 'lucide-react-native';
10
10
 
11
11
  interface AgentPermissionRowProps {
12
12
  webId: string;
@@ -20,17 +20,35 @@ export const AgentPermissionRow: FunctionComponent<AgentPermissionRowProps> = ({
20
20
  onChange,
21
21
  }) => {
22
22
  return (
23
- <View className="flex-row justify-between align-center">
23
+ <View style={styles.container}>
24
24
  <AgentInformation webId={webId} />
25
- <View className="flex-row">
25
+ <View style={styles.rightSection}>
26
26
  <Button
27
27
  variant="ghost"
28
28
  onPress={() => onChange(undefined)}
29
- className="w-10"
30
- iconLeft={<Trash size={14} />}
29
+ style={styles.deleteButton}
30
+ iconLeft={Trash}
31
+ textStyle={styles.deleteButtonText}
31
32
  />
32
33
  <AccessDropdown value={value} onChange={onChange} />
33
34
  </View>
34
35
  </View>
35
36
  );
36
37
  };
38
+
39
+ const styles = StyleSheet.create({
40
+ container: {
41
+ flexDirection: 'row',
42
+ justifyContent: 'space-between',
43
+ alignItems: 'center',
44
+ },
45
+ rightSection: {
46
+ flexDirection: 'row',
47
+ },
48
+ deleteButton: {
49
+ width: 40,
50
+ },
51
+ deleteButtonText: {
52
+ fontSize: 14,
53
+ },
54
+ });
@@ -12,7 +12,7 @@ import Animated, {
12
12
  useDerivedValue,
13
13
  withTiming,
14
14
  } from 'react-native-reanimated';
15
- import { ChevronDown } from '../../lib/icons/ChevronDown';
15
+ import { ChevronDown } from 'lucide-react-native';
16
16
  import { cn } from '../../lib/utils';
17
17
  import { TextClassContext } from '../../components/ui/text';
18
18
 
@@ -1,48 +1,34 @@
1
1
  import { useTheme } from '@react-navigation/native';
2
- import { cva, type VariantProps } from 'class-variance-authority';
3
2
  import type { LucideIcon } from 'lucide-react-native';
4
3
  import * as React from 'react';
5
- import { View, type ViewProps } from 'react-native';
6
- import { cn } from '../../lib/utils';
4
+ import { View, type ViewProps, StyleSheet } from 'react-native';
7
5
  import { Text } from '../../components/ui/text';
8
6
 
9
- const alertVariants = cva(
10
- 'relative bg-background w-full rounded-lg border border-border p-4 shadow shadow-foreground/10',
11
- {
12
- variants: {
13
- variant: {
14
- default: '',
15
- destructive: 'border-destructive',
16
- },
17
- },
18
- defaultVariants: {
19
- variant: 'default',
20
- },
21
- },
22
- );
7
+ type AlertVariant = 'default' | 'destructive';
8
+
9
+ interface AlertProps extends ViewProps {
10
+ ref?: React.RefObject<View>;
11
+ icon: LucideIcon;
12
+ iconSize?: number;
13
+ variant?: AlertVariant;
14
+ }
23
15
 
24
16
  function Alert({
25
- className,
26
- variant,
17
+ style,
18
+ variant = 'default',
27
19
  children,
28
20
  icon: Icon,
29
21
  iconSize = 16,
30
22
  ...props
31
- }: ViewProps &
32
- VariantProps<typeof alertVariants> & {
33
- ref?: React.RefObject<View>;
34
- icon: LucideIcon;
35
- iconSize?: number;
36
- iconClassName?: string;
37
- }) {
23
+ }: AlertProps) {
38
24
  const { colors } = useTheme();
39
25
  return (
40
26
  <View
41
27
  role="alert"
42
- className={alertVariants({ variant, className })}
28
+ style={StyleSheet.flatten([styles.base, styles[variant], style])}
43
29
  {...props}
44
30
  >
45
- <View className="absolute left-3.5 top-4 -translate-y-0.5">
31
+ <View style={styles.icon}>
46
32
  <Icon
47
33
  size={iconSize}
48
34
  color={variant === 'destructive' ? colors.notification : colors.text}
@@ -53,31 +39,61 @@ function Alert({
53
39
  );
54
40
  }
55
41
 
56
- function AlertTitle({
57
- className,
58
- ...props
59
- }: React.ComponentProps<typeof Text>) {
60
- return (
61
- <Text
62
- className={cn(
63
- 'pl-7 mb-1 font-medium text-base leading-none tracking-tight text-foreground',
64
- className,
65
- )}
66
- {...props}
67
- />
68
- );
42
+ function AlertTitle({ style, ...props }: React.ComponentProps<typeof Text>) {
43
+ return <Text style={StyleSheet.flatten([styles.title, style])} {...props} />;
69
44
  }
70
45
 
71
46
  function AlertDescription({
72
- className,
47
+ style,
73
48
  ...props
74
49
  }: React.ComponentProps<typeof Text>) {
75
50
  return (
76
- <Text
77
- className={cn('pl-7 text-sm leading-relaxed text-foreground', className)}
78
- {...props}
79
- />
51
+ <Text style={StyleSheet.flatten([styles.description, style])} {...props} />
80
52
  );
81
53
  }
82
54
 
55
+ const styles = StyleSheet.create({
56
+ base: {
57
+ position: 'relative',
58
+ backgroundColor: 'hsl(var(--background))',
59
+ width: '100%',
60
+ borderRadius: 8,
61
+ borderWidth: 1,
62
+ borderColor: 'hsl(var(--border))',
63
+ padding: 16,
64
+ shadowColor: 'hsl(var(--foreground))',
65
+ shadowOffset: { width: 0, height: 0 },
66
+ shadowOpacity: 0.1,
67
+ shadowRadius: 4,
68
+ elevation: 2,
69
+ },
70
+ default: {
71
+ // no additional styles
72
+ },
73
+ destructive: {
74
+ borderColor: 'hsl(var(--destructive))',
75
+ },
76
+ icon: {
77
+ position: 'absolute',
78
+ left: 14,
79
+ top: 16,
80
+ transform: [{ translateY: -2 }],
81
+ },
82
+ title: {
83
+ paddingLeft: 28,
84
+ marginBottom: 4,
85
+ fontWeight: '500',
86
+ fontSize: 16,
87
+ lineHeight: 16,
88
+ letterSpacing: -0.025,
89
+ color: 'hsl(var(--foreground))',
90
+ },
91
+ description: {
92
+ paddingLeft: 28,
93
+ fontSize: 14,
94
+ lineHeight: 20,
95
+ color: 'hsl(var(--foreground))',
96
+ },
97
+ });
98
+
83
99
  export { Alert, AlertDescription, AlertTitle };
@@ -1,53 +1,78 @@
1
+ import { useTheme } from '@react-navigation/native';
1
2
  import * as AvatarPrimitive from '@rn-primitives/avatar';
2
3
  import * as React from 'react';
3
- import { cn } from '../../lib/utils';
4
+ import { StyleSheet } from 'react-native';
4
5
 
5
6
  function Avatar({
6
- className,
7
+ style,
7
8
  ...props
8
9
  }: AvatarPrimitive.RootProps & {
9
10
  ref?: React.RefObject<AvatarPrimitive.RootRef>;
10
11
  }) {
11
12
  return (
12
13
  <AvatarPrimitive.Root
13
- className={cn(
14
- 'relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full',
15
- className,
16
- )}
14
+ style={StyleSheet.flatten([styles.avatar, style])}
17
15
  {...props}
18
16
  />
19
17
  );
20
18
  }
21
19
 
22
20
  function AvatarImage({
23
- className,
21
+ style,
24
22
  ...props
25
23
  }: AvatarPrimitive.ImageProps & {
26
24
  ref?: React.RefObject<AvatarPrimitive.ImageRef>;
27
25
  }) {
28
26
  return (
29
27
  <AvatarPrimitive.Image
30
- className={cn('aspect-square h-full w-full', className)}
28
+ style={StyleSheet.flatten([styles.image, style])}
31
29
  {...props}
32
30
  />
33
31
  );
34
32
  }
35
33
 
36
34
  function AvatarFallback({
37
- className,
35
+ style,
38
36
  ...props
39
37
  }: AvatarPrimitive.FallbackProps & {
40
38
  ref?: React.RefObject<AvatarPrimitive.FallbackRef>;
41
39
  }) {
40
+ const { colors } = useTheme();
42
41
  return (
43
42
  <AvatarPrimitive.Fallback
44
- className={cn(
45
- 'flex h-full w-full items-center justify-center rounded-full bg-muted',
46
- className,
47
- )}
43
+ style={StyleSheet.flatten([
44
+ styles.fallback,
45
+ { backgroundColor: colors.border },
46
+ style,
47
+ ])}
48
48
  {...props}
49
49
  />
50
50
  );
51
51
  }
52
52
 
53
+ const styles = StyleSheet.create({
54
+ avatar: {
55
+ position: 'relative',
56
+ flexDirection: 'row',
57
+ height: 40,
58
+ width: 40,
59
+ flexShrink: 0,
60
+ overflow: 'hidden',
61
+ borderRadius: 20,
62
+ },
63
+ image: {
64
+ aspectRatio: 1,
65
+ height: '100%',
66
+ width: '100%',
67
+ },
68
+ fallback: {
69
+ flexDirection: 'row',
70
+ height: '100%',
71
+ width: '100%',
72
+ alignItems: 'center',
73
+ justifyContent: 'center',
74
+ borderRadius: 20,
75
+ },
76
+ });
77
+
53
78
  export { Avatar, AvatarFallback, AvatarImage };
@@ -1,59 +1,74 @@
1
1
  import React from 'react';
2
2
  import * as Slot from '@rn-primitives/slot';
3
- import { cva, type VariantProps } from 'class-variance-authority';
4
- import { View, ViewProps } from 'react-native';
5
- import { cn } from '../../lib/utils';
6
- import { TextClassContext } from '../ui/text';
7
-
8
- const badgeVariants = cva(
9
- 'web:inline-flex items-center rounded-full border border-border px-2.5 py-0.5 web:transition-colors web:focus:outline-none web:focus:ring-2 web:focus:ring-ring web:focus:ring-offset-2',
10
- {
11
- variants: {
12
- variant: {
13
- default:
14
- 'border-transparent bg-primary web:hover:opacity-80 active:opacity-80',
15
- secondary:
16
- 'border-transparent bg-secondary web:hover:opacity-80 active:opacity-80',
17
- destructive:
18
- 'border-transparent bg-destructive web:hover:opacity-80 active:opacity-80',
19
- outline: 'text-foreground',
20
- },
21
- },
22
- defaultVariants: {
23
- variant: 'default',
24
- },
25
- },
26
- );
27
-
28
- const badgeTextVariants = cva('text-xs font-semibold ', {
29
- variants: {
30
- variant: {
31
- default: 'text-primary-foreground',
32
- secondary: 'text-secondary-foreground',
33
- destructive: 'text-destructive-foreground',
34
- outline: 'text-foreground',
35
- },
36
- },
37
- defaultVariants: {
38
- variant: 'default',
39
- },
40
- });
3
+ import { View, ViewProps, StyleSheet } from 'react-native';
4
+ import { TextStyleContext } from '../ui/text';
5
+
6
+ type BadgeVariant = 'default' | 'secondary' | 'destructive' | 'outline';
41
7
 
42
8
  type BadgeProps = ViewProps & {
43
9
  asChild?: boolean;
44
- } & VariantProps<typeof badgeVariants>;
10
+ variant?: BadgeVariant;
11
+ };
45
12
 
46
- function Badge({ className, variant, asChild, ...props }: BadgeProps) {
13
+ function Badge({ style, variant = 'default', asChild, ...props }: BadgeProps) {
47
14
  const Component = asChild ? Slot.View : View;
15
+
16
+ const badgeStyle = StyleSheet.flatten([styles.base, styles[variant], style]);
17
+
18
+ const textStyle = StyleSheet.flatten([textStyles.base, textStyles[variant]]);
19
+
48
20
  return (
49
- <TextClassContext.Provider value={badgeTextVariants({ variant })}>
50
- <Component
51
- className={cn(badgeVariants({ variant }), className)}
52
- {...props}
53
- />
54
- </TextClassContext.Provider>
21
+ <TextStyleContext.Provider value={{ style: textStyle }}>
22
+ <Component style={badgeStyle} {...props} />
23
+ </TextStyleContext.Provider>
55
24
  );
56
25
  }
57
26
 
58
- export { Badge, badgeTextVariants, badgeVariants };
59
- export type { BadgeProps };
27
+ const styles = StyleSheet.create({
28
+ base: {
29
+ flexDirection: 'row',
30
+ alignItems: 'center',
31
+ borderRadius: 20,
32
+ borderWidth: 1,
33
+ paddingHorizontal: 10,
34
+ paddingVertical: 2,
35
+ },
36
+ default: {
37
+ borderColor: 'transparent',
38
+ backgroundColor: 'hsl(var(--primary))',
39
+ },
40
+ secondary: {
41
+ borderColor: 'transparent',
42
+ backgroundColor: 'hsl(var(--secondary))',
43
+ },
44
+ destructive: {
45
+ borderColor: 'transparent',
46
+ backgroundColor: 'hsl(var(--destructive))',
47
+ },
48
+ outline: {
49
+ borderColor: 'hsl(var(--border))',
50
+ backgroundColor: 'transparent',
51
+ },
52
+ });
53
+
54
+ const textStyles = StyleSheet.create({
55
+ base: {
56
+ fontSize: 12,
57
+ fontWeight: '600',
58
+ },
59
+ default: {
60
+ color: 'hsl(var(--primary-foreground))',
61
+ },
62
+ secondary: {
63
+ color: 'hsl(var(--secondary-foreground))',
64
+ },
65
+ destructive: {
66
+ color: 'hsl(var(--destructive-foreground))',
67
+ },
68
+ outline: {
69
+ color: 'hsl(var(--foreground))',
70
+ },
71
+ });
72
+
73
+ export { Badge };
74
+ export type { BadgeProps, BadgeVariant };