@streamplace/components 0.7.35 → 0.8.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 (45) hide show
  1. package/dist/components/content-metadata/content-metadata-form.js +404 -0
  2. package/dist/components/content-metadata/content-rights.js +78 -0
  3. package/dist/components/content-metadata/content-warnings.js +68 -0
  4. package/dist/components/content-metadata/index.js +11 -0
  5. package/dist/components/mobile-player/player.js +4 -0
  6. package/dist/components/mobile-player/ui/report-modal.js +3 -2
  7. package/dist/components/ui/checkbox.js +87 -0
  8. package/dist/components/ui/dialog.js +188 -83
  9. package/dist/components/ui/primitives/input.js +13 -1
  10. package/dist/components/ui/primitives/modal.js +2 -2
  11. package/dist/components/ui/select.js +89 -0
  12. package/dist/components/ui/textarea.js +23 -4
  13. package/dist/components/ui/toast.js +464 -114
  14. package/dist/components/ui/tooltip.js +103 -0
  15. package/dist/index.js +2 -0
  16. package/dist/lib/metadata-constants.js +157 -0
  17. package/dist/lib/theme/theme.js +5 -3
  18. package/dist/streamplace-provider/index.js +14 -4
  19. package/dist/streamplace-store/content-metadata-actions.js +118 -0
  20. package/dist/streamplace-store/streamplace-store.js +18 -5
  21. package/dist/streamplace-store/user.js +67 -7
  22. package/node-compile-cache/v22.15.0-x64-efe9a9df-0/37be0eec +0 -0
  23. package/package.json +3 -3
  24. package/src/components/content-metadata/content-metadata-form.tsx +761 -0
  25. package/src/components/content-metadata/content-rights.tsx +104 -0
  26. package/src/components/content-metadata/content-warnings.tsx +100 -0
  27. package/src/components/content-metadata/index.tsx +18 -0
  28. package/src/components/mobile-player/player.tsx +5 -0
  29. package/src/components/mobile-player/ui/report-modal.tsx +13 -7
  30. package/src/components/ui/checkbox.tsx +147 -0
  31. package/src/components/ui/dialog.tsx +319 -99
  32. package/src/components/ui/primitives/input.tsx +19 -2
  33. package/src/components/ui/primitives/modal.tsx +4 -2
  34. package/src/components/ui/select.tsx +175 -0
  35. package/src/components/ui/textarea.tsx +47 -29
  36. package/src/components/ui/toast.tsx +785 -179
  37. package/src/components/ui/tooltip.tsx +131 -0
  38. package/src/index.tsx +3 -0
  39. package/src/lib/metadata-constants.ts +180 -0
  40. package/src/lib/theme/theme.tsx +10 -6
  41. package/src/streamplace-provider/index.tsx +20 -2
  42. package/src/streamplace-store/content-metadata-actions.tsx +142 -0
  43. package/src/streamplace-store/streamplace-store.tsx +30 -4
  44. package/src/streamplace-store/user.tsx +71 -7
  45. package/tsconfig.tsbuildinfo +1 -1
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Checkbox = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const lucide_react_native_1 = require("lucide-react-native");
6
+ const react_1 = require("react");
7
+ const react_native_1 = require("react-native");
8
+ const theme_1 = require("../../lib/theme/theme");
9
+ const text_1 = require("./text");
10
+ exports.Checkbox = (0, react_1.forwardRef)(({ checked, onCheckedChange, disabled = false, size = "md", label, description, style, ...props }, ref) => {
11
+ const { theme } = (0, theme_1.useTheme)();
12
+ const handlePress = () => {
13
+ if (!disabled) {
14
+ onCheckedChange(!checked);
15
+ }
16
+ };
17
+ const styles = createStyles(theme, size, disabled, checked);
18
+ return ((0, jsx_runtime_1.jsxs)(react_native_1.TouchableOpacity, { ref: ref, style: [styles.container, style], onPress: handlePress, disabled: disabled, ...props, children: [(0, jsx_runtime_1.jsx)(react_native_1.View, { style: styles.checkbox, children: checked && ((0, jsx_runtime_1.jsx)(lucide_react_native_1.Check, { size: size === "sm" ? 12 : size === "lg" ? 18 : 14, color: disabled
19
+ ? theme.colors.textDisabled
20
+ : theme.colors.primaryForeground })) }), (label || description) && ((0, jsx_runtime_1.jsxs)(react_native_1.View, { style: styles.content, children: [label && (0, jsx_runtime_1.jsx)(text_1.Text, { style: styles.label, children: label }), description && ((0, jsx_runtime_1.jsx)(text_1.Text, { style: styles.description, children: description }))] }))] }));
21
+ });
22
+ exports.Checkbox.displayName = "Checkbox";
23
+ function createStyles(theme, size, disabled, checked) {
24
+ const sizeStyles = {
25
+ sm: {
26
+ checkboxSize: 16,
27
+ borderRadius: 2,
28
+ padding: theme.spacing[1],
29
+ gap: theme.spacing[1],
30
+ },
31
+ md: {
32
+ checkboxSize: 20,
33
+ borderRadius: 4,
34
+ padding: theme.spacing[1],
35
+ gap: theme.spacing[2],
36
+ },
37
+ lg: {
38
+ checkboxSize: 24,
39
+ borderRadius: 6,
40
+ padding: theme.spacing[2],
41
+ gap: theme.spacing[3],
42
+ },
43
+ };
44
+ const currentSize = sizeStyles[size];
45
+ return react_native_1.StyleSheet.create({
46
+ container: {
47
+ flexDirection: "row",
48
+ alignItems: "flex-start",
49
+ opacity: disabled ? 0.5 : 1,
50
+ },
51
+ checkbox: {
52
+ width: currentSize.checkboxSize,
53
+ height: currentSize.checkboxSize,
54
+ borderWidth: 1.5,
55
+ borderColor: disabled
56
+ ? theme.colors.border
57
+ : checked
58
+ ? theme.colors.primary
59
+ : theme.colors.border,
60
+ borderRadius: currentSize.borderRadius,
61
+ backgroundColor: disabled
62
+ ? theme.colors.muted
63
+ : checked
64
+ ? theme.colors.primary
65
+ : "transparent",
66
+ alignItems: "center",
67
+ justifyContent: "center",
68
+ },
69
+ content: {
70
+ flex: 1,
71
+ paddingTop: currentSize.padding * 0.5,
72
+ paddingLeft: theme.spacing[2],
73
+ },
74
+ label: {
75
+ fontSize: size === "sm" ? 14 : size === "lg" ? 18 : 16,
76
+ fontWeight: "500",
77
+ color: disabled ? theme.colors.textDisabled : theme.colors.text,
78
+ lineHeight: size === "sm" ? 18 : size === "lg" ? 22 : 20,
79
+ },
80
+ description: {
81
+ fontSize: size === "sm" ? 12 : size === "lg" ? 16 : 14,
82
+ color: disabled ? theme.colors.textDisabled : theme.colors.textMuted,
83
+ marginTop: theme.spacing[1],
84
+ lineHeight: size === "sm" ? 16 : size === "lg" ? 20 : 18,
85
+ },
86
+ });
87
+ }
@@ -1,16 +1,20 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.dialogVariants = exports.DialogFooter = exports.DialogDescription = exports.DialogTitle = exports.Dialog = void 0;
3
+ exports.dialogVariants = exports.DialogFooter = exports.DialogDescription = exports.DialogTitle = exports.ResponsiveDialog = exports.Dialog = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const jsx_runtime_1 = require("react/jsx-runtime");
6
+ const bottom_sheet_1 = tslib_1.__importStar(require("@gorhom/bottom-sheet"));
7
+ // to get the portal
8
+ const Portal = tslib_1.__importStar(require("@rn-primitives/portal"));
6
9
  const class_variance_authority_1 = require("class-variance-authority");
