linked-data-browser 0.0.7 → 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 (101) hide show
  1. package/.env +2 -0
  2. package/.eslintrc.js +1 -0
  3. package/app/index.tsx +3 -0
  4. package/babel.config.js +7 -8
  5. package/components/DataBrowser.tsx +9 -19
  6. package/components/DataBrowserContext.ts +24 -0
  7. package/components/TargetResourceProvider.tsx +1 -1
  8. package/components/ThemeProvider.tsx +2 -4
  9. package/components/common/LoadingBar.tsx +11 -1
  10. package/components/common/ProfileAvatar.tsx +4 -7
  11. package/components/nav/Layout.tsx +20 -4
  12. package/components/nav/header/AddressBox.tsx +104 -48
  13. package/components/nav/header/AvatarMenu.tsx +42 -10
  14. package/components/nav/header/Header.tsx +26 -19
  15. package/components/nav/header/SignInMenu.tsx +63 -36
  16. package/components/nav/header/ThemeToggleMenu.tsx +21 -9
  17. package/components/nav/header/ViewMenu.tsx +79 -71
  18. package/components/sharing/AccessDropdown.tsx +18 -7
  19. package/components/sharing/CopyLink.tsx +15 -3
  20. package/components/sharing/PermissionRow.tsx +17 -2
  21. package/components/sharing/SharingModal.tsx +30 -3
  22. package/components/sharing/WacRuleForm.tsx +12 -3
  23. package/components/sharing/agentPermissions/AgentInformation.tsx +16 -3
  24. package/components/sharing/agentPermissions/AgentInput.tsx +19 -4
  25. package/components/sharing/agentPermissions/AgentPermissionRow.tsx +24 -6
  26. package/components/ui/accordion.tsx +1 -1
  27. package/components/ui/alert.tsx +62 -46
  28. package/components/ui/avatar.tsx +38 -13
  29. package/components/ui/badge.tsx +63 -48
  30. package/components/ui/button.tsx +226 -108
  31. package/components/ui/card.tsx +53 -38
  32. package/components/ui/checkbox.tsx +53 -16
  33. package/components/ui/context-menu.tsx +4 -4
  34. package/components/ui/dialog.tsx +116 -65
  35. package/components/ui/dropdown-menu.tsx +304 -105
  36. package/components/ui/icon.tsx +23 -0
  37. package/components/ui/input-dropdown.tsx +42 -5
  38. package/components/ui/input.tsx +85 -22
  39. package/components/ui/label.tsx +16 -7
  40. package/components/ui/menubar.tsx +4 -4
  41. package/components/ui/navigation-menu.tsx +157 -90
  42. package/components/ui/progress.tsx +38 -24
  43. package/components/ui/select.tsx +139 -67
  44. package/components/ui/separator.tsx +22 -7
  45. package/components/ui/skeleton.tsx +14 -11
  46. package/components/ui/switch.tsx +82 -37
  47. package/components/ui/table.tsx +57 -35
  48. package/components/ui/tabs.tsx +66 -35
  49. package/components/ui/text.tsx +221 -30
  50. package/components/ui/textarea.tsx +34 -10
  51. package/components/ui/typography.tsx +94 -65
  52. package/components/useViewContext.tsx +8 -8
  53. package/global.css +93 -3
  54. package/metro.config.js +1 -3
  55. package/package.json +3 -7
  56. package/resourceViews/Container/ContainerConfig.tsx +1 -1
  57. package/resourceViews/Container/ContainerView.tsx +63 -25
  58. package/resourceViews/Profile/ProfileConfig.tsx +1 -1
  59. package/resourceViews/Profile/ProfileKnows.tsx +17 -9
  60. package/resourceViews/Profile/ProfileView.tsx +21 -4
  61. package/resourceViews/RawCode/RawCodeConfig.tsx +1 -1
  62. package/resourceViews/RawCode/RawCodeView.tsx +20 -6
  63. package/components.json +0 -7
  64. package/lib/icons/ArrowRight.tsx +0 -4
  65. package/lib/icons/Check.tsx +0 -4
  66. package/lib/icons/ChevronDown.tsx +0 -4
  67. package/lib/icons/ChevronRight.tsx +0 -4
  68. package/lib/icons/ChevronUp.tsx +0 -4
  69. package/lib/icons/ChevronsRight.tsx +0 -4
  70. package/lib/icons/CircleSlash.tsx +0 -4
  71. package/lib/icons/CircleX.tsx +0 -4
  72. package/lib/icons/Code.tsx +0 -4
  73. package/lib/icons/EllipsisVertical.tsx +0 -4
  74. package/lib/icons/EyeOff.tsx +0 -4
  75. package/lib/icons/File.tsx +0 -4
  76. package/lib/icons/Fingerprint.tsx +0 -4
  77. package/lib/icons/Folder.tsx +0 -4
  78. package/lib/icons/Folders.tsx +0 -4
  79. package/lib/icons/Info.tsx +0 -4
  80. package/lib/icons/Link.tsx +0 -4
  81. package/lib/icons/Loader.tsx +0 -4
  82. package/lib/icons/LogOut.tsx +0 -4
  83. package/lib/icons/MonitorSmartphone.tsx +0 -4
  84. package/lib/icons/MoonStar.tsx +0 -4
  85. package/lib/icons/OctagonX.tsx +0 -4
  86. package/lib/icons/Plus.tsx +0 -4
  87. package/lib/icons/RefreshCw.tsx +0 -4
  88. package/lib/icons/Save.tsx +0 -4
  89. package/lib/icons/ShieldX.tsx +0 -4
  90. package/lib/icons/Sun.tsx +0 -4
  91. package/lib/icons/TextCursorInput.tsx +0 -4
  92. package/lib/icons/Trash.tsx +0 -4
  93. package/lib/icons/User.tsx +0 -4
  94. package/lib/icons/UserPlus.tsx +0 -4
  95. package/lib/icons/Users.tsx +0 -4
  96. package/lib/icons/ViewIcon.tsx +0 -4
  97. package/lib/icons/X.tsx +0 -4
  98. package/lib/icons/iconWithClassName.ts +0 -14
  99. package/lib/utils.ts +0 -6
  100. package/nativewind-env.d.ts +0 -1
  101. package/tailwind.config.js +0 -69
