@kaushverse/pickify 1.0.0 → 1.0.1

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/dist/index.d.mts CHANGED
@@ -25,6 +25,11 @@ type PickerStyles = {
25
25
  doneText?: TextStyle;
26
26
  selectTab?: ViewStyle;
27
27
  selectTabText?: TextStyle;
28
+ inputContainer?: ViewStyle;
29
+ label?: TextStyle;
30
+ selectBox?: ViewStyle;
31
+ selectText?: TextStyle;
32
+ error?: TextStyle;
28
33
  };
29
34
  type Props = {
30
35
  visible: boolean;
@@ -45,8 +50,10 @@ type Props = {
45
50
  onClose: () => void;
46
51
  };
47
52
 
48
- declare function PickerModal({ visible, selectedValue, options, groups, styles, theme, renderTab, renderItem, renderContainer, onSelect, onClose, renderIcon, variant, }: Props & {
49
- variant?: "tabs" | "input";
53
+ declare function PickerModal({ visible, selectedValue, options, groups, styles, theme, renderTab, renderItem, renderContainer, onSelect, onClose, renderIcon, label, placeholder, error, }: Props & {
54
+ label?: string;
55
+ placeholder?: string;
56
+ error?: string;
50
57
  }): react_jsx_runtime.JSX.Element;
51
58
 
52
59
  declare const groupOptions: (options: Option[], config: Record<string, string[]>) => Group[];
package/dist/index.d.ts CHANGED
@@ -25,6 +25,11 @@ type PickerStyles = {
25
25
  doneText?: TextStyle;
26
26
  selectTab?: ViewStyle;
27
27
  selectTabText?: TextStyle;
28
+ inputContainer?: ViewStyle;
29
+ label?: TextStyle;
30
+ selectBox?: ViewStyle;
31
+ selectText?: TextStyle;
32
+ error?: TextStyle;
28
33
  };
29
34
  type Props = {
30
35
  visible: boolean;
@@ -45,8 +50,10 @@ type Props = {
45
50
  onClose: () => void;
46
51
  };
47
52
 
48
- declare function PickerModal({ visible, selectedValue, options, groups, styles, theme, renderTab, renderItem, renderContainer, onSelect, onClose, renderIcon, variant, }: Props & {
49
- variant?: "tabs" | "input";
53
+ declare function PickerModal({ visible, selectedValue, options, groups, styles, theme, renderTab, renderItem, renderContainer, onSelect, onClose, renderIcon, label, placeholder, error, }: Props & {
54
+ label?: string;
55
+ placeholder?: string;
56
+ error?: string;
50
57
  }): react_jsx_runtime.JSX.Element;
51
58
 
52
59
  declare const groupOptions: (options: Option[], config: Record<string, string[]>) => Group[];
package/dist/index.js CHANGED
@@ -43,11 +43,14 @@ function PickerModal({
43
43
  onSelect,
44
44
  onClose,
45
45
  renderIcon,
46
- variant = "tabs"
46
+ label,
47
+ placeholder = "Select",
48
+ error
47
49
  }) {
48
50
  const [activeTab, setActiveTab] = (0, import_react.useState)(0);
51
+ const [open, setOpen] = (0, import_react.useState)(false);
52
+ const isVisible = visible ?? open;
49
53
  const hasGroups = groups.length > 0;
50
- const isInputVariant = variant === "input";
51
54
  const currentOptions = hasGroups ? groups[activeTab]?.data || [] : options;
52
55
  (0, import_react.useEffect)(() => {
53
56
  if (!hasGroups) return;
@@ -55,10 +58,21 @@ function PickerModal({
55
58
  (group) => group.data.some((item) => item.value === selectedValue)
56
59
  );
57
60
  if (index !== -1) setActiveTab(index);
58
- }, [selectedValue, visible]);
61
+ }, [selectedValue, isVisible]);
59
62
  const primary = theme?.primaryColor || "#6366f1";
60
63
  const bg = theme?.backgroundColor || "#fff";
61
64
  const text = theme?.textColor || "#111827";
65
+ const getLabel = () => {
66
+ const all = hasGroups ? groups.flatMap((g) => g.data) : options;
67
+ return all.find((o) => o.value === selectedValue)?.label;
68
+ };
69
+ const handleClose = () => {
70
+ setOpen(false);
71
+ onClose?.();
72
+ };
73
+ const handleOpen = () => {
74
+ setOpen(true);
75
+ };
62
76
  const content = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
63
77
  import_react_native.View,
64
78
  {
@@ -76,14 +90,18 @@ function PickerModal({
76
90
  { backgroundColor: primary },
77
91
  styles?.doneBtn
78
92
  ],
79
- onPress: onClose,
93
+ onPress: handleClose,
80
94
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.Text, { style: [defaultStyles.doneText, styles?.doneText], children: "Done" })
81
95
  }
82
96
  ),
83
- hasGroups && !isInputVariant && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.ScrollView, { horizontal: true, showsHorizontalScrollIndicator: false, children: groups.map((tab, index) => {
97
+ hasGroups && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.ScrollView, { horizontal: true, showsHorizontalScrollIndicator: false, children: groups.map((tab, index) => {
84
98
  const isActive = activeTab === index;
85
99
  if (renderTab) {
86
- return renderTab(tab, isActive, () => setActiveTab(index));
100
+ return renderTab(
101
+ tab,
102
+ isActive,
103
+ () => setActiveTab(index)
104
+ );
87
105
  }
88
106
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
89
107
  import_react_native.TouchableOpacity,
@@ -91,9 +109,7 @@ function PickerModal({
91
109
  style: [
92
110
  defaultStyles.tab,
93
111
  styles?.tab,
94
- isActive && {
95
- backgroundColor: primary
96
- }
112
+ isActive && { backgroundColor: primary }
97
113
  ],
98
114
  onPress: () => setActiveTab(index),
99
115
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
@@ -111,50 +127,53 @@ function PickerModal({
111
127
  tab.label
112
128
  );
113
129
  }) }),
114
- hasGroups && isInputVariant && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.ScrollView, { horizontal: true, showsHorizontalScrollIndicator: false, children: groups.map((tab, index) => {
115
- const isActive = activeTab === index;
116
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
117
- import_react_native.TouchableOpacity,
118
- {
119
- style: [
120
- defaultStyles.selectTab,
121
- styles?.selectTab,
122
- isActive && { borderColor: primary }
123
- ],
124
- onPress: () => setActiveTab(index),
125
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native.View, { style: defaultStyles.selectTabInner, children: [
126
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
127
- import_react_native.Text,
128
- {
129
- style: [defaultStyles.selectTabText, styles?.selectTabText],
130
- children: tab.label
131
- }
132
- ),
133
- renderIcon?.({
134
- name: "chevron-down",
135
- size: 18,
136
- color: "#6B7280"
137
- })
138
- ] })
139
- },
140
- tab.label
141
- );
142
- }) }),
143
130
  renderItem ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.ScrollView, { style: { maxHeight: 250 }, children: currentOptions.map(
144
131
  (item) => renderItem(item, selectedValue === item.value)
145
- ) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_picker.Picker, { selectedValue, onValueChange: onSelect, children: currentOptions.map((item) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
146
- import_picker.Picker.Item,
132
+ ) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
133
+ import_picker.Picker,
147
134
  {
148
- label: item.label,
149
- value: item.value,
150
- color: text
151
- },
152
- item.value
153
- )) })
135
+ selectedValue,
136
+ onValueChange: (val) => onSelect(val),
137
+ children: currentOptions.map((item) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
138
+ import_picker.Picker.Item,
139
+ {
140
+ label: item.label,
141
+ value: item.value,
142
+ color: text
143
+ },
144
+ item.value
145
+ ))
146
+ }
147
+ )
154
148
  ]