7
10
  const lucide_react_native_1 = require("lucide-react-native");
8
11
  const react_1 = tslib_1.__importStar(require("react"));
9
12
  const react_native_1 = require("react-native");
13
+ const react_native_safe_area_context_1 = require("react-native-safe-area-context");
10
14
  const theme_1 = require("../../lib/theme/theme");
11
- const zero = tslib_1.__importStar(require("../../ui"));
12
15
  const icons_1 = require("./icons");
13
16
  const modal_1 = require("./primitives/modal");
17
+ const text_1 = require("./text");
14
18
  const ThemedX = (0, icons_1.createThemedIcon)(lucide_react_native_1.X);
15
19
  // Dialog variants using class-variance-authority pattern
16
20
  const dialogVariants = (0, class_variance_authority_1.cva)("", {
@@ -42,67 +46,59 @@ const dialogVariants = (0, class_variance_authority_1.cva)("", {
42
46
  },
43
47
  });
44
48
  exports.dialogVariants = dialogVariants;
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) => {
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%",
49
+ // Bottom Sheet Dialog Component
50
+ const DialogBottomSheet = (0, react_1.forwardRef)(function DialogBottomSheet({ overlayStyle, portalHost, children, title, description, showCloseButton = true, onClose, open = false, onOpenChange, ...props }, _ref) {
51
+ const { theme } = (0, theme_1.useTheme)();
52
+ const sheetRef = (0, react_1.useRef)(null);
53
+ const { top } = (0, react_native_safe_area_context_1.useSafeAreaInsets)();
54
+ const dims = (0, react_native_1.useWindowDimensions)();
55
+ const handleClose = react_1.default.useCallback(() => {
56
+ if (onClose) {
57
+ onClose();
58
+ }
59
+ if (onOpenChange) {
60
+ onOpenChange(false);
61
+ }
62
+ }, [onClose, onOpenChange]);
63
+ if (!open) {
64
+ return null;
65
+ }
66
+ return ((0, jsx_runtime_1.jsx)(Portal.Portal, { name: "dialog", children: (0, jsx_runtime_1.jsx)(bottom_sheet_1.default, { ref: sheetRef, index: open ? 0 : -1, enablePanDownToClose: true, enableDynamicSizing: true, maxDynamicContentSize: dims.height - top, keyboardBehavior: "interactive", keyboardBlurBehavior: "restore", enableContentPanningGesture: false, backdropComponent: ({ style }) => ((0, jsx_runtime_1.jsx)(react_native_1.Pressable, { style: [style, react_native_1.StyleSheet.absoluteFill], onPress: handleClose })), onClose: handleClose, style: [overlayStyle], backgroundStyle: {
67
+ backgroundColor: theme.colors.card,
68
+ borderRadius: theme.borderRadius.lg,
69
+ ...theme.shadows.lg,
70
+ }, handleIndicatorStyle: {
71
+ width: 48,
72
+ height: 4,
73
+ backgroundColor: theme.colors.textMuted,
74
+ }, children: (0, jsx_runtime_1.jsxs)(bottom_sheet_1.BottomSheetScrollView, { style: {
75
+ flex: 1,
76
+ width: "100%",
77
+ }, contentContainerStyle: { flexGrow: 1 }, children: [(title || showCloseButton) && ((0, jsx_runtime_1.jsxs)(react_native_1.View, { style: {
78
+ paddingHorizontal: theme.spacing[4],
79
+ paddingVertical: theme.spacing[4],
80
+ flexDirection: "row",
81
+ alignItems: "center",
82
+ justifyContent: "space-between",
66
83
  width: "100%",
67
- maxWidth: "100%",
68
- },
69
- ];
70
- case "fullscreen":
71
- return [
72
- {
84
+ }, children: [title && (0, jsx_runtime_1.jsx)(exports.DialogTitle, { children: title }), showCloseButton && ((0, jsx_runtime_1.jsx)(react_native_1.Pressable, { onPress: handleClose, style: {
85
+ width: theme.touchTargets.minimum,
86
+ height: theme.touchTargets.minimum,
87
+ alignItems: "center",
88
+ justifyContent: "center",
89
+ borderRadius: theme.borderRadius.sm,
90
+ marginLeft: theme.spacing[2],
91
+ }, children: (0, jsx_runtime_1.jsx)(DialogCloseIcon, {}) }))] })), (0, jsx_runtime_1.jsxs)(react_native_1.View, { style: {
92
+ paddingHorizontal: theme.spacing[4],
93
+ paddingBottom: theme.spacing[6],
94
+ flex: 1,
73
95
  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]);
96
+ }, children: [description && ((0, jsx_runtime_1.jsx)(exports.DialogDescription, { children: description })), children] })] }) }) }));
97
+ });
98
+ exports.Dialog = (0, react_1.forwardRef)(({ variant = "default", size = "md", position = "center", children, title, description, dismissible = true, showCloseButton = true, onClose, open = false, onOpenChange, ...props }, ref) => {
99
+ const { theme } = (0, theme_1.useTheme)();
100
+ // Create dynamic styles based on theme
101
+ const styles = react_1.default.useMemo(() => createStyles(theme), [theme]);
106
102
  const handleClose = react_1.default.useCallback(() => {
107
103
  if (onClose) {
108
104
  onClose();
@@ -128,46 +124,155 @@ exports.Dialog = (0, react_1.forwardRef)(({ variant = "left", size = "md", posit
128
124
  }
129
125
  return "fade";
130
126
  }, [variant]);
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] })] }) }) }));
127
+ 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 || "center", size: size || "md", style: [
128
+ styles.content,
129
+ variant === "sheet" && styles.sheetContent,
130
+ variant === "fullscreen" && styles.fullscreenContent,
131
+ size === "sm" && styles.smContent,
132
+ size === "md" && styles.mdContent,
133
+ size === "lg" && styles.lgContent,
134
+ size === "xl" && styles.xlContent,
135
+ size === "full" && styles.fullContent,
136
+ ], 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] })] }) }) }));
147
137
  });