@@ -1,38 +1,37 @@
1
1
  import * as TablePrimitive from '@rn-primitives/table';
2
2
  import * as React from 'react';
3
- import { cn } from '../../lib/utils';
4
- import { TextClassContext } from '../ui/text';
3
+ import { StyleSheet } from 'react-native';
4
+ import { TextStyleContext } from '../ui/text';
5
5
 
6
6
  function Table({
7
- className,
7
+ style,
8
8
  ...props
9
9
  }: TablePrimitive.RootProps & {
10
10
  ref?: React.RefObject<TablePrimitive.RootRef>;
11
11
  }) {
12
12
  return (
13
13
  <TablePrimitive.Root
14
- className={cn('w-full caption-bottom text-sm', className)}
14
+ style={StyleSheet.flatten([styles.table, style])}
15
15
  {...props}
16
16
  />
17
17
  );
18
18
  }
19
19
 
20
20
  function TableHeader({
21
- className,
21
+ style,
22
22
  ...props
23
23
  }: TablePrimitive.HeaderProps & {
24
24
  ref?: React.RefObject<TablePrimitive.HeaderRef>;
25
25
  }) {
26
26
  return (
27
27
  <TablePrimitive.Header
28
- className={cn('border-border [&_tr]:border-b', className)}
28
+ style={StyleSheet.flatten([styles.header, style])}
29
29
  {...props}
30
30
  />
31
31
  );
32
32
  }
33
33
 
