@streamplace/components 0.8.6 → 0.8.9

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.
@@ -1,15 +1,20 @@
1
- import { ChevronDown } from "lucide-react-native";
2
- import { forwardRef, useState } from "react";
3
- import {
4
- FlatList,
5
- Modal,
6
- StyleSheet,
7
- TouchableOpacity,
8
- View,
9
- } from "react-native";
1
+ import { Check, ChevronDown } from "lucide-react-native";
2
+ import { forwardRef } from "react";
3
+ import { View } from "react-native";
4
+ import { zero } from "../..";
10
5
  import { useTheme } from "../../lib/theme/theme";
6
+ import { flex } from "../../ui";
7
+ import {
8
+ DropdownMenu,
9
+ DropdownMenuItem,
10
+ DropdownMenuSeparator,
11
+ DropdownMenuTrigger,
12
+ ResponsiveDropdownMenuContent,
13
+ } from "./dropdown";
11
14
  import { Text } from "./text";
12
15
 
16
+ const { layout, px, py, borders, r, gap } = zero;
17
+
13
18
  export interface SelectItem {
14
19
  label: string;
15
20
  value: string;
@@ -25,7 +30,7 @@ export interface SelectProps {
25
30
  style?: any;
26
31
  }
27
32
 
28
- export const Select = forwardRef<any, SelectProps>(
33
+ export const Select = forwardRef<View, SelectProps>(
29
34
  (
30
35
  {
31
36
  value,
@@ -38,138 +43,105 @@ export const Select = forwardRef<any, SelectProps>(
38
43
  ref,
39
44
  ) => {
40
45
  const { theme } = useTheme();
41
- const [isOpen, setIsOpen] = useState(false);
42
46
 
43
47
  const selectedItem = items.find((item) => item.value === value);
44
48
 
45
- const handleSelect = (itemValue: string) => {
46
- onValueChange(itemValue);
47
- setIsOpen(false);
48
- };
49
-
50
- const styles = createStyles(theme, disabled);
51
-
52
49
  return (
53
- <>
54
- <TouchableOpacity
55
- ref={ref}
56
- style={[styles.container, style]}
57
- onPress={() => !disabled && setIsOpen(true)}
58
- disabled={disabled}
59
- >
60
- <Text style={styles.value}>{selectedItem?.label || placeholder}</Text>
61
- <ChevronDown size={16} color={theme.colors.textMuted} />
62
- </TouchableOpacity>
50
+ <DropdownMenu>
51
+ <DropdownMenuTrigger disabled={disabled}>
52
+ <View
53
+ ref={ref}
54
+ style={[
55
+ {
56
+ width: "100%",
57
+ paddingHorizontal: theme.spacing[3],
58
+ paddingVertical: theme.spacing[3],
59
+ borderWidth: 1,
60
+ borderColor: theme.colors.border,
61
+ borderRadius: theme.borderRadius.md,
62
+ backgroundColor: disabled
63
+ ? theme.colors.muted
64
+ : theme.colors.card,
65
+ minHeight: theme.touchTargets.minimum,
66
+ opacity: disabled ? 0.5 : 1,
67
+ },
68
+ style,
69
+ ]}
70
+ >
71
+ <View
72
+ style={{
73
+ flexDirection: "row",
74
+ alignItems: "center",
75
+ justifyContent: "space-between",
76
+ width: "100%",
77
+ gap: 8,
78
+ }}
79
+ >
80
+ <Text
81
+ style={{
82
+ fontSize: 16,
83
+ color: disabled
84
+ ? theme.colors.textDisabled
85
+ : theme.colors.text,
86
+ flex: 1,
87
+ }}
88
+ >
89
+ {selectedItem?.label || placeholder}
90
+ </Text>
91
+ <ChevronDown size={16} color={theme.colors.textMuted} />
92
+ </View>
93
+ </View>
94
+ </DropdownMenuTrigger>
63
95
 
64
- <Modal
65
- visible={isOpen}
66
- transparent
67
- animationType="fade"
68
- onRequestClose={() => setIsOpen(false)}
96
+ <ResponsiveDropdownMenuContent
97
+ align="start"
98
+ style={[
99
+ {
100
+ maxHeight: 400,
101
+ },
102
+ ]}
69
103
  >
70
- <TouchableOpacity
71
- style={styles.overlay}
72
- activeOpacity={1}
73
- onPress={() => setIsOpen(false)}
74
- >
75
- <View style={styles.dropdown}>
76
- <FlatList
77
- data={items}
78
- keyExtractor={(item) => item.value}
79
- renderItem={({ item }) => (
80
- <TouchableOpacity
81
- style={[
82
- styles.item,
83
- item.value === value && styles.selectedItem,
84
- ]}
85
- onPress={() => handleSelect(item.value)}
86
- >
104
+ {items.map((item, index) => (
105
+ <View key={item.value}>
106
+ <DropdownMenuItem onPress={() => onValueChange(item.value)}>
107
+ <View
108
+ style={{
109
+ flexDirection: "row",
110
+ alignItems: "center",
111
+ justifyContent: "space-between",
112
+ width: "100%",
113
+ gap: 8,
114
+ }}
115
+ >
116
+ <View style={[gap.all[1], py[1], flex.values[1]]}>
87
117
  <Text
88
- style={[
89
- styles.itemText,
90
- item.value === value ? styles.selectedItemText : {},
91
- ]}
118
+ style={{
119
+ fontWeight: item.value === value ? "500" : "400",
120
+ }}
121
+ color={item.value === value ? "primary" : "default"}
92
122
  >
93
123
  {item.label}
94
124
  </Text>
95
125
  {item.description && (
96
- <Text style={styles.itemDescription}>
126
+ <Text size="sm" color="muted">
97
127
  {item.description}
98
128
  </Text>
99
129
  )}
100
- </TouchableOpacity>
101
- )}
102
- style={styles.list}
103
- />
130
+ </View>
131
+ {item.value === value ? (
132
+ <Check size={16} color={theme.colors.primary} />
133
+ ) : (
134
+ <View style={{ width: 16 }} />
135
+ )}
136
+ </View>
137
+ </DropdownMenuItem>
138
+ {index < items.length - 1 && <DropdownMenuSeparator />}
104
139
  </View>
105
- </TouchableOpacity>
106
- </Modal>
107
- </>
140
+ ))}
141
+ </ResponsiveDropdownMenuContent>
142
+ </DropdownMenu>
108
143
  );
109
144
  },
110
145
  );
111
146
 
112
147
  Select.displayName = "Select";
113
-
114
- function createStyles(theme: any, disabled: boolean) {
115
- return StyleSheet.create({
116
- container: {
117
- flexDirection: "row",
118
- alignItems: "center",
119
- justifyContent: "space-between",
120
- paddingHorizontal: theme.spacing[3],
121
- paddingVertical: theme.spacing[3],
122
- borderWidth: 1,
123
- borderColor: theme.colors.border,
124
- borderRadius: theme.borderRadius.md,
125
- backgroundColor: disabled ? theme.colors.muted : theme.colors.card,
126
- minHeight: theme.touchTargets.minimum,
127
- },
128
- value: {
129
- fontSize: 16,
130
- color: disabled ? theme.colors.textDisabled : theme.colors.text,
131
- flex: 1,
132
- },
133
- overlay: {
134
- flex: 1,
135
- backgroundColor: "rgba(0, 0, 0, 0.5)",
136
- justifyContent: "center",
137
- alignItems: "center",
138
- },
139
- dropdown: {
140
- backgroundColor: theme.colors.background,
141
- borderRadius: theme.borderRadius.md,
142
- borderWidth: 1,
143
- borderColor: theme.colors.border,
144
- maxHeight: 300,
145
- width: "90%",
146
- maxWidth: 400,
147
- ...theme.shadows.lg,
148
- },
149
- list: {
150
- maxHeight: 300,
151
- },
152
- item: {
153
- paddingHorizontal: theme.spacing[4],
154
- paddingVertical: theme.spacing[3],
155
- borderBottomWidth: 1,
156
- borderBottomColor: theme.colors.border,
157
- },
158
- selectedItem: {
159
- backgroundColor: theme.colors.primary,
160
- },
161
- itemText: {
162
- fontSize: 16,
163
- color: theme.colors.text,
164
- },
165
- selectedItemText: {
166
- color: theme.colors.primaryForeground,
167
- fontWeight: "500",
168
- },
169
- itemDescription: {
170
- fontSize: 14,
171
- color: theme.colors.textMuted,
172
- marginTop: theme.spacing[1],
173
- },
174
- });
175
- }