react-native-molecules 0.5.0-beta.1 → 0.5.0-beta.11

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 (165) hide show
  1. package/README.md +87 -0
  2. package/components/Accordion/index.tsx +1 -6
  3. package/components/Accordion/utils.ts +17 -14
  4. package/components/ActivityIndicator/ActivityIndicator.tsx +12 -20
  5. package/components/ActivityIndicator/index.tsx +1 -5
  6. package/components/Appbar/index.tsx +1 -4
  7. package/components/Appbar/utils.ts +33 -21
  8. package/components/Avatar/index.tsx +1 -5
  9. package/components/Avatar/utils.ts +2 -6
  10. package/components/Backdrop/Backdrop.tsx +2 -2
  11. package/components/Backdrop/index.tsx +1 -5
  12. package/components/Backdrop/utils.ts +5 -6
  13. package/components/Badge/index.tsx +1 -5
  14. package/components/Badge/utils.ts +2 -6
  15. package/components/Button/Button.tsx +211 -264
  16. package/components/Button/index.tsx +9 -7
  17. package/components/Button/types.ts +16 -2
  18. package/components/Button/utils.ts +231 -210
  19. package/components/Card/Card.tsx +8 -4
  20. package/components/Card/CardContent.tsx +5 -4
  21. package/components/Card/CardHeader.tsx +5 -3
  22. package/components/Card/CardMedia.tsx +5 -3
  23. package/components/Card/CardTypography.tsx +5 -3
  24. package/components/Card/index.tsx +1 -5
  25. package/components/Card/utils.ts +5 -6
  26. package/components/Checkbox/Checkbox.tsx +1 -0
  27. package/components/Checkbox/CheckboxBase.ios.tsx +1 -0
  28. package/components/Checkbox/CheckboxBase.tsx +24 -128
  29. package/components/Checkbox/index.tsx +1 -5
  30. package/components/Checkbox/utils.ts +6 -31
  31. package/components/Chip/Chip.tsx +40 -52
  32. package/components/Chip/index.tsx +1 -5
  33. package/components/Chip/utils.ts +5 -13
  34. package/components/DatePickerDocked/index.tsx +1 -5
  35. package/components/DatePickerDocked/utils.ts +21 -19
  36. package/components/DatePickerInline/index.tsx +1 -5
  37. package/components/DatePickerInline/utils.ts +41 -28
  38. package/components/DatePickerInput/DatePickerInput.tsx +4 -2
  39. package/components/DatePickerInput/DatePickerInputWithoutModal.tsx +0 -4
  40. package/components/DatePickerInput/index.tsx +1 -5
  41. package/components/DatePickerInput/types.ts +1 -3
  42. package/components/DatePickerInput/utils.ts +5 -6
  43. package/components/DatePickerModal/CalendarEdit.tsx +10 -9
  44. package/components/DatePickerModal/DatePickerModalHeader.tsx +1 -1
  45. package/components/DatePickerModal/index.tsx +1 -5
  46. package/components/DatePickerModal/utils.ts +17 -16
  47. package/components/DateTimePicker/index.tsx +1 -5
  48. package/components/DateTimePicker/utils.ts +5 -6
  49. package/components/Dialog/index.tsx +1 -5
  50. package/components/Dialog/utils.ts +22 -16
  51. package/components/Drawer/Collapsible/utils.ts +13 -13
  52. package/components/Drawer/Drawer.tsx +2 -3
  53. package/components/Drawer/DrawerContent.tsx +5 -3
  54. package/components/Drawer/DrawerFooter.tsx +5 -4
  55. package/components/Drawer/DrawerHeader.tsx +5 -4
  56. package/components/Drawer/DrawerItem.tsx +5 -3
  57. package/components/Drawer/DrawerItemGroup.tsx +5 -4
  58. package/components/Drawer/index.tsx +1 -5
  59. package/components/Drawer/utils.ts +7 -7
  60. package/components/ElementGroup/ElementGroup.tsx +16 -14
  61. package/components/ElementGroup/index.tsx +1 -5
  62. package/components/ElementGroup/utils.ts +5 -6
  63. package/components/FAB/index.tsx +1 -5
  64. package/components/FAB/utils.ts +2 -6
  65. package/components/FilePicker/FilePicker.tsx +47 -76
  66. package/components/FilePicker/index.tsx +1 -5
  67. package/components/FilePicker/utils.ts +5 -6
  68. package/components/HelperText/HelperText.tsx +0 -35
  69. package/components/HelperText/index.tsx +1 -5
  70. package/components/HelperText/utils.ts +5 -7
  71. package/components/HorizontalDivider/HorizontalDivider.tsx +5 -3
  72. package/components/HorizontalDivider/index.tsx +1 -5
  73. package/components/Icon/CrossFadeIcon.tsx +3 -5
  74. package/components/Icon/Icon.tsx +2 -4
  75. package/components/Icon/iconFactory.tsx +3 -3
  76. package/components/Icon/index.tsx +2 -6
  77. package/components/Icon/types.ts +17 -6
  78. package/components/IconButton/IconButton.tsx +45 -58
  79. package/components/IconButton/index.tsx +1 -5
  80. package/components/IconButton/utils.ts +153 -49
  81. package/components/If/index.tsx +1 -5
  82. package/components/InputAddon/index.tsx +1 -5
  83. package/components/InputAddon/utils.ts +5 -6
  84. package/components/Link/index.tsx +1 -5
  85. package/components/Link/utils.ts +2 -6
  86. package/components/ListItem/index.tsx +1 -5
  87. package/components/ListItem/utils.ts +13 -11
  88. package/components/LoadingIndicator/LoadingIndicator.tsx +253 -0
  89. package/components/LoadingIndicator/LoadingIndicator.web.tsx +136 -0
  90. package/components/LoadingIndicator/index.tsx +13 -0
  91. package/components/LoadingIndicator/utils.ts +117 -0
  92. package/components/Menu/index.tsx +1 -5
  93. package/components/Menu/utils.ts +6 -8
  94. package/components/Modal/index.tsx +1 -5
  95. package/components/Modal/utils.ts +2 -6
  96. package/components/NavigationRail/NavigationRailHeader.tsx +1 -1
  97. package/components/NavigationRail/index.tsx +1 -5
  98. package/components/NavigationRail/utils.ts +21 -17
  99. package/components/NavigationStack/index.tsx +1 -5
  100. package/components/NavigationStack/utils.tsx +7 -1
  101. package/components/Portal/index.tsx +1 -5
  102. package/components/RadioButton/index.ts +1 -5
  103. package/components/RadioButton/utils.ts +9 -8
  104. package/components/Rating/index.tsx +1 -5
  105. package/components/Rating/utils.ts +6 -8
  106. package/components/Select/Select.tsx +369 -507
  107. package/components/Select/index.ts +7 -14
  108. package/components/Select/types.ts +2 -4
  109. package/components/Select/utils.ts +215 -0
  110. package/components/Slot/Slot.tsx +244 -0
  111. package/components/Slot/compose-refs.tsx +60 -0
  112. package/components/Slot/index.tsx +8 -0
  113. package/components/StateLayer/index.tsx +1 -5
  114. package/components/StateLayer/utils.ts +5 -6
  115. package/components/Surface/Surface.android.tsx +34 -8
  116. package/components/Surface/Surface.ios.tsx +36 -29
  117. package/components/Surface/Surface.tsx +31 -4
  118. package/components/Surface/index.tsx +1 -5
  119. package/components/Surface/utils.ts +49 -36
  120. package/components/Switch/Switch.tsx +8 -2
  121. package/components/Switch/index.tsx +1 -5
  122. package/components/Switch/utils.ts +2 -6
  123. package/components/Tabs/TabItem.tsx +35 -58
  124. package/components/Tabs/TabLabel.tsx +5 -9
  125. package/components/Tabs/Tabs.tsx +154 -149
  126. package/components/Tabs/index.tsx +1 -5
  127. package/components/Tabs/utils.ts +25 -12
  128. package/components/Text/Text.tsx +2 -8
  129. package/components/TextInput/TextInput.tsx +655 -571
  130. package/components/TextInput/index.tsx +19 -7
  131. package/components/TextInput/types.ts +76 -27
  132. package/components/TextInput/utils.ts +232 -159
  133. package/components/TextInputWithMask/index.tsx +1 -5
  134. package/components/TimePicker/AmPmSwitcher.tsx +1 -1
  135. package/components/TimePicker/index.tsx +1 -5
  136. package/components/TimePicker/utils.ts +29 -21
  137. package/components/TimePickerField/TimePickerField.tsx +7 -5
  138. package/components/TimePickerField/index.tsx +1 -5
  139. package/components/TimePickerField/utils.ts +5 -6
  140. package/components/TimePickerModal/TimePickerModal.tsx +6 -2
  141. package/components/TimePickerModal/index.tsx +1 -5
  142. package/components/TimePickerModal/utils.ts +5 -6
  143. package/components/Tooltip/TooltipTrigger.tsx +25 -16
  144. package/components/Tooltip/index.tsx +1 -5
  145. package/components/Tooltip/utils.ts +5 -6
  146. package/components/TouchableRipple/TouchableRipple.native.tsx +50 -14
  147. package/components/TouchableRipple/TouchableRipple.tsx +137 -47
  148. package/components/TouchableRipple/index.tsx +1 -5
  149. package/components/TouchableRipple/utils.ts +5 -6
  150. package/components/VerticalDivider/VerticalDivider.tsx +9 -8
  151. package/components/VerticalDivider/index.tsx +1 -5
  152. package/core/componentsRegistry.ts +31 -19
  153. package/hocs/withPortal.tsx +1 -1
  154. package/hooks/index.tsx +0 -5
  155. package/hooks/useControlledValue.tsx +20 -4
  156. package/hooks/useSubcomponents.tsx +63 -31
  157. package/hooks/useWhatHasUpdated.tsx +48 -0
  158. package/package.json +12 -15
  159. package/shortcuts-manager/ShortcutsManager/ShortcutsManager.tsx +5 -2
  160. package/styles/shadow.ts +2 -1
  161. package/styles/themes/LightTheme.tsx +1 -1
  162. package/utils/extractPropertiesFromStyles.ts +25 -0
  163. package/utils/lodash.ts +77 -6
  164. package/utils/repository.ts +2 -52
  165. package/hooks/useSearchable.tsx +0 -74
