cpk-ui 0.5.5 → 0.7.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 (130) hide show
  1. package/README.md +80 -147
  2. package/components/modals/AlertDialog/AlertDialog.d.ts.map +1 -1
  3. package/components/modals/AlertDialog/AlertDialog.js +14 -7
  4. package/components/modals/Snackbar/Snackbar.d.ts.map +1 -1
  5. package/components/modals/Snackbar/Snackbar.js +20 -17
  6. package/components/uis/Accordion/AccordionItem.d.ts.map +1 -1
  7. package/components/uis/Accordion/AccordionItem.js +41 -17
  8. package/components/uis/Button/Button.d.ts.map +1 -1
  9. package/components/uis/Button/Button.js +10 -10
  10. package/components/uis/Card/Card.d.ts +2 -1
  11. package/components/uis/Card/Card.d.ts.map +1 -1
  12. package/components/uis/Card/Card.js +12 -3
  13. package/components/uis/Checkbox/Checkbox.d.ts.map +1 -1
  14. package/components/uis/Checkbox/Checkbox.js +1 -1
  15. package/components/uis/CustomPressable/CustomPressable.d.ts.map +1 -1
  16. package/components/uis/CustomPressable/CustomPressable.js +6 -6
  17. package/components/uis/EditText/EditText.d.ts.map +1 -1
  18. package/components/uis/EditText/EditText.js +17 -12
  19. package/components/uis/Fab/Fab.d.ts +2 -2
  20. package/components/uis/Fab/Fab.d.ts.map +1 -1
  21. package/components/uis/Fab/Fab.js +22 -4
  22. package/components/uis/Icon/Icon.d.ts.map +1 -1
  23. package/components/uis/Icon/Icon.js +6 -3
  24. package/components/uis/IconButton/IconButton.d.ts.map +1 -1
  25. package/components/uis/IconButton/IconButton.js +43 -41
  26. package/components/uis/LoadingIndicator/LoadingIndicator.d.ts +2 -1
  27. package/components/uis/LoadingIndicator/LoadingIndicator.d.ts.map +1 -1
  28. package/components/uis/LoadingIndicator/LoadingIndicator.js +4 -4
  29. package/components/uis/RadioGroup/RadioButton.d.ts.map +1 -1
  30. package/components/uis/RadioGroup/RadioButton.js +1 -1
  31. package/components/uis/RadioGroup/RadioGroup.d.ts.map +1 -1
  32. package/components/uis/RadioGroup/RadioGroup.js +16 -3
  33. package/components/uis/Rating/Rating.d.ts.map +1 -1
  34. package/components/uis/Rating/Rating.js +23 -19
  35. package/components/uis/SegmentedControl/SegmentedControl.d.ts.map +1 -1
  36. package/components/uis/SegmentedControl/SegmentedControl.js +1 -1
  37. package/components/uis/StatusbarBrightness/StatusBarBrightness.d.ts +2 -2
  38. package/components/uis/StatusbarBrightness/StatusBarBrightness.d.ts.map +1 -1
  39. package/components/uis/StatusbarBrightness/StatusBarBrightness.js +1 -1
  40. package/components/uis/SwitchToggle/SwitchToggle.d.ts.map +1 -1
  41. package/components/uis/SwitchToggle/SwitchToggle.js +1 -1
  42. package/hooks/useHoverState.d.ts +8 -0
  43. package/hooks/useHoverState.d.ts.map +1 -0
  44. package/hooks/useHoverState.js +16 -0
  45. package/package.json +18 -6
  46. package/providers/ThemeProvider.d.ts.map +1 -1
  47. package/providers/ThemeProvider.js +0 -1
  48. package/providers/index.d.ts.map +1 -1
  49. package/providers/index.js +3 -2
  50. package/components/uis/Icon/selection.json +0 -1
  51. package/src/components/common/ErrorBoundary/ErrorBoundary.tsx +0 -75
  52. package/src/components/modals/AlertDialog/AlertDialog.stories.tsx +0 -216
  53. package/src/components/modals/AlertDialog/AlertDialog.test.tsx +0 -251
  54. package/src/components/modals/AlertDialog/AlertDialog.tsx +0 -356
  55. package/src/components/modals/Snackbar/Snackbar.stories.tsx +0 -182
  56. package/src/components/modals/Snackbar/Snackbar.test.tsx +0 -319
  57. package/src/components/modals/Snackbar/Snackbar.tsx +0 -260
  58. package/src/components/modals/Snackbar/const.ts +0 -4
  59. package/src/components/uis/Accordion/Accordion.stories.tsx +0 -167
  60. package/src/components/uis/Accordion/Accordion.test.tsx +0 -272
  61. package/src/components/uis/Accordion/Accordion.tsx +0 -109
  62. package/src/components/uis/Accordion/AccordionItem.tsx +0 -306
  63. package/src/components/uis/Button/Button.stories.tsx +0 -218
  64. package/src/components/uis/Button/Button.test.tsx +0 -694
  65. package/src/components/uis/Button/Button.tsx +0 -440
  66. package/src/components/uis/Card/Card.test.tsx +0 -146
  67. package/src/components/uis/Card/Card.tsx +0 -102
  68. package/src/components/uis/Checkbox/Checkbox.stories.tsx +0 -216
  69. package/src/components/uis/Checkbox/Checkbox.test.tsx +0 -267
  70. package/src/components/uis/Checkbox/Checkbox.tsx +0 -225
  71. package/src/components/uis/CustomPressable/CustomPressable.tsx +0 -48
  72. package/src/components/uis/EditText/EditText.stories.tsx +0 -124
  73. package/src/components/uis/EditText/EditText.test.tsx +0 -477
  74. package/src/components/uis/EditText/EditText.tsx +0 -593
  75. package/src/components/uis/Fab/Fab.stories.tsx +0 -133
  76. package/src/components/uis/Fab/Fab.test.tsx +0 -110
  77. package/src/components/uis/Fab/Fab.tsx +0 -168
  78. package/src/components/uis/Hr/Hr.test.tsx +0 -26
  79. package/src/components/uis/Hr/Hr.tsx +0 -19
  80. package/src/components/uis/Icon/Icon.stories.tsx +0 -98
  81. package/src/components/uis/Icon/Icon.test.tsx +0 -49
  82. package/src/components/uis/Icon/Icon.tsx +0 -3819
  83. package/src/components/uis/IconButton/IconButton.test.tsx +0 -204
  84. package/src/components/uis/IconButton/IconButton.tsx +0 -279
  85. package/src/components/uis/LoadingIndicator/LoadingIndicator.tsx +0 -126
  86. package/src/components/uis/LoadingIndicator/LodingIndicator.stories.tsx +0 -81
  87. package/src/components/uis/PinchZoom/PinchZoom.stories.tsx +0 -266
  88. package/src/components/uis/PinchZoom/PinchZoom.test.tsx +0 -113
  89. package/src/components/uis/PinchZoom/PinchZoom.tsx +0 -424
  90. package/src/components/uis/RadioGroup/RadioButton.tsx +0 -193
  91. package/src/components/uis/RadioGroup/RadioGroup.stories.tsx +0 -188
  92. package/src/components/uis/RadioGroup/RadioGroup.test.tsx +0 -354
  93. package/src/components/uis/RadioGroup/RadioGroup.tsx +0 -109
  94. package/src/components/uis/Rating/Rating.test.tsx +0 -98
  95. package/src/components/uis/Rating/Rating.tsx +0 -200
  96. package/src/components/uis/SegmentedControl/SegmentedControl.stories.tsx +0 -546
  97. package/src/components/uis/SegmentedControl/SegmentedControl.test.tsx +0 -274
  98. package/src/components/uis/SegmentedControl/SegmentedControl.tsx +0 -232
  99. package/src/components/uis/StatusbarBrightness/StatusBarBrightness.test.tsx +0 -41
  100. package/src/components/uis/StatusbarBrightness/StatusBarBrightness.tsx +0 -26
  101. package/src/components/uis/Styled/StyledComponents.tsx +0 -217
  102. package/src/components/uis/SwitchToggle/SwitchToggle.stories.tsx +0 -75
  103. package/src/components/uis/SwitchToggle/SwitchToggle.test.tsx +0 -149
  104. package/src/components/uis/SwitchToggle/SwitchToggle.tsx +0 -309
  105. package/src/components/uis/Typography/Typography.stories.tsx +0 -149
  106. package/src/components/uis/Typography/Typography.test.tsx +0 -58
  107. package/src/components/uis/Typography/Typography.tsx +0 -386
  108. package/src/hooks/index.ts +0 -2
  109. package/src/hooks/useAnimations.ts +0 -71
  110. package/src/hooks/useDebouncedColorScheme.tsx +0 -30
  111. package/src/hooks/useOptimizedStyles.ts +0 -22
  112. package/src/hooks/usePerformance.ts +0 -93
  113. package/src/index.tsx +0 -38
  114. package/src/providers/ThemeProvider.tsx +0 -177
  115. package/src/providers/index.tsx +0 -130
  116. package/src/test/testUtils.tsx +0 -101
  117. package/src/types/common.ts +0 -77
  118. package/src/types/index.ts +0 -1
  119. package/src/types/kstyled.d.ts +0 -6
  120. package/src/utils/accessibility.ts +0 -110
  121. package/src/utils/colors.ts +0 -151
  122. package/src/utils/createCtx.tsx +0 -26
  123. package/src/utils/guards.ts +0 -93
  124. package/src/utils/index.ts +0 -2
  125. package/src/utils/performanceTest.ts +0 -174
  126. package/src/utils/platform.ts +0 -69
  127. package/src/utils/theme.ts +0 -38
  128. package/test/testUtils.d.ts +0 -113
  129. package/test/testUtils.d.ts.map +0 -1
  130. package/test/testUtils.js +0 -65