148
138
  exports.Dialog.displayName = "Dialog";
139
+ /// Responsive Dialog Component. On mobile this will render a *bottom sheet*.
140
+ /// Prefer this over the regular Dialog component for better mobile UX.
141
+ exports.ResponsiveDialog = (0, react_1.forwardRef)(({ children, size, ...props }, ref) => {
142
+ const { width } = (0, react_native_1.useWindowDimensions)();
143
+ // On web, you might want to always use the normal dialog
144
+ // On mobile (width < 800), use the bottom sheet
145
+ const isBottomSheet = react_native_1.Platform.OS !== "web" && width < 800;
146
+ if (isBottomSheet) {
147
+ return ((0, jsx_runtime_1.jsx)(DialogBottomSheet, { ref: ref, ...props, size: "full", showCloseButton: false, variant: "fullscreen", children: children }));
148
+ }
149
+ // Use larger default size for regular dialogs to give more room
150
+ const dialogSize = size || "lg";
151
+ return ((0, jsx_runtime_1.jsx)(exports.Dialog, { ref: ref, size: dialogSize, ...props, children: children }));
152
+ });
153
+ exports.ResponsiveDialog.displayName = "ResponsiveDialog";
149
154
  exports.DialogTitle = (0, react_1.forwardRef)(({ children, style, ...props }, ref) => {
150
- const { zero: zt } = (0, theme_1.useTheme)();
155
+ const { theme } = (0, theme_1.useTheme)();
156
+ const styles = react_1.default.useMemo(() => createStyles(theme), [theme]);
151
157
  if (!children)
152
158
  return null;
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 }));
159
+ return ((0, jsx_runtime_1.jsx)(text_1.Text, { ref: ref, style: [styles.title, style], ...props, children: children }));
154
160
  });