@@ -71,7 +71,7 @@ function SwitchButton({
71
71
  disabled: boolean;
72
72
  }) {
73
73
  timePickerAmPmSwitcherStyles.useVariants({
74
- // TODO - fix ts issues
74
+ // @ts-ignore // TODO - fix this
75
75
  state: resolveStateVariant({
76
76
  selected,
77
77
  }),
@@ -1,10 +1,6 @@
1
- import { getRegisteredComponentWithFallback, registerMoleculesComponents } from '../../core';
1
+ import { getRegisteredComponentWithFallback } from '../../core';
2
2
  import TimePickerDefault from './TimePicker';
3
3
 
4
- registerMoleculesComponents({
5
- TimePicker: TimePickerDefault,
6
- });
7
-
8
4
  export const TimePicker = getRegisteredComponentWithFallback('TimePicker', TimePickerDefault);
9
5
 
10
6
  export type { Props as TimePickerProps } from './TimePicker';
@@ -1,6 +1,6 @@
1
1
  import { StyleSheet } from 'react-native-unistyles';
2
2
 
3
- import { getRegisteredMoleculesComponentStyles, registerComponentsStyles } from '../../core';
3
+ import { getRegisteredComponentStylesWithFallback } from '../../core';
4
4
  import { circleSize } from './timeUtils';
5
5
 
6
6
  const timePickerStylesDefault = StyleSheet.create(theme => ({
@@ -263,23 +263,31 @@ const timePickerAmPmSwitcherStylesDefault = StyleSheet.create(theme => ({
263
263
  },
264
264
  }));
265
265
 
266
- registerComponentsStyles({
267
- TimePicker: timePickerStylesDefault,
268
- TimePicker_Inputs: timePickerInputsStylesDefault,
269
- TimePicker_Input: timePickerInputStylesDefault,
270
- TimePicker_Clock: timePickerClockStylesDefault,
271
- TimePicker_ClockHours: timePickerClockHoursStylesDefault,
272
- TimePicker_ClockMinutes: timePickerClockMinutesStylesDefault,
273
- TimePicker_AmPmSwitcher: timePickerAmPmSwitcherStylesDefault,
274
- });
275
-
276
- export const timePickerStyles = getRegisteredMoleculesComponentStyles('TimePicker');
277
- export const timePickerInputsStyles = getRegisteredMoleculesComponentStyles('TimePicker_Inputs');
278
- export const timePickerInputStyles = getRegisteredMoleculesComponentStyles('TimePicker_Input');
279
- export const timePickerClockStyles = getRegisteredMoleculesComponentStyles('TimePicker_Clock');
280
- export const timePickerClockHoursStyles =
281
- getRegisteredMoleculesComponentStyles('TimePicker_ClockHours');
282
- export const timePickerClockMinutesStyles =
283
- getRegisteredMoleculesComponentStyles('TimePicker_ClockMinutes');
284
- export const timePickerAmPmSwitcherStyles =
285
- getRegisteredMoleculesComponentStyles('TimePicker_AmPmSwitcher');
266
+ export const timePickerStyles = getRegisteredComponentStylesWithFallback(
267
+ 'TimePicker',
268
+ timePickerStylesDefault,
269
+ );
270
+ export const timePickerInputsStyles = getRegisteredComponentStylesWithFallback(
271
+ 'TimePicker_Inputs',
272
+ timePickerInputsStylesDefault,
273
+ );
274
+ export const timePickerInputStyles = getRegisteredComponentStylesWithFallback(
275
+ 'TimePicker_Input',
276
+ timePickerInputStylesDefault,
277
+ );
278
+ export const timePickerClockStyles = getRegisteredComponentStylesWithFallback(
279
+ 'TimePicker_Clock',
280
+ timePickerClockStylesDefault,
281
+ );
282
+ export const timePickerClockHoursStyles = getRegisteredComponentStylesWithFallback(
283
+ 'TimePicker_ClockHours',
284
+ timePickerClockHoursStylesDefault,
285
+ );
286
+ export const timePickerClockMinutesStyles = getRegisteredComponentStylesWithFallback(
287
+ 'TimePicker_ClockMinutes',
288
+ timePickerClockMinutesStylesDefault,
289
+ );
290
+ export const timePickerAmPmSwitcherStyles = getRegisteredComponentStylesWithFallback(
291
+ 'TimePicker_AmPmSwitcher',
292
+ timePickerAmPmSwitcherStylesDefault,
293
+ );
@@ -26,10 +26,11 @@ const TimePickerField = (
26
26
  withModal = true,
27
27
  style,
28
28
  onBlur: onBlurProp,
29
- modalProps = {},
30
- iconButtonProps = {},
29
+ modalProps,
30
+ iconButtonProps,
31
31
  disabled,
32
32
  onFocus: onFocusProp,
33
+ children,
33
34
  ...rest
34
35
  }: Props,
35
36
  ref: any,
@@ -143,9 +144,10 @@ const TimePickerField = (
143
144
  onFocus={onFocus}
144
145
  onChangeText={onChangeText}
145
146
  style={componentStyles}
146
- onBlur={onBlur}
147
- right={rightElement}
148
- />
147
+ onBlur={onBlur}>
148
+ <TextInput.Right>{rightElement}</TextInput.Right>
149
+ {children}
150
+ </TextInput>
149
151
  );
150
152
  };
151
153
 
@@ -1,10 +1,6 @@
1
- import { getRegisteredComponentWithFallback, registerMoleculesComponents } from '../../core';
1
+ import { getRegisteredComponentWithFallback } from '../../core';
2
2
  import TimePickerFieldDefault from './TimePickerField';
3
3
 
4
- registerMoleculesComponents({
5
- TimePickerField: TimePickerFieldDefault,
6
- });
7
-
8
4
  export const TimePickerField = getRegisteredComponentWithFallback(
9
5
  'TimePickerField',
10
6
  TimePickerFieldDefault,
@@ -5,17 +5,16 @@ export declare type MaskItem = string | RegExp | [RegExp];
5
5
  export declare type MaskArray = Array<MaskItem>;
6
6
  export declare type Mask = MaskArray | ((value?: string) => MaskArray);
7
7
 
8
- import { getRegisteredMoleculesComponentStyles, registerComponentsStyles } from '../../core';
8
+ import { getRegisteredComponentStylesWithFallback } from '../../core';
9
9
 
10
10
  const timepickerFieldStylesDefault = StyleSheet.create({
11
11
  root: {},
12
12
  });
13
13
 
14
- registerComponentsStyles({
15
- TimePickerField: timepickerFieldStylesDefault,
16
- });
17
-
18
- export const styles = getRegisteredMoleculesComponentStyles('TimePickerField');
14
+ export const styles = getRegisteredComponentStylesWithFallback(
15
+ 'TimePickerField',
16
+ timepickerFieldStylesDefault,
17
+ );
19
18
 
20
19
  export const timeMask24Hour: Mask = (text: string = '') => {
21
20
  const cleanTime = text.replace(/\D+/g, '');
@@ -103,8 +103,12 @@ export function TimePickerModal({
103
103
  accessibilityLabel="toggle keyboard"
104
104
  />
105
105
  <View style={styles.fill} />
106
- <Button onPress={onClose}>{cancelLabel}</Button>
107
- <Button onPress={onConfirm}>{confirmLabel}</Button>
106
+ <Button onPress={onClose}>
107
+ <Button.Text>{cancelLabel}</Button.Text>
108
+ </Button>
109
+ <Button onPress={onConfirm}>
110
+ <Button.Text>{confirmLabel}</Button.Text>
111
+ </Button>
108
112
  </View>
109
113
  </KeyboardAvoidingView>
110
114
  </Modal>
@@ -1,10 +1,6 @@
1
- import { getRegisteredComponentWithFallback, registerMoleculesComponents } from '../../core';
1
+ import { getRegisteredComponentWithFallback } from '../../core';
2
2
  import TimePickerModalDefault from './TimePickerModal';
3
3
 
4
- registerMoleculesComponents({
5
- TimePickerModal: TimePickerModalDefault,
6
- });
7
-
8
4
  export const TimePickerModal = getRegisteredComponentWithFallback(
9
5
  'TimePickerModal',
10
6
  TimePickerModalDefault,
@@ -1,6 +1,6 @@
1
1
  import { StyleSheet } from 'react-native-unistyles';
2
2
 
3
- import { getRegisteredMoleculesComponentStyles, registerComponentsStyles } from '../../core';
3
+ import { getRegisteredComponentStylesWithFallback } from '../../core';
4
4
 
5
5
  const timepickerModalStylesDefault = StyleSheet.create(theme => ({
6
6
  keyboardView: {
@@ -41,8 +41,7 @@ const timepickerModalStylesDefault = StyleSheet.create(theme => ({
41
41
  fill: { flex: 1 },
42
42
  }));
43
43
 
44
- registerComponentsStyles({
45
- TimePickerModal: timepickerModalStylesDefault,
46
- });
47
-
48
- export const styles = getRegisteredMoleculesComponentStyles('TimePickerModal');
44
+ export const styles = getRegisteredComponentStylesWithFallback(
45
+ 'TimePickerModal',
46
+ timepickerModalStylesDefault,
47
+ );
@@ -30,27 +30,36 @@ const TooltipTrigger = memo(({ children }: { children: ReactElement }) => {
30
30
  () => triggerRef?.current,
31
31
  );
32
32
 
33
- const onPress = useCallback(() => {
34
- // @ts-ignore
35
- children?.props?.onPress?.();
36
- }, [children?.props]);
33
+ const onPress = useCallback(
34
+ (e: unknown) => {
35
+ // @ts-ignore
36
+ children?.props?.onPress?.(e);
37
+ },
38
+ [children?.props],
39
+ );
37
40
 
38
- const onLongPress = useCallback(() => {
39
- // @ts-ignore
40
- children?.props?.onLongPress?.();
41
+ const onLongPress = useCallback(
42
+ (e: unknown) => {
43
+ // @ts-ignore
44
+ children?.props?.onLongPress?.(e);
41
45
 
42
- if (isWeb) return;
43
- onOpen();
44
- }, [children?.props, isWeb, onOpen]);
46
+ if (isWeb) return;
47
+ onOpen();
48
+ },
49
+ [children?.props, isWeb, onOpen],
50
+ );
45
51
 
46
- const onPressOut = useCallback(() => {
47
- // @ts-ignore
52
+ const onPressOut = useCallback(
53
+ (e: unknown) => {
54
+ // @ts-ignore
48
55
 
49
- children?.props?.onPressOut?.();
56
+ children?.props?.onPressOut?.(e);
50
57
 
51
- if (isWeb) return;
52
- onClose();
53
- }, [children?.props, isWeb, onClose]);
58
+ if (isWeb) return;
59
+ onClose();
60
+ },
61
+ [children?.props, isWeb, onClose],
62
+ );
54
63
 
55
64
  const onHoverIn = useCallback(() => {
56
65
  // @ts-ignore
@@ -1,4 +1,4 @@
1
- import { getRegisteredComponentWithFallback, registerMoleculesComponents } from '../../core';
1
+ import { getRegisteredComponentWithFallback } from '../../core';
2
2
  import TooltipComponent from './Tooltip';
3
3
  import TooltipContent from './TooltipContent';
4
4
  import TooltipTrigger from './TooltipTrigger';
@@ -8,10 +8,6 @@ export const TooltipDefault = Object.assign(TooltipComponent, {
8
8
  Content: TooltipContent,
9
9
  });
10
10
 
11
- registerMoleculesComponents({
12
- Tooltip: TooltipDefault,
13
- });
14
-
15
11
  export const Tooltip = getRegisteredComponentWithFallback('Tooltip', TooltipDefault);
16
12
 
17
13
  export type { Props as TooltipProps } from './Tooltip';
@@ -1,6 +1,6 @@
1
1
  import { StyleSheet } from 'react-native-unistyles';
2
2
 
3
- import { getRegisteredMoleculesComponentStyles, registerComponentsStyles } from '../../core';
3
+ import { getRegisteredComponentStylesWithFallback } from '../../core';
4
4
 
5
5
  const tooltipStylesDefault = StyleSheet.create(theme => ({
6
6
  content: {
@@ -14,8 +14,7 @@ const tooltipStylesDefault = StyleSheet.create(theme => ({
14
14
  },
15
15
  }));
16
16
 
17
- registerComponentsStyles({
18
- Tooltip: tooltipStylesDefault,
19
- });
20
-
21
- export const tooltipStyles = getRegisteredMoleculesComponentStyles('Tooltip');
17
+ export const tooltipStyles = getRegisteredComponentStylesWithFallback(
18
+ 'Tooltip',
19
+ tooltipStylesDefault,
20
+ );
@@ -1,4 +1,4 @@
1
- import React, { forwardRef, memo, useMemo } from 'react';
1
+ import { type ComponentProps, forwardRef, memo, type ReactNode, useMemo } from 'react';
2
2
  import {
3
3
  type BackgroundPropType,
4
4
  Platform,
@@ -7,25 +7,44 @@ import {
7
7
  StyleSheet,
8
8
  TouchableNativeFeedback,
9
9
  TouchableWithoutFeedback,
10
- View,
11
10
  type ViewStyle,
12
11
  } from 'react-native';
13
- import { withUnistyles } from 'react-native-unistyles';
14
12
 
13
+ import { extractPropertiesFromStyles } from '../../utils/extractPropertiesFromStyles';
14
+ import { Slot } from '../Slot';
15
15
  import { touchableRippleStyles } from './utils';
16
16
 
17
17
  const ANDROID_VERSION_LOLLIPOP = 21;
18
18
  const ANDROID_VERSION_PIE = 28;
19
19
 
20
- type Props = React.ComponentProps<typeof TouchableWithoutFeedback> & {
20
+ type Props = ComponentProps<typeof TouchableWithoutFeedback> & {
21
21
  borderless?: boolean;
22
22
  background?: BackgroundPropType;
23
23
  disabled?: boolean;
24
24
  onPress?: () => void | null;
25
25
  rippleColor?: string;
26
26
  underlayColor?: string;
27
- children: React.ReactNode;
27
+ children: ReactNode;
28
28
  style?: StyleProp<ViewStyle>;
29
+ /**
30
+ * When `true`, the component will not render a wrapper element. Instead, it will
31
+ * merge its props (styles, event handlers, ref) onto its immediate child element.
32
+ * This follows the Radix UI "Slot" pattern for flexible component composition.
33
+ *
34
+ * @note On Android, the native ripple effect will NOT work when `asChild` is `true`
35
+ * because `TouchableNativeFeedback` requires a View wrapper. Only press events will work.
36
+ *
37
+ * @example
38
+ * ```tsx
39
+ * <TouchableRipple asChild onPress={handlePress}>
40
+ * <View><Text>Custom pressable</Text></View>
41
+ * </TouchableRipple>
42
+ * ```
43
+ *
44
+ * @note When `asChild` is `true`, only a single child element is allowed.
45
+ * @default false
46
+ */
47
+ asChild?: boolean;
29
48
  };
30
49
 
31
50
  const TouchableRipple = (
@@ -37,17 +56,22 @@ const TouchableRipple = (
37
56
  rippleColor: rippleColorProp,
38
57
  underlayColor: underlayColorProp,
39
58
  children,
59
+ asChild = false,
40
60
  ...rest
41
61
  }: Props,
42
62
  ref: any,
43
63
  ) => {
44
- const disabled = disabledProp || !rest.onPress;
64
+ const disabled = disabledProp;
45
65
 
46
66
  const componentStyles = touchableRippleStyles;
47
67
 
48
68
  const { rippleColor, underlayColor, containerStyle } = useMemo(() => {
69
+ const { rippleColor: _rippleColor } = extractPropertiesFromStyles(
70
+ [componentStyles.root, style],
71
+ ['rippleColor'],
72
+ );
49
73
  return {
50
- rippleColor: rippleColorProp,
74
+ rippleColor: rippleColorProp || _rippleColor,
51
75
  underlayColor: underlayColorProp || rippleColorProp,
52
76
  containerStyle: [borderless && styles.borderless, componentStyles.root, style],
53
77
  };
@@ -58,6 +82,21 @@ const TouchableRipple = (
58
82
  const useForeground =
59
83
  Platform.OS === 'android' && Platform.Version >= ANDROID_VERSION_PIE && borderless;
60
84
 
85
+ if (asChild) {
86
+ // When asChild is true, use Slot to merge props with the child
87
+ // Note: TouchableNativeFeedback ripple won't work with asChild since it requires a View wrapper
88
+ return (
89
+ <Slot
90
+ {...rest}
91
+ style={containerStyle}
92
+ ref={ref}
93
+ onPress={rest.onPress}
94
+ disabled={disabled}>
95
+ {children}
96
+ </Slot>
97
+ );
98
+ }
99
+
61
100
  if (TouchableRipple.supported) {
62
101
  return (
63
102
  <TouchableNativeFeedback
@@ -65,12 +104,13 @@ const TouchableRipple = (
65
104
  ref={ref}
66
105
  disabled={disabled}
67
106
  useForeground={useForeground}
107
+ style={containerStyle}
68
108
  background={
69
109
  background != null
70
110
  ? background
71
111
  : TouchableNativeFeedback.Ripple(rippleColor!, borderless)
72
112
  }>
73
- <View style={containerStyle}>{React.Children.only(children)}</View>
113
+ <>{children}</>
74
114
  </TouchableNativeFeedback>
75
115
  );
76
116
  }
@@ -84,7 +124,7 @@ const TouchableRipple = (
84
124
  containerStyle,
85
125
  pressed && { backgroundColor: underlayColor },
86
126
  ]}>
87
- {React.Children.only(children)}
127
+ {children}
88
128
  </Pressable>
89
129
  );
90
130
  };
@@ -98,8 +138,4 @@ const styles = StyleSheet.create({
98
138
  TouchableRipple.supported =
99
139
  Platform.OS === 'android' && Platform.Version >= ANDROID_VERSION_LOLLIPOP;
100
140
 
101
- export default memo(
102
- withUnistyles(forwardRef(TouchableRipple), theme => ({
103
- rippleColor: theme.colors.onSurfaceRipple,
104
- })),
105
- );
141
+ export default memo(forwardRef(TouchableRipple));