@streamplace/components 0.7.26 → 0.7.29

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 (61) hide show
  1. package/dist/components/chat/chat-box.js +2 -2
  2. package/dist/components/chat/chat.js +1 -1
  3. package/dist/components/mobile-player/ui/autoplay-button.js +1 -0
  4. package/dist/components/mobile-player/ui/viewer-context-menu.js +1 -1
  5. package/dist/components/mobile-player/ui/viewer-loading-overlay.js +2 -2
  6. package/dist/components/mobile-player/use-webrtc.js +37 -1
  7. package/dist/components/mobile-player/video.native.js +10 -1
  8. package/dist/components/ui/button.js +107 -155
  9. package/dist/components/ui/dialog.js +83 -116
  10. package/dist/components/ui/dropdown.js +41 -18
  11. package/dist/components/ui/input.js +53 -128
  12. package/dist/components/ui/primitives/button.js +0 -2
  13. package/dist/components/ui/primitives/modal.js +2 -2
  14. package/dist/components/ui/primitives/text.js +48 -8
  15. package/dist/components/ui/text.js +37 -66
  16. package/dist/components/ui/toast.js +78 -40
  17. package/dist/components/ui/view.js +28 -41
  18. package/dist/crypto-polyfill.js +0 -0
  19. package/dist/crypto-polyfill.native.js +24 -0
  20. package/dist/index.js +1 -0
  21. package/dist/lib/theme/index.js +1 -2
  22. package/dist/lib/theme/theme.js +106 -54
  23. package/dist/lib/theme/tokens.js +94 -1
  24. package/dist/livestream-store/chat.js +0 -2
  25. package/dist/livestream-store/stream-key.js +1 -1
  26. package/dist/player-store/player-provider.js +10 -2
  27. package/dist/player-store/single-player-provider.js +1 -1
  28. package/dist/streamplace-store/stream.js +1 -1
  29. package/dist/ui/index.js +2 -3
  30. package/node-compile-cache/v22.15.0-x64-efe9a9df-0/37be0eec +0 -0
  31. package/package.json +3 -2
  32. package/src/components/chat/chat-box.tsx +6 -3
  33. package/src/components/chat/chat.tsx +1 -0
  34. package/src/components/mobile-player/ui/autoplay-button.tsx +1 -0
  35. package/src/components/mobile-player/ui/viewer-context-menu.tsx +2 -2
  36. package/src/components/mobile-player/ui/viewer-loading-overlay.tsx +2 -2
  37. package/src/components/mobile-player/use-webrtc.tsx +41 -1
  38. package/src/components/mobile-player/video.native.tsx +19 -4
  39. package/src/components/ui/button.tsx +110 -172
  40. package/src/components/ui/dialog.tsx +96 -138
  41. package/src/components/ui/dropdown.tsx +60 -22
  42. package/src/components/ui/input.tsx +57 -144
  43. package/src/components/ui/primitives/button.tsx +0 -2
  44. package/src/components/ui/primitives/modal.tsx +0 -2
  45. package/src/components/ui/primitives/text.tsx +51 -8
  46. package/src/components/ui/text.tsx +42 -67
  47. package/src/components/ui/toast.tsx +108 -90
  48. package/src/components/ui/view.tsx +27 -41
  49. package/src/crypto-polyfill.native.tsx +24 -0
  50. package/src/crypto-polyfill.tsx +0 -0
  51. package/src/index.tsx +2 -0
  52. package/src/lib/theme/index.ts +0 -2
  53. package/src/lib/theme/theme.tsx +179 -72
  54. package/src/lib/theme/tokens.ts +97 -0
  55. package/src/livestream-store/chat.tsx +0 -3
  56. package/src/livestream-store/stream-key.tsx +1 -1
  57. package/src/player-store/player-provider.tsx +13 -1
  58. package/src/player-store/single-player-provider.tsx +1 -1
  59. package/src/streamplace-store/stream.tsx +1 -1
  60. package/src/ui/index.ts +0 -2
  61. package/tsconfig.tsbuildinfo +1 -1
@@ -11,11 +11,81 @@ import {
11
11
  ViewStyle,
12
12
  } from "react-native";
13
13
  import { useSafeAreaInsets } from "react-native-safe-area-context";
14
- import { useTheme } from "../../lib/theme/theme";
15
14
 
16
- import { useCallback } from "react";
15
+ import { useTheme } from "../../ui";
17
16
 
