@streamplace/components 0.0.1 → 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.
Files changed (169) hide show
  1. package/LICENSE +18 -0
  2. package/README.md +35 -0
  3. package/dist/components/chat/chat-box.js +109 -0
  4. package/dist/components/chat/chat-message.js +76 -0
  5. package/dist/components/chat/chat.js +56 -0
  6. package/dist/components/chat/mention-suggestions.js +39 -0
  7. package/dist/components/chat/mod-view.js +33 -0
  8. package/dist/components/mobile-player/fullscreen.js +69 -0
  9. package/dist/components/mobile-player/fullscreen.native.js +151 -0
  10. package/dist/components/mobile-player/player.js +103 -0
  11. package/dist/components/mobile-player/props.js +1 -0
  12. package/dist/components/mobile-player/shared.js +51 -0
  13. package/dist/components/mobile-player/ui/countdown.js +79 -0
  14. package/dist/components/mobile-player/ui/index.js +5 -0
  15. package/dist/components/mobile-player/ui/input.js +38 -0
  16. package/dist/components/mobile-player/ui/metrics.js +40 -0
  17. package/dist/components/mobile-player/ui/streamer-context-menu.js +4 -0
  18. package/dist/components/mobile-player/ui/viewer-context-menu.js +20 -0
  19. package/dist/components/mobile-player/use-webrtc.js +232 -0
  20. package/dist/components/mobile-player/video.js +375 -0
  21. package/dist/components/mobile-player/video.native.js +238 -0
  22. package/dist/components/mobile-player/webrtc-diagnostics.js +106 -0
  23. package/dist/components/mobile-player/webrtc-primitives.js +25 -0
  24. package/dist/components/mobile-player/webrtc-primitives.native.js +1 -0
  25. package/dist/components/ui/button.js +220 -0
  26. package/dist/components/ui/dialog.js +203 -0
  27. package/dist/components/ui/dropdown.js +148 -0
  28. package/dist/components/ui/icons.js +22 -0
  29. package/dist/components/ui/index.js +22 -0
  30. package/dist/components/ui/input.js +202 -0
  31. package/dist/components/ui/loader.js +7 -0
  32. package/dist/components/ui/primitives/button.js +121 -0
  33. package/dist/components/ui/primitives/input.js +202 -0
  34. package/dist/components/ui/primitives/modal.js +203 -0
  35. package/dist/components/ui/primitives/text.js +286 -0
  36. package/dist/components/ui/resizeable.js +101 -0
  37. package/dist/components/ui/text.js +175 -0
  38. package/dist/components/ui/textarea.js +17 -0
  39. package/dist/components/ui/toast.js +129 -0
  40. package/dist/components/ui/view.js +250 -0
  41. package/dist/hooks/index.js +9 -0
  42. package/dist/hooks/useAvatars.js +32 -0
  43. package/dist/hooks/useCameraToggle.js +9 -0
  44. package/dist/hooks/useKeyboard.js +33 -0
  45. package/dist/hooks/useKeyboardSlide.js +11 -0
  46. package/dist/hooks/useLivestreamInfo.js +62 -0
  47. package/dist/hooks/useOuterAndInnerDimensions.js +27 -0
  48. package/dist/hooks/usePlayerDimensions.js +19 -0
  49. package/dist/hooks/useSegmentTiming.js +62 -0
  50. package/dist/index.js +16 -0
  51. package/dist/lib/facet.js +88 -0
  52. package/dist/lib/theme/atoms.js +620 -0
  53. package/dist/lib/theme/atoms.types.js +5 -0
  54. package/dist/lib/theme/index.js +9 -0
  55. package/dist/lib/theme/theme.js +248 -0
  56. package/dist/lib/theme/tokens.js +383 -0
  57. package/dist/lib/utils.js +94 -0
  58. package/dist/livestream-provider/index.js +25 -0
  59. package/dist/livestream-provider/websocket.js +41 -0
  60. package/dist/livestream-store/chat.js +186 -0
  61. package/dist/livestream-store/context.js +2 -0
  62. package/dist/livestream-store/index.js +4 -0
  63. package/dist/livestream-store/livestream-state.js +1 -0
  64. package/dist/livestream-store/livestream-store.js +42 -0
  65. package/dist/livestream-store/stream-key.js +115 -0
  66. package/dist/livestream-store/websocket-consumer.js +55 -0
  67. package/dist/player-store/context.js +2 -0
  68. package/dist/player-store/index.js +6 -0
  69. package/dist/player-store/player-provider.js +52 -0
  70. package/dist/player-store/player-state.js +22 -0
  71. package/dist/player-store/player-store.js +159 -0
  72. package/dist/player-store/single-player-provider.js +109 -0
  73. package/dist/streamplace-provider/context.js +2 -0
  74. package/dist/streamplace-provider/index.js +16 -0
  75. package/dist/streamplace-provider/poller.js +46 -0
  76. package/dist/streamplace-provider/xrpc.js +0 -0
  77. package/dist/streamplace-store/block.js +23 -0
  78. package/dist/streamplace-store/index.js +3 -0
  79. package/dist/streamplace-store/stream.js +193 -0
  80. package/dist/streamplace-store/streamplace-store.js +37 -0
  81. package/dist/streamplace-store/user.js +47 -0
  82. package/dist/streamplace-store/xrpc.js +12 -0
  83. package/node-compile-cache/v22.15.0-x64-efe9a9df-0/37be0eec +0 -0
  84. package/node-compile-cache/v22.15.0-x64-efe9a9df-0/56540125 +0 -0
  85. package/node-compile-cache/v22.15.0-x64-efe9a9df-0/67b1eb60 +0 -0
  86. package/node-compile-cache/v22.15.0-x64-efe9a9df-0/7c275f90 +0 -0
  87. package/package.json +50 -8
  88. package/src/components/chat/chat-box.tsx +195 -0
  89. package/src/components/chat/chat-message.tsx +192 -0
  90. package/src/components/chat/chat.tsx +128 -0
  91. package/src/components/chat/mention-suggestions.tsx +71 -0
  92. package/src/components/chat/mod-view.tsx +118 -0
  93. package/src/components/mobile-player/fullscreen.native.tsx +193 -0
  94. package/src/components/mobile-player/fullscreen.tsx +79 -0
  95. package/src/components/mobile-player/player.tsx +134 -0
  96. package/src/components/mobile-player/props.tsx +11 -0
  97. package/src/components/mobile-player/shared.tsx +56 -0
  98. package/src/components/mobile-player/ui/countdown.tsx +119 -0
  99. package/src/components/mobile-player/ui/index.ts +5 -0
  100. package/src/components/mobile-player/ui/input.tsx +85 -0
  101. package/src/components/mobile-player/ui/metrics.tsx +69 -0
  102. package/src/components/mobile-player/ui/streamer-context-menu.tsx +3 -0
  103. package/src/components/mobile-player/ui/viewer-context-menu.tsx +70 -0
  104. package/src/components/mobile-player/use-webrtc.tsx +282 -0
  105. package/src/components/mobile-player/video.native.tsx +360 -0
  106. package/src/components/mobile-player/video.tsx +557 -0
  107. package/src/components/mobile-player/webrtc-diagnostics.tsx +149 -0
  108. package/src/components/mobile-player/webrtc-primitives.native.tsx +6 -0
  109. package/src/components/mobile-player/webrtc-primitives.tsx +33 -0
  110. package/src/components/ui/button.tsx +309 -0
  111. package/src/components/ui/dialog.tsx +376 -0
  112. package/src/components/ui/dropdown.tsx +399 -0
  113. package/src/components/ui/icons.tsx +50 -0
  114. package/src/components/ui/index.ts +33 -0
  115. package/src/components/ui/input.tsx +350 -0
  116. package/src/components/ui/loader.tsx +9 -0
  117. package/src/components/ui/primitives/button.tsx +292 -0
  118. package/src/components/ui/primitives/input.tsx +422 -0
  119. package/src/components/ui/primitives/modal.tsx +421 -0
  120. package/src/components/ui/primitives/text.tsx +499 -0
  121. package/src/components/ui/resizeable.tsx +169 -0
  122. package/src/components/ui/text.tsx +330 -0
  123. package/src/components/ui/textarea.tsx +34 -0
  124. package/src/components/ui/toast.tsx +203 -0
  125. package/src/components/ui/view.tsx +344 -0
  126. package/src/hooks/index.ts +9 -0
  127. package/src/hooks/useAvatars.tsx +44 -0
  128. package/src/hooks/useCameraToggle.ts +12 -0
  129. package/src/hooks/useKeyboard.tsx +41 -0
  130. package/src/hooks/useKeyboardSlide.ts +12 -0
  131. package/src/hooks/useLivestreamInfo.ts +67 -0
  132. package/src/hooks/useOuterAndInnerDimensions.tsx +32 -0
  133. package/src/hooks/usePlayerDimensions.ts +23 -0
  134. package/src/hooks/useSegmentTiming.tsx +88 -0
  135. package/src/index.tsx +27 -0
  136. package/src/lib/facet.ts +131 -0
  137. package/src/lib/theme/atoms.ts +760 -0
  138. package/src/lib/theme/atoms.types.ts +258 -0
  139. package/src/lib/theme/index.ts +48 -0
  140. package/src/lib/theme/theme.tsx +436 -0
  141. package/src/lib/theme/tokens.ts +409 -0
  142. package/src/lib/utils.ts +132 -0
  143. package/src/livestream-provider/index.tsx +48 -0
  144. package/src/livestream-provider/websocket.tsx +47 -0
  145. package/src/livestream-store/chat.tsx +261 -0
  146. package/src/livestream-store/context.tsx +10 -0
  147. package/src/livestream-store/index.tsx +4 -0
  148. package/src/livestream-store/livestream-state.tsx +21 -0
  149. package/src/livestream-store/livestream-store.tsx +59 -0
  150. package/src/livestream-store/stream-key.tsx +124 -0
  151. package/src/livestream-store/websocket-consumer.tsx +62 -0
  152. package/src/player-store/context.tsx +11 -0
  153. package/src/player-store/index.tsx +6 -0
  154. package/src/player-store/player-provider.tsx +89 -0
  155. package/src/player-store/player-state.tsx +187 -0
  156. package/src/player-store/player-store.tsx +239 -0
  157. package/src/player-store/single-player-provider.tsx +181 -0
  158. package/src/streamplace-provider/context.tsx +10 -0
  159. package/src/streamplace-provider/index.tsx +32 -0
  160. package/src/streamplace-provider/poller.tsx +55 -0
  161. package/src/streamplace-provider/xrpc.tsx +0 -0
  162. package/src/streamplace-store/block.tsx +29 -0
  163. package/src/streamplace-store/index.tsx +3 -0
  164. package/src/streamplace-store/stream.tsx +262 -0
  165. package/src/streamplace-store/streamplace-store.tsx +89 -0
  166. package/src/streamplace-store/user.tsx +57 -0
  167. package/src/streamplace-store/xrpc.tsx +15 -0
  168. package/tsconfig.json +9 -0
  169. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,202 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import React, { forwardRef } from "react";
