@towsila/expo-ui-library 1.0.19 → 1.0.21

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@towsila/expo-ui-library",
3
- "version": "1.0.19",
3
+ "version": "1.0.21",
4
4
  "description": "",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
package/src/index.ts CHANGED
@@ -60,4 +60,3 @@ export {default as WarningModel} from "./components/ui/warningModel";
60
60
  export {default as Toast} from "./components/ui/toast";
61
61
  export {default as AccountStatusScreen} from "./components/screens/AccountStatusScreen";
62
62
  export {sendEmail} from "./service/sendEmail";
63
- export {default as SharpDropdown} from "./components/ui/sharpDropdown";
@@ -1,165 +0,0 @@
1
- import { useState, useRef } from "react";
2
- import { Text, View, TouchableOpacity, Modal } from "react-native";
3
- import { useAppTheme } from "../../context/ThemeContext";
4
- import { Fonts, textSize } from "../../tokens/typography";
5
- import { Ionicons } from "@expo/vector-icons";
6
- import SharpContainer from "./sharpContainer";
7
- import ErrorMessage from "./error";
8
-
9
- interface Option {
10
- value: string;
11
- label: string;
12
- }
13
-
14
- interface SharpDropdownProps {
15
- options: Option[];
16
- value: string | null;
17
- onChange: (value: string) => void;
18
- label?: string;
19
- placeholder?: string;
20
- error?: string;
21
- onClearError?: () => void;
22
- height?: number;
23
- bgColor?: string;
24
- }
25
-
26
- export default function SharpDropdown({
27
- options,
28
- value,
29
- onChange,
30
- label,
31
- placeholder = "Select an option",
32
- error,
33
- onClearError,
34
- height = 50,
35
- bgColor,
36
- }: SharpDropdownProps) {
37
- const [open, setOpen] = useState(false);
38
- const [dropdownPos, setDropdownPos] = useState({ x: 0, y: 0, width: 0 });
39
- const triggerRef = useRef<View>(null);
40
- const { colors } = useAppTheme();
41
-
42
- const selectedLabel = options.find((o) => o.value === value)?.label;
43
-
44
- const getBorderColor = () => {
45
- if (error) return colors.semantic.error;
46
- if (open) return colors.primary;
47
- return colors.semantic.border;
48
- };
49
-
50
- const handleOpen = () => {
51
- triggerRef.current?.measureInWindow((x, y, width, h) => {
52
- setDropdownPos({ x, y: y + h + 4, width });
53
- setOpen(true);
54
- onClearError?.();
55
- });
56
- };
57
-
58
- return (
59
- <View style={{ marginBottom: 4 }}>
60
- {label && (
61
- <Text style={{
62
- color: colors.text.primary,
63
- fontSize: textSize.xs,
64
- fontFamily: Fonts.montserrat.semiBold,
65
- marginBottom: 6,
66
- }}>
67
- {label}
68
- </Text>
69
- )}
70
-
71
- {/* Sharp trigger — same as SharpInput */}
72
- <TouchableOpacity
73
- onPress={() => open ? setOpen(false) : handleOpen()}
74
- activeOpacity={0.8}
75
- >
76
- <View ref={triggerRef}>
77
- <SharpContainer
78
- height={height}
79
- bgColor={bgColor ?? colors.background.main}
80
- borderColor={getBorderColor()}
81
- >
82
- <View style={{
83
- flex: 1,
84
- flexDirection: "row",
85
- alignItems: "center",
86
- justifyContent: "space-between",
87
- paddingHorizontal: 16,
88
- }}>
89
- <Text style={{
90
- fontSize: textSize.sm,
91
- fontFamily: Fonts.montserrat.regular,
92
- color: selectedLabel ? colors.text.primary : colors.text.secondary,
93
- }}>
94
- {selectedLabel ?? placeholder}
95
- </Text>
96
- <Ionicons
97
- name={open ? "chevron-up" : "chevron-down"}
98
- size={16}
99
- color={colors.text.secondary}
100
- />
101
- </View>
102
- </SharpContainer>
103
- </View>
104
- </TouchableOpacity>
105
-
106
- {error && <ErrorMessage message={error} />}
107
-
108
- {/* Normal rounded dropdown options */}
109
- <Modal visible={open} transparent animationType="none">
110
- <TouchableOpacity
111
- style={{ flex: 1 }}
112
- activeOpacity={1}
113
- onPress={() => setOpen(false)}
114
- >
115
- <View style={{
116
- position: "absolute",
117
- top: dropdownPos.y,
118
- left: dropdownPos.x,
119
- width: dropdownPos.width,
120
- backgroundColor: colors.background.card,
121
- borderRadius: 12,
122
- borderWidth: 1,
123
- borderColor: colors.semantic.border,
124
- elevation: 10,
125
- shadowColor: "#000",
126
- shadowOffset: { width: 0, height: 4 },
127
- shadowOpacity: 0.15,
128
- shadowRadius: 6,
129
- overflow: "hidden",
130
- }}>
131
- {options.map((opt, index) => (
132
- <TouchableOpacity
133
- key={opt.value}
134
- onPress={() => {
135
- onChange(opt.value);
136
- setOpen(false);
137
- }}
138
- style={{
139
- padding: 14,
140
- flexDirection: "row",
141
- alignItems: "center",
142
- justifyContent: "space-between",
143
- borderBottomWidth: index < options.length - 1 ? 1 : 0,
144
- borderBottomColor: colors.background.main,
145
- backgroundColor: value === opt.value ? colors.primary + "15" : "transparent",
146
- }}
147
- >
148
- <Text style={{
149
- fontSize: textSize.sm,
150
- fontFamily: value === opt.value ? Fonts.montserrat.semiBold : Fonts.montserrat.regular,
151
- color: value === opt.value ? colors.primary : colors.text.primary,
152
- }}>
153
- {opt.label}
154
- </Text>
155
- {value === opt.value && (
156
- <Ionicons name="checkmark" size={16} color={colors.primary} />
157
- )}
158
- </TouchableOpacity>
159
- ))}
160
- </View>
161
- </TouchableOpacity>
162
- </Modal>
163
- </View>
164
- );
165
- }