155
149
  }
156
150
  );
157
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.Modal, { visible, transparent: true, animationType: "slide", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.View, { style: defaultStyles.modalOverlay, children: renderContainer ? renderContainer(content) : content }) });
151
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
152
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native.View, { style: styles?.inputContainer, children: [
153
+ label && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.Text, { style: styles?.label, children: label }),
154
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
155
+ import_react_native.TouchableOpacity,
156
+ {
157
+ style: [
158
+ defaultStyles.selectBox,
159
+ styles?.selectBox,
160
+ error && { borderColor: "red" }
161
+ ],
162
+ onPress: handleOpen,
163
+ children: [
164
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.Text, { style: [defaultStyles.selectText, styles?.selectText], children: getLabel() || placeholder }),
165
+ renderIcon?.({
166
+ name: "chevron-down",
167
+ size: 18,
168
+ color: "#6B7280"
169
+ })
170
+ ]
171
+ }
172
+ ),
173
+ error && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.Text, { style: [defaultStyles.error, styles?.error], children: error })
174
+ ] }),
175
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.Modal, { visible: isVisible, transparent: true, animationType: "slide", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native.View, { style: defaultStyles.modalOverlay, children: renderContainer ? renderContainer(content) : content }) })
176
+ ] });
158
177
  }
