react-native-molecules 0.5.0-beta.20 → 0.5.0-beta.22
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.
- package/components/Card/Card.tsx +1 -1
- package/components/Checkbox/CheckboxBase.ios.tsx +9 -16
- package/components/Checkbox/CheckboxBase.tsx +11 -18
- package/components/DateField/DateField.tsx +4 -3
- package/components/DatePicker/DateCalendar.tsx +4 -4
- package/components/DatePicker/DatePickerModal.tsx +35 -23
- package/components/DatePicker/DatePickerProvider.tsx +8 -2
- package/components/DatePicker/context.tsx +2 -1
- package/components/DatePicker/index.tsx +1 -0
- package/components/DatePickerInline/DatePickerDockedHeader.tsx +11 -7
- package/components/DatePickerInline/DatePickerInline.tsx +1 -1
- package/components/DatePickerInline/DatePickerInlineBase.tsx +3 -3
- package/components/DatePickerInline/DatePickerInlineHeader.tsx +50 -20
- package/components/DatePickerInline/DayNames.tsx +13 -10
- package/components/DatePickerInline/HeaderItem.tsx +2 -2
- package/components/DatePickerInline/Month.tsx +4 -3
- package/components/DatePickerInline/MonthPicker.tsx +74 -54
- package/components/DatePickerInline/Swiper.native.tsx +2 -2
- package/components/DatePickerInline/Swiper.tsx +3 -3
- package/components/DatePickerInline/YearPicker.tsx +136 -112
- package/components/DatePickerInline/{DatePickerContext.tsx → store.tsx} +7 -3
- package/components/DatePickerInline/types.ts +4 -3
- package/components/Divider/Divider.tsx +192 -0
- package/components/Divider/index.tsx +11 -0
- package/components/Drawer/DrawerItemGroup.tsx +3 -7
- package/components/IconButton/IconButton.tsx +2 -12
- package/components/List/List.tsx +507 -0
- package/components/List/context.tsx +28 -0
- package/components/List/index.ts +9 -0
- package/components/List/types.ts +149 -0
- package/components/{ListItem → List}/utils.ts +47 -50
- package/components/Menu/Menu.tsx +156 -12
- package/components/Menu/index.tsx +11 -7
- package/components/Menu/utils.ts +21 -70
- package/components/RadioButton/RadioButtonAndroid.tsx +38 -54
- package/components/RadioButton/RadioButtonIOS.tsx +2 -16
- package/components/Select/Select.tsx +139 -497
- package/components/Select/context.tsx +14 -32
- package/components/Select/types.ts +44 -53
- package/components/Select/utils.ts +15 -47
- package/components/Text/textFactory.tsx +17 -5
- package/components/TimeField/TimeField.tsx +1 -1
- package/components/TimePicker/TimeInput.tsx +2 -7
- package/components/TimePicker/TimePickerModal.tsx +15 -15
- package/components/TimePicker/utils.ts +0 -4
- package/components/TouchableRipple/TouchableRipple.native.tsx +36 -5
- package/components/TouchableRipple/TouchableRipple.tsx +53 -19
- package/components/TouchableRipple/rippleFromForegroundColor.ts +21 -0
- package/package.json +4 -2
- package/components/HorizontalDivider/HorizontalDivider.tsx +0 -103
- package/components/HorizontalDivider/index.tsx +0 -9
- package/components/ListItem/ListItem.tsx +0 -138
- package/components/ListItem/ListItemDescription.tsx +0 -25
- package/components/ListItem/ListItemTitle.tsx +0 -25
- package/components/ListItem/index.tsx +0 -14
- package/components/Menu/MenuDivider.tsx +0 -13
- package/components/Menu/MenuItem.tsx +0 -128
- package/components/VerticalDivider/VerticalDivider.tsx +0 -100
- package/components/VerticalDivider/index.tsx +0 -9
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { forwardRef, memo, type ReactNode, useCallback,
|
|
1
|
+
import { forwardRef, memo, type ReactNode, useCallback, useRef } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
type GestureResponderEvent,
|
|
4
|
+
Platform,
|
|
4
5
|
Pressable,
|
|
5
6
|
type PressableProps,
|
|
6
7
|
type StyleProp,
|
|
@@ -9,7 +10,9 @@ import {
|
|
|
9
10
|
} from 'react-native';
|
|
10
11
|
import { StyleSheet } from 'react-native-unistyles';
|
|
11
12
|
|
|
13
|
+
import { useTheme } from '../../hooks/useTheme';
|
|
12
14
|
import { Slot } from '../Slot';
|
|
15
|
+
import { rippleColorFromBackground } from './rippleFromForegroundColor';
|
|
13
16
|
import { touchableRippleStyles } from './utils';
|
|
14
17
|
|
|
15
18
|
export type Props = PressableProps & {
|
|
@@ -46,6 +49,11 @@ export type Props = PressableProps & {
|
|
|
46
49
|
* Color of the underlay for the highlight effect (Android < 5.0 and iOS).
|
|
47
50
|
*/
|
|
48
51
|
underlayColor?: string;
|
|
52
|
+
/**
|
|
53
|
+
* Alpha used for auto-derived ripple color when `rippleColor` is not provided.
|
|
54
|
+
* @default 0.24
|
|
55
|
+
*/
|
|
56
|
+
rippleAlpha?: number;
|
|
49
57
|
/**
|
|
50
58
|
* Content of the `TouchableRipple`.
|
|
51
59
|
*/
|
|
@@ -114,6 +122,7 @@ const TouchableRipple = (
|
|
|
114
122
|
disabled: disabledProp,
|
|
115
123
|
rippleColor: rippleColorProp,
|
|
116
124
|
underlayColor: _underlayColor,
|
|
125
|
+
rippleAlpha = 0.24,
|
|
117
126
|
onPress,
|
|
118
127
|
children,
|
|
119
128
|
onPressIn: onPressInProp,
|
|
@@ -126,24 +135,27 @@ const TouchableRipple = (
|
|
|
126
135
|
) => {
|
|
127
136
|
// TODO - enable ripple onLongPress, need to check for mobile as well
|
|
128
137
|
const disabled = disabledProp;
|
|
138
|
+
const theme = useTheme();
|
|
129
139
|
|
|
130
140
|
const componentStyles = touchableRippleStyles;
|
|
131
141
|
|
|
132
|
-
const { rippleColor
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
}
|
|
146
|
-
|
|
142
|
+
const { rippleColor: themeRippleFallback } = componentStyles.root;
|
|
143
|
+
|
|
144
|
+
const tokenResolvedColor =
|
|
145
|
+
typeof rippleColorProp === 'string'
|
|
146
|
+
? theme.colors[rippleColorProp as keyof typeof theme.colors]
|
|
147
|
+
: undefined;
|
|
148
|
+
|
|
149
|
+
const rippleColorResolvedProp =
|
|
150
|
+
typeof tokenResolvedColor === 'string' ? tokenResolvedColor : rippleColorProp;
|
|
151
|
+
const containerStyle = [
|
|
152
|
+
styles.touchable,
|
|
153
|
+
{ borderRadius: 'inherit' },
|
|
154
|
+
borderless && styles.borderless,
|
|
155
|
+
// ...(Platform.OS === 'web' && !disabled ? ({ cursor: 'pointer' } as any) : {}),
|
|
156
|
+
componentStyles.root,
|
|
157
|
+
style,
|
|
158
|
+
];
|
|
147
159
|
|
|
148
160
|
// Track whether pointer is currently down for handling pointer leave
|
|
149
161
|
const isPointerDownRef = useRef(false);
|
|
@@ -165,6 +177,16 @@ const TouchableRipple = (
|
|
|
165
177
|
const computedStyle = window.getComputedStyle(button);
|
|
166
178
|
const dimensions = button.getBoundingClientRect();
|
|
167
179
|
|
|
180
|
+
const resolvedRippleColor =
|
|
181
|
+
rippleColorResolvedProp ??
|
|
182
|
+
(Platform.OS === 'web'
|
|
183
|
+
? rippleColorFromBackground(
|
|
184
|
+
computedStyle.backgroundColor,
|
|
185
|
+
String(themeRippleFallback),
|
|
186
|
+
rippleAlpha,
|
|
187
|
+
)
|
|
188
|
+
: String(themeRippleFallback));
|
|
189
|
+
|
|
168
190
|
let touchX: number;
|
|
169
191
|
let touchY: number;
|
|
170
192
|
|
|
@@ -225,7 +247,7 @@ const TouchableRipple = (
|
|
|
225
247
|
Object.assign(ripple.style, {
|
|
226
248
|
position: 'absolute',
|
|
227
249
|
pointerEvents: 'none',
|
|
228
|
-
backgroundColor:
|
|
250
|
+
backgroundColor: resolvedRippleColor,
|
|
229
251
|
borderRadius: '50%',
|
|
230
252
|
|
|
231
253
|
/* Transition configuration */
|
|
@@ -261,7 +283,14 @@ const TouchableRipple = (
|
|
|
261
283
|
});
|
|
262
284
|
});
|
|
263
285
|
},
|
|
264
|
-
[
|
|
286
|
+
[
|
|
287
|
+
onPressInProp,
|
|
288
|
+
disabled,
|
|
289
|
+
centered,
|
|
290
|
+
rippleColorResolvedProp,
|
|
291
|
+
themeRippleFallback,
|
|
292
|
+
rippleAlpha,
|
|
293
|
+
],
|
|
265
294
|
);
|
|
266
295
|
|
|
267
296
|
const fadeOutRipples = useCallback((target: HTMLElement) => {
|
|
@@ -345,9 +374,14 @@ const TouchableRipple = (
|
|
|
345
374
|
onPointerCancel: handlePointerCancel,
|
|
346
375
|
};
|
|
347
376
|
|
|
377
|
+
const accessibilityRoleProp = (rest as { accessibilityRole?: unknown }).accessibilityRole;
|
|
378
|
+
const roleProp = (rest as { role?: unknown }).role;
|
|
379
|
+
const applyDefaultWebButtonRole =
|
|
380
|
+
!!onPress && accessibilityRoleProp === undefined && roleProp === undefined;
|
|
381
|
+
|
|
348
382
|
return (
|
|
349
383
|
<Component
|
|
350
|
-
{...(
|
|
384
|
+
{...(applyDefaultWebButtonRole ? { role: 'button' } : {})}
|
|
351
385
|
{...rest}
|
|
352
386
|
style={containerStyle}
|
|
353
387
|
ref={ref}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import setColor from 'color';
|
|
2
|
+
|
|
3
|
+
/** Ripple ink derived from background color for better contrast. */
|
|
4
|
+
export function rippleColorFromBackground(
|
|
5
|
+
backgroundColor: string | undefined,
|
|
6
|
+
fallback: string,
|
|
7
|
+
alpha: number = 0.24,
|
|
8
|
+
): string {
|
|
9
|
+
if (!backgroundColor || backgroundColor === '') {
|
|
10
|
+
return fallback;
|
|
11
|
+
}
|
|
12
|
+
try {
|
|
13
|
+
const base = setColor(backgroundColor);
|
|
14
|
+
if (base.alpha() < 0.05) {
|
|
15
|
+
return fallback;
|
|
16
|
+
}
|
|
17
|
+
return base.isLight() ? `rgba(0, 0, 0, ${alpha})` : `rgba(255, 255, 255, ${alpha})`;
|
|
18
|
+
} catch {
|
|
19
|
+
return fallback;
|
|
20
|
+
}
|
|
21
|
+
}
|
package/package.json
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-molecules",
|
|
3
|
-
"version": "0.5.0-beta.
|
|
3
|
+
"version": "0.5.0-beta.22",
|
|
4
4
|
"author": "Thet Aung <thetaung.dev@gmail.com>",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "index.ts",
|
|
7
7
|
"sideEffects": [
|
|
8
8
|
"components/DatePicker/context.tsx",
|
|
9
|
+
"components/DatePickerInline/store.tsx",
|
|
10
|
+
"components/List/context.tsx",
|
|
9
11
|
"components/Select/context.tsx",
|
|
10
12
|
"components/TimePicker/context.tsx"
|
|
11
13
|
],
|
|
@@ -78,7 +80,7 @@
|
|
|
78
80
|
"react-native": "0.81.4",
|
|
79
81
|
"react-native-builder-bob": "^0.17.1",
|
|
80
82
|
"react-native-reanimated": "~4.1.1",
|
|
81
|
-
"react-native-unistyles": "^3.
|
|
83
|
+
"react-native-unistyles": "^3.2.4",
|
|
82
84
|
"react-native-web": "~0.21.1"
|
|
83
85
|
},
|
|
84
86
|
"eslintIgnore": [
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
import { memo } from 'react';
|
|
2
|
-
import { type StyleProp, View, type ViewProps, type ViewStyle } from 'react-native';
|
|
3
|
-
import { StyleSheet } from 'react-native-unistyles';
|
|
4
|
-
|
|
5
|
-
import { getRegisteredComponentStylesWithFallback } from '../../core';
|
|
6
|
-
|
|
7
|
-
export type Props = Omit<ViewProps, 'children'> & {
|
|
8
|
-
/**
|
|
9
|
-
* left inset of the divider.
|
|
10
|
-
*/
|
|
11
|
-
leftInset?: number;
|
|
12
|
-
/**
|
|
13
|
-
* right inset of the divider.
|
|
14
|
-
*/
|
|
15
|
-
rightInset?: number;
|
|
16
|
-
/**
|
|
17
|
-
* Whether divider should be bolded.
|
|
18
|
-
*/
|
|
19
|
-
bold?: boolean;
|
|
20
|
-
/**
|
|
21
|
-
* Vertical spacing of the Divider
|
|
22
|
-
*/
|
|
23
|
-
spacing?: number;
|
|
24
|
-
style?: StyleProp<ViewStyle>;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* A divider is a thin, lightweight separator that groups content in lists and page layouts.
|
|
29
|
-
*
|
|
30
|
-
* <div class="screenshots">
|
|
31
|
-
* <figure>
|
|
32
|
-
* <img class="medium" src="screenshots/divider.png" />
|
|
33
|
-
* </figure>
|
|
34
|
-
* </div>
|
|
35
|
-
*
|
|
36
|
-
* ## Usage
|
|
37
|
-
* ```js
|
|
38
|
-
* import * as React from 'react';
|
|
39
|
-
* import { View } from 'react-native';
|
|
40
|
-
* import { Divider, Text } from 'react-native-paper';
|
|
41
|
-
*
|
|
42
|
-
* const MyComponent = () => (
|
|
43
|
-
* <View>
|
|
44
|
-
* <Text>Lemon</Text>
|
|
45
|
-
* <Divider />
|
|
46
|
-
* <Text>Mango</Text>
|
|
47
|
-
* <Divider />
|
|
48
|
-
* </View>
|
|
49
|
-
* );
|
|
50
|
-
*
|
|
51
|
-
* export default MyComponent;
|
|
52
|
-
* ```
|
|
53
|
-
*/
|
|
54
|
-
|
|
55
|
-
const HorizontalDivider = ({
|
|
56
|
-
leftInset = 0,
|
|
57
|
-
rightInset = 0,
|
|
58
|
-
style,
|
|
59
|
-
bold = false,
|
|
60
|
-
spacing = 0,
|
|
61
|
-
...rest
|
|
62
|
-
}: Props) => {
|
|
63
|
-
horizontalDividerStyles.useVariants({
|
|
64
|
-
isBold: bold,
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
return (
|
|
68
|
-
<View
|
|
69
|
-
{...rest}
|
|
70
|
-
style={
|
|
71
|
-
[
|
|
72
|
-
horizontalDividerStyles.root,
|
|
73
|
-
leftInset && { marginLeft: leftInset },
|
|
74
|
-
rightInset && { marginRight: rightInset },
|
|
75
|
-
spacing && { marginVertical: spacing },
|
|
76
|
-
style,
|
|
77
|
-
] as StyleProp<ViewStyle>
|
|
78
|
-
}
|
|
79
|
-
/>
|
|
80
|
-
);
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
export const horizontalDividerStylesDefault = StyleSheet.create(theme => ({
|
|
84
|
-
root: {
|
|
85
|
-
height: StyleSheet.hairlineWidth,
|
|
86
|
-
background: theme.colors.outlineVariant,
|
|
87
|
-
|
|
88
|
-
variants: {
|
|
89
|
-
isBold: {
|
|
90
|
-
true: {
|
|
91
|
-
height: 1,
|
|
92
|
-
},
|
|
93
|
-
},
|
|
94
|
-
},
|
|
95
|
-
},
|
|
96
|
-
}));
|
|
97
|
-
|
|
98
|
-
export const horizontalDividerStyles = getRegisteredComponentStylesWithFallback(
|
|
99
|
-
'HorizontalDivider',
|
|
100
|
-
horizontalDividerStylesDefault,
|
|
101
|
-
);
|
|
102
|
-
|
|
103
|
-
export default memo(HorizontalDivider);
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { getRegisteredComponentWithFallback } from '../../core';
|
|
2
|
-
import HorizontalDividerDefault from './HorizontalDivider';
|
|
3
|
-
|
|
4
|
-
export const HorizontalDivider = getRegisteredComponentWithFallback(
|
|
5
|
-
'HorizontalDivider',
|
|
6
|
-
HorizontalDividerDefault,
|
|
7
|
-
);
|
|
8
|
-
|
|
9
|
-
export { type Props as HorizontalDividerProps, horizontalDividerStyles } from './HorizontalDivider';
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
import { createContext, forwardRef, memo, type ReactNode, useMemo } from 'react';
|
|
2
|
-
import { type StyleProp, View, type ViewStyle } from 'react-native';
|
|
3
|
-
|
|
4
|
-
import { useActionState } from '../../hooks';
|
|
5
|
-
import type { WithElements } from '../../types';
|
|
6
|
-
import { resolveStateVariant } from '../../utils';
|
|
7
|
-
import { HorizontalDivider } from '../HorizontalDivider';
|
|
8
|
-
import { StateLayer } from '../StateLayer';
|
|
9
|
-
import { TouchableRipple, type TouchableRippleProps } from '../TouchableRipple';
|
|
10
|
-
import { listItemStyles } from './utils';
|
|
11
|
-
|
|
12
|
-
export type Props = Omit<TouchableRippleProps, 'children'> &
|
|
13
|
-
WithElements<ReactNode | ((renderArgs: { hovered: boolean }) => ReactNode)> & {
|
|
14
|
-
hovered?: boolean;
|
|
15
|
-
/**
|
|
16
|
-
* Description text for the list item or callback which returns a React element to display the description.
|
|
17
|
-
*/
|
|
18
|
-
children: ReactNode;
|
|
19
|
-
/**
|
|
20
|
-
* Style that is passed to the wrapping TouchableRipple element.
|
|
21
|
-
*/
|
|
22
|
-
style?: StyleProp<ViewStyle>;
|
|
23
|
-
/**
|
|
24
|
-
* Whether the divider shows or not.
|
|
25
|
-
*/
|
|
26
|
-
divider?: boolean;
|
|
27
|
-
/**
|
|
28
|
-
* variant of the ListItem
|
|
29
|
-
*/
|
|
30
|
-
variant?: 'default' | 'menuItem';
|
|
31
|
-
/**
|
|
32
|
-
* Whether the ListItem is selected or not
|
|
33
|
-
*/
|
|
34
|
-
selected?: boolean;
|
|
35
|
-
/**
|
|
36
|
-
* Whether the ListItem is hoverable or not
|
|
37
|
-
* @default true if onPress is passed
|
|
38
|
-
*/
|
|
39
|
-
hoverable?: boolean;
|
|
40
|
-
contentStyle?: StyleProp<ViewStyle>;
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
const ListItem = (
|
|
44
|
-
{
|
|
45
|
-
left,
|
|
46
|
-
right,
|
|
47
|
-
children,
|
|
48
|
-
style: styleProp,
|
|
49
|
-
disabled = false,
|
|
50
|
-
divider = false,
|
|
51
|
-
variant = 'default',
|
|
52
|
-
selected = false,
|
|
53
|
-
onPress,
|
|
54
|
-
hoverable: hoverableProp = false,
|
|
55
|
-
hovered: hoveredProp = false,
|
|
56
|
-
contentStyle: contentStyleProp,
|
|
57
|
-
...props
|
|
58
|
-
}: Props,
|
|
59
|
-
ref: any,
|
|
60
|
-
) => {
|
|
61
|
-
const { hovered: _hovered, actionsRef } = useActionState({ ref, actionsToListen: ['hover'] });
|
|
62
|
-
const hoverable = hoverableProp || !!onPress;
|
|
63
|
-
const hovered = hoveredProp || _hovered;
|
|
64
|
-
|
|
65
|
-
const state = resolveStateVariant({
|
|
66
|
-
selected,
|
|
67
|
-
disabled,
|
|
68
|
-
hovered: hoverable && hovered,
|
|
69
|
-
}) as any;
|
|
70
|
-
|
|
71
|
-
listItemStyles.useVariants({
|
|
72
|
-
state,
|
|
73
|
-
variant: variant as any,
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
const {
|
|
77
|
-
containerStyles,
|
|
78
|
-
innerContainerStyle,
|
|
79
|
-
contentStyle,
|
|
80
|
-
leftElementStyle,
|
|
81
|
-
rightElementStyle,
|
|
82
|
-
} = useMemo(() => {
|
|
83
|
-
const { innerContainer, content, leftElement, rightElement } = listItemStyles;
|
|
84
|
-
return {
|
|
85
|
-
containerStyles: [listItemStyles.root, styleProp],
|
|
86
|
-
innerContainerStyle: innerContainer,
|
|
87
|
-
contentStyle: content,
|
|
88
|
-
leftElementStyle: leftElement,
|
|
89
|
-
rightElementStyle: rightElement,
|
|
90
|
-
};
|
|
91
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
92
|
-
}, [styleProp, state, variant]);
|
|
93
|
-
|
|
94
|
-
const contextValue = useMemo(
|
|
95
|
-
() => ({ disabled, hovered: hoverable && hovered, selected, variant }),
|
|
96
|
-
[disabled, hoverable, hovered, selected, variant],
|
|
97
|
-
);
|
|
98
|
-
|
|
99
|
-
return (
|
|
100
|
-
<TouchableRipple
|
|
101
|
-
{...props}
|
|
102
|
-
style={containerStyles}
|
|
103
|
-
disabled={disabled}
|
|
104
|
-
onPress={onPress}
|
|
105
|
-
ref={actionsRef}>
|
|
106
|
-
<>
|
|
107
|
-
<View style={innerContainerStyle}>
|
|
108
|
-
{left ? (
|
|
109
|
-
<View style={leftElementStyle}>
|
|
110
|
-
{typeof left === 'function' ? left({ hovered }) : left}
|
|
111
|
-
</View>
|
|
112
|
-
) : null}
|
|
113
|
-
<View style={[contentStyle, contentStyleProp]}>
|
|
114
|
-
<ListItemContext.Provider value={contextValue}>
|
|
115
|
-
<>{children}</>
|
|
116
|
-
</ListItemContext.Provider>
|
|
117
|
-
</View>
|
|
118
|
-
{right ? (
|
|
119
|
-
<View style={rightElementStyle}>
|
|
120
|
-
{typeof right === 'function' ? right({ hovered }) : right}
|
|
121
|
-
</View>
|
|
122
|
-
) : null}
|
|
123
|
-
</View>
|
|
124
|
-
{divider && <HorizontalDivider />}
|
|
125
|
-
<StateLayer style={listItemStyles.stateLayer} />
|
|
126
|
-
</>
|
|
127
|
-
</TouchableRipple>
|
|
128
|
-
);
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
export const ListItemContext = createContext({
|
|
132
|
-
disabled: false,
|
|
133
|
-
hovered: false,
|
|
134
|
-
selected: false,
|
|
135
|
-
variant: 'default',
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
export default memo(forwardRef(ListItem));
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { memo, useContext } from 'react';
|
|
2
|
-
import { type TextProps } from 'react-native';
|
|
3
|
-
|
|
4
|
-
import { resolveStateVariant } from '../../utils';
|
|
5
|
-
import { Text } from '../Text';
|
|
6
|
-
import { ListItemContext } from './ListItem';
|
|
7
|
-
import { listItemDescriptionStyles } from './utils';
|
|
8
|
-
|
|
9
|
-
type Props = TextProps & {};
|
|
10
|
-
|
|
11
|
-
const ListItemDescription = ({ style, ...rest }: Props) => {
|
|
12
|
-
const { disabled, hovered, variant } = useContext(ListItemContext);
|
|
13
|
-
|
|
14
|
-
listItemDescriptionStyles.useVariants({
|
|
15
|
-
state: resolveStateVariant({
|
|
16
|
-
disabled,
|
|
17
|
-
hovered,
|
|
18
|
-
}) as any,
|
|
19
|
-
variant: variant as any,
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
return <Text selectable={false} {...rest} style={[listItemDescriptionStyles.root, style]} />;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
export default memo(ListItemDescription);
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { memo, useContext } from 'react';
|
|
2
|
-
import { type TextProps } from 'react-native';
|
|
3
|
-
|
|
4
|
-
import { resolveStateVariant } from '../../utils';
|
|
5
|
-
import { Text } from '../Text';
|
|
6
|
-
import { ListItemContext } from './ListItem';
|
|
7
|
-
import { listItemTitleStyles } from './utils';
|
|
8
|
-
|
|
9
|
-
type Props = TextProps & {};
|
|
10
|
-
|
|
11
|
-
const ListItemTitle = ({ style, ...rest }: Props) => {
|
|
12
|
-
const { disabled, hovered, variant } = useContext(ListItemContext);
|
|
13
|
-
|
|
14
|
-
listItemTitleStyles.useVariants({
|
|
15
|
-
state: resolveStateVariant({
|
|
16
|
-
disabled,
|
|
17
|
-
hovered,
|
|
18
|
-
}) as any,
|
|
19
|
-
variant: variant as any,
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
return <Text selectable={false} {...rest} style={[listItemTitleStyles.root, style]} />;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
export default memo(ListItemTitle);
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { getRegisteredComponentWithFallback } from '../../core';
|
|
2
|
-
import ListItemComponent from './ListItem';
|
|
3
|
-
import ListItemDescription from './ListItemDescription';
|
|
4
|
-
import ListItemTitle from './ListItemTitle';
|
|
5
|
-
|
|
6
|
-
const ListItemDefault = Object.assign(ListItemComponent, {
|
|
7
|
-
Title: ListItemTitle,
|
|
8
|
-
Description: ListItemDescription,
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
export const ListItem = getRegisteredComponentWithFallback('ListItem', ListItemDefault);
|
|
12
|
-
|
|
13
|
-
export type { Props as ListItemProps } from './ListItem';
|
|
14
|
-
export { listItemDescriptionStyles, listItemStyles, listItemTitleStyles } from './utils';
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { memo } from 'react';
|
|
2
|
-
|
|
3
|
-
import { HorizontalDivider, type HorizontalDividerProps } from '../HorizontalDivider';
|
|
4
|
-
|
|
5
|
-
export type Props = HorizontalDividerProps & {};
|
|
6
|
-
|
|
7
|
-
const MenuDivider = memo(({ spacing = 8, ...rest }: Props) => {
|
|
8
|
-
return <HorizontalDivider spacing={spacing} {...rest} />;
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
MenuDivider.displayName = 'Menu_Divider';
|
|
12
|
-
|
|
13
|
-
export default MenuDivider;
|
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
import { forwardRef, memo, type ReactNode, useCallback, useContext, useMemo } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
type GestureResponderEvent,
|
|
4
|
-
type StyleProp,
|
|
5
|
-
Text,
|
|
6
|
-
type TextProps,
|
|
7
|
-
View,
|
|
8
|
-
type ViewStyle,
|
|
9
|
-
} from 'react-native';
|
|
10
|
-
|
|
11
|
-
import { useActionState } from '../../hooks';
|
|
12
|
-
import type { WithElements } from '../../types';
|
|
13
|
-
import { resolveStateVariant } from '../../utils';
|
|
14
|
-
import { StateLayer, type StateLayerProps } from '../StateLayer';
|
|
15
|
-
import { TouchableRipple, type TouchableRippleProps } from '../TouchableRipple';
|
|
16
|
-
import { MenuContext } from './Menu';
|
|
17
|
-
import { menuItemStyles } from './utils';
|
|
18
|
-
|
|
19
|
-
export type Props = TouchableRippleProps &
|
|
20
|
-
WithElements<ReactNode> & {
|
|
21
|
-
size?: 'default' | 'dense';
|
|
22
|
-
stateLayerProps?: StateLayerProps;
|
|
23
|
-
textProps?: Omit<TextProps, 'children'>;
|
|
24
|
-
leftElementStyle?: StyleProp<ViewStyle>;
|
|
25
|
-
rightElementStyle?: StyleProp<ViewStyle>;
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
const emptyObj = {};
|
|
29
|
-
|
|
30
|
-
const _MenuItem = (
|
|
31
|
-
{
|
|
32
|
-
onPress,
|
|
33
|
-
left,
|
|
34
|
-
right,
|
|
35
|
-
children,
|
|
36
|
-
disabled = false,
|
|
37
|
-
size = 'default',
|
|
38
|
-
style,
|
|
39
|
-
testID,
|
|
40
|
-
stateLayerProps,
|
|
41
|
-
textProps = emptyObj,
|
|
42
|
-
leftElementStyle: _leftElementStyle,
|
|
43
|
-
rightElementStyle: _rightElementStyle,
|
|
44
|
-
...rest
|
|
45
|
-
}: Props,
|
|
46
|
-
ref: any,
|
|
47
|
-
) => {
|
|
48
|
-
const { hovered, actionsRef } = useActionState({ ref, actionsToListen: ['hover'] });
|
|
49
|
-
|
|
50
|
-
const { closeOnSelect, onClose } = useContext(MenuContext);
|
|
51
|
-
|
|
52
|
-
const state = resolveStateVariant({
|
|
53
|
-
disabled,
|
|
54
|
-
hovered,
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
menuItemStyles.useVariants({
|
|
58
|
-
size: size as any,
|
|
59
|
-
state: state as any,
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
const onPressItem = useCallback(
|
|
63
|
-
(e: GestureResponderEvent) => {
|
|
64
|
-
if (closeOnSelect) onClose();
|
|
65
|
-
|
|
66
|
-
onPress?.(e);
|
|
67
|
-
},
|
|
68
|
-
[closeOnSelect, onClose, onPress],
|
|
69
|
-
);
|
|
70
|
-
|
|
71
|
-
const { containerStyle, leftElementStyle, rightElementStyle, textStyle, stateLayerStyle } =
|
|
72
|
-
useMemo(() => {
|
|
73
|
-
const { text, leftElement, rightElement, stateLayer } = menuItemStyles;
|
|
74
|
-
|
|
75
|
-
return {
|
|
76
|
-
containerStyle: [menuItemStyles.root, style],
|
|
77
|
-
textStyle: [text, textProps?.style],
|
|
78
|
-
leftElementStyle: [leftElement, _leftElementStyle],
|
|
79
|
-
rightElementStyle: [rightElement, _rightElementStyle],
|
|
80
|
-
stateLayerStyle: stateLayer,
|
|
81
|
-
};
|
|
82
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
83
|
-
}, [_leftElementStyle, _rightElementStyle, style, textProps?.style, state, size]);
|
|
84
|
-
|
|
85
|
-
return (
|
|
86
|
-
<TouchableRipple
|
|
87
|
-
{...rest}
|
|
88
|
-
testID={testID}
|
|
89
|
-
style={containerStyle}
|
|
90
|
-
disabled={disabled}
|
|
91
|
-
onPress={onPressItem}
|
|
92
|
-
ref={actionsRef}>
|
|
93
|
-
<>
|
|
94
|
-
{left ? (
|
|
95
|
-
<View style={leftElementStyle} testID={testID ? `${testID}-left` : ''}>
|
|
96
|
-
{left}
|
|
97
|
-
</View>
|
|
98
|
-
) : null}
|
|
99
|
-
|
|
100
|
-
<Text
|
|
101
|
-
style={textStyle}
|
|
102
|
-
numberOfLines={1}
|
|
103
|
-
{...textProps}
|
|
104
|
-
testID={testID ? `${testID}-text` : ''}>
|
|
105
|
-
{children}
|
|
106
|
-
</Text>
|
|
107
|
-
|
|
108
|
-
{right ? (
|
|
109
|
-
<View style={rightElementStyle} testID={testID ? `${testID}-right` : ''}>
|
|
110
|
-
{right}
|
|
111
|
-
</View>
|
|
112
|
-
) : null}
|
|
113
|
-
|
|
114
|
-
<StateLayer
|
|
115
|
-
testID={testID ? `${testID}-stateLayer` : ''}
|
|
116
|
-
{...stateLayerProps}
|
|
117
|
-
style={stateLayerStyle}
|
|
118
|
-
/>
|
|
119
|
-
</>
|
|
120
|
-
</TouchableRipple>
|
|
121
|
-
);
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
const MenuItem = memo(forwardRef(_MenuItem));
|
|
125
|
-
|
|
126
|
-
MenuItem.displayName = 'Menu_Item';
|
|
127
|
-
|
|
128
|
-
export default MenuItem;
|