@streamplace/components 0.7.34 → 0.7.35
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/dist/components/dashboard/header.js +16 -2
- package/dist/components/dashboard/problems.js +29 -28
- package/dist/components/mobile-player/ui/viewer-context-menu.js +44 -1
- package/dist/components/ui/button.js +9 -9
- package/dist/components/ui/dropdown.js +15 -10
- package/dist/components/ui/icons.js +6 -0
- package/dist/components/ui/primitives/button.js +0 -7
- package/dist/lib/theme/tokens.js +9 -0
- package/dist/streamplace-store/graph.js +195 -0
- package/node-compile-cache/v22.15.0-x64-efe9a9df-0/37be0eec +0 -0
- package/package.json +2 -2
- package/src/components/dashboard/header.tsx +37 -3
- package/src/components/dashboard/index.tsx +1 -1
- package/src/components/dashboard/problems.tsx +57 -46
- package/src/components/mobile-player/ui/viewer-context-menu.tsx +100 -1
- package/src/components/ui/button.tsx +10 -13
- package/src/components/ui/dropdown.tsx +27 -13
- package/src/components/ui/icons.tsx +14 -0
- package/src/components/ui/primitives/button.tsx +0 -7
- package/src/lib/theme/tokens.ts +9 -0
- package/src/streamplace-store/graph.tsx +232 -0
- package/tsconfig.tsbuildinfo +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@streamplace/components",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.35",
|
|
4
4
|
"description": "Streamplace React (Native) Components",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "src/index.tsx",
|
|
@@ -54,5 +54,5 @@
|
|
|
54
54
|
"start": "tsc --watch --preserveWatchOutput",
|
|
55
55
|
"prepare": "tsc"
|
|
56
56
|
},
|
|
57
|
-
"gitHead": "
|
|
57
|
+
"gitHead": "eaefc85434e81e296c7248f6e6965a2f31d50ff8"
|
|
58
58
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Car, Radio, Users } from "lucide-react-native";
|
|
2
|
-
import { Text, View } from "react-native";
|
|
1
|
+
import { AlertCircle, Car, Radio, Users } from "lucide-react-native";
|
|
2
|
+
import { Pressable, Text, View } from "react-native";
|
|
3
3
|
import * as zero from "../../ui";
|
|
4
4
|
|
|
5
5
|
const { bg, r, borders, px, py, text, layout, gap } = zero;
|
|
@@ -103,6 +103,8 @@ interface HeaderProps {
|
|
|
103
103
|
bitrate?: string;
|
|
104
104
|
timeBetweenSegments?: number;
|
|
105
105
|
connectionStatus?: "excellent" | "good" | "poor" | "offline";
|
|
106
|
+
problemsCount?: number;
|
|
107
|
+
onProblemsPress?: () => void;
|
|
106
108
|
}
|
|
107
109
|
|
|
108
110
|
export default function Header({
|
|
@@ -113,6 +115,8 @@ export default function Header({
|
|
|
113
115
|
bitrate = "0 mbps",
|
|
114
116
|
timeBetweenSegments = 0,
|
|
115
117
|
connectionStatus = "offline",
|
|
118
|
+
problemsCount = 0,
|
|
119
|
+
onProblemsPress,
|
|
116
120
|
}: HeaderProps) {
|
|
117
121
|
const getConnectionQuality = (): "good" | "warning" | "error" => {
|
|
118
122
|
if (timeBetweenSegments <= 1500) return "good";
|
|
@@ -139,7 +143,37 @@ export default function Header({
|
|
|
139
143
|
<Text style={[text.white, { fontSize: 18, fontWeight: "600" }]}>
|
|
140
144
|
{streamTitle}
|
|
141
145
|
</Text>
|
|
142
|
-
<
|
|
146
|
+
<View style={[layout.flex.row, layout.flex.alignCenter, gap.all[3]]}>
|
|
147
|
+
<StatusIndicator status={connectionStatus} isLive={isLive} />
|
|
148
|
+
{problemsCount > 0 && (
|
|
149
|
+
<Pressable onPress={onProblemsPress}>
|
|
150
|
+
<View
|
|
151
|
+
style={[
|
|
152
|
+
layout.flex.row,
|
|
153
|
+
layout.flex.alignCenter,
|
|
154
|
+
gap.all[1],
|
|
155
|
+
px[2],
|
|
156
|
+
py[1],
|
|
157
|
+
r.md,
|
|
158
|
+
bg.orange[900],
|
|
159
|
+
borders.width.thin,
|
|
160
|
+
borders.color.orange[700],
|
|
161
|
+
{ marginVertical: -8 },
|
|
162
|
+
]}
|
|
163
|
+
>
|
|
164
|
+
<AlertCircle size={14} color="#fb923c" />
|
|
165
|
+
<Text
|
|
166
|
+
style={[
|
|
167
|
+
text.orange[400],
|
|
168
|
+
{ fontSize: 11, fontWeight: "600" },
|
|
169
|
+
]}
|
|
170
|
+
>
|
|
171
|
+
{problemsCount} {problemsCount === 1 ? "Issue" : "Issues"}
|
|
172
|
+
</Text>
|
|
173
|
+
</View>
|
|
174
|
+
</Pressable>
|
|
175
|
+
)}
|
|
176
|
+
</View>
|
|
143
177
|
</View>
|
|
144
178
|
</View>
|
|
145
179
|
|
|
@@ -2,4 +2,4 @@ export { default as ChatPanel } from "./chat-panel";
|
|
|
2
2
|
export { default as Header } from "./header";
|
|
3
3
|
export { default as InformationWidget } from "./information-widget";
|
|
4
4
|
export { default as ModActions } from "./mod-actions";
|
|
5
|
-
export { default as Problems } from "./problems";
|
|
5
|
+
export { default as Problems, ProblemsWrapperRef } from "./problems";
|
|
@@ -1,12 +1,32 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import {
|
|
2
|
+
CircleAlert,
|
|
3
|
+
CircleX,
|
|
4
|
+
ExternalLink,
|
|
5
|
+
Info,
|
|
6
|
+
Sparkle,
|
|
7
|
+
} from "lucide-react-native";
|
|
8
|
+
import { forwardRef, useImperativeHandle, useState } from "react";
|
|
9
|
+
import { Linking, Pressable, View } from "react-native";
|
|
4
10
|
import { useLivestreamStore } from "../../livestream-store";
|
|
5
11
|
import { LivestreamProblem } from "../../livestream-store/livestream-state";
|
|
6
12
|
import * as zero from "../../ui";
|
|
13
|
+
import { Button, Text } from "../ui";
|
|
7
14
|
|
|
8
15
|
const { bg, r, borders, p, text, layout, gap } = zero;
|
|
9
16
|
|
|
17
|
+
const getIcon = (severity: string) => {
|
|
18
|
+
switch (severity) {
|
|
19
|
+
case "error":
|
|
20
|
+
return <CircleX size={24} color="white" />;
|
|
21
|
+
case "warning":
|
|
22
|
+
return <CircleAlert size={24} color="white" />;
|
|
23
|
+
case "info":
|
|
24
|
+
return <Info size={24} color="white" />;
|
|
25
|
+
default:
|
|
26
|
+
return <Sparkle size={24} color="white" />;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
10
30
|
const Problems = ({
|
|
11
31
|
probs,
|
|
12
32
|
onIgnore,
|
|
@@ -15,9 +35,9 @@ const Problems = ({
|
|
|
15
35
|
onIgnore: () => void;
|
|
16
36
|
}) => {
|
|
17
37
|
return (
|
|
18
|
-
<View style={[gap.all[
|
|
19
|
-
<View>
|
|
20
|
-
<Text style={[text.white, {
|
|
38
|
+
<View style={[gap.all[4]]}>
|
|
39
|
+
<View style={[gap.all[2]]}>
|
|
40
|
+
<Text size="2xl" style={[text.white, { fontWeight: "600" }]}>
|
|
21
41
|
Optimize Your Stream
|
|
22
42
|
</Text>
|
|
23
43
|
<Text style={[text.gray[300]]}>
|
|
@@ -34,26 +54,22 @@ const Problems = ({
|
|
|
34
54
|
{ gap: 8, alignItems: "flex-start" },
|
|
35
55
|
]}
|
|
36
56
|
>
|
|
37
|
-
<
|
|
57
|
+
<View
|
|
38
58
|
style={[
|
|
39
|
-
r.
|
|
40
|
-
p[
|
|
59
|
+
zero.r.full,
|
|
60
|
+
zero.p[1],
|
|
41
61
|
{
|
|
42
|
-
width: 82,
|
|
43
|
-
textAlign: "center",
|
|
44
62
|
backgroundColor:
|
|
45
63
|
p.severity === "error"
|
|
46
64
|
? "#7f1d1d"
|
|
47
65
|
: p.severity === "warning"
|
|
48
66
|
? "#7c2d12"
|
|
49
67
|
: "#1e3a8a",
|
|
50
|
-
color: "white",
|
|
51
|
-
fontSize: 12,
|
|
52
68
|
},
|
|
53
69
|
]}
|
|
54
70
|
>
|
|
55
|
-
{p.severity}
|
|
56
|
-
</
|
|
71
|
+
{getIcon(p.severity)}
|
|
72
|
+
</View>
|
|
57
73
|
<View style={[{ flex: 1 }, gap.all[1]]}>
|
|
58
74
|
<Text style={[text.white, { fontWeight: "600" }]}>{p.code}</Text>
|
|
59
75
|
<Text style={[text.gray[400], { fontSize: 14 }]}>
|
|
@@ -79,39 +95,34 @@ const Problems = ({
|
|
|
79
95
|
</View>
|
|
80
96
|
</View>
|
|
81
97
|
))}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
r.md,
|
|
88
|
-
p[3],
|
|
89
|
-
layout.flex.center,
|
|
90
|
-
{ marginTop: 16 },
|
|
91
|
-
]}
|
|
92
|
-
>
|
|
93
|
-
<Text style={[text.white, { fontWeight: "600" }]}>Ignore</Text>
|
|
94
|
-
</Pressable>
|
|
98
|
+
<View style={[layout.flex.row, layout.flex.justify.end]}>
|
|
99
|
+
<Button onPress={onIgnore} variant="secondary">
|
|
100
|
+
<Text style={[text.white, { fontWeight: "600" }]}>Acknowledge</Text>
|
|
101
|
+
</Button>
|
|
102
|
+
</View>
|
|
95
103
|
</View>
|
|
96
104
|
);
|
|
97
105
|
};
|
|
98
106
|
|
|
99
|
-
export
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
|
|
107
|
+
export interface ProblemsWrapperRef {
|
|
108
|
+
setDismiss: (value: boolean) => void;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export const ProblemsWrapper = forwardRef<
|
|
112
|
+
ProblemsWrapperRef,
|
|
113
|
+
{
|
|
114
|
+
children: React.ReactElement;
|
|
115
|
+
}
|
|
116
|
+
>(({ children }, ref) => {
|
|
104
117
|
const problems = useLivestreamStore((x) => x.problems);
|
|
105
118
|
const [dismiss, setDismiss] = useState(false);
|
|
106
119
|
|
|
120
|
+
useImperativeHandle(ref, () => ({
|
|
121
|
+
setDismiss,
|
|
122
|
+
}));
|
|
123
|
+
|
|
107
124
|
return (
|
|
108
|
-
|
|
109
|
-
style={[
|
|
110
|
-
{ position: "relative", flex: 1 },
|
|
111
|
-
layout.flex.center,
|
|
112
|
-
{ flexBasis: 0 },
|
|
113
|
-
]}
|
|
114
|
-
>
|
|
125
|
+
<>
|
|
115
126
|
{children}
|
|
116
127
|
{problems.length > 0 && !dismiss && (
|
|
117
128
|
<View
|
|
@@ -127,16 +138,16 @@ export const ProblemsWrapper = ({
|
|
|
127
138
|
},
|
|
128
139
|
layout.flex.center,
|
|
129
140
|
{ justifyContent: "flex-start" },
|
|
130
|
-
p[
|
|
141
|
+
p[12],
|
|
131
142
|
]}
|
|
132
143
|
>
|
|
133
144
|
<View
|
|
134
145
|
style={[
|
|
135
|
-
bg.
|
|
136
|
-
borders.color.
|
|
146
|
+
bg.neutral[900],
|
|
147
|
+
borders.color.neutral[700],
|
|
137
148
|
borders.width.thin,
|
|
138
149
|
r.lg,
|
|
139
|
-
p[
|
|
150
|
+
p[8],
|
|
140
151
|
{ maxWidth: 700, width: "100%" },
|
|
141
152
|
]}
|
|
142
153
|
>
|
|
@@ -144,8 +155,8 @@ export const ProblemsWrapper = ({
|
|
|
144
155
|
</View>
|
|
145
156
|
</View>
|
|
146
157
|
)}
|
|
147
|
-
|
|
158
|
+
</>
|
|
148
159
|
);
|
|
149
|
-
};
|
|
160
|
+
});
|
|
150
161
|
|
|
151
162
|
export default Problems;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { useRootContext } from "@rn-primitives/dropdown-menu";
|
|
2
2
|
import { Menu } from "lucide-react-native";
|
|
3
|
-
import { Platform, View } from "react-native";
|
|
3
|
+
import { Image, Linking, Platform, Pressable, View } from "react-native";
|
|
4
|
+
import { useAvatars, useLivestreamInfo, zero } from "../../..";
|
|
4
5
|
import { colors } from "../../../lib/theme";
|
|
5
6
|
import { useLivestreamStore } from "../../../livestream-store";
|
|
6
7
|
import { PlayerProtocol, usePlayerStore } from "../../../player-store/";
|
|
8
|
+
import { useGraphManager } from "../../../streamplace-store/graph";
|
|
7
9
|
import {
|
|
8
10
|
DropdownMenu,
|
|
9
11
|
DropdownMenuCheckboxItem,
|
|
@@ -14,6 +16,7 @@ import {
|
|
|
14
16
|
DropdownMenuPortal,
|
|
15
17
|
DropdownMenuRadioGroup,
|
|
16
18
|
DropdownMenuRadioItem,
|
|
19
|
+
DropdownMenuSeparator,
|
|
17
20
|
DropdownMenuTrigger,
|
|
18
21
|
ResponsiveDropdownMenuContent,
|
|
19
22
|
Text,
|
|
@@ -38,6 +41,12 @@ export function ContextMenu({
|
|
|
38
41
|
const setReportModalOpen = usePlayerStore((x) => x.setReportModalOpen);
|
|
39
42
|
const setReportSubject = usePlayerStore((x) => x.setReportSubject);
|
|
40
43
|
|
|
44
|
+
const { profile } = useLivestreamInfo();
|
|
45
|
+
const avatars = useAvatars(profile?.did ? [profile?.did] : []);
|
|
46
|
+
const ls = useLivestreamStore((x) => x.livestream);
|
|
47
|
+
|
|
48
|
+
let graphManager = useGraphManager(profile?.did);
|
|
49
|
+
|
|
41
50
|
const lowLatency = protocol === "webrtc";
|
|
42
51
|
const setLowLatency = (value: boolean) => {
|
|
43
52
|
setProtocol(value ? PlayerProtocol.WEBRTC : PlayerProtocol.HLS);
|
|
@@ -61,6 +70,96 @@ export function ContextMenu({
|
|
|
61
70
|
</DropdownMenuTrigger>
|
|
62
71
|
<Portal container={dropdownPortalContainer}>
|
|
63
72
|
<DropdownMenuContent side="top" align="end">
|
|
73
|
+
{Platform.OS !== "web" && (
|
|
74
|
+
<DropdownMenuGroup title="Streamer">
|
|
75
|
+
<View
|
|
76
|
+
style={[
|
|
77
|
+
zero.layout.flex.row,
|
|
78
|
+
zero.layout.flex.center,
|
|
79
|
+
zero.gap.all[3],
|
|
80
|
+
{ flex: 1, minWidth: 0 },
|
|
81
|
+
]}
|
|
82
|
+
>
|
|
83
|
+
{profile?.did && avatars[profile?.did]?.avatar && (
|
|
84
|
+
<Image
|
|
85
|
+
key="avatar"
|
|
86
|
+
source={{
|
|
87
|
+
uri: avatars[profile?.did]?.avatar,
|
|
88
|
+
}}
|
|
89
|
+
style={{ width: 42, height: 42, borderRadius: 999 }}
|
|
90
|
+
resizeMode="cover"
|
|
91
|
+
/>
|
|
92
|
+
)}
|
|
93
|
+
<View style={{ flex: 1, minWidth: 0 }}>
|
|
94
|
+
<View
|
|
95
|
+
style={[
|
|
96
|
+
zero.layout.flex.row,
|
|
97
|
+
zero.layout.flex.alignCenter,
|
|
98
|
+
zero.gap.all[2],
|
|
99
|
+
]}
|
|
100
|
+
>
|
|
101
|
+
<Pressable
|
|
102
|
+
onPress={() => {
|
|
103
|
+
if (profile?.handle) {
|
|
104
|
+
const url = `https://bsky.app/profile/${profile.handle}`;
|
|
105
|
+
Linking.openURL(url);
|
|
106
|
+
}
|
|
107
|
+
}}
|
|
108
|
+
>
|
|
109
|
+
<Text>@{profile?.handle || "user"}</Text>
|
|
110
|
+
</Pressable>
|
|
111
|
+
{/*{did && profile && (
|
|
112
|
+
<FollowButton streamerDID={profile?.did} currentUserDID={did} />
|
|
113
|
+
)}*/}
|
|
114
|
+
</View>
|
|
115
|
+
<Text
|
|
116
|
+
color="muted"
|
|
117
|
+
size="sm"
|
|
118
|
+
numberOfLines={2}
|
|
119
|
+
ellipsizeMode="tail"
|
|
120
|
+
>
|
|
121
|
+
{ls?.record.title || "Stream Title"}
|
|
122
|
+
</Text>
|
|
123
|
+
</View>
|
|
124
|
+
</View>
|
|
125
|
+
<DropdownMenuSeparator />
|
|
126
|
+
<DropdownMenuItem
|
|
127
|
+
disabled={graphManager.isLoading || !profile?.did}
|
|
128
|
+
onPress={async () => {
|
|
129
|
+
try {
|
|
130
|
+
if (graphManager.isFollowing) {
|
|
131
|
+
await graphManager.unfollow();
|
|
132
|
+
} else {
|
|
133
|
+
await graphManager.follow();
|
|
134
|
+
}
|
|
135
|
+
} catch (err) {
|
|
136
|
+
console.error("Follow/unfollow error:", err);
|
|
137
|
+
}
|
|
138
|
+
}}
|
|
139
|
+
>
|
|
140
|
+
<Text
|
|
141
|
+
color={graphManager.isFollowing ? "destructive" : "default"}
|
|
142
|
+
>
|
|
143
|
+
{graphManager.isLoading
|
|
144
|
+
? "Loading..."
|
|
145
|
+
: graphManager.isFollowing
|
|
146
|
+
? "Unfollow"
|
|
147
|
+
: "Follow"}
|
|
148
|
+
</Text>
|
|
149
|
+
</DropdownMenuItem>
|
|
150
|
+
<DropdownMenuSeparator />
|
|
151
|
+
<DropdownMenuItem
|
|
152
|
+
onPress={() => {
|
|
153
|
+
if (profile?.handle) {
|
|
154
|
+
const url = `https://bsky.app/profile/${profile.handle}`;
|
|
155
|
+
Linking.openURL(url);
|
|
156
|
+
}
|
|
157
|
+
}}
|
|
158
|
+
>
|
|
159
|
+
<Text>View Profile on Bluesky</Text>
|
|
160
|
+
</DropdownMenuItem>
|
|
161
|
+
</DropdownMenuGroup>
|
|
162
|
+
)}
|
|
64
163
|
<DropdownMenuGroup title="Resolution">
|
|
65
164
|
<DropdownMenuRadioGroup value={quality} onValueChange={setQuality}>
|
|
66
165
|
<DropdownMenuRadioItem value="source">
|
|
@@ -109,7 +109,7 @@ export const Button = forwardRef<any, ButtonProps>(
|
|
|
109
109
|
{ borderRadius: zero.borderRadius.md },
|
|
110
110
|
],
|
|
111
111
|
inner: { gap: 4 },
|
|
112
|
-
text:
|
|
112
|
+
text: zero.typography.universal.sm,
|
|
113
113
|
};
|
|
114
114
|
case "lg":
|
|
115
115
|
return {
|
|
@@ -118,8 +118,8 @@ export const Button = forwardRef<any, ButtonProps>(
|
|
|
118
118
|
zero.py[3],
|
|
119
119
|
{ borderRadius: zero.borderRadius.md },
|
|
120
120
|
],
|
|
121
|
-
inner: { gap:
|
|
122
|
-
text:
|
|
121
|
+
inner: { gap: 12 },
|
|
122
|
+
text: zero.typography.universal.lg,
|
|
123
123
|
};
|
|
124
124
|
case "xl":
|
|
125
125
|
return {
|
|
@@ -129,17 +129,17 @@ export const Button = forwardRef<any, ButtonProps>(
|
|
|
129
129
|
{ borderRadius: zero.borderRadius.lg },
|
|
130
130
|
],
|
|
131
131
|
inner: { gap: 12 },
|
|
132
|
-
text:
|
|
132
|
+
text: zero.typography.universal.xl,
|
|
133
133
|
};
|
|
134
134
|
case "pill":
|
|
135
135
|
return {
|
|
136
136
|
button: [
|
|
137
|
-
zero.px[
|
|
138
|
-
zero.py[
|
|
137
|
+
zero.px[2],
|
|
138
|
+
zero.py[1],
|
|
139
139
|
{ borderRadius: zero.borderRadius.full },
|
|
140
140
|
],
|
|
141
141
|
inner: { gap: 4 },
|
|
142
|
-
text:
|
|
142
|
+
text: zero.typography.universal.xs,
|
|
143
143
|
};
|
|
144
144
|
case "md":
|
|
145
145
|
default:
|
|
@@ -150,7 +150,7 @@ export const Button = forwardRef<any, ButtonProps>(
|
|
|
150
150
|
{ borderRadius: zero.borderRadius.md },
|
|
151
151
|
],
|
|
152
152
|
inner: { gap: 6 },
|
|
153
|
-
text:
|
|
153
|
+
text: zero.typography.universal.sm,
|
|
154
154
|
};
|
|
155
155
|
}
|
|
156
156
|
}, [size, zt]);
|
|
@@ -211,15 +211,12 @@ export const Button = forwardRef<any, ButtonProps>(
|
|
|
211
211
|
<ActivityIndicator size={spinnerSize} color={spinnerColor} />
|
|
212
212
|
</ButtonPrimitive.Icon>
|
|
213
213
|
) : leftIcon ? (
|
|
214
|
-
<ButtonPrimitive.Icon
|
|
215
|
-
position="left"
|
|
216
|
-
style={{ width: iconSize, height: iconSize }}
|
|
217
|
-
>
|
|
214
|
+
<ButtonPrimitive.Icon position="left">
|
|
218
215
|
{leftIcon}
|
|
219
216
|
</ButtonPrimitive.Icon>
|
|
220
217
|
) : null}
|
|
221
218
|
|
|
222
|
-
<TextPrimitive.Root style={[textStyle, sizeStyles.text]}>
|
|
219
|
+
<TextPrimitive.Root style={[textStyle as any, sizeStyles.text]}>
|
|
223
220
|
{loading && loadingText ? loadingText : children}
|
|
224
221
|
</TextPrimitive.Root>
|
|
225
222
|
|
|
@@ -13,7 +13,6 @@ import {
|
|
|
13
13
|
Platform,
|
|
14
14
|
Pressable,
|
|
15
15
|
StyleSheet,
|
|
16
|
-
Text,
|
|
17
16
|
useWindowDimensions,
|
|
18
17
|
View,
|
|
19
18
|
} from "react-native";
|
|
@@ -39,6 +38,7 @@ import {
|
|
|
39
38
|
objectFromObjects,
|
|
40
39
|
TextContext as TextClassContext,
|
|
41
40
|
} from "./primitives/text";
|
|
41
|
+
import { Text } from "./text";
|
|
42
42
|
|
|
43
43
|
export const DropdownMenu = DropdownMenuPrimitive.Root;
|
|
44
44
|
export const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
|
|
@@ -87,7 +87,7 @@ export const DropdownMenuBottomSheet = forwardRef<
|
|
|
87
87
|
zt.bg.mutedForeground,
|
|
88
88
|
]}
|
|
89
89
|
>
|
|
90
|
-
<BottomSheetView style={[px[
|
|
90
|
+
<BottomSheetView style={[px[4]]}>
|
|
91
91
|
{typeof children === "function"
|
|
92
92
|
? children({ pressed: true })
|
|
93
93
|
: children}
|
|
@@ -285,9 +285,15 @@ export const DropdownMenuItem = forwardRef<
|
|
|
285
285
|
pr[2],
|
|
286
286
|
]}
|
|
287
287
|
>
|
|
288
|
-
{typeof children === "function"
|
|
289
|
-
|
|
290
|
-
|
|
288
|
+
{typeof children === "function" ? (
|
|
289
|
+
children({ pressed: true })
|
|
290
|
+
) : typeof children === "string" ? (
|
|
291
|
+
<Text style={[inset && gap[2], disabled && { opacity: 0.5 }]}>
|
|
292
|
+
{children}
|
|
293
|
+
</Text>
|
|
294
|
+
) : (
|
|
295
|
+
children
|
|
296
|
+
)}
|
|
291
297
|
</View>
|
|
292
298
|
</TextClassContext.Provider>
|
|
293
299
|
</Pressable>
|
|
@@ -384,13 +390,15 @@ export const DropdownMenuLabel = forwardRef<
|
|
|
384
390
|
return (
|
|
385
391
|
<Text
|
|
386
392
|
ref={ref}
|
|
387
|
-
style={
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
393
|
+
style={
|
|
394
|
+
[
|
|
395
|
+
px[2],
|
|
396
|
+
py[2],
|
|
397
|
+
{ color: theme.colors.textMuted },
|
|
398
|
+
a.fontSize.base,
|
|
399
|
+
(inset && gap[2]) as any,
|
|
400
|
+
] as any
|
|
401
|
+
}
|
|
394
402
|
{...props}
|
|
395
403
|
/>
|
|
396
404
|
);
|
|
@@ -404,7 +412,13 @@ export const DropdownMenuSeparator = forwardRef<
|
|
|
404
412
|
return (
|
|
405
413
|
<View
|
|
406
414
|
ref={ref}
|
|
407
|
-
style={[
|
|
415
|
+
style={[
|
|
416
|
+
{
|
|
417
|
+
borderBottomWidth: 1,
|
|
418
|
+
borderBottomColor: theme.colors.border,
|
|
419
|
+
marginVertical: -0.5,
|
|
420
|
+
},
|
|
421
|
+
]}
|
|
408
422
|
{...props}
|
|
409
423
|
/>
|
|
410
424
|
);
|
|
@@ -48,3 +48,17 @@ export function createThemedIcon(
|
|
|
48
48
|
);
|
|
49
49
|
};
|
|
50
50
|
}
|
|
51
|
+
|
|
52
|
+
// usage of createThemedIcon
|
|
53
|
+
export function Icon({
|
|
54
|
+
icon,
|
|
55
|
+
variant = "default",
|
|
56
|
+
size = "md",
|
|
57
|
+
color,
|
|
58
|
+
...restProps
|
|
59
|
+
}: { icon: React.ComponentType<LucideProps> } & IconProps) {
|
|
60
|
+
const ThemedIcon = createThemedIcon(icon);
|
|
61
|
+
return (
|
|
62
|
+
<ThemedIcon variant={variant} size={size} color={color} {...restProps} />
|
|
63
|
+
);
|
|
64
|
+
}
|
|
@@ -244,7 +244,6 @@ const primitiveStyles = StyleSheet.create({
|
|
|
244
244
|
flexDirection: "row",
|
|
245
245
|
alignItems: "center",
|
|
246
246
|
justifyContent: "center",
|
|
247
|
-
minHeight: 44, // iOS minimum touch target
|
|
248
247
|
},
|
|
249
248
|
disabled: {
|
|
250
249
|
opacity: 0.5,
|
|
@@ -264,12 +263,6 @@ const primitiveStyles = StyleSheet.create({
|
|
|
264
263
|
alignItems: "center",
|
|
265
264
|
justifyContent: "center",
|
|
266
265
|
},
|
|
267
|
-
iconLeft: {
|
|
268
|
-
marginRight: 8,
|
|
269
|
-
},
|
|
270
|
-
iconRight: {
|
|
271
|
-
marginLeft: 8,
|
|
272
|
-
},
|
|
273
266
|
iconDisabled: {
|
|
274
267
|
opacity: 0.5,
|
|
275
268
|
},
|
package/src/lib/theme/tokens.ts
CHANGED
|
@@ -590,52 +590,61 @@ export const typography = {
|
|
|
590
590
|
},
|
|
591
591
|
|
|
592
592
|
// Universal typography scale
|
|
593
|
+
// Atkinson's center is weird so the marginBottom is there to correct it?
|
|
593
594
|
universal: {
|
|
594
595
|
xs: {
|
|
595
596
|
fontSize: 12,
|
|
596
597
|
lineHeight: 16,
|
|
598
|
+
marginBottom: -0.7,
|
|
597
599
|
fontWeight: "400" as const,
|
|
598
600
|
fontFamily: "AtkinsonHyperlegibleNext-Regular",
|
|
599
601
|
},
|
|
600
602
|
sm: {
|
|
601
603
|
fontSize: 14,
|
|
602
604
|
lineHeight: 20,
|
|
605
|
+
marginBottom: -1,
|
|
603
606
|
fontWeight: "400" as const,
|
|
604
607
|
fontFamily: "AtkinsonHyperlegibleNext-Regular",
|
|
605
608
|
},
|
|
606
609
|
base: {
|
|
607
610
|
fontSize: 16,
|
|
608
611
|
lineHeight: 24,
|
|
612
|
+
marginBottom: -1.2,
|
|
609
613
|
fontWeight: "400" as const,
|
|
610
614
|
fontFamily: "AtkinsonHyperlegibleNext-Regular",
|
|
611
615
|
},
|
|
612
616
|
lg: {
|
|
613
617
|
fontSize: 18,
|
|
614
618
|
lineHeight: 28,
|
|
619
|
+
marginBottom: -1.5,
|
|
615
620
|
fontWeight: "400" as const,
|
|
616
621
|
fontFamily: "AtkinsonHyperlegibleNext-Regular",
|
|
617
622
|
},
|
|
618
623
|
xl: {
|
|
619
624
|
fontSize: 20,
|
|
620
625
|
lineHeight: 28,
|
|
626
|
+
marginBottom: -1.75,
|
|
621
627
|
fontWeight: "500" as const,
|
|
622
628
|
fontFamily: "AtkinsonHyperlegibleNext-Medium",
|
|
623
629
|
},
|
|
624
630
|
"2xl": {
|
|
625
631
|
fontSize: 24,
|
|
626
632
|
lineHeight: 32,
|
|
633
|
+
marginBottom: -2,
|
|
627
634
|
fontWeight: "600" as const,
|
|
628
635
|
fontFamily: "AtkinsonHyperlegibleNext-SemiBold",
|
|
629
636
|
},
|
|
630
637
|
"3xl": {
|
|
631
638
|
fontSize: 30,
|
|
632
639
|
lineHeight: 36,
|
|
640
|
+
marginBottom: -2.5,
|
|
633
641
|
fontWeight: "700" as const,
|
|
634
642
|
fontFamily: "AtkinsonHyperlegibleNext-Bold",
|
|
635
643
|
},
|
|
636
644
|
"4xl": {
|
|
637
645
|
fontSize: 36,
|
|
638
646
|
lineHeight: 40,
|
|
647
|
+
marginBottom: -3,
|
|
639
648
|
fontWeight: "700" as const,
|
|
640
649
|
fontFamily: "AtkinsonHyperlegibleNext-ExtraBold",
|
|
641
650
|
},
|