@streamplace/components 0.6.37 → 0.7.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/dist/components/chat/chat-box.js +109 -0
- package/dist/components/chat/chat-message.js +76 -0
- package/dist/components/chat/chat.js +56 -0
- package/dist/components/chat/mention-suggestions.js +39 -0
- package/dist/components/chat/mod-view.js +33 -0
- package/dist/components/mobile-player/fullscreen.js +69 -0
- package/dist/components/mobile-player/fullscreen.native.js +151 -0
- package/dist/components/mobile-player/player.js +103 -0
- package/dist/components/mobile-player/props.js +1 -0
- package/dist/components/mobile-player/shared.js +51 -0
- package/dist/components/mobile-player/ui/countdown.js +79 -0
- package/dist/components/mobile-player/ui/index.js +5 -0
- package/dist/components/mobile-player/ui/input.js +38 -0
- package/dist/components/mobile-player/ui/metrics.js +40 -0
- package/dist/components/mobile-player/ui/streamer-context-menu.js +4 -0
- package/dist/components/mobile-player/ui/viewer-context-menu.js +20 -0
- package/dist/components/mobile-player/use-webrtc.js +232 -0
- package/dist/components/mobile-player/video.js +375 -0
- package/dist/components/mobile-player/video.native.js +238 -0
- package/dist/components/mobile-player/webrtc-diagnostics.js +106 -0
- package/dist/components/mobile-player/webrtc-primitives.js +25 -0
- package/dist/components/mobile-player/webrtc-primitives.native.js +1 -0
- package/dist/components/ui/button.js +220 -0
- package/dist/components/ui/dialog.js +203 -0
- package/dist/components/ui/dropdown.js +148 -0
- package/dist/components/ui/icons.js +22 -0
- package/dist/components/ui/index.js +22 -0
- package/dist/components/ui/input.js +202 -0
- package/dist/components/ui/loader.js +7 -0
- package/dist/components/ui/primitives/button.js +121 -0
- package/dist/components/ui/primitives/input.js +202 -0
- package/dist/components/ui/primitives/modal.js +203 -0
- package/dist/components/ui/primitives/text.js +286 -0
- package/dist/components/ui/resizeable.js +101 -0
- package/dist/components/ui/text.js +175 -0
- package/dist/components/ui/textarea.js +17 -0
- package/dist/components/ui/toast.js +129 -0
- package/dist/components/ui/view.js +250 -0
- package/dist/hooks/index.js +9 -0
- package/dist/hooks/useAvatars.js +32 -0
- package/dist/hooks/useCameraToggle.js +9 -0
- package/dist/hooks/useKeyboard.js +33 -0
- package/dist/hooks/useKeyboardSlide.js +11 -0
- package/dist/hooks/useLivestreamInfo.js +62 -0
- package/dist/hooks/useOuterAndInnerDimensions.js +27 -0
- package/dist/hooks/usePlayerDimensions.js +19 -0
- package/dist/hooks/useSegmentTiming.js +62 -0
- package/dist/index.js +10 -0
- package/dist/lib/facet.js +88 -0
- package/dist/lib/theme/atoms.js +620 -0
- package/dist/lib/theme/atoms.types.js +5 -0
- package/dist/lib/theme/index.js +9 -0
- package/dist/lib/theme/theme.js +248 -0
- package/dist/lib/theme/tokens.js +383 -0
- package/dist/lib/utils.js +94 -0
- package/dist/livestream-provider/index.js +8 -3
- package/dist/livestream-store/chat.js +89 -65
- package/dist/livestream-store/index.js +1 -0
- package/dist/livestream-store/livestream-store.js +3 -0
- package/dist/livestream-store/stream-key.js +115 -0
- package/dist/player-store/player-provider.js +0 -1
- package/dist/player-store/player-store.js +13 -0
- package/dist/streamplace-store/block.js +23 -0
- package/dist/streamplace-store/index.js +1 -0
- package/dist/streamplace-store/stream.js +193 -0
- package/node-compile-cache/v22.15.0-x64-efe9a9df-0/37be0eec +0 -0
- package/node-compile-cache/v22.15.0-x64-efe9a9df-0/56540125 +0 -0
- package/node-compile-cache/v22.15.0-x64-efe9a9df-0/67b1eb60 +0 -0
- package/node-compile-cache/v22.15.0-x64-efe9a9df-0/7c275f90 +0 -0
- package/package.json +20 -4
- package/src/components/chat/chat-box.tsx +195 -0
- package/src/components/chat/chat-message.tsx +192 -0
- package/src/components/chat/chat.tsx +128 -0
- package/src/components/chat/mention-suggestions.tsx +71 -0
- package/src/components/chat/mod-view.tsx +118 -0
- package/src/components/mobile-player/fullscreen.native.tsx +193 -0
- package/src/components/mobile-player/fullscreen.tsx +79 -0
- package/src/components/mobile-player/player.tsx +134 -0
- package/src/components/mobile-player/props.tsx +11 -0
- package/src/components/mobile-player/shared.tsx +56 -0
- package/src/components/mobile-player/ui/countdown.tsx +119 -0
- package/src/components/mobile-player/ui/index.ts +5 -0
- package/src/components/mobile-player/ui/input.tsx +85 -0
- package/src/components/mobile-player/ui/metrics.tsx +69 -0
- package/src/components/mobile-player/ui/streamer-context-menu.tsx +3 -0
- package/src/components/mobile-player/ui/viewer-context-menu.tsx +70 -0
- package/src/components/mobile-player/use-webrtc.tsx +282 -0
- package/src/components/mobile-player/video.native.tsx +360 -0
- package/src/components/mobile-player/video.tsx +557 -0
- package/src/components/mobile-player/webrtc-diagnostics.tsx +149 -0
- package/src/components/mobile-player/webrtc-primitives.native.tsx +6 -0
- package/src/components/mobile-player/webrtc-primitives.tsx +33 -0
- package/src/components/ui/button.tsx +309 -0
- package/src/components/ui/dialog.tsx +376 -0
- package/src/components/ui/dropdown.tsx +399 -0
- package/src/components/ui/icons.tsx +50 -0
- package/src/components/ui/index.ts +33 -0
- package/src/components/ui/input.tsx +350 -0
- package/src/components/ui/loader.tsx +9 -0
- package/src/components/ui/primitives/button.tsx +292 -0
- package/src/components/ui/primitives/input.tsx +422 -0
- package/src/components/ui/primitives/modal.tsx +421 -0
- package/src/components/ui/primitives/text.tsx +499 -0
- package/src/components/ui/resizeable.tsx +169 -0
- package/src/components/ui/text.tsx +330 -0
- package/src/components/ui/textarea.tsx +34 -0
- package/src/components/ui/toast.tsx +203 -0
- package/src/components/ui/view.tsx +344 -0
- package/src/hooks/index.ts +9 -0
- package/src/hooks/useAvatars.tsx +44 -0
- package/src/hooks/useCameraToggle.ts +12 -0
- package/src/hooks/useKeyboard.tsx +41 -0
- package/src/hooks/useKeyboardSlide.ts +12 -0
- package/src/hooks/useLivestreamInfo.ts +67 -0
- package/src/hooks/useOuterAndInnerDimensions.tsx +32 -0
- package/src/hooks/usePlayerDimensions.ts +23 -0
- package/src/hooks/useSegmentTiming.tsx +88 -0
- package/src/index.tsx +21 -0
- package/src/lib/facet.ts +131 -0
- package/src/lib/theme/atoms.ts +760 -0
- package/src/lib/theme/atoms.types.ts +258 -0
- package/src/lib/theme/index.ts +48 -0
- package/src/lib/theme/theme.tsx +436 -0
- package/src/lib/theme/tokens.ts +409 -0
- package/src/lib/utils.ts +132 -0
- package/src/livestream-provider/index.tsx +13 -2
- package/src/livestream-store/chat.tsx +115 -78
- package/src/livestream-store/index.tsx +1 -0
- package/src/livestream-store/livestream-state.tsx +3 -0
- package/src/livestream-store/livestream-store.tsx +3 -0
- package/src/livestream-store/stream-key.tsx +124 -0
- package/src/player-store/player-provider.tsx +0 -1
- package/src/player-store/player-state.tsx +28 -0
- package/src/player-store/player-store.tsx +22 -0
- package/src/streamplace-store/block.tsx +29 -0
- package/src/streamplace-store/index.tsx +1 -0
- package/src/streamplace-store/stream.tsx +262 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1,499 @@
|
|
|
1
|
+
import { createContext, forwardRef, useContext } from "react";
|
|
2
|
+
import type { ColorValue as RNColorValue } from "react-native";
|
|
3
|
+
import {
|
|
4
|
+
AnimatableNumericValue,
|
|
5
|
+
ColorValue,
|
|
6
|
+
OpaqueColorValue,
|
|
7
|
+
Platform,
|
|
8
|
+
Text as RNText,
|
|
9
|
+
TextProps as RNTextProps,
|
|
10
|
+
TextStyle,
|
|
11
|
+
} from "react-native";
|
|
12
|
+
import { useTheme } from "../../../lib/theme/theme";
|
|
13
|
+
import { typography, type Typography } from "../../../lib/theme/tokens";
|
|
14
|
+
|
|
15
|
+
// Text inheritance context
|
|
16
|
+
interface TextContextValue {
|
|
17
|
+
fontSize?: number;
|
|
18
|
+
fontWeight?: TextStyle["fontWeight"];
|
|
19
|
+
color?: string | RNColorValue | OpaqueColorValue;
|
|
20
|
+
fontFamily?: string;
|
|
21
|
+
lineHeight?: number;
|
|
22
|
+
textAlign?: TextStyle["textAlign"];
|
|
23
|
+
letterSpacing?: number;
|
|
24
|
+
textTransform?: TextStyle["textTransform"];
|
|
25
|
+
textDecorationLine?: TextStyle["textDecorationLine"];
|
|
26
|
+
fontStyle?: TextStyle["fontStyle"];
|
|
27
|
+
opacity?: number | AnimatableNumericValue;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export const TextContext = createContext<Partial<TextContextValue> | null>(
|
|
31
|
+
null,
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
export function objectFromObjects(
|
|
35
|
+
arr: Record<string, any>[],
|
|
36
|
+
): Record<string, any> {
|
|
37
|
+
return Object.assign({}, ...arr);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Text primitive props
|
|
41
|
+
export interface TextPrimitiveProps extends Omit<RNTextProps, "style"> {
|
|
42
|
+
// Typography variants
|
|
43
|
+
variant?:
|
|
44
|
+
| "h1"
|
|
45
|
+
| "h2"
|
|
46
|
+
| "h3"
|
|
47
|
+
| "h4"
|
|
48
|
+
| "h5"
|
|
49
|
+
| "h6"
|
|
50
|
+
| "body1"
|
|
51
|
+
| "body2"
|
|
52
|
+
| "caption"
|
|
53
|
+
| "overline"
|
|
54
|
+
| "subtitle1"
|
|
55
|
+
| "subtitle2";
|
|
56
|
+
|
|
57
|
+
// Size system
|
|
58
|
+
size?: "xs" | "sm" | "base" | "lg" | "xl" | "2xl" | "3xl" | "4xl" | number;
|
|
59
|
+
|
|
60
|
+
// Weight system
|
|
61
|
+
weight?:
|
|
62
|
+
| "thin"
|
|
63
|
+
| "light"
|
|
64
|
+
| "normal"
|
|
65
|
+
| "medium"
|
|
66
|
+
| "semibold"
|
|
67
|
+
| "bold"
|
|
68
|
+
| "extrabold"
|
|
69
|
+
| "black";
|
|
70
|
+
|
|
71
|
+
// Color variants
|
|
72
|
+
color?:
|
|
73
|
+
| "default"
|
|
74
|
+
| "muted"
|
|
75
|
+
| "primary"
|
|
76
|
+
| "secondary"
|
|
77
|
+
| "destructive"
|
|
78
|
+
| "success"
|
|
79
|
+
| "warning"
|
|
80
|
+
| (string & {});
|
|
81
|
+
|
|
82
|
+
// Text alignment
|
|
83
|
+
align?: "left" | "center" | "right" | "justify";
|
|
84
|
+
|
|
85
|
+
// Line height
|
|
86
|
+
leading?: "none" | "tight" | "snug" | "normal" | "relaxed" | "loose" | number;
|
|
87
|
+
|
|
88
|
+
// Letter spacing
|
|
89
|
+
tracking?:
|
|
90
|
+
| "tighter"
|
|
91
|
+
| "tight"
|
|
92
|
+
| "normal"
|
|
93
|
+
| "wide"
|
|
94
|
+
| "wider"
|
|
95
|
+
| "widest"
|
|
96
|
+
| number;
|
|
97
|
+
|
|
98
|
+
// Text transform
|
|
99
|
+
transform?: "none" | "capitalize" | "uppercase" | "lowercase";
|
|
100
|
+
|
|
101
|
+
// Text decoration
|
|
102
|
+
decoration?: "none" | "underline" | "line-through";
|
|
103
|
+
|
|
104
|
+
// Font style
|
|
105
|
+
italic?: boolean;
|
|
106
|
+
|
|
107
|
+
// Opacity
|
|
108
|
+
opacity?: number;
|
|
109
|
+
|
|
110
|
+
// Custom style
|
|
111
|
+
style?: TextStyle | TextStyle[];
|
|
112
|
+
|
|
113
|
+
// Inheritance - whether this component should inherit from parent context
|
|
114
|
+
inherit?: boolean;
|
|
115
|
+
|
|
116
|
+
// Reset inheritance - start fresh context
|
|
117
|
+
reset?: boolean;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Size mapping
|
|
121
|
+
const sizeMap = {
|
|
122
|
+
xs: 12,
|
|
123
|
+
sm: 14,
|
|
124
|
+
base: 16,
|
|
125
|
+
lg: 18,
|
|
126
|
+
xl: 20,
|
|
127
|
+
"2xl": 24,
|
|
128
|
+
"3xl": 30,
|
|
129
|
+
"4xl": 36,
|
|
130
|
+
} as const;
|
|
131
|
+
|
|
132
|
+
// Weight mapping
|
|
133
|
+
const weightMap = {
|
|
134
|
+
thin: "100",
|
|
135
|
+
light: "300",
|
|
136
|
+
normal: "400",
|
|
137
|
+
medium: "500",
|
|
138
|
+
semibold: "600",
|
|
139
|
+
bold: "700",
|
|
140
|
+
extrabold: "800",
|
|
141
|
+
black: "900",
|
|
142
|
+
} as const;
|
|
143
|
+
|
|
144
|
+
// Line height mapping
|
|
145
|
+
const leadingMap = {
|
|
146
|
+
none: 1,
|
|
147
|
+
tight: 1.2,
|
|
148
|
+
snug: 1.3,
|
|
149
|
+
normal: 1.5,
|
|
150
|
+
relaxed: 1.7,
|
|
151
|
+
loose: 2,
|
|
152
|
+
} as const;
|
|
153
|
+
|
|
154
|
+
// Letter spacing mapping
|
|
155
|
+
const trackingMap = {
|
|
156
|
+
tighter: -0.8,
|
|
157
|
+
tight: -0.4,
|
|
158
|
+
normal: 0,
|
|
159
|
+
wide: 0.4,
|
|
160
|
+
wider: 0.8,
|
|
161
|
+
widest: 1.6,
|
|
162
|
+
} as const;
|
|
163
|
+
|
|
164
|
+
// Variant definitions (platform-aware)
|
|
165
|
+
const getVariantStyles = () => {
|
|
166
|
+
// get platform-specific typography
|
|
167
|
+
// iOS, Android, Web (Universal)
|
|
168
|
+
const typographicPlatform = (
|
|
169
|
+
Platform.OS === "ios"
|
|
170
|
+
? "ios"
|
|
171
|
+
: Platform.OS === "android"
|
|
172
|
+
? "android"
|
|
173
|
+
: "universal"
|
|
174
|
+
) as keyof Typography;
|
|
175
|
+
const platformTypography = typography[typographicPlatform] as Record<
|
|
176
|
+
string,
|
|
177
|
+
TextStyle
|
|
178
|
+
>;
|
|
179
|
+
|
|
180
|
+
if (!platformTypography) {
|
|
181
|
+
throw new Error("Platform typography not defined");
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Define mapping based on platform
|
|
185
|
+
if (typographicPlatform === "ios") {
|
|
186
|
+
return {
|
|
187
|
+
h1: platformTypography.largeTitle,
|
|
188
|
+
h2: platformTypography.title1,
|
|
189
|
+
h3: platformTypography.title2,
|
|
190
|
+
h4: platformTypography.title3,
|
|
191
|
+
h5: platformTypography.headline,
|
|
192
|
+
h6: platformTypography.headline,
|
|
193
|
+
subtitle1: platformTypography.subhead,
|
|
194
|
+
subtitle2: platformTypography.footnote,
|
|
195
|
+
body1: platformTypography.body,
|
|
196
|
+
body2: platformTypography.callout,
|
|
197
|
+
caption: platformTypography.caption1,
|
|
198
|
+
overline: platformTypography.caption2,
|
|
199
|
+
};
|
|
200
|
+
} else if (typographicPlatform === "android") {
|
|
201
|
+
return {
|
|
202
|
+
h1: platformTypography.headline1,
|
|
203
|
+
h2: platformTypography.headline2,
|
|
204
|
+
h3: platformTypography.headline3,
|
|
205
|
+
h4: platformTypography.headline4,
|
|
206
|
+
h5: platformTypography.headline5,
|
|
207
|
+
h6: platformTypography.headline6,
|
|
208
|
+
subtitle1: platformTypography.subtitle1,
|
|
209
|
+
subtitle2: platformTypography.subtitle2,
|
|
210
|
+
body1: platformTypography.body1,
|
|
211
|
+
body2: platformTypography.body2,
|
|
212
|
+
caption: platformTypography.caption,
|
|
213
|
+
overline: platformTypography.overline,
|
|
214
|
+
};
|
|
215
|
+
} else {
|
|
216
|
+
// universal
|
|
217
|
+
// Map variants to universal sizes
|
|
218
|
+
return {
|
|
219
|
+
h1: platformTypography["4xl"],
|
|
220
|
+
h2: platformTypography["3xl"],
|
|
221
|
+
h3: platformTypography["2xl"],
|
|
222
|
+
h4: platformTypography["xl"],
|
|
223
|
+
h5: platformTypography["lg"],
|
|
224
|
+
h6: platformTypography["base"],
|
|
225
|
+
subtitle1: platformTypography.base,
|
|
226
|
+
subtitle2: platformTypography.sm,
|
|
227
|
+
body1: platformTypography.base,
|
|
228
|
+
body2: platformTypography.sm,
|
|
229
|
+
caption: platformTypography.xs,
|
|
230
|
+
overline: platformTypography.xs,
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
// Text root primitive
|
|
236
|
+
export const TextRoot = forwardRef<RNText, TextPrimitiveProps>(
|
|
237
|
+
(
|
|
238
|
+
{
|
|
239
|
+
variant,
|
|
240
|
+
size,
|
|
241
|
+
weight,
|
|
242
|
+
color,
|
|
243
|
+
align,
|
|
244
|
+
leading,
|
|
245
|
+
tracking,
|
|
246
|
+
transform,
|
|
247
|
+
decoration,
|
|
248
|
+
italic = false,
|
|
249
|
+
opacity,
|
|
250
|
+
style,
|
|
251
|
+
inherit = true,
|
|
252
|
+
reset = false,
|
|
253
|
+
children,
|
|
254
|
+
...props
|
|
255
|
+
},
|
|
256
|
+
ref,
|
|
257
|
+
) => {
|
|
258
|
+
const { theme } = useTheme();
|
|
259
|
+
const parentContext = useContext(TextContext);
|
|
260
|
+
|
|
261
|
+
// Get variant styles
|
|
262
|
+
const variantStyles = getVariantStyles() as Record<string, TextStyle>;
|
|
263
|
+
|
|
264
|
+
// Calculate inherited values
|
|
265
|
+
const inheritedContext =
|
|
266
|
+
inherit && !reset && parentContext ? parentContext : {};
|
|
267
|
+
|
|
268
|
+
// Calculate final styles
|
|
269
|
+
const finalStyles: TextStyle = {
|
|
270
|
+
// Start with inherited values
|
|
271
|
+
fontSize: inheritedContext.fontSize,
|
|
272
|
+
fontWeight: inheritedContext.fontWeight,
|
|
273
|
+
//color: inheritedContext.color,
|
|
274
|
+
fontFamily: inheritedContext.fontFamily,
|
|
275
|
+
lineHeight: inheritedContext.lineHeight,
|
|
276
|
+
textAlign: inheritedContext.textAlign,
|
|
277
|
+
letterSpacing: inheritedContext.letterSpacing,
|
|
278
|
+
textTransform: inheritedContext.textTransform,
|
|
279
|
+
textDecorationLine:
|
|
280
|
+
inheritedContext.textDecorationLine as TextStyle["textDecorationLine"],
|
|
281
|
+
fontStyle: inheritedContext.fontStyle,
|
|
282
|
+
opacity: inheritedContext.opacity,
|
|
283
|
+
|
|
284
|
+
// Apply variant styles (these may override inherited)
|
|
285
|
+
...(variant && variantStyles[variant]),
|
|
286
|
+
|
|
287
|
+
// Apply explicit prop styles (these should override inherited and variant)
|
|
288
|
+
|
|
289
|
+
// Apply size
|
|
290
|
+
...(size && {
|
|
291
|
+
fontSize: typeof size === "number" ? size : sizeMap[size],
|
|
292
|
+
}),
|
|
293
|
+
|
|
294
|
+
// Apply weight
|
|
295
|
+
...(weight && {
|
|
296
|
+
fontWeight: weightMap[weight] as TextStyle["fontWeight"],
|
|
297
|
+
}),
|
|
298
|
+
|
|
299
|
+
// Apply color
|
|
300
|
+
...(color
|
|
301
|
+
? {
|
|
302
|
+
color:
|
|
303
|
+
color === "default"
|
|
304
|
+
? theme.colors.text
|
|
305
|
+
: color === "muted"
|
|
306
|
+
? theme.colors.textMuted
|
|
307
|
+
: color === "primary"
|
|
308
|
+
? theme.colors.primary
|
|
309
|
+
: color === "secondary"
|
|
310
|
+
? theme.colors.secondary
|
|
311
|
+
: color === "destructive"
|
|
312
|
+
? theme.colors.destructive
|
|
313
|
+
: color === "success"
|
|
314
|
+
? theme.colors.success
|
|
315
|
+
: color === "warning"
|
|
316
|
+
? theme.colors.warning
|
|
317
|
+
: color || inheritedContext.color, // Custom color string
|
|
318
|
+
}
|
|
319
|
+
: { color: inheritedContext.color || theme.colors.text }),
|
|
320
|
+
|
|
321
|
+
// Apply alignment
|
|
322
|
+
...(align && {
|
|
323
|
+
textAlign: align,
|
|
324
|
+
}),
|
|
325
|
+
|
|
326
|
+
// Apply line height
|
|
327
|
+
...(leading && {
|
|
328
|
+
lineHeight: typeof leading === "number" ? leading : leadingMap[leading],
|
|
329
|
+
}),
|
|
330
|
+
|
|
331
|
+
// Apply letter spacing
|
|
332
|
+
...(tracking && {
|
|
333
|
+
letterSpacing:
|
|
334
|
+
typeof tracking === "number" ? tracking : trackingMap[tracking],
|
|
335
|
+
}),
|
|
336
|
+
|
|
337
|
+
// Apply text transform
|
|
338
|
+
...(transform &&
|
|
339
|
+
transform !== "none" && {
|
|
340
|
+
textTransform: transform,
|
|
341
|
+
}),
|
|
342
|
+
|
|
343
|
+
// Apply text decoration
|
|
344
|
+
...(decoration &&
|
|
345
|
+
decoration !== "none" && {
|
|
346
|
+
textDecorationLine: decoration,
|
|
347
|
+
}),
|
|
348
|
+
|
|
349
|
+
// Apply italic
|
|
350
|
+
...(italic && {
|
|
351
|
+
fontStyle: "italic",
|
|
352
|
+
}),
|
|
353
|
+
|
|
354
|
+
// Apply opacity
|
|
355
|
+
...(opacity !== undefined && {
|
|
356
|
+
opacity,
|
|
357
|
+
}),
|
|
358
|
+
};
|
|
359
|
+
|
|
360
|
+
finalStyles.color = finalStyles.color as ColorValue;
|
|
361
|
+
|
|
362
|
+
// Create context value for children
|
|
363
|
+
const contextValue: TextContextValue = {
|
|
364
|
+
fontSize:
|
|
365
|
+
typeof finalStyles.fontSize === "number"
|
|
366
|
+
? finalStyles.fontSize
|
|
367
|
+
: undefined,
|
|
368
|
+
fontWeight: finalStyles.fontWeight,
|
|
369
|
+
color: finalStyles.color || undefined,
|
|
370
|
+
fontFamily:
|
|
371
|
+
typeof finalStyles.fontFamily === "string"
|
|
372
|
+
? finalStyles.fontFamily
|
|
373
|
+
: undefined,
|
|
374
|
+
lineHeight:
|
|
375
|
+
typeof finalStyles.lineHeight === "number"
|
|
376
|
+
? finalStyles.lineHeight
|
|
377
|
+
: undefined,
|
|
378
|
+
textAlign: finalStyles.textAlign,
|
|
379
|
+
letterSpacing: finalStyles.letterSpacing as number | undefined,
|
|
380
|
+
textTransform: finalStyles.textTransform,
|
|
381
|
+
textDecorationLine:
|
|
382
|
+
finalStyles.textDecorationLine as TextStyle["textDecorationLine"],
|
|
383
|
+
fontStyle: finalStyles.fontStyle,
|
|
384
|
+
opacity: finalStyles.opacity as number | undefined,
|
|
385
|
+
};
|
|
386
|
+
|
|
387
|
+
return (
|
|
388
|
+
<TextContext.Provider value={contextValue}>
|
|
389
|
+
<RNText ref={ref} style={[finalStyles, style]} {...props}>
|
|
390
|
+
{children}
|
|
391
|
+
</RNText>
|
|
392
|
+
</TextContext.Provider>
|
|
393
|
+
);
|
|
394
|
+
},
|
|
395
|
+
);
|
|
396
|
+
|
|
397
|
+
TextRoot.displayName = "TextRoot";
|
|
398
|
+
|
|
399
|
+
// Text span primitive (inherits from parent but doesn't create new context)
|
|
400
|
+
export const TextSpan = forwardRef<RNText, Omit<TextPrimitiveProps, "reset">>(
|
|
401
|
+
({ children, ...props }, ref) => {
|
|
402
|
+
return (
|
|
403
|
+
<TextRoot ref={ref as any} inherit={true} {...props}>
|
|
404
|
+
{children}
|
|
405
|
+
</TextRoot>
|
|
406
|
+
);
|
|
407
|
+
},
|
|
408
|
+
);
|
|
409
|
+
|
|
410
|
+
TextSpan.displayName = "TextSpan";
|
|
411
|
+
|
|
412
|
+
// Text block primitive (always creates new context)
|
|
413
|
+
export const TextBlock = forwardRef<RNText, TextPrimitiveProps>(
|
|
414
|
+
({ children, reset = true, ...props }, ref) => {
|
|
415
|
+
return (
|
|
416
|
+
<TextRoot ref={ref as any} reset={reset} {...props}>
|
|
417
|
+
{children}
|
|
418
|
+
</TextRoot>
|
|
419
|
+
);
|
|
420
|
+
},
|
|
421
|
+
);
|
|
422
|
+
|
|
423
|
+
TextBlock.displayName = "TextBlock";
|
|
424
|
+
|
|
425
|
+
// Hook to access current text context
|
|
426
|
+
export function useTextContext(): TextContextValue | null {
|
|
427
|
+
return useContext(TextContext);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// Utility function to create text styles
|
|
431
|
+
export function createTextStyle(
|
|
432
|
+
props: Omit<TextPrimitiveProps, "children" | "style" | "ref">,
|
|
433
|
+
): TextStyle {
|
|
434
|
+
// This is a utility function that can be used to generate styles
|
|
435
|
+
// without rendering a component
|
|
436
|
+
const style: TextStyle = {};
|
|
437
|
+
|
|
438
|
+
if (props.size) {
|
|
439
|
+
style.fontSize =
|
|
440
|
+
typeof props.size === "number" ? props.size : sizeMap[props.size];
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
if (props.weight) {
|
|
444
|
+
style.fontWeight = weightMap[props.weight] as TextStyle["fontWeight"];
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
if (props.align) {
|
|
448
|
+
style.textAlign = props.align;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
if (props.leading) {
|
|
452
|
+
style.lineHeight =
|
|
453
|
+
typeof props.leading === "number"
|
|
454
|
+
? props.leading
|
|
455
|
+
: leadingMap[props.leading];
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
if (props.tracking) {
|
|
459
|
+
style.letterSpacing =
|
|
460
|
+
typeof props.tracking === "number"
|
|
461
|
+
? props.tracking
|
|
462
|
+
: trackingMap[props.tracking];
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
if (props.transform && props.transform !== "none") {
|
|
466
|
+
style.textTransform = props.transform;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
if (props.decoration && props.decoration !== "none") {
|
|
470
|
+
style.textDecorationLine = props.decoration;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
if (props.italic) {
|
|
474
|
+
style.fontStyle = "italic";
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
if (props.opacity !== undefined) {
|
|
478
|
+
style.opacity = props.opacity;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
return style;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
// Export primitive collection
|
|
485
|
+
export const TextPrimitive: {
|
|
486
|
+
Root: typeof TextRoot;
|
|
487
|
+
Span: typeof TextSpan;
|
|
488
|
+
Block: typeof TextBlock;
|
|
489
|
+
Context: typeof TextContext;
|
|
490
|
+
useContext: typeof useTextContext;
|
|
491
|
+
createStyle: typeof createTextStyle;
|
|
492
|
+
} = {
|
|
493
|
+
Root: TextRoot,
|
|
494
|
+
Span: TextSpan,
|
|
495
|
+
Block: TextBlock,
|
|
496
|
+
Context: TextContext,
|
|
497
|
+
useContext: useTextContext,
|
|
498
|
+
createStyle: createTextStyle,
|
|
499
|
+
};
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { ChevronUp } from "lucide-react-native";
|
|
2
|
+
import { ComponentProps } from "react";
|
|
3
|
+
import { Dimensions } from "react-native";
|
|
4
|
+
import {
|
|
5
|
+
Gesture,
|
|
6
|
+
GestureDetector,
|
|
7
|
+
Pressable,
|
|
8
|
+
} from "react-native-gesture-handler";
|
|
9
|
+
import Animated, {
|
|
10
|
+
Extrapolation,
|
|
11
|
+
interpolate,
|
|
12
|
+
useAnimatedStyle,
|
|
13
|
+
useSharedValue,
|
|
14
|
+
withSpring,
|
|
15
|
+
} from "react-native-reanimated";
|
|
16
|
+
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
17
|
+
import { useKeyboardSlide } from "../../hooks";
|
|
18
|
+
import { bottom, layout, p, w, zIndex } from "../../lib/theme/atoms";
|
|
19
|
+
import { View } from "./view";
|
|
20
|
+
|
|
21
|
+
const AnimatedView = Animated.createAnimatedComponent(View);
|
|
22
|
+
|
|
23
|
+
const { height: SCREEN_HEIGHT } = Dimensions.get("window");
|
|
24
|
+
|
|
25
|
+
type ResizableChatSheetProps = {
|
|
26
|
+
isPlayerRatioGreater: boolean;
|
|
27
|
+
style?: ComponentProps<typeof AnimatedView>["style"];
|
|
28
|
+
children?: React.ReactNode;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const SPRING_CONFIG = { damping: 20, stiffness: 100 };
|
|
32
|
+
|
|
33
|
+
export function Resizable({
|
|
34
|
+
isPlayerRatioGreater,
|
|
35
|
+
style = {},
|
|
36
|
+
children,
|
|
37
|
+
}: ResizableChatSheetProps) {
|
|
38
|
+
const { slideKeyboard } = useKeyboardSlide();
|
|
39
|
+
const { bottom: safeBottom } = useSafeAreaInsets();
|
|
40
|
+
const MAX_HEIGHT = (SCREEN_HEIGHT - safeBottom) * 0.5;
|
|
41
|
+
const MIN_HEIGHT = -(SCREEN_HEIGHT - safeBottom) * 0.2;
|
|
42
|
+
const COLLAPSE_HEIGHT = (SCREEN_HEIGHT - safeBottom) * 0.1;
|
|
43
|
+
|
|
44
|
+
const sheetHeight = useSharedValue(MIN_HEIGHT);
|
|
45
|
+
const startHeight = useSharedValue(MIN_HEIGHT);
|
|
46
|
+
|
|
47
|
+
const panGesture = Gesture.Pan()
|
|
48
|
+
.onStart(() => {
|
|
49
|
+
startHeight.value = sheetHeight.value;
|
|
50
|
+
})
|
|
51
|
+
.onUpdate((event) => {
|
|
52
|
+
let newHeight = startHeight.value - event.translationY;
|
|
53
|
+
if (newHeight > MAX_HEIGHT) newHeight = MAX_HEIGHT;
|
|
54
|
+
if (newHeight < MIN_HEIGHT) newHeight = MIN_HEIGHT;
|
|
55
|
+
sheetHeight.value = newHeight;
|
|
56
|
+
|
|
57
|
+
if (newHeight < COLLAPSE_HEIGHT) {
|
|
58
|
+
sheetHeight.value = withSpring(MIN_HEIGHT, SPRING_CONFIG);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
const animatedStyle = useAnimatedStyle(() => ({
|
|
63
|
+
height: sheetHeight.value < COLLAPSE_HEIGHT ? 0 : sheetHeight.value,
|
|
64
|
+
opacity: interpolate(
|
|
65
|
+
sheetHeight.value,
|
|
66
|
+
[MIN_HEIGHT, COLLAPSE_HEIGHT],
|
|
67
|
+
[0, 1],
|
|
68
|
+
Extrapolation.CLAMP,
|
|
69
|
+
),
|
|
70
|
+
transform: [
|
|
71
|
+
{
|
|
72
|
+
translateY:
|
|
73
|
+
slideKeyboard - safeBottom + Math.max(0, -sheetHeight.value),
|
|
74
|
+
},
|
|
75
|
+
],
|
|
76
|
+
}));
|
|
77
|
+
|
|
78
|
+
const handleAnimatedStyle = useAnimatedStyle(() => ({
|
|
79
|
+
opacity: sheetHeight.value < COLLAPSE_HEIGHT ? 1 : 0,
|
|
80
|
+
transform: [
|
|
81
|
+
{
|
|
82
|
+
translateY: sheetHeight.value < COLLAPSE_HEIGHT ? 0 : withSpring(20),
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
}));
|
|
86
|
+
|
|
87
|
+
return (
|
|
88
|
+
<>
|
|
89
|
+
<Animated.View
|
|
90
|
+
style={[
|
|
91
|
+
handleAnimatedStyle,
|
|
92
|
+
layout.position.absolute,
|
|
93
|
+
bottom[4],
|
|
94
|
+
w.percent[100],
|
|
95
|
+
layout.flex.center,
|
|
96
|
+
zIndex[1],
|
|
97
|
+
{ marginBottom: safeBottom },
|
|
98
|
+
]}
|
|
99
|
+
>
|
|
100
|
+
<Pressable
|
|
101
|
+
onPress={() => {
|
|
102
|
+
sheetHeight.value =
|
|
103
|
+
sheetHeight.value === MIN_HEIGHT
|
|
104
|
+
? withSpring(MAX_HEIGHT, SPRING_CONFIG)
|
|
105
|
+
: withSpring(MIN_HEIGHT, SPRING_CONFIG);
|
|
106
|
+
}}
|
|
107
|
+
>
|
|
108
|
+
<View
|
|
109
|
+
style={[
|
|
110
|
+
p[1],
|
|
111
|
+
{
|
|
112
|
+
borderRadius: 999,
|
|
113
|
+
backgroundColor: "rgba(0, 0, 0, 0.5)",
|
|
114
|
+
overflow: "hidden",
|
|
115
|
+
},
|
|
116
|
+
]}
|
|
117
|
+
>
|
|
118
|
+
<ChevronUp
|
|
119
|
+
size={32}
|
|
120
|
+
color="white"
|
|
121
|
+
style={{ marginBottom: 1, marginTop: -1 }}
|
|
122
|
+
/>
|
|
123
|
+
</View>
|
|
124
|
+
</Pressable>
|
|
125
|
+
</Animated.View>
|
|
126
|
+
<AnimatedView
|
|
127
|
+
style={[
|
|
128
|
+
animatedStyle,
|
|
129
|
+
isPlayerRatioGreater
|
|
130
|
+
? layout.position.relative
|
|
131
|
+
: layout.position.absolute,
|
|
132
|
+
bottom[0],
|
|
133
|
+
zIndex[1],
|
|
134
|
+
w.percent[100],
|
|
135
|
+
{
|
|
136
|
+
backgroundColor: "rgba(0, 0, 0, 0.5)",
|
|
137
|
+
overflow: "visible",
|
|
138
|
+
borderTopLeftRadius: 16,
|
|
139
|
+
borderTopRightRadius: 16,
|
|
140
|
+
minWidth: "100%",
|
|
141
|
+
},
|
|
142
|
+
style,
|
|
143
|
+
]}
|
|
144
|
+
>
|
|
145
|
+
<View style={[layout.flex.row, layout.flex.justifyCenter]}>
|
|
146
|
+
<GestureDetector gesture={panGesture}>
|
|
147
|
+
<View
|
|
148
|
+
hitSlop={{ top: 20, bottom: 20, left: 20, right: 20 }}
|
|
149
|
+
style={[
|
|
150
|
+
w[32],
|
|
151
|
+
{
|
|
152
|
+
height: 6,
|
|
153
|
+
transform: [{ translateY: -10 }],
|
|
154
|
+
backgroundColor: "#eeeeee66",
|
|
155
|
+
alignItems: "center",
|
|
156
|
+
justifyContent: "center",
|
|
157
|
+
borderRadius: 999,
|
|
158
|
+
},
|
|
159
|
+
]}
|
|
160
|
+
/>
|
|
161
|
+
</GestureDetector>
|
|
162
|
+
</View>
|
|
163
|
+
{children}
|
|
164
|
+
</AnimatedView>
|
|
165
|
+
</>
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
Resizable.displayName = "ResizableChatSheet";
|