@@ -1,216 +0,0 @@
1
- import {type ComponentProps} from 'react';
2
- import {Text} from 'react-native';
3
- import {css} from 'kstyled';
4
- import type {Meta, StoryObj} from '@storybook/react';
5
-
6
- import {withThemeProvider} from '../../../../.storybook/decorators';
7
- import {Checkbox, CheckboxColor} from './Checkbox';
8
- import {Typography} from '../Typography/Typography';
9
-
10
- const colors: CheckboxColor[] = [
11
- 'primary',
12
- 'success',
13
- 'info',
14
- 'warning',
15
- 'danger',
16
- 'secondary',
17
- ];
18
-
19
- const meta = {
20
- title: 'Checkbox',
21
- component: (props) => <Checkbox {...props} />,
22
- parameters: {
23
- notes: `
24
- An animated Checkbox component with smooth transitions and flexible sizing options.
25
-
26
- ## Features
27
- - **Smooth Animations**: Spring-based fade and scale animations
28
- - **Flexible Sizing**: Preset sizes and custom numeric values
29
- - **Color Variants**: Multiple color options for different contexts
30
- - **Disabled State**: Can disable checkbox interaction
31
- - **Icon Elements**: Add elements before or after the checkbox
32
- - **Optimized Performance**: Memoized for better performance
33
-
34
- ## Size Options
35
- - \`small\`: 16px checkbox
36
- - \`medium\`: 20px checkbox (default)
37
- - \`large\`: 24px checkbox
38
- - Custom number: Any pixel value (e.g., \`size={28}\`)
39
-
40
- ## Animation Details
41
- The checkbox uses two simultaneous animations:
42
- - **Fade**: Opacity transition from 0 to 1
43
- - **Scale**: Size transition from 0.8 to 1.0
44
-
45
- ## Usage
46
-
47
- ### With String Text
48
- \`\`\`tsx
49
- <Checkbox
50
- checked={isChecked}
51
- onPress={() => setIsChecked(!isChecked)}
52
- size="medium"
53
- color="primary"
54
- text="Accept terms"
55
- direction="right"
56
- />
57
- \`\`\`
58
-
59
- ### With Custom Element
60
- \`\`\`tsx
61
- <Checkbox
62
- checked={isChecked}
63
- onPress={() => setIsChecked(!isChecked)}
64
- size="large"
65
- color="success"
66
- text={<CustomComponent />}
67
- direction="left"
68
- />
69
- \`\`\`
70
- `,
71
- docs: {
72
- description: {
73
- component: `
74
- An animated Checkbox component with smooth transitions and flexible sizing options.
75
-
76
- ## Features
77
- - **Smooth Animations**: Spring-based fade and scale animations
78
- - **Flexible Sizing**: Preset sizes and custom numeric values
79
- - **Color Variants**: Multiple color options for different contexts
80
- - **Disabled State**: Can disable checkbox interaction
81
- - **Icon Elements**: Add elements before or after the checkbox
82
- - **Optimized Performance**: Memoized for better performance
83
-
84
- ## Size Options
85
- - \`small\`: 16px checkbox
86
- - \`medium\`: 20px checkbox (default)
87
- - \`large\`: 24px checkbox
88
- - Custom number: Any pixel value (e.g., \`size={28}\`)
89
-
90
- ## Animation Details
91
- The checkbox uses two simultaneous animations:
92
- - **Fade**: Opacity transition from 0 to 1
93
- - **Scale**: Size transition from 0.8 to 1.0
94
-
95
- ## Usage
96
-
97
- ### With String Text
98
- \`\`\`tsx
99
- <Checkbox
100
- checked={isChecked}
101
- onPress={() => setIsChecked(!isChecked)}
102
- size="medium"
103
- color="primary"
104
- text="Accept terms"
105
- direction="right"
106
- />
107
- \`\`\`
108
-
109
- ### With Custom Element
110
- \`\`\`tsx
111
- <Checkbox
112
- checked={isChecked}
113
- onPress={() => setIsChecked(!isChecked)}
114
- size="large"
115
- color="success"
116
- text={<CustomComponent />}
117
- direction="left"
118
- />
119
- \`\`\`
120
- `,
121
- },
122
- },
123
- },
124
- argTypes: {
125
- color: {
126
- control: 'select',
127
- options: colors,
128
- description: 'Color variant of the checkbox',
129
- },
130
- size: {
131
- control: 'radio',
132
- options: ['small', 'medium', 'large', 16, 20, 24, 32],
133
- description: 'Checkbox size: "small" (16px), "medium" (20px), "large" (24px), or custom number in pixels',
134
- },
135
- checked: {
136
- defaultValue: false,
137
- type: 'boolean',
138
- description: 'Whether the checkbox is checked',
139
- },
140
- disabled: {
141
- description: 'Disables checkbox interaction',
142
- },
143
- direction: {
144
- control: 'radio',
145
- options: ['left', 'right'],
146
- description: 'Position of the text relative to the checkbox',
147
- },
148
- text: {
149
- description: 'Text or custom element to display next to the checkbox',
150
- },
151
- },
152
- decorators: [withThemeProvider],
153
- } satisfies Meta<typeof Checkbox>;
154
-
155
- export default meta;
156
-
157
- type Story = StoryObj<typeof meta>;
158
-
159
- export const Basic: Story = {
160
- args: {
161
- color: 'primary',
162
- size: 'medium',
163
- text: 'Click Checkbox!',
164
- direction: 'right',
165
- checked: false,
166
- onPress: () => {},
167
- },
168
- argTypes: {
169
- theme: {
170
- control: 'select',
171
- options: ['light', 'dark'],
172
- },
173
- },
174
- };
175
-
176
- export const WithLeftText: Story = {
177
- args: {
178
- color: 'primary',
179
- size: 'medium',
180
- text: 'Accept terms and conditions',
181
- direction: 'left',
182
- checked: false,
183
- onPress: () => {},
184
- },
185
- argTypes: {
186
- theme: {
187
- control: 'select',
188
- options: ['light', 'dark'],
189
- },
190
- },
191
- };
192
-
193
- export const WithCustomElement: Story = {
194
- args: {
195
- color: 'success',
196
- size: 'large',
197
- text: (
198
- <Typography.Body2
199
- style={css`
200
- font-weight: bold;
201
- `}
202
- >
203
- Custom Element
204
- </Typography.Body2>
205
- ),
206
- direction: 'right',
207
- checked: true,
208
- onPress: () => {},
209
- },
210
- argTypes: {
211
- theme: {
212
- control: 'select',
213
- options: ['light', 'dark'],
214
- },
215
- },
216
- };
@@ -1,267 +0,0 @@
1
- import React, {type ReactElement} from 'react';
2
- import {Text, View} from 'react-native';
3
- import type {RenderAPI} from '@testing-library/react-native';
4
- import {render} from '@testing-library/react-native';
5
-
6
- import {createComponent} from '../../../../test/testUtils';
7
- import {Checkbox, type CheckboxProps} from './Checkbox';
8
- import {light} from '../../../utils/colors';
9
-
10
- let testingLib: RenderAPI;
11
-
12
- const Component = (props?: CheckboxProps): ReactElement =>
13
- createComponent(<Checkbox {...props} />);
14
-
15
- describe('[Checkbox]', () => {
16
- it('should render without crashing', () => {
17
- testingLib = render(Component());
18
-
19
- const json = testingLib.toJSON();
20
-
21
- expect(json).toBeTruthy();
22
- });
23
-
24
- it('should render `disabled` button', () => {
25
- testingLib = render(
26
- Component({
27
- disabled: true,
28
- }),
29
- );
30
-
31
- const json = testingLib.toJSON();
32
-
33
- expect(json).toBeTruthy();
34
- });
35
-
36
- it('should render `startElement`', () => {
37
- testingLib = render(
38
- Component({
39
- startElement: <View />,
40
- }),
41
- );
42
-
43
- const json = testingLib.toJSON();
44
-
45
- expect(json).toBeTruthy();
46
- });
47
-
48
- it('should render `endElement`', () => {
49
- testingLib = render(
50
- Component({
51
- endElement: <View />,
52
- }),
53
- );
54
-
55
- const json = testingLib.toJSON();
56
-
57
- expect(json).toBeTruthy();
58
- });
59
-
60
- describe('colors', () => {
61
- const colors = [
62
- 'primary',
63
- 'secondary',
64
- 'success',
65
- 'info',
66
- 'warning',
67
- 'danger',
68
- ];
69
-
70
- it('should render all colors', () => {
71
- testingLib = render(
72
- createComponent(
73
- <View>
74
- {colors.map((color) => (
75
- <Checkbox
76
- key={color}
77
- checked={true}
78
- color={color as any}
79
- />
80
- ))}
81
- </View>,
82
- ),
83
- );
84
-
85
- const json = testingLib.toJSON();
86
- // $type is a transient prop used for styling only,
87
- // so it's not accessible via props in tests
88
- // Just verify the component renders correctly with all colors
89
- expect(json).toBeTruthy();
90
- });
91
-
92
- it('should render with specific color type and verify checked state', () => {
93
- testingLib = render(
94
- Component({
95
- color: 'success',
96
- checked: true,
97
- }),
98
- );
99
-
100
- const checkbox = testingLib.getByTestId('cpk-ui-checkbox');
101
-
102
- // While we can't directly test transient props ($type, $checked),
103
- // we can verify the component renders and has the testID
104
- expect(checkbox).toBeTruthy();
105
-
106
- // The checkbox wrapper receives $checked prop which affects its styling
107
- // We can verify it's rendered in checked state by checking the component structure
108
- expect(checkbox).toBeDefined();
109
- });
110
-
111
- it('should render unchecked state', () => {
112
- testingLib = render(
113
- Component({
114
- color: 'primary',
115
- checked: false,
116
- }),
117
- );
118
-
119
- const checkbox = testingLib.getByTestId('cpk-ui-checkbox');
120
- expect(checkbox).toBeTruthy();
121
- });
122
- });
123
-
124
- describe('sizes', () => {
125
- it('should render with small size', () => {
126
- testingLib = render(
127
- Component({
128
- size: 'small',
129
- checked: true,
130
- }),
131
- );
132
-
133
- const checkbox = testingLib.getByTestId('cpk-ui-checkbox');
134
- expect(checkbox).toBeTruthy();
135
- });
136
-
137
- it('should render with medium size', () => {
138
- testingLib = render(
139
- Component({
140
- size: 'medium',
141
- checked: true,
142
- }),
143
- );
144
-
145
- const checkbox = testingLib.getByTestId('cpk-ui-checkbox');
146
- expect(checkbox).toBeTruthy();
147
- });
148
-
149
- it('should render with large size', () => {
150
- testingLib = render(
151
- Component({
152
- size: 'large',
153
- checked: true,
154
- }),
155
- );
156
-
157
- const checkbox = testingLib.getByTestId('cpk-ui-checkbox');
158
- expect(checkbox).toBeTruthy();
159
- });
160
-
161
- it('should render with custom numeric size', () => {
162
- testingLib = render(
163
- Component({
164
- size: 24,
165
- checked: true,
166
- }),
167
- );
168
-
169
- const checkbox = testingLib.getByTestId('cpk-ui-checkbox');
170
- expect(checkbox).toBeTruthy();
171
- });
172
- });
173
-
174
- describe('accessibility', () => {
175
- it('should have accessibilityRole="checkbox"', () => {
176
- testingLib = render(
177
- Component({
178
- text: 'Accept terms',
179
- }),
180
- );
181
-
182
- const json = testingLib.toJSON();
183
- expect(json).toBeTruthy();
184
- // The root element should have accessibilityRole
185
- expect((json as any).props.accessibilityRole).toBe('checkbox');
186
- });
187
-
188
- it('should use text as default accessibilityLabel', () => {
189
- testingLib = render(
190
- Component({
191
- text: 'Accept terms',
192
- }),
193
- );
194
-
195
- const json = testingLib.toJSON();
196
- expect((json as any).props.accessibilityLabel).toBe('Accept terms');
197
- });
198
-
199
- it('should use custom accessibilityLabel when provided', () => {
200
- testingLib = render(
201
- Component({
202
- text: 'Accept',
203
- accessibilityLabel: 'Accept terms and conditions',
204
- }),
205
- );
206
-
207
- const json = testingLib.toJSON();
208
- expect((json as any).props.accessibilityLabel).toBe('Accept terms and conditions');
209
- });
210
-
211
- it('should have accessibilityState with checked=true when checked', () => {
212
- testingLib = render(
213
- Component({
214
- text: 'Accept terms',
215
- checked: true,
216
- }),
217
- );
218
-
219
- const json = testingLib.toJSON();
220
- expect((json as any).props.accessibilityState).toEqual({
221
- checked: true,
222
- disabled: false,
223
- });
224
- });
225
-
226
- it('should have accessibilityState with checked=false when unchecked', () => {
227
- testingLib = render(
228
- Component({
229
- text: 'Accept terms',
230
- checked: false,
231
- }),
232
- );
233
-
234
- const json = testingLib.toJSON();
235
- expect((json as any).props.accessibilityState).toEqual({
236
- checked: false,
237
- disabled: false,
238
- });
239
- });
240
-
241
- it('should have accessibilityState with disabled=true when disabled', () => {
242
- testingLib = render(
243
- Component({
244
- text: 'Accept terms',
245
- disabled: true,
246
- }),
247
- );
248
-
249
- const json = testingLib.toJSON();
250
- expect((json as any).props.accessibilityState).toEqual({
251
- checked: false,
252
- disabled: true,
253
- });
254
- });
255
-
256
- it('should have undefined accessibilityLabel when text is ReactElement', () => {
257
- testingLib = render(
258
- Component({
259
- text: <Text>Custom text</Text>,
260
- }),
261
- );
262
-
263
- const json = testingLib.toJSON();
264
- expect((json as any).props.accessibilityLabel).toBeUndefined();
265
- });
266
- });
267
- });
@@ -1,225 +0,0 @@
1
- import React, {useCallback, useEffect, useMemo, useRef, type ReactElement} from 'react';
2
- import type {StyleProp, TextStyle, ViewStyle} from 'react-native';
3
- import {Animated, Platform, TouchableOpacity, View} from 'react-native';
4
- import {styled, css} from 'kstyled';
5
-
6
- import {
7
- CheckboxWrapper,
8
- CheckboxWrapperOutlined,
9
- } from '../Styled/StyledComponents';
10
- import {Icon} from '../Icon/Icon';
11
- import {Typography} from '../Typography/Typography';
12
- import {useTheme} from '../../../providers/ThemeProvider';
13
-
14
- type Styles = {
15
- container?: StyleProp<ViewStyle>;
16
- checkbox?: StyleProp<ViewStyle>;
17
- check?: ViewStyle;
18
- text?: StyleProp<TextStyle>;
19
- };
20
-
21
- export type CheckboxColor =
22
- | 'primary'
23
- | 'secondary'
24
- | 'success'
25
- | 'danger'
26
- | 'warning'
27
- | 'info';
28
-
29
- export type CheckboxSizeType = 'small' | 'medium' | 'large' | number;
30
-
31
- export interface CheckboxProps {
32
- onPress?: () => void;
33
- style?: StyleProp<ViewStyle>;
34
- styles?: Styles;
35
- color?: CheckboxColor;
36
- size?: CheckboxSizeType;
37
- disabled?: boolean;
38
- checked?: boolean;
39
- text?: string | ReactElement;
40
- direction?: 'left' | 'right';
41
- accessibilityLabel?: string;
42
- }
43
-
44
- const Container = styled(TouchableOpacity)`
45
- flex-direction: row;
46
- align-items: center;
47
- `;
48
-
49
- const StyledCheckboxOutlined = styled(CheckboxWrapperOutlined)`
50
- border-width: 1px;
51
- margin: 0 6px;
52
-
53
- justify-content: center;
54
- align-items: center;
55
- `;
56
-
57
- // Create animated version for checkbox that needs animation
58
- const AnimatedView = Animated.createAnimatedComponent(View);
59
- const AnimatedCheckbox = styled(AnimatedView)`
60
- margin: 0 6px;
61
-
62
- justify-content: center;
63
- align-items: center;
64
- `;
65
-
66
- const StyledCheck = styled(Icon)<{$checked?: boolean}>`
67
- font-weight: bold;
68
- color: ${({theme, $checked}) => ($checked ? theme.bg.basic : 'transparent')};
69
- `;
70
-
71
- export function Checkbox({
72
- style,
73
- styles,
74
- text,
75
- direction = 'right',
76
- color = 'primary',
77
- size = 'medium',
78
- disabled = false,
79
- checked = false,
80
- onPress,
81
- accessibilityLabel,
82
- }: CheckboxProps): ReactElement {
83
- const checkboxSize = typeof size === 'number'
84
- ? size
85
- : size === 'small'
86
- ? 16
87
- : size === 'large'
88
- ? 24
89
- : 20;
90
-
91
- const textFontSize = typeof size === 'number'
92
- ? size * 0.7
93
- : size === 'small'
94
- ? 12
95
- : size === 'large'
96
- ? 16
97
- : 14;
98
- // Separate animated values for fade and scale
99
- const fadeAnim = useRef(new Animated.Value(checked ? 1 : 0)).current;
100
- const scaleAnim = useRef(new Animated.Value(checked ? 1 : 0.8)).current; // Start from 0.8, not 0
101
- const {theme} = useTheme();
102
-
103
- // Memoize animation config
104
- const animationConfig = useMemo(
105
- () => ({
106
- useNativeDriver: Platform.select({
107
- web: false,
108
- default: true,
109
- }),
110
- }),
111
- [],
112
- );
113
-
114
- useEffect(() => {
115
- Animated.parallel([
116
- Animated.spring(fadeAnim, {
117
- toValue: checked ? 1 : 0,
118
- ...animationConfig,
119
- }),
120
- Animated.spring(scaleAnim, {
121
- toValue: checked ? 1 : 0.8, // Scale to 0.8 when unchecked, not 0
122
- ...animationConfig,
123
- }),
124
- ]).start();
125
- }, [fadeAnim, scaleAnim, checked, animationConfig]);
126
-
127
- // Memoize container styles
128
- const containerStyles = useMemo(
129
- () => [
130
- css`
131
- flex: 1;
132
- padding: 6px 0;
133
-
134
- flex-direction: ${direction === 'left' ? 'row-reverse' : 'row'};
135
- column-gap: 2px;
136
- align-items: center;
137
- `,
138
- styles?.container,
139
- ],
140
- [styles?.container, direction],
141
- );
142
-
143
- // Memoize checkbox size styles
144
- const checkboxSizeStyles = useMemo(
145
- () => ({
146
- width: checkboxSize,
147
- height: checkboxSize,
148
- }),
149
- [checkboxSize],
150
- );
151
-
152
- // Memoize animated styles
153
- const animatedStyles = useMemo(
154
- () => [
155
- checkboxSizeStyles,
156
- styles?.checkbox,
157
- {
158
- opacity: fadeAnim,
159
- transform: [{scale: scaleAnim}],
160
- },
161
- ],
162
- [checkboxSizeStyles, styles?.checkbox, fadeAnim, scaleAnim],
163
- );
164
-
165
- // Memoize text styles
166
- const textStyles = useMemo(
167
- () => [
168
- css`
169
- font-size: ${textFontSize}px;
170
- `,
171
- styles?.text,
172
- ],
173
- [textFontSize, styles?.text],
174
- );
175
-
176
- // Render text element
177
- const TextElement = useMemo(() => {
178
- if (!text) return null;
179
-
180
- if (typeof text === 'string') {
181
- return (
182
- <Typography.Body2 style={textStyles}>
183
- {text}
184
- </Typography.Body2>
185
- );
186
- }
187
-
188
- return text;
189
- }, [text, textStyles]);
190
-
191
- return (
192
- <Container
193
- accessibilityLabel={accessibilityLabel ?? (typeof text === 'string' ? text : undefined)}
194
- accessibilityRole="checkbox"
195
- accessibilityState={{checked, disabled}}
196
- activeOpacity={0.9}
197
- disabled={disabled}
198
- onPress={onPress}
199
- style={style}
200
- >
201
- <View style={containerStyles}>
202
- <StyledCheckboxOutlined
203
- $checked={checked}
204
- $disabled={disabled}
205
- style={[checkboxSizeStyles, styles?.checkbox]}
206
- testID="cpk-ui-checkbox"
207
- $type={color}
208
- >
209
- <AnimatedCheckbox style={animatedStyles}>
210
- <StyledCheck
211
- $checked={checked}
212
- name="Check"
213
- size={checkboxSize * 0.7}
214
- style={styles?.check}
215
- />
216
- </AnimatedCheckbox>
217
- </StyledCheckboxOutlined>
218
- {TextElement}
219
- </View>
220
- </Container>
221
- );
222
- }
223
-
224
- // Export memoized component for better performance
225
- export default React.memo(Checkbox) as typeof Checkbox;