155
161
  exports.DialogTitle.displayName = "DialogTitle";
156
162
  exports.DialogDescription = (0, react_1.forwardRef)(({ children, style, ...props }, ref) => {
157
- const { zero: zt } = (0, theme_1.useTheme)();
163
+ const { theme } = (0, theme_1.useTheme)();
164
+ const styles = react_1.default.useMemo(() => createStyles(theme), [theme]);
158
165
  if (!children)
159
166
  return null;
160
- return ((0, jsx_runtime_1.jsx)(react_native_1.Text, { ref: ref, style: [zt.text.muted, zero.mb[4], style], ...props, children: children }));
167
+ return ((0, jsx_runtime_1.jsx)(text_1.Text, { ref: ref, style: [styles.description, style], ...props, children: children }));
161
168
  });
162
169
  exports.DialogDescription.displayName = "DialogDescription";
163
170
  exports.DialogFooter = (0, react_1.forwardRef)(({ children, direction = "row", justify = "flex-end", withBorder = true, style, ...props }, ref) => {
164
- const { zero: zt } = (0, theme_1.useTheme)();
171
+ const { theme } = (0, theme_1.useTheme)();
172
+ const styles = react_1.default.useMemo(() => createStyles(theme), [theme]);
165
173
  if (!children)
166
174
  return null;
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 }));
175
+ 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 }));
168
176
  });