34
34
  function TableBody({
35
- className,
36
35
  style,
37
36
  ...props
38
37
  }: TablePrimitive.BodyProps & {
@@ -40,87 +39,110 @@ function TableBody({
40
39
  }) {
41
40
  return (
42
41
  <TablePrimitive.Body
43
- className={cn(
44
- 'flex-1 border-border [&_tr:last-child]:border-0',
45
- className,
46
- )}
47
- // eslint-disable-next-line react-native/no-inline-styles
48
- style={[{ minHeight: 2 }, style]}
42
+ style={StyleSheet.flatten([styles.body, { minHeight: 2 }, style])}
49
43
  {...props}
50
44
  />
51
45
  );
52
46
  }
53
47
 
54
48
  function TableFooter({
55
- className,
49
+ style,
56
50
  ...props
57
51
  }: TablePrimitive.FooterProps & {
58
52
  ref?: React.RefObject<TablePrimitive.FooterRef>;
59
53
  }) {
60
54
  return (
61
55
  <TablePrimitive.Footer
62
- className={cn(
63
- 'bg-muted/50 font-medium [&>tr]:last:border-b-0',
64
- className,
65
- )}
56
+ style={StyleSheet.flatten([styles.footer, style])}
66
57
  {...props}
67
58
  />
68
59
  );
69
60
  }
70
61
 
71
62
  function TableRow({
72
- className,
63
+ style,
73
64
  ...props
74
65
  }: TablePrimitive.RowProps & {
75
66
  ref?: React.RefObject<TablePrimitive.RowRef>;
76
67
  }) {
77
68
  return (
78
69
  <TablePrimitive.Row
79
- className={cn(
80
- 'flex-row border-border border-b web:transition-colors web:hover:bg-muted/50 web:data-[state=selected]:bg-muted',
81
- className,
82
- )}
70
+ style={StyleSheet.flatten([styles.row, style])}
83
71
  {...props}
84
72
  />
85
73
  );
86
74
  }
87
75
 
88
76
  function TableHead({
89
- className,
77
+ style,
90
78
  ...props
91
79
  }: TablePrimitive.HeadProps & {
92
80
  ref?: React.RefObject<TablePrimitive.HeadRef>;
93
81
  }) {
94
82
  return (
95
- <TextClassContext.Provider value="text-muted-foreground">
83
+ <TextStyleContext.Provider
84
+ value={{ style: { color: 'hsl(var(--muted-foreground))' } }}
85
+ >
96
86
  <TablePrimitive.Head
97
- className={cn(
98
- 'h-12 px-4 text-left justify-center font-medium [&:has([role=checkbox])]:pr-0',
99
- className,
100
- )}
87
+ style={StyleSheet.flatten([styles.head, style])}
101
88
  {...props}
102
89
  />
103
- </TextClassContext.Provider>
90
+ </TextStyleContext.Provider>
104
91
  );
105
92
  }
106
93
 
107
94
  function TableCell({
108
- className,
95
+ style,
109
96
  ...props
110
97
  }: TablePrimitive.CellProps & {
111
98
  ref?: React.RefObject<TablePrimitive.CellRef>;
112
99
  }) {
113
100
  return (
114
101
  <TablePrimitive.Cell
115
- className={cn(
116
- 'p-4 align-middle [&:has([role=checkbox])]:pr-0',
117
- className,
118
- )}
102
+ style={StyleSheet.flatten([styles.cell, style])}
119
103
  {...props}
120
104
  />
121
105
  );
122
106
  }
123
107
 
108
+ const styles = StyleSheet.create({
109
+ table: {
110
+ width: '100%',
111
+ fontSize: 14,
112
+ },
113
+ header: {
114
+ borderBottomWidth: 1,
115
+ borderBottomColor: 'hsl(var(--border))',
116
+ },
117
+ body: {
118
+ flex: 1,
119
+ borderBottomWidth: 1,
120
+ borderBottomColor: 'hsl(var(--border))',
121
+ },
122
+ footer: {
123
+ backgroundColor: 'hsl(var(--muted) / 0.5)',
124
+ fontWeight: '500',
125
+ },
126
+ row: {
127
+ flexDirection: 'row',
128
+ borderBottomWidth: 1,
129
+ borderBottomColor: 'hsl(var(--border))',
130
+ },
131
+ head: {
132
+ height: 48,
133
+ paddingHorizontal: 16,
134
+ alignItems: 'flex-start',
135
+ justifyContent: 'center',
136
+ fontWeight: '500',
137
+ color: 'hsl(var(--muted-foreground))',
138
+ },
139
+ cell: {
140
+ padding: 16,
141
+ alignItems: 'center',
142
+ justifyContent: 'center',
143
+ },
144
+ });
145
+
124
146
  export {
125
147
  Table,
126
148
  TableBody,
@@ -1,70 +1,101 @@
1
1
  import * as TabsPrimitive from '@rn-primitives/tabs';
2
2
  import * as React from 'react';
3
- import { cn } from '../../lib/utils';
4
- import { TextClassContext } from '../ui/text';
3
+ import { StyleSheet } from 'react-native';
4
+ import { TextStyleContext } from '../ui/text';
5
5
 
6
6
  const Tabs = TabsPrimitive.Root;
7
7
 
8
8
  function TabsList({
9
- className,
9
+ style,
10
10
  ...props
11
11
  }: TabsPrimitive.ListProps & {
12
12
  ref?: React.RefObject<TabsPrimitive.ListRef>;
13
13
  }) {
14
14
  return (
15
15
  <TabsPrimitive.List
16
- className={cn(
17
- 'web:inline-flex h-10 native:h-12 items-center justify-center rounded-md bg-muted p-1 native:px-1.5',
18
- className,
19
- )}
16
+ style={StyleSheet.flatten([styles.list, style])}
20
17
  {...props}
21
18
  />
22
19
  );
23
20
  }
24
21
 
25
22
  function TabsTrigger({
26
- className,
23
+ style,
27
24
  ...props
28
25
  }: TabsPrimitive.TriggerProps & {
29
26
  ref?: React.RefObject<TabsPrimitive.TriggerRef>;
30
27
  }) {
31
28
  const { value } = TabsPrimitive.useRootContext();
29
+ const isActive = props.value === value;
30
+
31
+ const triggerStyle = StyleSheet.flatten([
32
+ styles.trigger,
33
+ isActive && styles.triggerActive,
34
+ props.disabled && styles.triggerDisabled,
35
+ style,
36
+ ]);
37
+
38
+ const textStyle = isActive
39
+ ? StyleSheet.flatten([styles.triggerText, styles.triggerTextActive])
40
+ : styles.triggerText;
41
+
32
42
  return (
33
- <TextClassContext.Provider
34
- value={cn(
35
- 'text-sm native:text-base font-medium text-muted-foreground web:transition-all',
36
- value === props.value && 'text-foreground',
37
- )}
38
- >
39
- <TabsPrimitive.Trigger
40
- className={cn(
41
- 'inline-flex items-center justify-center shadow-none web:whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium web:ring-offset-background web:transition-all web:focus-visible:outline-none web:focus-visible:ring-2 web:focus-visible:ring-ring web:focus-visible:ring-offset-2',
42
- props.disabled && 'web:pointer-events-none opacity-50',
43
- props.value === value &&
44
- 'bg-background shadow-lg shadow-foreground/10',
45
- className,
46
- )}
47
- {...props}
48
- />
49
- </TextClassContext.Provider>
43
+ <TextStyleContext.Provider value={{ style: textStyle }}>
44
+ <TabsPrimitive.Trigger style={triggerStyle} {...props} />
45
+ </TextStyleContext.Provider>
50
46
  );
51
47
  }
52
48
 
53
49
  function TabsContent({
54
- className,
50
+ style,
55
51
  ...props
56
52
  }: TabsPrimitive.ContentProps & {
57
53
  ref?: React.RefObject<TabsPrimitive.ContentRef>;
58
54
  }) {
59
- return (
60
- <TabsPrimitive.Content
61
- className={cn(
62
- 'web:ring-offset-background web:focus-visible:outline-none web:focus-visible:ring-2 web:focus-visible:ring-ring web:focus-visible:ring-offset-2',
63
- className,
64
- )}
65
- {...props}
66
- />
67
- );
55
+ return <TabsPrimitive.Content style={style} {...props} />;
68
56
  }
69
57
 
58
+ const styles = StyleSheet.create({
59
+ list: {
60
+ flexDirection: 'row',
61
+ height: 40,
62
+ alignItems: 'center',
63
+ justifyContent: 'center',
64
+ borderRadius: 6,
65
+ backgroundColor: 'hsl(var(--muted))',
66
+ padding: 4,
67
+ },
68
+ trigger: {
69
+ flexDirection: 'row',
70
+ alignItems: 'center',
71
+ justifyContent: 'center',
72
+ borderRadius: 2,
73
+ paddingHorizontal: 12,
74
+ paddingVertical: 6,
75
+ fontSize: 14,
76
+ fontWeight: '500',
77
+ color: 'hsl(var(--muted-foreground))',
78
+ },
79
+ triggerActive: {
80
+ backgroundColor: 'hsl(var(--background))',
81
+ shadowColor: 'hsl(var(--foreground))',
82
+ shadowOffset: { width: 0, height: 0 },
83
+ shadowOpacity: 0.1,
84
+ shadowRadius: 4,
85
+ elevation: 2,
86
+ color: 'hsl(var(--foreground))',
87
+ },
88
+ triggerDisabled: {
89
+ opacity: 0.5,
90
+ },
91
+ triggerText: {
92
+ fontSize: 14,
93
+ fontWeight: '500',
94
+ color: 'hsl(var(--muted-foreground))',
95
+ },
96
+ triggerTextActive: {
97
+ color: 'hsl(var(--foreground))',
98
+ },
99
+ });
100
+
70
101
  export { Tabs, TabsContent, TabsList, TabsTrigger };
@@ -1,38 +1,152 @@
1
+ import { useTheme } from '@react-navigation/native';
1
2
  import * as Slot from '@rn-primitives/slot';
2
- import * as React from 'react';
3
- import { Text as RNText } from 'react-native';
4
- import { cn } from '../../lib/utils';
3
+ import React, {
4
+ PropsWithChildren,
5
+ FunctionComponent,
6
+ ComponentProps,
7
+ createContext,
8
+ useContext,
9
+ RefObject,
10
+ } from 'react';
11
+ import { Text as RNText, StyleSheet, TextStyle } from 'react-native';
5
12
 
6
- const TextClassContext = React.createContext<string | undefined>(undefined);
13
+ interface TextStyleProps {
14
+ style?: TextStyle;
15
+ variant?: TextVariant;
16
+ size?: TextSize;
17
+ muted?: boolean;
18
+ bold?: boolean;
19
+ }
7
20
 
8
- export type TextVariant = 'default' | 'h1' | 'h2' | 'h3' | 'label';
9
- export type TextSize = 'xs' | 'sm' | 'base' | 'lg' | 'xl' | '2xl' | '3xl';
21
+ interface TextStyleContextValue extends TextStyleProps {}
10
22
 
11
- function Text({
12
- className,
13
- asChild = false,
23
+ const TextStyleContext = createContext<TextStyleContextValue | undefined>(
24
+ undefined,
25
+ );
26
+
27
+ interface TextStyleProviderProps extends PropsWithChildren, TextStyleProps {}
28
+
29
+ const TextStyleProvider: FunctionComponent<TextStyleProviderProps> = ({
30
+ children,
31
+ style,
14
32
  variant,
15
33
  size,
16
34
  muted,
17
35
  bold,
18
- ...props
19
- }: React.ComponentProps<typeof RNText> & {
20
- ref?: React.RefObject<RNText>;
21
- asChild?: boolean;
36
+ }) => {
37
+ const contextValue: TextStyleContextValue = {
38
+ style,
39
+ variant,
40
+ size,
41
+ muted,
42
+ bold,
43
+ };
44
+
45
+ return (
46
+ <TextStyleContext.Provider value={contextValue}>
47
+ {children}
48
+ </TextStyleContext.Provider>
49
+ );
50
+ };
51
+
52
+ export type TextVariant = 'default' | 'h1' | 'h2' | 'h3' | 'label';
53
+ export type TextSize =
54
+ | 'xs'
55
+ | 'sm'
56
+ | 'base'
57
+ | 'lg'
58
+ | 'xl'
59
+ | '2xl'
60
+ | '3xl'
61
+ | number;
62
+
63
+ interface UseTextStylesParams {
22
64
  variant?: TextVariant;
23
65
  size?: TextSize;
24
66
  muted?: boolean;
25
67
  bold?: boolean;
26
- }) {
27
- const textClass = React.useContext(TextClassContext);
28
- const Component = asChild ? Slot.Text : RNText;
68
+ style?: TextStyle;
69
+ }
70
+
71
+ // Helper function to add opacity to HSL colors
72
+ function addOpacityToHSL(hslColor: string, opacity: number): string {
73
+ // Extract HSL values from string like "hsl(0 0% 98%)"
74
+ const hslMatch = hslColor.match(
75
+ /hsl\((\d+(?:\.\d+)?)\s+(\d+(?:\.\d+)?)%\s+(\d+(?:\.\d+)?)%\)/,
76
+ );
77
+ if (hslMatch) {
78
+ const [, h, s, l] = hslMatch;
79
+
80
+ // Convert HSL to RGB for better React Native compatibility
81
+ const hNum = parseFloat(h) / 360;
82
+ const sNum = parseFloat(s) / 100;
83
+ const lNum = parseFloat(l) / 100;
84
+
85
+ const c = (1 - Math.abs(2 * lNum - 1)) * sNum;
86
+ const x = c * (1 - Math.abs(((hNum * 6) % 2) - 1));
87
+ const m = lNum - c / 2;
88
+
89
+ let r, g, b;
90
+ if (hNum < 1 / 6) {
91
+ r = c;
92
+ g = x;
93
+ b = 0;
94
+ } else if (hNum < 2 / 6) {
95
+ r = x;
96
+ g = c;
97
+ b = 0;
98
+ } else if (hNum < 3 / 6) {
99
+ r = 0;
100
+ g = c;
101
+ b = x;
102
+ } else if (hNum < 4 / 6) {
103
+ r = 0;
104
+ g = x;
105
+ b = c;
106
+ } else if (hNum < 5 / 6) {
107
+ r = x;
108
+ g = 0;
109
+ b = c;
110
+ } else {
111
+ r = c;
112
+ g = 0;
113
+ b = x;
114
+ }
115
+
116
+ const rFinal = Math.round((r + m) * 255);
117
+ const gFinal = Math.round((g + m) * 255);
118
+ const bFinal = Math.round((b + m) * 255);
119
+
120
+ const rgbaResult = `rgba(${rFinal}, ${gFinal}, ${bFinal}, ${opacity})`;
121
+
122
+ // Return RGBA for better React Native compatibility
123
+ return rgbaResult;
124
+ }
125
+ return hslColor;
126
+ }
127
+
128
+ function useTextStyles({
129
+ variant,
130
+ size,
131
+ muted,
132
+ bold,
133
+ style,
134
+ }: UseTextStylesParams): TextStyle[] {
135
+ const contextValue = useContext(TextStyleContext);
136
+ const { colors } = useTheme();
137
+ // Use context values as defaults, but allow props to override
138
+ const effectiveVariant = variant ?? contextValue?.variant;
139
+ const effectiveSize = size ?? contextValue?.size;
140
+ const effectiveMuted = muted ?? contextValue?.muted;
141
+ const effectiveBold = bold ?? contextValue?.bold;
29
142
 
30
143
  let isMuted = false;
31
144
  let isBold = false;
32
145
  let textSize: TextSize = 'base';
146
+ let customFontSize: number | undefined;
33
147
 
34
- if (variant) {
35
- switch (variant) {
148
+ if (effectiveVariant) {
149
+ switch (effectiveVariant) {
36
150
  case 'h1':
37
151
  isBold = true;
38
152
  textSize = '3xl';
@@ -55,23 +169,100 @@ function Text({
55
169
  }
56
170
  }
57
171
 
58
- if (muted !== undefined) isMuted = muted;
59
- if (bold !== undefined) isBold = bold;
60
- if (size !== undefined) textSize = size;
172
+ if (effectiveMuted !== undefined) isMuted = effectiveMuted;
173
+ if (effectiveBold !== undefined) isBold = effectiveBold;
174
+ if (effectiveSize !== undefined) {
175
+ if (typeof effectiveSize === 'number') {
176
+ customFontSize = effectiveSize;
177
+ } else {
178
+ textSize = effectiveSize;
179
+ }
180
+ }
181
+
182
+ // Build the style array with theme colors
183
+ return [
184
+ styles.base,
185
+ { color: colors.text }, // Use theme color instead of hard-coded
186
+ contextValue?.style, // Apply context style
187
+ isBold && styles.bold,
188
+ isMuted && { color: addOpacityToHSL(colors.text, 0.5) }, // Use theme color with proper opacity for muted
189
+ customFontSize ? { fontSize: customFontSize } : styles[textSize],
190
+ contextValue?.style,
191
+ style, // Individual style prop overrides everything
192
+ ].filter((styleItem): styleItem is TextStyle => Boolean(styleItem));
193
+ }
194
+
195
+ function Text({
196
+ style,
197
+ asChild = false,
198
+ variant,
199
+ size,
200
+ muted,
201
+ bold,
202
+ ...props
203
+ }: ComponentProps<typeof RNText> & {
204
+ ref?: RefObject<RNText>;
205
+ asChild?: boolean;
206
+ } & TextStyleProps) {
207
+ const Component = asChild ? Slot.Text : RNText;
208
+
209
+ const textStyles = useTextStyles({
210
+ variant,
211
+ size,
212
+ muted,
213
+ bold,
214
+ style,
215
+ });
61
216
 
62
217
  return (
63
218
  <Component
64
- className={cn(
65
- 'text-base text-foreground web:select-text',
66
- textClass,
67
- isBold ? 'font-semibold' : '',
68
- isMuted ? 'text-muted-foreground' : '',
69
- `text-${textSize}`,
70
- className,
71
- )}
219
+ style={textStyles}
220
+ selectable={true} // web:select-text equivalent
72
221
  {...props}
73
222
  />
74
223
  );
75
224
  }
76
225
 
77
- export { Text, TextClassContext };
226
+ export {
227
+ Text,
228
+ TextStyleProvider,
229
+ TextStyleContext,
230
+ useTextStyles,
231
+ TextStyleProps,
232
+ };
233
+
234
+ const styles = StyleSheet.create({
235
+ base: {
236
+ fontSize: 16, // text-base
237
+ // color is now handled dynamically with theme
238
+ },
239
+ selectable: {
240
+ // web:select-text - this is handled by selectable prop in React Native
241
+ },
242
+ bold: {
243
+ fontWeight: '600', // font-semibold
244
+ },
245
+ // muted color is now handled dynamically with theme
246
+ // Size variants
247
+ xs: {
248
+ fontSize: 12, // text-xs
249
+ },
250
+ sm: {
251
+ fontSize: 14, // text-sm
252
+ },
253
+ baseSize: {
254
+ fontSize: 16, // text-base
255
+ },
256
+ lg: {
257
+ fontSize: 18, // text-lg
258
+ },
259
+ xl: {
260
+ fontSize: 20, // text-xl
261
+ },
262
+ '2xl': {
263
+ fontSize: 24, // text-2xl
264
+ },
265
+ '3xl': {
266
+ fontSize: 30, // text-3xl
267
+ },
268
+ });
@@ -1,24 +1,27 @@
1
1
  import * as React from 'react';
2
- import { TextInput, type TextInputProps } from 'react-native';
3
- import { cn } from '../../lib/utils';
2
+ import { TextInput, type TextInputProps, StyleSheet } from 'react-native';
4
3
 
5
4
  function Textarea({
6
- className,
5
+ style,
7
6
  multiline = true,
8
7
  numberOfLines = 4,
9
- placeholderClassName,
8
+ placeholderTextColor,
10
9
  ...props
11
10
  }: TextInputProps & {
12
11
  ref?: React.RefObject<TextInput>;
13
12
  }) {
13
+ const textareaStyle = StyleSheet.flatten([
14
+ styles.textarea,
15
+ props.editable === false && styles.textareaDisabled,
16
+ style,
17
+ ]);
18
+
14
19
  return (
15
20
  <TextInput
16
- className={cn(
17
- 'web:flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-base lg:text-sm native:text-lg native:leading-[1.25] text-foreground web:ring-offset-background placeholder:text-muted-foreground web:focus-visible:outline-none web:focus-visible:ring-2 web:focus-visible:ring-ring web:focus-visible:ring-offset-2',
18
- props.editable === false && 'opacity-50 web:cursor-not-allowed',
19
- className,
20
- )}
21
- placeholderClassName={cn('text-muted-foreground', placeholderClassName)}
21
+ style={textareaStyle}
22
+ placeholderTextColor={
23
+ placeholderTextColor || 'hsl(var(--muted-foreground))'
24
+ }
22
25
  multiline={multiline}
23
26
  numberOfLines={numberOfLines}
24
27
  textAlignVertical="top"
@@ -27,4 +30,25 @@ function Textarea({
27
30
  );
28
31
  }
29
32
 
33
+ const styles = StyleSheet.create({
34
+ textarea: {
35
+ minHeight: 80,
36
+ width: '100%',
37
+ borderRadius: 6,
38
+ borderWidth: 1,
39
+ borderColor: 'hsl(var(--input))',
40
+ backgroundColor: 'hsl(var(--background))',
41
+ paddingHorizontal: 12,
42
+ paddingVertical: 8,
43
+ fontSize: 16,
44
+ color: 'hsl(var(--foreground))',
45
+ },
46
+ textareaDisabled: {
47
+ opacity: 0.5,
48
+ },
49
+ placeholder: {
50
+ color: 'hsl(var(--muted-foreground))',
51
+ },
52
+ });
53
+
30
54
  export { Textarea };