3
+ import { Platform, StyleSheet, Text, TextInput, TouchableOpacity, View, } from "react-native";
4
+ // Input root primitive - the main TextInput component
5
+ export const InputRoot = forwardRef(({ value, onChangeText, onChange, onFocus, onBlur, error = false, disabled = false, loading = false, editable, style, placeholderTextColor = "#9ca3af", ...props }, ref) => {
6
+ const [isFocused, setIsFocused] = React.useState(false);
7
+ const handleChangeText = React.useCallback((text) => {
8
+ if (onChangeText) {
9
+ onChangeText(text);
10
+ }
11
+ if (onChange) {
12
+ onChange(text);
13
+ }
14
+ }, [onChangeText, onChange]);
15
+ const handleFocus = React.useCallback((event) => {
16
+ setIsFocused(true);
17
+ if (onFocus) {
18
+ onFocus(event);
19
+ }
20
+ }, [onFocus]);
21
+ const handleBlur = React.useCallback((event) => {
22
+ setIsFocused(false);
23
+ if (onBlur) {
24
+ onBlur(event);
25
+ }
26
+ }, [onBlur]);
27
+ return (_jsx(TextInput, { ref: ref, value: value, onChangeText: handleChangeText, onFocus: handleFocus, onBlur: handleBlur, editable: !disabled && !loading && editable, placeholderTextColor: placeholderTextColor, style: [
28
+ primitiveStyles.input,
29
+ style,
30
+ error && primitiveStyles.inputError,
31
+ disabled && primitiveStyles.inputDisabled,
32
+ loading && primitiveStyles.inputLoading,
33
+ ], ...props }));
34
+ });
35
+ InputRoot.displayName = "InputRoot";
36
+ export const InputContainer = forwardRef(({ children, focused = false, error = false, disabled = false, style, ...props }, ref) => {
37
+ return (_jsx(View, { ref: ref, style: [
38
+ primitiveStyles.container,
39
+ style,
40
+ focused && primitiveStyles.containerFocused,
41
+ error && primitiveStyles.containerError,
42
+ disabled && primitiveStyles.containerDisabled,
43
+ ], ...props, children: children }));
44
+ });
45
+ InputContainer.displayName = "InputContainer";
46
+ export const InputLabel = forwardRef(({ children, required = false, disabled = false, error = false, style, ...props }, ref) => {
47
+ return (_jsxs(Text, { ref: ref, style: [
48
+ primitiveStyles.label,
49
+ style,
50
+ error && primitiveStyles.labelError,
51
+ disabled && primitiveStyles.labelDisabled,
52
+ ], ...props, children: [children, required && _jsx(Text, { style: primitiveStyles.required, children: " *" })] }));
53
+ });
54
+ InputLabel.displayName = "InputLabel";
55
+ export const InputDescription = forwardRef(({ children, error = false, disabled = false, style, ...props }, ref) => {
56
+ return (_jsx(Text, { ref: ref, style: [
57
+ primitiveStyles.description,
58
+ style,
59
+ error && primitiveStyles.descriptionError,
60
+ disabled && primitiveStyles.descriptionDisabled,
61
+ ], ...props, children: children }));
62
+ });
63
+ InputDescription.displayName = "InputDescription";
64
+ export const InputError = forwardRef(({ children, visible = true, style, ...props }, ref) => {
65
+ if (!visible || !children)
66
+ return null;
67
+ return (_jsx(Text, { ref: ref, style: [primitiveStyles.error, style], ...props, children: children }));
68
+ });
69
+ InputError.displayName = "InputError";
70
+ export const InputAddon = forwardRef(({ children, position = "left", touchable = false, onPress, style, ...props }, ref) => {
71
+ const addonStyle = [
72
+ primitiveStyles.addon,
73
+ primitiveStyles[`addon${position.charAt(0).toUpperCase() + position.slice(1)}`],
74
+ style,
75
+ ];
76
+ if (touchable && onPress) {
77
+ return (_jsx(TouchableOpacity, { ref: ref, style: addonStyle, onPress: onPress, ...props, children: children }));
78
+ }
79
+ return (_jsx(View, { ref: ref, style: addonStyle, ...props, children: children }));
80
+ });
81
+ InputAddon.displayName = "InputAddon";
82
+ export const InputGroup = forwardRef(({ children, spacing = 8, style, ...props }, ref) => {
83
+ return (_jsx(View, { ref: ref, style: [primitiveStyles.group, { gap: spacing }, style], ...props, children: children }));
84
+ });
85
+ InputGroup.displayName = "InputGroup";
86
+ // Primitive styles (minimal, unstyled)
87
+ const primitiveStyles = StyleSheet.create({
88
+ input: {
89
+ minHeight: 44, // iOS minimum touch target
90
+ paddingHorizontal: 12,
91
+ paddingVertical: 8,
92
+ fontSize: 16,
93
+ borderWidth: 1,
94
+ borderColor: "#d1d5db",
95
+ borderRadius: 8,
96
+ backgroundColor: "white",
97
+ ...Platform.select({
98
+ ios: {
99
+ paddingVertical: 12,
100
+ },
101
+ android: {
102
+ paddingVertical: 8,
103
+ textAlignVertical: "center",
104
+ },
105
+ }),
106
+ },
107
+ inputFocused: {
108
+ // No focus styles for the actual input
109
+ },
110
+ inputError: {
111
+ borderColor: "#ef4444",
112
+ borderWidth: 1,
113
+ },
114
+ inputDisabled: {
115
+ backgroundColor: "#f3f4f6",
116
+ borderColor: "#e5e7eb",
117
+ opacity: 0.6,
118
+ },
119
+ inputLoading: {
120
+ opacity: 0.7,
121
+ },
122
+ container: {
123
+ flexDirection: "row",
124
+ alignItems: "center",
125
+ borderWidth: 1,
126
+ borderColor: "#d1d5db",
127
+ borderRadius: 8,
128
+ backgroundColor: "white",
129
+ paddingHorizontal: 12,
130
+ minHeight: 44,
131
+ },
132
+ containerFocused: {
133
+ borderColor: "#3b82f6",
134
+ borderWidth: 1,
135
+ },
136
+ containerError: {
137
+ borderColor: "#ef4444",
138
+ borderWidth: 1,
139
+ },
140
+ containerDisabled: {
141
+ backgroundColor: "#f3f4f6",
142
+ borderColor: "#e5e7eb",
143
+ opacity: 0.6,
144
+ },
145
+ label: {
146
+ fontSize: 14,
147
+ fontWeight: "500",
148
+ color: "#374151",
149
+ marginBottom: 4,
150
+ },
151
+ labelError: {
152
+ color: "#ef4444",
153
+ },
154
+ labelDisabled: {
155
+ color: "#9ca3af",
156
+ opacity: 0.6,
157
+ },
158
+ required: {
159
+ color: "#ef4444",
160
+ },
161
+ description: {
162
+ fontSize: 12,
163
+ color: "#6b7280",
164
+ marginTop: 4,
165
+ },
166
+ descriptionError: {
167
+ color: "#ef4444",
168
+ },
169
+ descriptionDisabled: {
170
+ color: "#9ca3af",
171
+ opacity: 0.6,
172
+ },
173
+ error: {
174
+ fontSize: 12,
175
+ color: "#ef4444",
176
+ marginTop: 4,
177
+ },
178
+ addon: {
179
+ alignItems: "center",
180
+ justifyContent: "center",
181
+ paddingHorizontal: 8,
182
+ },
183
+ addonLeft: {
184
+ marginRight: 8,
185
+ },
186
+ addonRight: {
187
+ marginLeft: 8,
188
+ },
189
+ group: {
190
+ flexDirection: "column",
191
+ },
192
+ });
193
+ // Export primitive collection
194
+ export const InputPrimitive = {
195
+ Root: InputRoot,
196
+ Container: InputContainer,
197
+ Label: InputLabel,
198
+ Description: InputDescription,
199
+ Error: InputError,
200
+ Addon: InputAddon,
201
+ Group: InputGroup,
202
+ };
@@ -0,0 +1,203 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import React, { forwardRef } from "react";
3
+ import { Dimensions, Modal, Platform, ScrollView, StyleSheet, TouchableOpacity, View, } from "react-native";
4
+ const { width: screenWidth, height: screenHeight } = Dimensions.get("window");
5
+ // Modal root primitive - handles the native Modal component
6
+ export const ModalRoot = forwardRef(({ open = false, onOpenChange, children, onRequestClose, animationType = "fade", presentationStyle = Platform.OS === "ios" ? "pageSheet" : "fullScreen", transparent = true, statusBarTranslucent = Platform.OS === "android", ...props }, ref) => {
7
+ const handleRequestClose = React.useCallback((e) => {
8
+ if (onOpenChange) {
9
+ onOpenChange(false);
10
+ }
11
+ if (onRequestClose) {
12
+ onRequestClose(e);
13
+ }
14
+ }, [onOpenChange, onRequestClose]);
15
+ return (_jsx(Modal, { visible: open, onRequestClose: handleRequestClose, animationType: animationType, presentationStyle: presentationStyle, transparent: transparent, statusBarTranslucent: statusBarTranslucent, ...props, children: _jsx(View, { ref: ref, style: primitiveStyles.container, children: children }) }));
16
+ });
17
+ ModalRoot.displayName = "ModalRoot";
18
+ export const ModalOverlay = forwardRef(({ dismissible = true, onDismiss, onPress, style, children, activeOpacity = 1, ...props }, ref) => {
19
+ const handlePress = React.useCallback((event) => {
20
+ if (dismissible && onDismiss) {
21
+ onDismiss();
22
+ }
23
+ if (onPress) {
24
+ onPress(event);
25
+ }
26
+ }, [dismissible, onDismiss, onPress]);
27
+ return (_jsx(TouchableOpacity, { ref: ref, style: [primitiveStyles.overlay, style], activeOpacity: activeOpacity, onPress: handlePress, ...props, children: children }));
28
+ });
29
+ ModalOverlay.displayName = "ModalOverlay";
30
+ export const ModalContent = forwardRef(({ children, position = "center", size = "md", style, onStartShouldSetResponder, ...props }, ref) => {
31
+ // Prevent touches from propagating to overlay
32
+ const handleStartShouldSetResponder = React.useCallback(() => {
33
+ return true;
34
+ }, []);
35
+ const positionStyle = React.useMemo(() => {
36
+ switch (position) {
37
+ case "top":
38
+ return primitiveStyles.contentTop;
39
+ case "bottom":
40
+ return primitiveStyles.contentBottom;
41
+ case "left":
42
+ return primitiveStyles.contentLeft;
43
+ case "right":
44
+ return primitiveStyles.contentRight;
45
+ case "center":
46
+ default:
47
+ return primitiveStyles.contentCenter;
48
+ }
49
+ }, [position]);
50
+ const sizeStyle = React.useMemo(() => {
51
+ switch (size) {
52
+ case "sm":
53
+ return primitiveStyles.sizeSm;
54
+ case "lg":
55
+ return primitiveStyles.sizeLg;
56
+ case "xl":
57
+ return primitiveStyles.sizeXl;
58
+ case "full":
59
+ return primitiveStyles.sizeFull;
60
+ case "md":
61
+ default:
62
+ return primitiveStyles.sizeMd;
63
+ }
64
+ }, [size]);
65
+ return (_jsx(View, { ref: ref, style: [primitiveStyles.content, positionStyle, sizeStyle, style], onStartShouldSetResponder: onStartShouldSetResponder || handleStartShouldSetResponder, ...props, children: children }));
66
+ });
67
+ ModalContent.displayName = "ModalContent";
68
+ export const ModalHeader = forwardRef(({ children, withBorder = false, style, ...props }, ref) => {
69
+ return (_jsx(View, { ref: ref, style: [
70
+ primitiveStyles.header,
71
+ withBorder && primitiveStyles.headerBorder,
72
+ style,
73
+ ], ...props, children: children }));
74
+ });
75
+ ModalHeader.displayName = "ModalHeader";
76
+ export const ModalBody = forwardRef(({ children, scrollable = true, style, ...props }, ref) => {
77
+ if (!scrollable) {
78
+ return _jsx(View, { style: [primitiveStyles.body, style], children: children });
79
+ }
80
+ return (_jsx(ScrollView, { ref: ref, style: [primitiveStyles.body, style], showsVerticalScrollIndicator: false, keyboardShouldPersistTaps: "handled", ...props, children: children }));
81
+ });
82
+ ModalBody.displayName = "ModalBody";
83
+ export const ModalFooter = forwardRef(({ children, withBorder = false, direction = "row", justify = "flex-end", style, ...props }, ref) => {
84
+ return (_jsx(View, { ref: ref, style: [
85
+ primitiveStyles.footer,
86
+ withBorder && primitiveStyles.footerBorder,
87
+ {
88
+ flexDirection: direction,
89
+ justifyContent: justify,
90
+ },
91
+ style,
92
+ ], ...props, children: children }));
93
+ });
94
+ ModalFooter.displayName = "ModalFooter";
95
+ export const ModalClose = forwardRef(({ children, onClose, onPress, ...props }, ref) => {
96
+ const handlePress = React.useCallback((event) => {
97
+ if (onClose) {
98
+ onClose();
99
+ }
100
+ if (onPress) {
101
+ onPress(event);
102
+ }
103
+ }, [onClose, onPress]);
104
+ return (_jsx(TouchableOpacity, { ref: ref, onPress: handlePress, ...props, children: children }));
105
+ });
106
+ ModalClose.displayName = "ModalClose";
107
+ // Primitive styles (minimal, unstyled)
108
+ const primitiveStyles = StyleSheet.create({
109
+ container: {
110
+ flex: 1,
111
+ },
112
+ overlay: {
113
+ flex: 1,
114
+ backgroundColor: "rgba(0, 0, 0, 0.5)",
115
+ justifyContent: "center",
116
+ alignItems: "center",
117
+ padding: 16,
118
+ },
119
+ content: {
120
+ backgroundColor: "white",
121
+ borderRadius: 8,
122
+ overflow: "hidden",
123
+ },
124
+ contentCenter: {
125
+ alignSelf: "center",
126
+ },
127
+ contentTop: {
128
+ alignSelf: "center",
129
+ marginTop: 0,
130
+ },
131
+ contentBottom: {
132
+ alignSelf: "center",
133
+ marginTop: "auto",
134
+ },
135
+ contentLeft: {
136
+ alignSelf: "flex-start",
137
+ marginRight: "auto",
138
+ },
139
+ contentRight: {
140
+ alignSelf: "flex-end",
141
+ marginLeft: "auto",
142
+ },
143
+ sizeSm: {
144
+ maxWidth: screenWidth * 0.4,
145
+ maxHeight: screenHeight * 0.6,
146
+ },
147
+ sizeMd: {
148
+ maxWidth: screenWidth * 0.6,
149
+ maxHeight: screenHeight * 0.8,
150
+ },
151
+ sizeLg: {
152
+ maxWidth: screenWidth * 0.8,
153
+ maxHeight: screenHeight * 0.9,
154
+ },
155
+ sizeXl: {
156
+ maxWidth: screenWidth * 0.95,
157
+ maxHeight: screenHeight * 0.95,
158
+ },
159
+ sizeFull: {
160
+ width: screenWidth,
161
+ height: screenHeight,
162
+ maxWidth: screenWidth,
163
+ maxHeight: screenHeight,
164
+ borderRadius: 0,
165
+ },
166
+ header: {
167
+ paddingHorizontal: 16,
168
+ paddingVertical: 12,
169
+ flexDirection: "row",
170
+ alignItems: "center",
171
+ justifyContent: "space-between",
172
+ },
173
+ headerBorder: {
174
+ borderBottomWidth: 1,
175
+ borderBottomColor: "#e5e7eb",
176
+ },
177
+ body: {
178
+ flex: 1,
179
+ paddingHorizontal: 16,
180
+ paddingVertical: 12,
181
+ },
182
+ footer: {
183
+ paddingHorizontal: 16,
184
+ paddingVertical: 12,
185
+ flexDirection: "row",
186
+ alignItems: "center",
187
+ gap: 8,
188
+ },
189
+ footerBorder: {
190
+ borderTopWidth: 1,
191
+ borderTopColor: "#e5e7eb",
192
+ },
193
+ });
194
+ // Export primitive collection
195
+ export const ModalPrimitive = {
196
+ Root: ModalRoot,
197
+ Overlay: ModalOverlay,
198
+ Content: ModalContent,
199
+ Header: ModalHeader,
200
+ Body: ModalBody,
201
+ Footer: ModalFooter,
202
+ Close: ModalClose,
203
+ };
@@ -0,0 +1,286 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { createContext, forwardRef, useContext } from "react";
3
+ import { Platform, Text as RNText, } from "react-native";
4
+ import { useTheme } from "../../../lib/theme/theme";
5
+ import { typography } from "../../../lib/theme/tokens";
6
+ export const TextContext = createContext(null);
7
+ export function objectFromObjects(arr) {
8
+ return Object.assign({}, ...arr);
9
+ }
10
+ // Size mapping
11
+ const sizeMap = {
12
+ xs: 12,
13
+ sm: 14,
14
+ base: 16,
15
+ lg: 18,
16
+ xl: 20,
17
+ "2xl": 24,
18
+ "3xl": 30,
19
+ "4xl": 36,
20
+ };
21
+ // Weight mapping
22
+ const weightMap = {
23
+ thin: "100",
24
+ light: "300",
25
+ normal: "400",
26
+ medium: "500",
27
+ semibold: "600",
28
+ bold: "700",
29
+ extrabold: "800",
30
+ black: "900",
31
+ };
32
+ // Line height mapping
33
+ const leadingMap = {
34
+ none: 1,
35
+ tight: 1.2,
36
+ snug: 1.3,
37
+ normal: 1.5,
38
+ relaxed: 1.7,
39
+ loose: 2,
40
+ };
41
+ // Letter spacing mapping
42
+ const trackingMap = {
43
+ tighter: -0.8,
44
+ tight: -0.4,
45
+ normal: 0,
46
+ wide: 0.4,
47
+ wider: 0.8,
48
+ widest: 1.6,
49
+ };
50
+ // Variant definitions (platform-aware)
51
+ const getVariantStyles = () => {
52
+ // get platform-specific typography
53
+ // iOS, Android, Web (Universal)
54
+ const typographicPlatform = (Platform.OS === "ios"
55
+ ? "ios"
56
+ : Platform.OS === "android"
57
+ ? "android"
58
+ : "universal");
59
+ const platformTypography = typography[typographicPlatform];
60
+ if (!platformTypography) {
61
+ throw new Error("Platform typography not defined");
62
+ }
63
+ // Define mapping based on platform
64
+ if (typographicPlatform === "ios") {
65
+ return {
66
+ h1: platformTypography.largeTitle,
67
+ h2: platformTypography.title1,
68
+ h3: platformTypography.title2,
69
+ h4: platformTypography.title3,
70
+ h5: platformTypography.headline,
71
+ h6: platformTypography.headline,
72
+ subtitle1: platformTypography.subhead,
73
+ subtitle2: platformTypography.footnote,
74
+ body1: platformTypography.body,
75
+ body2: platformTypography.callout,
76
+ caption: platformTypography.caption1,
77
+ overline: platformTypography.caption2,
78
+ };
79
+ }
80
+ else if (typographicPlatform === "android") {
81
+ return {
82
+ h1: platformTypography.headline1,
83
+ h2: platformTypography.headline2,
84
+ h3: platformTypography.headline3,
85
+ h4: platformTypography.headline4,
86
+ h5: platformTypography.headline5,
87
+ h6: platformTypography.headline6,
88
+ subtitle1: platformTypography.subtitle1,
89
+ subtitle2: platformTypography.subtitle2,
90
+ body1: platformTypography.body1,
91
+ body2: platformTypography.body2,
92
+ caption: platformTypography.caption,
93
+ overline: platformTypography.overline,
94
+ };
95
+ }
96
+ else {
97
+ // universal
98
+ // Map variants to universal sizes
99
+ return {
100
+ h1: platformTypography["4xl"],
101
+ h2: platformTypography["3xl"],
102
+ h3: platformTypography["2xl"],
103
+ h4: platformTypography["xl"],
104
+ h5: platformTypography["lg"],
105
+ h6: platformTypography["base"],
106
+ subtitle1: platformTypography.base,
107
+ subtitle2: platformTypography.sm,
108
+ body1: platformTypography.base,
109
+ body2: platformTypography.sm,
110
+ caption: platformTypography.xs,
111
+ overline: platformTypography.xs,
112
+ };
113
+ }
114
+ };
115
+ // Text root primitive
116
+ export const TextRoot = forwardRef(({ variant, size, weight, color, align, leading, tracking, transform, decoration, italic = false, opacity, style, inherit = true, reset = false, children, ...props }, ref) => {
117
+ const { theme } = useTheme();
118
+ const parentContext = useContext(TextContext);
119
+ // Get variant styles
120
+ const variantStyles = getVariantStyles();
121
+ // Calculate inherited values
122
+ const inheritedContext = inherit && !reset && parentContext ? parentContext : {};
123
+ // Calculate final styles
124
+ const finalStyles = {
125
+ // Start with inherited values
126
+ fontSize: inheritedContext.fontSize,
127
+ fontWeight: inheritedContext.fontWeight,
128
+ //color: inheritedContext.color,
129
+ fontFamily: inheritedContext.fontFamily,
130
+ lineHeight: inheritedContext.lineHeight,
131
+ textAlign: inheritedContext.textAlign,
132
+ letterSpacing: inheritedContext.letterSpacing,
133
+ textTransform: inheritedContext.textTransform,
134
+ textDecorationLine: inheritedContext.textDecorationLine,
135
+ fontStyle: inheritedContext.fontStyle,
136
+ opacity: inheritedContext.opacity,
137
+ // Apply variant styles (these may override inherited)
138
+ ...(variant && variantStyles[variant]),
139
+ // Apply explicit prop styles (these should override inherited and variant)
140
+ // Apply size
141
+ ...(size && {
142
+ fontSize: typeof size === "number" ? size : sizeMap[size],
143
+ }),
144
+ // Apply weight
145
+ ...(weight && {
146
+ fontWeight: weightMap[weight],
147
+ }),
148
+ // Apply color
149
+ ...(color
150
+ ? {
151
+ color: color === "default"
152
+ ? theme.colors.text
153
+ : color === "muted"
154
+ ? theme.colors.textMuted
155
+ : color === "primary"
156
+ ? theme.colors.primary
157
+ : color === "secondary"
158
+ ? theme.colors.secondary
159
+ : color === "destructive"
160
+ ? theme.colors.destructive
161
+ : color === "success"
162
+ ? theme.colors.success
163
+ : color === "warning"
164
+ ? theme.colors.warning
165
+ : color || inheritedContext.color, // Custom color string
166
+ }
167
+ : { color: inheritedContext.color || theme.colors.text }),
168
+ // Apply alignment
169
+ ...(align && {
170
+ textAlign: align,
171
+ }),
172
+ // Apply line height
173
+ ...(leading && {
174
+ lineHeight: typeof leading === "number" ? leading : leadingMap[leading],
175
+ }),
176
+ // Apply letter spacing
177
+ ...(tracking && {
178
+ letterSpacing: typeof tracking === "number" ? tracking : trackingMap[tracking],
179
+ }),
180
+ // Apply text transform
181
+ ...(transform &&
182
+ transform !== "none" && {
183
+ textTransform: transform,
184
+ }),
185
+ // Apply text decoration
186
+ ...(decoration &&
187
+ decoration !== "none" && {
188
+ textDecorationLine: decoration,
189
+ }),
190
+ // Apply italic
191
+ ...(italic && {
192
+ fontStyle: "italic",
193
+ }),
194
+ // Apply opacity
195
+ ...(opacity !== undefined && {
196
+ opacity,
197
+ }),
198
+ };
199
+ finalStyles.color = finalStyles.color;
200
+ // Create context value for children
201
+ const contextValue = {
202
+ fontSize: typeof finalStyles.fontSize === "number"
203
+ ? finalStyles.fontSize
204
+ : undefined,
205
+ fontWeight: finalStyles.fontWeight,
206
+ color: finalStyles.color || undefined,
207
+ fontFamily: typeof finalStyles.fontFamily === "string"
208
+ ? finalStyles.fontFamily
209
+ : undefined,
210
+ lineHeight: typeof finalStyles.lineHeight === "number"
211
+ ? finalStyles.lineHeight
212
+ : undefined,
213
+ textAlign: finalStyles.textAlign,
214
+ letterSpacing: finalStyles.letterSpacing,
215
+ textTransform: finalStyles.textTransform,
216
+ textDecorationLine: finalStyles.textDecorationLine,
217
+ fontStyle: finalStyles.fontStyle,
218
+ opacity: finalStyles.opacity,
219
+ };
220
+ return (_jsx(TextContext.Provider, { value: contextValue, children: _jsx(RNText, { ref: ref, style: [finalStyles, style], ...props, children: children }) }));
221
+ });
222
+ TextRoot.displayName = "TextRoot";
223
+ // Text span primitive (inherits from parent but doesn't create new context)
224
+ export const TextSpan = forwardRef(({ children, ...props }, ref) => {
225
+ return (_jsx(TextRoot, { ref: ref, inherit: true, ...props, children: children }));
226
+ });
227
+ TextSpan.displayName = "TextSpan";
228
+ // Text block primitive (always creates new context)
229
+ export const TextBlock = forwardRef(({ children, reset = true, ...props }, ref) => {
230
+ return (_jsx(TextRoot, { ref: ref, reset: reset, ...props, children: children }));
231
+ });
232
+ TextBlock.displayName = "TextBlock";
233
+ // Hook to access current text context
234
+ export function useTextContext() {
235
+ return useContext(TextContext);
236
+ }
237
+ // Utility function to create text styles
238
+ export function createTextStyle(props) {
239
+ // This is a utility function that can be used to generate styles
240
+ // without rendering a component
241
+ const style = {};
242
+ if (props.size) {
243
+ style.fontSize =
244
+ typeof props.size === "number" ? props.size : sizeMap[props.size];
245
+ }
246
+ if (props.weight) {
247
+ style.fontWeight = weightMap[props.weight];
248
+ }
249
+ if (props.align) {
250
+ style.textAlign = props.align;
251
+ }
252
+ if (props.leading) {
253
+ style.lineHeight =
254
+ typeof props.leading === "number"
255
+ ? props.leading
256
+ : leadingMap[props.leading];
257
+ }
258
+ if (props.tracking) {
259
+ style.letterSpacing =
260
+ typeof props.tracking === "number"
261
+ ? props.tracking
262
+ : trackingMap[props.tracking];
263
+ }
264
+ if (props.transform && props.transform !== "none") {
265
+ style.textTransform = props.transform;
266
+ }
267
+ if (props.decoration && props.decoration !== "none") {
268
+ style.textDecorationLine = props.decoration;
269
+ }
270
+ if (props.italic) {
271
+ style.fontStyle = "italic";
272
+ }
273
+ if (props.opacity !== undefined) {
274
+ style.opacity = props.opacity;
275
+ }
276
+ return style;
277
+ }
278
+ // Export primitive collection
279
+ export const TextPrimitive = {
280
+ Root: TextRoot,
281
+ Span: TextSpan,
282
+ Block: TextBlock,
283
+ Context: TextContext,
284
+ useContext: useTextContext,
285
+ createStyle: createTextStyle,
286
+ };