169
177
  exports.DialogFooter.displayName = "DialogFooter";
170
178
  // Dialog Close Icon component (Lucide X)
171
179
  const DialogCloseIcon = () => {
172
180
  return (0, jsx_runtime_1.jsx)(ThemedX, { size: "md", variant: "default" });
173
181
  };
182
+ // Create theme-aware styles
183
+ function createStyles(theme) {
184
+ return react_native_1.StyleSheet.create({
185
+ overlay: {
186
+ backgroundColor: "rgba(0, 0, 0, 0.5)",
187
+ },
188
+ content: {
189
+ backgroundColor: theme.colors.card,
190
+ borderRadius: theme.borderRadius.lg,
191
+ ...theme.shadows.lg,
192
+ maxHeight: "90%",
193
+ maxWidth: "90%",
194
+ },
195
+ // Variant styles
196
+ sheetContent: {
197
+ borderTopLeftRadius: theme.borderRadius.xl,
198
+ borderTopRightRadius: theme.borderRadius.xl,
199
+ borderBottomLeftRadius: 0,
200
+ borderBottomRightRadius: 0,
201
+ marginTop: "auto",
202
+ marginBottom: 0,
203
+ maxHeight: "80%",
204
+ width: "100%",
205
+ maxWidth: "100%",
206
+ },
207
+ fullscreenContent: {
208
+ width: "100%",
209
+ height: "100%",
210
+ maxWidth: "100%",
211
+ maxHeight: "100%",
212
+ borderRadius: 0,
213
+ margin: 0,
214
+ },
215
+ // Size styles
216
+ smContent: {
217
+ minWidth: 300,
218
+ minHeight: 200,
219
+ },
220
+ mdContent: {
221
+ minWidth: 400,
222
+ minHeight: 300,
223
+ },
224
+ lgContent: {
225
+ minWidth: 500,
226
+ minHeight: 400,
227
+ },
228
+ xlContent: {
229
+ minWidth: 600,
230
+ minHeight: 500,
231
+ },
232
+ fullContent: {
233
+ width: "95%",
234
+ height: "95%",
235
+ maxWidth: "95%",
236
+ maxHeight: "95%",
237
+ },
238
+ header: {
239
+ paddingHorizontal: theme.spacing[6],
240
+ paddingVertical: theme.spacing[4],
241
+ flexDirection: "row",
242
+ alignItems: "center",
243
+ justifyContent: "space-between",
244
+ },
245
+ body: {
246
+ paddingHorizontal: theme.spacing[6],
247
+ paddingBottom: theme.spacing[6],
248
+ flex: 1,
249
+ },
250
+ footer: {
251
+ paddingHorizontal: theme.spacing[6],
252
+ paddingVertical: theme.spacing[4],
253
+ gap: theme.spacing[2],
254
+ width: "100%",
255
+ },
256
+ title: {
257
+ fontSize: 20,
258
+ fontWeight: "600",
259
+ color: theme.colors.text,
260
+ flex: 1,
261
+ lineHeight: 24,
262
+ },
263
+ description: {
264
+ fontSize: 16,
265
+ color: theme.colors.textMuted,
266
+ lineHeight: 22,
267
+ marginVertical: theme.spacing[4],
268
+ },
269
+ closeButton: {
270
+ width: theme.touchTargets.minimum,
271
+ height: theme.touchTargets.minimum,
272
+ alignItems: "center",
273
+ justifyContent: "center",
274
+ borderRadius: theme.borderRadius.sm,
275
+ marginLeft: theme.spacing[2],
276
+ },
277
+ });
278
+ }
@@ -3,11 +3,23 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.InputPrimitive = exports.InputGroup = exports.InputAddon = exports.InputError = exports.InputDescription = exports.InputLabel = exports.InputContainer = exports.InputRoot = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const jsx_runtime_1 = require("react/jsx-runtime");
6
+ const bottom_sheet_1 = require("@gorhom/bottom-sheet");
6
7
  const react_1 = tslib_1.__importStar(require("react"));
