react-native-molecules 0.5.0-beta.3 → 0.5.0-beta.31

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 (227) hide show
  1. package/components/Accordion/Accordion.tsx +2 -6
  2. package/components/Accordion/AccordionItem.tsx +16 -12
  3. package/components/Accordion/AccordionItemContent.tsx +6 -1
  4. package/components/Accordion/AccordionItemHeader.tsx +1 -1
  5. package/components/Accordion/utils.ts +6 -0
  6. package/components/ActivityIndicator/ActivityIndicator.tsx +6 -15
  7. package/components/Appbar/AppbarBase.tsx +18 -13
  8. package/components/Button/Button.tsx +211 -264
  9. package/components/Button/index.tsx +9 -3
  10. package/components/Button/types.ts +16 -2
  11. package/components/Button/utils.ts +230 -208
  12. package/components/Card/Card.tsx +1 -1
  13. package/components/Checkbox/Checkbox.tsx +125 -88
  14. package/components/Checkbox/CheckboxBase.ios.tsx +14 -23
  15. package/components/Checkbox/CheckboxBase.tsx +21 -137
  16. package/components/Checkbox/context.tsx +14 -0
  17. package/components/Checkbox/index.tsx +11 -4
  18. package/components/Checkbox/types.ts +63 -29
  19. package/components/Checkbox/utils.ts +25 -108
  20. package/components/Chip/Chip.tsx +41 -52
  21. package/components/Chip/utils.ts +3 -7
  22. package/components/DateField/DateField.tsx +111 -0
  23. package/components/DateField/index.tsx +6 -0
  24. package/components/{DatePickerInput/inputUtils.ts → DateField/useDateFieldState.ts} +19 -51
  25. package/components/DatePicker/DateCalendar.tsx +83 -0
  26. package/components/DatePicker/DatePickerActions.tsx +73 -0
  27. package/components/DatePicker/DatePickerModal.tsx +246 -0
  28. package/components/DatePicker/DatePickerPopover.tsx +79 -0
  29. package/components/DatePicker/DatePickerProvider.tsx +158 -0
  30. package/components/DatePicker/DatePickerTrigger.tsx +23 -0
  31. package/components/DatePicker/context.tsx +83 -0
  32. package/components/DatePicker/index.tsx +45 -0
  33. package/components/DatePicker/utils.ts +295 -0
  34. package/components/DatePickerInline/DatePickerDockedHeader.tsx +117 -0
  35. package/components/DatePickerInline/DatePickerInline.tsx +17 -16
  36. package/components/DatePickerInline/DatePickerInlineBase.tsx +11 -5
  37. package/components/DatePickerInline/DatePickerInlineHeader.tsx +50 -20
  38. package/components/DatePickerInline/Day.tsx +25 -1
  39. package/components/DatePickerInline/DayNames.tsx +13 -10
  40. package/components/DatePickerInline/DayRange.tsx +2 -4
  41. package/components/DatePickerInline/HeaderItem.tsx +44 -29
  42. package/components/DatePickerInline/Month.tsx +48 -67
  43. package/components/DatePickerInline/MonthPicker.tsx +80 -92
  44. package/components/DatePickerInline/Swiper.native.tsx +21 -4
  45. package/components/DatePickerInline/Swiper.tsx +169 -14
  46. package/components/DatePickerInline/SwiperUtils.ts +1 -1
  47. package/components/DatePickerInline/Week.tsx +6 -1
  48. package/components/DatePickerInline/YearPicker.tsx +220 -78
  49. package/components/DatePickerInline/dateUtils.tsx +18 -13
  50. package/components/DatePickerInline/store.tsx +27 -0
  51. package/components/DatePickerInline/types.ts +6 -2
  52. package/components/DatePickerInline/utils.ts +66 -29
  53. package/components/Divider/Divider.tsx +192 -0
  54. package/components/Divider/index.tsx +10 -0
  55. package/components/Drawer/Drawer.tsx +17 -6
  56. package/components/Drawer/DrawerItemGroup.tsx +3 -7
  57. package/components/ElementGroup/ElementGroup.tsx +1 -1
  58. package/components/FilePicker/FilePicker.tsx +48 -78
  59. package/components/FilePicker/index.tsx +2 -1
  60. package/components/FilePicker/utils.ts +9 -0
  61. package/components/HelperText/HelperText.tsx +0 -35
  62. package/components/Icon/iconFactory.tsx +5 -4
  63. package/components/Icon/index.tsx +1 -1
  64. package/components/Icon/types.ts +17 -6
  65. package/components/IconButton/IconButton.tsx +84 -84
  66. package/components/IconButton/index.tsx +1 -0
  67. package/components/IconButton/types.ts +10 -0
  68. package/components/IconButton/utils.ts +167 -33
  69. package/components/List/List.tsx +276 -0
  70. package/components/List/context.tsx +27 -0
  71. package/components/List/index.ts +8 -0
  72. package/components/List/types.ts +117 -0
  73. package/components/List/utils.ts +79 -0
  74. package/components/LoadingIndicator/LoadingIndicator.tsx +253 -0
  75. package/components/LoadingIndicator/LoadingIndicator.web.tsx +136 -0
  76. package/components/LoadingIndicator/index.tsx +13 -0
  77. package/components/LoadingIndicator/utils.ts +117 -0
  78. package/components/Menu/Menu.tsx +162 -39
  79. package/components/Menu/index.tsx +10 -7
  80. package/components/Menu/utils.ts +21 -70
  81. package/components/NavigationRail/NavigationRail.tsx +15 -9
  82. package/components/Popover/Popover.tsx +119 -145
  83. package/components/Popover/PopoverRoot.tsx +60 -0
  84. package/components/Popover/common.ts +54 -34
  85. package/components/Popover/index.ts +12 -1
  86. package/components/Popover/usePlatformMeasure.native.ts +90 -0
  87. package/components/Popover/usePlatformMeasure.ts +120 -0
  88. package/components/Popover/utils.ts +34 -0
  89. package/components/Portal/Portal.tsx +1 -2
  90. package/components/Radio/Radio.tsx +188 -0
  91. package/components/Radio/RadioBase.ios.tsx +69 -0
  92. package/components/Radio/RadioBase.tsx +136 -0
  93. package/components/Radio/context.tsx +23 -0
  94. package/components/Radio/index.tsx +20 -0
  95. package/components/Radio/types.ts +101 -0
  96. package/components/Radio/utils.ts +115 -0
  97. package/components/Rating/Rating.tsx +1 -1
  98. package/components/Select/Select.tsx +521 -785
  99. package/components/Select/context.tsx +81 -0
  100. package/components/Select/index.ts +26 -14
  101. package/components/Select/types.ts +65 -58
  102. package/components/Select/utils.ts +126 -0
  103. package/components/Slot/Slot.tsx +224 -0
  104. package/components/Slot/compose-refs.tsx +62 -0
  105. package/components/Slot/index.tsx +8 -0
  106. package/components/Surface/Surface.android.tsx +32 -7
  107. package/components/Surface/Surface.ios.tsx +34 -29
  108. package/components/Surface/Surface.tsx +31 -4
  109. package/components/Surface/utils.ts +44 -6
  110. package/components/Switch/Switch.ios.tsx +1 -1
  111. package/components/Switch/Switch.tsx +10 -3
  112. package/components/Tabs/TabItem.tsx +35 -58
  113. package/components/Tabs/TabLabel.tsx +5 -9
  114. package/components/Tabs/Tabs.tsx +156 -150
  115. package/components/Tabs/utils.ts +15 -2
  116. package/components/Text/textFactory.tsx +17 -5
  117. package/components/TextInput/TextInput.tsx +663 -579
  118. package/components/TextInput/index.tsx +19 -3
  119. package/components/TextInput/types.ts +77 -28
  120. package/components/TextInput/utils.ts +235 -145
  121. package/components/TimeField/TimeField.tsx +75 -0
  122. package/components/TimeField/index.tsx +6 -0
  123. package/components/TimeField/useTimeFieldState.ts +70 -0
  124. package/components/{TimePickerField/sanitizeTime.ts → TimeField/utils.ts} +77 -10
  125. package/components/TimePicker/AnalogClock.tsx +1 -1
  126. package/components/TimePicker/TimeInput.tsx +87 -42
  127. package/components/TimePicker/TimeInputs.tsx +138 -50
  128. package/components/TimePicker/TimePicker.tsx +74 -11
  129. package/components/TimePicker/TimePickerModal.tsx +186 -0
  130. package/components/TimePicker/context.tsx +17 -0
  131. package/components/TimePicker/index.tsx +15 -3
  132. package/components/TimePicker/utils.ts +93 -4
  133. package/components/Tooltip/Tooltip.tsx +42 -67
  134. package/components/Tooltip/TooltipContent.tsx +32 -5
  135. package/components/Tooltip/TooltipTrigger.tsx +21 -24
  136. package/components/Tooltip/index.tsx +1 -1
  137. package/components/TouchableRipple/TouchableRipple.native.tsx +83 -16
  138. package/components/TouchableRipple/TouchableRipple.tsx +150 -102
  139. package/components/TouchableRipple/rippleFromForegroundColor.ts +21 -0
  140. package/hocs/index.tsx +1 -1
  141. package/hocs/withKeyboardAccessibility.tsx +2 -3
  142. package/hocs/withPortal.tsx +1 -1
  143. package/hooks/index.tsx +2 -12
  144. package/hooks/useActionState.tsx +19 -8
  145. package/hooks/useContrastColor.ts +1 -2
  146. package/hooks/useFilePicker.tsx +7 -17
  147. package/hooks/useHandleNumberFormat.tsx +2 -2
  148. package/hooks/useMediaQuery.tsx +1 -2
  149. package/package.json +95 -111
  150. package/shortcuts-manager/ShortcutsManager/ShortcutsManager.tsx +6 -3
  151. package/shortcuts-manager/ShortcutsManager/utils.tsx +1 -1
  152. package/shortcuts-manager/useSetScopes/useSetScopes.tsx +1 -1
  153. package/shortcuts-manager/useShortcut/useShortcut.tsx +1 -1
  154. package/styles/shadow.ts +2 -1
  155. package/styles/themes/LightTheme.tsx +1 -1
  156. package/utils/DocumentPicker/documentPicker.ts +78 -27
  157. package/utils/DocumentPicker/types.ts +0 -1
  158. package/utils/extractSubcomponents.ts +89 -0
  159. package/utils/extractTextStyles.ts +1 -2
  160. package/utils/formatNumberWithMask/formatNumberWithMask.ts +2 -1
  161. package/utils/index.ts +0 -3
  162. package/utils/normalizeToNumberString/normalizeToNumberString.ts +1 -1
  163. package/components/DatePickerDocked/DatePickerDocked.tsx +0 -30
  164. package/components/DatePickerDocked/DatePickerDockedHeader.tsx +0 -129
  165. package/components/DatePickerDocked/index.tsx +0 -17
  166. package/components/DatePickerDocked/types.ts +0 -11
  167. package/components/DatePickerDocked/utils.ts +0 -157
  168. package/components/DatePickerInline/DatePickerContext.tsx +0 -21
  169. package/components/DatePickerInput/DatePickerInput.tsx +0 -139
  170. package/components/DatePickerInput/DatePickerInputModal.tsx +0 -48
  171. package/components/DatePickerInput/DatePickerInputWithoutModal.tsx +0 -77
  172. package/components/DatePickerInput/DateRangeInput.tsx +0 -88
  173. package/components/DatePickerInput/index.tsx +0 -10
  174. package/components/DatePickerInput/types.ts +0 -28
  175. package/components/DatePickerInput/utils.ts +0 -15
  176. package/components/DatePickerModal/AnimatedCrossView.tsx +0 -94
  177. package/components/DatePickerModal/CalendarEdit.tsx +0 -139
  178. package/components/DatePickerModal/DatePickerModal.tsx +0 -85
  179. package/components/DatePickerModal/DatePickerModalContent.tsx +0 -155
  180. package/components/DatePickerModal/DatePickerModalContentHeader.tsx +0 -213
  181. package/components/DatePickerModal/DatePickerModalHeader.tsx +0 -74
  182. package/components/DatePickerModal/DatePickerModalHeaderBackground.tsx +0 -13
  183. package/components/DatePickerModal/index.tsx +0 -16
  184. package/components/DatePickerModal/types.ts +0 -92
  185. package/components/DatePickerModal/utils.ts +0 -122
  186. package/components/DateTimePicker/DateTimePicker.tsx +0 -172
  187. package/components/DateTimePicker/index.tsx +0 -10
  188. package/components/DateTimePicker/utils.ts +0 -12
  189. package/components/HorizontalDivider/HorizontalDivider.tsx +0 -103
  190. package/components/HorizontalDivider/index.tsx +0 -9
  191. package/components/ListItem/ListItem.tsx +0 -136
  192. package/components/ListItem/ListItemDescription.tsx +0 -25
  193. package/components/ListItem/ListItemTitle.tsx +0 -25
  194. package/components/ListItem/index.tsx +0 -14
  195. package/components/ListItem/utils.ts +0 -115
  196. package/components/Menu/MenuDivider.tsx +0 -13
  197. package/components/Menu/MenuItem.tsx +0 -128
  198. package/components/Popover/Popover.native.tsx +0 -185
  199. package/components/RadioButton/RadioButton.tsx +0 -138
  200. package/components/RadioButton/RadioButtonAndroid.tsx +0 -188
  201. package/components/RadioButton/RadioButtonGroup.tsx +0 -98
  202. package/components/RadioButton/RadioButtonIOS.tsx +0 -106
  203. package/components/RadioButton/RadioButtonItem.tsx +0 -232
  204. package/components/RadioButton/index.ts +0 -22
  205. package/components/RadioButton/utils.ts +0 -165
  206. package/components/TimePickerField/TimePickerField.tsx +0 -152
  207. package/components/TimePickerField/index.tsx +0 -10
  208. package/components/TimePickerField/utils.ts +0 -94
  209. package/components/TimePickerModal/TimePickerModal.tsx +0 -115
  210. package/components/TimePickerModal/index.tsx +0 -10
  211. package/components/TimePickerModal/utils.ts +0 -47
  212. package/components/VerticalDivider/VerticalDivider.tsx +0 -100
  213. package/components/VerticalDivider/index.tsx +0 -9
  214. package/context-bridge/index.tsx +0 -87
  215. package/fast-context/index.tsx +0 -190
  216. package/hocs/typedMemo.tsx +0 -5
  217. package/hooks/useControlledValue.tsx +0 -68
  218. package/hooks/useLatest.tsx +0 -9
  219. package/hooks/useMergedRefs.ts +0 -14
  220. package/hooks/usePrevious.ts +0 -13
  221. package/hooks/useSearchable.tsx +0 -74
  222. package/hooks/useSubcomponents.tsx +0 -59
  223. package/hooks/useToggle.tsx +0 -24
  224. package/utils/color.ts +0 -22
  225. package/utils/compare/index.ts +0 -54
  226. package/utils/lodash.ts +0 -49
  227. package/utils/repository.ts +0 -53
