@idealyst/components 1.0.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 (112) hide show
  1. package/README.md +568 -0
  2. package/package.json +107 -0
  3. package/plugin/web.js +186 -0
  4. package/src/Avatar/Avatar.native.tsx +44 -0
  5. package/src/Avatar/Avatar.styles.tsx +67 -0
  6. package/src/Avatar/Avatar.web.tsx +51 -0
  7. package/src/Avatar/index.native.ts +2 -0
  8. package/src/Avatar/index.ts +2 -0
  9. package/src/Avatar/index.web.ts +2 -0
  10. package/src/Avatar/types.ts +43 -0
  11. package/src/Badge/Badge.native.tsx +43 -0
  12. package/src/Badge/Badge.styles.tsx +154 -0
  13. package/src/Badge/Badge.web.tsx +45 -0
  14. package/src/Badge/index.native.ts +2 -0
  15. package/src/Badge/index.ts +2 -0
  16. package/src/Badge/index.web.ts +2 -0
  17. package/src/Badge/types.ts +34 -0
  18. package/src/Button/Button.native.tsx +39 -0
  19. package/src/Button/Button.styles.tsx +215 -0
  20. package/src/Button/Button.types.ts +12 -0
  21. package/src/Button/Button.web.tsx +56 -0
  22. package/src/Button/index.native.ts +3 -0
  23. package/src/Button/index.ts +5 -0
  24. package/src/Button/index.web.ts +3 -0
  25. package/src/Button/types.ts +49 -0
  26. package/src/Card/Card.native.tsx +52 -0
  27. package/src/Card/Card.styles.tsx +240 -0
  28. package/src/Card/Card.web.tsx +62 -0
  29. package/src/Card/index.native.ts +3 -0
  30. package/src/Card/index.ts +5 -0
  31. package/src/Card/index.web.ts +3 -0
  32. package/src/Card/types.ts +59 -0
  33. package/src/Checkbox/Checkbox.native.tsx +99 -0
  34. package/src/Checkbox/Checkbox.styles.tsx +292 -0
  35. package/src/Checkbox/Checkbox.web.tsx +131 -0
  36. package/src/Checkbox/index.native.ts +3 -0
  37. package/src/Checkbox/index.ts +5 -0
  38. package/src/Checkbox/index.web.ts +3 -0
  39. package/src/Checkbox/types.ts +79 -0
  40. package/src/Divider/Divider.native.tsx +145 -0
  41. package/src/Divider/Divider.styles.tsx +602 -0
  42. package/src/Divider/Divider.web.tsx +73 -0
  43. package/src/Divider/index.native.ts +3 -0
  44. package/src/Divider/index.ts +5 -0
  45. package/src/Divider/index.web.ts +3 -0
  46. package/src/Divider/types.ts +54 -0
  47. package/src/Icon/Icon.native.tsx +39 -0
  48. package/src/Icon/Icon.styles.tsx +50 -0
  49. package/src/Icon/Icon.web.tsx +47 -0
  50. package/src/Icon/icon-types.ts +7452 -0
  51. package/src/Icon/index.native.ts +3 -0
  52. package/src/Icon/index.ts +5 -0
  53. package/src/Icon/index.web.ts +3 -0
  54. package/src/Icon/types.ts +36 -0
  55. package/src/Input/Input.native.tsx +75 -0
  56. package/src/Input/Input.styles.tsx +177 -0
  57. package/src/Input/Input.web.tsx +71 -0
  58. package/src/Input/index.native.ts +3 -0
  59. package/src/Input/index.ts +5 -0
  60. package/src/Input/index.web.ts +3 -0
  61. package/src/Input/types.ts +69 -0
  62. package/src/Screen/Screen.native.tsx +41 -0
  63. package/src/Screen/Screen.styles.tsx +60 -0
  64. package/src/Screen/Screen.web.tsx +33 -0
  65. package/src/Screen/index.native.ts +2 -0
  66. package/src/Screen/index.ts +2 -0
  67. package/src/Screen/index.web.ts +2 -0
  68. package/src/Screen/types.ts +38 -0
  69. package/src/Text/Text.native.tsx +36 -0
  70. package/src/Text/Text.styles.tsx +67 -0
  71. package/src/Text/Text.web.tsx +41 -0
  72. package/src/Text/index.native.ts +3 -0
  73. package/src/Text/index.ts +5 -0
  74. package/src/Text/index.web.ts +3 -0
  75. package/src/Text/types.ts +39 -0
  76. package/src/View/View.native.tsx +56 -0
  77. package/src/View/View.styles.tsx +103 -0
  78. package/src/View/View.web.tsx +60 -0
  79. package/src/View/index.native.ts +3 -0
  80. package/src/View/index.ts +5 -0
  81. package/src/View/index.web.ts +3 -0
  82. package/src/View/types.ts +73 -0
  83. package/src/examples/AllExamples.tsx +72 -0
  84. package/src/examples/AvatarExamples.tsx +97 -0
  85. package/src/examples/BadgeExamples.tsx +200 -0
  86. package/src/examples/ButtonExamples.tsx +150 -0
  87. package/src/examples/CardExamples.tsx +176 -0
  88. package/src/examples/CheckboxExamples.tsx +217 -0
  89. package/src/examples/DividerExamples.tsx +218 -0
  90. package/src/examples/IconExamples.tsx +342 -0
  91. package/src/examples/InputExamples.tsx +134 -0
  92. package/src/examples/README.md +136 -0
  93. package/src/examples/ScreenExamples.tsx +154 -0
  94. package/src/examples/TextExamples.tsx +89 -0
  95. package/src/examples/ThemeExtensionExamples.tsx +91 -0
  96. package/src/examples/ValidationExamples.tsx +95 -0
  97. package/src/examples/ViewExamples.tsx +129 -0
  98. package/src/examples/extendedTheme.ts +331 -0
  99. package/src/examples/index.ts +15 -0
  100. package/src/index.native.ts +52 -0
  101. package/src/index.ts +48 -0
  102. package/src/theme/breakpoints.ts +8 -0
  103. package/src/theme/colorResolver.ts +218 -0
  104. package/src/theme/colors.ts +315 -0
  105. package/src/theme/defaultThemes.ts +326 -0
  106. package/src/theme/index.ts +188 -0
  107. package/src/theme/themeBuilder.ts +602 -0
  108. package/src/theme/unistyles.d.ts +6 -0
  109. package/src/theme/variantHelpers.ts +584 -0
  110. package/src/theme/variants.ts +56 -0
  111. package/src/unistyles.d.ts +108 -0
  112. package/src/unistyles.ts +43 -0
