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

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.
@@ -1,14 +1,7 @@
1
- export { default as Select } from './Select';
2
- export type {
3
- DefaultItemT,
4
- SelectContentProps,
5
- SelectContextValue,
6
- SelectDropdownContextValue,
7
- SelectDropdownProps,
8
- SelectGroupProps,
9
- SelectOptionProps,
10
- SelectProviderProps,
11
- SelectSearchInputProps,
12
- SelectTriggerProps,
13
- SelectValueProps,
14
- } from './types';
1
+ import { getRegisteredComponentWithFallback } from '../../core';
2
+ import SelectDefault from './Select';
3
+
4
+ export const Select = getRegisteredComponentWithFallback('Select', SelectDefault);
5
+
6
+ export type * from './types';
7
+ export * from './utils';
@@ -38,7 +38,7 @@ export type SelectDropdownContextValue = {
38
38
  };
39
39
 
40
40
  // SelectProvider props
41
- export type SelectProviderProps<Option extends DefaultItemT = DefaultItemT> = {
41
+ export type SelectProps<Option extends DefaultItemT = DefaultItemT> = {
42
42
  children: ReactNode;
43
43
  value?: Option['id'] | Option['id'][] | null;
44
44
  defaultValue?: Option['id'] | Option['id'][] | null;
@@ -110,6 +110,4 @@ export type SelectOptionProps<Option extends DefaultItemT = DefaultItemT> = View
110
110
  };
111
111
 
112
112
  // Select.SearchInput props
113
- export type SelectSearchInputProps = TextInputProps & {
114
- onQueryChange?: (query: string) => void;
115
- };
113
+ export type SelectSearchInputProps = Omit<TextInputProps, 'value' | 'onChangeText'> & {};
@@ -0,0 +1,215 @@
1
+ import type { View } from 'react-native';
2
+ import { StyleSheet } from 'react-native-unistyles';
3
+
4
+ import { getRegisteredComponentStylesWithFallback } from '../../core';
5
+ import { createFastContext } from '../../fast-context';
6
+ import { registerPortalContext } from '../Portal';
7
+ import type { DefaultItemT, SelectContextValue, SelectDropdownContextValue } from './types';
8
+
9
+ // SelectContext - holds value, onAdd, onRemove with fast-context for optimized rendering
10
+ const selectContextDefaultValue: SelectContextValue<DefaultItemT> = {
11
+ value: null,
12
+ multiple: false,
13
+ onAdd: () => {},
14
+ onRemove: () => {},
15
+ disabled: false,
16
+ error: false,
17
+ labelKey: 'label',
18
+ options: [],
19
+ searchQuery: '',
20
+ setSearchQuery: () => {},
21
+ filteredOptions: [],
22
+ };
23
+
24
+ const {
25
+ useStoreRef: useSelectStoreRef,
26
+ Provider: SelectContextProvider,
27
+ useContext: useSelectContext,
28
+ useContextValue: useSelectContextValue,
29
+ Context: SelectContext,
30
+ } = createFastContext<SelectContextValue<DefaultItemT>>(selectContextDefaultValue, true);
31
+
32
+ export {
33
+ SelectContext,
34
+ SelectContextProvider,
35
+ useSelectContext,
36
+ useSelectContextValue,
37
+ useSelectStoreRef,
38
+ };
39
+
40
+ // SelectDropdownContext - holds isOpen, onClose, triggerRef with fast-context
41
+ export type SelectDropdownContextType = SelectDropdownContextValue & {
42
+ triggerRef: React.RefObject<View> | null;
43
+ contentRef: React.RefObject<any> | null;
44
+ triggerLayout: { width: number; height: number } | null;
45
+ setTriggerLayout: (layout: { width: number; height: number }) => void;
46
+ };
47
+
48
+ const selectDropdownContextDefaultValue: SelectDropdownContextType = {
49
+ isOpen: false,
50
+ onClose: () => {},
51
+ onOpen: () => {},
52
+ triggerRef: null,
53
+ contentRef: null,
54
+ triggerLayout: null,
55
+ setTriggerLayout: () => {},
56
+ };
57
+
58
+ const {
59
+ useStoreRef: useSelectDropdownStoreRef,
60
+ Provider: SelectDropdownContextProvider,
61
+ useContext: useSelectDropdownContext,
62
+ useContextValue: useSelectDropdownContextValue,
63
+ Context: SelectDropdownContext,
64
+ } = createFastContext<SelectDropdownContextType>(selectDropdownContextDefaultValue, true);
65
+
66
+ export {
67
+ SelectDropdownContext,
68
+ SelectDropdownContextProvider,
69
+ useSelectDropdownContext,
70
+ useSelectDropdownContextValue,
71
+ useSelectDropdownStoreRef,
72
+ };
73
+
74
+ registerPortalContext([SelectContext, SelectDropdownContext]);
75
+
76
+ const triggerDefaultStyles = StyleSheet.create(theme => ({
77
+ trigger: {
78
+ borderRadius: theme.shapes.corner.extraSmall,
79
+ paddingHorizontal: theme.spacings['3'],
80
+ paddingVertical: theme.spacings['2'],
81
+ minHeight: 48,
82
+ flexDirection: 'row',
83
+ alignItems: 'center',
84
+ justifyContent: 'space-between',
85
+ width: '100%',
86
+ variants: {
87
+ state: {
88
+ disabled: {
89
+ opacity: 0.38,
90
+ backgroundColor: theme.colors.surfaceVariant,
91
+ },
92
+ errorDisabled: {
93
+ opacity: 0.38,
94
+ },
95
+ },
96
+ },
97
+ },
98
+ outline: {
99
+ position: 'absolute',
100
+ top: 0,
101
+ left: 0,
102
+ right: 0,
103
+ bottom: 0,
104
+ borderRadius: theme.shapes.corner.extraSmall,
105
+ borderWidth: 1,
106
+ borderColor: theme.colors.outline,
107
+ pointerEvents: 'none',
108
+ variants: {
109
+ state: {
110
+ focused: {
111
+ borderWidth: 2,
112
+ borderColor: theme.colors.primary,
113
+ },
114
+ hovered: {
115
+ borderColor: theme.colors.onSurface,
116
+ },
117
+ hoveredAndFocused: {
118
+ borderWidth: 2,
119
+ borderColor: theme.colors.primary,
120
+ },
121
+ disabled: {
122
+ borderColor: theme.colors.onSurface,
123
+ },
124
+ error: {
125
+ borderColor: theme.colors.error,
126
+ },
127
+ errorFocused: {
128
+ borderWidth: 2,
129
+ borderColor: theme.colors.error,
130
+ },
131
+ errorHovered: {
132
+ borderColor: theme.colors.onErrorContainer,
133
+ },
134
+ errorFocusedAndHovered: {
135
+ borderWidth: 2,
136
+ borderColor: theme.colors.error,
137
+ },
138
+ errorDisabled: {
139
+ borderColor: theme.colors.error,
140
+ },
141
+ },
142
+ },
143
+ },
144
+ triggerIcon: {
145
+ marginLeft: theme.spacings['2'],
146
+ color: theme.colors.onSurfaceVariant,
147
+ },
148
+ }));
149
+
150
+ export const defaultStyles = StyleSheet.create(theme => ({
151
+ chipContainer: {
152
+ flexDirection: 'row',
153
+ flexWrap: 'wrap',
154
+ gap: 6,
155
+ maxWidth: '90%',
156
+ },
157
+ groupLabel: {
158
+ paddingHorizontal: theme.spacings['4'],
159
+ paddingVertical: theme.spacings['2'],
160
+ fontWeight: '600',
161
+ color: theme.colors.onSurface,
162
+ },
163
+ item: {
164
+ paddingHorizontal: theme.spacings['4'],
165
+ paddingVertical: theme.spacings['3'],
166
+ backgroundColor: 'transparent',
167
+
168
+ _web: {
169
+ cursor: 'pointer',
170
+ outlineStyle: 'none',
171
+ _hover: {
172
+ backgroundColor: theme.colors.stateLayer.hover.primary,
173
+ },
174
+ _focus: {
175
+ backgroundColor: theme.colors.stateLayer.focussed.primary,
176
+ },
177
+ },
178
+ },
179
+ itemSelected: {
180
+ backgroundColor: theme.colors.stateLayer.hover.primary,
181
+ },
182
+ itemDisabled: {
183
+ opacity: 0.38,
184
+ _web: {
185
+ cursor: 'not-allowed',
186
+ },
187
+ },
188
+ itemDisabledText: {
189
+ color: theme.colors.onSurfaceVariant,
190
+ },
191
+ searchInput: {
192
+ marginHorizontal: theme.spacings['2'],
193
+ marginVertical: theme.spacings['3'],
194
+ },
195
+ searchInputInput: {
196
+ height: 42,
197
+ },
198
+ emptyState: {
199
+ paddingHorizontal: theme.spacings['4'],
200
+ paddingVertical: theme.spacings['6'],
201
+ alignItems: 'center',
202
+ justifyContent: 'center',
203
+ },
204
+ emptyStateText: {
205
+ color: theme.colors.onSurfaceVariant,
206
+ fontSize: 14,
207
+ },
208
+ }));
209
+
210
+ export const triggerStyles = getRegisteredComponentStylesWithFallback(
211
+ 'Select_Trigger',
212
+ triggerDefaultStyles,
213
+ );
214
+
215
+ export const styles = getRegisteredComponentStylesWithFallback('Select', defaultStyles);
@@ -0,0 +1,244 @@
1
+ import { composeRefs } from '@radix-ui/react-compose-refs';
2
+ import * as React from 'react';
3
+ import { type PressableProps, type StyleProp, type ViewProps, type ViewStyle } from 'react-native';
4
+
5
+ declare module 'react' {
6
+ interface ReactElement {
7
+ $$typeof?: symbol | string;
8
+ }
9
+ }
10
+
11
+ const REACT_LAZY_TYPE = Symbol.for('react.lazy');
12
+
13
+ interface LazyReactElement extends React.ReactElement {
14
+ $$typeof: typeof REACT_LAZY_TYPE;
15
+ _payload: PromiseLike<Exclude<React.ReactNode, PromiseLike<any>>>;
16
+ }
17
+
18
+ /* -------------------------------------------------------------------------------------------------
19
+ * Slot
20
+ * -----------------------------------------------------------------------------------------------*/
21
+
22
+ export type Usable<T> = PromiseLike<T> | React.Context<T>;
23
+ const use: typeof React.use | undefined = (React as any)[' use '.trim().toString()];
24
+
25
+ interface SlotProps
26
+ extends Omit<ViewProps, 'children'>,
27
+ Partial<
28
+ Pick<
29
+ PressableProps,
30
+ 'onPress' | 'onPressIn' | 'onPressOut' | 'onLongPress' | 'disabled'
31
+ >
32
+ > {
33
+ children?: React.ReactNode;
34
+ }
35
+
36
+ function isPromiseLike(value: unknown): value is PromiseLike<unknown> {
37
+ return typeof value === 'object' && value !== null && 'then' in value;
38
+ }
39
+
40
+ function isLazyComponent(element: React.ReactNode): element is LazyReactElement {
41
+ return (
42
+ element != null &&
43
+ typeof element === 'object' &&
44
+ '$$typeof' in element &&
45
+ element.$$typeof === REACT_LAZY_TYPE &&
46
+ '_payload' in element &&
47
+ isPromiseLike(element._payload)
48
+ );
49
+ }
50
+
51
+ /* @__NO_SIDE_EFFECTS__ */ export function createSlot(ownerName: string) {
52
+ const SlotClone = createSlotClone(ownerName);
53
+ const Slot = React.forwardRef<any, SlotProps>((props, forwardedRef) => {
54
+ const { children: childrenProp, ...slotProps } = props;
55
+ let children = childrenProp;
56
+ if (isLazyComponent(children) && typeof use === 'function') {
57
+ children = use(children._payload);
58
+ }
59
+ const childrenArray = React.Children.toArray(children);
60
+ const slottable = childrenArray.find(isSlottable);
61
+
62
+ if (slottable) {
63
+ // the new element to render is the one passed as a child of `Slottable`
64
+ const newElement = slottable.props.children;
65
+
66
+ const newChildren = childrenArray.map(child => {
67
+ if (child === slottable) {
68
+ // because the new element will be the one rendered, we are only interested
69
+ // in grabbing its children (`newElement.props.children`)
70
+ if (React.Children.count(newElement) > 1) return React.Children.only(null);
71
+ return React.isValidElement(newElement)
72
+ ? (newElement.props as { children: React.ReactNode }).children
73
+ : null;
74
+ } else {
75
+ return child;
76
+ }
77
+ });
78
+
79
+ return (
80
+ <SlotClone {...slotProps} ref={forwardedRef}>
81
+ {React.isValidElement(newElement)
82
+ ? React.cloneElement(newElement, undefined, newChildren)
83
+ : null}
84
+ </SlotClone>
85
+ );
86
+ }
87
+
88
+ return (
89
+ <SlotClone {...slotProps} ref={forwardedRef}>
90
+ {children}
91
+ </SlotClone>
92
+ );
93
+ });
94
+
95
+ Slot.displayName = `${ownerName}.Slot`;
96
+ return Slot;
97
+ }
98
+
99
+ const Slot = createSlot('Slot');
100
+
101
+ /* -------------------------------------------------------------------------------------------------
102
+ * SlotClone
103
+ * -----------------------------------------------------------------------------------------------*/
104
+
105
+ interface SlotCloneProps {
106
+ children: React.ReactNode;
107
+ }
108
+
109
+ /* @__NO_SIDE_EFFECTS__ */ function createSlotClone(ownerName: string) {
110
+ const SlotClone = React.forwardRef<any, SlotCloneProps>((props, forwardedRef) => {
111
+ const { children: childrenProp, ...slotProps } = props;
112
+ let children = childrenProp;
113
+ if (isLazyComponent(children) && typeof use === 'function') {
114
+ children = use(children._payload);
115
+ }
116
+
117
+ if (React.isValidElement(children)) {
118
+ const childrenRef = getElementRef(children);
119
+ const mergedProps = mergeProps(slotProps, children.props as AnyProps);
120
+ // do not pass ref to React.Fragment for React 19 compatibility
121
+ if (children.type !== React.Fragment) {
122
+ mergedProps.ref = forwardedRef
123
+ ? composeRefs(forwardedRef, childrenRef)
124
+ : childrenRef;
125
+ }
126
+ return React.cloneElement(children, mergedProps);
127
+ }
128
+
129
+ return React.Children.count(children) > 1 ? React.Children.only(null) : null;
130
+ });
131
+
132
+ SlotClone.displayName = `${ownerName}.SlotClone`;
133
+ return SlotClone;
134
+ }
135
+
136
+ /* -------------------------------------------------------------------------------------------------
137
+ * Slottable
138
+ * -----------------------------------------------------------------------------------------------*/
139
+
140
+ const SLOTTABLE_IDENTIFIER = Symbol('radix.slottable');
141
+
142
+ interface SlottableProps {
143
+ children: React.ReactNode;
144
+ }
145
+
146
+ export interface SlottableComponent extends React.FC<SlottableProps> {
147
+ __radixId: symbol;
148
+ }
149
+
150
+ /* @__NO_SIDE_EFFECTS__ */ export function createSlottable(ownerName: string) {
151
+ const Slottable: SlottableComponent = ({ children }) => {
152
+ return <>{children}</>;
153
+ };
154
+ Slottable.displayName = `${ownerName}.Slottable`;
155
+ Slottable.__radixId = SLOTTABLE_IDENTIFIER;
156
+ return Slottable;
157
+ }
158
+
159
+ const Slottable = createSlottable('Slottable');
160
+
161
+ /* ---------------------------------------------------------------------------------------------- */
162
+
163
+ type AnyProps = Record<string, any>;
164
+
165
+ function isSlottable(
166
+ child: React.ReactNode,
167
+ ): child is React.ReactElement<SlottableProps, typeof Slottable> {
168
+ return (
169
+ React.isValidElement(child) &&
170
+ typeof child.type === 'function' &&
171
+ '__radixId' in child.type &&
172
+ child.type.__radixId === SLOTTABLE_IDENTIFIER
173
+ );
174
+ }
175
+
176
+ function mergeProps(slotProps: AnyProps, childProps: AnyProps) {
177
+ // all child props should override
178
+ const overrideProps = { ...childProps };
179
+
180
+ for (const propName in childProps) {
181
+ const slotPropValue = slotProps[propName];
182
+ const childPropValue = childProps[propName];
183
+
184
+ const isHandler = /^on[A-Z]/.test(propName);
185
+ if (isHandler) {
186
+ // if the handler exists on both, we compose them
187
+ if (slotPropValue && childPropValue) {
188
+ overrideProps[propName] = (...args: unknown[]) => {
189
+ const result = childPropValue(...args);
190
+ slotPropValue(...args);
191
+ return result;
192
+ };
193
+ }
194
+ // but if it exists only on the slot, we use only this one
195
+ else if (slotPropValue) {
196
+ overrideProps[propName] = slotPropValue;
197
+ }
198
+ }
199
+ // if it's `style`, we merge them (React Native styles can be arrays)
200
+ else if (propName === 'style') {
201
+ const slotStyle = slotPropValue as StyleProp<ViewStyle> | undefined;
202
+ const childStyle = childPropValue as StyleProp<ViewStyle> | undefined;
203
+ if (slotStyle || childStyle) {
204
+ overrideProps[propName] = [slotStyle, childStyle].filter(
205
+ Boolean,
206
+ ) as StyleProp<ViewStyle>;
207
+ }
208
+ }
209
+ }
210
+
211
+ return { ...slotProps, ...overrideProps };
212
+ }
213
+
214
+ // Before React 19 accessing `element.props.ref` will throw a warning and suggest using `element.ref`
215
+ // After React 19 accessing `element.ref` does the opposite.
216
+ // https://github.com/facebook/react/pull/28348
217
+ //
218
+ // Access the ref using the method that doesn't yield a warning.
219
+ function getElementRef(element: React.ReactElement) {
220
+ // React <=18 in DEV
221
+ let getter = Object.getOwnPropertyDescriptor(element.props, 'ref')?.get;
222
+ let mayWarn = getter && 'isReactWarning' in getter && getter.isReactWarning;
223
+ if (mayWarn) {
224
+ return (element as any).ref;
225
+ }
226
+
227
+ // React 19 in DEV
228
+ getter = Object.getOwnPropertyDescriptor(element, 'ref')?.get;
229
+ mayWarn = getter && 'isReactWarning' in getter && getter.isReactWarning;
230
+ if (mayWarn) {
231
+ return (element.props as { ref?: React.Ref<unknown> }).ref;
232
+ }
233
+
234
+ // Not DEV
235
+ return (element.props as { ref?: React.Ref<unknown> }).ref || (element as any).ref;
236
+ }
237
+
238
+ export {
239
+ //
240
+ Slot as Root,
241
+ Slot,
242
+ Slottable,
243
+ };
244
+ export type { SlotProps };
@@ -0,0 +1,60 @@
1
+ import * as React from 'react';
2
+
3
+ type PossibleRef<T> = React.Ref<T> | undefined;
4
+
5
+ /**
6
+ * Set a given ref to a given value
7
+ * This utility takes care of different types of refs: callback refs and RefObject(s)
8
+ */
9
+ function setRef<T>(ref: PossibleRef<T>, value: T) {
10
+ if (typeof ref === 'function') {
11
+ return ref(value);
12
+ } else if (ref !== null && ref !== undefined) {
13
+ ref.current = value;
14
+ }
15
+ }
16
+
17
+ /**
18
+ * A utility to compose multiple refs together
19
+ * Accepts callback refs and RefObject(s)
20
+ */
21
+ function composeRefs<T>(...refs: PossibleRef<T>[]): React.RefCallback<T> {
22
+ return node => {
23
+ let hasCleanup = false;
24
+ const cleanups = refs.map(ref => {
25
+ const cleanup = setRef(ref, node);
26
+ if (!hasCleanup && typeof cleanup === 'function') {
27
+ hasCleanup = true;
28
+ }
29
+ return cleanup;
30
+ });
31
+
32
+ // React <19 will log an error to the console if a callback ref returns a
33
+ // value. We don't use ref cleanups internally so this will only happen if a
34
+ // user's ref callback returns a value, which we only expect if they are
35
+ // using the cleanup functionality added in React 19.
36
+ if (hasCleanup) {
37
+ return () => {
38
+ for (let i = 0; i < cleanups.length; i++) {
39
+ const cleanup = cleanups[i];
40
+ if (typeof cleanup === 'function') {
41
+ cleanup();
42
+ } else {
43
+ setRef(refs[i], null);
44
+ }
45
+ }
46
+ };
47
+ }
48
+ };
49
+ }
50
+
51
+ /**
52
+ * A custom hook that composes multiple refs
53
+ * Accepts callback refs and RefObject(s)
54
+ */
55
+ function useComposedRefs<T>(...refs: PossibleRef<T>[]): React.RefCallback<T> {
56
+ // eslint-disable-next-line react-hooks/exhaustive-deps
57
+ return React.useCallback(composeRefs(...refs), refs);
58
+ }
59
+
60
+ export { composeRefs, useComposedRefs };
@@ -0,0 +1,8 @@
1
+ import { getRegisteredComponentWithFallback } from '../../core';
2
+ import { Slot as SlotComponent, Slottable } from './Slot';
3
+
4
+ const SlotDefault = Object.assign(SlotComponent, { Slottable, Root: SlotComponent });
5
+
6
+ export const Slot = getRegisteredComponentWithFallback('Slot', SlotDefault);
7
+
8
+ export { createSlot, createSlottable, type SlotProps } from './Slot';
@@ -2,11 +2,13 @@ import { forwardRef, memo, type ReactNode, useMemo } from 'react';
2
2
  import { Animated, type StyleProp, View, type ViewProps, type ViewStyle } from 'react-native';
3
3
  import { useUnistyles } from 'react-native-unistyles';
4
4
 
5
- import { inputRange } from '../../styles/shadow';
6
5
  import type { MD3Elevation } from '../../types/theme';
7
6
  import { extractPropertiesFromStyles } from '../../utils/extractPropertiesFromStyles';
7
+ import { Slot } from '../Slot';
8
8
  import { BackgroundContextWrapper } from './BackgroundContextWrapper';
9
- import { defaultStyles, getElevationAndroid } from './utils';
9
+ import { defaultStyles } from './utils';
10
+
11
+ const AnimatedView = Animated.createAnimatedComponent(View);
10
12
 
11
13
  export type Props = ViewProps & {
12
14
  /**
@@ -20,11 +22,19 @@ export type Props = ViewProps & {
20
22
  * TestID used for testing purposes
21
23
  */
22
24
  testID?: string;
25
+ /**
26
+ * Change the component to the HTML tag or custom component use the passed child.
27
+ * This will merge the props of the Surface with the props of the child element.
28
+ */
29
+ asChild?: boolean;
23
30
  };
24
31
 
25
32
  const elevationLevel = [0, 1, 2, 6, 8, 12];
26
33
 
27
- const Surface = ({ elevation = 1, style, children, testID, ...props }: Props, ref: any) => {
34
+ const Surface = (
35
+ { elevation: _elevation = 1, style, children, testID, asChild = false, ...props }: Props,
36
+ ref: any,
37
+ ) => {
28
38
  const { theme } = useUnistyles();
29
39
 
30
40
  const backgroundColor = (() => {
@@ -33,6 +43,7 @@ const Surface = ({ elevation = 1, style, children, testID, ...props }: Props, re
33
43
  })();
34
44
 
35
45
  const { memoizedStyles, surfaceBackground } = useMemo(() => {
46
+ const elevation = typeof _elevation === 'number' ? (_elevation > 5 ? 5 : _elevation) : 0;
36
47
  return {
37
48
  memoizedStyles: [
38
49
  {
@@ -41,7 +52,7 @@ const Surface = ({ elevation = 1, style, children, testID, ...props }: Props, re
41
52
  defaultStyles.root,
42
53
  style,
43
54
  {
44
- elevation: getElevationAndroid(elevation, inputRange, elevationLevel),
55
+ elevation: elevationLevel[elevation],
45
56
  },
46
57
  ] as StyleProp<ViewStyle>,
47
58
  surfaceBackground: extractPropertiesFromStyles(
@@ -49,13 +60,15 @@ const Surface = ({ elevation = 1, style, children, testID, ...props }: Props, re
49
60
  ['backgroundColor'],
50
61
  ).backgroundColor,
51
62
  };
52
- }, [backgroundColor, elevation, style]);
63
+ }, [backgroundColor, _elevation, style]);
64
+
65
+ const Component = asChild ? Slot : AnimatedView;
53
66
 
54
67
  return (
55
68
  <BackgroundContextWrapper backgroundColor={surfaceBackground}>
56
- <View ref={ref} {...props} testID={testID} style={memoizedStyles}>
69
+ <Component ref={ref} {...props} testID={testID} style={memoizedStyles}>
57
70
  {children}
58
- </View>
71
+ </Component>
59
72
  </BackgroundContextWrapper>
60
73
  );
61
74
  };