@sudobility/subscription-components-rn 1.0.2 → 1.0.4

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": "@sudobility/subscription-components-rn",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "React Native Subscription UI components for Sudobility with RevenueCat support",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.esm.js",
@@ -40,9 +40,6 @@
40
40
  "@sudobility/components-rn": "^1.0.7",
41
41
  "@sudobility/design": "^1.1.14",
42
42
  "@types/react": "^18.3.0",
43
- "@types/react-native": "^0.73.0",
44
- "react": "^18.3.0",
45
- "react-native": "^0.76.0",
46
43
  "typescript": "^5.6.0",
47
44
  "vite": "^6.0.0",
48
45
  "vite-plugin-dts": "^4.3.0"
@@ -1,4 +1,4 @@
1
- import { View, Text, Pressable } from 'react-native';
1
+ import { View, Text, Pressable, StyleSheet } from 'react-native';
2
2
 
3
3
  export interface SegmentedControlOption<T extends string = string> {
4
4
  /** Value for this option */
@@ -30,30 +30,6 @@ export interface SegmentedControlProps<T extends string = string> {
30
30
  accessibilityLabel?: string;
31
31
  }
32
32
 
33
- /**
34
- * Size class mapping
35
- */
36
- const sizeClasses = {
37
- sm: {
38
- container: 'p-1 rounded-lg',
39
- segment: 'px-3 py-1.5 rounded-md',
40
- text: 'text-xs',
41
- badge: 'text-xs px-1.5 py-0.5',
42
- },
43
- md: {
44
- container: 'p-1 rounded-lg',
45
- segment: 'px-4 py-2 rounded-md',
46
- text: 'text-sm',
47
- badge: 'text-xs px-2 py-0.5',
48
- },
49
- lg: {
50
- container: 'p-1 rounded-lg',
51
- segment: 'px-6 py-3 rounded-lg',
52
- text: 'text-base',
53
- badge: 'text-sm px-2 py-1',
54
- },
55
- };
56
-
57
33
  /**
58
34
  * SegmentedControl - A toggle control for switching between options
59
35
  *
@@ -82,51 +58,31 @@ export function SegmentedControl<T extends string = string>({
82
58
  fullWidth = true,
83
59
  accessibilityLabel,
84
60
  }: SegmentedControlProps<T>) {
85
- const sizes = sizeClasses[size];
86
-
87
- const containerClasses = [
88
- 'flex-row bg-gray-100 dark:bg-gray-800',
89
- sizes.container,
90
- fullWidth ? 'w-full' : '',
91
- disabled ? 'opacity-50' : '',
92
- className,
93
- ]
94
- .filter(Boolean)
95
- .join(' ');
61
+ void className;
96
62
 
97
63
  return (
98
64
  <View
99
- className={containerClasses}
100
- accessibilityRole='tablist'
65
+ style={[
66
+ styles.container,
67
+ fullWidth && styles.fullWidth,
68
+ disabled && styles.disabled,
69
+ size === 'sm' && styles.containerSm,
70
+ size === 'md' && styles.containerMd,
71
+ size === 'lg' && styles.containerLg,
72
+ ]}
73
+ accessibilityRole="tablist"
101
74
  accessibilityLabel={accessibilityLabel}
102
75
  >
103
76
  {options.map(option => {
104
77
  const isSelected = value === option.value;
105
78
  const isDisabled = disabled || option.disabled;
106
79
 
107
- const segmentClasses = [
108
- sizes.segment,
109
- 'flex-1 items-center justify-center flex-row gap-2',
110
- isSelected ? 'bg-white dark:bg-gray-700 shadow-sm' : 'bg-transparent',
111
- isDisabled ? 'opacity-50' : '',
112
- ]
113
- .filter(Boolean)
114
- .join(' ');
115
-
116
- const textClasses = [
117
- sizes.text,
118
- 'font-medium',
119
- isSelected
120
- ? 'text-gray-900 dark:text-white'
121
- : 'text-gray-600 dark:text-gray-400',
122
- ].join(' ');
123
-
124
80
  return (
125
81
  <Pressable
126
82
  key={option.value}
127
83
  onPress={() => !isDisabled && onChange(option.value)}
128
84
  disabled={isDisabled}
129
- accessibilityRole='tab'
85
+ accessibilityRole="tab"
130
86
  accessibilityState={{
131
87
  selected: isSelected,
132
88
  disabled: isDisabled,
@@ -134,28 +90,45 @@ export function SegmentedControl<T extends string = string>({
134
90
  accessibilityLabel={
135
91
  option.label + (option.badge ? ', ' + option.badge : '')
136
92
  }
137
- className={segmentClasses}
93
+ style={[
94
+ styles.segment,
95
+ size === 'sm' && styles.segmentSm,
96
+ size === 'md' && styles.segmentMd,
97
+ size === 'lg' && styles.segmentLg,
98
+ isSelected && styles.segmentSelected,
99
+ isDisabled && styles.disabled,
100
+ ]}
138
101
  >
139
- <Text className={textClasses}>{option.label}</Text>
102
+ <Text
103
+ style={[
104
+ styles.text,
105
+ size === 'sm' && styles.textSm,
106
+ size === 'md' && styles.textMd,
107
+ size === 'lg' && styles.textLg,
108
+ isSelected ? styles.textSelected : styles.textUnselected,
109
+ ]}
110
+ >
111
+ {option.label}
112
+ </Text>
140
113
 
141
114
  {/* Badge */}
