@streamplace/components 0.7.27 → 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 (43) 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 +30 -0
  7. package/dist/components/ui/button.js +107 -155
  8. package/dist/components/ui/dialog.js +83 -116
  9. package/dist/components/ui/dropdown.js +41 -18
  10. package/dist/components/ui/input.js +53 -128
  11. package/dist/components/ui/primitives/button.js +0 -2
  12. package/dist/components/ui/primitives/modal.js +2 -2
  13. package/dist/components/ui/primitives/text.js +48 -8
  14. package/dist/components/ui/text.js +37 -66
  15. package/dist/components/ui/toast.js +78 -40
  16. package/dist/components/ui/view.js +28 -41
  17. package/dist/lib/theme/index.js +1 -2
  18. package/dist/lib/theme/theme.js +106 -54
  19. package/dist/lib/theme/tokens.js +94 -1
  20. package/dist/ui/index.js +2 -3
  21. package/node-compile-cache/v22.15.0-x64-efe9a9df-0/37be0eec +0 -0
  22. package/package.json +3 -2
  23. package/src/components/chat/chat-box.tsx +6 -3
  24. package/src/components/chat/chat.tsx +1 -0
  25. package/src/components/mobile-player/ui/autoplay-button.tsx +1 -0
  26. package/src/components/mobile-player/ui/viewer-context-menu.tsx +2 -2
  27. package/src/components/mobile-player/ui/viewer-loading-overlay.tsx +2 -2
  28. package/src/components/mobile-player/use-webrtc.tsx +31 -0
  29. package/src/components/ui/button.tsx +110 -172
  30. package/src/components/ui/dialog.tsx +96 -138
  31. package/src/components/ui/dropdown.tsx +60 -22
  32. package/src/components/ui/input.tsx +57 -144
  33. package/src/components/ui/primitives/button.tsx +0 -2
  34. package/src/components/ui/primitives/modal.tsx +0 -2
  35. package/src/components/ui/primitives/text.tsx +51 -8
  36. package/src/components/ui/text.tsx +42 -67
  37. package/src/components/ui/toast.tsx +108 -90
  38. package/src/components/ui/view.tsx +27 -41
  39. package/src/lib/theme/index.ts +0 -2
  40. package/src/lib/theme/theme.tsx +179 -72
  41. package/src/lib/theme/tokens.ts +97 -0
  42. package/src/ui/index.ts +0 -2
  43. package/tsconfig.tsbuildinfo +1 -1
@@ -290,7 +290,7 @@ function ChatBox({ isPopout, chatBoxStyle, emojiData, setIsChatVisible, }) {
290
290
  atoms_1.mb[2],
291
291
  atoms_1.gap.all[2],
292
292
  { justifyContent: "flex-end" },
293
- ], children: [(0, jsx_runtime_1.jsx)(__1.Button, { variant: "secondary", style: { borderRadius: 16, height: 36, maxWidth: 36 }, onPress: () => {
293
+ ], children: [(0, jsx_runtime_1.jsx)(__1.Button, { variant: "secondary", style: { borderRadius: 16, maxWidth: 44, aspectRatio: 1 }, "aria-label": "Insert Mention", onPress: () => {
294
294
  // if the last character is not @, add it
295
295
  !message.endsWith("@") && setMessage(message + "@");
296
296
  // get all the text after the last @
@@ -302,7 +302,7 @@ function ChatBox({ isPopout, chatBoxStyle, emojiData, setIsChatVisible, }) {
302
302
  textAreaRef.current?.focus();
303
303
  }, children: (0, jsx_runtime_1.jsx)(lucide_react_native_1.AtSignIcon, { size: 20, color: "white" }) }), (0, jsx_runtime_1.jsx)(react_native_1.Pressable, { onHoverOut: () => {
304
304
  setEmojiIconIndex(Math.floor(Math.random() * COOL_EMOJI_LIST.length));
305
- }, children: (0, jsx_runtime_1.jsx)(__1.Button, { variant: "secondary", style: { borderRadius: 16, height: 36, maxWidth: 36 }, onPress: () => setShowEmojiSelector(!showEmojiSelector), children: (0, jsx_runtime_1.jsx)(__1.Text, { children: COOL_EMOJI_LIST[emojiIconIndex] }) }) }), !isPopout && ((0, jsx_runtime_1.jsx)(__1.Button, { variant: "secondary", style: { borderRadius: 16, height: 36, maxWidth: 36 }, onPress: () => {
305
+ }, children: (0, jsx_runtime_1.jsx)(__1.Button, { variant: "secondary", "aria-label": "Insert Emoji", style: { borderRadius: 16, maxWidth: 44, aspectRatio: 1 }, onPress: () => setShowEmojiSelector(!showEmojiSelector), children: (0, jsx_runtime_1.jsx)(__1.Text, { children: COOL_EMOJI_LIST[emojiIconIndex] }) }) }), !isPopout && ((0, jsx_runtime_1.jsx)(__1.Button, { variant: "secondary", "aria-label": "Popout Chat", style: { borderRadius: 16, maxWidth: 44, aspectRatio: 1 }, onPress: () => {
306
306
  if (!linfo)
307
307
  return;
308
308
  const u = new URL(window.location.href);
@@ -156,5 +156,5 @@ function Chat({ shownMessages = SHOWN_MSGS, style: propsStyle, canModerate = fal
156
156
  atoms_1.flex.grow[1],
157
157
  atoms_1.flex.shrink[1],
158
158
  { minWidth: 0, maxWidth: "100%" },
159
- ], data: chat.slice(0, shownMessages), inverted: true, keyExtractor: keyExtractor, renderItem: ({ item, index }) => ((0, jsx_runtime_1.jsx)(ChatLine, { item: item, canModerate: canModerate })), removeClippedSubviews: true, maxToRenderPerBatch: 10, initialNumToRender: 10, updateCellsBatchingPeriod: 50, onScroll: handleScroll, scrollEventThrottle: 16 }), (0, jsx_runtime_1.jsx)(mod_view_1.ModView, {})] }));
159
+ ], data: chat.slice(0, shownMessages), inverted: true, keyExtractor: keyExtractor, renderItem: ({ item, index }) => ((0, jsx_runtime_1.jsx)(ChatLine, { item: item, canModerate: canModerate })), removeClippedSubviews: true, maxToRenderPerBatch: 10, initialNumToRender: 10, updateCellsBatchingPeriod: 50, onScroll: handleScroll, scrollEventThrottle: 16, nestedScrollEnabled: true }), (0, jsx_runtime_1.jsx)(mod_view_1.ModView, {})] }));
160
160
  }
