@onlynative/components 0.1.0-alpha.0
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/README.md +99 -0
- package/dist/appbar/index.d.ts +71 -0
- package/dist/appbar/index.js +952 -0
- package/dist/button/index.d.ts +41 -0
- package/dist/button/index.js +454 -0
- package/dist/card/index.d.ts +31 -0
- package/dist/card/index.js +264 -0
- package/dist/checkbox/index.d.ts +25 -0
- package/dist/checkbox/index.js +291 -0
- package/dist/chip/index.d.ts +62 -0
- package/dist/chip/index.js +452 -0
- package/dist/icon-button/index.d.ts +10 -0
- package/dist/icon-button/index.js +575 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +3374 -0
- package/dist/layout/index.d.ts +98 -0
- package/dist/layout/index.js +282 -0
- package/dist/list/index.d.ts +60 -0
- package/dist/list/index.js +300 -0
- package/dist/radio/index.d.ts +25 -0
- package/dist/radio/index.js +250 -0
- package/dist/switch/index.d.ts +37 -0
- package/dist/switch/index.js +315 -0
- package/dist/text-field/index.d.ts +52 -0
- package/dist/text-field/index.js +496 -0
- package/dist/types-D3hlyvz-.d.ts +51 -0
- package/dist/typography/index.d.ts +28 -0
- package/dist/typography/index.js +69 -0
- package/package.json +166 -0
- package/src/appbar/AppBar.tsx +302 -0
- package/src/appbar/index.ts +2 -0
- package/src/appbar/styles.ts +92 -0
- package/src/appbar/types.ts +67 -0
- package/src/button/Button.tsx +130 -0
- package/src/button/index.ts +2 -0
- package/src/button/styles.ts +288 -0
- package/src/button/types.ts +42 -0
- package/src/card/Card.tsx +69 -0
- package/src/card/index.ts +2 -0
- package/src/card/styles.ts +151 -0
- package/src/card/types.ts +27 -0
- package/src/checkbox/Checkbox.tsx +109 -0
- package/src/checkbox/index.ts +2 -0
- package/src/checkbox/styles.ts +155 -0
- package/src/checkbox/types.ts +20 -0
- package/src/chip/Chip.tsx +182 -0
- package/src/chip/index.ts +2 -0
- package/src/chip/styles.ts +240 -0
- package/src/chip/types.ts +58 -0
- package/src/icon-button/IconButton.tsx +358 -0
- package/src/icon-button/index.ts +6 -0
- package/src/icon-button/styles.ts +259 -0
- package/src/icon-button/types.ts +55 -0
- package/src/index.ts +51 -0
- package/src/layout/Box.tsx +99 -0
- package/src/layout/Column.tsx +16 -0
- package/src/layout/Grid.tsx +49 -0
- package/src/layout/Layout.tsx +81 -0
- package/src/layout/Row.tsx +22 -0
- package/src/layout/index.ts +13 -0
- package/src/layout/resolveSpacing.ts +11 -0
- package/src/layout/types.ts +82 -0
- package/src/list/List.tsx +17 -0
- package/src/list/ListDivider.tsx +20 -0
- package/src/list/ListItem.tsx +128 -0
- package/src/list/index.ts +9 -0
- package/src/list/styles.ts +132 -0
- package/src/list/types.ts +54 -0
- package/src/radio/Radio.tsx +103 -0
- package/src/radio/index.ts +2 -0
- package/src/radio/styles.ts +139 -0
- package/src/radio/types.ts +20 -0
- package/src/switch/Switch.tsx +118 -0
- package/src/switch/index.ts +2 -0
- package/src/switch/styles.ts +172 -0
- package/src/switch/types.ts +32 -0
- package/src/test-utils/render-with-theme.tsx +13 -0
- package/src/text-field/TextField.tsx +298 -0
- package/src/text-field/index.ts +2 -0
- package/src/text-field/styles.ts +240 -0
- package/src/text-field/types.ts +49 -0
- package/src/typography/Typography.tsx +65 -0
- package/src/typography/index.ts +3 -0
- package/src/typography/types.ts +17 -0
- package/src/utils/color.ts +64 -0
- package/src/utils/elevation.ts +33 -0
- package/src/utils/rtl.ts +19 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { ReactNode } from 'react'
|
|
2
|
+
import type { ViewProps } from 'react-native'
|
|
3
|
+
|
|
4
|
+
/** Surface style variant of the card following Material Design 3 roles. */
|
|
5
|
+
export type CardVariant = 'elevated' | 'filled' | 'outlined'
|
|
6
|
+
|
|
7
|
+
export interface CardProps extends ViewProps {
|
|
8
|
+
/** Content rendered inside the card surface. */
|
|
9
|
+
children: ReactNode
|
|
10
|
+
/**
|
|
11
|
+
* Surface style variant.
|
|
12
|
+
* @default 'elevated'
|
|
13
|
+
*/
|
|
14
|
+
variant?: CardVariant
|
|
15
|
+
/** When provided, the card becomes interactive (Pressable). Omit to render as a plain View. */
|
|
16
|
+
onPress?: () => void
|
|
17
|
+
/**
|
|
18
|
+
* Disables the press interaction and reduces opacity. Only effective when `onPress` is provided.
|
|
19
|
+
* @default false
|
|
20
|
+
*/
|
|
21
|
+
disabled?: boolean
|
|
22
|
+
/**
|
|
23
|
+
* Override the container (background) color.
|
|
24
|
+
* State-layer colors (hover, press) are derived automatically.
|
|
25
|
+
*/
|
|
26
|
+
containerColor?: string
|
|
27
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import MaterialCommunityIcons from '@expo/vector-icons/MaterialCommunityIcons'
|
|
2
|
+
import { useMemo } from 'react'
|
|
3
|
+
import { Platform, Pressable, StyleSheet, View } from 'react-native'
|
|
4
|
+
import type { StyleProp, ViewStyle } from 'react-native'
|
|
5
|
+
import { useTheme } from '@onlynative/core'
|
|
6
|
+
|
|
7
|
+
import { createStyles } from './styles'
|
|
8
|
+
import type { CheckboxProps } from './types'
|
|
9
|
+
|
|
10
|
+
interface PressableState {
|
|
11
|
+
pressed: boolean
|
|
12
|
+
hovered?: boolean
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function resolveStyle(
|
|
16
|
+
containerStyle: StyleProp<ViewStyle>,
|
|
17
|
+
hoveredContainerStyle: StyleProp<ViewStyle>,
|
|
18
|
+
pressedContainerStyle: StyleProp<ViewStyle>,
|
|
19
|
+
disabledContainerStyle: StyleProp<ViewStyle>,
|
|
20
|
+
disabled: boolean,
|
|
21
|
+
style: CheckboxProps['style'],
|
|
22
|
+
): (state: PressableState) => StyleProp<ViewStyle> {
|
|
23
|
+
if (typeof style === 'function') {
|
|
24
|
+
return (state) => [
|
|
25
|
+
containerStyle,
|
|
26
|
+
state.hovered && !state.pressed && !disabled
|
|
27
|
+
? hoveredContainerStyle
|
|
28
|
+
: undefined,
|
|
29
|
+
state.pressed && !disabled ? pressedContainerStyle : undefined,
|
|
30
|
+
disabled ? disabledContainerStyle : undefined,
|
|
31
|
+
style(state),
|
|
32
|
+
]
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return (state) => [
|
|
36
|
+
containerStyle,
|
|
37
|
+
state.hovered && !state.pressed && !disabled
|
|
38
|
+
? hoveredContainerStyle
|
|
39
|
+
: undefined,
|
|
40
|
+
state.pressed && !disabled ? pressedContainerStyle : undefined,
|
|
41
|
+
disabled ? disabledContainerStyle : undefined,
|
|
42
|
+
style,
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function Checkbox({
|
|
47
|
+
style,
|
|
48
|
+
value = false,
|
|
49
|
+
onValueChange,
|
|
50
|
+
containerColor,
|
|
51
|
+
contentColor,
|
|
52
|
+
disabled = false,
|
|
53
|
+
...props
|
|
54
|
+
}: CheckboxProps) {
|
|
55
|
+
const isDisabled = Boolean(disabled)
|
|
56
|
+
const isChecked = Boolean(value)
|
|
57
|
+
|
|
58
|
+
const theme = useTheme()
|
|
59
|
+
const styles = useMemo(
|
|
60
|
+
() => createStyles(theme, isChecked, containerColor, contentColor),
|
|
61
|
+
[theme, isChecked, containerColor, contentColor],
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
const resolvedIconColor = useMemo(() => {
|
|
65
|
+
const base = StyleSheet.flatten([
|
|
66
|
+
styles.iconColor,
|
|
67
|
+
isDisabled ? styles.disabledIconColor : undefined,
|
|
68
|
+
])
|
|
69
|
+
return typeof base?.color === 'string' ? base.color : undefined
|
|
70
|
+
}, [styles.iconColor, styles.disabledIconColor, isDisabled])
|
|
71
|
+
|
|
72
|
+
const handlePress = () => {
|
|
73
|
+
if (!isDisabled) {
|
|
74
|
+
onValueChange?.(!isChecked)
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return (
|
|
79
|
+
<Pressable
|
|
80
|
+
{...props}
|
|
81
|
+
accessibilityRole="checkbox"
|
|
82
|
+
accessibilityState={{
|
|
83
|
+
disabled: isDisabled,
|
|
84
|
+
checked: isChecked,
|
|
85
|
+
}}
|
|
86
|
+
hitSlop={Platform.OS === 'web' ? undefined : 4}
|
|
87
|
+
disabled={isDisabled}
|
|
88
|
+
onPress={handlePress}
|
|
89
|
+
style={resolveStyle(
|
|
90
|
+
styles.container,
|
|
91
|
+
styles.hoveredContainer,
|
|
92
|
+
styles.pressedContainer,
|
|
93
|
+
styles.disabledContainer,
|
|
94
|
+
isDisabled,
|
|
95
|
+
style,
|
|
96
|
+
)}
|
|
97
|
+
>
|
|
98
|
+
<View style={[styles.box, isDisabled ? styles.disabledBox : undefined]}>
|
|
99
|
+
{isChecked ? (
|
|
100
|
+
<MaterialCommunityIcons
|
|
101
|
+
name="check"
|
|
102
|
+
size={14}
|
|
103
|
+
color={resolvedIconColor}
|
|
104
|
+
/>
|
|
105
|
+
) : null}
|
|
106
|
+
</View>
|
|
107
|
+
</Pressable>
|
|
108
|
+
)
|
|
109
|
+
}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { StyleSheet } from 'react-native'
|
|
2
|
+
import type { Theme } from '@onlynative/core'
|
|
3
|
+
|
|
4
|
+
import { alphaColor, blendColor } from '../utils/color'
|
|
5
|
+
|
|
6
|
+
interface BoxColors {
|
|
7
|
+
backgroundColor: string
|
|
8
|
+
borderColor: string
|
|
9
|
+
borderWidth: number
|
|
10
|
+
iconColor: string
|
|
11
|
+
hoveredBackgroundColor: string
|
|
12
|
+
pressedBackgroundColor: string
|
|
13
|
+
disabledBackgroundColor: string
|
|
14
|
+
disabledBorderColor: string
|
|
15
|
+
disabledBorderWidth: number
|
|
16
|
+
disabledIconColor: string
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function getColors(theme: Theme, checked: boolean): BoxColors {
|
|
20
|
+
const disabledOnSurface38 = alphaColor(theme.colors.onSurface, 0.38)
|
|
21
|
+
|
|
22
|
+
if (checked) {
|
|
23
|
+
return {
|
|
24
|
+
backgroundColor: theme.colors.primary,
|
|
25
|
+
borderColor: 'transparent',
|
|
26
|
+
borderWidth: 0,
|
|
27
|
+
iconColor: theme.colors.onPrimary,
|
|
28
|
+
hoveredBackgroundColor: blendColor(
|
|
29
|
+
theme.colors.primary,
|
|
30
|
+
theme.colors.onPrimary,
|
|
31
|
+
theme.stateLayer.hoveredOpacity,
|
|
32
|
+
),
|
|
33
|
+
pressedBackgroundColor: blendColor(
|
|
34
|
+
theme.colors.primary,
|
|
35
|
+
theme.colors.onPrimary,
|
|
36
|
+
theme.stateLayer.pressedOpacity,
|
|
37
|
+
),
|
|
38
|
+
disabledBackgroundColor: disabledOnSurface38,
|
|
39
|
+
disabledBorderColor: 'transparent',
|
|
40
|
+
disabledBorderWidth: 0,
|
|
41
|
+
disabledIconColor: theme.colors.surface,
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
backgroundColor: 'transparent',
|
|
47
|
+
borderColor: theme.colors.onSurfaceVariant,
|
|
48
|
+
borderWidth: 2,
|
|
49
|
+
iconColor: 'transparent',
|
|
50
|
+
hoveredBackgroundColor: alphaColor(
|
|
51
|
+
theme.colors.onSurface,
|
|
52
|
+
theme.stateLayer.hoveredOpacity,
|
|
53
|
+
),
|
|
54
|
+
pressedBackgroundColor: alphaColor(
|
|
55
|
+
theme.colors.onSurface,
|
|
56
|
+
theme.stateLayer.pressedOpacity,
|
|
57
|
+
),
|
|
58
|
+
disabledBackgroundColor: 'transparent',
|
|
59
|
+
disabledBorderColor: disabledOnSurface38,
|
|
60
|
+
disabledBorderWidth: 2,
|
|
61
|
+
disabledIconColor: 'transparent',
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function applyColorOverrides(
|
|
66
|
+
theme: Theme,
|
|
67
|
+
colors: BoxColors,
|
|
68
|
+
containerColor?: string,
|
|
69
|
+
contentColor?: string,
|
|
70
|
+
): BoxColors {
|
|
71
|
+
if (!containerColor && !contentColor) return colors
|
|
72
|
+
|
|
73
|
+
const result = { ...colors }
|
|
74
|
+
|
|
75
|
+
if (contentColor) {
|
|
76
|
+
result.iconColor = contentColor
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (containerColor) {
|
|
80
|
+
const overlay = contentColor ?? colors.iconColor
|
|
81
|
+
result.backgroundColor = containerColor
|
|
82
|
+
result.borderColor = containerColor
|
|
83
|
+
result.hoveredBackgroundColor = blendColor(
|
|
84
|
+
containerColor,
|
|
85
|
+
overlay,
|
|
86
|
+
theme.stateLayer.hoveredOpacity,
|
|
87
|
+
)
|
|
88
|
+
result.pressedBackgroundColor = blendColor(
|
|
89
|
+
containerColor,
|
|
90
|
+
overlay,
|
|
91
|
+
theme.stateLayer.pressedOpacity,
|
|
92
|
+
)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return result
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function createStyles(
|
|
99
|
+
theme: Theme,
|
|
100
|
+
checked: boolean,
|
|
101
|
+
containerColor?: string,
|
|
102
|
+
contentColor?: string,
|
|
103
|
+
) {
|
|
104
|
+
const colors = applyColorOverrides(
|
|
105
|
+
theme,
|
|
106
|
+
getColors(theme, checked),
|
|
107
|
+
containerColor,
|
|
108
|
+
contentColor,
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
const size = 18
|
|
112
|
+
const touchTarget = 48
|
|
113
|
+
|
|
114
|
+
return StyleSheet.create({
|
|
115
|
+
container: {
|
|
116
|
+
width: touchTarget,
|
|
117
|
+
height: touchTarget,
|
|
118
|
+
alignItems: 'center',
|
|
119
|
+
justifyContent: 'center',
|
|
120
|
+
cursor: 'pointer',
|
|
121
|
+
},
|
|
122
|
+
hoveredContainer: {
|
|
123
|
+
borderRadius: touchTarget / 2,
|
|
124
|
+
backgroundColor: colors.hoveredBackgroundColor,
|
|
125
|
+
},
|
|
126
|
+
pressedContainer: {
|
|
127
|
+
borderRadius: touchTarget / 2,
|
|
128
|
+
backgroundColor: colors.pressedBackgroundColor,
|
|
129
|
+
},
|
|
130
|
+
disabledContainer: {
|
|
131
|
+
cursor: 'auto',
|
|
132
|
+
},
|
|
133
|
+
box: {
|
|
134
|
+
width: size,
|
|
135
|
+
height: size,
|
|
136
|
+
borderRadius: theme.shape.cornerExtraSmall,
|
|
137
|
+
backgroundColor: colors.backgroundColor,
|
|
138
|
+
borderColor: colors.borderColor,
|
|
139
|
+
borderWidth: colors.borderWidth,
|
|
140
|
+
alignItems: 'center' as const,
|
|
141
|
+
justifyContent: 'center' as const,
|
|
142
|
+
},
|
|
143
|
+
disabledBox: {
|
|
144
|
+
backgroundColor: colors.disabledBackgroundColor,
|
|
145
|
+
borderColor: colors.disabledBorderColor,
|
|
146
|
+
borderWidth: colors.disabledBorderWidth,
|
|
147
|
+
},
|
|
148
|
+
iconColor: {
|
|
149
|
+
color: colors.iconColor,
|
|
150
|
+
},
|
|
151
|
+
disabledIconColor: {
|
|
152
|
+
color: colors.disabledIconColor,
|
|
153
|
+
},
|
|
154
|
+
})
|
|
155
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { PressableProps } from 'react-native'
|
|
2
|
+
|
|
3
|
+
export interface CheckboxProps extends Omit<PressableProps, 'children'> {
|
|
4
|
+
/**
|
|
5
|
+
* Whether the checkbox is checked.
|
|
6
|
+
* @default false
|
|
7
|
+
*/
|
|
8
|
+
value?: boolean
|
|
9
|
+
/** Callback fired when the checkbox is toggled. Receives the new value. */
|
|
10
|
+
onValueChange?: (value: boolean) => void
|
|
11
|
+
/**
|
|
12
|
+
* Override the container (box) color when checked.
|
|
13
|
+
* State-layer colors (hover, press) are derived automatically.
|
|
14
|
+
*/
|
|
15
|
+
containerColor?: string
|
|
16
|
+
/**
|
|
17
|
+
* Override the checkmark icon color.
|
|
18
|
+
*/
|
|
19
|
+
contentColor?: string
|
|
20
|
+
}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import MaterialCommunityIcons from '@expo/vector-icons/MaterialCommunityIcons'
|
|
2
|
+
import { useMemo } from 'react'
|
|
3
|
+
import { Platform, Pressable, StyleSheet, Text, View } from 'react-native'
|
|
4
|
+
import type { StyleProp, ViewStyle } from 'react-native'
|
|
5
|
+
import { useTheme } from '@onlynative/core'
|
|
6
|
+
|
|
7
|
+
import { createStyles } from './styles'
|
|
8
|
+
import type { ChipProps } from './types'
|
|
9
|
+
|
|
10
|
+
interface PressableState {
|
|
11
|
+
pressed: boolean
|
|
12
|
+
hovered?: boolean
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function resolveStyle(
|
|
16
|
+
containerStyle: StyleProp<ViewStyle>,
|
|
17
|
+
hoveredContainerStyle: StyleProp<ViewStyle>,
|
|
18
|
+
pressedContainerStyle: StyleProp<ViewStyle>,
|
|
19
|
+
disabledContainerStyle: StyleProp<ViewStyle>,
|
|
20
|
+
disabled: boolean,
|
|
21
|
+
style: ChipProps['style'],
|
|
22
|
+
): (state: PressableState) => StyleProp<ViewStyle> {
|
|
23
|
+
if (typeof style === 'function') {
|
|
24
|
+
return (state) => [
|
|
25
|
+
containerStyle,
|
|
26
|
+
state.hovered && !state.pressed && !disabled
|
|
27
|
+
? hoveredContainerStyle
|
|
28
|
+
: undefined,
|
|
29
|
+
state.pressed && !disabled ? pressedContainerStyle : undefined,
|
|
30
|
+
disabled ? disabledContainerStyle : undefined,
|
|
31
|
+
style(state),
|
|
32
|
+
]
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return (state) => [
|
|
36
|
+
containerStyle,
|
|
37
|
+
state.hovered && !state.pressed && !disabled
|
|
38
|
+
? hoveredContainerStyle
|
|
39
|
+
: undefined,
|
|
40
|
+
state.pressed && !disabled ? pressedContainerStyle : undefined,
|
|
41
|
+
disabled ? disabledContainerStyle : undefined,
|
|
42
|
+
style,
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function Chip({
|
|
47
|
+
children,
|
|
48
|
+
style,
|
|
49
|
+
variant = 'assist',
|
|
50
|
+
elevated = false,
|
|
51
|
+
selected = false,
|
|
52
|
+
leadingIcon,
|
|
53
|
+
iconSize = 18,
|
|
54
|
+
avatar,
|
|
55
|
+
onClose,
|
|
56
|
+
containerColor,
|
|
57
|
+
contentColor,
|
|
58
|
+
labelStyle: labelStyleOverride,
|
|
59
|
+
disabled = false,
|
|
60
|
+
...props
|
|
61
|
+
}: ChipProps) {
|
|
62
|
+
const isDisabled = Boolean(disabled)
|
|
63
|
+
const isSelected = variant === 'filter' ? Boolean(selected) : false
|
|
64
|
+
|
|
65
|
+
const showCloseIcon =
|
|
66
|
+
onClose !== undefined &&
|
|
67
|
+
(variant === 'input' || (variant === 'filter' && isSelected))
|
|
68
|
+
|
|
69
|
+
const hasLeadingContent = Boolean(
|
|
70
|
+
(variant === 'input' && avatar) ||
|
|
71
|
+
leadingIcon ||
|
|
72
|
+
(variant === 'filter' && isSelected),
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
const theme = useTheme()
|
|
76
|
+
const styles = useMemo(
|
|
77
|
+
() =>
|
|
78
|
+
createStyles(
|
|
79
|
+
theme,
|
|
80
|
+
variant,
|
|
81
|
+
elevated,
|
|
82
|
+
isSelected,
|
|
83
|
+
hasLeadingContent,
|
|
84
|
+
showCloseIcon,
|
|
85
|
+
containerColor,
|
|
86
|
+
contentColor,
|
|
87
|
+
),
|
|
88
|
+
[
|
|
89
|
+
theme,
|
|
90
|
+
variant,
|
|
91
|
+
elevated,
|
|
92
|
+
isSelected,
|
|
93
|
+
hasLeadingContent,
|
|
94
|
+
showCloseIcon,
|
|
95
|
+
containerColor,
|
|
96
|
+
contentColor,
|
|
97
|
+
],
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
const resolvedIconColor = useMemo(() => {
|
|
101
|
+
const base = StyleSheet.flatten([
|
|
102
|
+
styles.label,
|
|
103
|
+
isDisabled ? styles.disabledLabel : undefined,
|
|
104
|
+
])
|
|
105
|
+
return typeof base?.color === 'string' ? base.color : undefined
|
|
106
|
+
}, [styles.label, styles.disabledLabel, isDisabled])
|
|
107
|
+
|
|
108
|
+
const computedLabelStyle = useMemo(
|
|
109
|
+
() => [
|
|
110
|
+
styles.label,
|
|
111
|
+
isDisabled ? styles.disabledLabel : undefined,
|
|
112
|
+
labelStyleOverride,
|
|
113
|
+
],
|
|
114
|
+
[isDisabled, styles.disabledLabel, styles.label, labelStyleOverride],
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
const renderLeadingContent = () => {
|
|
118
|
+
if (variant === 'input' && avatar) {
|
|
119
|
+
return <View style={styles.avatar}>{avatar}</View>
|
|
120
|
+
}
|
|
121
|
+
if (leadingIcon) {
|
|
122
|
+
return (
|
|
123
|
+
<MaterialCommunityIcons
|
|
124
|
+
name={leadingIcon}
|
|
125
|
+
size={iconSize}
|
|
126
|
+
color={resolvedIconColor}
|
|
127
|
+
style={styles.leadingIcon}
|
|
128
|
+
/>
|
|
129
|
+
)
|
|
130
|
+
}
|
|
131
|
+
if (variant === 'filter' && isSelected) {
|
|
132
|
+
return (
|
|
133
|
+
<MaterialCommunityIcons
|
|
134
|
+
name="check"
|
|
135
|
+
size={iconSize}
|
|
136
|
+
color={resolvedIconColor}
|
|
137
|
+
style={styles.leadingIcon}
|
|
138
|
+
/>
|
|
139
|
+
)
|
|
140
|
+
}
|
|
141
|
+
return null
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return (
|
|
145
|
+
<Pressable
|
|
146
|
+
{...props}
|
|
147
|
+
accessibilityRole="button"
|
|
148
|
+
accessibilityState={{
|
|
149
|
+
disabled: isDisabled,
|
|
150
|
+
...(variant === 'filter' ? { selected: isSelected } : undefined),
|
|
151
|
+
}}
|
|
152
|
+
hitSlop={Platform.OS === 'web' ? undefined : 4}
|
|
153
|
+
disabled={isDisabled}
|
|
154
|
+
style={resolveStyle(
|
|
155
|
+
styles.container,
|
|
156
|
+
styles.hoveredContainer,
|
|
157
|
+
styles.pressedContainer,
|
|
158
|
+
styles.disabledContainer,
|
|
159
|
+
isDisabled,
|
|
160
|
+
style,
|
|
161
|
+
)}
|
|
162
|
+
>
|
|
163
|
+
{renderLeadingContent()}
|
|
164
|
+
<Text style={computedLabelStyle}>{children}</Text>
|
|
165
|
+
{showCloseIcon ? (
|
|
166
|
+
<Pressable
|
|
167
|
+
onPress={onClose}
|
|
168
|
+
accessibilityRole="button"
|
|
169
|
+
accessibilityLabel="Remove"
|
|
170
|
+
hitSlop={4}
|
|
171
|
+
style={styles.closeButton}
|
|
172
|
+
>
|
|
173
|
+
<MaterialCommunityIcons
|
|
174
|
+
name="close"
|
|
175
|
+
size={iconSize}
|
|
176
|
+
color={resolvedIconColor}
|
|
177
|
+
/>
|
|
178
|
+
</Pressable>
|
|
179
|
+
) : null}
|
|
180
|
+
</Pressable>
|
|
181
|
+
)
|
|
182
|
+
}
|