@retray-dev/ui-kit 12.1.0 → 13.0.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/COMPONENTS.md +183 -147
- package/CONSUMER.md +2 -2
- package/DESIGN.md +2 -2
- package/README.md +13 -8
- package/dist/Accordion.d.mts +6 -0
- package/dist/Accordion.d.ts +6 -0
- package/dist/Accordion.js +62 -208
- package/dist/Accordion.mjs +6 -5
- package/dist/AlertBanner.js +29 -151
- package/dist/AlertBanner.mjs +3 -3
- package/dist/AppHeader.js +37 -233
- package/dist/AppHeader.mjs +6 -7
- package/dist/Avatar.d.mts +17 -1
- package/dist/Avatar.d.ts +17 -1
- package/dist/Avatar.js +80 -113
- package/dist/Avatar.mjs +2 -2
- package/dist/Badge.js +24 -147
- package/dist/Badge.mjs +3 -3
- package/dist/Button.js +86 -274
- package/dist/Button.mjs +6 -6
- package/dist/Card.js +15 -198
- package/dist/Card.mjs +4 -5
- package/dist/CategoryStrip.d.mts +0 -5
- package/dist/CategoryStrip.d.ts +0 -5
- package/dist/CategoryStrip.js +47 -263
- package/dist/CategoryStrip.mjs +6 -6
- package/dist/Checkbox.js +15 -198
- package/dist/Checkbox.mjs +5 -5
- package/dist/Chip.js +44 -234
- package/dist/Chip.mjs +7 -6
- package/dist/ConfirmDialog.js +100 -296
- package/dist/ConfirmDialog.mjs +7 -7
- package/dist/CurrencyDisplay.js +1 -112
- package/dist/CurrencyDisplay.mjs +2 -2
- package/dist/CurrencyInput.js +35 -160
- package/dist/CurrencyInput.mjs +5 -5
- package/dist/DetailRow.js +25 -148
- package/dist/DetailRow.mjs +3 -3
- package/dist/EmptyState.js +87 -275
- package/dist/EmptyState.mjs +7 -7
- package/dist/ErrorBoundary.js +32 -197
- package/dist/ErrorBoundary.mjs +4 -4
- package/dist/Form.js +1 -112
- package/dist/Form.mjs +2 -2
- package/dist/HolographicCard.d.mts +0 -28
- package/dist/HolographicCard.d.ts +0 -28
- package/dist/HolographicCard.js +20 -130
- package/dist/HolographicCard.mjs +9 -32
- package/dist/IconButton.js +36 -232
- package/dist/IconButton.mjs +5 -6
- package/dist/IconPicker.js +222 -927
- package/dist/IconPicker.mjs +5 -5
- package/dist/ImageUpload.d.mts +5 -1
- package/dist/ImageUpload.d.ts +5 -1
- package/dist/ImageUpload.js +32 -215
- package/dist/ImageUpload.mjs +5 -6
- package/dist/ImageViewer.js +75 -264
- package/dist/ImageViewer.mjs +8 -8
- package/dist/Input.d.mts +1 -1
- package/dist/Input.d.ts +1 -1
- package/dist/Input.js +35 -160
- package/dist/Input.mjs +4 -4
- package/dist/LabelValue.js +24 -147
- package/dist/LabelValue.mjs +3 -3
- package/dist/ListGroup.js +1 -112
- package/dist/ListGroup.mjs +2 -2
- package/dist/ListItem.js +38 -233
- package/dist/ListItem.mjs +5 -6
- package/dist/MediaCard.d.mts +0 -14
- package/dist/MediaCard.d.ts +0 -14
- package/dist/MediaCard.js +69 -313
- package/dist/MediaCard.mjs +5 -6
- package/dist/MenuGroup.js +1 -112
- package/dist/MenuGroup.mjs +2 -2
- package/dist/MenuItem.js +36 -232
- package/dist/MenuItem.mjs +5 -6
- package/dist/MonthPicker.js +8 -161
- package/dist/MonthPicker.mjs +3 -3
- package/dist/NumberStepper.js +40 -236
- package/dist/NumberStepper.mjs +5 -6
- package/dist/PagerDots.d.mts +1 -1
- package/dist/PagerDots.d.ts +1 -1
- package/dist/PagerDots.js +69 -222
- package/dist/PagerDots.mjs +6 -5
- package/dist/Pressable.js +14 -85
- package/dist/Pressable.mjs +4 -4
- package/dist/PricingCard.js +94 -279
- package/dist/PricingCard.mjs +8 -8
- package/dist/Progress.js +3 -121
- package/dist/Progress.mjs +3 -3
- package/dist/RadioGroup.js +52 -263
- package/dist/RadioGroup.mjs +5 -5
- package/dist/RetrayProvider.d.mts +1 -1
- package/dist/RetrayProvider.d.ts +1 -1
- package/dist/RetrayProvider.js +5 -6
- package/dist/RetrayProvider.mjs +3 -3
- package/dist/Select.d.mts +2 -1
- package/dist/Select.d.ts +2 -1
- package/dist/Select.js +24 -230
- package/dist/Select.mjs +4 -5
- package/dist/SelectableCard.d.mts +27 -0
- package/dist/SelectableCard.d.ts +27 -0
- package/dist/SelectableCard.js +335 -0
- package/dist/SelectableCard.mjs +8 -0
- package/dist/SelectableGrid.d.mts +0 -21
- package/dist/SelectableGrid.d.ts +0 -21
- package/dist/SelectableGrid.js +49 -269
- package/dist/SelectableGrid.mjs +5 -6
- package/dist/Separator.js +1 -112
- package/dist/Separator.mjs +2 -2
- package/dist/Sheet.js +16 -163
- package/dist/Sheet.mjs +3 -3
- package/dist/SheetSelect.js +39 -234
- package/dist/SheetSelect.mjs +6 -6
- package/dist/Skeleton.d.mts +3 -1
- package/dist/Skeleton.d.ts +3 -1
- package/dist/Skeleton.js +7 -124
- package/dist/Skeleton.mjs +3 -3
- package/dist/Slider.js +6 -159
- package/dist/Slider.mjs +3 -3
- package/dist/Spinner.js +3 -114
- package/dist/Spinner.mjs +2 -2
- package/dist/Stats.d.mts +4 -1
- package/dist/Stats.d.ts +4 -1
- package/dist/Stats.js +60 -234
- package/dist/Stats.mjs +5 -6
- package/dist/Switch.js +24 -173
- package/dist/Switch.mjs +5 -4
- package/dist/TabBar.js +43 -198
- package/dist/TabBar.mjs +5 -4
- package/dist/Tabs.js +15 -197
- package/dist/Tabs.mjs +5 -5
- package/dist/Text.js +9 -128
- package/dist/Text.mjs +2 -2
- package/dist/Textarea.d.mts +2 -1
- package/dist/Textarea.d.ts +2 -1
- package/dist/Textarea.js +71 -217
- package/dist/Textarea.mjs +4 -4
- package/dist/Toast.js +1 -112
- package/dist/Toast.mjs +2 -2
- package/dist/Toggle.js +39 -234
- package/dist/Toggle.mjs +6 -6
- package/dist/{chunk-FFTYLPSB.mjs → chunk-2QOHHBJC.mjs} +13 -7
- package/dist/{chunk-BCWEHE34.mjs → chunk-2VIDP72N.mjs} +3 -3
- package/dist/{chunk-PGERH3P7.mjs → chunk-4NQFTHN3.mjs} +13 -7
- package/dist/{chunk-3N2M3WZL.mjs → chunk-4ZO5PTKF.mjs} +4 -4
- package/dist/{chunk-MYZ2EDYU.mjs → chunk-5MYNAAFE.mjs} +13 -17
- package/dist/{chunk-E7NEHHXV.mjs → chunk-62BBSSUF.mjs} +3 -3
- package/dist/{chunk-ISY26JQJ.mjs → chunk-6CR4S6W2.mjs} +3 -3
- package/dist/{chunk-FUVYSVGR.mjs → chunk-6QLBHUEG.mjs} +8 -7
- package/dist/chunk-ARONDO7M.mjs +40 -0
- package/dist/{chunk-3UYAZ7I4.mjs → chunk-AZV7KNJI.mjs} +3 -3
- package/dist/{chunk-HLMPMUK2.mjs → chunk-BTUW5LSG.mjs} +11 -8
- package/dist/chunk-BULKGOIZ.mjs +235 -0
- package/dist/{chunk-265G6A46.mjs → chunk-CBIZLRYH.mjs} +29 -12
- package/dist/chunk-CM2DG4MR.mjs +142 -0
- package/dist/{chunk-2I2AYECM.mjs → chunk-DBHSUUKU.mjs} +2 -2
- package/dist/{chunk-P64WHW4A.mjs → chunk-DE25XTVQ.mjs} +3 -3
- package/dist/{chunk-DI7CBDL6.mjs → chunk-E4EQSCKR.mjs} +5 -5
- package/dist/{chunk-357YO24D.mjs → chunk-EHGBHFMH.mjs} +9 -17
- package/dist/{chunk-GK4VRMNE.mjs → chunk-EROPDCB5.mjs} +24 -27
- package/dist/{chunk-XBAGGKLW.mjs → chunk-ERWJPVX7.mjs} +2 -2
- package/dist/{chunk-LRM4AVYY.mjs → chunk-ESQDPO5E.mjs} +7 -7
- package/dist/{chunk-EFLFRAHD.mjs → chunk-EW2FIDSM.mjs} +1 -1
- package/dist/{chunk-7HSILTC4.mjs → chunk-FTTI6T5Q.mjs} +4 -4
- package/dist/{chunk-X26S5EVZ.mjs → chunk-HUSSF6TF.mjs} +1 -1
- package/dist/chunk-IFYMBOEN.mjs +14 -0
- package/dist/{chunk-S3KJCPEJ.mjs → chunk-IGU223UM.mjs} +80 -4
- package/dist/chunk-IJCMPVW5.mjs +121 -0
- package/dist/{chunk-I4V5XZPS.mjs → chunk-ITG4JQM3.mjs} +4 -4
- package/dist/{chunk-F4V6XLP4.mjs → chunk-K3QX2M26.mjs} +11 -8
- package/dist/{chunk-V6NFJXKO.mjs → chunk-K7TKID3V.mjs} +8 -7
- package/dist/{chunk-ZHMSAYLT.mjs → chunk-KAGADD2O.mjs} +4 -4
- package/dist/{chunk-3GEYJ7I5.mjs → chunk-KC5QDYGZ.mjs} +4 -4
- package/dist/{chunk-HJ46DTJE.mjs → chunk-KPTY7UYQ.mjs} +1 -1
- package/dist/{chunk-EMUWGDWC.mjs → chunk-KSSVIFYR.mjs} +11 -12
- package/dist/chunk-L3YKPTJQ.mjs +119 -0
- package/dist/chunk-M53LC4Q7.mjs +35 -0
- package/dist/{chunk-NXI4YDZ2.mjs → chunk-MP7GLMIR.mjs} +17 -25
- package/dist/chunk-MZ6WRTD2.mjs +40 -0
- package/dist/chunk-NGEN2EES.mjs +581 -0
- package/dist/{chunk-JULSIZDM.mjs → chunk-OBV72JD4.mjs} +1 -1
- package/dist/{chunk-2A2LEFZG.mjs → chunk-PGQ6FMXS.mjs} +6 -5
- package/dist/{chunk-BQZE3HAW.mjs → chunk-PI6RULJX.mjs} +1 -1
- package/dist/{chunk-FA2KMTH5.mjs → chunk-RA6SAAFE.mjs} +9 -8
- package/dist/{chunk-FVTVCJAH.mjs → chunk-RRKM4MKB.mjs} +7 -7
- package/dist/{chunk-AKM4EPOT.mjs → chunk-S2VGME7X.mjs} +1 -1
- package/dist/{chunk-OULVKTWL.mjs → chunk-S44XWTTC.mjs} +35 -25
- package/dist/{chunk-QSFV2P7O.mjs → chunk-SZEKQAOY.mjs} +1 -1
- package/dist/{chunk-N4ZPVCJH.mjs → chunk-TETMEKZE.mjs} +9 -9
- package/dist/{chunk-2CBQKU7H.mjs → chunk-TMH263OK.mjs} +5 -4
- package/dist/{chunk-D3Y2T42P.mjs → chunk-U6DEBYU5.mjs} +10 -9
- package/dist/{chunk-4WFMPFZB.mjs → chunk-UOKFSFNJ.mjs} +2 -2
- package/dist/{chunk-WOEWGSTU.mjs → chunk-URIH43IJ.mjs} +13 -21
- package/dist/{chunk-JCZQOY4O.mjs → chunk-V2ZB2XNS.mjs} +16 -10
- package/dist/{chunk-P73V2EKS.mjs → chunk-WIPEDNSD.mjs} +7 -7
- package/dist/{chunk-BOVUP27T.mjs → chunk-XCIG6HT2.mjs} +6 -5
- package/dist/chunk-Y6YS33GM.mjs +131 -0
- package/dist/{chunk-5OLNXP3S.mjs → chunk-ZKDKKQCE.mjs} +29 -7
- package/dist/{chunk-DF6DU42P.mjs → chunk-ZTPYUU5C.mjs} +5 -5
- package/dist/{index-wt-orHUi.d.ts → index-CY34hxPN.d.mts} +1 -0
- package/dist/{index-wt-orHUi.d.mts → index-CY34hxPN.d.ts} +1 -0
- package/dist/index.d.mts +15 -74
- package/dist/index.d.ts +15 -74
- package/dist/index.js +1055 -1562
- package/dist/index.mjs +81 -84
- package/package.json +8 -10
- package/src/components/Accordion/Accordion.tsx +32 -9
- package/src/components/AlertBanner/AlertBanner.tsx +7 -6
- package/src/components/AppHeader/AppHeader.tsx +1 -1
- package/src/components/Avatar/Avatar.tsx +92 -1
- package/src/components/Avatar/index.ts +2 -2
- package/src/components/Badge/Badge.tsx +2 -2
- package/src/components/Button/Button.tsx +64 -57
- package/src/components/Card/Card.tsx +1 -0
- package/src/components/CategoryStrip/CategoryStrip.tsx +36 -49
- package/src/components/Chip/Chip.tsx +5 -4
- package/src/components/ConfirmDialog/ConfirmDialog.tsx +13 -6
- package/src/components/DetailRow/DetailRow.tsx +3 -3
- package/src/components/EmptyState/EmptyState.tsx +2 -2
- package/src/components/ErrorBoundary/ErrorBoundary.tsx +6 -6
- package/src/components/HolographicCard/HolographicCard.tsx +14 -95
- package/src/components/IconButton/IconButton.tsx +2 -2
- package/src/components/IconPicker/IconPicker.tsx +13 -12
- package/src/components/ImageUpload/ImageUpload.tsx +24 -28
- package/src/components/ImageViewer/ImageViewer.tsx +3 -3
- package/src/components/Input/Input.tsx +11 -5
- package/src/components/LabelValue/LabelValue.tsx +2 -2
- package/src/components/ListItem/ListItem.tsx +4 -4
- package/src/components/MediaCard/MediaCard.tsx +21 -59
- package/src/components/MenuItem/MenuItem.tsx +2 -2
- package/src/components/MonthPicker/MonthPicker.tsx +2 -2
- package/src/components/NumberStepper/NumberStepper.tsx +6 -6
- package/src/components/PagerDots/PagerDots.tsx +38 -28
- package/src/components/PricingCard/PricingCard.tsx +6 -6
- package/src/components/RadioGroup/RadioGroup.tsx +18 -31
- package/src/components/Select/Select.tsx +32 -39
- package/src/components/SelectableCard/SelectableCard.tsx +302 -0
- package/src/components/SelectableCard/index.ts +1 -0
- package/src/components/SelectableGrid/SelectableGrid.tsx +38 -72
- package/src/components/Sheet/Sheet.tsx +11 -4
- package/src/components/SheetSelect/SheetSelect.tsx +3 -3
- package/src/components/Skeleton/Skeleton.tsx +6 -3
- package/src/components/Spinner/Spinner.tsx +2 -2
- package/src/components/Stats/Stats.tsx +36 -8
- package/src/components/Switch/Switch.tsx +9 -6
- package/src/components/TabBar/TabBar.tsx +9 -8
- package/src/components/Text/Text.tsx +12 -1
- package/src/components/Textarea/Textarea.tsx +18 -32
- package/src/components/Toggle/Toggle.tsx +3 -3
- package/src/hooks/useConfirmDialog.ts +31 -42
- package/src/index.ts +4 -4
- package/src/theme/ThemeProvider.tsx +1 -4
- package/src/theme/colorUtils.ts +1 -72
- package/src/theme/colors.ts +47 -1
- package/src/theme/types.ts +6 -3
- package/src/utils/animations.ts +0 -47
- package/src/utils/curatedIcons.ts +93 -801
- package/src/utils/haptics.ts +13 -208
- package/src/utils/icons.ts +27 -91
- package/src/utils/pressable.ts +10 -61
- package/dist/VirtualList.d.mts +0 -19
- package/dist/VirtualList.d.ts +0 -19
- package/dist/VirtualList.js +0 -38
- package/dist/VirtualList.mjs +0 -2
- package/dist/chunk-3DKJ2GIC.mjs +0 -30
- package/dist/chunk-AQEVCEXV.mjs +0 -164
- package/dist/chunk-DOGIPOF5.mjs +0 -131
- package/dist/chunk-DVK4G2GT.mjs +0 -59
- package/dist/chunk-EJ7ZPXOH.mjs +0 -163
- package/dist/chunk-J6Q2YJEV.mjs +0 -134
- package/dist/chunk-JNVAIDLK.mjs +0 -136
- package/dist/chunk-KA7LTET3.mjs +0 -71
- package/dist/chunk-KHYX4IOM.mjs +0 -1114
- package/dist/chunk-NC5ZTR2Y.mjs +0 -32
- package/dist/chunk-YNROWHQJ.mjs +0 -46
- package/src/components/VirtualList/VirtualList.tsx +0 -60
- package/src/components/VirtualList/index.ts +0 -1
- package/src/utils/fontGuard.ts +0 -35
- package/src/utils/hover.ts +0 -25
- package/src/utils/useColorTransition.ts +0 -40
- package/src/utils/usePressScale.ts +0 -75
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
|
+
import { Image } from 'expo-image'
|
|
2
3
|
import {
|
|
3
4
|
View,
|
|
4
|
-
Image,
|
|
5
5
|
Text,
|
|
6
6
|
TouchableOpacity,
|
|
7
7
|
StyleSheet,
|
|
@@ -9,15 +9,12 @@ import {
|
|
|
9
9
|
ImageSourcePropType,
|
|
10
10
|
Platform,
|
|
11
11
|
} from 'react-native'
|
|
12
|
-
import Animated from 'react-native-reanimated'
|
|
13
12
|
import { impactLight } from '../../utils/haptics'
|
|
14
13
|
import { useTheme } from '../../theme'
|
|
15
14
|
import { s, vs, ms, mvs } from '../../utils/scaling'
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import { SPRINGS, PRESS_SCALE } from '../../utils/animations'
|
|
20
|
-
import { RADIUS, SHADOWS } from '../../tokens'
|
|
15
|
+
import { Icon } from '../../utils/icons'
|
|
16
|
+
import { PressableCard } from '../../utils/pressable'
|
|
17
|
+
import { RADIUS } from '../../tokens'
|
|
21
18
|
|
|
22
19
|
export type MediaCardAspectRatio = '1:1' | '4:3' | '16:9' | '4:5' | '3:2'
|
|
23
20
|
|
|
@@ -30,34 +27,20 @@ const aspectRatioMap: Record<MediaCardAspectRatio, number> = {
|
|
|
30
27
|
}
|
|
31
28
|
|
|
32
29
|
export interface MediaCardProps {
|
|
33
|
-
/** Image source — URI string or require(). */
|
|
34
30
|
imageSource?: ImageSourcePropType
|
|
35
|
-
/** Image aspect ratio. Defaults to `'4:3'`. */
|
|
36
31
|
aspectRatio?: MediaCardAspectRatio
|
|
37
|
-
/** Badge content rendered top-left over the image (e.g. a Badge component or Text). */
|
|
38
32
|
badge?: React.ReactNode
|
|
39
|
-
/** Icon rendered in a circle button top-right over the image. Defaults to `'heart'`. */
|
|
40
33
|
actionIcon?: React.ReactNode
|
|
41
|
-
/** Icon name for the action button. Overrides `actionIcon`. */
|
|
42
34
|
actionIconName?: string
|
|
43
|
-
/** Whether the action icon is in active/filled state. */
|
|
44
35
|
actionActive?: boolean
|
|
45
|
-
/** Called when the top-right action icon is pressed. */
|
|
46
36
|
onActionPress?: () => void
|
|
47
|
-
/** Primary text below the image. */
|
|
48
37
|
title?: string
|
|
49
|
-
/** Secondary text below the title. */
|
|
50
38
|
subtitle?: string
|
|
51
|
-
/** Tertiary / caption text below subtitle. */
|
|
52
39
|
caption?: string
|
|
53
|
-
/** Called when the card body is pressed. */
|
|
54
40
|
onPress?: () => void
|
|
55
41
|
style?: ViewStyle
|
|
56
|
-
/** Style for the image container. */
|
|
57
42
|
imageStyle?: ViewStyle
|
|
58
|
-
/** Additional content rendered below caption. */
|
|
59
43
|
footer?: React.ReactNode
|
|
60
|
-
/** Accessibility label override. Defaults to title (and subtitle if present). */
|
|
61
44
|
accessibilityLabel?: string
|
|
62
45
|
}
|
|
63
46
|
|
|
@@ -79,13 +62,6 @@ function MediaCardBase({
|
|
|
79
62
|
accessibilityLabel,
|
|
80
63
|
}: MediaCardProps) {
|
|
81
64
|
const { colors } = useTheme()
|
|
82
|
-
const { hovered, hoverHandlers } = useHover()
|
|
83
|
-
const { animatedStyle, onPressIn, onPressOut } = usePressScale({
|
|
84
|
-
pressScale: PRESS_SCALE.card,
|
|
85
|
-
pressInSpring: SPRINGS.surfacePressIn,
|
|
86
|
-
pressOutSpring: SPRINGS.surfacePressOut,
|
|
87
|
-
disabled: !onPress,
|
|
88
|
-
})
|
|
89
65
|
|
|
90
66
|
const handlePress = () => {
|
|
91
67
|
if (!onPress) return
|
|
@@ -95,22 +71,14 @@ function MediaCardBase({
|
|
|
95
71
|
|
|
96
72
|
const ratio = aspectRatioMap[aspectRatio]
|
|
97
73
|
|
|
98
|
-
// Action icon: active = primary fill, inactive = foreground outline
|
|
99
74
|
const resolvedActionIcon = actionIconName
|
|
100
|
-
?
|
|
101
|
-
: actionIcon ??
|
|
75
|
+
? <Icon name={actionIconName} size={18} color={actionActive ? colors.primary : colors.background} />
|
|
76
|
+
: actionIcon ?? <Icon name="heart" size={18} color={actionActive ? colors.primary : colors.background} />
|
|
102
77
|
|
|
103
78
|
const a11yLabel = accessibilityLabel ?? [title, subtitle].filter(Boolean).join('. ')
|
|
104
79
|
|
|
105
80
|
const cardContent = (
|
|
106
|
-
<View
|
|
107
|
-
style={[
|
|
108
|
-
styles.card,
|
|
109
|
-
hovered && styles.cardHovered,
|
|
110
|
-
style,
|
|
111
|
-
]}
|
|
112
|
-
{...(Platform.OS === 'web' ? hoverHandlers : {})}
|
|
113
|
-
>
|
|
81
|
+
<View style={[styles.card, style]}>
|
|
114
82
|
<View style={[styles.imageContainer, imageStyle]}>
|
|
115
83
|
<View style={{ paddingTop: `${ratio * 100}%` as `${number}%` }}>
|
|
116
84
|
<View style={StyleSheet.absoluteFill}>
|
|
@@ -118,7 +86,7 @@ function MediaCardBase({
|
|
|
118
86
|
<Image
|
|
119
87
|
source={imageSource}
|
|
120
88
|
style={styles.image}
|
|
121
|
-
|
|
89
|
+
contentFit="cover"
|
|
122
90
|
/>
|
|
123
91
|
) : (
|
|
124
92
|
<View style={[styles.imagePlaceholder, { backgroundColor: colors.surface }]} />
|
|
@@ -136,16 +104,14 @@ function MediaCardBase({
|
|
|
136
104
|
<TouchableOpacity
|
|
137
105
|
style={[styles.actionButton, { backgroundColor: 'rgba(0,0,0,0.24)' }]}
|
|
138
106
|
onPress={(e) => {
|
|
139
|
-
// Stop propagation to prevent triggering parent onPress
|
|
140
107
|
e?.stopPropagation?.()
|
|
141
108
|
impactLight()
|
|
142
109
|
onActionPress?.()
|
|
143
110
|
}}
|
|
144
111
|
activeOpacity={0.8}
|
|
145
112
|
touchSoundDisabled={true}
|
|
146
|
-
// On web, avoid nested <button> by using a non-button role when parent is pressable
|
|
147
113
|
accessibilityRole={Platform.OS === 'web' && onPress ? undefined : 'button'}
|
|
148
|
-
accessibilityLabel={actionIconName ?? '
|
|
114
|
+
accessibilityLabel={actionIconName ?? 'acción'}
|
|
149
115
|
accessibilityState={{ selected: actionActive }}
|
|
150
116
|
>
|
|
151
117
|
{resolvedActionIcon}
|
|
@@ -178,19 +144,18 @@ function MediaCardBase({
|
|
|
178
144
|
|
|
179
145
|
if (onPress) {
|
|
180
146
|
return (
|
|
181
|
-
<
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
</Animated.View>
|
|
147
|
+
<PressableCard
|
|
148
|
+
onPress={handlePress}
|
|
149
|
+
enabled
|
|
150
|
+
rippleColor="transparent"
|
|
151
|
+
touchSoundDisabled
|
|
152
|
+
activateOnHover
|
|
153
|
+
accessibilityRole="button"
|
|
154
|
+
accessibilityLabel={a11yLabel}
|
|
155
|
+
accessibilityState={{ disabled: false }}
|
|
156
|
+
>
|
|
157
|
+
{cardContent}
|
|
158
|
+
</PressableCard>
|
|
194
159
|
)
|
|
195
160
|
}
|
|
196
161
|
|
|
@@ -205,9 +170,6 @@ const styles = StyleSheet.create({
|
|
|
205
170
|
overflow: 'hidden',
|
|
206
171
|
backgroundColor: 'transparent',
|
|
207
172
|
},
|
|
208
|
-
cardHovered: {
|
|
209
|
-
...SHADOWS.md,
|
|
210
|
-
},
|
|
211
173
|
imageContainer: {
|
|
212
174
|
borderRadius: RADIUS.md,
|
|
213
175
|
overflow: 'hidden',
|
|
@@ -10,7 +10,7 @@ import { Entypo } from '@expo/vector-icons'
|
|
|
10
10
|
import { selectionAsync as hapticSelection } from '../../utils/haptics'
|
|
11
11
|
import { useTheme } from '../../theme'
|
|
12
12
|
import { s, vs, ms } from '../../utils/scaling'
|
|
13
|
-
import {
|
|
13
|
+
import { Icon } from '../../utils/icons'
|
|
14
14
|
import { RADIUS } from '../../tokens'
|
|
15
15
|
import { PressableRow } from '../../utils/pressable'
|
|
16
16
|
|
|
@@ -81,7 +81,7 @@ function MenuItemBase({
|
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
const resolvedIcon: React.ReactNode = iconName
|
|
84
|
-
?
|
|
84
|
+
? <Icon name={iconName} size={22} color={iconColor ?? colors.foreground} />
|
|
85
85
|
: icon
|
|
86
86
|
|
|
87
87
|
const cardStyle: ViewStyle =
|
|
@@ -83,7 +83,7 @@ export function MonthPicker({ value, onChange, minValue, maxValue, locale = 'en'
|
|
|
83
83
|
activeOpacity={0.6}
|
|
84
84
|
touchSoundDisabled={true}
|
|
85
85
|
accessibilityRole="button"
|
|
86
|
-
accessibilityLabel="
|
|
86
|
+
accessibilityLabel="Mes anterior"
|
|
87
87
|
accessibilityState={{ disabled: prevDisabled }}
|
|
88
88
|
hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}
|
|
89
89
|
>
|
|
@@ -103,7 +103,7 @@ export function MonthPicker({ value, onChange, minValue, maxValue, locale = 'en'
|
|
|
103
103
|
activeOpacity={0.6}
|
|
104
104
|
touchSoundDisabled={true}
|
|
105
105
|
accessibilityRole="button"
|
|
106
|
-
accessibilityLabel="
|
|
106
|
+
accessibilityLabel="Mes siguiente"
|
|
107
107
|
accessibilityState={{ disabled: nextDisabled }}
|
|
108
108
|
hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}
|
|
109
109
|
>
|
|
@@ -3,7 +3,7 @@ import { View, Text, StyleSheet, ViewStyle } from 'react-native'
|
|
|
3
3
|
import { impactLight } from '../../utils/haptics'
|
|
4
4
|
import { useTheme } from '../../theme'
|
|
5
5
|
import { s, ms, mvs } from '../../utils/scaling'
|
|
6
|
-
import {
|
|
6
|
+
import { Icon } from '../../utils/icons'
|
|
7
7
|
import { RADIUS } from '../../tokens'
|
|
8
8
|
import { PressableButton } from '../../utils/pressable'
|
|
9
9
|
|
|
@@ -77,10 +77,10 @@ function NumberStepperBase({
|
|
|
77
77
|
rippleColor="transparent"
|
|
78
78
|
touchSoundDisabled
|
|
79
79
|
accessibilityRole="button"
|
|
80
|
-
accessibilityLabel={`
|
|
80
|
+
accessibilityLabel={`Disminuir, valor actual ${displayValue}`}
|
|
81
81
|
accessibilityState={{ disabled: !canDecrement }}
|
|
82
82
|
>
|
|
83
|
-
|
|
83
|
+
<Icon name="minus" size={iconSize} color={canDecrement ? colors.foreground : colors.foregroundMuted} />
|
|
84
84
|
</PressableButton>
|
|
85
85
|
<Text
|
|
86
86
|
style={[
|
|
@@ -93,7 +93,7 @@ function NumberStepperBase({
|
|
|
93
93
|
},
|
|
94
94
|
]}
|
|
95
95
|
allowFontScaling={true}
|
|
96
|
-
accessibilityLabel={accessibilityLabel ?? `
|
|
96
|
+
accessibilityLabel={accessibilityLabel ?? `Cantidad: ${displayValue}`}
|
|
97
97
|
accessibilityRole="text"
|
|
98
98
|
>
|
|
99
99
|
{displayValue}
|
|
@@ -114,10 +114,10 @@ function NumberStepperBase({
|
|
|
114
114
|
rippleColor="transparent"
|
|
115
115
|
touchSoundDisabled
|
|
116
116
|
accessibilityRole="button"
|
|
117
|
-
accessibilityLabel={`
|
|
117
|
+
accessibilityLabel={`Aumentar, valor actual ${displayValue}`}
|
|
118
118
|
accessibilityState={{ disabled: !canIncrement }}
|
|
119
119
|
>
|
|
120
|
-
|
|
120
|
+
<Icon name="plus" size={iconSize} color={canIncrement ? colors.foreground : colors.foregroundMuted} />
|
|
121
121
|
</PressableButton>
|
|
122
122
|
</View>
|
|
123
123
|
)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useEffect } from 'react'
|
|
2
|
-
import { View,
|
|
2
|
+
import { View, StyleSheet, ViewStyle } from 'react-native'
|
|
3
3
|
import Animated, {
|
|
4
4
|
useSharedValue,
|
|
5
5
|
useAnimatedStyle,
|
|
@@ -10,7 +10,8 @@ import { useTheme } from '../../theme'
|
|
|
10
10
|
import { s } from '../../utils/scaling'
|
|
11
11
|
import { SPRINGS } from '../../utils/animations'
|
|
12
12
|
import { selectionAsync as hapticSelection } from '../../utils/haptics'
|
|
13
|
-
import {
|
|
13
|
+
import { Icon } from '../../utils/icons'
|
|
14
|
+
import { PressableButton } from '../../utils/pressable'
|
|
14
15
|
|
|
15
16
|
export interface PagerDotsProps {
|
|
16
17
|
/** Total number of pages. */
|
|
@@ -23,7 +24,7 @@ export interface PagerDotsProps {
|
|
|
23
24
|
showControls?: boolean | { onPrevious?: () => void; onNext?: () => void }
|
|
24
25
|
/** Diameter of an inactive dot (dp). Defaults to 8. */
|
|
25
26
|
dotSize?: number
|
|
26
|
-
/** Gap between dots (dp). Defaults to
|
|
27
|
+
/** Gap between dots (dp). Defaults to 4. */
|
|
27
28
|
spacing?: number
|
|
28
29
|
/** Active dot color. Defaults to theme `primary`. */
|
|
29
30
|
activeColor?: string
|
|
@@ -53,7 +54,7 @@ function Dot({ active, size, activeColor, inactiveColor, onPress, index, total }
|
|
|
53
54
|
|
|
54
55
|
// Active dot stretches into a pill (width = 2.5×). Color crossfades on the UI thread.
|
|
55
56
|
const animatedStyle = useAnimatedStyle(() => ({
|
|
56
|
-
width: size + progress.value * size
|
|
57
|
+
width: size + progress.value * size,
|
|
57
58
|
backgroundColor: interpolateColor(progress.value, [0, 1], [inactiveColor, activeColor]),
|
|
58
59
|
}))
|
|
59
60
|
|
|
@@ -69,16 +70,17 @@ function Dot({ active, size, activeColor, inactiveColor, onPress, index, total }
|
|
|
69
70
|
}
|
|
70
71
|
|
|
71
72
|
return (
|
|
72
|
-
<
|
|
73
|
+
<PressableButton
|
|
73
74
|
onPress={handlePress}
|
|
74
|
-
|
|
75
|
-
touchSoundDisabled
|
|
75
|
+
rippleColor="transparent"
|
|
76
|
+
touchSoundDisabled
|
|
76
77
|
accessibilityRole="button"
|
|
77
|
-
accessibilityLabel={`
|
|
78
|
-
hitSlop={{ top:
|
|
78
|
+
accessibilityLabel={`Página ${index + 1} de ${total}${active ? ', página actual' : ''}`}
|
|
79
|
+
hitSlop={{ top: 10, bottom: 10, left: 18, right: 18 }}
|
|
80
|
+
style={styles.dotTouchable}
|
|
79
81
|
>
|
|
80
82
|
{dot}
|
|
81
|
-
</
|
|
83
|
+
</PressableButton>
|
|
82
84
|
)
|
|
83
85
|
}
|
|
84
86
|
|
|
@@ -95,7 +97,7 @@ export function PagerDots({
|
|
|
95
97
|
onDotPress,
|
|
96
98
|
showControls = false,
|
|
97
99
|
dotSize = 8,
|
|
98
|
-
spacing =
|
|
100
|
+
spacing = 4,
|
|
99
101
|
activeColor,
|
|
100
102
|
inactiveColor,
|
|
101
103
|
style,
|
|
@@ -133,21 +135,21 @@ export function PagerDots({
|
|
|
133
135
|
<View
|
|
134
136
|
style={[styles.container, { gap: s(spacing) }, style]}
|
|
135
137
|
accessibilityRole="adjustable"
|
|
136
|
-
accessibilityLabel={`
|
|
138
|
+
accessibilityLabel={`Página ${activeIndex + 1} de ${count}`}
|
|
137
139
|
>
|
|
138
140
|
{hasControls && (
|
|
139
|
-
<
|
|
141
|
+
<PressableButton
|
|
140
142
|
onPress={handlePrevious}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
touchSoundDisabled
|
|
143
|
+
enabled={canGoPrev}
|
|
144
|
+
rippleColor="transparent"
|
|
145
|
+
touchSoundDisabled
|
|
144
146
|
accessibilityRole="button"
|
|
145
|
-
accessibilityLabel="
|
|
146
|
-
hitSlop={{ top:
|
|
147
|
+
accessibilityLabel="Página anterior"
|
|
148
|
+
hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}
|
|
147
149
|
style={[styles.controlBtn, !canGoPrev && styles.controlBtnDisabled]}
|
|
148
150
|
>
|
|
149
|
-
|
|
150
|
-
</
|
|
151
|
+
<Icon name="chevron-left" size={s(18)} color={canGoPrev ? colors.foreground : colors.foregroundMuted} />
|
|
152
|
+
</PressableButton>
|
|
151
153
|
)}
|
|
152
154
|
<View style={[styles.dotsRow, { gap: s(spacing) }]}>
|
|
153
155
|
{Array.from({ length: count }).map((_, i) => (
|
|
@@ -164,18 +166,18 @@ export function PagerDots({
|
|
|
164
166
|
))}
|
|
165
167
|
</View>
|
|
166
168
|
{hasControls && (
|
|
167
|
-
<
|
|
169
|
+
<PressableButton
|
|
168
170
|
onPress={handleNext}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
touchSoundDisabled
|
|
171
|
+
enabled={canGoNext}
|
|
172
|
+
rippleColor="transparent"
|
|
173
|
+
touchSoundDisabled
|
|
172
174
|
accessibilityRole="button"
|
|
173
|
-
accessibilityLabel="
|
|
174
|
-
hitSlop={{ top:
|
|
175
|
+
accessibilityLabel="Página siguiente"
|
|
176
|
+
hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}
|
|
175
177
|
style={[styles.controlBtn, !canGoNext && styles.controlBtnDisabled]}
|
|
176
178
|
>
|
|
177
|
-
|
|
178
|
-
</
|
|
179
|
+
<Icon name="chevron-right" size={s(18)} color={canGoNext ? colors.foreground : colors.foregroundMuted} />
|
|
180
|
+
</PressableButton>
|
|
179
181
|
)}
|
|
180
182
|
</View>
|
|
181
183
|
)
|
|
@@ -193,6 +195,14 @@ const styles = StyleSheet.create({
|
|
|
193
195
|
},
|
|
194
196
|
controlBtn: {
|
|
195
197
|
padding: s(4),
|
|
198
|
+
minHeight: 44,
|
|
199
|
+
justifyContent: 'center',
|
|
200
|
+
},
|
|
201
|
+
dotTouchable: {
|
|
202
|
+
minHeight: 44,
|
|
203
|
+
paddingHorizontal: s(14),
|
|
204
|
+
justifyContent: 'center',
|
|
205
|
+
alignItems: 'center',
|
|
196
206
|
},
|
|
197
207
|
controlBtnDisabled: {
|
|
198
208
|
opacity: 0.3,
|
|
@@ -3,7 +3,7 @@ import { View, Text, StyleSheet, ViewStyle } from 'react-native'
|
|
|
3
3
|
import { useTheme } from '../../theme'
|
|
4
4
|
import { Button } from '../Button'
|
|
5
5
|
import { Badge } from '../Badge'
|
|
6
|
-
import {
|
|
6
|
+
import { Icon } from '../../utils/icons'
|
|
7
7
|
import { s, vs, ms, mvs } from '../../utils/scaling'
|
|
8
8
|
import { RADIUS, SHADOWS } from '../../tokens'
|
|
9
9
|
|
|
@@ -113,11 +113,11 @@ export function PricingCard({
|
|
|
113
113
|
<View style={styles.features}>
|
|
114
114
|
{features.map(normalize).map((f, i) => (
|
|
115
115
|
<View key={i} style={styles.featureRow}>
|
|
116
|
-
|
|
117
|
-
f.included ? 'check' : 'minus'
|
|
118
|
-
ms(16)
|
|
119
|
-
f.included ? colors.success : colors.foregroundMuted
|
|
120
|
-
|
|
116
|
+
<Icon
|
|
117
|
+
name={f.included ? 'check' : 'minus'}
|
|
118
|
+
size={ms(16)}
|
|
119
|
+
color={f.included ? colors.success : colors.foregroundMuted}
|
|
120
|
+
/>
|
|
121
121
|
<Text
|
|
122
122
|
style={[
|
|
123
123
|
styles.featureLabel,
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
|
-
import {
|
|
3
|
-
import Animated from 'react-native-reanimated'
|
|
2
|
+
import { View, Text, StyleSheet, ViewStyle } from 'react-native'
|
|
4
3
|
import { EaseView } from 'react-native-ease'
|
|
5
4
|
import { selectionAsync as hapticSelection } from '../../utils/haptics'
|
|
6
5
|
import { useTheme } from '../../theme'
|
|
7
6
|
import { s, vs, ms, mvs } from '../../utils/scaling'
|
|
8
|
-
import {
|
|
9
|
-
import { COLOR_TRANSITION, SPRING_ELASTIC
|
|
7
|
+
import { PressableButton } from '../../utils/pressable'
|
|
8
|
+
import { COLOR_TRANSITION, SPRING_ELASTIC } from '../../utils/animations'
|
|
10
9
|
|
|
11
10
|
export interface RadioOption {
|
|
12
11
|
label: string
|
|
@@ -33,16 +32,9 @@ function RadioItem({
|
|
|
33
32
|
onSelect: () => void
|
|
34
33
|
}) {
|
|
35
34
|
const { colors } = useTheme()
|
|
36
|
-
const { animatedStyle: scaleStyle, onPressIn, onPressOut } = usePressScale({
|
|
37
|
-
pressScale: PRESS_SCALE.button,
|
|
38
|
-
disabled: option.disabled,
|
|
39
|
-
})
|
|
40
35
|
|
|
41
36
|
return (
|
|
42
|
-
|
|
43
|
-
// at full opacity when disabled. The whole row now dims uniformly so users
|
|
44
|
-
// get a single, consistent disabled signal across the entire item.
|
|
45
|
-
<TouchableOpacity
|
|
37
|
+
<PressableButton
|
|
46
38
|
style={[styles.row, option.disabled && styles.rowDisabled]}
|
|
47
39
|
onPress={() => {
|
|
48
40
|
if (!option.disabled) {
|
|
@@ -50,35 +42,31 @@ function RadioItem({
|
|
|
50
42
|
onSelect()
|
|
51
43
|
}
|
|
52
44
|
}}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
touchSoundDisabled={true}
|
|
57
|
-
disabled={option.disabled}
|
|
45
|
+
enabled={!option.disabled}
|
|
46
|
+
rippleColor="transparent"
|
|
47
|
+
touchSoundDisabled
|
|
58
48
|
accessibilityRole="radio"
|
|
59
49
|
accessibilityLabel={option.label}
|
|
60
50
|
accessibilityState={{ checked: selected, disabled: !!option.disabled }}
|
|
61
51
|
>
|
|
62
|
-
<
|
|
52
|
+
<EaseView
|
|
53
|
+
style={styles.radio}
|
|
54
|
+
animate={{ borderColor: selected ? colors.primary : colors.border }}
|
|
55
|
+
transition={COLOR_TRANSITION}
|
|
56
|
+
>
|
|
63
57
|
<EaseView
|
|
64
|
-
style={styles.
|
|
65
|
-
animate={{
|
|
66
|
-
transition={
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
style={[styles.dot, { backgroundColor: colors.primary }]}
|
|
70
|
-
animate={{ scale: selected ? 1 : 0, opacity: selected ? 1 : 0 }}
|
|
71
|
-
transition={SPRING_ELASTIC}
|
|
72
|
-
/>
|
|
73
|
-
</EaseView>
|
|
74
|
-
</Animated.View>
|
|
58
|
+
style={[styles.dot, { backgroundColor: colors.primary }]}
|
|
59
|
+
animate={{ scale: selected ? 1 : 0, opacity: selected ? 1 : 0 }}
|
|
60
|
+
transition={SPRING_ELASTIC}
|
|
61
|
+
/>
|
|
62
|
+
</EaseView>
|
|
75
63
|
<Text
|
|
76
64
|
style={[styles.label, { color: colors.foreground }]}
|
|
77
65
|
allowFontScaling={true}
|
|
78
66
|
>
|
|
79
67
|
{option.label}
|
|
80
68
|
</Text>
|
|
81
|
-
</
|
|
69
|
+
</PressableButton>
|
|
82
70
|
)
|
|
83
71
|
}
|
|
84
72
|
|
|
@@ -121,7 +109,6 @@ const styles = StyleSheet.create({
|
|
|
121
109
|
alignItems: 'center',
|
|
122
110
|
gap: s(12),
|
|
123
111
|
},
|
|
124
|
-
// AUDIT FIX: was opacity on the inner circle only
|
|
125
112
|
rowDisabled: {
|
|
126
113
|
opacity: 0.45,
|
|
127
114
|
},
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import React, { useRef, useState } from 'react'
|
|
2
2
|
import { View, Text, TouchableOpacity, Modal, StyleSheet, ViewStyle, Platform } from 'react-native'
|
|
3
|
-
import Animated from 'react-native-reanimated'
|
|
4
3
|
import { Picker } from '@react-native-picker/picker'
|
|
5
4
|
import { Entypo } from '@expo/vector-icons'
|
|
6
5
|
import { selectionAsync as hapticSelection } from '../../utils/haptics'
|
|
7
6
|
import { useTheme } from '../../theme'
|
|
8
7
|
import { s, vs, ms } from '../../utils/scaling'
|
|
9
|
-
import {
|
|
10
|
-
import { PRESS_SCALE } from '../../utils/animations'
|
|
8
|
+
import { PressableButton } from '../../utils/pressable'
|
|
11
9
|
|
|
12
10
|
const isIOS = Platform.OS === 'ios'
|
|
13
11
|
const isAndroid = Platform.OS === 'android'
|
|
@@ -25,6 +23,7 @@ export interface SelectProps {
|
|
|
25
23
|
onValueChange?: (value: string) => void
|
|
26
24
|
placeholder?: string
|
|
27
25
|
label?: string
|
|
26
|
+
hint?: string
|
|
28
27
|
error?: string
|
|
29
28
|
disabled?: boolean
|
|
30
29
|
style?: ViewStyle
|
|
@@ -37,16 +36,13 @@ export function Select({
|
|
|
37
36
|
onValueChange,
|
|
38
37
|
placeholder = 'Select an option',
|
|
39
38
|
label,
|
|
39
|
+
hint,
|
|
40
40
|
error,
|
|
41
41
|
disabled,
|
|
42
42
|
style,
|
|
43
43
|
accessibilityLabel,
|
|
44
44
|
}: SelectProps) {
|
|
45
45
|
const { colors } = useTheme()
|
|
46
|
-
const { animatedStyle, onPressIn, onPressOut } = usePressScale({
|
|
47
|
-
pressScale: PRESS_SCALE.button,
|
|
48
|
-
disabled,
|
|
49
|
-
})
|
|
50
46
|
const [pickerVisible, setPickerVisible] = useState(false)
|
|
51
47
|
const [pendingValue, setPendingValue] = useState<string | undefined>(value)
|
|
52
48
|
const pickerRef = useRef<React.ElementRef<typeof Picker>>(null)
|
|
@@ -82,38 +78,36 @@ export function Select({
|
|
|
82
78
|
|
|
83
79
|
{/* Trigger button — shown on iOS and Android only */}
|
|
84
80
|
{!isWeb ? (
|
|
85
|
-
<
|
|
86
|
-
|
|
81
|
+
<PressableButton
|
|
82
|
+
style={[
|
|
83
|
+
styles.trigger,
|
|
84
|
+
{
|
|
85
|
+
borderColor: error ? colors.destructive : colors.border,
|
|
86
|
+
backgroundColor: colors.background,
|
|
87
|
+
},
|
|
88
|
+
disabled && { opacity: 0.45 },
|
|
89
|
+
]}
|
|
90
|
+
onPress={handleOpen}
|
|
91
|
+
enabled={!disabled}
|
|
92
|
+
rippleColor="transparent"
|
|
93
|
+
touchSoundDisabled
|
|
94
|
+
accessibilityRole="combobox"
|
|
95
|
+
accessibilityLabel={accessibilityLabel ?? label}
|
|
96
|
+
accessibilityValue={{ text: selected?.label ?? placeholder }}
|
|
97
|
+
accessibilityState={{ disabled: !!disabled, expanded: pickerVisible }}
|
|
98
|
+
>
|
|
99
|
+
<Text
|
|
87
100
|
style={[
|
|
88
|
-
styles.
|
|
89
|
-
{
|
|
90
|
-
borderColor: error ? colors.destructive : colors.border,
|
|
91
|
-
backgroundColor: colors.background,
|
|
92
|
-
},
|
|
101
|
+
styles.triggerText,
|
|
102
|
+
{ color: selected ? colors.foreground : colors.foregroundMuted },
|
|
93
103
|
]}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
onPressOut={onPressOut}
|
|
97
|
-
activeOpacity={1}
|
|
98
|
-
touchSoundDisabled={true}
|
|
99
|
-
accessibilityRole="combobox"
|
|
100
|
-
accessibilityLabel={accessibilityLabel ?? label}
|
|
101
|
-
accessibilityValue={{ text: selected?.label ?? placeholder }}
|
|
102
|
-
accessibilityState={{ disabled: !!disabled, expanded: pickerVisible }}
|
|
104
|
+
numberOfLines={1}
|
|
105
|
+
allowFontScaling={true}
|
|
103
106
|
>
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
]}
|
|
109
|
-
numberOfLines={1}
|
|
110
|
-
allowFontScaling={true}
|
|
111
|
-
>
|
|
112
|
-
{selected?.label ?? placeholder}
|
|
113
|
-
</Text>
|
|
114
|
-
<Entypo name="chevron-down" size={20} color={colors.foregroundMuted} />
|
|
115
|
-
</TouchableOpacity>
|
|
116
|
-
</Animated.View>
|
|
107
|
+
{selected?.label ?? placeholder}
|
|
108
|
+
</Text>
|
|
109
|
+
<Entypo name="chevron-down" size={20} color={colors.foregroundMuted} />
|
|
110
|
+
</PressableButton>
|
|
117
111
|
) : null}
|
|
118
112
|
|
|
119
113
|
{/* iOS: Modal with wheel Picker */}
|
|
@@ -224,6 +218,8 @@ export function Select({
|
|
|
224
218
|
|
|
225
219
|
{error ? (
|
|
226
220
|
<Text style={[styles.helperText, { color: colors.destructive }]} allowFontScaling={true}>{error}</Text>
|
|
221
|
+
) : !error && hint ? (
|
|
222
|
+
<Text style={[styles.helperText, { color: colors.foregroundMuted }]} allowFontScaling={true}>{hint}</Text>
|
|
227
223
|
) : null}
|
|
228
224
|
</View>
|
|
229
225
|
)
|
|
@@ -251,9 +247,6 @@ const styles = StyleSheet.create({
|
|
|
251
247
|
fontSize: ms(15),
|
|
252
248
|
flex: 1,
|
|
253
249
|
},
|
|
254
|
-
chevron: {
|
|
255
|
-
marginLeft: s(8),
|
|
256
|
-
},
|
|
257
250
|
helperText: {
|
|
258
251
|
fontFamily: 'Sohne-Regular',
|
|
259
252
|
fontSize: ms(13),
|