@@ -19,6 +19,7 @@ function AutoplayButton() {
19
19
  .play()
20
20
  .then(() => {
21
21
  setAutoplayFailed(false);
22
+ setMuted(false);
22
23
  setUserInteraction();
23
24
  })
24
25
  .catch((err) => {
@@ -33,7 +33,7 @@ function ContextMenu({ dropdownPortalContainer, }) {
33
33
  const DropdownMenuContent = isMobile
34
34
  ? ui_1.ResponsiveDropdownMenuContent
35
35
  : ui_1.DropdownMenuContentWithoutPortal;
36
- return ((0, jsx_runtime_1.jsxs)(ui_1.DropdownMenu, { children: [(0, jsx_runtime_1.jsx)(ui_1.DropdownMenuTrigger, { children: (0, jsx_runtime_1.jsx)(lucide_react_native_1.Settings, { color: theme_1.colors.gray[200] }) }), (0, jsx_runtime_1.jsx)(Portal, { container: dropdownPortalContainer, children: (0, jsx_runtime_1.jsxs)(DropdownMenuContent, { side: "top", align: "end", children: [(0, jsx_runtime_1.jsx)(ui_1.DropdownMenuGroup, { title: "Resolution", children: (0, jsx_runtime_1.jsxs)(ui_1.DropdownMenuRadioGroup, { value: quality, onValueChange: setQuality, children: [(0, jsx_runtime_1.jsx)(ui_1.DropdownMenuRadioItem, { value: "source", children: (0, jsx_runtime_1.jsx)(ui_1.Text, { children: "Source (Original Quality)" }) }), qualities.map((r) => ((0, jsx_runtime_1.jsx)(ui_1.DropdownMenuRadioItem, { value: r.name, children: (0, jsx_runtime_1.jsx)(ui_1.Text, { children: r.name }) })))] }) }), (0, jsx_runtime_1.jsx)(ui_1.DropdownMenuGroup, { title: "Advanced", children: (0, jsx_runtime_1.jsx)(ui_1.DropdownMenuCheckboxItem, { checked: lowLatency, onCheckedChange: () => setLowLatency(!lowLatency), children: (0, jsx_runtime_1.jsx)(ui_1.Text, { children: "Low Latency" }) }) }), (0, jsx_runtime_1.jsx)(ui_1.DropdownMenuInfo, { description: "Reduces the delay between video and chat for a more real-time experience." }), (0, jsx_runtime_1.jsx)(ui_1.DropdownMenuGroup, { children: (0, jsx_runtime_1.jsx)(ui_1.DropdownMenuCheckboxItem, { checked: debugInfo, onCheckedChange: () => setShowDebugInfo(!debugInfo), children: (0, jsx_runtime_1.jsx)(ui_1.Text, { children: "Show Debug Info" }) }) }), (0, jsx_runtime_1.jsx)(ui_1.DropdownMenuGroup, { title: "Report", children: (0, jsx_runtime_1.jsx)(ReportButton, { livestream: livestream, setReportModalOpen: setReportModalOpen, setReportSubject: setReportSubject }) })] }) })] }));
36
+ return ((0, jsx_runtime_1.jsxs)(ui_1.DropdownMenu, { children: [(0, jsx_runtime_1.jsx)(ui_1.DropdownMenuTrigger, { children: (0, jsx_runtime_1.jsx)(lucide_react_native_1.Menu, { color: theme_1.colors.gray[200] }) }), (0, jsx_runtime_1.jsx)(Portal, { container: dropdownPortalContainer, children: (0, jsx_runtime_1.jsxs)(DropdownMenuContent, { side: "top", align: "end", children: [(0, jsx_runtime_1.jsx)(ui_1.DropdownMenuGroup, { title: "Resolution", children: (0, jsx_runtime_1.jsxs)(ui_1.DropdownMenuRadioGroup, { value: quality, onValueChange: setQuality, children: [(0, jsx_runtime_1.jsx)(ui_1.DropdownMenuRadioItem, { value: "source", children: (0, jsx_runtime_1.jsx)(ui_1.Text, { children: "Source (Original Quality)" }) }), qualities.map((r) => ((0, jsx_runtime_1.jsx)(ui_1.DropdownMenuRadioItem, { value: r.name, children: (0, jsx_runtime_1.jsx)(ui_1.Text, { children: r.name }) })))] }) }), (0, jsx_runtime_1.jsx)(ui_1.DropdownMenuGroup, { title: "Advanced", children: (0, jsx_runtime_1.jsx)(ui_1.DropdownMenuCheckboxItem, { checked: lowLatency, onCheckedChange: () => setLowLatency(!lowLatency), children: (0, jsx_runtime_1.jsx)(ui_1.Text, { children: "Low Latency" }) }) }), (0, jsx_runtime_1.jsx)(ui_1.DropdownMenuInfo, { description: "Reduces the delay between video and chat for a more real-time experience." }), (0, jsx_runtime_1.jsx)(ui_1.DropdownMenuGroup, { children: (0, jsx_runtime_1.jsx)(ui_1.DropdownMenuCheckboxItem, { checked: debugInfo, onCheckedChange: () => setShowDebugInfo(!debugInfo), children: (0, jsx_runtime_1.jsx)(ui_1.Text, { children: "Show Debug Info" }) }) }), (0, jsx_runtime_1.jsx)(ui_1.DropdownMenuGroup, { title: "Report", children: (0, jsx_runtime_1.jsx)(ReportButton, { livestream: livestream, setReportModalOpen: setReportModalOpen, setReportSubject: setReportSubject }) })] }) })] }));
37
37
  }
38
38
  function ReportButton({ livestream, setReportModalOpen, setReportSubject, }) {
39
39
  const { onOpenChange } = (0, dropdown_menu_1.useRootContext)();
@@ -9,7 +9,7 @@ const react_native_reanimated_1 = tslib_1.__importStar(require("react-native-rea
9
9
  const __1 = require("../../..");
10
10
  function ViewerLoadingOverlay() {
11
11
  const status = (0, __1.usePlayerStore)((x) => x.status);
12
- const theme = (0, __1.useTheme)();
12
+ const { theme, zero: zt } = (0, __1.useTheme)();
13
13
  const opacity = (0, react_native_reanimated_1.useSharedValue)(0);
14
14
  (0, react_1.useEffect)(() => {
15
15
  if (status === __1.PlayerStatus.PLAYING || status === __1.PlayerStatus.SUSPEND) {
@@ -32,7 +32,7 @@ function ViewerLoadingOverlay() {
32
32
  }
33
33
  let spinner = (0, jsx_runtime_1.jsx)(__1.Loader, { size: "large" });
34
34
  if (status === __1.PlayerStatus.PAUSE) {
35
- spinner = (0, jsx_runtime_1.jsx)(lucide_react_native_1.Play, { size: "$12", color: theme.styles.text.primary["color"] });
35
+ spinner = (0, jsx_runtime_1.jsx)(lucide_react_native_1.Play, { size: "$12", color: theme.colors.foreground });
36
36
  }
37
37
  return ((0, jsx_runtime_1.jsx)(react_native_reanimated_1.default.View, { style: [
38
38
  {
@@ -3,7 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.default = useWebRTC;
4
4
  exports.negotiateConnectionWithClientOffer = negotiateConnectionWithClientOffer;
5
5
  exports.useWebRTCIngest = useWebRTCIngest;
6
+ exports.forceStereoAudio = forceStereoAudio;
7
+ const tslib_1 = require("tslib");
6
8
  const react_1 = require("react");
9
+ const sdpTransform = tslib_1.__importStar(require("sdp-transform"));
7
10
  const __1 = require("../..");
8
11
  const webrtc_primitives_1 = require("./webrtc-primitives");
9
12
  function useWebRTC(endpoint) {
@@ -97,6 +100,11 @@ async function negotiateConnectionWithClientOffer(peerConnection, endpoint, bear
97
100
  offerToReceiveAudio: true,
98
101
  offerToReceiveVideo: true,
99
102
  });
103
+ if (!offer.sdp) {
104
+ throw Error("no SDP in offer");
105
+ }
106
+ const newSDP = forceStereoAudio(offer.sdp);
107
+ offer.sdp = newSDP;
100
108
  /** https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/setLocalDescription */
101
109
  await peerConnection.setLocalDescription(offer);
102
110
  /** Wait for ICE gathering to complete */
@@ -247,3 +255,25 @@ function useWebRTCIngest({ endpoint, }) {
247
255
  }, [peerConnection, mediaStream, ingestLive]);
248
256
  return [mediaStream, setMediaStream];
249
257
  }
258
+ function forceStereoAudio(sdp) {
259
+ const parsedSDP = sdpTransform.parse(sdp);
260
+ const audioMedia = parsedSDP.media.find((m) => m.type === "audio");
261
+ if (!audioMedia) {
262
+ throw Error("no audio media in SDP");
263
+ }
264
+ const opusCodec = audioMedia.rtp.find((c) => c.codec === "opus");
265
+ if (!opusCodec) {
266
+ throw Error("no opus codec in SDP");
267
+ }
268
+ const opusFMTP = audioMedia.fmtp.find((c) => c.payload === opusCodec.payload);
269
+ if (!opusFMTP) {
270
+ throw Error("no opus fmtp in SDP");
271
+ }
272
+ const opusParams = sdpTransform.parseParams(opusFMTP.config);
273
+ opusParams.stereo = 1;
274
+ const newParams = Object.entries(opusParams)
275
+ .map(([k, v]) => `${k}=${v}`)
276
+ .join(";");
277
+ opusFMTP.config = newParams;
278
+ return sdpTransform.write(parsedSDP);
279
+ }
@@ -7,7 +7,7 @@ const class_variance_authority_1 = require("class-variance-authority");
7
7
  const react_1 = tslib_1.__importStar(require("react"));
8
8
  const react_native_1 = require("react-native");
9
9
  const theme_1 = require("../../lib/theme/theme");
10
- const tokens = tslib_1.__importStar(require("../../lib/theme/tokens"));
10
+ const zero = tslib_1.__importStar(require("../../ui"));
11
11
  const button_1 = require("./primitives/button");
12
12
  const text_1 = require("./primitives/text");
13
13
  // Button variants using class-variance-authority pattern
@@ -36,38 +36,113 @@ const buttonVariants = (0, class_variance_authority_1.cva)("", {
36
36
  });
37
37
  exports.buttonVariants = buttonVariants;
38
38
  exports.Button = (0, react_1.forwardRef)(({ variant = "primary", size = "md", children, leftIcon, rightIcon, loading = false, loadingText, disabled, style, ...props }, ref) => {
39
- const { theme } = (0, theme_1.useTheme)();
40
- // Create dynamic styles based on theme
41
- const styles = (0, react_1.useMemo)(() => createStyles(theme), [theme]);
42
- // Get variant styles
39
+ const { zero: zt, icons } = (0, theme_1.useTheme)();
40
+ // Get variant styles using theme.zero
43
41
  const buttonStyle = (0, react_1.useMemo)(() => {
44
- const variantStyle = styles[`${variant}Button`];
45
- const sizeStyle = styles[`${size}Button`];
46
- return [variantStyle, sizeStyle];
47
- }, [variant, size, styles]);
48
- // Get inner styles for button content
49
- const buttonInnerStyle = (0, react_1.useMemo)(() => {
50
- const sizeInnerStyle = styles[`${size}ButtonInner`];
51
- return sizeInnerStyle;
52
- }, [size, styles]);
53
- const textStyle = react_1.default.useMemo(() => {
54
- const variantTextStyle = styles[`${variant}Text`];
55
- const sizeTextStyle = styles[`${size}Text`];
56
- return [variantTextStyle, sizeTextStyle];
57
- }, [variant, size, styles]);
42
+ switch (variant) {
43
+ case "primary":
44
+ return zt.button.primary;
45
+ case "secondary":
46
+ return zt.button.secondary;
47
+ case "outline":
48
+ return zt.button.outline;
49
+ case "ghost":
50
+ return zt.button.ghost;
51
+ case "destructive":
52
+ return [zt.bg.destructive, zero.shadows.sm];
53
+ case "success":
54
+ return [zt.bg.success, zero.shadows.sm];
55
+ default:
56
+ return zt.button.primary;
57
+ }
58
+ }, [variant, zt]);
59
+ // Get text styles using theme.zero
60
+ const textStyle = (0, react_1.useMemo)(() => {
61
+ switch (variant) {
62
+ case "primary":
63
+ return [zt.text.primaryForeground, { fontWeight: "600" }];
64
+ case "secondary":
65
+ return [zt.text.secondaryForeground, { fontWeight: "500" }];
66
+ case "outline":
67
+ case "ghost":
68
+ return [zt.text.foreground, { fontWeight: "500" }];
69
+ case "destructive":
70
+ return [zt.text.destructiveForeground, { fontWeight: "600" }];
71
+ case "success":
72
+ return [zt.text.successForeground, { fontWeight: "600" }];
73
+ default:
74
+ return [zt.text.primaryForeground, { fontWeight: "600" }];
75
+ }
76
+ }, [variant, zt]);
77
+ // Size styles using theme.zero
78
+ const sizeStyles = (0, react_1.useMemo)(() => {
79
+ switch (size) {
80
+ case "sm":
81
+ return {
82
+ button: [
83
+ zero.px[3],
84
+ zero.py[2],
85
+ { borderRadius: zero.borderRadius.md },
86
+ ],
87
+ inner: { gap: 4 },
88
+ text: zt.text.sm,
89
+ };
90
+ case "lg":
91
+ return {
92
+ button: [
93
+ zero.px[6],
94
+ zero.py[3],
95
+ { borderRadius: zero.borderRadius.md },
96
+ ],
97
+ inner: { gap: 8 },
98
+ text: zt.text.lg,
99
+ };
100
+ case "xl":
101
+ return {
102
+ button: [
103
+ zero.px[8],
104
+ zero.py[4],
105
+ { borderRadius: zero.borderRadius.lg },
106
+ ],
107
+ inner: { gap: 12 },
108
+ text: zt.text.xl,
109
+ };
110
+ case "pill":
111
+ return {
112
+ button: [
113
+ zero.px[4],
114
+ zero.py[2],
115
+ { borderRadius: zero.borderRadius.full },
116
+ ],
117
+ inner: { gap: 4 },
118
+ text: zt.text.sm,
119
+ };
120
+ case "md":
121
+ default:
122
+ return {
123
+ button: [
124
+ zero.px[4],
125
+ zero.py[2],
126
+ { borderRadius: zero.borderRadius.md },
127
+ ],
128
+ inner: { gap: 6 },
129
+ text: zt.text.md,
130
+ };
131
+ }
132
+ }, [size, zt]);
58
133
  const iconSize = react_1.default.useMemo(() => {
59
134
  switch (size) {
60
135
  case "sm":
61
- return 16;
136
+ return icons.size.sm;
62
137
  case "lg":
63
- return 20;
138
+ return icons.size.lg;
64
139
  case "xl":
65
- return 24;
140
+ return icons.size.xl;
66
141
  case "md":
67
142
  default:
68
- return 18;
143
+ return icons.size.md;
69
144
  }
70
- }, [size]);
145
+ }, [size, icons]);
71
146
  const spinnerSize = (0, react_1.useMemo)(() => {
72
147
  switch (size) {
73
148
  case "sm":
@@ -84,140 +159,17 @@ exports.Button = (0, react_1.forwardRef)(({ variant = "primary", size = "md", ch
84
159
  switch (variant) {
85
160
  case "outline":
86
161
  case "ghost":
87
- return theme.colors.primary;
162
+ return icons.color.primary;
88
163
  case "secondary":
89
- return theme.colors.secondaryForeground;
164
+ return icons.color.secondary;
90
165
  case "destructive":
91
- return theme.colors.destructiveForeground;
166
+ return icons.color.destructive;
167
+ case "success":
168
+ return icons.color.success;
92
169
  default:
93
- return theme.colors.primaryForeground;
170
+ return icons.color.default;
94
171
  }
95
- }, [variant, theme.colors]);
96
- return ((0, jsx_runtime_1.jsx)(button_1.ButtonPrimitive.Root, { ref: ref, disabled: disabled || loading, style: [buttonStyle, style], ...props, children: (0, jsx_runtime_1.jsxs)(button_1.ButtonPrimitive.Content, { style: buttonInnerStyle, children: [loading && !leftIcon ? ((0, jsx_runtime_1.jsx)(button_1.ButtonPrimitive.Icon, { position: "left", children: (0, jsx_runtime_1.jsx)(react_native_1.ActivityIndicator, { size: spinnerSize, color: spinnerColor }) })) : leftIcon ? ((0, jsx_runtime_1.jsx)(button_1.ButtonPrimitive.Icon, { position: "left", style: { width: iconSize, height: iconSize }, children: leftIcon })) : null, (0, jsx_runtime_1.jsx)(text_1.TextPrimitive.Root, { style: textStyle, children: loading && loadingText ? loadingText : children }), loading && rightIcon ? ((0, jsx_runtime_1.jsx)(button_1.ButtonPrimitive.Icon, { position: "right", children: (0, jsx_runtime_1.jsx)(react_native_1.ActivityIndicator, { size: spinnerSize, color: spinnerColor }) })) : rightIcon ? ((0, jsx_runtime_1.jsx)(button_1.ButtonPrimitive.Icon, { position: "right", style: { width: iconSize, height: iconSize }, children: rightIcon })) : null] }) }));
172
+ }, [variant, icons]);
173
+ return ((0, jsx_runtime_1.jsx)(button_1.ButtonPrimitive.Root, { ref: ref, disabled: disabled || loading, style: [buttonStyle, sizeStyles.button, style], ...props, children: (0, jsx_runtime_1.jsxs)(button_1.ButtonPrimitive.Content, { style: sizeStyles.inner, children: [loading && !leftIcon ? ((0, jsx_runtime_1.jsx)(button_1.ButtonPrimitive.Icon, { position: "left", children: (0, jsx_runtime_1.jsx)(react_native_1.ActivityIndicator, { size: spinnerSize, color: spinnerColor }) })) : leftIcon ? ((0, jsx_runtime_1.jsx)(button_1.ButtonPrimitive.Icon, { position: "left", style: { width: iconSize, height: iconSize }, children: leftIcon })) : null, (0, jsx_runtime_1.jsx)(text_1.TextPrimitive.Root, { style: [textStyle, sizeStyles.text], children: loading && loadingText ? loadingText : children }), loading && rightIcon ? ((0, jsx_runtime_1.jsx)(button_1.ButtonPrimitive.Icon, { position: "right", children: (0, jsx_runtime_1.jsx)(react_native_1.ActivityIndicator, { size: spinnerSize, color: spinnerColor }) })) : rightIcon ? ((0, jsx_runtime_1.jsx)(button_1.ButtonPrimitive.Icon, { position: "right", style: { width: iconSize, height: iconSize }, children: rightIcon })) : null] }) }));
97
174
  });
98
175
  exports.Button.displayName = "Button";
99
- // Create theme-based styles
100
- function createStyles(theme) {
101
- return react_native_1.StyleSheet.create({
102
- // Variant styles
103
- primaryButton: {
104
- backgroundColor: theme.colors.primary,
105
- borderWidth: 0,
106
- ...theme.shadows.sm,
107
- },
108
- primaryText: {
109
- color: theme.colors.primaryForeground,
110
- fontWeight: "600",
111
- },
112
- secondaryButton: {
113
- backgroundColor: theme.colors.secondary,
114
- borderWidth: 0,
115
- },
116
- secondaryText: {
117
- color: theme.colors.secondaryForeground,
118
- fontWeight: "500",
119
- },
120
- outlineButton: {
121
- backgroundColor: "transparent",
122
- borderWidth: 1,
123
- borderColor: theme.colors.border,
124
- },
125
- outlineText: {
126
- color: theme.colors.foreground,
127
- fontWeight: "500",
128
- },
129
- ghostButton: {
130
- backgroundColor: "transparent",
131
- borderWidth: 0,
132
- },
133
- ghostText: {
134
- color: theme.colors.foreground,
135
- fontWeight: "500",
136
- },
137
- destructiveButton: {
138
- backgroundColor: theme.colors.destructive,
139
- borderWidth: 0,
140
- ...theme.shadows.sm,
141
- },
142
- destructiveText: {
143
- color: theme.colors.destructiveForeground,
144
- fontWeight: "600",
145
- },
146
- successButton: {
147
- backgroundColor: theme.colors.success,
148
- borderWidth: 0,
149
- ...theme.shadows.sm,
150
- },
151
- successText: {
152
- color: theme.colors.successForeground,
153
- fontWeight: "600",
154
- },
155
- pillButton: {
156
- paddingHorizontal: theme.spacing[2],
157
- paddingVertical: theme.spacing[1],
158
- borderRadius: tokens.borderRadius.full,
159
- minHeight: tokens.touchTargets.minimum / 2,
160
- },
161
- pillText: {
162
- color: theme.colors.primaryForeground,
163
- fontWeight: "400",
164
- },
165
- // Size styles
166
- smButton: {
167
- paddingHorizontal: theme.spacing[3],
168
- paddingVertical: theme.spacing[2],
169
- borderRadius: tokens.borderRadius.md,
170
- minHeight: tokens.touchTargets.minimum,
171
- gap: theme.spacing[1],
172
- },
173
- smButtonInner: {
174
- gap: theme.spacing[1],
175
- },
176
- smText: {
177
- fontSize: 14,
178
- lineHeight: 16,
179
- },
180
- mdButton: {
181
- paddingHorizontal: theme.spacing[4],
182
- paddingVertical: theme.spacing[3],
183
- borderRadius: tokens.borderRadius.md,
184
- minHeight: tokens.touchTargets.minimum,
185
- gap: theme.spacing[2],
186
- },
187
- mdButtonInner: {
188
- gap: theme.spacing[2],
189
- },
190
- mdText: {
191
- fontSize: 16,
192
- lineHeight: 18,
193
- },
194
- lgButton: {
195
- paddingHorizontal: theme.spacing[6],
196
- paddingVertical: theme.spacing[4],
197
- borderRadius: tokens.borderRadius.md,
198
- minHeight: tokens.touchTargets.comfortable,
199
- gap: theme.spacing[3],
200
- },
201
- lgButtonInner: {
202
- gap: theme.spacing[3],
203
- },
204
- lgText: {
205
- fontSize: 18,
206
- lineHeight: 20,
207
- },
208
- xlButton: {
209
- paddingHorizontal: theme.spacing[8],
210
- paddingVertical: theme.spacing[5],
211
- borderRadius: tokens.borderRadius.lg,
212
- minHeight: tokens.touchTargets.large,
213
- gap: theme.spacing[4],
214
- },
215
- xlButtonInner: {
216
- gap: theme.spacing[4],
217
- },
218
- xlText: {
219
- fontSize: 20,
220
- lineHeight: 24,
221
- },
222
- });
223
- }
@@ -8,6 +8,7 @@ const lucide_react_native_1 = require("lucide-react-native");
8
8
  const react_1 = tslib_1.__importStar(require("react"));
9
9
  const react_native_1 = require("react-native");
10
10
  const theme_1 = require("../../lib/theme/theme");
11
+ const zero = tslib_1.__importStar(require("../../ui"));
11
12
  const icons_1 = require("./icons");
12
13
  const modal_1 = require("./primitives/modal");
13
14
  const ThemedX = (0, icons_1.createThemedIcon)(lucide_react_native_1.X);
@@ -42,9 +43,66 @@ const dialogVariants = (0, class_variance_authority_1.cva)("", {
42
43
  });
43
44
  exports.dialogVariants = dialogVariants;
44
45
  exports.Dialog = (0, react_1.forwardRef)(({ variant = "left", size = "md", position = "center", children, title, description, dismissible = true, showCloseButton = true, onClose, open = false, onOpenChange, ...props }, ref) => {
45
- const { theme } = (0, theme_1.useTheme)();
46
- // Create dynamic styles based on theme
47
- const styles = react_1.default.useMemo(() => createStyles(theme), [theme]);
46
+ const { zero: zt, theme } = (0, theme_1.useTheme)();
47
+ // Content styles using theme.zero
48
+ const contentStyles = react_1.default.useMemo(() => {
49
+ const baseStyle = [
50
+ zt.bg.card,
51
+ zero.r.lg,
52
+ zero.shadows.lg,
53
+ { maxHeight: "90%", maxWidth: "90%" },
54
+ ];
55
+ const variantStyle = (() => {
56
+ switch (variant) {
57
+ case "sheet":
58
+ return [
59
+ { borderRadius: zero.borderRadius.xl },
60
+ {
61
+ borderBottomLeftRadius: 0,
62
+ borderBottomRightRadius: 0,
63
+ marginTop: "auto",
64
+ marginBottom: 0,
65
+ maxHeight: "80%",
66
+ width: "100%",
67
+ maxWidth: "100%",
68
+ },
69
+ ];
70
+ case "fullscreen":
71
+ return [
72
+ {
73
+ width: "100%",
74
+ height: "100%",
75
+ maxWidth: "100%",
76
+ maxHeight: "100%",
77
+ borderRadius: 0,
78
+ margin: 0,
79
+ },
80
+ ];
81
+ default:
82
+ return [];
83
+ }
84
+ })();
85
+ const sizeStyle = (() => {
86
+ switch (size) {
87
+ case "sm":
88
+ return { minWidth: 300, minHeight: 200 };
89
+ case "lg":
90
+ return { minWidth: 500, minHeight: 400 };
91
+ case "xl":
92
+ return { minWidth: 600, minHeight: 500 };
93
+ case "full":
94
+ return {
95
+ width: "95%",
96
+ height: "95%",
97
+ maxWidth: "95%",
98
+ maxHeight: "95%",
99
+ };
100
+ default:
101
+ return { minWidth: 400, minHeight: 300 };
102
+ }
103
+ })();
104
+ return [baseStyle, variantStyle, sizeStyle].flat();
105
+ }, [variant, size, zero]);
48
106
  const handleClose = react_1.default.useCallback(() => {
49
107
  if (onClose) {
50
108
  onClose();
@@ -70,137 +128,46 @@ exports.Dialog = (0, react_1.forwardRef)(({ variant = "left", size = "md", posit
70
128
  }
71
129
  return "fade";
72
130
  }, [variant]);
73
- return ((0, jsx_runtime_1.jsx)(modal_1.ModalPrimitive.Root, { ref: ref, open: open, onOpenChange: onOpenChange, presentationStyle: presentationStyle, animationType: animationType, ...props, children: (0, jsx_runtime_1.jsx)(modal_1.ModalPrimitive.Overlay, { dismissible: dismissible, onDismiss: handleClose, style: styles.overlay, children: (0, jsx_runtime_1.jsxs)(modal_1.ModalPrimitive.Content, { position: position || "left", size: size || "md", style: [
74
- styles.content,
75
- styles[`${variant}Content`],
76
- styles[`${size}Content`],
77
- ], children: [(title || showCloseButton) && ((0, jsx_runtime_1.jsxs)(modal_1.ModalPrimitive.Header, { withBorder: variant !== "sheet", style: styles.header, children: [(0, jsx_runtime_1.jsx)(exports.DialogTitle, { children: title }), showCloseButton && ((0, jsx_runtime_1.jsx)(modal_1.ModalPrimitive.Close, { onClose: handleClose, style: styles.closeButton, children: (0, jsx_runtime_1.jsx)(DialogCloseIcon, {}) }))] })), (0, jsx_runtime_1.jsxs)(modal_1.ModalPrimitive.Body, { scrollable: variant !== "fullscreen", style: styles.body, children: [description && ((0, jsx_runtime_1.jsx)(exports.DialogDescription, { children: description })), children] })] }) }) }));
131
+ return ((0, jsx_runtime_1.jsx)(modal_1.ModalPrimitive.Root, { ref: ref, open: open, onOpenChange: onOpenChange, presentationStyle: presentationStyle, animationType: animationType, ...props, children: (0, jsx_runtime_1.jsx)(modal_1.ModalPrimitive.Overlay, { dismissible: dismissible, onDismiss: handleClose, style: zt.bg.overlay, children: (0, jsx_runtime_1.jsxs)(modal_1.ModalPrimitive.Content, { position: position || "left", size: size || "md", style: contentStyles, children: [(title || showCloseButton) && ((0, jsx_runtime_1.jsxs)(modal_1.ModalPrimitive.Header, { withBorder: variant !== "sheet", style: [
132
+ zero.p[4],
133
+ {
134
+ flexDirection: "row",
135
+ alignItems: "center",
136
+ justifyContent: "space-between",
137
+ },
138
+ ], children: [(0, jsx_runtime_1.jsx)(exports.DialogTitle, { children: title }), showCloseButton && ((0, jsx_runtime_1.jsx)(modal_1.ModalPrimitive.Close, { onClose: handleClose, style: [
139
+ zero.p[2],
140
+ {
141
+ width: 44,
142
+ height: 44,
143
+ alignItems: "center",
144
+ justifyContent: "center",
145
+ },
146
+ ], children: (0, jsx_runtime_1.jsx)(DialogCloseIcon, {}) }))] })), (0, jsx_runtime_1.jsxs)(modal_1.ModalPrimitive.Body, { scrollable: variant !== "fullscreen", style: [zero.p[6], { paddingTop: 0, flex: 1 }], children: [description && ((0, jsx_runtime_1.jsx)(exports.DialogDescription, { children: description })), children] })] }) }) }));
78
147
  });
79
148
  exports.Dialog.displayName = "Dialog";
80
149
  exports.DialogTitle = (0, react_1.forwardRef)(({ children, style, ...props }, ref) => {
81
- const { theme } = (0, theme_1.useTheme)();
82
- const styles = react_1.default.useMemo(() => createStyles(theme), [theme]);
150
+ const { zero: zt } = (0, theme_1.useTheme)();
83
151
  if (!children)
84
152
  return null;
85
- return ((0, jsx_runtime_1.jsx)(react_native_1.Text, { ref: ref, style: [styles.title, style], ...props, children: children }));
153
+ return ((0, jsx_runtime_1.jsx)(react_native_1.Text, { ref: ref, style: [zt.text.xl, { fontWeight: "600", flex: 1 }, style], ...props, children: children }));
86
154
  });
87
155
  exports.DialogTitle.displayName = "DialogTitle";
88
156
  exports.DialogDescription = (0, react_1.forwardRef)(({ children, style, ...props }, ref) => {
89
- const { theme } = (0, theme_1.useTheme)();
90
- const styles = react_1.default.useMemo(() => createStyles(theme), [theme]);
157
+ const { zero: zt } = (0, theme_1.useTheme)();
91
158
  if (!children)
92
159
  return null;
93
- return ((0, jsx_runtime_1.jsx)(react_native_1.Text, { ref: ref, style: [styles.description, style], ...props, children: children }));
160
+ return ((0, jsx_runtime_1.jsx)(react_native_1.Text, { ref: ref, style: [zt.text.muted, zero.mb[4], style], ...props, children: children }));
94
161
  });
95
162
  exports.DialogDescription.displayName = "DialogDescription";
96
163
  exports.DialogFooter = (0, react_1.forwardRef)(({ children, direction = "row", justify = "flex-end", withBorder = true, style, ...props }, ref) => {
97
- const { theme } = (0, theme_1.useTheme)();
98
- const styles = react_1.default.useMemo(() => createStyles(theme), [theme]);
164
+ const { zero: zt } = (0, theme_1.useTheme)();
99
165
  if (!children)
100
166
  return null;
101
- return ((0, jsx_runtime_1.jsx)(modal_1.ModalPrimitive.Footer, { ref: ref, withBorder: withBorder, direction: direction, justify: justify, style: [styles.footer, style], ...props, children: children }));
167
+ return ((0, jsx_runtime_1.jsx)(modal_1.ModalPrimitive.Footer, { ref: ref, withBorder: withBorder, direction: direction, justify: justify, style: [zero.p[6], { gap: 8 }, style], ...props, children: children }));
102
168
  });
103
169
  exports.DialogFooter.displayName = "DialogFooter";
104
170
  // Dialog Close Icon component (Lucide X)
105
171
  const DialogCloseIcon = () => {
106
172
  return (0, jsx_runtime_1.jsx)(ThemedX, { size: "md", variant: "default" });
107
173
  };
108
- // Create theme-aware styles
109
- function createStyles(theme) {
110
- return react_native_1.StyleSheet.create({
111
- overlay: {
112
- backgroundColor: "rgba(0, 0, 0, 0.5)",
113
- },
114
- content: {
115
- backgroundColor: theme.colors.card,
116
- borderRadius: theme.borderRadius.lg,
117
- ...theme.shadows.lg,
118
- maxHeight: "90%",
119
- maxWidth: "90%",
120
- },
121
- // Variant styles
122
- defaultContent: {
123
- // Default styles already applied in content
124
- },
125
- sheetContent: {
126
- borderTopLeftRadius: theme.borderRadius.xl,
127
- borderTopRightRadius: theme.borderRadius.xl,
128
- borderBottomLeftRadius: 0,
129
- borderBottomRightRadius: 0,
130
- marginTop: "auto",
131
- marginBottom: 0,
132
- maxHeight: "80%",
133
- width: "100%",
134
- maxWidth: "100%",
135
- },
136
- fullscreenContent: {
137
- width: "100%",
138
- height: "100%",
139
- maxWidth: "100%",
140
- maxHeight: "100%",
141
- borderRadius: 0,
142
- margin: 0,
143
- },
144
- // Size styles
145
- smContent: {
146
- minWidth: 300,
147
- minHeight: 200,
148
- },
149
- mdContent: {
150
- minWidth: 400,
151
- minHeight: 300,
152
- },
153
- lgContent: {
154
- minWidth: 500,
155
- minHeight: 400,
156
- },
157
- xlContent: {
158
- minWidth: 600,
159
- minHeight: 500,
160
- },
161
- fullContent: {
162
- width: "95%",
163
- height: "95%",
164
- maxWidth: "95%",
165
- maxHeight: "95%",
166
- },
167
- header: {
168
- paddingHorizontal: theme.spacing[6],
169
- paddingVertical: theme.spacing[4],
170
- flexDirection: "row",
171
- alignItems: "center",
172
- justifyContent: "space-between",
173
- },
174
- body: {
175
- paddingHorizontal: theme.spacing[6],
176
- paddingBottom: theme.spacing[6],
177
- flex: 1,
178
- },
179
- footer: {
180
- paddingHorizontal: theme.spacing[6],
181
- paddingVertical: theme.spacing[4],
182
- gap: theme.spacing[2],
183
- },
184
- title: {
185
- fontSize: 20,
186
- fontWeight: "600",
187
- color: theme.colors.text,
188
- flex: 1,
189
- lineHeight: 24,
190
- },
191
- description: {
192
- fontSize: 16,
193
- color: theme.colors.textMuted,
194
- lineHeight: 22,
195
- marginBottom: theme.spacing[4],
196
- },
197
- closeButton: {
198
- width: theme.touchTargets.minimum,
199
- height: theme.touchTargets.minimum,
200
- alignItems: "center",
201
- justifyContent: "center",
202
- borderRadius: theme.borderRadius.sm,
203
- marginLeft: theme.spacing[2],
204
- },
205
- });
206
- }