@@ -0,0 +1,62 @@
1
+ import React from 'react';
2
+ import { getWebProps } from 'react-native-unistyles/web';
3
+ import { CardProps } from './types';
4
+ import { cardStyles, cardHoverStyles } from './Card.styles';
5
+
6
+ const Card: React.FC<CardProps> = ({
7
+ children,
8
+ variant = 'default',
9
+ padding = 'medium',
10
+ radius = 'medium',
11
+ intent = 'neutral',
12
+ clickable = false,
13
+ onPress,
14
+ disabled = false,
15
+ style,
16
+ testID,
17
+ accessibilityLabel,
18
+ }) => {
19
+ const handleClick = () => {
20
+ if (!disabled && clickable && onPress) {
21
+ onPress();
22
+ }
23
+ };
24
+
25
+ // Apply variants
26
+ cardStyles.useVariants({
27
+ variant: variant as any,
28
+ padding,
29
+ radius,
30
+ intent,
31
+ clickable,
32
+ disabled,
33
+ });
34
+
35
+ // Create style arrays
36
+ const cardStyleArray = [
37
+ cardStyles.card,
38
+ clickable && !disabled && cardHoverStyles.clickableHover,
39
+ style,
40
+ ].filter(Boolean);
41
+
42
+ // Generate web props
43
+ const webProps = getWebProps(cardStyleArray);
44
+
45
+ // Use appropriate HTML element based on clickable state
46
+ const Component = clickable ? 'button' : 'div';
47
+
48
+ return (
49
+ <Component
50
+ {...webProps}
51
+ onClick={clickable ? handleClick : undefined}
52
+ disabled={clickable && disabled}
53
+ data-testid={testID}
54
+ aria-label={accessibilityLabel}
55
+ role={clickable ? 'button' : undefined}
56
+ >
57
+ {children}
58
+ </Component>
59
+ );
60
+ };
61
+
62
+ export default Card;
@@ -0,0 +1,3 @@
1
+ // React Native-specific Card export
2
+ export { default } from './Card.native';
3
+ export * from './types';
@@ -0,0 +1,5 @@
1
+ // Platform-agnostic Card export
2
+ // Metro will resolve to index.native.ts for React Native
3
+ // This file serves as fallback for web environments
4
+ export { default } from './Card.web';
5
+ export * from './types';
@@ -0,0 +1,3 @@
1
+ // Web-specific Card export
2
+ export { default } from './Card.web';
3
+ export * from './types';
@@ -0,0 +1,59 @@
1
+ import { ReactNode } from 'react';
2
+ import type { IntentVariant } from '../theme/variants';
3
+
4
+ export interface CardProps {
5
+ /**
6
+ * The content to display inside the card
7
+ */
8
+ children?: ReactNode;
9
+
10
+ /**
11
+ * The visual style variant of the card
12
+ */
13
+ variant?: 'default' | 'outlined' | 'elevated' | 'filled';
14
+
15
+ /**
16
+ * The padding size inside the card
17
+ */
18
+ padding?: 'none' | 'small' | 'medium' | 'large';
19
+
20
+ /**
21
+ * The border radius of the card
22
+ */
23
+ radius?: 'none' | 'small' | 'medium' | 'large';
24
+
25
+ /**
26
+ * The intent/color scheme of the card
27
+ */
28
+ intent?: IntentVariant;
29
+
30
+ /**
31
+ * Whether the card is clickable
32
+ */
33
+ clickable?: boolean;
34
+
35
+ /**
36
+ * Called when the card is pressed (if clickable)
37
+ */
38
+ onPress?: () => void;
39
+
40
+ /**
41
+ * Whether the card is disabled
42
+ */
43
+ disabled?: boolean;
44
+
45
+ /**
46
+ * Additional styles (platform-specific)
47
+ */
48
+ style?: any;
49
+
50
+ /**
51
+ * Test ID for testing
52
+ */
53
+ testID?: string;
54
+
55
+ /**
56
+ * Accessibility label
57
+ */
58
+ accessibilityLabel?: string;
59
+ }
@@ -0,0 +1,99 @@
1
+ import React, { useState, useEffect } from 'react';
2
+ import { View, Text, Pressable } from 'react-native';
3
+ import { CheckboxProps } from './types';
4
+ import { checkboxStyles, checkboxLabelStyles, checkboxCheckmarkStyles, checkboxHelperStyles } from './Checkbox.styles';
5
+
6
+ const Checkbox: React.FC<CheckboxProps> = ({
7
+ checked = false,
8
+ indeterminate = false,
9
+ disabled = false,
10
+ onCheckedChange,
11
+ size = 'medium',
12
+ intent = 'primary',
13
+ variant = 'default',
14
+ label,
15
+ children,
16
+ style,
17
+ testID,
18
+ accessibilityLabel,
19
+ required = false,
20
+ error,
21
+ helperText,
22
+ }) => {
23
+ const [internalChecked, setInternalChecked] = useState(checked);
24
+
25
+ useEffect(() => {
26
+ setInternalChecked(checked);
27
+ }, [checked]);
28
+
29
+ const handlePress = () => {
30
+ if (disabled) return;
31
+
32
+ const newChecked = !internalChecked;
33
+ setInternalChecked(newChecked);
34
+ onCheckedChange?.(newChecked);
35
+ };
36
+
37
+ // Apply variants for main checkbox
38
+ checkboxStyles.useVariants({
39
+ size,
40
+ intent,
41
+ variant: variant as any,
42
+ checked: internalChecked,
43
+ disabled,
44
+ });
45
+
46
+ // Apply variants for label
47
+ checkboxLabelStyles.useVariants({
48
+ size,
49
+ disabled,
50
+ });
51
+
52
+ // Apply variants for checkmark
53
+ checkboxCheckmarkStyles.useVariants({
54
+ size,
55
+ visible: internalChecked,
56
+ });
57
+
58
+ // Apply variants for helper text
59
+ checkboxHelperStyles.useVariants({
60
+ error: !!error,
61
+ });
62
+
63
+ const labelContent = children || label;
64
+ const displayHelperText = error || helperText;
65
+
66
+ return (
67
+ <View style={[checkboxStyles.wrapper, style]}>
68
+ <Pressable
69
+ onPress={handlePress}
70
+ disabled={disabled}
71
+ testID={testID}
72
+ accessibilityLabel={accessibilityLabel}
73
+ accessibilityRole="checkbox"
74
+ accessibilityState={{ checked: internalChecked }}
75
+ style={checkboxStyles.container}
76
+ >
77
+ <View style={checkboxStyles.checkbox}>
78
+ {(internalChecked || indeterminate) && (
79
+ <Text style={checkboxCheckmarkStyles.checkmark}>
80
+ {indeterminate ? '−' : '✓'}
81
+ </Text>
82
+ )}
83
+ </View>
84
+ {labelContent && (
85
+ <Text style={checkboxLabelStyles.label}>
86
+ {labelContent}
87
+ </Text>
88
+ )}
89
+ </Pressable>
90
+ {displayHelperText && (
91
+ <Text style={checkboxHelperStyles.helperText}>
92
+ {error || helperText}
93
+ </Text>
94
+ )}
95
+ </View>
96
+ );
97
+ };
98
+
99
+ export default Checkbox;
@@ -0,0 +1,292 @@
1
+ import { StyleSheet } from 'react-native-unistyles';
2
+
3
+ export const checkboxStyles = StyleSheet.create((theme) => ({
4
+ wrapper: {
5
+ flexDirection: 'column',
6
+ gap: theme.spacing?.xs || 4,
7
+
8
+ // Web-specific styles
9
+ _web: {
10
+ display: 'flex',
11
+ flexDirection: 'column',
12
+ alignItems: 'flex-start',
13
+ width: 'auto',
14
+ },
15
+ },
16
+
17
+ container: {
18
+ flexDirection: 'row',
19
+ alignItems: 'center',
20
+ gap: theme.spacing?.sm || 8,
21
+
22
+ // Web-specific styles for proper layout
23
+ _web: {
24
+ display: 'flex',
25
+ flexDirection: 'row',
26
+ alignItems: 'center',
27
+ gap: theme.spacing?.sm || 8,
28
+ width: 'fit-content',
29
+ cursor: 'pointer',
30
+ },
31
+ },
32
+
33
+ checkbox: {
34
+ alignItems: 'center',
35
+ justifyContent: 'center',
36
+ borderRadius: theme.borderRadius?.sm || 4,
37
+ position: 'relative',
38
+ transition: 'all 0.2s ease',
39
+
40
+ variants: {
41
+ size: {
42
+ small: {
43
+ width: 16,
44
+ height: 16,
45
+ },
46
+ medium: {
47
+ width: 20,
48
+ height: 20,
49
+ },
50
+ large: {
51
+ width: 24,
52
+ height: 24,
53
+ },
54
+ },
55
+ intent: {
56
+ primary: {
57
+ backgroundColor: 'transparent',
58
+ borderColor: theme.colors?.border?.primary || theme.palettes?.gray?.[300] || '#d1d5db',
59
+ },
60
+ success: {
61
+ backgroundColor: 'transparent',
62
+ borderColor: theme.colors?.border?.primary || theme.palettes?.gray?.[300] || '#d1d5db',
63
+ },
64
+ error: {
65
+ backgroundColor: 'transparent',
66
+ borderColor: theme.colors?.border?.primary || theme.palettes?.gray?.[300] || '#d1d5db',
67
+ },
68
+ warning: {
69
+ backgroundColor: 'transparent',
70
+ borderColor: theme.colors?.border?.primary || theme.palettes?.gray?.[300] || '#d1d5db',
71
+ },
72
+ neutral: {
73
+ backgroundColor: 'transparent',
74
+ borderColor: theme.colors?.border?.primary || theme.palettes?.gray?.[300] || '#d1d5db',
75
+ },
76
+ info: {
77
+ backgroundColor: 'transparent',
78
+ borderColor: theme.colors?.border?.primary || theme.palettes?.gray?.[300] || '#d1d5db',
79
+ },
80
+ },
81
+ variant: {
82
+ default: {
83
+ // React Native border properties
84
+ borderWidth: 1,
85
+ borderColor: theme.colors?.border?.primary || theme.palettes?.gray?.[300] || '#d1d5db',
86
+ // Web-specific border override
87
+ _web: {
88
+ border: `1px solid ${theme.colors?.border?.primary || theme.palettes?.gray?.[300] || '#d1d5db'}`,
89
+ },
90
+ },
91
+ outlined: {
92
+ // React Native border properties
93
+ borderWidth: 2,
94
+ borderColor: theme.colors?.border?.primary || theme.palettes?.gray?.[300] || '#d1d5db',
95
+ // Web-specific border override
96
+ _web: {
97
+ border: `2px solid ${theme.colors?.border?.primary || theme.palettes?.gray?.[300] || '#d1d5db'}`,
98
+ },
99
+ },
100
+ },
101
+ checked: {
102
+ true: {
103
+ // Checked state handled by compound variants
104
+ },
105
+ false: {
106
+ backgroundColor: 'transparent',
107
+ },
108
+ },
109
+ disabled: {
110
+ true: {
111
+ opacity: 0.5,
112
+ },
113
+ false: {
114
+ opacity: 1,
115
+ },
116
+ },
117
+ },
118
+
119
+ compoundVariants: [
120
+ // Checked state for each intent
121
+ {
122
+ checked: true,
123
+ intent: 'primary',
124
+ styles: {
125
+ backgroundColor: theme.intents?.primary?.main || '#3b82f6',
126
+ borderColor: theme.intents?.primary?.main || '#3b82f6',
127
+ _web: {
128
+ border: `1px solid ${theme.intents?.primary?.main || '#3b82f6'}`,
129
+ },
130
+ },
131
+ },
132
+ {
133
+ checked: true,
134
+ intent: 'success',
135
+ styles: {
136
+ backgroundColor: theme.intents?.success?.main || '#22c55e',
137
+ borderColor: theme.intents?.success?.main || '#22c55e',
138
+ _web: {
139
+ border: `1px solid ${theme.intents?.success?.main || '#22c55e'}`,
140
+ },
141
+ },
142
+ },
143
+ {
144
+ checked: true,
145
+ intent: 'error',
146
+ styles: {
147
+ backgroundColor: theme.intents?.error?.main || '#ef4444',
148
+ borderColor: theme.intents?.error?.main || '#ef4444',
149
+ _web: {
150
+ border: `1px solid ${theme.intents?.error?.main || '#ef4444'}`,
151
+ },
152
+ },
153
+ },
154
+ {
155
+ checked: true,
156
+ intent: 'warning',
157
+ styles: {
158
+ backgroundColor: theme.intents?.warning?.main || '#f59e0b',
159
+ borderColor: theme.intents?.warning?.main || '#f59e0b',
160
+ _web: {
161
+ border: `1px solid ${theme.intents?.warning?.main || '#f59e0b'}`,
162
+ },
163
+ },
164
+ },
165
+ {
166
+ checked: true,
167
+ intent: 'neutral',
168
+ styles: {
169
+ backgroundColor: theme.intents?.neutral?.main || '#6b7280',
170
+ borderColor: theme.intents?.neutral?.main || '#6b7280',
171
+ _web: {
172
+ border: `1px solid ${theme.intents?.neutral?.main || '#6b7280'}`,
173
+ },
174
+ },
175
+ },
176
+ {
177
+ checked: true,
178
+ intent: 'info',
179
+ styles: {
180
+ backgroundColor: theme.intents?.info?.main || '#06b6d4',
181
+ borderColor: theme.intents?.info?.main || '#06b6d4',
182
+ _web: {
183
+ border: `1px solid ${theme.intents?.info?.main || '#06b6d4'}`,
184
+ },
185
+ },
186
+ },
187
+ ],
188
+
189
+ _web: {
190
+ cursor: 'pointer',
191
+ outline: 'none',
192
+ display: 'flex',
193
+ boxSizing: 'border-box',
194
+ userSelect: 'none',
195
+ WebkitAppearance: 'none',
196
+ MozAppearance: 'none',
197
+ appearance: 'none',
198
+ _hover: {
199
+ opacity: 0.8,
200
+ },
201
+ _focus: {
202
+ outline: `2px solid ${theme.intents?.primary?.main || '#3b82f6'}`,
203
+ outlineOffset: '2px',
204
+ },
205
+ },
206
+ },
207
+ }));
208
+
209
+ export const checkboxLabelStyles = StyleSheet.create((theme) => ({
210
+ label: {
211
+ color: theme.colors?.text?.primary || theme.palettes?.gray?.[900] || '#111827',
212
+
213
+ // Web-specific styles to prevent centering issues
214
+ _web: {
215
+ display: 'block',
216
+ textAlign: 'left',
217
+ margin: 0,
218
+ padding: 0,
219
+ },
220
+
221
+ variants: {
222
+ size: {
223
+ small: {
224
+ fontSize: theme.typography?.fontSize?.sm || 14,
225
+ },
226
+ medium: {
227
+ fontSize: theme.typography?.fontSize?.md || 16,
228
+ },
229
+ large: {
230
+ fontSize: theme.typography?.fontSize?.lg || 18,
231
+ },
232
+ },
233
+ disabled: {
234
+ true: {
235
+ color: theme.colors?.text?.disabled || theme.palettes?.gray?.[400] || '#9ca3af',
236
+ },
237
+ false: {
238
+ color: theme.colors?.text?.primary || theme.palettes?.gray?.[900] || '#111827',
239
+ },
240
+ },
241
+ },
242
+ },
243
+ }));
244
+
245
+ export const checkboxCheckmarkStyles = StyleSheet.create((theme) => ({
246
+ checkmark: {
247
+ position: 'absolute',
248
+ color: '#ffffff',
249
+ fontWeight: 'bold',
250
+
251
+ variants: {
252
+ size: {
253
+ small: {
254
+ fontSize: 10,
255
+ },
256
+ medium: {
257
+ fontSize: 12,
258
+ },
259
+ large: {
260
+ fontSize: 14,
261
+ },
262
+ },
263
+ visible: {
264
+ true: {
265
+ opacity: 1,
266
+ },
267
+ false: {
268
+ opacity: 0,
269
+ },
270
+ },
271
+ },
272
+ },
273
+ }));
274
+
275
+ export const checkboxHelperStyles = StyleSheet.create((theme) => ({
276
+ helperText: {
277
+ fontSize: theme.typography?.fontSize?.sm || 14,
278
+ color: theme.colors?.text?.secondary || theme.palettes?.gray?.[600] || '#4b5563',
279
+ marginTop: 2, // Reduced spacing between checkbox and helper text
280
+
281
+ variants: {
282
+ error: {
283
+ true: {
284
+ color: theme.intents?.error?.main || '#ef4444',
285
+ },
286
+ false: {
287
+ color: theme.colors?.text?.secondary || theme.palettes?.gray?.[600] || '#4b5563',
288
+ },
289
+ },
290
+ },
291
+ },
292
+ }));
@@ -0,0 +1,131 @@
1
+ import React, { useState, useEffect } from 'react';
2
+ import { getWebProps } from 'react-native-unistyles/web';
3
+ import { CheckboxProps } from './types';
4
+ import { checkboxStyles, checkboxLabelStyles, checkboxCheckmarkStyles, checkboxHelperStyles } from './Checkbox.styles';
5
+
6
+ const Checkbox: React.FC<CheckboxProps> = ({
7
+ checked = false,
8
+ indeterminate = false,
9
+ disabled = false,
10
+ onCheckedChange,
11
+ size = 'medium',
12
+ intent = 'primary',
13
+ variant = 'default',
14
+ label,
15
+ children,
16
+ style,
17
+ testID,
18
+ accessibilityLabel,
19
+ required = false,
20
+ error,
21
+ helperText,
22
+ }) => {
23
+ const [internalChecked, setInternalChecked] = useState(checked);
24
+
25
+ useEffect(() => {
26
+ setInternalChecked(checked);
27
+ }, [checked]);
28
+
29
+ const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
30
+ if (disabled) return;
31
+
32
+ const newChecked = event.target.checked;
33
+ setInternalChecked(newChecked);
34
+ onCheckedChange?.(newChecked);
35
+ };
36
+
37
+ // Apply variants for main checkbox
38
+ checkboxStyles.useVariants({
39
+ size,
40
+ intent,
41
+ variant: variant as any,
42
+ checked: internalChecked,
43
+ disabled,
44
+ });
45
+
46
+ // Apply variants for label
47
+ checkboxLabelStyles.useVariants({
48
+ size,
49
+ disabled,
50
+ });
51
+
52
+ // Apply variants for checkmark
53
+ checkboxCheckmarkStyles.useVariants({
54
+ size,
55
+ visible: internalChecked,
56
+ });
57
+
58
+ // Apply variants for helper text
59
+ checkboxHelperStyles.useVariants({
60
+ error: !!error,
61
+ });
62
+
63
+ // Create style arrays
64
+ const wrapperStyleArray = [checkboxStyles.wrapper, style];
65
+ const containerStyleArray = [checkboxStyles.container];
66
+ const checkboxStyleArray = [checkboxStyles.checkbox];
67
+ const labelStyleArray = [checkboxLabelStyles.label];
68
+ const helperTextStyleArray = [checkboxHelperStyles.helperText];
69
+ const checkmarkStyleArray = [checkboxCheckmarkStyles.checkmark];
70
+
71
+ // Generate web props
72
+ const wrapperProps = getWebProps(wrapperStyleArray);
73
+ const containerProps = getWebProps(containerStyleArray);
74
+ const checkboxProps = getWebProps(checkboxStyleArray);
75
+ const labelProps = getWebProps(labelStyleArray);
76
+ const helperTextProps = getWebProps(helperTextStyleArray);
77
+ const checkmarkProps = getWebProps(checkmarkStyleArray);
78
+
79
+ const labelContent = children || label;
80
+ const displayHelperText = error || helperText;
81
+
82
+ return (
83
+ <div {...wrapperProps}>
84
+ <label {...containerProps}>
85
+ <div style={{ position: 'relative' }}>
86
+ <input
87
+ type="checkbox"
88
+ checked={internalChecked}
89
+ onChange={handleChange}
90
+ disabled={disabled}
91
+ required={required}
92
+ data-testid={testID}
93
+ aria-label={accessibilityLabel}
94
+ ref={(ref) => {
95
+ if (ref) {
96
+ ref.indeterminate = indeterminate;
97
+ }
98
+ }}
99
+ style={{
100
+ position: 'absolute',
101
+ opacity: 0,
102
+ width: '100%',
103
+ height: '100%',
104
+ margin: 0,
105
+ cursor: disabled ? 'not-allowed' : 'pointer',
106
+ }}
107
+ />
108
+ <div {...checkboxProps}>
109
+ {(internalChecked || indeterminate) && (
110
+ <div {...checkmarkProps}>
111
+ {indeterminate ? '−' : '✓'}
112
+ </div>
113
+ )}
114
+ </div>
115
+ </div>
116
+ {labelContent && (
117
+ <span {...labelProps}>
118
+ {labelContent}
119
+ </span>
120
+ )}
121
+ </label>
122
+ {displayHelperText && (
123
+ <div {...helperTextProps}>
124
+ {error || helperText}
125
+ </div>
126
+ )}
127
+ </div>
128
+ );
129
+ };
130
+
131
+ export default Checkbox;
@@ -0,0 +1,3 @@
1
+ // React Native-specific Checkbox export
2
+ export { default } from './Checkbox.native';
3
+ export * from './types';
@@ -0,0 +1,5 @@
1
+ // Platform-agnostic Checkbox export
2
+ // Metro will resolve to index.native.ts for React Native
3
+ // This file serves as fallback for web environments
4
+ export { default } from './Checkbox.web';
5
+ export * from './types';
@@ -0,0 +1,3 @@
1
+ // Web-specific Checkbox export
2
+ export { default } from './Checkbox.web';
3
+ export * from './types';