18
- type ToastController = {
17
+ type ToastConfig = {
18
+ title: string;
19
+ description?: string;
20
+ duration?: number;
21
+ actionLabel?: string;
22
+ onAction?: () => void;
23
+ };
24
+
25
+ type ToastState = {
26
+ id: string;
27
+ open: boolean;
28
+ title: string;
29
+ description?: string;
30
+ duration: number;
31
+ actionLabel?: string;
32
+ onAction?: () => void;
33
+ };
34
+
35
+ class ToastManager {
36
+ private listeners: Set<(state: ToastState | null) => void> = new Set();
37
+ private currentToast: ToastState | null = null;
38
+ private timeoutId: ReturnType<typeof setTimeout> | null = null;
39
+
40
+ show(config: ToastConfig) {
41
+ if (this.timeoutId) {
42
+ clearTimeout(this.timeoutId);
43
+ }
44
+
45
+ const toast: ToastState = {
46
+ id: Math.random().toString(36).substr(2, 9),
47
+ open: true,
48
+ title: config.title,
49
+ description: config.description,
50
+ duration: config.duration ?? 3,
51
+ actionLabel: config.actionLabel,
52
+ onAction: config.onAction,
53
+ };
54
+
55
+ this.currentToast = toast;
56
+ this.notifyListeners();
57
+
58
+ if (toast.duration > 0) {
59
+ this.timeoutId = setTimeout(() => {
60
+ this.hide();
61
+ }, toast.duration * 1000);
62
+ }
63
+ }
64
+
65
+ hide() {
66
+ if (this.timeoutId) {
67
+ clearTimeout(this.timeoutId);
68
+ this.timeoutId = null;
69
+ }
70
+ this.currentToast = null;
71
+ this.notifyListeners();
72
+ }
73
+
74
+ subscribe(listener: (state: ToastState | null) => void) {
75
+ this.listeners.add(listener);
76
+ return () => {
77
+ this.listeners.delete(listener);
78
+ };
79
+ }
80
+
81
+ private notifyListeners() {
82
+ this.listeners.forEach((listener) => listener(this.currentToast));
83
+ }
84
+ }
85
+
86
+ const toastManager = new ToastManager();
87
+
88
+ export const toast = {
19
89
  show: (
20
90
  title: string,
21
91
  description?: string,
@@ -24,103 +94,51 @@ type ToastController = {
24
94
  actionLabel?: string;
25
95
  onAction?: () => void;
26
96
  },
27
- ) => void;
28
- hide: () => void;
97
+ ) => {
98
+ toastManager.show({
99
+ title,
100
+ description,
101
+ ...options,
102
+ });
103
+ },
104
+ hide: () => toastManager.hide(),
29
105
  };
30
106
 