@@ -1,185 +0,0 @@
1
- import { Fragment, memo, useCallback, useEffect, useLayoutEffect, useRef } from 'react';
2
- import { AppState, Dimensions, Platform, Pressable, StyleSheet, View } from 'react-native';
3
- import { ScopedTheme, UnistylesRuntime } from 'react-native-unistyles';
4
-
5
- import { Portal } from '../Portal';
6
- import {
7
- DEFAULT_ARROW_SIZE,
8
- popoverDefaultStyles,
9
- type PopoverProps,
10
- useArrowStyles,
11
- usePopover,
12
- } from './common';
13
-
14
- const Popover = ({
15
- triggerRef,
16
- children,
17
- isOpen,
18
- onClose,
19
- position = 'bottom',
20
- align = 'center',
21
- style,
22
- showArrow = false,
23
- arrowSize = DEFAULT_ARROW_SIZE,
24
- inverted = false,
25
- triggerDimensions,
26
- offset = 8,
27
- ...rest
28
- }: PopoverProps) => {
29
- const {
30
- popoverLayoutRef,
31
- targetLayoutRef,
32
- actualPositionRef,
33
- calculatedPosition,
34
- calculateAndSetPosition,
35
- handlePopoverLayout,
36
- } = usePopover({
37
- isOpen,
38
- position,
39
- align,
40
- showArrow,
41
- arrowSize,
42
- offset,
43
- });
44
-
45
- const popoverRef = useRef<View>(null);
46
-
47
- const measureTarget = useCallback(() => {
48
- if (triggerRef.current) {
49
- triggerRef.current.measure(
50
- (
51
- _fx: number,
52
- _fy: number,
53
- width: number,
54
- height: number,
55
- px: number,
56
- py: number,
57
- ) => {
58
- if (width !== 0 || height !== 0) {
59
- const newLayout = { x: px, y: py, width, height };
60
- const changed =
61
- !targetLayoutRef.current ||
62
- targetLayoutRef.current.x !== newLayout.x ||
63
- targetLayoutRef.current.y !== newLayout.y ||
64
- targetLayoutRef.current.width !== newLayout.width ||
65
- targetLayoutRef.current.height !== newLayout.height;
66
-
67
- if (changed) {
68
- targetLayoutRef.current = newLayout;
69
- calculateAndSetPosition();
70
- }
71
- } else {
72
- targetLayoutRef.current = null;
73
- calculateAndSetPosition();
74
- }
75
- },
76
- () => {
77
- console.error('Failed to measure target element for Popover.');
78
- targetLayoutRef.current = null;
79
- calculateAndSetPosition();
80
- },
81
- );
82
- } else {
83
- targetLayoutRef.current = null;
84
- calculateAndSetPosition();
85
- }
86
- }, [triggerRef, calculateAndSetPosition, targetLayoutRef]);
87
-
88
- useLayoutEffect(() => {
89
- if (isOpen) {
90
- measureTarget();
91
- }
92
- }, [isOpen, measureTarget, triggerDimensions]);
93
-
94
- useEffect(() => {
95
- if (!isOpen) return;
96
- const subscription = Dimensions.addEventListener('change', measureTarget);
97
- return () => {
98
- if (typeof subscription?.remove === 'function') {
99
- subscription.remove();
100
- }
101
- };
102
- }, [isOpen, measureTarget]);
103
-
104
- useEffect(() => {
105
- if (!isOpen || Platform.OS === 'web') return;
106
- const handleAppStateChange = (nextAppState: string) => {
107
- if (nextAppState === 'active') {
108
- setTimeout(measureTarget, 50);
109
- }
110
- };
111
- const subscription = AppState.addEventListener('change', handleAppStateChange);
112
- return () => {
113
- if (typeof subscription?.remove === 'function') {
114
- subscription.remove();
115
- }
116
- };
117
- }, [isOpen, measureTarget]);
118
-
119
- const arrowStyles = useArrowStyles({
120
- showArrow,
121
- arrowSize,
122
- style,
123
- calculatedPosition,
124
- targetLayoutRef,
125
- popoverLayoutRef,
126
- actualPositionRef,
127
- });
128
-
129
- const popoverStyle = calculatedPosition ?? popoverDefaultStyles;
130
- const Wrapper = inverted ? ScopedTheme : Fragment;
131
-
132
- if (!isOpen && popoverStyle.opacity === 0) {
133
- return null;
134
- }
135
-
136
- const handleOutsidePress = () => {
137
- if (isOpen && onClose) {
138
- onClose();
139
- }
140
- };
141
-
142
- return (
143
- <Portal>
144
- <Wrapper
145
- {...(inverted
146
- ? { name: UnistylesRuntime.themeName === 'dark' ? 'light' : 'dark' }
147
- : ({} as { name: 'light' }))}>
148
- <Pressable onPress={handleOutsidePress} style={styles.overlay} />
149
-
150
- <View
151
- ref={popoverRef}
152
- onLayout={handlePopoverLayout}
153
- style={[styles.popoverContainer, style, popoverStyle]}
154
- {...rest}>
155
- {children}
156
- {showArrow && popoverStyle.opacity === 1 && <View style={arrowStyles} />}
157
- </View>
158
- </Wrapper>
159
- </Portal>
160
- );
161
- };
162
-
163
- const styles = StyleSheet.create({
164
- overlay: {
165
- position: 'absolute',
166
- top: 0,
167
- bottom: 0,
168
- left: 0,
169
- right: 0,
170
- backgroundColor: 'transparent',
171
- },
172
- popoverContainer: {
173
- ...popoverDefaultStyles,
174
- backgroundColor: 'white',
175
- borderRadius: 4,
176
- shadowColor: 'rgba(0, 0, 0, 1)',
177
- shadowOffset: { width: 0, height: 2 },
178
- shadowOpacity: 0.3,
179
- shadowRadius: 3.84,
180
- elevation: 5,
181
- zIndex: 100,
182
- },
183
- });
184
-
185
- export default memo(Popover);
@@ -1,138 +0,0 @@
1
- import { forwardRef, memo, useContext, useMemo } from 'react';
2
- import { Platform } from 'react-native';
3
-
4
- import RadioButtonAndroid from './RadioButtonAndroid';
5
- import { RadioButtonContext } from './RadioButtonGroup';
6
- import RadioButtonIOS from './RadioButtonIOS';
7
- import { handlePress, isChecked } from './utils';
8
-
9
- export type Props = {
10
- /**
11
- * Value of the radio button
12
- */
13
- value: string;
14
- /**
15
- * Status of radio button.
16
- */
17
- status?: 'checked' | 'unchecked';
18
- /**
19
- * Whether radio is disabled.
20
- */
21
- disabled?: boolean;
22
- /**
23
- * Function to execute on press.
24
- */
25
- onPress?: () => void;
26
- /**
27
- * Custom color for unchecked radio.
28
- */
29
- uncheckedColor?: string;
30
- /**
31
- * Custom color for radio.
32
- */
33
- color?: string;
34
- /**
35
- * testID to be used on tests.
36
- */
37
- testID?: string;
38
- };
39
-
40
- /**
41
- * Radio buttons allow the selection a single option from a set.
42
- *
43
- * <div class="screenshots">
44
- * <figure>
45
- * <img src="screenshots/radio-enabled.android.png" />
46
- * <figcaption>Android (enabled)</figcaption>
47
- * </figure>
48
- * <figure>
49
- * <img src="screenshots/radio-disabled.android.png" />
50
- * <figcaption>Android (disabled)</figcaption>
51
- * </figure>
52
- * <figure>
53
- * <img src="screenshots/radio-enabled.ios.png" />
54
- * <figcaption>iOS (enabled)</figcaption>
55
- * </figure>
56
- * <figure>
57
- * <img src="screenshots/radio-disabled.ios.png" />
58
- * <figcaption>iOS (disabled)</figcaption>
59
- * </figure>
60
- * </div>
61
- *
62
- * ## Usage
63
- * ```js
64
- * import * as React from 'react';
65
- * import { View } from 'react-native';
66
- * import { RadioButton } from 'react-native-paper';
67
- *
68
- * const MyComponent = () => {
69
- * const [checked, setChecked] = React.useState('first');
70
- *
71
- * return (
72
- * <View>
73
- * <RadioButton
74
- * value="first"
75
- * status={ checked === 'first' ? 'checked' : 'unchecked' }
76
- * onPress={() => setChecked('first')}
77
- * />
78
- * <RadioButton
79
- * value="second"
80
- * status={ checked === 'second' ? 'checked' : 'unchecked' }
81
- * onPress={() => setChecked('second')}
82
- * />
83
- * </View>
84
- * );
85
- * };
86
- *
87
- * export default MyComponent;
88
- * ```
89
- */
90
-
91
- const Button = Platform.OS === 'ios' ? RadioButtonIOS : RadioButtonAndroid;
92
-
93
- const RadioButton = ({ value, status, disabled, onPress, testID, ...rest }: Props, ref: any) => {
94
- const context = useContext(RadioButtonContext);
95
-
96
- const checked = useMemo(
97
- () =>
98
- isChecked({
99
- contextValue: context?.value,
100
- status,
101
- value,
102
- }) === 'checked',
103
- [context?.value, status, value],
104
- );
105
- const onRadioPress = useMemo(
106
- () =>
107
- disabled
108
- ? undefined
109
- : () => {
110
- handlePress({
111
- onPress,
112
- onValueChange: context?.onValueChange,
113
- value,
114
- });
115
- },
116
- [disabled, onPress, context?.onValueChange, value],
117
- );
118
-
119
- const accessibilityState = useMemo(() => ({ disabled, checked }), [checked, disabled]);
120
-
121
- return (
122
- <Button
123
- {...rest}
124
- checked={checked}
125
- onPress={onRadioPress}
126
- status={status}
127
- disabled={disabled}
128
- borderless
129
- accessibilityRole="radio"
130
- accessibilityState={accessibilityState}
131
- accessibilityLiveRegion="polite"
132
- testID={testID}
133
- ref={ref}
134
- />
135
- );
136
- };
137
-
138
- export default memo(forwardRef(RadioButton));
@@ -1,188 +0,0 @@
1
- import setColor from 'color';
2
- import { forwardRef, memo, type PropsWithoutRef, useEffect, useMemo, useRef } from 'react';
3
- import type { ViewProps } from 'react-native';
4
- import { Animated, StyleSheet, View } from 'react-native';
5
-
6
- import { useActionState } from '../../hooks';
7
- import { resolveStateVariant } from '../../utils';
8
- import { tokenStylesParser } from '../../utils/tokenStylesParser';
9
- import { StateLayer } from '../StateLayer';
10
- import { TouchableRipple, type TouchableRippleProps } from '../TouchableRipple';
11
- import { ANIMATION_DURATION, radioButtonStyles } from './utils';
12
-
13
- export type Props = Omit<TouchableRippleProps, 'children'> & {
14
- /**
15
- * Status of radio button.
16
- */
17
- status?: 'checked' | 'unchecked';
18
- /**
19
- * Whether radio is disabled.
20
- */
21
- disabled?: boolean;
22
- /**
23
- * Custom color for unchecked radio.
24
- */
25
- uncheckedColor?: string;
26
- /**
27
- * Custom color for radio.
28
- */
29
- color?: string;
30
- /**
31
- * testID to be used on tests.
32
- */
33
- testID?: string;
34
- /**
35
- * passed from RadioButton component
36
- */
37
- checked: boolean;
38
- onPress: (() => void) | undefined;
39
- /**
40
- * props for the stateLayer
41
- */
42
- stateLayerProps?: PropsWithoutRef<ViewProps>;
43
- };
44
-
45
- const BORDER_WIDTH = 2;
46
-
47
- const RadioButtonAndroid = (
48
- {
49
- disabled = false,
50
- status,
51
- testID,
52
- color: colorProp,
53
- uncheckedColor: uncheckedColorProp,
54
- style,
55
- checked,
56
- onPress,
57
- stateLayerProps = {},
58
- ...rest
59
- }: Props,
60
- ref: any,
61
- ) => {
62
- const { actionsRef, hovered } = useActionState({ ref, actionsToListen: ['hover'] });
63
- const { current: borderAnim } = useRef<Animated.Value>(new Animated.Value(BORDER_WIDTH));
64
-
65
- const { current: radioAnim } = useRef<Animated.Value>(new Animated.Value(1));
66
-
67
- const isFirstRendering = useRef<boolean>(true);
68
-
69
- const state = resolveStateVariant({
70
- disabled,
71
- checkedAndHovered: checked && hovered,
72
- checked,
73
- hovered,
74
- });
75
-
76
- radioButtonStyles.useVariants({
77
- state: state as any,
78
- });
79
-
80
- const {
81
- containerStyles,
82
- rippleColor,
83
- radioStyles,
84
- dotStyles,
85
- dotContainerStyles,
86
- stateLayerStyle,
87
- } = useMemo(() => {
88
- const _color = tokenStylesParser.getColor(checked ? colorProp : uncheckedColorProp);
89
-
90
- let _rippleColor: string | undefined;
91
-
92
- try {
93
- _rippleColor = setColor(_color).alpha(0.32).rgb().string();
94
- } catch (e) {
95
- _rippleColor = undefined;
96
- }
97
-
98
- return {
99
- containerStyles: [radioButtonStyles.container, radioButtonStyles.root, style],
100
- rippleColor: _rippleColor,
101
- radioStyles: [
102
- radioButtonStyles.radio,
103
- {
104
- borderWidth: borderAnim,
105
- },
106
- tokenStylesParser.getColor(checked ? colorProp : uncheckedColorProp, 'borderColor'),
107
- ],
108
- dotContainerStyles: [StyleSheet.absoluteFill, radioButtonStyles.radioContainer],
109
- dotStyles: [
110
- radioButtonStyles.dot,
111
- {
112
- transform: [{ scale: radioAnim }],
113
- },
114
- tokenStylesParser.getColor(
115
- checked ? colorProp : uncheckedColorProp,
116
- 'backgroundColor',
117
- ),
118
- ],
119
- stateLayerStyle: [radioButtonStyles.stateLayer, stateLayerProps?.style],
120
- };
121
- // eslint-disable-next-line react-hooks/exhaustive-deps
122
- }, [
123
- borderAnim,
124
- checked,
125
- colorProp,
126
- radioAnim,
127
- stateLayerProps?.style,
128
- uncheckedColorProp,
129
- style,
130
- state,
131
- ]);
132
-
133
- useEffect(() => {
134
- // Do not run animation on very first rendering
135
- if (isFirstRendering.current) {
136
- isFirstRendering.current = false;
137
- return;
138
- }
139
-
140
- if (status === 'checked') {
141
- radioAnim.setValue(1.2);
142
-
143
- Animated.timing(radioAnim, {
144
- toValue: 1,
145
- duration: ANIMATION_DURATION,
146
- useNativeDriver: true,
147
- }).start();
148
- } else {
149
- borderAnim.setValue(10);
150
-
151
- Animated.timing(borderAnim, {
152
- toValue: BORDER_WIDTH,
153
- duration: ANIMATION_DURATION,
154
- useNativeDriver: false,
155
- }).start();
156
- }
157
- }, [status, borderAnim, radioAnim]);
158
-
159
- return (
160
- <TouchableRipple
161
- {...rest}
162
- ref={actionsRef}
163
- rippleColor={rippleColor}
164
- onPress={onPress}
165
- style={containerStyles}
166
- testID={testID}>
167
- <>
168
- <Animated.View style={radioStyles}>
169
- {checked ? (
170
- <View style={dotContainerStyles}>
171
- <Animated.View style={dotStyles} />
172
- </View>
173
- ) : null}
174
- </Animated.View>
175
-
176
- <StateLayer
177
- testID={testID ? `${testID}-stateLayer` : ''}
178
- {...stateLayerProps}
179
- style={stateLayerStyle}
180
- />
181
- </>
182
- </TouchableRipple>
183
- );
184
- };
185
-
186
- RadioButtonAndroid.displayName = 'RadioButton_Android';
187
-
188
- export default memo(forwardRef(RadioButtonAndroid));
@@ -1,98 +0,0 @@
1
- import { createContext, memo, type ReactNode, useMemo } from 'react';
2
- import { View, type ViewProps } from 'react-native';
3
-
4
- import { useControlledValue } from '../../hooks';
5
-
6
- export type Props = ViewProps & {
7
- /**
8
- * Function to execute on selection change.
9
- */
10
- onValueChange?: (value: string) => void;
11
- /**
12
- * Value of the currently selected radio button.
13
- */
14
- value?: string;
15
- /**
16
- * Default selected radio button
17
- */
18
- defaultValue?: string;
19
- /**
20
- * React elements containing radio buttons.
21
- */
22
- children: ReactNode;
23
- };
24
-
25
- export type RadioButtonContextType = {
26
- value: string;
27
- onValueChange: (item: string) => void;
28
- };
29
-
30
- export const RadioButtonContext = createContext<RadioButtonContextType>(null as any);
31
-
32
- /**
33
- * Radio button group allows to control a group of radio buttons.
34
- *
35
- * <div class="screenshots">
36
- * <figure>
37
- * <img class="medium" src="screenshots/radio-button-group-android.gif" />
38
- * <figcaption>Android</figcaption>
39
- * </figure>
40
- * <figure>
41
- * <img class="medium" src="screenshots/radio-button-group-ios.gif" />
42
- * <figcaption>iOS</figcaption>
43
- * </figure>
44
- * </div>
45
- *
46
- * ## Usage
47
- * ```js
48
- * import * as React from 'react';
49
- * import { View } from 'react-native';
50
- * import { RadioButton, Text } from 'react-native-paper';
51
- *
52
- * const MyComponent = () => {
53
- * const [value, setValue] = React.useState('first');
54
- *
55
- * return (
56
- * <RadioButton.Group onValueChange={newValue => setValue(newValue)} value={value}>
57
- * <View>
58
- * <Text>First</Text>
59
- * <RadioButton value="first" />
60
- * </View>
61
- * <View>
62
- * <Text>Second</Text>
63
- * <RadioButton value="second" />
64
- * </View>
65
- * </RadioButton.Group>
66
- * );
67
- * };
68
- *
69
- * export default MyComponent;
70
- *```
71
- */
72
- const RadioButtonGroup = ({
73
- value: valueProp,
74
- defaultValue,
75
- onValueChange: onValueChangeProp,
76
- children,
77
- ...rest
78
- }: Props) => {
79
- const [value, onValueChange] = useControlledValue({
80
- value: valueProp,
81
- defaultValue,
82
- onChange: onValueChangeProp,
83
- });
84
-
85
- const contextValue = useMemo(() => ({ value, onValueChange }), [onValueChange, value]);
86
-
87
- return (
88
- <RadioButtonContext.Provider value={contextValue}>
89
- <View accessibilityRole="radiogroup" {...rest}>
90
- {children}
91
- </View>
92
- </RadioButtonContext.Provider>
93
- );
94
- };
95
-
96
- RadioButtonGroup.displayName = 'RadioButton_Group';
97
-
98
- export default memo(RadioButtonGroup);
@@ -1,106 +0,0 @@
1
- import setColor from 'color';
2
- import { forwardRef, memo, useMemo } from 'react';
3
- import { StyleSheet, View } from 'react-native';
4
-
5
- import { resolveStateVariant } from '../../utils';
6
- import { tokenStylesParser } from '../../utils/tokenStylesParser';
7
- import { Icon } from '../Icon';
8
- import { TouchableRipple, type TouchableRippleProps } from '../TouchableRipple';
9
- import { DEFAULT_ICON_SIZE, radioButtonStyles } from './utils';
10
-
11
- export type Props = Omit<TouchableRippleProps, 'children'> & {
12
- /**
13
- * Status of radio button.
14
- */
15
- status?: 'checked' | 'unchecked';
16
- /**
17
- * Whether radio is disabled.
18
- */
19
- disabled?: boolean;
20
- /**
21
- * Custom color for unchecked radio.
22
- */
23
- uncheckedColor?: string;
24
- /**
25
- * Custom color for radio.
26
- */
27
- color?: string;
28
- /**
29
- * testID to be used on tests.
30
- */
31
- testID?: string;
32
- /**
33
- * passed from RadioButton component
34
- */
35
- checked: boolean;
36
- onPress: (() => void) | undefined;
37
- };
38
-
39
- const RadioButtonIOS = (
40
- {
41
- disabled,
42
- style,
43
- color: colorProp,
44
- checked,
45
- onPress,
46
- uncheckedColor: uncheckedColorProp,
47
- ...rest
48
- }: Props,
49
- ref: any,
50
- ) => {
51
- const state = resolveStateVariant({
52
- disabled: !!disabled,
53
- checked,
54
- });
55
- radioButtonStyles.useVariants({
56
- state: state as any,
57
- });
58
-
59
- const { containerStyle, iconContainerStyle, iconStyle, rippleColor } = useMemo(() => {
60
- const _color = tokenStylesParser.getColor(checked ? colorProp : uncheckedColorProp);
61
- let _rippleColor: string | undefined;
62
-
63
- try {
64
- _rippleColor = setColor(_color).alpha(0.32).rgb().string();
65
- } catch (e) {
66
- _rippleColor = undefined;
67
- }
68
-
69
- return {
70
- containerStyle: [styles.container, radioButtonStyles.root, style],
71
- iconContainerStyle: { opacity: checked ? 1 : 0 },
72
- iconStyle: [radioButtonStyles.icon, _color],
73
- rippleColor: _rippleColor,
74
- };
75
- // eslint-disable-next-line react-hooks/exhaustive-deps
76
- }, [checked, colorProp, style, state, uncheckedColorProp]);
77
-
78
- return (
79
- <TouchableRipple
80
- {...rest}
81
- ref={ref}
82
- rippleColor={rippleColor}
83
- onPress={onPress}
84
- style={containerStyle}>
85
- <View style={iconContainerStyle}>
86
- <Icon
87
- allowFontScaling={false}
88
- name="check"
89
- size={DEFAULT_ICON_SIZE}
90
- style={iconStyle}
91
- />
92
- </View>
93
- </TouchableRipple>
94
- );
95
- };
96
-
97
- RadioButtonIOS.displayName = 'RadioButton_IOS';
98
-
99
- const styles = StyleSheet.create({
100
- container: {
101
- borderRadius: 18,
102
- padding: 6,
103
- },
104
- });
105
-
106
- export default memo(forwardRef(RadioButtonIOS));