@ledgerhq/lumen-ui-rnative 0.0.46 → 0.0.47
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/dist/package.json +5 -1
- package/dist/src/lib/Components/Icon/Icon.d.ts.map +1 -1
- package/dist/src/lib/Components/Icon/Icon.js +3 -4
- package/dist/src/lib/Components/Icon/createIcon.d.ts.map +1 -1
- package/dist/src/lib/Components/Icon/createIcon.js +1 -1
- package/dist/src/lib/Components/ListItem/ListItem.d.ts +88 -34
- package/dist/src/lib/Components/ListItem/ListItem.d.ts.map +1 -1
- package/dist/src/lib/Components/ListItem/ListItem.js +242 -97
- package/dist/src/lib/Components/ListItem/ListItem.stories.d.ts +2 -3
- package/dist/src/lib/Components/ListItem/ListItem.stories.d.ts.map +1 -1
- package/dist/src/lib/Components/ListItem/ListItem.stories.js +63 -73
- package/dist/src/lib/Components/ListItem/index.d.ts +1 -1
- package/dist/src/lib/Components/ListItem/index.d.ts.map +1 -1
- package/dist/src/lib/Components/ListItem/index.js +1 -1
- package/dist/src/lib/Components/ListItem/types.d.ts +106 -0
- package/dist/src/lib/Components/ListItem/types.d.ts.map +1 -0
- package/dist/src/lib/Components/Spot/types.d.ts +1 -1
- package/dist/src/lib/Components/Spot/types.d.ts.map +1 -1
- package/dist/src/lib/utils/index.d.ts +3 -4
- package/dist/src/lib/utils/index.d.ts.map +1 -1
- package/dist/src/lib/utils/index.js +3 -4
- package/dist/src/lib/utils/react/{extract-text-from-children.d.ts → extractTextFromChildren.d.ts} +1 -1
- package/dist/src/lib/utils/react/extractTextFromChildren.d.ts.map +1 -0
- package/dist/src/lib/utils/react/index.d.ts +1 -1
- package/dist/src/lib/utils/react/index.d.ts.map +1 -1
- package/dist/src/lib/utils/react/index.js +1 -1
- package/dist/src/lib/utils/startTransition/index.d.ts +2 -0
- package/dist/src/lib/utils/startTransition/index.d.ts.map +1 -0
- package/dist/src/lib/utils/startTransition/index.js +1 -0
- package/dist/src/lib/utils/{start-transition/start-transition.d.ts → startTransition/startTransition.d.ts} +1 -1
- package/dist/src/lib/utils/startTransition/startTransition.d.ts.map +1 -0
- package/dist/src/lib/utils/useControllableState/index.d.ts +2 -0
- package/dist/src/lib/utils/useControllableState/index.d.ts.map +1 -0
- package/dist/src/lib/utils/useControllableState/index.js +1 -0
- package/dist/src/lib/utils/{use-controllable-state/use-controllable-state.d.ts → useControllableState/useControllableState.d.ts} +1 -1
- package/dist/src/lib/utils/useControllableState/useControllableState.d.ts.map +1 -0
- package/dist/src/lib/utils/{use-controllable-state/use-controllable-state.js → useControllableState/useControllableState.js} +2 -2
- package/dist/src/lib/utils/useEvent/index.d.ts +3 -0
- package/dist/src/lib/utils/useEvent/index.d.ts.map +1 -0
- package/dist/src/lib/utils/useEvent/index.js +2 -0
- package/dist/src/lib/utils/{use-event/use-event.d.ts → useEvent/useEvent.d.ts} +1 -1
- package/dist/src/lib/utils/useEvent/useEvent.d.ts.map +1 -0
- package/dist/src/lib/utils/{use-event/use-event.js → useEvent/useEvent.js} +1 -1
- package/dist/src/lib/utils/{use-event/use-get.d.ts → useEvent/useGet.d.ts} +1 -1
- package/dist/src/lib/utils/useEvent/useGet.d.ts.map +1 -0
- package/dist/src/styles/provider/LumenStyleSheetProvider.d.ts +1 -1
- package/dist/src/styles/provider/LumenStyleSheetProvider.d.ts.map +1 -1
- package/dist/src/styles/provider/LumenStyleSheetProvider.js +1 -2
- package/package.json +6 -2
- package/src/lib/Components/Checkbox/Checkbox.mdx +1 -0
- package/src/lib/Components/Icon/Icon.tsx +3 -5
- package/src/lib/Components/Icon/createIcon.ts +1 -1
- package/src/lib/Components/ListItem/ListItem.mdx +402 -124
- package/src/lib/Components/ListItem/ListItem.stories.tsx +357 -228
- package/src/lib/Components/ListItem/ListItem.tsx +437 -181
- package/src/lib/Components/ListItem/index.ts +1 -1
- package/src/lib/Components/ListItem/types.ts +121 -0
- package/src/lib/Components/Spot/types.ts +5 -1
- package/src/lib/Components/Switch/Switch.mdx +1 -0
- package/src/lib/utils/index.ts +3 -4
- package/src/lib/utils/react/index.ts +1 -1
- package/src/lib/utils/startTransition/index.ts +1 -0
- package/src/lib/utils/useControllableState/index.ts +1 -0
- package/src/lib/utils/{use-controllable-state/use-controllable-state.ts → useControllableState/useControllableState.ts} +2 -2
- package/src/lib/utils/useEvent/index.ts +2 -0
- package/src/lib/utils/{use-event/use-event.ts → useEvent/useEvent.ts} +1 -1
- package/src/styles/provider/LumenStyleSheetProvider.tsx +2 -3
- package/dist/src/lib/Components/ListItem/ListItem.types.d.ts +0 -31
- package/dist/src/lib/Components/ListItem/ListItem.types.d.ts.map +0 -1
- package/dist/src/lib/utils/react/extract-text-from-children.d.ts.map +0 -1
- package/dist/src/lib/utils/start-transition/index.d.ts +0 -2
- package/dist/src/lib/utils/start-transition/index.d.ts.map +0 -1
- package/dist/src/lib/utils/start-transition/index.js +0 -1
- package/dist/src/lib/utils/start-transition/start-transition.d.ts.map +0 -1
- package/dist/src/lib/utils/string-utils.d.ts +0 -6
- package/dist/src/lib/utils/string-utils.d.ts.map +0 -1
- package/dist/src/lib/utils/string-utils.js +0 -12
- package/dist/src/lib/utils/use-controllable-state/index.d.ts +0 -2
- package/dist/src/lib/utils/use-controllable-state/index.d.ts.map +0 -1
- package/dist/src/lib/utils/use-controllable-state/index.js +0 -1
- package/dist/src/lib/utils/use-controllable-state/use-controllable-state.d.ts.map +0 -1
- package/dist/src/lib/utils/use-event/index.d.ts +0 -3
- package/dist/src/lib/utils/use-event/index.d.ts.map +0 -1
- package/dist/src/lib/utils/use-event/index.js +0 -2
- package/dist/src/lib/utils/use-event/use-event.d.ts.map +0 -1
- package/dist/src/lib/utils/use-event/use-get.d.ts.map +0 -1
- package/src/lib/Components/ListItem/ListItem.types.ts +0 -31
- package/src/lib/utils/start-transition/index.ts +0 -1
- package/src/lib/utils/string-utils.test.ts +0 -73
- package/src/lib/utils/string-utils.ts +0 -11
- package/src/lib/utils/use-controllable-state/index.ts +0 -1
- package/src/lib/utils/use-event/index.ts +0 -2
- /package/dist/src/lib/Components/ListItem/{ListItem.types.js → types.js} +0 -0
- /package/dist/src/lib/utils/react/{extract-text-from-children.js → extractTextFromChildren.js} +0 -0
- /package/dist/src/lib/utils/{start-transition/start-transition.js → startTransition/startTransition.js} +0 -0
- /package/dist/src/lib/utils/{use-event/use-get.js → useEvent/useGet.js} +0 -0
- /package/src/lib/utils/react/{extract-text-from-children.ts → extractTextFromChildren.ts} +0 -0
- /package/src/lib/utils/{start-transition/start-transition.ts → startTransition/startTransition.ts} +0 -0
- /package/src/lib/utils/{use-event/use-get.ts → useEvent/useGet.ts} +0 -0
|
@@ -1,93 +1,60 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createSafeContext,
|
|
3
|
+
isTextChildren,
|
|
4
|
+
} from '@ledgerhq/lumen-utils-shared';
|
|
1
5
|
import React from 'react';
|
|
2
|
-
import { StyleSheet,
|
|
3
|
-
import { useStyleSheet } from '../../../styles';
|
|
4
|
-
import {
|
|
6
|
+
import { StyleSheet, View } from 'react-native';
|
|
7
|
+
import { useStyleSheet, useTheme } from '../../../styles';
|
|
8
|
+
import { Spot } from '../Spot';
|
|
9
|
+
import { Box, Pressable, Text } from '../Utility';
|
|
10
|
+
import {
|
|
11
|
+
ListItemContentProps,
|
|
12
|
+
ListItemContextValue,
|
|
13
|
+
ListItemDescriptionProps,
|
|
14
|
+
ListItemIconProps,
|
|
15
|
+
ListItemLeadingProps,
|
|
16
|
+
ListItemProps,
|
|
17
|
+
ListItemSpotProps,
|
|
18
|
+
ListItemTitleProps,
|
|
19
|
+
ListItemTrailingProps,
|
|
20
|
+
ListItemTruncateProps,
|
|
21
|
+
} from './types';
|
|
5
22
|
|
|
6
|
-
|
|
23
|
+
const [ListItemProvider, useListItemContext] =
|
|
24
|
+
createSafeContext<ListItemContextValue>('ListItem', {});
|
|
7
25
|
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}) => {
|
|
26
|
+
const [ListItemTrailingProvider, useListItemTrailingContext] =
|
|
27
|
+
createSafeContext<{ isInTrailing: boolean }>('ListItemTrailing', {
|
|
28
|
+
isInTrailing: false,
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const useRootStyles = ({ pressed }: { pressed: boolean }) => {
|
|
15
32
|
return useStyleSheet(
|
|
16
|
-
(t) => {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
{
|
|
20
|
-
flexDirection: 'row',
|
|
21
|
-
alignItems: 'center',
|
|
22
|
-
height: t.sizes.s64,
|
|
23
|
-
width: t.sizes.full,
|
|
24
|
-
gap: t.spacings.s16,
|
|
25
|
-
borderRadius: t.borderRadius.md,
|
|
26
|
-
backgroundColor: 'transparent',
|
|
27
|
-
paddingHorizontal: t.spacings.s8,
|
|
28
|
-
paddingVertical: t.spacings.s12,
|
|
29
|
-
},
|
|
30
|
-
pressed && {
|
|
31
|
-
backgroundColor: t.colors.bg.baseTransparentPressed,
|
|
32
|
-
},
|
|
33
|
-
disabled && {
|
|
34
|
-
backgroundColor: 'transparent',
|
|
35
|
-
},
|
|
36
|
-
]),
|
|
37
|
-
contentWrapper: {
|
|
38
|
-
flex: 1,
|
|
39
|
-
minWidth: 0,
|
|
40
|
-
flexDirection: 'row',
|
|
41
|
-
alignItems: 'center',
|
|
42
|
-
gap: t.spacings.s12,
|
|
43
|
-
},
|
|
44
|
-
textWrapper: {
|
|
45
|
-
flex: 1,
|
|
46
|
-
minWidth: 0,
|
|
47
|
-
flexDirection: 'column',
|
|
48
|
-
gap: t.spacings.s4,
|
|
49
|
-
},
|
|
50
|
-
title: StyleSheet.flatten([
|
|
51
|
-
t.typographies.body2SemiBold,
|
|
52
|
-
{
|
|
53
|
-
color: disabled ? t.colors.text.disabled : t.colors.text.base,
|
|
54
|
-
},
|
|
55
|
-
]),
|
|
56
|
-
descriptionRow: {
|
|
33
|
+
(t) => ({
|
|
34
|
+
container: StyleSheet.flatten([
|
|
35
|
+
{
|
|
57
36
|
flexDirection: 'row',
|
|
58
37
|
alignItems: 'center',
|
|
59
|
-
|
|
38
|
+
height: t.sizes.s64,
|
|
39
|
+
width: t.sizes.full,
|
|
40
|
+
gap: t.spacings.s16,
|
|
41
|
+
borderRadius: t.borderRadius.md,
|
|
42
|
+
backgroundColor: 'transparent',
|
|
43
|
+
paddingHorizontal: t.spacings.s8,
|
|
44
|
+
paddingVertical: t.spacings.s12,
|
|
60
45
|
},
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
flexShrink: 1,
|
|
46
|
+
pressed && {
|
|
47
|
+
backgroundColor: t.colors.bg.baseTransparentPressed,
|
|
64
48
|
},
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
color: disabled ? t.colors.text.disabled : t.colors.text.muted,
|
|
69
|
-
minWidth: 0,
|
|
70
|
-
flexShrink: 1,
|
|
71
|
-
},
|
|
72
|
-
]),
|
|
73
|
-
descriptionTagWrapper: {
|
|
74
|
-
height: t.sizes.s16,
|
|
75
|
-
flexShrink: 0,
|
|
76
|
-
flexDirection: 'row',
|
|
77
|
-
alignItems: 'center',
|
|
78
|
-
},
|
|
79
|
-
trailingWrapper: {
|
|
80
|
-
flexShrink: 0,
|
|
81
|
-
},
|
|
82
|
-
};
|
|
83
|
-
},
|
|
84
|
-
[disabled, pressed],
|
|
49
|
+
]),
|
|
50
|
+
}),
|
|
51
|
+
[pressed],
|
|
85
52
|
);
|
|
86
53
|
};
|
|
87
54
|
|
|
88
55
|
/**
|
|
89
|
-
* A flexible list item component that
|
|
90
|
-
*
|
|
56
|
+
* A flexible list item component that provides a composable structure for displaying
|
|
57
|
+
* interactive list items with leading content, title, description, and trailing content.
|
|
91
58
|
*
|
|
92
59
|
* @see {@link https://ldls.vercel.app/?path=/docs/react-native_containment-listitem--docs Storybook}
|
|
93
60
|
* @see {@link https://ldls.vercel.app/?path=/docs/react-native_containment-listitem--docs#dos-and-donts Guidelines}
|
|
@@ -96,53 +63,36 @@ const useStyles = ({
|
|
|
96
63
|
* Do not use it to modify the list item's core appearance (colors, padding, etc).
|
|
97
64
|
*
|
|
98
65
|
* @example
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
* import { ListItem, Spot } from '@ledgerhq/lumen-ui-rnative';
|
|
110
|
-
* import { Wallet, Settings } from '@ledgerhq/lumen-ui-rnative/symbols';
|
|
66
|
+
* import {
|
|
67
|
+
* ListItem,
|
|
68
|
+
* ListItemLeading,
|
|
69
|
+
* ListItemSpot,
|
|
70
|
+
* ListItemContent,
|
|
71
|
+
* ListItemTitle,
|
|
72
|
+
* ListItemDescription,
|
|
73
|
+
* ListItemTrailing,
|
|
74
|
+
* } from '@ledgerhq/lumen-ui-rnative';
|
|
75
|
+
* import { Wallet, ChevronRight } from '@ledgerhq/lumen-ui-rnative/symbols';
|
|
111
76
|
*
|
|
112
|
-
* <ListItem
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
*
|
|
124
|
-
* trailingContent={<ChevronRight size={24} />}
|
|
125
|
-
* />
|
|
77
|
+
* <ListItem onPress={() => console.log('Clicked!')}>
|
|
78
|
+
* <ListItemLeading>
|
|
79
|
+
* <ListItemSpot appearance="icon" icon={Wallet} />
|
|
80
|
+
* <ListItemContent>
|
|
81
|
+
* <ListItemTitle>Balance</ListItemTitle>
|
|
82
|
+
* <ListItemDescription>Optional description</ListItemDescription>
|
|
83
|
+
* </ListItemContent>
|
|
84
|
+
* </ListItemLeading>
|
|
85
|
+
* <ListItemTrailing>
|
|
86
|
+
* <ChevronRight size={24} />
|
|
87
|
+
* </ListItemTrailing>
|
|
88
|
+
* </ListItem>
|
|
126
89
|
*/
|
|
127
90
|
export const ListItem = React.forwardRef<
|
|
128
91
|
React.ElementRef<typeof Pressable>,
|
|
129
92
|
ListItemProps
|
|
130
|
-
>(
|
|
131
|
-
(
|
|
132
|
-
{
|
|
133
|
-
title,
|
|
134
|
-
description,
|
|
135
|
-
leadingContent,
|
|
136
|
-
descriptionTag,
|
|
137
|
-
trailingContent,
|
|
138
|
-
lx = {},
|
|
139
|
-
style,
|
|
140
|
-
disabled = false,
|
|
141
|
-
...touchableProps
|
|
142
|
-
},
|
|
143
|
-
ref,
|
|
144
|
-
) => {
|
|
145
|
-
return (
|
|
93
|
+
>(({ children, lx = {}, style, disabled = false, ...pressableProps }, ref) => {
|
|
94
|
+
return (
|
|
95
|
+
<ListItemProvider value={{ disabled }}>
|
|
146
96
|
<Pressable
|
|
147
97
|
ref={ref}
|
|
148
98
|
lx={lx}
|
|
@@ -150,79 +100,385 @@ export const ListItem = React.forwardRef<
|
|
|
150
100
|
disabled={disabled}
|
|
151
101
|
accessibilityRole='button'
|
|
152
102
|
accessibilityState={{ disabled }}
|
|
153
|
-
{...
|
|
103
|
+
{...pressableProps}
|
|
154
104
|
>
|
|
155
105
|
{({ pressed }) => (
|
|
156
|
-
<
|
|
157
|
-
disabled={disabled}
|
|
158
|
-
pressed={pressed}
|
|
159
|
-
title={title}
|
|
160
|
-
description={description}
|
|
161
|
-
leadingContent={leadingContent}
|
|
162
|
-
descriptionTag={descriptionTag}
|
|
163
|
-
trailingContent={trailingContent}
|
|
164
|
-
/>
|
|
106
|
+
<ListItemInner pressed={pressed}>{children}</ListItemInner>
|
|
165
107
|
)}
|
|
166
108
|
</Pressable>
|
|
109
|
+
</ListItemProvider>
|
|
110
|
+
);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
ListItem.displayName = 'ListItem';
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Internal component to handle pressed state styling
|
|
117
|
+
*/
|
|
118
|
+
const ListItemInner = ({
|
|
119
|
+
pressed,
|
|
120
|
+
children,
|
|
121
|
+
}: {
|
|
122
|
+
pressed: boolean;
|
|
123
|
+
children: React.ReactNode;
|
|
124
|
+
}) => {
|
|
125
|
+
const styles = useRootStyles({ pressed });
|
|
126
|
+
return (
|
|
127
|
+
<View style={styles.container} testID='list-item-content'>
|
|
128
|
+
{children}
|
|
129
|
+
</View>
|
|
130
|
+
);
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Container for the leading (left) part of the list item.
|
|
135
|
+
* Contains the visual element (ListItemSpot, Avatar, Icon) and the content (title + description).
|
|
136
|
+
*/
|
|
137
|
+
export const ListItemLeading = React.forwardRef<View, ListItemLeadingProps>(
|
|
138
|
+
({ children, lx = {}, style, ...viewProps }, ref) => {
|
|
139
|
+
const styles = useStyleSheet(
|
|
140
|
+
(t) => ({
|
|
141
|
+
leading: {
|
|
142
|
+
flex: 1,
|
|
143
|
+
minWidth: 0,
|
|
144
|
+
flexDirection: 'row',
|
|
145
|
+
alignItems: 'center',
|
|
146
|
+
gap: t.spacings.s12,
|
|
147
|
+
},
|
|
148
|
+
}),
|
|
149
|
+
[],
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
return (
|
|
153
|
+
<Box
|
|
154
|
+
ref={ref}
|
|
155
|
+
lx={lx}
|
|
156
|
+
style={StyleSheet.flatten([styles.leading, style])}
|
|
157
|
+
{...viewProps}
|
|
158
|
+
>
|
|
159
|
+
{children}
|
|
160
|
+
</Box>
|
|
167
161
|
);
|
|
168
162
|
},
|
|
169
163
|
);
|
|
170
164
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
165
|
+
ListItemLeading.displayName = 'ListItemLeading';
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Container for the text content (title and description) within the leading area.
|
|
169
|
+
*/
|
|
170
|
+
export const ListItemContent = React.forwardRef<View, ListItemContentProps>(
|
|
171
|
+
({ children, lx = {}, style, ...viewProps }, ref) => {
|
|
172
|
+
const styles = useStyleSheet(
|
|
173
|
+
(t) => ({
|
|
174
|
+
content: {
|
|
175
|
+
flex: 1,
|
|
176
|
+
minWidth: 0,
|
|
177
|
+
flexDirection: 'column',
|
|
178
|
+
gap: t.spacings.s4,
|
|
179
|
+
},
|
|
180
|
+
}),
|
|
181
|
+
[],
|
|
182
|
+
);
|
|
183
|
+
|
|
184
|
+
return (
|
|
185
|
+
<Box
|
|
186
|
+
ref={ref}
|
|
187
|
+
lx={lx}
|
|
188
|
+
style={StyleSheet.flatten([styles.content, style])}
|
|
189
|
+
{...viewProps}
|
|
190
|
+
>
|
|
191
|
+
{children}
|
|
192
|
+
</Box>
|
|
193
|
+
);
|
|
194
|
+
},
|
|
195
|
+
);
|
|
196
|
+
|
|
197
|
+
ListItemContent.displayName = 'ListItemContent';
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* The main title of the list item. Can contain text directly or
|
|
201
|
+
* ListItemTruncate + Tag for more complex layouts.
|
|
202
|
+
*/
|
|
203
|
+
export const ListItemTitle = React.forwardRef<View, ListItemTitleProps>(
|
|
204
|
+
({ children, lx = {}, style, ...viewProps }, ref) => {
|
|
205
|
+
const { disabled } = useListItemContext({
|
|
206
|
+
consumerName: 'ListItemTitle',
|
|
207
|
+
contextRequired: true,
|
|
208
|
+
});
|
|
209
|
+
const { isInTrailing } = useListItemTrailingContext({
|
|
210
|
+
consumerName: 'ListItemTitle',
|
|
211
|
+
contextRequired: false,
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
const styles = useStyleSheet(
|
|
215
|
+
(t) => {
|
|
216
|
+
const { boxStyle } = StyleSheet.create({
|
|
217
|
+
boxStyle: {
|
|
218
|
+
flexDirection: 'row',
|
|
219
|
+
alignItems: 'center',
|
|
220
|
+
gap: t.spacings.s4,
|
|
221
|
+
width: '100%',
|
|
222
|
+
textAlign: isInTrailing ? 'right' : 'left',
|
|
223
|
+
justifyContent: isInTrailing ? 'flex-end' : 'flex-start',
|
|
224
|
+
} as const,
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
return {
|
|
228
|
+
asBox: boxStyle,
|
|
229
|
+
asText: StyleSheet.flatten([
|
|
230
|
+
t.typographies.body2SemiBold,
|
|
231
|
+
{
|
|
232
|
+
...boxStyle,
|
|
233
|
+
color: disabled ? t.colors.text.disabled : t.colors.text.base,
|
|
234
|
+
},
|
|
235
|
+
]),
|
|
236
|
+
};
|
|
237
|
+
},
|
|
238
|
+
[disabled],
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
// If children is a string, render it directly as Text with truncation
|
|
242
|
+
if (isTextChildren(children)) {
|
|
243
|
+
return (
|
|
244
|
+
<Text
|
|
245
|
+
ref={ref as React.Ref<React.ElementRef<typeof Text>>}
|
|
246
|
+
lx={lx}
|
|
247
|
+
style={StyleSheet.flatten([styles.asText, style])}
|
|
248
|
+
numberOfLines={1}
|
|
249
|
+
ellipsizeMode='tail'
|
|
250
|
+
>
|
|
251
|
+
{children}
|
|
252
|
+
</Text>
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Otherwise, render as a row container for ListItemTruncate + Tag
|
|
257
|
+
return (
|
|
258
|
+
<Box
|
|
259
|
+
ref={ref}
|
|
260
|
+
lx={lx}
|
|
261
|
+
style={StyleSheet.flatten([styles.asBox, style])}
|
|
262
|
+
{...viewProps}
|
|
263
|
+
>
|
|
264
|
+
{children}
|
|
265
|
+
</Box>
|
|
266
|
+
);
|
|
267
|
+
},
|
|
268
|
+
);
|
|
269
|
+
|
|
270
|
+
ListItemTitle.displayName = 'ListItemTitle';
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Optional description below the title. Can contain text directly or
|
|
274
|
+
* ListItemTruncate + Tag for more complex layouts.
|
|
275
|
+
* Automatically applies disabled styling when the parent ListItem is disabled.
|
|
276
|
+
*/
|
|
277
|
+
export const ListItemDescription = React.forwardRef<
|
|
278
|
+
View,
|
|
279
|
+
ListItemDescriptionProps
|
|
280
|
+
>(({ children, lx = {}, style, ...viewProps }, ref) => {
|
|
281
|
+
const { disabled } = useListItemContext({
|
|
282
|
+
consumerName: 'ListItemDescription',
|
|
283
|
+
contextRequired: true,
|
|
284
|
+
});
|
|
285
|
+
const { isInTrailing } = useListItemTrailingContext({
|
|
286
|
+
consumerName: 'ListItemDescription',
|
|
287
|
+
contextRequired: false,
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
const styles = useStyleSheet(
|
|
291
|
+
(t) => {
|
|
292
|
+
const { boxStyle } = StyleSheet.create({
|
|
293
|
+
boxStyle: {
|
|
294
|
+
flexDirection: 'row',
|
|
295
|
+
alignItems: 'center',
|
|
296
|
+
gap: t.spacings.s4,
|
|
297
|
+
width: '100%',
|
|
298
|
+
textAlign: isInTrailing ? 'right' : 'left',
|
|
299
|
+
justifyContent: isInTrailing ? 'flex-end' : 'flex-start',
|
|
300
|
+
} as const,
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
return {
|
|
304
|
+
asBox: boxStyle,
|
|
305
|
+
asText: StyleSheet.flatten([
|
|
306
|
+
t.typographies.body3,
|
|
307
|
+
{
|
|
308
|
+
...boxStyle,
|
|
309
|
+
color: disabled ? t.colors.text.disabled : t.colors.text.muted,
|
|
310
|
+
},
|
|
311
|
+
]),
|
|
312
|
+
};
|
|
313
|
+
},
|
|
314
|
+
[disabled, isInTrailing],
|
|
315
|
+
);
|
|
316
|
+
|
|
317
|
+
// If children is a string, render it directly as Text with truncation
|
|
318
|
+
if (isTextChildren(children)) {
|
|
319
|
+
return (
|
|
320
|
+
<Text
|
|
321
|
+
ref={ref as React.Ref<React.ElementRef<typeof Text>>}
|
|
322
|
+
lx={lx}
|
|
323
|
+
style={StyleSheet.flatten([styles.asText, style])}
|
|
324
|
+
numberOfLines={1}
|
|
325
|
+
ellipsizeMode='tail'
|
|
326
|
+
>
|
|
327
|
+
{children}
|
|
328
|
+
</Text>
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// Otherwise, render as a row container for ListItemTruncate + Tag
|
|
333
|
+
return (
|
|
334
|
+
<Box
|
|
335
|
+
ref={ref}
|
|
336
|
+
lx={lx}
|
|
337
|
+
style={StyleSheet.flatten([styles.asBox, style])}
|
|
338
|
+
{...viewProps}
|
|
339
|
+
>
|
|
340
|
+
{children}
|
|
341
|
+
</Box>
|
|
342
|
+
);
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
ListItemDescription.displayName = 'ListItemDescription';
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Container for the trailing (right) content of the list item.
|
|
349
|
+
* Used for icons, switches, values, tags, chevrons, etc.
|
|
350
|
+
*/
|
|
351
|
+
export const ListItemTrailing = React.forwardRef<View, ListItemTrailingProps>(
|
|
352
|
+
({ children, lx = {}, style, ...viewProps }, ref) => {
|
|
353
|
+
const styles = useStyleSheet(
|
|
354
|
+
() => ({
|
|
355
|
+
trailing: {
|
|
356
|
+
flexShrink: 0,
|
|
357
|
+
flexDirection: 'row',
|
|
358
|
+
alignItems: 'center',
|
|
359
|
+
},
|
|
360
|
+
}),
|
|
361
|
+
[],
|
|
362
|
+
);
|
|
363
|
+
|
|
364
|
+
return (
|
|
365
|
+
<ListItemTrailingProvider value={{ isInTrailing: true }}>
|
|
366
|
+
<Box
|
|
367
|
+
ref={ref}
|
|
368
|
+
lx={lx}
|
|
369
|
+
style={StyleSheet.flatten([styles.trailing, style])}
|
|
370
|
+
{...viewProps}
|
|
371
|
+
>
|
|
372
|
+
{children}
|
|
373
|
+
</Box>
|
|
374
|
+
</ListItemTrailingProvider>
|
|
375
|
+
);
|
|
376
|
+
},
|
|
377
|
+
);
|
|
378
|
+
|
|
379
|
+
ListItemTrailing.displayName = 'ListItemTrailing';
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Spot adapter for ListItem. Automatically inherits disabled state from parent ListItem.
|
|
383
|
+
* Fixed at size 48 for consistent list item appearance.
|
|
384
|
+
*/
|
|
385
|
+
export const ListItemSpot = (props: ListItemSpotProps) => {
|
|
386
|
+
const { disabled } = useListItemContext({
|
|
387
|
+
consumerName: 'ListItemSpot',
|
|
388
|
+
contextRequired: true,
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
return <Spot {...props} size={48} disabled={disabled} />;
|
|
179
392
|
};
|
|
180
393
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
394
|
+
ListItemSpot.displayName = 'ListItemSpot';
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* Icon adapter for ListItem. Automatically inherits disabled state from parent ListItem.
|
|
398
|
+
* Fixed at size 24 for consistent list item appearance.
|
|
399
|
+
*/
|
|
400
|
+
export const ListItemIcon = ({
|
|
401
|
+
icon: Icon,
|
|
402
|
+
color,
|
|
403
|
+
lx = {},
|
|
404
|
+
style,
|
|
405
|
+
...viewProps
|
|
406
|
+
}: ListItemIconProps) => {
|
|
407
|
+
const { theme } = useTheme();
|
|
408
|
+
const { disabled } = useListItemContext({
|
|
409
|
+
consumerName: 'ListItemIcon',
|
|
410
|
+
contextRequired: true,
|
|
411
|
+
});
|
|
191
412
|
|
|
192
413
|
return (
|
|
193
|
-
<
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
numberOfLines={1}
|
|
206
|
-
ellipsizeMode='tail'
|
|
207
|
-
style={styles.description}
|
|
208
|
-
>
|
|
209
|
-
{description}
|
|
210
|
-
</Text>
|
|
211
|
-
</View>
|
|
212
|
-
{descriptionTag && (
|
|
213
|
-
<View style={styles.descriptionTagWrapper}>
|
|
214
|
-
{descriptionTag}
|
|
215
|
-
</View>
|
|
216
|
-
)}
|
|
217
|
-
</View>
|
|
218
|
-
)}
|
|
219
|
-
</View>
|
|
220
|
-
</View>
|
|
221
|
-
{trailingContent && (
|
|
222
|
-
<View style={styles.trailingWrapper}>{trailingContent}</View>
|
|
223
|
-
)}
|
|
224
|
-
</View>
|
|
414
|
+
<Box
|
|
415
|
+
lx={lx}
|
|
416
|
+
style={StyleSheet.flatten([{ flexShrink: 0 }, style])}
|
|
417
|
+
{...viewProps}
|
|
418
|
+
>
|
|
419
|
+
<Icon
|
|
420
|
+
size={24}
|
|
421
|
+
style={{
|
|
422
|
+
color: disabled ? theme.colors.text.disabled : (color ?? undefined),
|
|
423
|
+
}}
|
|
424
|
+
/>
|
|
425
|
+
</Box>
|
|
225
426
|
);
|
|
226
427
|
};
|
|
227
428
|
|
|
228
|
-
|
|
429
|
+
ListItemIcon.displayName = 'ListItemIcon';
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* Text wrapper that truncates when space is limited.
|
|
433
|
+
* Use inside ListItemTitle or ListItemDescription when combining text with a Tag.
|
|
434
|
+
* Set variant='title' for title styling or variant='description' (default) for description styling.
|
|
435
|
+
*/
|
|
436
|
+
export const ListItemTruncate = React.forwardRef<
|
|
437
|
+
React.ElementRef<typeof Text>,
|
|
438
|
+
ListItemTruncateProps
|
|
439
|
+
>(
|
|
440
|
+
(
|
|
441
|
+
{ children, variant = 'description', lx = {}, style, ...textProps },
|
|
442
|
+
ref,
|
|
443
|
+
) => {
|
|
444
|
+
const { disabled } = useListItemContext({
|
|
445
|
+
consumerName: 'ListItemTruncate',
|
|
446
|
+
contextRequired: true,
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
const styles = useStyleSheet(
|
|
450
|
+
(t) => ({
|
|
451
|
+
truncate: StyleSheet.flatten([
|
|
452
|
+
variant === 'title'
|
|
453
|
+
? t.typographies.body2SemiBold
|
|
454
|
+
: t.typographies.body3,
|
|
455
|
+
{
|
|
456
|
+
color: disabled
|
|
457
|
+
? t.colors.text.disabled
|
|
458
|
+
: variant === 'title'
|
|
459
|
+
? t.colors.text.base
|
|
460
|
+
: t.colors.text.muted,
|
|
461
|
+
minWidth: 0,
|
|
462
|
+
flexShrink: 1,
|
|
463
|
+
},
|
|
464
|
+
]),
|
|
465
|
+
}),
|
|
466
|
+
[disabled, variant],
|
|
467
|
+
);
|
|
468
|
+
|
|
469
|
+
return (
|
|
470
|
+
<Text
|
|
471
|
+
ref={ref}
|
|
472
|
+
lx={lx}
|
|
473
|
+
style={StyleSheet.flatten([styles.truncate, style])}
|
|
474
|
+
numberOfLines={1}
|
|
475
|
+
ellipsizeMode='tail'
|
|
476
|
+
{...textProps}
|
|
477
|
+
>
|
|
478
|
+
{children}
|
|
479
|
+
</Text>
|
|
480
|
+
);
|
|
481
|
+
},
|
|
482
|
+
);
|
|
483
|
+
|
|
484
|
+
ListItemTruncate.displayName = 'ListItemTruncate';
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export * from './ListItem';
|
|
2
|
-
export * from './
|
|
2
|
+
export * from './types';
|