@tamagui/list-item 2.7.7 → 3.0.0-beta.643.1
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/cjs/ListItem.cjs +151 -222
- package/dist/cjs/ListItem.native.cjs +192 -0
- package/dist/cjs/ListItem.native.js +156 -223
- package/dist/cjs/ListItem.native.js.map +1 -1
- package/dist/cjs/index.cjs +10 -11
- package/dist/cjs/index.native.cjs +21 -0
- package/dist/cjs/index.native.js +10 -10
- package/dist/cjs/index.native.js.map +1 -1
- package/dist/esm/ListItem.mjs +141 -210
- package/dist/esm/ListItem.mjs.map +1 -1
- package/dist/esm/ListItem.native.js +147 -213
- package/dist/esm/ListItem.native.js.map +1 -1
- package/dist/esm/index.js +1 -2
- package/dist/esm/index.mjs +1 -2
- package/dist/esm/index.native.js +1 -2
- package/dist/jsx/ListItem.mjs +141 -210
- package/dist/jsx/ListItem.mjs.map +1 -1
- package/dist/jsx/ListItem.native.cjs +192 -0
- package/dist/jsx/ListItem.native.js +156 -223
- package/dist/jsx/ListItem.native.js.map +1 -1
- package/dist/jsx/index.js +1 -2
- package/dist/jsx/index.mjs +1 -2
- package/dist/jsx/index.native.cjs +21 -0
- package/dist/jsx/index.native.js +10 -10
- package/dist/jsx/index.native.js.map +1 -1
- package/package.json +11 -10
- package/src/ListItem.tsx +159 -193
- package/types/ListItem.d.ts +121 -51
- package/types/ListItem.d.ts.map +1 -1
- package/dist/esm/index.js.map +0 -1
- package/dist/esm/index.mjs.map +0 -1
- package/dist/esm/index.native.js.map +0 -1
- package/dist/jsx/index.js.map +0 -1
- package/dist/jsx/index.mjs.map +0 -1
package/src/ListItem.tsx
CHANGED
|
@@ -1,12 +1,25 @@
|
|
|
1
|
-
import { getFontSize } from '@tamagui/font-size'
|
|
2
1
|
import { getFontSized } from '@tamagui/get-font-sized'
|
|
3
|
-
import {
|
|
2
|
+
import { oneSizeTokenSmaller } from '@tamagui/get-token'
|
|
4
3
|
import { withStaticProperties } from '@tamagui/helpers'
|
|
5
|
-
import {
|
|
4
|
+
import { getThemedIconSize, useGetThemedIcon } from '@tamagui/helpers-tamagui'
|
|
6
5
|
import { YStack } from '@tamagui/stacks'
|
|
6
|
+
import { resolveSizeToken } from '@tamagui/size'
|
|
7
7
|
import { SizableText, wrapChildrenInText } from '@tamagui/text'
|
|
8
|
-
import type {
|
|
9
|
-
|
|
8
|
+
import type {
|
|
9
|
+
ColorTokens,
|
|
10
|
+
FontSizeTokens,
|
|
11
|
+
GetProps,
|
|
12
|
+
SizeTokens,
|
|
13
|
+
VariantSpreadExtras,
|
|
14
|
+
} from '@tamagui/web'
|
|
15
|
+
import {
|
|
16
|
+
createStyledContext,
|
|
17
|
+
createStyledHOC,
|
|
18
|
+
getVariableValue,
|
|
19
|
+
styled,
|
|
20
|
+
useProps,
|
|
21
|
+
View,
|
|
22
|
+
} from '@tamagui/web'
|
|
10
23
|
import type { FunctionComponent, JSX, ReactNode } from 'react'
|
|
11
24
|
|
|
12
25
|
type IconProp = JSX.Element | FunctionComponent<{ color?: any; size?: any }> | null
|
|
@@ -19,7 +32,8 @@ export type ListItemExtraProps = {
|
|
|
19
32
|
scaleIcon?: number
|
|
20
33
|
title?: ReactNode
|
|
21
34
|
subTitle?: ReactNode
|
|
22
|
-
iconSize?: SizeTokens
|
|
35
|
+
iconSize?: SizeTokens | true
|
|
36
|
+
color?: ColorTokens | string
|
|
23
37
|
}
|
|
24
38
|
|
|
25
39
|
export type ListItemProps = GetProps<typeof ListItemFrame> & ListItemExtraProps
|
|
@@ -27,7 +41,7 @@ export type ListItemProps = GetProps<typeof ListItemFrame> & ListItemExtraProps
|
|
|
27
41
|
const NAME = 'ListItem'
|
|
28
42
|
|
|
29
43
|
const context = createStyledContext<{
|
|
30
|
-
size?: SizeTokens
|
|
44
|
+
size?: SizeTokens | true
|
|
31
45
|
variant?: ListItemVariant
|
|
32
46
|
color?: ColorTokens | string
|
|
33
47
|
}>({
|
|
@@ -36,160 +50,97 @@ const context = createStyledContext<{
|
|
|
36
50
|
color: undefined,
|
|
37
51
|
})
|
|
38
52
|
|
|
53
|
+
export const listItemSizeVariant = (
|
|
54
|
+
val: SizeTokens | true,
|
|
55
|
+
{ tokens }: VariantSpreadExtras<any>
|
|
56
|
+
) => {
|
|
57
|
+
const sizeToken = resolveSizeToken(val, 'size')
|
|
58
|
+
const spaceToken = resolveSizeToken(val, 'space')
|
|
59
|
+
const size = typeof sizeToken === 'number' ? sizeToken : tokens.size[sizeToken]
|
|
60
|
+
const sizeVal = getVariableValue(size) as number
|
|
61
|
+
return {
|
|
62
|
+
minHeight: size,
|
|
63
|
+
paddingHorizontal: tokens.space[spaceToken],
|
|
64
|
+
paddingVertical: Math.max(0, Math.round(sizeVal * 0.36 - 9)),
|
|
65
|
+
gap: getThemedIconSize(sizeToken, 0.4),
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const listItemSubtitleSizeVariant = (
|
|
70
|
+
val: SizeTokens | true,
|
|
71
|
+
extras: VariantSpreadExtras<any>
|
|
72
|
+
) => {
|
|
73
|
+
const fontSizeToken = resolveSizeToken(val, 'fontSize')
|
|
74
|
+
const oneSmaller = oneSizeTokenSmaller(fontSizeToken)
|
|
75
|
+
return getFontSized(oneSmaller as FontSizeTokens, extras as any)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Unstyled ListItem frame: structural layout + the size mechanism + the
|
|
79
|
+
// disabled pointer-event block only. Theme decoration (palette, border, cursor,
|
|
80
|
+
// hover/press color styling, the outlined/active appearance, disabled dimming)
|
|
81
|
+
// lives in the tamagui skin (code/ui/tamagui/src/components/ListItem.tsx).
|
|
39
82
|
const ListItemFrame = styled(View, {
|
|
40
83
|
context,
|
|
41
|
-
|
|
84
|
+
displayName: NAME,
|
|
42
85
|
render: 'li',
|
|
43
86
|
role: 'listitem',
|
|
87
|
+
size: true,
|
|
88
|
+
alignItems: 'center',
|
|
89
|
+
justifyContent: 'space-between',
|
|
90
|
+
flexWrap: 'nowrap',
|
|
91
|
+
width: '100%',
|
|
92
|
+
maxWidth: '100%',
|
|
93
|
+
overflow: 'hidden',
|
|
94
|
+
flexDirection: 'row',
|
|
44
95
|
|
|
45
96
|
variants: {
|
|
46
|
-
unstyled: {
|
|
47
|
-
false: {
|
|
48
|
-
size: '$true',
|
|
49
|
-
alignItems: 'center',
|
|
50
|
-
justifyContent: 'space-between',
|
|
51
|
-
flexWrap: 'nowrap',
|
|
52
|
-
borderColor: '$borderColor',
|
|
53
|
-
width: '100%',
|
|
54
|
-
maxWidth: '100%',
|
|
55
|
-
overflow: 'hidden',
|
|
56
|
-
flexDirection: 'row',
|
|
57
|
-
backgroundColor: '$background',
|
|
58
|
-
cursor: 'default',
|
|
59
|
-
|
|
60
|
-
hoverStyle: {
|
|
61
|
-
backgroundColor: '$backgroundHover',
|
|
62
|
-
borderColor: '$borderColorHover',
|
|
63
|
-
},
|
|
64
|
-
|
|
65
|
-
pressStyle: {
|
|
66
|
-
backgroundColor: '$backgroundPress',
|
|
67
|
-
borderColor: '$borderColorPress',
|
|
68
|
-
},
|
|
69
|
-
},
|
|
70
|
-
},
|
|
71
|
-
|
|
72
|
-
variant: {
|
|
73
|
-
outlined:
|
|
74
|
-
process.env.TAMAGUI_HEADLESS === '1'
|
|
75
|
-
? {}
|
|
76
|
-
: {
|
|
77
|
-
backgroundColor: 'transparent',
|
|
78
|
-
borderWidth: 1,
|
|
79
|
-
borderColor: '$borderColor',
|
|
80
|
-
|
|
81
|
-
hoverStyle: {
|
|
82
|
-
backgroundColor: 'transparent',
|
|
83
|
-
borderColor: '$borderColorHover',
|
|
84
|
-
},
|
|
85
|
-
|
|
86
|
-
pressStyle: {
|
|
87
|
-
backgroundColor: 'transparent',
|
|
88
|
-
borderColor: '$borderColorPress',
|
|
89
|
-
},
|
|
90
|
-
},
|
|
91
|
-
},
|
|
92
|
-
|
|
93
97
|
size: {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
minHeight: tokens.size[val],
|
|
97
|
-
paddingHorizontal: tokens.space[val],
|
|
98
|
-
paddingVertical: getSpace(tokens.space[val], {
|
|
99
|
-
shift: -4,
|
|
100
|
-
}),
|
|
101
|
-
}
|
|
102
|
-
},
|
|
103
|
-
},
|
|
104
|
-
|
|
105
|
-
active: {
|
|
106
|
-
true: {
|
|
107
|
-
hoverStyle: {
|
|
108
|
-
backgroundColor: '$background',
|
|
109
|
-
},
|
|
110
|
-
},
|
|
98
|
+
true: listItemSizeVariant,
|
|
99
|
+
Size: listItemSizeVariant,
|
|
111
100
|
},
|
|
112
101
|
|
|
113
102
|
disabled: {
|
|
114
103
|
true: {
|
|
115
|
-
opacity: 0.5,
|
|
116
104
|
pointerEvents: 'none',
|
|
117
105
|
},
|
|
118
106
|
},
|
|
119
107
|
} as const,
|
|
120
|
-
|
|
121
|
-
defaultVariants: {
|
|
122
|
-
unstyled: process.env.TAMAGUI_HEADLESS === '1',
|
|
123
|
-
},
|
|
124
108
|
})
|
|
125
109
|
|
|
110
|
+
// text color comes from the styled context (the tamagui skin sets a default
|
|
111
|
+
// `color` on ListItem, which flows through as context.color); unstyled it
|
|
112
|
+
// inherits.
|
|
126
113
|
const ListItemText = styled(SizableText, {
|
|
127
114
|
context,
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
size: '$true',
|
|
135
|
-
flexGrow: 1,
|
|
136
|
-
flexShrink: 1,
|
|
137
|
-
ellipsis: true,
|
|
138
|
-
cursor: 'inherit',
|
|
139
|
-
},
|
|
140
|
-
},
|
|
141
|
-
} as const,
|
|
142
|
-
|
|
143
|
-
defaultVariants: {
|
|
144
|
-
unstyled: process.env.TAMAGUI_HEADLESS === '1',
|
|
145
|
-
},
|
|
115
|
+
displayName: 'ListItemText',
|
|
116
|
+
size: true,
|
|
117
|
+
flexGrow: 1,
|
|
118
|
+
flexShrink: 1,
|
|
119
|
+
ellipsis: true,
|
|
120
|
+
cursor: 'inherit',
|
|
146
121
|
})
|
|
147
122
|
|
|
148
123
|
const ListItemSubtitle = styled(ListItemText, {
|
|
149
|
-
|
|
124
|
+
displayName: 'ListItemSubtitle',
|
|
150
125
|
context,
|
|
126
|
+
opacity: 0.6,
|
|
127
|
+
maxWidth: '100%',
|
|
151
128
|
variants: {
|
|
152
|
-
unstyled: {
|
|
153
|
-
false: {
|
|
154
|
-
opacity: 0.6,
|
|
155
|
-
maxWidth: '100%',
|
|
156
|
-
color: '$color',
|
|
157
|
-
},
|
|
158
|
-
},
|
|
159
|
-
|
|
160
129
|
size: {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
shift: -1,
|
|
164
|
-
excludeHalfSteps: true,
|
|
165
|
-
})
|
|
166
|
-
const fontStyle = getFontSized(oneSmaller.key as FontSizeTokens, extras as any)
|
|
167
|
-
return fontStyle
|
|
168
|
-
},
|
|
130
|
+
true: listItemSubtitleSizeVariant,
|
|
131
|
+
Size: listItemSubtitleSizeVariant,
|
|
169
132
|
},
|
|
170
133
|
} as const,
|
|
171
|
-
|
|
172
|
-
defaultVariants: {
|
|
173
|
-
unstyled: process.env.TAMAGUI_HEADLESS === '1',
|
|
174
|
-
},
|
|
175
134
|
})
|
|
176
135
|
|
|
177
136
|
const ListItemTitle = styled(ListItemText, {
|
|
178
|
-
|
|
137
|
+
displayName: 'ListItemTitle',
|
|
179
138
|
context,
|
|
180
|
-
variants: {
|
|
181
|
-
unstyled: {
|
|
182
|
-
false: {},
|
|
183
|
-
},
|
|
184
|
-
} as const,
|
|
185
|
-
defaultVariants: {
|
|
186
|
-
unstyled: process.env.TAMAGUI_HEADLESS === '1',
|
|
187
|
-
},
|
|
188
139
|
})
|
|
189
140
|
|
|
190
141
|
const ListItemIcon = (props: {
|
|
191
142
|
children: React.ReactNode
|
|
192
|
-
size?: SizeTokens
|
|
143
|
+
size?: SizeTokens | true
|
|
193
144
|
scaleIcon?: number
|
|
194
145
|
}) => {
|
|
195
146
|
const { children, size, scaleIcon = 1 } = props
|
|
@@ -198,91 +149,106 @@ const ListItemIcon = (props: {
|
|
|
198
149
|
throw new Error('ListItem.Icon must be used within a ListItem')
|
|
199
150
|
}
|
|
200
151
|
|
|
201
|
-
const sizeToken = size ?? styledContext.size ??
|
|
202
|
-
const
|
|
203
|
-
|
|
204
|
-
|
|
152
|
+
const sizeToken = size ?? styledContext.size ?? true
|
|
153
|
+
const contextColor = styledContext.color
|
|
154
|
+
const iconColorProp =
|
|
155
|
+
contextColor === 'unset' || typeof contextColor === 'number'
|
|
156
|
+
? undefined
|
|
157
|
+
: contextColor
|
|
205
158
|
|
|
206
|
-
|
|
159
|
+
const iconSize = getThemedIconSize(sizeToken, scaleIcon)
|
|
160
|
+
const getThemedIcon = useGetThemedIcon({
|
|
207
161
|
size: iconSize,
|
|
208
|
-
color:
|
|
162
|
+
color: iconColorProp,
|
|
209
163
|
})
|
|
164
|
+
|
|
165
|
+
return getThemedIcon(children)
|
|
210
166
|
}
|
|
211
167
|
|
|
212
|
-
const ListItemComponent =
|
|
213
|
-
|
|
168
|
+
const ListItemComponent = createStyledHOC(
|
|
169
|
+
ListItemFrame,
|
|
170
|
+
function ListItem(propsIn: ListItemProps, ref) {
|
|
171
|
+
const processedProps = useProps(propsIn, {
|
|
172
|
+
noNormalize: true,
|
|
173
|
+
noExpand: true,
|
|
174
|
+
})
|
|
175
|
+
|
|
214
176
|
const {
|
|
215
177
|
children,
|
|
216
178
|
icon,
|
|
217
179
|
iconAfter,
|
|
218
180
|
scaleIcon = 1,
|
|
219
|
-
unstyled = false,
|
|
220
181
|
subTitle,
|
|
221
182
|
title,
|
|
222
183
|
iconSize,
|
|
184
|
+
color,
|
|
223
185
|
...rest
|
|
224
|
-
} =
|
|
186
|
+
} = processedProps
|
|
225
187
|
|
|
226
|
-
const size = propsIn.size || '$true'
|
|
227
188
|
const styledContext = context.useStyledContext()
|
|
228
|
-
const
|
|
229
|
-
const
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
) : null
|
|
242
|
-
|
|
243
|
-
const wrappedChildren = wrapChildrenInText(
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
189
|
+
const size = rest.size ?? propsIn.size ?? styledContext?.size ?? true
|
|
190
|
+
const contextColor = color ?? propsIn.color ?? styledContext?.color
|
|
191
|
+
const iconColorProp =
|
|
192
|
+
contextColor === 'unset' || typeof contextColor === 'number'
|
|
193
|
+
? undefined
|
|
194
|
+
: contextColor
|
|
195
|
+
const iconSizeNumber = getThemedIconSize(iconSize ?? (size as any), scaleIcon)
|
|
196
|
+
const getThemedIcon = useGetThemedIcon({
|
|
197
|
+
size: iconSizeNumber,
|
|
198
|
+
color: iconColorProp,
|
|
199
|
+
})
|
|
200
|
+
|
|
201
|
+
const themedIcon = icon ? getThemedIcon(icon) : null
|
|
202
|
+
const themedIconAfter = iconAfter ? getThemedIcon(iconAfter) : null
|
|
203
|
+
|
|
204
|
+
const wrappedChildren = wrapChildrenInText(ListItemText, { children }, { size })
|
|
205
|
+
|
|
206
|
+
const listItemContext = {
|
|
207
|
+
...styledContext,
|
|
208
|
+
color: contextColor,
|
|
209
|
+
size: size as SizeTokens,
|
|
210
|
+
variant: (rest.variant ?? propsIn.variant ?? styledContext?.variant) as
|
|
211
|
+
| ListItemVariant
|
|
212
|
+
| undefined,
|
|
213
|
+
}
|
|
214
|
+
const frameProps = {
|
|
215
|
+
size,
|
|
216
|
+
variant: listItemContext.variant,
|
|
217
|
+
...rest,
|
|
218
|
+
}
|
|
253
219
|
|
|
254
220
|
return (
|
|
255
|
-
<
|
|
256
|
-
{
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
{title ? (
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
)}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
</
|
|
221
|
+
<context.Provider {...listItemContext}>
|
|
222
|
+
<ListItemFrame ref={ref} {...(frameProps as any)}>
|
|
223
|
+
<context.Provider {...listItemContext}>
|
|
224
|
+
{themedIcon}
|
|
225
|
+
{title || subTitle ? (
|
|
226
|
+
<YStack flex={1}>
|
|
227
|
+
{title ? (
|
|
228
|
+
typeof title === 'string' ? (
|
|
229
|
+
<ListItemTitle size={size as any}>{title}</ListItemTitle>
|
|
230
|
+
) : (
|
|
231
|
+
title
|
|
232
|
+
)
|
|
233
|
+
) : null}
|
|
234
|
+
{subTitle ? (
|
|
235
|
+
<>
|
|
236
|
+
{typeof subTitle === 'string' ? (
|
|
237
|
+
<ListItemSubtitle size={size}>{subTitle}</ListItemSubtitle>
|
|
238
|
+
) : (
|
|
239
|
+
subTitle
|
|
240
|
+
)}
|
|
241
|
+
</>
|
|
242
|
+
) : null}
|
|
243
|
+
{wrappedChildren}
|
|
244
|
+
</YStack>
|
|
245
|
+
) : (
|
|
246
|
+
wrappedChildren
|
|
247
|
+
)}
|
|
248
|
+
{themedIconAfter}
|
|
249
|
+
</context.Provider>
|
|
250
|
+
</ListItemFrame>
|
|
251
|
+
</context.Provider>
|
|
286
252
|
)
|
|
287
253
|
}
|
|
288
254
|
)
|