31
- type UseToastReturn = {
32
- open: boolean;
33
- title: string;
34
- description?: string;
35
- actionLabel?: string;
36
- onAction?: () => void;
37
- duration?: number;
38
- setOpen: (open: boolean) => void;
39
- setTitle: (title: string) => void;
40
- setDescription: (description: string) => void;
41
- setActionLabel: (label: string) => void;
42
- setOnAction: (cb?: () => void) => void;
43
- setDuration: (duration: number) => void;
44
- toastController: ToastController;
45
- };
107
+ export function useToast() {
108
+ const [toastState, setToastState] = useState<ToastState | null>(null);
46
109
 
47
- /**
48
- * useToast - a hook to manage Toast state and provide a toastController.
49
- * Returns a ready-to-render ToastComponent.
50
- */
51
- export function useToast(
52
- initial: {
53
- title?: string;
54
- description?: string;
55
- duration?: number;
56
- actionLabel?: string;
57
- onAction?: () => void;
58
- } = {},
59
- ) {
60
- const [open, setOpen] = useState(false);
61
- const [title, setTitle] = useState(initial.title ?? "");
62
- const [description, setDescription] = useState(initial.description ?? "");
63
- const [duration, setDuration] = useState(initial.duration ?? 3);
64
- const [actionLabel, setActionLabel] = useState(
65
- initial.actionLabel ?? "Action",
66
- );
67
- const [onAction, setOnAction] = useState<(() => void) | undefined>(
68
- initial.onAction,
69
- );
110
+ useEffect(() => {
111
+ return toastManager.subscribe(setToastState);
112
+ }, []);
70
113
 
71
- const show = useCallback(
72
- (
73
- toastTitle: string,
74
- toastDescription?: string,
75
- options?: {
76
- duration?: number;
77
- actionLabel?: string;
78
- onAction?: () => void;
79
- },
80
- ) => {
81
- setTitle(toastTitle);
82
- setDescription(toastDescription ?? "");
83
- setDuration(options?.duration ?? 3);
84
- setActionLabel(options?.actionLabel ?? "Action");
85
- setOnAction(options?.onAction);
86
- setOpen(true);
87
- },
88
- [],
89
- );
114
+ return {
115
+ toast: toastState,
116
+ ...toast,
117
+ };
118
+ }
119
+
120
+ export function ToastProvider() {
121
+ const [toastState, setToastState] = useState<ToastState | null>(null);
90
122
 
91
- const hide = useCallback(() => {
92
- setOpen(false);
123
+ useEffect(() => {
124
+ return toastManager.subscribe(setToastState);
93
125
  }, []);
94
126
 
95
- // Ready-to-render Toast component
96
- const ToastComponent = (
127
+ if (!toastState?.open) return null;
128
+
129
+ return (
97
130
  <Toast
98
- open={open}
99
- onOpenChange={setOpen}
100
- title={title}
101
- description={description}
102
- actionLabel={actionLabel}
103
- onAction={onAction}
104
- duration={duration}
131
+ open={toastState.open}
132
+ onOpenChange={(open) => {
133
+ if (!open) toastManager.hide();
134
+ }}
135
+ title={toastState.title}
136
+ description={toastState.description}
137
+ actionLabel={toastState.actionLabel}
138
+ onAction={toastState.onAction}
139
+ duration={toastState.duration}
105
140
  />
106
141
  );
107
-
108
- return {
109
- open,
110
- title,
111
- description,
112
- actionLabel,
113
- onAction,
114
- duration,
115
- setOpen,
116
- setTitle,
117
- setDescription,
118
- setActionLabel,
119
- setOnAction,
120
- setDuration,
121
- toastController: { show, hide },
122
- ToastComponent,
123
- };
124
142
  }
125
143
 
126
144
  type ToastProps = {
@@ -5,8 +5,8 @@ import {
5
5
  ViewProps as RNViewProps,
6
6
  ViewStyle,
7
7
  } from "react-native";
8
- import { borderRadius as radius, spacing } from "../../lib/theme/atoms";
9
8
  import { useTheme } from "../../lib/theme/theme";
9
+ import * as zero from "../../ui";
10
10
 
11
11
  // View variants using class-variance-authority pattern
12
12
  const viewVariants = cva("", {
@@ -121,72 +121,64 @@ export const View = forwardRef<RNView, ViewProps>(
121
121
  },
122
122
  ref,
123
123
  ) => {
124
- const { theme } = useTheme();
124
+ const { zero: zt } = useTheme();
125
125
 
126
- // Map variant to styles
126
+ // Map variant to styles using theme.zero
127
127
  const variantStyles: ViewStyle = (() => {
128
128
  switch (variant) {
129
129
  case "card":
130
130
  return {
131
- backgroundColor: theme.colors.card,
132
- borderRadius: radius.lg,
133
- shadowColor: "#000",
134
- shadowOffset: { width: 0, height: 2 },
135
- shadowOpacity: 0.1,
136
- shadowRadius: 4,
137
- elevation: 3,
131
+ ...zt.bg.card,
132
+ borderRadius: zero.borderRadius.lg,
133
+ ...zero.shadows.md,
138
134
  };
139
135
  case "overlay":
140
- return {
141
- backgroundColor: "rgba(0, 0, 0, 0.5)",
142
- };
136
+ return zt.bg.overlay;
143
137
  case "surface":
144
- return {
145
- backgroundColor: theme.colors.background,
146
- };
138
+ return zt.bg.background;
147
139
  case "container":
148
140
  return {
149
- backgroundColor: theme.colors.background,
150
- padding: spacing[4],
141
+ ...zt.bg.background,
142
+ ...zero.p[8],
151
143
  };
152
144
  default:
153
145
  return {};
154
146
  }
155
147
  })();
156
148
 
157
- // Map padding to numeric values
149
+ // Map padding to zero tokens
158
150
  const paddingValue = (() => {
159
151
  switch (padding) {
160
152
  case "xs":
161
- return spacing[1];
153
+ return zero.p[1];
162
154
  case "sm":
163
- return spacing[2];
155
+ return zero.p[2];
164
156
  case "md":
165
- return spacing[3];
157
+ return zero.p[4];
166
158
  case "lg":
167
- return spacing[4];
159
+ return zero.p[6];
168
160
  case "xl":
169
- return spacing[5];
161
+ return zero.p[8];
170
162
  default:
171
- return undefined;
163
+ return {};
172
164
  }
173
165
  })();
174
166
 
175
- // Map margin to numeric values
167
+ // Map margin to zero tokens
176
168
  const marginValue = (() => {
177
169
  switch (margin) {
178
170
  case "xs":
179
- return spacing[1];
171
+ return zero.m[1];
180
172
  case "sm":
181
- return spacing[2];
173
+ return zero.m[2];
182
174
  case "md":
183
- return spacing[3];
175
+ return zero.m[4];
184
176
  case "lg":
185
- return spacing[4];
177
+ return zero.m[6];
186
178
  case "xl":
187
- return spacing[5];
179
+ return zero.m[8];
188
180
  default:
189
- return undefined;
181
+ return {};
190
182
  }
191
183
  })();
192
184
 
@@ -262,8 +254,8 @@ export const View = forwardRef<RNView, ViewProps>(
262
254
 
263
255
  const computedStyle: ViewStyle = {
264
256
  ...variantStyles,
265
- ...(paddingValue !== undefined && { padding: paddingValue }),
266
- ...(marginValue !== undefined && { margin: marginValue }),
257
+ ...paddingValue,
258
+ ...marginValue,
267
259
  flexDirection,
268
260
  alignItems,
269
261
  justifyContent,
@@ -278,13 +270,7 @@ export const View = forwardRef<RNView, ViewProps>(
278
270
  ...(borderColor && { borderColor }),
279
271
  ...(borderWidth !== undefined && { borderWidth }),
280
272
  ...(borderRadius !== undefined && { borderRadius }),
281
- ...(shadow && {
282
- shadowColor: "#000",
283
- shadowOffset: { width: 0, height: 2 },
284
- shadowOpacity: 0.1,
285
- shadowRadius: 4,
286
- elevation: 3,
287
- }),
273
+ ...(shadow && zero.shadows.md),
288
274
  };
289
275
 
290
276
  const finalStyle = Array.isArray(style)
@@ -0,0 +1,24 @@
1
+ // awkward use of require()? you betcha. but import() with Metro causes it to try and
2
+ // resolve the package at compile-time even if not installed, so here we are.
3
+ let rnqc: any | null = null;
4
+ let expoCrypto: any | null = null;
5
+ try {
6
+ rnqc = require("react-native-quick-crypto");
7
+ } catch (err) {}
8
+ try {
9
+ expoCrypto = require("expo-crypto");
10
+ } catch (err) {}
11
+
12
+ if (!rnqc && !expoCrypto) {
13
+ throw new Error(
14
+ "Livestreaming requires one of react-native-quick-crypto or expo-crypto",
15
+ );
16
+ } else if (!rnqc && expoCrypto) {
17
+ // @atproto/crypto dependencies expect crypto.getRandomValues to be a function
18
+ if (typeof globalThis.crypto === "undefined") {
19
+ globalThis.crypto = {} as any;
20
+ }
21
+ if (typeof globalThis.crypto.getRandomValues === "undefined") {
22
+ globalThis.crypto.getRandomValues = expoCrypto.getRandomValues;
23
+ }
24
+ }
File without changes
package/src/index.tsx CHANGED
@@ -1,4 +1,6 @@
1
1
  // barrel file :)
2
+ import "./crypto-polyfill";
3
+
2
4
  export * from "./livestream-provider";
3
5
  export * from "./livestream-store";
4
6
  export * from "./player-store";
@@ -3,7 +3,6 @@ export {
3
3
  ThemeProvider,
4
4
  createThemeColors,
5
5
  createThemeIcons,
6
- createThemeStyles,
7
6
  createThemedStyles,
8
7
  darkTheme,
9
8
  lightTheme,
@@ -11,7 +10,6 @@ export {
11
10
  useTheme,
12
11
  type Theme,
13
12
  type ThemeIcons,
14
- type ThemeStyles,
15
13
  } from "./theme";
16
14
 
17
15
  // Design tokens