@helpwave/hightide-native 0.0.8 → 0.1.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/README.md +4 -4
- package/package.json +8 -19
- package/src/components/card/Card.tsx +41 -0
- package/src/components/card/index.ts +1 -0
- package/src/components/chat/ChatAttachmentMessageBubble.tsx +246 -0
- package/src/components/chat/ChatConversationRow.tsx +21 -16
- package/src/components/chat/ChatDateDivider.tsx +2 -2
- package/src/components/chat/ChatMessageBubble.tsx +62 -52
- package/src/components/chat/ChatMessageComposer.tsx +16 -14
- package/src/components/chat/ChatQuickReplyChip.tsx +41 -43
- package/src/components/chat/ChatSystemLine.tsx +14 -7
- package/src/components/chat/ChatThreadHeader.tsx +60 -6
- package/src/components/chat/index.ts +1 -2
- package/src/components/index.ts +3 -1
- package/src/components/layout/Divider.tsx +60 -0
- package/src/components/layout/index.ts +1 -0
- package/src/components/list/ListActionItem.tsx +99 -0
- package/src/components/list/ListItem.tsx +96 -0
- package/src/components/list/ListNavigationItem.tsx +102 -0
- package/src/components/list/index.ts +3 -0
- package/src/components/user-interaction/Button.tsx +80 -31
- package/src/components/user-interaction/Checkbox.tsx +72 -32
- package/src/components/user-interaction/IconButton.tsx +68 -30
- package/src/components/user-interaction/Input.tsx +61 -14
- package/src/components/user-interaction/MultiSelect.tsx +142 -75
- package/src/components/user-interaction/SearchBar.tsx +222 -0
- package/src/components/user-interaction/Select.tsx +129 -58
- package/src/components/user-interaction/Switch.tsx +110 -80
- package/src/components/user-interaction/ThemedPressable.tsx +136 -0
- package/src/components/user-interaction/index.ts +2 -0
- package/src/components/visualization-and-display/Avatar.tsx +112 -93
- package/src/components/visualization-and-display/Chip.tsx +22 -22
- package/src/components/visualization-and-display/ThemedIcon.tsx +72 -0
- package/src/components/visualization-and-display/ThemedText.tsx +38 -0
- package/src/components/visualization-and-display/index.ts +2 -1
- package/src/global-contexts/HightideProvider.tsx +19 -10
- package/src/global-contexts/content-theme/ContentThemeContext.ts +22 -0
- package/src/global-contexts/content-theme/ContentThemeProvider.tsx +32 -0
- package/src/global-contexts/content-theme/index.ts +2 -0
- package/src/global-contexts/debug/forward-exports.ts +10 -0
- package/src/global-contexts/debug/index.ts +1 -0
- package/src/global-contexts/index.ts +2 -0
- package/src/global-contexts/theme/ThemeProvider.tsx +7 -1
- package/src/icons/HightideIconRegistry.ts +33 -0
- package/src/icons/index.ts +2 -0
- package/src/icons/types.ts +11 -0
- package/src/theme/adapters/container-adapter.ts +323 -0
- package/src/theme/adapters/defined.ts +11 -0
- package/src/theme/adapters/icon-style-adapter.ts +10 -0
- package/src/theme/adapters/index.ts +4 -0
- package/src/theme/adapters/text-style-adapter.ts +16 -0
- package/src/theme/index.ts +1 -0
- package/src/theme/resolvers/avatar.ts +385 -186
- package/src/theme/resolvers/button.ts +50 -82
- package/src/theme/resolvers/card.ts +27 -0
- package/src/theme/resolvers/chat/attachment-message-bubble.ts +163 -0
- package/src/theme/resolvers/chat/chat-theme.ts +69 -0
- package/src/theme/resolvers/chat/conversation-list.ts +35 -0
- package/src/theme/resolvers/chat/conversation-row.ts +64 -0
- package/src/theme/resolvers/chat/date-divider.ts +31 -0
- package/src/theme/resolvers/chat/index.ts +11 -0
- package/src/theme/resolvers/chat/message-bubble.ts +57 -0
- package/src/theme/resolvers/chat/message-composer.ts +38 -0
- package/src/theme/resolvers/chat/message-list.ts +27 -0
- package/src/theme/resolvers/chat/quick-reply-chip.ts +80 -0
- package/src/theme/resolvers/chat/system-line.ts +41 -0
- package/src/theme/resolvers/chat/thread-header.ts +85 -0
- package/src/theme/resolvers/checkbox.ts +87 -74
- package/src/theme/resolvers/chip.ts +30 -67
- package/src/theme/resolvers/colorScheme.ts +136 -0
- package/src/theme/resolvers/divider.ts +34 -0
- package/src/theme/resolvers/icon.ts +21 -0
- package/src/theme/resolvers/iconButton.ts +45 -61
- package/src/theme/resolvers/index.ts +7 -2
- package/src/theme/resolvers/input.ts +64 -42
- package/src/theme/resolvers/listItem.ts +115 -0
- package/src/theme/resolvers/multiSelect.ts +159 -84
- package/src/theme/resolvers/searchBar.ts +121 -0
- package/src/theme/resolvers/select.ts +141 -66
- package/src/theme/resolvers/switch.ts +59 -53
- package/src/theme/resolvers/themedPressable.ts +54 -0
- package/src/theme/themes/createHightideTheme.ts +214 -51
- package/src/theme/themes/hightideThemes.ts +10 -6
- package/src/theme/types/color.ts +2 -59
- package/src/theme/types/components/avatar.ts +37 -36
- package/src/theme/types/components/button.ts +13 -14
- package/src/theme/types/components/card.ts +9 -0
- package/src/theme/types/components/chat.ts +124 -103
- package/src/theme/types/components/checkbox.ts +11 -12
- package/src/theme/types/components/chip.ts +8 -14
- package/src/theme/types/components/divider.ts +18 -0
- package/src/theme/types/components/hightide.ts +41 -42
- package/src/theme/types/components/iconButton.ts +19 -14
- package/src/theme/types/components/index.ts +5 -1
- package/src/theme/types/components/input.ts +17 -8
- package/src/theme/types/components/listItem.ts +86 -0
- package/src/theme/types/components/multiSelect.ts +14 -12
- package/src/theme/types/components/searchBar.ts +28 -0
- package/src/theme/types/components/select.ts +21 -9
- package/src/theme/types/components/switch.ts +12 -5
- package/src/theme/types/components/themedPressable.ts +31 -0
- package/src/theme/types/decoration.ts +1 -11
- package/src/theme/types/icongraphy.ts +8 -0
- package/src/theme/types/index.ts +2 -0
- package/src/theme/types/layout.ts +25 -57
- package/src/theme/types/resolver.ts +54 -1
- package/src/theme/types/semantics.ts +72 -0
- package/src/theme/types/theme.ts +26 -13
- package/src/theme/types/typography.ts +16 -17
- package/src/utils/hitBoxOverlay.ts +44 -0
- package/src/utils/index.ts +2 -0
- package/src/utils/minimumTouchTargetHitSlop.ts +68 -0
- package/src/components/chat/ChatAttachmentCard.tsx +0 -110
- package/src/components/chat/ChatMessageCard.tsx +0 -118
- package/src/components/menu/Menu.tsx +0 -61
- package/src/components/menu/MenuActionItem.tsx +0 -90
- package/src/components/menu/MenuItem.tsx +0 -73
- package/src/components/menu/MenuNavigationItem.tsx +0 -90
- package/src/components/menu/index.ts +0 -4
- package/src/components/visualization-and-display/Icon.tsx +0 -27
- package/src/storybook/helper.tsx +0 -36
- package/src/theme/resolvers/chat.ts +0 -418
- package/src/theme/resolvers/coloring.ts +0 -94
- package/src/theme/resolvers/menu.ts +0 -120
- package/src/theme/types/components/menu.ts +0 -57
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
+
Fragment,
|
|
2
3
|
useCallback,
|
|
3
4
|
useEffect,
|
|
4
|
-
useMemo,
|
|
5
5
|
useRef
|
|
6
6
|
} from 'react'
|
|
7
7
|
import {
|
|
@@ -18,41 +18,46 @@ import {
|
|
|
18
18
|
useEventCallbackStabilizer
|
|
19
19
|
} from '@helpwave/hightide-utils/hooks'
|
|
20
20
|
|
|
21
|
+
import { useDebugContext } from '../../global-contexts/debug'
|
|
21
22
|
import { useTheme } from '../../global-contexts/theme/ThemeContext'
|
|
22
|
-
import type {
|
|
23
|
+
import type {
|
|
24
|
+
SwitchContainerStyle,
|
|
25
|
+
SwitchState,
|
|
26
|
+
SwitchThumbStyle,
|
|
27
|
+
SwitchTrackStyle
|
|
28
|
+
} from '../../theme/types/components/switch'
|
|
23
29
|
import type { StyleOverwrite } from '../../theme/types/resolver'
|
|
24
|
-
import type { Color } from '../../theme/types/color'
|
|
25
30
|
import type {
|
|
26
31
|
FormFieldDataHandling,
|
|
27
32
|
FormFieldInteractionStates
|
|
28
33
|
} from '../../types/formField'
|
|
34
|
+
import { createHitBoxOverlayStyle } from '../../utils/hitBoxOverlay'
|
|
35
|
+
import { useMinimumTouchTargetHitSlop } from '../../utils/minimumTouchTargetHitSlop'
|
|
29
36
|
|
|
30
|
-
const TRACK_WIDTH = 48
|
|
31
|
-
const TRACK_HEIGHT = 28
|
|
32
|
-
const TRACK_BORDER_WIDTH = 2
|
|
33
|
-
const TRACK_PADDING = 4
|
|
34
|
-
const THUMB_SIZE_INACTIVE = 12
|
|
35
|
-
const THUMB_SIZE_ACTIVE = 16
|
|
36
|
-
const THUMB_OFFSET_INACTIVE = 2
|
|
37
37
|
const ANIMATION_DURATION_MS = 250
|
|
38
38
|
|
|
39
|
-
const TRACK_INNER_WIDTH = TRACK_WIDTH - (TRACK_BORDER_WIDTH * 2) - (TRACK_PADDING * 2)
|
|
40
|
-
const TRACK_INNER_HEIGHT = TRACK_HEIGHT - (TRACK_BORDER_WIDTH * 2) - (TRACK_PADDING * 2)
|
|
41
|
-
const THUMB_OFFSET_ACTIVE = TRACK_INNER_WIDTH - THUMB_SIZE_ACTIVE
|
|
42
|
-
const THUMB_TOP_INACTIVE = (TRACK_INNER_HEIGHT - THUMB_SIZE_INACTIVE) / 2
|
|
43
|
-
const THUMB_TOP_ACTIVE = (TRACK_INNER_HEIGHT - THUMB_SIZE_ACTIVE) / 2
|
|
44
|
-
|
|
45
39
|
export type SwitchProps = Omit<PressableProps, 'children' | 'style' | 'disabled'>
|
|
46
40
|
& Partial<FormFieldInteractionStates>
|
|
47
41
|
& Partial<FormFieldDataHandling<boolean>>
|
|
48
42
|
& {
|
|
49
43
|
initialValue?: boolean,
|
|
50
44
|
style?: StyleProp<ViewStyle>,
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
45
|
+
containerStyle?: StyleOverwrite<SwitchState, SwitchContainerStyle>,
|
|
46
|
+
trackStyle?: StyleOverwrite<SwitchState, SwitchTrackStyle>,
|
|
47
|
+
thumbStyle?: StyleOverwrite<SwitchState, SwitchThumbStyle>,
|
|
54
48
|
}
|
|
55
49
|
|
|
50
|
+
type PressableInteraction = {
|
|
51
|
+
pressed: boolean,
|
|
52
|
+
hovered?: boolean,
|
|
53
|
+
focused?: boolean,
|
|
54
|
+
focusVisible?: boolean,
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const toNumber = (value: string | number | undefined, fallback: number): number => (
|
|
58
|
+
typeof value === 'number' ? value : fallback
|
|
59
|
+
)
|
|
60
|
+
|
|
56
61
|
export const Switch = ({
|
|
57
62
|
value: controlledValue,
|
|
58
63
|
initialValue = false,
|
|
@@ -62,13 +67,21 @@ export const Switch = ({
|
|
|
62
67
|
onValueChange,
|
|
63
68
|
onEditComplete,
|
|
64
69
|
style,
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
70
|
+
containerStyle,
|
|
71
|
+
trackStyle,
|
|
72
|
+
thumbStyle,
|
|
68
73
|
accessibilityLabel,
|
|
74
|
+
hitSlop: providedHitSlop,
|
|
75
|
+
onLayout: providedOnLayout,
|
|
69
76
|
...props
|
|
70
77
|
}: SwitchProps) => {
|
|
71
78
|
const { theme } = useTheme()
|
|
79
|
+
const { hitBox } = useDebugContext()
|
|
80
|
+
const { hitSlop, onLayout } = useMinimumTouchTargetHitSlop({
|
|
81
|
+
touchTargetSize: theme.semantics.touchTargetSize({}),
|
|
82
|
+
hitSlop: providedHitSlop,
|
|
83
|
+
onLayout: providedOnLayout,
|
|
84
|
+
})
|
|
72
85
|
const interactive = !disabled && !readOnly
|
|
73
86
|
|
|
74
87
|
const onEditCompleteStable = useEventCallbackStabilizer(onEditComplete)
|
|
@@ -85,26 +98,6 @@ export const Switch = ({
|
|
|
85
98
|
defaultValue: initialValue,
|
|
86
99
|
})
|
|
87
100
|
|
|
88
|
-
const state = useMemo((): SwitchState => ({
|
|
89
|
-
isActive: value,
|
|
90
|
-
isInvalid: invalid,
|
|
91
|
-
isDisabled: disabled,
|
|
92
|
-
isReadOnly: readOnly,
|
|
93
|
-
}), [disabled, invalid, readOnly, value])
|
|
94
|
-
|
|
95
|
-
const trackColor = useMemo(
|
|
96
|
-
() => theme.components.switch.trackColor(state, trackColorStyle),
|
|
97
|
-
[theme, state, trackColorStyle]
|
|
98
|
-
)
|
|
99
|
-
const borderColor = useMemo(
|
|
100
|
-
() => theme.components.switch.borderColor(state, borderColorStyle),
|
|
101
|
-
[theme, state, borderColorStyle]
|
|
102
|
-
)
|
|
103
|
-
const thumbColor = useMemo(
|
|
104
|
-
() => theme.components.switch.thumbColor(state, thumbColorStyle),
|
|
105
|
-
[theme, state, thumbColorStyle]
|
|
106
|
-
)
|
|
107
|
-
|
|
108
101
|
const progress = useRef(new Animated.Value(value ? 1 : 0)).current
|
|
109
102
|
|
|
110
103
|
useEffect(() => {
|
|
@@ -115,17 +108,15 @@ export const Switch = ({
|
|
|
115
108
|
}).start()
|
|
116
109
|
}, [progress, value])
|
|
117
110
|
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
inputRange: [0, 1],
|
|
128
|
-
outputRange: [THUMB_TOP_INACTIVE, THUMB_TOP_ACTIVE],
|
|
111
|
+
const resolveState = (interaction: PressableInteraction): SwitchState => ({
|
|
112
|
+
isActive: value,
|
|
113
|
+
isInvalid: invalid,
|
|
114
|
+
isDisabled: disabled,
|
|
115
|
+
isReadonly: readOnly,
|
|
116
|
+
isPressed: interaction.pressed,
|
|
117
|
+
isHovered: !!interaction.hovered,
|
|
118
|
+
isFocused: !!interaction.focused,
|
|
119
|
+
isFocusVisible: !!interaction.focusVisible,
|
|
129
120
|
})
|
|
130
121
|
|
|
131
122
|
return (
|
|
@@ -138,40 +129,79 @@ export const Switch = ({
|
|
|
138
129
|
checked: value,
|
|
139
130
|
disabled,
|
|
140
131
|
}}
|
|
132
|
+
hitSlop={hitSlop}
|
|
133
|
+
onLayout={onLayout}
|
|
141
134
|
onPress={(event) => {
|
|
142
135
|
if (interactive) {
|
|
143
136
|
setValue((previous) => !previous)
|
|
144
137
|
}
|
|
145
138
|
props.onPress?.(event)
|
|
146
139
|
}}
|
|
147
|
-
style={
|
|
140
|
+
style={(pressableState) => {
|
|
141
|
+
const state = resolveState(pressableState as PressableInteraction)
|
|
142
|
+
return [theme.components.switch.container(state, containerStyle), style]
|
|
143
|
+
}}
|
|
148
144
|
>
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
145
|
+
{(pressableState) => {
|
|
146
|
+
const state = resolveState(pressableState as PressableInteraction)
|
|
147
|
+
const inactiveState: SwitchState = { ...state, isActive: false }
|
|
148
|
+
const activeState: SwitchState = { ...state, isActive: true }
|
|
149
|
+
const resolvedTrackStyle = theme.components.switch.track(state, trackStyle)
|
|
150
|
+
const resolvedThumbInactive = theme.components.switch.thumb(inactiveState, thumbStyle)
|
|
151
|
+
const resolvedThumbActive = theme.components.switch.thumb(activeState, thumbStyle)
|
|
152
|
+
const trackWidth = toNumber(resolvedTrackStyle.width as string | number | undefined, 40)
|
|
153
|
+
const trackHeight = toNumber(resolvedTrackStyle.height as string | number | undefined, 28)
|
|
154
|
+
const trackBorderWidth = toNumber(resolvedTrackStyle.borderWidth, 0)
|
|
155
|
+
const thumbInactiveSize = toNumber(resolvedThumbInactive.width as string | number | undefined, 16)
|
|
156
|
+
const thumbActiveSize = toNumber(resolvedThumbActive.width as string | number | undefined, 20)
|
|
157
|
+
const trackInnerWidth = trackWidth - (trackBorderWidth * 2)
|
|
158
|
+
const trackInnerHeight = trackHeight - (trackBorderWidth * 2)
|
|
159
|
+
const thumbOffsetInactive = (trackInnerHeight - thumbInactiveSize) / 2
|
|
160
|
+
const thumbOffsetActive = trackInnerWidth - thumbActiveSize - (
|
|
161
|
+
(trackInnerHeight - thumbActiveSize) / 2
|
|
162
|
+
)
|
|
163
|
+
const thumbTopInactive = (trackInnerHeight - thumbInactiveSize) / 2
|
|
164
|
+
const thumbTopActive = (trackInnerHeight - thumbActiveSize) / 2
|
|
165
|
+
const thumbSize = progress.interpolate({
|
|
166
|
+
inputRange: [0, 1],
|
|
167
|
+
outputRange: [thumbInactiveSize, thumbActiveSize],
|
|
168
|
+
})
|
|
169
|
+
const thumbTranslateX = progress.interpolate({
|
|
170
|
+
inputRange: [0, 1],
|
|
171
|
+
outputRange: [thumbOffsetInactive, thumbOffsetActive],
|
|
172
|
+
})
|
|
173
|
+
const thumbTop = progress.interpolate({
|
|
174
|
+
inputRange: [0, 1],
|
|
175
|
+
outputRange: [thumbTopInactive, thumbTopActive],
|
|
176
|
+
})
|
|
177
|
+
const thumbColor = value
|
|
178
|
+
? resolvedThumbActive.backgroundColor
|
|
179
|
+
: resolvedThumbInactive.backgroundColor
|
|
180
|
+
|
|
181
|
+
return (
|
|
182
|
+
<Fragment>
|
|
183
|
+
{hitBox.isVisualizing && (
|
|
184
|
+
<View
|
|
185
|
+
pointerEvents="none"
|
|
186
|
+
style={createHitBoxOverlayStyle(hitSlop, hitBox.color)}
|
|
187
|
+
/>
|
|
188
|
+
)}
|
|
189
|
+
<View style={resolvedTrackStyle}>
|
|
190
|
+
<Animated.View
|
|
191
|
+
style={{
|
|
192
|
+
position: 'absolute',
|
|
193
|
+
top: thumbTop,
|
|
194
|
+
width: thumbSize,
|
|
195
|
+
height: thumbSize,
|
|
196
|
+
borderRadius: thumbActiveSize / 2,
|
|
197
|
+
backgroundColor: thumbColor,
|
|
198
|
+
transform: [{ translateX: thumbTranslateX }],
|
|
199
|
+
}}
|
|
200
|
+
/>
|
|
201
|
+
</View>
|
|
202
|
+
</Fragment>
|
|
203
|
+
)
|
|
204
|
+
}}
|
|
175
205
|
</Pressable>
|
|
176
206
|
)
|
|
177
207
|
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { Fragment, forwardRef } from 'react'
|
|
2
|
+
import {
|
|
3
|
+
Pressable,
|
|
4
|
+
View,
|
|
5
|
+
type PressableProps
|
|
6
|
+
} from 'react-native'
|
|
7
|
+
|
|
8
|
+
import type {
|
|
9
|
+
ColoringColorVariant,
|
|
10
|
+
ColoringStyle,
|
|
11
|
+
ComponentSize
|
|
12
|
+
} from '@helpwave/hightide-design/semantic-token-resolvers'
|
|
13
|
+
import type { ColorPairToken } from '@helpwave/hightide-design/theme-tokens'
|
|
14
|
+
|
|
15
|
+
import { ContentThemeProvider } from '../../global-contexts/content-theme/ContentThemeProvider'
|
|
16
|
+
import { useDebugContext } from '../../global-contexts/debug'
|
|
17
|
+
import { useTheme } from '../../global-contexts/theme/ThemeContext'
|
|
18
|
+
import type {
|
|
19
|
+
ThemedPressableState,
|
|
20
|
+
ThemedPressableStyle,
|
|
21
|
+
ThemedPressableTextStyle
|
|
22
|
+
} from '../../theme/types/components/themedPressable'
|
|
23
|
+
import type { StyleOverwrite } from '../../theme/types/resolver'
|
|
24
|
+
import { createHitBoxOverlayStyle } from '../../utils/hitBoxOverlay'
|
|
25
|
+
import { useMinimumTouchTargetHitSlop } from '../../utils/minimumTouchTargetHitSlop'
|
|
26
|
+
|
|
27
|
+
export type ThemedPressableSize = ComponentSize
|
|
28
|
+
|
|
29
|
+
export const ThemedPressableUtil = {
|
|
30
|
+
sizes: ['xs', 'sm', 'md', 'lg', 'xl'] as const satisfies readonly ComponentSize[],
|
|
31
|
+
coloringStyles: ['filled', 'foreground'] as const satisfies readonly ColoringStyle[],
|
|
32
|
+
coloringColorVariants: ['normal', 'tonal', 'transparent'] as const satisfies readonly ColoringColorVariant[],
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export type ThemedPressableProps = PressableProps & {
|
|
36
|
+
size?: ThemedPressableSize,
|
|
37
|
+
color?: ColorPairToken,
|
|
38
|
+
coloringStyle?: ColoringStyle,
|
|
39
|
+
coloringColorVariant?: ColoringColorVariant,
|
|
40
|
+
hasAdditionalHorizontalPadding?: boolean,
|
|
41
|
+
containerStyle?: StyleOverwrite<ThemedPressableState, ThemedPressableStyle>,
|
|
42
|
+
stateLayerStyle?: StyleOverwrite<ThemedPressableState, ThemedPressableStyle>,
|
|
43
|
+
textStyle?: StyleOverwrite<ThemedPressableState, ThemedPressableTextStyle>,
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
type PressableInteraction = {
|
|
47
|
+
pressed: boolean,
|
|
48
|
+
hovered?: boolean,
|
|
49
|
+
focused?: boolean,
|
|
50
|
+
focusVisible?: boolean,
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export const ThemedPressable = forwardRef<React.ComponentRef<typeof Pressable>, ThemedPressableProps>(function ThemedPressable({
|
|
54
|
+
children,
|
|
55
|
+
size = 'md',
|
|
56
|
+
color,
|
|
57
|
+
coloringStyle = 'foreground',
|
|
58
|
+
coloringColorVariant = 'normal',
|
|
59
|
+
hasAdditionalHorizontalPadding = false,
|
|
60
|
+
disabled,
|
|
61
|
+
style,
|
|
62
|
+
containerStyle,
|
|
63
|
+
stateLayerStyle,
|
|
64
|
+
textStyle,
|
|
65
|
+
hitSlop: providedHitSlop,
|
|
66
|
+
onLayout: providedOnLayout,
|
|
67
|
+
...props
|
|
68
|
+
}, ref) {
|
|
69
|
+
const { theme } = useTheme()
|
|
70
|
+
const { hitBox } = useDebugContext()
|
|
71
|
+
const { hitSlop, onLayout } = useMinimumTouchTargetHitSlop({
|
|
72
|
+
touchTargetSize: theme.semantics.touchTargetSize({}),
|
|
73
|
+
hitSlop: providedHitSlop,
|
|
74
|
+
onLayout: providedOnLayout,
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
const resolveState = (interaction: PressableInteraction): ThemedPressableState => ({
|
|
78
|
+
size,
|
|
79
|
+
color,
|
|
80
|
+
coloringStyle,
|
|
81
|
+
coloringColorVariant,
|
|
82
|
+
hasAdditionalHorizontalPadding,
|
|
83
|
+
isDisabled: !!disabled,
|
|
84
|
+
isPressed: interaction.pressed,
|
|
85
|
+
isHovered: !!interaction.hovered,
|
|
86
|
+
isFocused: !!interaction.focused,
|
|
87
|
+
isFocusVisible: !!interaction.focusVisible,
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
return (
|
|
91
|
+
<Pressable
|
|
92
|
+
{...props}
|
|
93
|
+
ref={ref}
|
|
94
|
+
disabled={disabled}
|
|
95
|
+
hitSlop={hitSlop}
|
|
96
|
+
onLayout={onLayout}
|
|
97
|
+
style={(pressableState) => {
|
|
98
|
+
const state = resolveState(pressableState as PressableInteraction)
|
|
99
|
+
const resolvedStyle = typeof style === 'function' ? style(pressableState) : style
|
|
100
|
+
return [
|
|
101
|
+
theme.components.themedPressable.container(state, containerStyle),
|
|
102
|
+
resolvedStyle,
|
|
103
|
+
]
|
|
104
|
+
}}
|
|
105
|
+
>
|
|
106
|
+
{(pressableState) => {
|
|
107
|
+
const state = resolveState(pressableState as PressableInteraction)
|
|
108
|
+
const resolvedText = theme.components.themedPressable.text(state, textStyle)
|
|
109
|
+
const resolvedChildren = typeof children === 'function'
|
|
110
|
+
? children(pressableState)
|
|
111
|
+
: children
|
|
112
|
+
|
|
113
|
+
return (
|
|
114
|
+
<Fragment>
|
|
115
|
+
{hitBox.isVisualizing && (
|
|
116
|
+
<View
|
|
117
|
+
pointerEvents="none"
|
|
118
|
+
style={createHitBoxOverlayStyle(hitSlop, hitBox.color)}
|
|
119
|
+
/>
|
|
120
|
+
)}
|
|
121
|
+
<View
|
|
122
|
+
pointerEvents="none"
|
|
123
|
+
style={theme.components.themedPressable.stateLayer(state, stateLayerStyle)}
|
|
124
|
+
/>
|
|
125
|
+
<ContentThemeProvider
|
|
126
|
+
foregroundColor={resolvedText.color ?? theme.colors.surface.onColor}
|
|
127
|
+
textStyle={resolvedText}
|
|
128
|
+
>
|
|
129
|
+
{resolvedChildren}
|
|
130
|
+
</ContentThemeProvider>
|
|
131
|
+
</Fragment>
|
|
132
|
+
)
|
|
133
|
+
}}
|
|
134
|
+
</Pressable>
|
|
135
|
+
)
|
|
136
|
+
})
|