142
115
  {option.badge && (
143
116
  <View
144
- className={[
145
- sizes.badge,
146
- 'rounded-full',
147
- isSelected
148
- ? 'bg-green-100 dark:bg-green-900'
149
- : 'bg-gray-200 dark:bg-gray-700',
150
- ].join(' ')}
117
+ style={[
118
+ styles.badge,
119
+ size === 'sm' && styles.badgeSm,
120
+ size === 'md' && styles.badgeMd,
121
+ size === 'lg' && styles.badgeLg,
122
+ isSelected ? styles.badgeSelected : styles.badgeUnselected,
123
+ ]}
151
124
  >
152
125
  <Text
153
- className={[
154
- 'text-xs font-semibold',
126
+ style={[
127
+ styles.badgeText,
155
128
  isSelected
156
- ? 'text-green-700 dark:text-green-300'
157
- : 'text-gray-600 dark:text-gray-400',
158
- ].join(' ')}
129
+ ? styles.badgeTextSelected
130
+ : styles.badgeTextUnselected,
131
+ ]}
159
132
  >
160
133
  {option.badge}
161
134
  </Text>
@@ -219,3 +192,103 @@ export function PeriodSelector({
219
192
  }
220
193
 
221
194
  export default SegmentedControl;
195
+
196
+ const styles = StyleSheet.create({
197
+ container: {
198
+ flexDirection: 'row',
199
+ backgroundColor: '#f3f4f6',
200
+ borderRadius: 8,
201
+ padding: 4,
202
+ },
203
+ fullWidth: {
204
+ width: '100%',
205
+ },
206
+ disabled: {
207
+ opacity: 0.5,
208
+ },
209
+ containerSm: {
210
+ borderRadius: 8,
211
+ },
212
+ containerMd: {
213
+ borderRadius: 8,
214
+ },
215
+ containerLg: {
216
+ borderRadius: 12,
217
+ },
218
+ segment: {
219
+ flex: 1,
220
+ alignItems: 'center',
221
+ justifyContent: 'center',
222
+ flexDirection: 'row',
223
+ },
224
+ segmentSm: {
225
+ paddingHorizontal: 12,
226
+ paddingVertical: 6,
227
+ borderRadius: 6,
228
+ gap: 8,
229
+ },
230
+ segmentMd: {
231
+ paddingHorizontal: 16,
232
+ paddingVertical: 8,
233
+ borderRadius: 6,
234
+ gap: 8,
235
+ },
236
+ segmentLg: {
237
+ paddingHorizontal: 24,
238
+ paddingVertical: 12,
239
+ borderRadius: 8,
240
+ gap: 8,
241
+ },
242
+ segmentSelected: {
243
+ backgroundColor: '#ffffff',
244
+ },
245
+ text: {
246
+ fontWeight: '500',
247
+ },
248
+ textSm: {
249
+ fontSize: 12,
250
+ },
251
+ textMd: {
252
+ fontSize: 14,
253
+ },
254
+ textLg: {
255
+ fontSize: 16,
256
+ },
257
+ textSelected: {
258
+ color: '#111827',
259
+ },
260
+ textUnselected: {
261
+ color: '#4b5563',
262
+ },
263
+ badge: {
264
+ borderRadius: 999,
265
+ },
266
+ badgeSm: {
267
+ paddingHorizontal: 6,
268
+ paddingVertical: 2,
269
+ },
270
+ badgeMd: {
271
+ paddingHorizontal: 8,
272
+ paddingVertical: 2,
273
+ },
274
+ badgeLg: {
275
+ paddingHorizontal: 8,
276
+ paddingVertical: 4,
277
+ },
278
+ badgeSelected: {
279
+ backgroundColor: '#dcfce7',
280
+ },
281
+ badgeUnselected: {
282
+ backgroundColor: '#e5e7eb',
283
+ },
284
+ badgeText: {
285
+ fontSize: 12,
286
+ fontWeight: '600',
287
+ },
288
+ badgeTextSelected: {
289
+ color: '#15803d',
290
+ },
291
+ badgeTextUnselected: {
292
+ color: '#4b5563',
293
+ },
294
+ });