159
178
  var defaultStyles = import_react_native.StyleSheet.create({
160
179
  modalOverlay: {
@@ -167,20 +186,8 @@ var defaultStyles = import_react_native.StyleSheet.create({
167
186
  borderTopRightRadius: 20,
168
187
  padding: 20
169
188
  },
170
- /* ---------- NORMAL TABS ---------- */
171
- tab: {
172
- paddingHorizontal: 16,
173
- paddingVertical: 8,
174
- borderRadius: 20,
175
- marginRight: 8,
176
- backgroundColor: "#f3f4f6"
177
- },
178
- tabText: {
179
- fontSize: 13,
180
- fontWeight: "500"
181
- },
182
- /* ---------- INPUT STYLE TABS ---------- */
183
- selectTab: {
189
+ /* ---------- INPUT ---------- */
190
+ selectBox: {
184
191
  height: 48,
185
192
  borderWidth: 1,
186
193
  borderColor: "#E5E7EB",
@@ -190,16 +197,28 @@ var defaultStyles = import_react_native.StyleSheet.create({
190
197
  justifyContent: "space-between",
191
198
  alignItems: "center"
192
199
  },
193
- selectTabInner: {
194
- flexDirection: "row",
195
- justifyContent: "space-between",
196
- alignItems: "center"
197
- },
198
- selectTabText: {
200
+ selectText: {
199
201
  fontSize: 16,
200
202
  fontWeight: "500"
201
203
  },
202
- /* ---------- DONE BUTTON ---------- */
204
+ error: {
205
+ color: "red",
206
+ fontSize: 12,
207
+ marginTop: 4
208
+ },
209
+ /* ---------- TABS ---------- */
210
+ tab: {
211
+ paddingHorizontal: 16,
212
+ paddingVertical: 8,
213
+ borderRadius: 20,
214
+ marginRight: 8,
215
+ backgroundColor: "#f3f4f6"
216
+ },
217
+ tabText: {
218
+ fontSize: 13,
219
+ fontWeight: "500"
220
+ },
221
+ /* ---------- DONE ---------- */
203
222
  doneBtn: {
204
223
  alignSelf: "flex-end",
205
224
  paddingHorizontal: 14,
package/dist/index.mjs CHANGED
@@ -9,7 +9,7 @@ import {
9
9
  ScrollView
10
10
  } from "react-native";
11
11
  import { Picker } from "@react-native-picker/picker";
12
- import { jsx, jsxs } from "react/jsx-runtime";
12
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
13
13
  function PickerModal({
14
14
  visible,
15
15
  selectedValue,
@@ -23,11 +23,14 @@ function PickerModal({
23
23
  onSelect,
24
24
  onClose,
25
25
  renderIcon,
26
- variant = "tabs"
26
+ label,
27
+ placeholder = "Select",
28
+ error
27
29
  }) {
28
30
  const [activeTab, setActiveTab] = useState(0);
31
+ const [open, setOpen] = useState(false);
32
+ const isVisible = visible ?? open;
29
33
  const hasGroups = groups.length > 0;
30
- const isInputVariant = variant === "input";
31
34
  const currentOptions = hasGroups ? groups[activeTab]?.data || [] : options;
32
35
  useEffect(() => {
33
36
  if (!hasGroups) return;
@@ -35,10 +38,21 @@ function PickerModal({
35
38
  (group) => group.data.some((item) => item.value === selectedValue)
36
39
  );
37
40
  if (index !== -1) setActiveTab(index);
38
- }, [selectedValue, visible]);
41
+ }, [selectedValue, isVisible]);
39
42
  const primary = theme?.primaryColor || "#6366f1";
40
43
  const bg = theme?.backgroundColor || "#fff";
41
44
  const text = theme?.textColor || "#111827";
45
+ const getLabel = () => {
46
+ const all = hasGroups ? groups.flatMap((g) => g.data) : options;
47
+ return all.find((o) => o.value === selectedValue)?.label;
48
+ };
49
+ const handleClose = () => {
50
+ setOpen(false);
51
+ onClose?.();
52
+ };
53
+ const handleOpen = () => {
54
+ setOpen(true);
55
+ };
42
56
  const content = /* @__PURE__ */ jsxs(
43
57
  View,
44
58
  {
@@ -56,14 +70,18 @@ function PickerModal({
56
70
  { backgroundColor: primary },
57
71
  styles?.doneBtn
58
72
  ],
59
- onPress: onClose,
73
+ onPress: handleClose,
60
74
  children: /* @__PURE__ */ jsx(Text, { style: [defaultStyles.doneText, styles?.doneText], children: "Done" })
61
75
  }
62
76
  ),
63
- hasGroups && !isInputVariant && /* @__PURE__ */ jsx(ScrollView, { horizontal: true, showsHorizontalScrollIndicator: false, children: groups.map((tab, index) => {
77
+ hasGroups && /* @__PURE__ */ jsx(ScrollView, { horizontal: true, showsHorizontalScrollIndicator: false, children: groups.map((tab, index) => {
64
78
  const isActive = activeTab === index;
65
79
  if (renderTab) {
66
- return renderTab(tab, isActive, () => setActiveTab(index));
80
+ return renderTab(
81
+ tab,
82
+ isActive,
83
+ () => setActiveTab(index)
84
+ );
67
85
  }
68
86
  return /* @__PURE__ */ jsx(
69
87
  TouchableOpacity,
@@ -71,9 +89,7 @@ function PickerModal({
71
89
  style: [
72
90
  defaultStyles.tab,
73
91
  styles?.tab,
74
- isActive && {
75
- backgroundColor: primary
76
- }
92
+ isActive && { backgroundColor: primary }
77
93
  ],
78
94
  onPress: () => setActiveTab(index),
79
95
  children: /* @__PURE__ */ jsx(
@@ -91,50 +107,53 @@ function PickerModal({
91
107
  tab.label
92
108
  );
93
109
  }) }),
94
- hasGroups && isInputVariant && /* @__PURE__ */ jsx(ScrollView, { horizontal: true, showsHorizontalScrollIndicator: false, children: groups.map((tab, index) => {
95
- const isActive = activeTab === index;
96
- return /* @__PURE__ */ jsx(
97
- TouchableOpacity,
98
- {
99
- style: [
100
- defaultStyles.selectTab,
101
- styles?.selectTab,
102
- isActive && { borderColor: primary }
103
- ],
104
- onPress: () => setActiveTab(index),
105
- children: /* @__PURE__ */ jsxs(View, { style: defaultStyles.selectTabInner, children: [
106
- /* @__PURE__ */ jsx(
107
- Text,
108
- {
109
- style: [defaultStyles.selectTabText, styles?.selectTabText],
110
- children: tab.label
111
- }
112
- ),
113
- renderIcon?.({
114
- name: "chevron-down",
115
- size: 18,
116
- color: "#6B7280"
117
- })
118
- ] })
119
- },
120
- tab.label
121
- );
122
- }) }),
123
110
  renderItem ? /* @__PURE__ */ jsx(ScrollView, { style: { maxHeight: 250 }, children: currentOptions.map(
124
111
  (item) => renderItem(item, selectedValue === item.value)
125
- ) }) : /* @__PURE__ */ jsx(Picker, { selectedValue, onValueChange: onSelect, children: currentOptions.map((item) => /* @__PURE__ */ jsx(
126
- Picker.Item,
112
+ ) }) : /* @__PURE__ */ jsx(
113
+ Picker,
127
114
  {
128
- label: item.label,
129
- value: item.value,
130
- color: text
131
- },
132
- item.value
133
- )) })
115
+ selectedValue,
116
+ onValueChange: (val) => onSelect(val),
117
+ children: currentOptions.map((item) => /* @__PURE__ */ jsx(
118
+ Picker.Item,
119
+ {
120
+ label: item.label,
121
+ value: item.value,
122
+ color: text
123
+ },
124
+ item.value
125
+ ))
126
+ }
127
+ )
134
128
  ]
135
129
  }
136
130
  );
137
- return /* @__PURE__ */ jsx(Modal, { visible, transparent: true, animationType: "slide", children: /* @__PURE__ */ jsx(View, { style: defaultStyles.modalOverlay, children: renderContainer ? renderContainer(content) : content }) });
131
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
132
+ /* @__PURE__ */ jsxs(View, { style: styles?.inputContainer, children: [
133
+ label && /* @__PURE__ */ jsx(Text, { style: styles?.label, children: label }),
134
+ /* @__PURE__ */ jsxs(
135
+ TouchableOpacity,
136
+ {
137
+ style: [
138
+ defaultStyles.selectBox,
139
+ styles?.selectBox,
140
+ error && { borderColor: "red" }
141
+ ],
142
+ onPress: handleOpen,
143
+ children: [
144
+ /* @__PURE__ */ jsx(Text, { style: [defaultStyles.selectText, styles?.selectText], children: getLabel() || placeholder }),
145
+ renderIcon?.({
146
+ name: "chevron-down",
147
+ size: 18,
148
+ color: "#6B7280"
149
+ })
150
+ ]
151
+ }
152
+ ),
153
+ error && /* @__PURE__ */ jsx(Text, { style: [defaultStyles.error, styles?.error], children: error })
154
+ ] }),
155
+ /* @__PURE__ */ jsx(Modal, { visible: isVisible, transparent: true, animationType: "slide", children: /* @__PURE__ */ jsx(View, { style: defaultStyles.modalOverlay, children: renderContainer ? renderContainer(content) : content }) })
156
+ ] });
138
157
  }
139
158
  var defaultStyles = StyleSheet.create({
140
159
  modalOverlay: {
@@ -147,20 +166,8 @@ var defaultStyles = StyleSheet.create({
147
166
  borderTopRightRadius: 20,
148
167
  padding: 20
149
168
  },
150
- /* ---------- NORMAL TABS ---------- */
151
- tab: {
152
- paddingHorizontal: 16,
153
- paddingVertical: 8,
154
- borderRadius: 20,
155
- marginRight: 8,
156
- backgroundColor: "#f3f4f6"
157
- },
158
- tabText: {
159
- fontSize: 13,
160
- fontWeight: "500"
161
- },
162
- /* ---------- INPUT STYLE TABS ---------- */
163
- selectTab: {
169
+ /* ---------- INPUT ---------- */
170
+ selectBox: {
164
171
  height: 48,
165
172
  borderWidth: 1,
166
173
  borderColor: "#E5E7EB",
@@ -170,16 +177,28 @@ var defaultStyles = StyleSheet.create({
170
177
  justifyContent: "space-between",
171
178
  alignItems: "center"
172
179
  },
173
- selectTabInner: {
174
- flexDirection: "row",
175
- justifyContent: "space-between",
176
- alignItems: "center"
177
- },
178
- selectTabText: {
180
+ selectText: {
179
181
  fontSize: 16,
180
182
  fontWeight: "500"
181
183
  },
182
- /* ---------- DONE BUTTON ---------- */
184
+ error: {
185
+ color: "red",
186
+ fontSize: 12,
187
+ marginTop: 4
188
+ },
189
+ /* ---------- TABS ---------- */
190
+ tab: {
191
+ paddingHorizontal: 16,
192
+ paddingVertical: 8,
193
+ borderRadius: 20,
194
+ marginRight: 8,
195
+ backgroundColor: "#f3f4f6"
196
+ },
197
+ tabText: {
198
+ fontSize: 13,
199
+ fontWeight: "500"
200
+ },
201
+ /* ---------- DONE ---------- */
183
202
  doneBtn: {
184
203
  alignSelf: "flex-end",
185
204
  paddingHorizontal: 14,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kaushverse/pickify",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "A fully customizable React Native picker with search, multi-select, grouping, and async support.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",