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.
- package/.env +2 -0
- package/.eslintrc.js +1 -0
- package/app/index.tsx +3 -0
- package/babel.config.js +7 -8
- package/components/DataBrowser.tsx +9 -19
- package/components/DataBrowserContext.ts +24 -0
- package/components/TargetResourceProvider.tsx +1 -1
- package/components/ThemeProvider.tsx +2 -4
- package/components/common/LoadingBar.tsx +11 -1
- package/components/common/ProfileAvatar.tsx +4 -7
- package/components/nav/Layout.tsx +20 -4
- package/components/nav/header/AddressBox.tsx +104 -48
- package/components/nav/header/AvatarMenu.tsx +42 -10
- package/components/nav/header/Header.tsx +26 -19
- package/components/nav/header/SignInMenu.tsx +63 -36
- package/components/nav/header/ThemeToggleMenu.tsx +21 -9
- package/components/nav/header/ViewMenu.tsx +79 -71
- package/components/sharing/AccessDropdown.tsx +18 -7
- package/components/sharing/CopyLink.tsx +15 -3
- package/components/sharing/PermissionRow.tsx +17 -2
- package/components/sharing/SharingModal.tsx +30 -3
- package/components/sharing/WacRuleForm.tsx +12 -3
- package/components/sharing/agentPermissions/AgentInformation.tsx +16 -3
- package/components/sharing/agentPermissions/AgentInput.tsx +19 -4
- package/components/sharing/agentPermissions/AgentPermissionRow.tsx +24 -6
- package/components/ui/accordion.tsx +1 -1
- package/components/ui/alert.tsx +62 -46
- package/components/ui/avatar.tsx +38 -13
- package/components/ui/badge.tsx +63 -48
- package/components/ui/button.tsx +226 -108
- package/components/ui/card.tsx +53 -38
- package/components/ui/checkbox.tsx +53 -16
- package/components/ui/context-menu.tsx +4 -4
- package/components/ui/dialog.tsx +116 -65
- package/components/ui/dropdown-menu.tsx +304 -105
- package/components/ui/icon.tsx +23 -0
- package/components/ui/input-dropdown.tsx +42 -5
- package/components/ui/input.tsx +85 -22
- package/components/ui/label.tsx +16 -7
- package/components/ui/menubar.tsx +4 -4
- package/components/ui/navigation-menu.tsx +157 -90
- package/components/ui/progress.tsx +38 -24
- package/components/ui/select.tsx +139 -67
- package/components/ui/separator.tsx +22 -7
- package/components/ui/skeleton.tsx +14 -11
- package/components/ui/switch.tsx +82 -37
- package/components/ui/table.tsx +57 -35
- package/components/ui/tabs.tsx +66 -35
- package/components/ui/text.tsx +221 -30
- package/components/ui/textarea.tsx +34 -10
- package/components/ui/typography.tsx +94 -65
- package/components/useViewContext.tsx +8 -8
- package/global.css +93 -3
- package/metro.config.js +1 -3
- package/package.json +3 -7
- package/resourceViews/Container/ContainerConfig.tsx +1 -1
- package/resourceViews/Container/ContainerView.tsx +63 -25
- package/resourceViews/Profile/ProfileConfig.tsx +1 -1
- package/resourceViews/Profile/ProfileKnows.tsx +17 -9
- package/resourceViews/Profile/ProfileView.tsx +21 -4
- package/resourceViews/RawCode/RawCodeConfig.tsx +1 -1
- package/resourceViews/RawCode/RawCodeView.tsx +20 -6
- package/components.json +0 -7
- package/lib/icons/ArrowRight.tsx +0 -4
- package/lib/icons/Check.tsx +0 -4
- package/lib/icons/ChevronDown.tsx +0 -4
- package/lib/icons/ChevronRight.tsx +0 -4
- package/lib/icons/ChevronUp.tsx +0 -4
- package/lib/icons/ChevronsRight.tsx +0 -4
- package/lib/icons/CircleSlash.tsx +0 -4
- package/lib/icons/CircleX.tsx +0 -4
- package/lib/icons/Code.tsx +0 -4
- package/lib/icons/EllipsisVertical.tsx +0 -4
- package/lib/icons/EyeOff.tsx +0 -4
- package/lib/icons/File.tsx +0 -4
- package/lib/icons/Fingerprint.tsx +0 -4
- package/lib/icons/Folder.tsx +0 -4
- package/lib/icons/Folders.tsx +0 -4
- package/lib/icons/Info.tsx +0 -4
- package/lib/icons/Link.tsx +0 -4
- package/lib/icons/Loader.tsx +0 -4
- package/lib/icons/LogOut.tsx +0 -4
- package/lib/icons/MonitorSmartphone.tsx +0 -4
- package/lib/icons/MoonStar.tsx +0 -4
- package/lib/icons/OctagonX.tsx +0 -4
- package/lib/icons/Plus.tsx +0 -4
- package/lib/icons/RefreshCw.tsx +0 -4
- package/lib/icons/Save.tsx +0 -4
- package/lib/icons/ShieldX.tsx +0 -4
- package/lib/icons/Sun.tsx +0 -4
- package/lib/icons/TextCursorInput.tsx +0 -4
- package/lib/icons/Trash.tsx +0 -4
- package/lib/icons/User.tsx +0 -4
- package/lib/icons/UserPlus.tsx +0 -4
- package/lib/icons/Users.tsx +0 -4
- package/lib/icons/ViewIcon.tsx +0 -4
- package/lib/icons/X.tsx +0 -4
- package/lib/icons/iconWithClassName.ts +0 -14
- package/lib/utils.ts +0 -6
- package/nativewind-env.d.ts +0 -1
- package/tailwind.config.js +0 -69
package/components/ui/table.tsx
CHANGED
|
@@ -1,38 +1,37 @@
|
|
|
1
1
|
import * as TablePrimitive from '@rn-primitives/table';
|
|
2
2
|
import * as React from 'react';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { StyleSheet } from 'react-native';
|
|
4
|
+
import { TextStyleContext } from '../ui/text';
|
|
5
5
|
|
|
6
6
|
function Table({
|
|
7
|
-
|
|
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
|
-
|
|
14
|
+
style={StyleSheet.flatten([styles.table, style])}
|
|
15
15
|
{...props}
|
|
16
16
|
/>
|
|
17
17
|
);
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
function TableHeader({
|
|
21
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
77
|
+
style,
|
|
90
78
|
...props
|
|
91
79
|
}: TablePrimitive.HeadProps & {
|
|
92
80
|
ref?: React.RefObject<TablePrimitive.HeadRef>;
|
|
93
81
|
}) {
|
|
94
82
|
return (
|
|
95
|
-
<
|
|
83
|
+
<TextStyleContext.Provider
|
|
84
|
+
value={{ style: { color: 'hsl(var(--muted-foreground))' } }}
|
|
85
|
+
>
|
|
96
86
|
<TablePrimitive.Head
|
|
97
|
-
|
|
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
|
-
</
|
|
90
|
+
</TextStyleContext.Provider>
|
|
104
91
|
);
|
|
105
92
|
}
|
|
106
93
|
|
|
107
94
|
function TableCell({
|
|
108
|
-
|
|
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
|
-
|
|
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,
|
package/components/ui/tabs.tsx
CHANGED
|
@@ -1,70 +1,101 @@
|
|
|
1
1
|
import * as TabsPrimitive from '@rn-primitives/tabs';
|
|
2
2
|
import * as React from 'react';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
<
|
|
34
|
-
|
|
35
|
-
|
|
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
|
-
|
|
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 };
|
package/components/ui/text.tsx
CHANGED
|
@@ -1,38 +1,152 @@
|
|
|
1
|
+
import { useTheme } from '@react-navigation/native';
|
|
1
2
|
import * as Slot from '@rn-primitives/slot';
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
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
|
-
|
|
13
|
+
interface TextStyleProps {
|
|
14
|
+
style?: TextStyle;
|
|
15
|
+
variant?: TextVariant;
|
|
16
|
+
size?: TextSize;
|
|
17
|
+
muted?: boolean;
|
|
18
|
+
bold?: boolean;
|
|
19
|
+
}
|
|
7
20
|
|
|
8
|
-
|
|
9
|
-
export type TextSize = 'xs' | 'sm' | 'base' | 'lg' | 'xl' | '2xl' | '3xl';
|
|
21
|
+
interface TextStyleContextValue extends TextStyleProps {}
|
|
10
22
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
-
|
|
28
|
-
|
|
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 (
|
|
35
|
-
switch (
|
|
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 (
|
|
59
|
-
if (
|
|
60
|
-
if (
|
|
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
|
-
|
|
65
|
-
|
|
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 {
|
|
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
|
-
|
|
5
|
+
style,
|
|
7
6
|
multiline = true,
|
|
8
7
|
numberOfLines = 4,
|
|
9
|
-
|
|
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
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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 };
|