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,424 +0,0 @@
1
- import type {PropsWithChildren, Ref} from 'react';
2
- import React, {
3
- forwardRef,
4
- useEffect,
5
- useImperativeHandle,
6
- useRef,
7
- useState,
8
- } from 'react';
9
- import type {
10
- NativeMethods,
11
- NativeTouchEvent,
12
- PanResponderInstance,
13
- ViewStyle,
14
- } from 'react-native';
15
- import {Animated, PanResponder} from 'react-native';
16
-
17
- export type PinchZoomProps = PropsWithChildren<{
18
- /**
19
- * Custom view style.
20
- * @warning Passing `transform` in style will disable pinch-zoom functionality.
21
- * Use a wrapper View for custom transforms instead.
22
- */
23
- style?: ViewStyle;
24
- children?: any;
25
- /** Callback fired when zoom scale changes */
26
- onScaleChanged?(value: number): void;
27
- /** Callback fired when content position changes */
28
- onTranslateChanged?(valueXY: {x: number; y: number}): void;
29
- /** Callback fired after gesture animation completes (decay or snap-back) */
30
- onRelease?(): void;
31
- /**
32
- * Allow unrestricted overflow on specific axes.
33
- * When true, allows overflow. When false/undefined, clamps to bounds.
34
- */
35
- allowEmpty?: {x?: boolean; y?: boolean};
36
- /**
37
- * Auto-snap to bounds after release.
38
- * @default true
39
- */
40
- fixOverflowAfterRelease?: boolean;
41
- /** Test ID for component testing */
42
- testID?: string;
43
- }>;
44
-
45
- export interface PinchZoomRef {
46
- animatedValue: {scale: Animated.Value; translate: Animated.ValueXY};
47
- setValues(_: {scale?: number; translate?: {x: number; y: number}}): void;
48
- }
49
-
50
- type TouchePosition = Pick<
51
- NativeTouchEvent,
52
- 'locationX' | 'locationY' | 'pageX' | 'pageY'
53
- >;
54
-
55
- function getDistanceFromTouches(touches: NativeTouchEvent[]): number {
56
- const [touch1, touch2] = touches;
57
-
58
- return Math.sqrt(
59
- (touch1.pageX - touch2.pageX) ** 2 + (touch1.pageY - touch2.pageY) ** 2,
60
- );
61
- }
62
-
63
- function getRelativeTouchesCenterPosition(
64
- touches: NativeTouchEvent[],
65
- layout: {width: number; height: number; pageX: number; pageY: number},
66
- transformCache: {scale: number; translateX: number; translateY: number},
67
- ): TouchePosition {
68
- const pageX =
69
- (touches[0].pageX + touches[1].pageX) / 2 - layout.width / 2 - layout.pageX;
70
-
71
- const pageY =
72
- (touches[0].pageY + touches[1].pageY) / 2 -
73
- layout.height / 2 -
74
- layout.pageY;
75
-
76
- return {
77
- locationX: (pageX - transformCache.translateX) / transformCache.scale,
78
- locationY: (pageY - transformCache.translateY) / transformCache.scale,
79
- pageX,
80
- pageY,
81
- };
82
- }
83
-
84
- function PinchZoom(
85
- {
86
- style,
87
- children,
88
- onScaleChanged,
89
- onRelease,
90
- onTranslateChanged,
91
- allowEmpty,
92
- fixOverflowAfterRelease = true,
93
- testID = 'pinch-zoom-container',
94
- }: PinchZoomProps,
95
- ref: Ref<PinchZoomRef>,
96
- ): JSX.Element {
97
- const containerView = useRef<NativeMethods | null>(null);
98
- const scale = useRef(new Animated.Value(1)).current;
99
- const translate = useRef(new Animated.ValueXY({x: 0, y: 0})).current;
100
-
101
- const transformCache = useRef({
102
- scale: 1,
103
- translateX: 0,
104
- translateY: 0,
105
- }).current;
106
-
107
- const lastTransform = useRef({scale: 1, translateX: 0, translateY: 0});
108
- const initialDistance = useRef<number | undefined>(undefined);
109
- const initialTouchesCenter = useRef<TouchePosition | undefined>(undefined);
110
-
111
- type Layout = {
112
- width: number;
113
- height: number;
114
- pageX: number;
115
- pageY: number;
116
- };
117
-
118
- const layout = useRef<Layout | undefined>(undefined);
119
-
120
- const decayingTranslateAnimation = useRef<
121
- Animated.CompositeAnimation | undefined
122
- >(undefined);
123
- const isResponderActive = useRef(false);
124
- const movingVelocity = useRef<{x: number; y: number} | undefined>(undefined);
125
-
126
- containerView.current?.measure((x, y, width, height, pageX, pageY) => {
127
- layout.current = {width, height, pageX, pageY};
128
- });
129
-
130
- useEffect(() => {
131
- scale.addListener(({value}) => {
132
- transformCache.scale = value;
133
- onScaleChanged?.(value);
134
- });
135
-
136
- const id = translate.addListener(({x, y}) => {
137
- if (
138
- decayingTranslateAnimation.current &&
139
- layout.current &&
140
- !isResponderActive.current
141
- ) {
142
- const overflowX =
143
- !allowEmpty?.x &&
144
- Math.abs(x) > ((transformCache.scale - 1) * layout.current.width) / 2;
145
-
146
- const overflowY =
147
- !allowEmpty?.y &&
148
- Math.abs(y) >
149
- ((transformCache.scale - 1) * layout.current.height) / 2;
150
-
151
- if (overflowX || overflowY) {
152
- decayingTranslateAnimation.current?.stop();
153
- decayingTranslateAnimation.current = undefined;
154
-
155
- translate.setValue({
156
- x: overflowX
157
- ? (Math.sign(x) *
158
- (transformCache.scale - 1) *
159
- layout.current.width) /
160
- 2
161
- : x,
162
- y: overflowY
163
- ? (Math.sign(y) *
164
- (transformCache.scale - 1) *
165
- layout.current.height) /
166
- 2
167
- : y,
168
- });
169
- }
170
- }
171
-
172
- transformCache.translateX = x;
173
- transformCache.translateY = y;
174
- onTranslateChanged?.({x, y});
175
- });
176
-
177
- return () => {
178
- scale.removeAllListeners();
179
- translate.removeListener(id);
180
- };
181
- }, [
182
- onScaleChanged,
183
- onTranslateChanged,
184
- scale,
185
- transformCache,
186
- translate,
187
- allowEmpty?.x,
188
- allowEmpty?.y,
189
- ]);
190
-
191
- const [panResponder, setPanResponder] = useState<PanResponderInstance>();
192
-
193
- useEffect(() => {
194
- setPanResponder(
195
- PanResponder.create({
196
- onMoveShouldSetPanResponder: () => true,
197
- onPanResponderGrant: ({nativeEvent}) => {
198
- isResponderActive.current = true;
199
- movingVelocity.current = undefined;
200
-
201
- if (decayingTranslateAnimation.current) {
202
- decayingTranslateAnimation.current.stop();
203
- }
204
-
205
- const {touches} = nativeEvent;
206
-
207
- lastTransform.current = {...transformCache};
208
-
209
- initialDistance.current = undefined;
210
-
211
- if (layout.current != null) {
212
- if (touches.length === 2) {
213
- initialDistance.current = getDistanceFromTouches(touches);
214
-
215
- initialTouchesCenter.current = getRelativeTouchesCenterPosition(
216
- touches,
217
- layout.current,
218
- transformCache,
219
- );
220
- } else {
221
- initialDistance.current = undefined;
222
- }
223
- }
224
- },
225
- onPanResponderMove: ({nativeEvent}, gestureState) => {
226
- const {touches} = nativeEvent;
227
-
228
- if (layout.current == null) {
229
- return;
230
- }
231
-
232
- if (movingVelocity.current) {
233
- movingVelocity.current = {
234
- x: (movingVelocity.current.x + gestureState.vx) / 2,
235
- y: (movingVelocity.current.y + gestureState.vy) / 2,
236
- };
237
- } else {
238
- movingVelocity.current = {x: gestureState.vx, y: gestureState.vy};
239
- }
240
-
241
- if (touches.length === 2) {
242
- if (
243
- initialDistance.current &&
244
- initialTouchesCenter.current &&
245
- layout.current
246
- ) {
247
- const newScale = Math.max(
248
- 1,
249
- (getDistanceFromTouches(touches) / initialDistance.current) *
250
- lastTransform.current.scale,
251
- );
252
-
253
- const {pageX, pageY} = getRelativeTouchesCenterPosition(
254
- touches,
255
- layout.current,
256
- transformCache,
257
- );
258
-
259
- scale.setValue(newScale);
260
-
261
- const newTranslateX =
262
- pageX - initialTouchesCenter.current.locationX * newScale;
263
-
264
- const newTranslateY =
265
- pageY - initialTouchesCenter.current.locationY * newScale;
266
-
267
- translate.setValue({
268
- x: allowEmpty?.x
269
- ? newTranslateX
270
- : Math.min(
271
- Math.abs(newTranslateX),
272
- ((newScale - 1) * layout.current.width) / 2,
273
- ) * Math.sign(newTranslateX),
274
- y: allowEmpty?.y
275
- ? newTranslateY
276
- : Math.min(
277
- Math.abs(newTranslateY),
278
- ((newScale - 1) * layout.current.height) / 2,
279
- ) * Math.sign(newTranslateY),
280
- });
281
- } else {
282
- initialDistance.current = getDistanceFromTouches(touches);
283
-
284
- initialTouchesCenter.current = getRelativeTouchesCenterPosition(
285
- touches,
286
- layout.current,
287
- transformCache,
288
- );
289
- }
290
- } else if (touches.length === 1) {
291
- if (initialDistance.current) {
292
- return;
293
- }
294
-
295
- const newTranslateX =
296
- lastTransform.current.translateX + gestureState.dx;
297
-
298
- const newTranslateY =
299
- lastTransform.current.translateY + gestureState.dy;
300
-
301
- translate.setValue({
302
- x: newTranslateX,
303
- y: newTranslateY,
304
- });
305
- }
306
- },
307
- onPanResponderRelease: () => {
308
- isResponderActive.current = false;
309
-
310
- if (layout.current == null) {
311
- return;
312
- }
313
-
314
- const overflowX =
315
- !allowEmpty?.x &&
316
- Math.abs(transformCache.translateX) >
317
- ((transformCache.scale - 1) * layout.current.width) / 2;
318
-
319
- const overflowY =
320
- !allowEmpty?.y &&
321
- Math.abs(transformCache.translateY) >
322
- ((transformCache.scale - 1) * layout.current.height) / 2;
323
-
324
- if (overflowX || overflowY) {
325
- if (!fixOverflowAfterRelease) {
326
- onRelease?.();
327
-
328
- return;
329
- }
330
-
331
- decayingTranslateAnimation.current?.stop();
332
- decayingTranslateAnimation.current = undefined;
333
-
334
- const toValue = {
335
- x: overflowX
336
- ? (Math.sign(transformCache.translateX) *
337
- (transformCache.scale - 1) *
338
- layout.current.width) /
339
- 2
340
- : transformCache.translateX,
341
- y: overflowY
342
- ? (Math.sign(transformCache.translateY) *
343
- (transformCache.scale - 1) *
344
- layout.current.height) /
345
- 2
346
- : transformCache.translateY,
347
- };
348
-
349
- Animated.timing(translate, {
350
- toValue,
351
- duration: 100,
352
- useNativeDriver: true,
353
- }).start(() => {
354
- onRelease?.();
355
- });
356
- } else {
357
- decayingTranslateAnimation.current = Animated.decay(translate, {
358
- velocity: movingVelocity.current ?? {x: 0, y: 0},
359
- useNativeDriver: true,
360
- });
361
-
362
- decayingTranslateAnimation.current.start(() => {
363
- decayingTranslateAnimation.current = undefined;
364
- onRelease?.();
365
- });
366
- }
367
- },
368
- }),
369
- );
370
- }, [
371
- allowEmpty?.x,
372
- allowEmpty?.y,
373
- fixOverflowAfterRelease,
374
- onRelease,
375
- scale,
376
- transformCache,
377
- translate,
378
- ]);
379
-
380
- useImperativeHandle(ref, () => ({
381
- animatedValue: {scale, translate},
382
- setValues: (values) => {
383
- values.scale != null && scale.setValue(values.scale);
384
- values.translate != null && translate.setValue(values.translate);
385
- },
386
- }));
387
-
388
- // Warn if style.transform is provided, as it will disable pinch-zoom
389
- if (__DEV__ && style?.transform) {
390
- console.warn(
391
- 'PinchZoom: passing transform in style prop will disable pinch-zoom functionality. ' +
392
- 'Use a wrapper View for custom transforms instead.',
393
- );
394
- }
395
-
396
- return (
397
- <Animated.View
398
- // @ts-ignore - ref type issue with NativeMethods
399
- ref={(pinchViewRef: NativeMethods | null) => {
400
- containerView.current = pinchViewRef;
401
- }}
402
- style={[
403
- style,
404
- style?.transform
405
- ? {}
406
- : {
407
- transform: [
408
- {translateX: translate.x},
409
- {translateY: translate.y},
410
- {scale},
411
- ],
412
- },
413
- ]}
414
- testID={testID}
415
- {...(panResponder?.panHandlers || {})}
416
- >
417
- {children}
418
- </Animated.View>
419
- );
420
- }
421
-
422
- const PinchZoomRoot = forwardRef<PinchZoomRef, PinchZoomProps>(PinchZoom);
423
-
424
- export {PinchZoomRoot as PinchZoom};
@@ -1,193 +0,0 @@
1
- import React, {useCallback, useEffect, useMemo, useRef, useState, type ReactElement} from 'react';
2
- import type {
3
- LayoutRectangle,
4
- StyleProp,
5
- TextStyle,
6
- ViewStyle,
7
- } from 'react-native';
8
- import {Animated, Platform, TouchableOpacity, View} from 'react-native';
9
- import {styled, css} from 'kstyled';
10
-
11
- import {
12
- ColoredText,
13
- RadioButtonWrapper,
14
- RadioWrapper,
15
- } from '../Styled/StyledComponents';
16
-
17
- import type {RadioButtonType} from './RadioGroup';
18
-
19
- export type RadioButtonSizeType = 'small' | 'medium' | 'large' | number;
20
-
21
- export type RadioButtonStyles = {
22
- container?: StyleProp<ViewStyle>;
23
- label?: StyleProp<TextStyle>;
24
- circleWrapper?: StyleProp<ViewStyle>;
25
- circle?: StyleProp<ViewStyle>;
26
- };
27
-
28
- export type RadioButtonProps = {
29
- testID?: string;
30
- onPress?: () => void;
31
- label?: string;
32
- labelPosition?: 'left' | 'right';
33
- style?: StyleProp<ViewStyle>;
34
- styles?: RadioButtonStyles;
35
- type?: RadioButtonType;
36
- size?: RadioButtonSizeType;
37
- disabled?: boolean;
38
- selected?: boolean;
39
- endElement?: ReactElement;
40
- startElement?: ReactElement;
41
- accessibilityLabel?: string;
42
- };
43
-
44
- const Container = styled.TouchableOpacity`
45
- flex-direction: row;
46
- align-items: center;
47
- `;
48
-
49
- const StyledRadioCircle = Animated.createAnimatedComponent(RadioWrapper);
50
-
51
- export default function RadioButton({
52
- testID,
53
- style,
54
- styles,
55
- endElement,
56
- startElement,
57
- type = 'primary',
58
- size = 'medium',
59
- disabled = false,
60
- selected,
61
- onPress,
62
- label,
63
- labelPosition = 'right',
64
- accessibilityLabel,
65
- }: RadioButtonProps): ReactElement {
66
- const [innerLayout, setInnerLayout] = useState<LayoutRectangle>();
67
- const fadeAnim = useRef(new Animated.Value(selected ? 1 : 0)).current;
68
- const scaleAnim = useRef(new Animated.Value(selected ? 1 : 0)).current;
69
-
70
- // Memoize layout handler
71
- const handleLayout = useCallback((e: any) => {
72
- setInnerLayout(e.nativeEvent.layout);
73
- }, []);
74
-
75
- // Memoize animation config
76
- const animationConfig = useMemo(
77
- () => ({
78
- useNativeDriver: Platform.select({
79
- web: false,
80
- default: true,
81
- }),
82
- }),
83
- []
84
- );
85
-
86
- useEffect(() => {
87
- Animated.parallel([
88
- Animated.spring(fadeAnim, {
89
- toValue: !selected ? 0 : 1,
90
- ...animationConfig,
91
- }),
92
- Animated.spring(scaleAnim, {
93
- toValue: !selected ? 0 : 1,
94
- ...animationConfig,
95
- }),
96
- ]).start();
97
- }, [fadeAnim, scaleAnim, selected, animationConfig]);
98
-
99
- // Memoize container styles
100
- const containerStyles = useMemo(
101
- () => [
102
- css`
103
- padding-top: 6;
104
- padding-bottom: 6;
105
- padding-left: ${startElement || (label && labelPosition === 'left')
106
- ? 8
107
- : 0};
108
- padding-right: ${endElement || (label && labelPosition === 'right')
109
- ? 8
110
- : 0};
111
-
112
- flex-direction: row;
113
- align-items: center;
114
- `,
115
- styles?.container,
116
- ],
117
- [startElement, endElement, label, labelPosition, styles?.container]
118
- );
119
-
120
- // Memoize animated styles with margin and borderRadius
121
- const animatedStyles = useMemo(
122
- () => [
123
- styles?.circle,
124
- {
125
- margin: innerLayout ? 2 : 0,
126
- borderRadius: innerLayout ? innerLayout.width / 2 : 0,
127
- opacity: fadeAnim,
128
- transform: [{scale: scaleAnim}],
129
- },
130
- ],
131
- [innerLayout, styles?.circle, fadeAnim, scaleAnim]
132
- );
133
-
134
- return (
135
- <Container
136
- accessibilityLabel={accessibilityLabel ?? label}
137
- accessibilityRole="radio"
138
- accessibilityState={{selected, disabled}}
139
- activeOpacity={0.9}
140
- disabled={disabled}
141
- onPress={onPress}
142
- style={style}
143
- testID={testID}
144
- >
145
- <View style={containerStyles}>
146
- {startElement}
147
- {label && labelPosition === 'left' ? (
148
- <ColoredText
149
- $disabled={!!disabled}
150
- $selected={!!selected}
151
- $size={size}
152
- style={styles?.label}
153
- $type={type}
154
- >
155
- {label}
156
- </ColoredText>
157
- ) : null}
158
- <RadioButtonWrapper
159
- $disabled={disabled}
160
- $selected={!!selected}
161
- $size={size}
162
- style={styles?.circleWrapper}
163
- $type={type}
164
- >
165
- <StyledRadioCircle
166
- $disabled={!!disabled}
167
- onLayout={handleLayout}
168
- $selected={!!selected}
169
- style={animatedStyles}
170
- testID={`circle-${testID}`}
171
- $type={type}
172
- />
173
- </RadioButtonWrapper>
174
- {label && labelPosition === 'right' ? (
175
- <ColoredText
176
- $disabled={!!disabled}
177
- $selected={!!selected}
178
- $size={size}
179
- style={styles?.label}
180
- $type={type}
181
- >
182
- {label}
183
- </ColoredText>
184
- ) : null}
185
- {endElement}
186
- </View>
187
- </Container>
188
- );
189
- }
190
-
191
- // Export memoized component for better performance
192
- const MemoizedRadioButton = React.memo(RadioButton);
193
- export {MemoizedRadioButton as RadioButton};