7
8
  const react_native_1 = require("react-native");
8
9
  // Input root primitive - the main TextInput component
9
10
  exports.InputRoot = (0, react_1.forwardRef)(({ value, onChangeText, onChange, onFocus, onBlur, error = false, disabled = false, loading = false, editable, style, placeholderTextColor = "#9ca3af", ...props }, ref) => {
10
11
  const [isFocused, setIsFocused] = react_1.default.useState(false);
12
+ let isInBottomSheet = false;
13
+ try {
14
+ (0, bottom_sheet_1.useBottomSheetInternal)();
15
+ isInBottomSheet = true;
16
+ }
17
+ catch {
18
+ isInBottomSheet = false;
19
+ }
20
+ const InputComponent = isInBottomSheet && react_native_1.Platform.OS !== "web"
21
+ ? bottom_sheet_1.BottomSheetTextInput
22
+ : react_native_1.TextInput;
11
23
  const handleChangeText = react_1.default.useCallback((text) => {
12
24
  if (onChangeText) {
13
25
  onChangeText(text);
@@ -28,7 +40,7 @@ exports.InputRoot = (0, react_1.forwardRef)(({ value, onChangeText, onChange, on
28
40
  onBlur(event);
29
41
  }
30
42
  }, [onBlur]);
31
- return ((0, jsx_runtime_1.jsx)(react_native_1.TextInput, { ref: ref, value: value, onChangeText: handleChangeText, onFocus: handleFocus, onBlur: handleBlur, editable: !disabled && !loading && editable, placeholderTextColor: placeholderTextColor, style: [
43
+ return ((0, jsx_runtime_1.jsx)(InputComponent, { ref: ref, value: value, onChangeText: handleChangeText, onFocus: handleFocus, onBlur: handleBlur, editable: !disabled && !loading && editable, placeholderTextColor: placeholderTextColor, style: [
32
44
  primitiveStyles.input,
33
45
  style,
34
46
  error && primitiveStyles.inputError,
@@ -7,7 +7,7 @@ const react_1 = tslib_1.__importStar(require("react"));
7
7
  const react_native_1 = require("react-native");
8
8
  const { width: screenWidth, height: screenHeight } = react_native_1.Dimensions.get("window");
9
9
  // Modal root primitive - handles the native Modal component
10
- exports.ModalRoot = (0, react_1.forwardRef)(({ open = false, onOpenChange, children, onRequestClose, animationType = "fade", presentationStyle = react_native_1.Platform.OS === "ios" ? "pageSheet" : "fullScreen", statusBarTranslucent = react_native_1.Platform.OS === "android", ...props }, ref) => {
10
+ exports.ModalRoot = (0, react_1.forwardRef)(({ open = false, onOpenChange, children, onRequestClose, animationType = "fade", presentationStyle = react_native_1.Platform.OS === "ios" ? "pageSheet" : "formSheet", statusBarTranslucent = react_native_1.Platform.OS !== "ios", transparent = true, ...props }, ref) => {
11
11
  const handleRequestClose = react_1.default.useCallback((e) => {
12
12
  if (onOpenChange) {
13
13
  onOpenChange(false);
@@ -16,7 +16,7 @@ exports.ModalRoot = (0, react_1.forwardRef)(({ open = false, onOpenChange, child
16
16
  onRequestClose(e);
17
17
  }
18
18
  }, [onOpenChange, onRequestClose]);
19
- return ((0, jsx_runtime_1.jsx)(react_native_1.Modal, { visible: open, onRequestClose: handleRequestClose, animationType: animationType, presentationStyle: presentationStyle, statusBarTranslucent: statusBarTranslucent, ...props, children: (0, jsx_runtime_1.jsx)(react_native_1.View, { ref: ref, style: primitiveStyles.container, children: children }) }));
19
+ return ((0, jsx_runtime_1.jsx)(react_native_1.Modal, { visible: open, onRequestClose: handleRequestClose, animationType: animationType, presentationStyle: presentationStyle, statusBarTranslucent: statusBarTranslucent, transparent: transparent, ...props, children: (0, jsx_runtime_1.jsx)(react_native_1.View, { ref: ref, style: primitiveStyles.container, children: children }) }));
20
20
  });
21
21
  exports.ModalRoot.displayName = "ModalRoot";
22
22
  exports.ModalOverlay = (0, react_1.forwardRef)(({ dismissible = true, onDismiss, onPress, style, children, activeOpacity = 1, ...props }, ref) => {
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Select = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const lucide_react_native_1 = require("lucide-react-native");
6
+ const react_1 = require("react");
7
+ const react_native_1 = require("react-native");
8
+ const theme_1 = require("../../lib/theme/theme");
9
+ const text_1 = require("./text");
10
+ exports.Select = (0, react_1.forwardRef)(({ value, onValueChange, placeholder = "Select...", items, disabled = false, style, }, ref) => {
11
+ const { theme } = (0, theme_1.useTheme)();
12
+ const [isOpen, setIsOpen] = (0, react_1.useState)(false);
13
+ const selectedItem = items.find((item) => item.value === value);
14
+ const handleSelect = (itemValue) => {
15
+ onValueChange(itemValue);
16
+ setIsOpen(false);
17
+ };
18
+ const styles = createStyles(theme, disabled);
19
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)(react_native_1.TouchableOpacity, { ref: ref, style: [styles.container, style], onPress: () => !disabled && setIsOpen(true), disabled: disabled, children: [(0, jsx_runtime_1.jsx)(text_1.Text, { style: styles.value, children: selectedItem?.label || placeholder }), (0, jsx_runtime_1.jsx)(lucide_react_native_1.ChevronDown, { size: 16, color: theme.colors.textMuted })] }), (0, jsx_runtime_1.jsx)(react_native_1.Modal, { visible: isOpen, transparent: true, animationType: "fade", onRequestClose: () => setIsOpen(false), children: (0, jsx_runtime_1.jsx)(react_native_1.TouchableOpacity, { style: styles.overlay, activeOpacity: 1, onPress: () => setIsOpen(false), children: (0, jsx_runtime_1.jsx)(react_native_1.View, { style: styles.dropdown, children: (0, jsx_runtime_1.jsx)(react_native_1.FlatList, { data: items, keyExtractor: (item) => item.value, renderItem: ({ item }) => ((0, jsx_runtime_1.jsxs)(react_native_1.TouchableOpacity, { style: [
20
+ styles.item,
21
+ item.value === value && styles.selectedItem,
22
+ ], onPress: () => handleSelect(item.value), children: [(0, jsx_runtime_1.jsx)(text_1.Text, { style: [
23
+ styles.itemText,
24
+ item.value === value ? styles.selectedItemText : {},
25
+ ], children: item.label }), item.description && ((0, jsx_runtime_1.jsx)(text_1.Text, { style: styles.itemDescription, children: item.description }))] })), style: styles.list }) }) }) })] }));
26
+ });
27
+ exports.Select.displayName = "Select";
28
+ function createStyles(theme, disabled) {
29
+ return react_native_1.StyleSheet.create({
30
+ container: {
31
+ flexDirection: "row",
32
+ alignItems: "center",
33
+ justifyContent: "space-between",
34
+ paddingHorizontal: theme.spacing[3],
35
+ paddingVertical: theme.spacing[3],
36
+ borderWidth: 1,
37
+ borderColor: theme.colors.border,
38
+ borderRadius: theme.borderRadius.md,
39
+ backgroundColor: disabled ? theme.colors.muted : theme.colors.card,
40
+ minHeight: theme.touchTargets.minimum,
41
+ },
42
+ value: {
43
+ fontSize: 16,
44
+ color: disabled ? theme.colors.textDisabled : theme.colors.text,
45
+ flex: 1,
46
+ },
47
+ overlay: {
48
+ flex: 1,
49
+ backgroundColor: "rgba(0, 0, 0, 0.5)",
50
+ justifyContent: "center",
51
+ alignItems: "center",
52
+ },
53
+ dropdown: {
54
+ backgroundColor: theme.colors.background,
55
+ borderRadius: theme.borderRadius.md,
56
+ borderWidth: 1,
57
+ borderColor: theme.colors.border,
58
+ maxHeight: 300,
59
+ width: "90%",
60
+ maxWidth: 400,
61
+ ...theme.shadows.lg,
62
+ },
63
+ list: {
64
+ maxHeight: 300,
65
+ },
66
+ item: {
67
+ paddingHorizontal: theme.spacing[4],
68
+ paddingVertical: theme.spacing[3],
69
+ borderBottomWidth: 1,
70
+ borderBottomColor: theme.colors.border,
71
+ },
72
+ selectedItem: {
73
+ backgroundColor: theme.colors.primary,
74
+ },
75
+ itemText: {
76
+ fontSize: 16,
77
+ color: theme.colors.text,
78
+ },
79
+ selectedItemText: {
80
+ color: theme.colors.primaryForeground,
81
+ fontWeight: "500",
82
+ },
83
+ itemDescription: {
84
+ fontSize: 14,
85
+ color: theme.colors.textMuted,
86
+ marginTop: theme.spacing[1],
87
+ },
88
+ });
89
+ }
@@ -1,11 +1,28 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Textarea = Textarea;
3
+ exports.Textarea = void 0;
4
+ const tslib_1 = require("tslib");
4
5
  const jsx_runtime_1 = require("react/jsx-runtime");
6
+ const bottom_sheet_1 = require("@gorhom/bottom-sheet");
7
+ const React = tslib_1.__importStar(require("react"));
5
8
  const react_native_1 = require("react-native");
6
9
  const atoms_1 = require("../../lib/theme/atoms");
7
- function Textarea({ style, multiline = true, numberOfLines = 4, ...props }) {
8
- return ((0, jsx_runtime_1.jsx)(react_native_1.TextInput, { style: [
10
+ const Textarea = React.forwardRef(({ style, multiline = true, numberOfLines = 4, ...props }, ref) => {
11
+ // Detect if we're inside a bottom sheet
12
+ let isInBottomSheet = false;
13
+ try {
14
+ (0, bottom_sheet_1.useBottomSheetInternal)();
15
+ isInBottomSheet = true;
16
+ }
17
+ catch {
18
+ // Not in a bottom sheet context
19
+ isInBottomSheet = false;
20
+ }
21
+ // Use BottomSheetTextInput when inside a bottom sheet, regular TextInput otherwise
22
+ const InputComponent = isInBottomSheet && react_native_1.Platform.OS !== "web"
23
+ ? bottom_sheet_1.BottomSheetTextInput
24
+ : react_native_1.TextInput;
25
+ return ((0, jsx_runtime_1.jsx)(InputComponent, { ref: ref, style: [
9
26
  atoms_1.flex.values[1],
10
27
  atoms_1.borders.width.thin,
11
28
  atoms_1.borders.color.gray[400],
@@ -16,4 +33,6 @@ function Textarea({ style, multiline = true, numberOfLines = 4, ...props }) {
16
33
  { borderRadius: 10 },
17
34
  style,
18
35
  ], multiline: multiline, numberOfLines: numberOfLines, textAlignVertical: "top", ...props }));
19
- }
36
+ });
37
+ exports.Textarea = Textarea;
38
+ Textarea.displayName = "Textarea";